rubex 0.0.1 → 0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (135) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +4 -0
  3. data/.travis.yml +14 -0
  4. data/CONTRIBUTING.md +101 -0
  5. data/HISTORY.md +3 -0
  6. data/README.md +112 -297
  7. data/REFERENCE.md +753 -0
  8. data/Rakefile +4 -1
  9. data/TUTORIAL.md +234 -0
  10. data/bin/rubex +1 -1
  11. data/docs/_config.yml +1 -0
  12. data/docs/index.html +1 -0
  13. data/examples/c_struct_interface/c_struct_interface.rb +6 -0
  14. data/examples/c_struct_interface/c_struct_interface.rubex +47 -0
  15. data/examples/linked_list/linked_list.rubex +39 -0
  16. data/examples/linked_list/rb_linked_list.rb +8 -0
  17. data/examples/rcsv wrapper/rcsv/README.md +1 -0
  18. data/examples/rcsv wrapper/rcsv/Rakefile +7 -0
  19. data/examples/rcsv wrapper/rcsv/ext/rcsv/extconf.rb +3 -0
  20. data/examples/rcsv wrapper/rcsv/ext/rcsv/rcsv.c +302 -0
  21. data/examples/rcsv wrapper/rcsv/ext/rcsv/rcsv.rubex +124 -0
  22. data/examples/rcsv wrapper/rcsv/lib/rcsv.rb +8 -0
  23. data/examples/rcsv wrapper/rcsv/lib/rcsv.so +0 -0
  24. data/examples/rcsv wrapper/rcsv/lib/rcsv/version.rb +1 -0
  25. data/examples/rcsv wrapper/rcsv/rcsv.gemspec +27 -0
  26. data/examples/rcsv wrapper/rcsv/spec/rcsv.csv +5 -0
  27. data/examples/rcsv wrapper/rcsv/spec/rcsv_spec.rb +17 -0
  28. data/examples/rcsv wrapper/rcsv/spec/spec_helper.rb +6 -0
  29. data/{spec/fixtures/basic_ruby_method/Makefile → examples/rcsv wrapper/rcsv/tmp/x86_64-linux/rcsv/2.3.3/Makefile } +20 -20
  30. data/examples/rcsv wrapper/rcsv/tmp/x86_64-linux/rcsv/2.3.3/rcsv.o +0 -0
  31. data/examples/rcsv wrapper/rcsv/tmp/x86_64-linux/rcsv/2.3.3/rcsv.so +0 -0
  32. data/examples/rcsv wrapper/rcsv/tmp/x86_64-linux/stage/lib/rcsv.so +0 -0
  33. data/lib/rubex.rb +6 -50
  34. data/lib/rubex/ast.rb +1 -3
  35. data/lib/rubex/ast/expression.rb +1257 -8
  36. data/lib/rubex/ast/node.rb +226 -28
  37. data/lib/rubex/ast/statement.rb +1162 -35
  38. data/lib/rubex/ast/top_statement.rb +815 -0
  39. data/lib/rubex/code_writer.rb +103 -26
  40. data/lib/rubex/compiler.rb +72 -0
  41. data/lib/rubex/compiler_config.rb +19 -0
  42. data/lib/rubex/constants.rb +145 -8
  43. data/lib/rubex/data_type.rb +667 -4
  44. data/lib/rubex/error.rb +15 -0
  45. data/lib/rubex/helpers.rb +154 -0
  46. data/lib/rubex/lexer.rex +186 -22
  47. data/lib/rubex/lexer.rex.rb +261 -35
  48. data/lib/rubex/parser.racc +876 -28
  49. data/lib/rubex/parser.racc.rb +2845 -90
  50. data/lib/rubex/rake_task.rb +34 -0
  51. data/lib/rubex/symbol_table/entry.rb +17 -3
  52. data/lib/rubex/symbol_table/scope.rb +298 -25
  53. data/lib/rubex/version.rb +1 -1
  54. data/rubex.gemspec +11 -3
  55. data/spec/basic_ruby_method_spec.rb +15 -21
  56. data/spec/binding_ptr_args_spec.rb +33 -0
  57. data/spec/bitwise_operators_spec.rb +40 -0
  58. data/spec/blocks_spec.rb +35 -0
  59. data/spec/c_bindings_spec.rb +36 -0
  60. data/spec/c_constants_spec.rb +33 -0
  61. data/spec/c_function_ptrs_spec.rb +38 -0
  62. data/spec/c_functions_spec.rb +35 -0
  63. data/spec/c_struct_interface_spec.rb +38 -0
  64. data/spec/call_by_reference_spec.rb +33 -0
  65. data/spec/class_methods_spec.rb +33 -0
  66. data/spec/class_spec.rb +40 -0
  67. data/spec/comments_spec.rb +33 -0
  68. data/spec/default_args_spec.rb +37 -0
  69. data/spec/error_handling_spec.rb +42 -0
  70. data/spec/examples_spec.rb +52 -0
  71. data/spec/expressions_spec.rb +33 -0
  72. data/spec/fixtures/basic_ruby_method/basic_ruby_method.rubex +2 -0
  73. data/spec/fixtures/binding_ptr_args/binding_ptr_args.rubex +30 -0
  74. data/spec/fixtures/bitwise_operators/bitwise_operators.rubex +40 -0
  75. data/spec/fixtures/blocks/blocks.rubex +11 -0
  76. data/spec/fixtures/c_bindings/c_bindings.rubex +58 -0
  77. data/spec/fixtures/c_constants/c_constants.rubex +7 -0
  78. data/spec/fixtures/c_function_ptrs/c_function_ptrs.rubex +52 -0
  79. data/spec/fixtures/c_functions/c_functions.rubex +25 -0
  80. data/spec/fixtures/c_struct_interface/c_struct_interface.rubex +34 -0
  81. data/spec/fixtures/call_by_reference/call_by_reference.rubex +30 -0
  82. data/spec/fixtures/class/class.rubex +20 -0
  83. data/spec/fixtures/class_methods/class_methods.rubex +12 -0
  84. data/spec/fixtures/comments/comments.rubex +9 -0
  85. data/spec/fixtures/default_args/default_args.rubex +11 -0
  86. data/spec/fixtures/error_handling/error_handling.rubex +54 -0
  87. data/spec/fixtures/examples/array_to_hash.rubex +14 -0
  88. data/spec/fixtures/examples/rcsv.csv +5 -0
  89. data/spec/fixtures/examples/rcsv.rubex +329 -0
  90. data/spec/fixtures/expressions/expressions.rubex +10 -0
  91. data/spec/fixtures/if_else/if_else.rubex +77 -0
  92. data/spec/fixtures/implicit_lib_include/implicit_lib_include.rubex +15 -0
  93. data/spec/fixtures/init_ruby_objects_with_literal_syntax/init_ruby_objects_with_literal_syntax.rubex +17 -0
  94. data/spec/fixtures/loops/loops.rubex +33 -0
  95. data/spec/fixtures/recursion/recursion.rubex +9 -0
  96. data/spec/fixtures/ruby_constant_method_calls/ruby_constant_method_calls.rubex +17 -0
  97. data/spec/fixtures/ruby_operators/ruby_operators.rubex +29 -0
  98. data/spec/fixtures/ruby_raise/ruby_raise.rubex +13 -0
  99. data/spec/fixtures/ruby_strings/ruby_strings.rubex +19 -0
  100. data/spec/fixtures/ruby_strings/string_blank_bm.rb +37 -0
  101. data/spec/fixtures/ruby_symbols/ruby_symbols.rubex +12 -0
  102. data/spec/fixtures/ruby_types/ruby_types.rubex +15 -0
  103. data/spec/fixtures/statement_expression/statement_expression.rubex +23 -0
  104. data/spec/fixtures/static_array/static_array.rubex +20 -0
  105. data/spec/fixtures/string_literals/string_literals.rubex +15 -0
  106. data/spec/fixtures/struct/struct.rubex +82 -0
  107. data/spec/fixtures/typecasting/typecasting.rubex +23 -0
  108. data/spec/fixtures/var_declarations/var_declarations.rubex +39 -0
  109. data/spec/if_else_spec.rb +39 -0
  110. data/spec/implicit_lib_include_spec.rb +33 -0
  111. data/spec/init_ruby_objects_with_literal_syntax_spec.rb +39 -0
  112. data/spec/loops_spec.rb +34 -0
  113. data/spec/recursion_spec.rb +35 -0
  114. data/spec/ruby_constant_method_calls_spec.rb +35 -0
  115. data/spec/ruby_operators_spec.rb +40 -0
  116. data/spec/ruby_raise_spec.rb +35 -0
  117. data/spec/ruby_strings_spec.rb +33 -0
  118. data/spec/ruby_symbols_spec.rb +37 -0
  119. data/spec/ruby_types_spec.rb +35 -0
  120. data/spec/spec_helper.rb +54 -1
  121. data/spec/statement_expression_spec.rb +34 -0
  122. data/spec/static_array_spec.rb +33 -0
  123. data/spec/string_literals_spec.rb +34 -0
  124. data/spec/struct_spec.rb +36 -0
  125. data/spec/typecasting_spec.rb +38 -0
  126. data/spec/var_declarions_spec.rb +35 -0
  127. metadata +255 -29
  128. data/lib/rubex/ast/argument_list.rb +0 -20
  129. data/lib/rubex/ast/c_base_type.rb +0 -11
  130. data/lib/rubex/ast/ruby_method_def.rb +0 -84
  131. data/spec/fixtures/basic_ruby_method/basic.rb +0 -3
  132. data/spec/fixtures/basic_ruby_method/basic_ruby_method.c +0 -16
  133. data/spec/fixtures/basic_ruby_method/basic_ruby_method.o +0 -0
  134. data/spec/fixtures/basic_ruby_method/basic_ruby_method.so +0 -0
  135. data/spec/fixtures/basic_ruby_method/extconf.rb +0 -3
