rubex 0.0.1 → 0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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