@@ -0,0 +1,30 @@
1
+ struct attribs
2
+ int a, b
3
+ float c
4
+ end
5
+
6
+ class CallByReference
7
+ def ref_call
8
+ attribs a
9
+ int b_flat = 1
10
+ int *i
11
+ a.a = 1
12
+ a.b = 1
13
+
14
+ i = &b_flat
15
+ c_function(&a, b_flat, i)
16
+ add(&a)
17
+
18
+ b_flat = a.c + i[0]
19
+
20
+ return b_flat
21
+ end
22
+
23
+ cfunc void c_function(attribs *a, int b, int *i)
24
+ a[0].a = b + i[0]
25
+ end
26
+
27
+ cfunc void add(attribs *a)
28
+ a[0].c = a[0].a + a[0].b
29
+ end
30
+ end
@@ -0,0 +1,20 @@
1
+ class Kustom
2
+ def bye
3
+ prelude
4
+ return "Bye world!"
5
+ end
6
+
7
+ def prelude
8
+ return "This is a prelude."
9
+ end
10
+ end
11
+
12
+ class Kustom2 < Kustom
13
+ def hello
14
+ a = prelude
15
+ return a.concat("Hello world!")
16
+ end
17
+ end
18
+
19
+ class RandomRubyError < StandardError
20
+ end
@@ -0,0 +1,12 @@
1
+ class Bhau
2
+ def self.say_what(string)
3
+ int i = 0
4
+
5
+ while i < 10 do
6
+ print string
7
+ i += 1
8
+ end
9
+
10
+ return i
11
+ end
12
+ end
@@ -0,0 +1,9 @@
1
+ # This is a comment
2
+
3
+ def crazy_comment # so is this
4
+ # And this
5
+ int i = 4 # ... and this
6
+ return i # this!!
7
+ end # This is a comment too
8
+
9
+ # This is the end
@@ -0,0 +1,11 @@
1
+ def default_method(hello, bye = nil , opts = {})
2
+ print "aaaa", opts[:a], "hello"
3
+ if bye && opts[:a]
4
+ return 7
5
+ elsif opts[:a]
6
+ return 5
7
+ else
8
+ print "val ->>", opts
9
+ return opts[:a]
10
+ end
11
+ end
@@ -0,0 +1,54 @@
1
+ class Handler
2
+ def error_test(num)
3
+ int i = num
4
+ int j = 0
5
+
6
+ begin
7
+ raise(ArgumentError, "Horrible error.") if i == 1
8
+ raise(LoadError, "Bad error.") if i == 2
9
+ raise(SyntaxError, "Disgusting error.") if i == 3
10
+ rescue ArgumentError
11
+ j = 1
12
+ rescue LoadError
13
+ j = 2
14
+ rescue SyntaxError
15
+ j = 3
16
+ else
17
+ j = 4
18
+ ensure
19
+ j += 5
20
+ end
21
+
22
+ return j
23
+ end
24
+
25
+ def test_uncaught_error
26
+ begin
27
+ raise ArgumentError
28
+ rescue SyntaxError
29
+ end
30
+ end
31
+
32
+ def test_without_rescue
33
+ int i = 1
34
+ begin
35
+ raise ArgumentError
36
+ ensure
37
+ return i
38
+ end
39
+ end
40
+
41
+ def test_decl_inside_begin
42
+ int i
43
+ string = "hello world"
44
+
45
+ begin
46
+ char* s = string
47
+ raise(ArgumentError) if s[0] == 'h'
48
+ rescue ArgumentError
49
+ i = 44
50
+ end
51
+
52
+ return i
53
+ end
54
+ end
@@ -0,0 +1,14 @@
1
+ class Array2Hash
2
+ def self.convert(arr a)
3
+ long int i = a.size
4
+ long int j = 0
5
+ hsh result = {}
6
+
7
+ while j < i do
8
+ result[a[j]] = j
9
+ j += 1
10
+ end
11
+
12
+ return result
13
+ end
14
+ end
@@ -0,0 +1,5 @@
1
+ Name, age, sex
2
+ Sameer, 24, M
3
+ Ameya, 23, M
4
+ Neeraja, 23, F
5
+ Shounak, 24, M
@@ -0,0 +1,329 @@
1
+ lib "rubex/ruby"; end
2
+ lib "rubex/ruby/encoding"; end
3
+ lib "rubex/stdlib"; end
4
+
5
+ lib "csv.h", link: "csv"
6
+ struct csv_parser
7
+ end
8
+
9
+ struct FILE
10
+ end
11
+
12
+ int CSV_STRICT_FINI
13
+ int CSV_APPEND_NULL
14
+ int CSV_EPARSE
15
+ int CSV_ENOMEM
16
+ int CSV_ETOOBIG
17
+ int CSV_EINVALID
18
+ int CSV_STRICT
19
+ int CSV_EMPTY_IS_NULL
20
+
21
+ int csv_init(csv_parser, unsigned char)
22
+ int csv_fini(csv_parser, void (*cb1)(void *, size_t, void *), void (*cb2)(int, void *), void *)
23
+ void csv_free(csv_parser *)
24
+ int csv_error(csv_parser *)
25
+ char * csv_strerror(int)
26
+ size_t csv_parse(csv_parser *p, void *, size_t, void (*cb1)(void *, size_t, void *), void (*cb2)(int, void *), void *)
27
+ size_t csv_write(void *, size_t, void *, size_t)
28
+ int csv_fwrite(FILE *, void *, size_t)
29
+ size_t csv_write2(void *, size_t, void *, size_t, unsigned char)
30
+ int csv_fwrite2(FILE *, void *, size_t, unsigned char)
31
+ int csv_get_opts(csv_parser *)
32
+ int csv_set_opts(csv_parser *, unsigned char)
33
+ void csv_set_delim(csv_parser *, unsigned char)
34
+ void csv_set_quote(csv_parser *, unsigned char)
35
+ unsigned char csv_get_delim(csv_parser *)
36
+ unsigned char csv_get_quote(csv_parser *)
37
+ void csv_set_space_func(csv_parser *, int (*f)(unsigned char))
38
+ void csv_set_term_func(csv_parser *, int (*f)(unsigned char))
39
+ void csv_set_realloc_func(csv_parser *, void *(*cb)(void *, size_t))
40
+ void csv_set_free_func(csv_parser *, void (*cb)(void *))
41
+ void csv_set_blk_size(csv_parser *, size_t)
42
+ size_t csv_get_buffer_size(csv_parser *)
43
+ end
44
+
45
+ struct rcsv_metadata
46
+ # Derived from user-specified options
47
+ bool row_as_hash # Used to return array of hashes rather than array of arrays
48
+ bool empty_field_is_nil # Do we convert empty fields to nils?
49
+ size_t offset_rows # Number of rows to skip before parsing
50
+ int encoding_index # If available, the encoding index of the original input
51
+
52
+ char * row_conversions # A pointer to string/array of row conversions char specifiers
53
+ object * only_rows # A pointer to array of row filters
54
+ object * except_rows # A pointer to array of negative row filters
55
+ object * row_defaults # A pointer to array of row defaults
56
+ object * column_names # A pointer to array of column names to be used with hashes
57
+
58
+ # Pointer options lengths
59
+ size_t num_row_conversions # Number of converter types in row_conversions array
60
+ size_t num_only_rows # Number of items in only_rows filter
61
+ size_t num_except_rows # Number of items in except_rows filter
62
+ size_t num_row_defaults # Number of default values in row_defaults array
63
+ size_t num_columns # Number of columns detected from column_names.size
64
+
65
+ # Internal state
66
+ bool skip_current_row # Used by only_rows and except_rows filters to skip parsing of the row remainder
67
+ size_t current_col # Current column's index
68
+ size_t current_row # Current row's index
69
+
70
+ object last_entry # A pointer to the last entry that's going to be appended to result
71
+ object result # A pointer to the parsed data
72
+ end
73
+
74
+ class RcsvParseError < StandardError
75
+ end
76
+
77
+ class Rcsv
78
+ cfunc object validate_filter_row(row)
79
+ if row == nil
80
+ return nil
81
+ elsif row.is_a?(Array)
82
+ size_t j
83
+ int r_size = row.size
84
+ int type
85
+ for (0 <= j < r_size) do
86
+ type = TYPE(row[i])
87
+
88
+ if type == T_NIL || type == T_TRUE || type == T_FALSE || type == T_FLOAT || type == T_FLOAT || type == T_FIXNUM || type == T_STRING
89
+ break
90
+ else
91
+ raise(RcsvParseError, "Wrong type passed.")
92
+ end
93
+ end
94
+ return row
95
+ else
96
+ raise(RcsvParseError, "Wrong type passed.")
97
+ end
98
+
99
+ end
100
+
101
+ cfunc void end_of_field_callback(void* field, size_t field_size, void* data)
102
+ char* field_str = <char *>field
103
+ rcsv_metadata* meta_p = <rcsv_metadata*>data
104
+ rcsv_metadata meta = meta_p[0]
105
+ char row_conversion = 0
106
+ object parsed_field
107
+
108
+ # No need to parse anything until the end of the line if skip_current_row is set */
109
+ # return if meta.skip_current_row
110
+
111
+ # Skip the row if its position is less than specifed offset
112
+ if (meta.current_row < meta.offset_rows)
113
+ meta_p[0].skip_current_row = true
114
+ return
115
+ end
116
+
117
+ parsed_field = ENCODED_STR_NEW(field_str, field_size, meta.encoding_index)
118
+
119
+ # Filter by row values listed in meta->only_rows */
120
+ if ((meta.only_rows != NULL) && (meta.current_col < meta.num_only_rows) && (meta.only_rows[meta.current_col] != nil) && (!rb_ary_includes(meta.only_rows[meta.current_col], parsed_field)))
121
+ meta_p[0].skip_current_row = true
122
+ return
123
+ end
124
+ # Filter out by row values listed in meta->except_rows
125
+ if ((meta.except_rows != NULL) && (meta.current_col < meta.num_except_rows) && (meta.except_rows[meta.current_col] != nil) && (rb_ary_includes(meta.except_rows[meta.current_col], parsed_field)))
126
+ meta.skip_current_row = true
127
+ return
128
+ end
129
+
130
+ # Assign the value to appropriate hash key if parsing into Hash */
131
+ if meta.row_as_hash
132
+ if meta.current_col >= meta.num_columns
133
+ raise_with_location(meta.current_row, meta.current_col, field_str)
134
+ else
135
+ meta_p[0].last_entry[meta.column_names[meta.current_col]] = parsed_field
136
+ end
137
+ else # Parse into Array
138
+ meta_p[0].last_entry.push(parsed_field) # /* last_entry << field */
139
+ end
140
+
141
+ # Increment column counter */
142
+ meta_p[0].current_col += 1
143
+ return
144
+ end
145
+
146
+ cfunc void raise_with_location(size_t current_row, size_t current_col, char* string)
147
+ end
148
+
149
+ cfunc void end_of_line_callback(int last_char, void* data)
150
+ rcsv_metadata* meta_p = <rcsv_metadata *> data
151
+ rcsv_metadata meta = meta_p[0]
152
+
153
+ # If filters didn't match, current row parsing is reverted */
154
+ if meta.skip_current_row
155
+ meta.skip_current_row = false
156
+ else
157
+ if block_given? # STREAMING
158
+ yield(meta.last_entry)
159
+ else
160
+ meta_p[0].result.push(meta.last_entry)
161
+ end
162
+ end
163
+
164
+ # /* Re-initialize last_entry unless EOF reached */
165
+ if last_char != -1
166
+ if meta.row_as_hash
167
+ meta.last_entry = {}
168
+ else
169
+ meta_p[0].last_entry = []
170
+ end
171
+ end
172
+
173
+ # Resetting column counter
174
+ meta.current_col = 0
175
+
176
+ # Incrementing row counter
177
+ meta.current_row += 1
178
+ end
179
+
180
+ cfunc object ENCODED_STR_NEW(char* string, int length, int enc_index)
181
+ _string = rb_str_new(string, length)
182
+ if (enc_index != -1)
183
+ rb_enc_associate_index(_string, enc_index)
184
+ end
185
+ return _string
186
+ end
187
+
188
+ cfunc void free_all_memory(csv_parser *p_cp, rcsv_metadata *p_meta)
189
+ if p_cp
190
+ csv_free(p_cp)
191
+ end
192
+ end
193
+
194
+ cfunc void setup_rcsv_metadata_defaults(rcsv_metadata *p_meta)
195
+ p_meta[0].row_as_hash = 0
196
+ p_meta[0].empty_field_is_nil = 0
197
+ p_meta[0].skip_current_row = 0
198
+ p_meta[0].encoding_index = -1
199
+ p_meta[0].num_columns = 0
200
+ p_meta[0].current_col = 0
201
+ p_meta[0].current_row = 0
202
+ p_meta[0].offset_rows = 0
203
+ p_meta[0].num_only_rows = 0
204
+ p_meta[0].num_except_rows = 0
205
+ p_meta[0].num_row_defaults = 0
206
+ p_meta[0].num_row_conversions = 0
207
+ p_meta[0].only_rows = NULL
208
+ p_meta[0].except_rows = NULL
209
+ p_meta[0].row_defaults = NULL
210
+ p_meta[0].row_conversions = NULL
211
+ p_meta[0].column_names = NULL
212
+ p_meta[0].result = []
213
+ end
214
+
215
+ def self.parse(file_name, opts)
216
+ rcsv_metadata meta
217
+ object csvio, options, option
218
+ csv_parser cp
219
+ ensure_container = []
220
+ unsigned char csv_options = CSV_STRICT_FINI | CSV_APPEND_NULL
221
+ int csv_string_len
222
+
223
+ setup_rcsv_metadata_defaults(&meta)
224
+ csvio = StringIO.new(file_name)
225
+
226
+ if !opts[:nostrict]
227
+ csv_options |= CSV_STRICT
228
+ end
229
+
230
+ option = opts[:parse_empty_fields_as]
231
+
232
+ if option == nil || option == :nil_or_string
233
+ csv_options |= CSV_EMPTY_IS_NULL
234
+ elsif option.nil?
235
+ meta.empty_field_is_nil = 1
236
+ elsif option == :string
237
+ meta.empty_field_is_nil = 0
238
+ else
239
+ raise(RcsvParseError, "The only valid options for :parse_empty_fields_as are :nil, :string and :nil_or_string.")
240
+ end
241
+
242
+ if csv_init(&cp, csv_options) == -1
243
+ raise(RcsvParseError, "Failed to initialize libcsv.")
244
+ end
245
+
246
+ buffer_size = opts[:buffer_size]
247
+ meta.row_as_hash = 1 if opts[:row_as_hash]
248
+
249
+ csv_set_delim(&cp, col_sep) if opts[:col_sep]
250
+ csv_set_quote(&cp, quote_char) if opts[:quote_char]
251
+
252
+ meta.offset_rows = opts[:offset_rows] if opts[:offset_rows]
253
+
254
+ # Specify character encoding
255
+ option = opts[:output_encoding]
256
+ meta.encoding_index = rb_enc_find_index(<char*>option) if option != nil
257
+
258
+ # :only_rows is a list of values where row is only parsed
259
+ # if its fields match those in the passed array.
260
+ option = opts[:only_rows]
261
+ if option
262
+ meta.num_only_rows = option.size
263
+ meta.only_rows = <object*>xmalloc(meta.num_only_rows * sizeof(object))
264
+
265
+ int i = 0
266
+
267
+ for 0 <= i < meta.num_only_rows do
268
+ only_row = option[i]
269
+ meta.only_rows[i] = validate_filter_row(only_row)
270
+ end
271
+ end
272
+ # TODO: row_defaults, row_conversions, column name declaration when parsing
273
+ # fields as Hashes,
274
+
275
+ # :row_conversions specifies Ruby types that CSV field values should be
276
+ # converted into. Each char of row_conversions string represents Ruby
277
+ # type for CSV field with matching position.
278
+ row_conversions = opts[:row_conversions]
279
+ if row_conversions
280
+ meta.num_row_conversions = row_conversions.size
281
+ meta.row_conversions = row_conversions
282
+ end
283
+
284
+ if meta.row_as_hash
285
+ column_names = opts[:column_names]
286
+
287
+ if column_names.nil?
288
+ # raise RcsvParseError, ":row_as_hash requires :column_names to be set."
289
+ else
290
+ meta.last_entry = {}
291
+ meta.num_columns = column_names.size
292
+ meta.column_names = column_names
293
+ end
294
+ else
295
+ meta.last_entry = []
296
+ end
297
+
298
+ while true do
299
+ csvstr = csvio.read
300
+ # print csvstr
301
+ if csvstr.nil? || csvstr.size == 0
302
+ break
303
+ end
304
+
305
+ char* csv_string = csvstr
306
+ csv_string_len = csvstr.size
307
+
308
+ if csv_string_len != csv_parse(&cp, csv_string, csv_string_len, &end_of_field_callback, &end_of_line_callback, &meta)
309
+ int error = csv_error(&cp)
310
+
311
+ if error == CSV_EPARSE
312
+ raise(RcsvParseError, "Error when parsing malformed data.")
313
+ elsif error == CSV_ENOMEM
314
+ raise(RcsvParseError, "No memory.")
315
+ elsif error == CSV_ETOOBIG
316
+ raise(RcsvParseError, "Field data data is too large.")
317
+ elsif error == CSV_EINVALID
318
+ raise(RcsvParseError, "#{csv_strerror(error)}")
319
+ else
320
+ raise(RcsvParseError, "Something went wrong.")
321
+ end
322
+ end
323
+ end
324
+
325
+ csv_fini(&cp, &end_of_field_callback, &end_of_line_callback, &meta)
326
+ free_all_memory(&cp, &meta)
327
+ return meta.result
328
+ end
329
+ end