daff 1.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. data/bin/daff.rb +3 -0
  2. data/lib/daff.rb +95 -0
  3. data/lib/lib/coopy/alignment.rb +409 -0
  4. data/lib/lib/coopy/bag.rb +10 -0
  5. data/lib/lib/coopy/cell_info.rb +29 -0
  6. data/lib/lib/coopy/change.rb +48 -0
  7. data/lib/lib/coopy/change_type.rb +21 -0
  8. data/lib/lib/coopy/compare.rb +98 -0
  9. data/lib/lib/coopy/compare_flags.rb +46 -0
  10. data/lib/lib/coopy/compare_table.rb +402 -0
  11. data/lib/lib/coopy/coopy.rb +414 -0
  12. data/lib/lib/coopy/cross_match.rb +16 -0
  13. data/lib/lib/coopy/csv.rb +181 -0
  14. data/lib/lib/coopy/diff_render.rb +254 -0
  15. data/lib/lib/coopy/highlight_patch.rb +651 -0
  16. data/lib/lib/coopy/highlight_patch_unit.rb +37 -0
  17. data/lib/lib/coopy/index.rb +101 -0
  18. data/lib/lib/coopy/index_item.rb +20 -0
  19. data/lib/lib/coopy/index_pair.rb +87 -0
  20. data/lib/lib/coopy/mover.rb +195 -0
  21. data/lib/lib/coopy/ordering.rb +49 -0
  22. data/lib/lib/coopy/report.rb +23 -0
  23. data/lib/lib/coopy/row.rb +9 -0
  24. data/lib/lib/coopy/simple_cell.rb +23 -0
  25. data/lib/lib/coopy/simple_table.rb +242 -0
  26. data/lib/lib/coopy/simple_view.rb +41 -0
  27. data/lib/lib/coopy/sparse_sheet.rb +50 -0
  28. data/lib/lib/coopy/table.rb +17 -0
  29. data/lib/lib/coopy/table_comparison_state.rb +32 -0
  30. data/lib/lib/coopy/table_diff.rb +738 -0
  31. data/lib/lib/coopy/table_io.rb +33 -0
  32. data/lib/lib/coopy/table_modifier.rb +39 -0
  33. data/lib/lib/coopy/table_text.rb +25 -0
  34. data/lib/lib/coopy/unit.rb +70 -0
  35. data/lib/lib/coopy/view.rb +14 -0
  36. data/lib/lib/coopy/viewed_datum.rb +37 -0
  37. data/lib/lib/coopy/viterbi.rb +172 -0
  38. data/lib/lib/coopy/workspace.rb +22 -0
  39. data/lib/lib/haxe/ds/int_map.rb +14 -0
  40. data/lib/lib/haxe/ds/string_map.rb +14 -0
  41. data/lib/lib/haxe/format/json_parser.rb +264 -0
  42. data/lib/lib/haxe/format/json_printer.rb +239 -0
  43. data/lib/lib/haxe/io/bytes.rb +33 -0
  44. data/lib/lib/haxe/io/eof.rb +17 -0
  45. data/lib/lib/haxe/io/error.rb +21 -0
  46. data/lib/lib/haxe/io/output.rb +40 -0
  47. data/lib/lib/haxe/log.rb +16 -0
  48. data/lib/lib/hx_overrides.rb +18 -0
  49. data/lib/lib/imap.rb +6 -0
  50. data/lib/lib/lambda.rb +36 -0
  51. data/lib/lib/list.rb +42 -0
  52. data/lib/lib/rb/boot.rb +19 -0
  53. data/lib/lib/rb/ruby_iterator.rb +49 -0
  54. data/lib/lib/reflect.rb +29 -0
  55. data/lib/lib/string_buf.rb +14 -0
  56. data/lib/lib/sys.rb +19 -0
  57. data/lib/lib/sys/io/file.rb +19 -0
  58. data/lib/lib/sys/io/file_handle.rb +17 -0
  59. data/lib/lib/sys/io/file_output.rb +35 -0
  60. data/lib/lib/type.rb +32 -0
  61. data/lib/lib/value_type.rb +22 -0
  62. metadata +181 -0
@@ -0,0 +1,414 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: utf-8
3
+
4
+ module Coopy
5
+ class Coopy
6
+
7
+ def initialize
8
+ end
9
+
10
+ # protected - in ruby this doesn't play well with static/inline methods
11
+
12
+ attr_accessor :format_preference
13
+ attr_accessor :io
14
+ attr_accessor :mv
15
+
16
+ def save_table(name,t)
17
+ txt = ""
18
+ if @format_preference != "json"
19
+ csv = ::Coopy::Csv.new
20
+ txt = csv.render_table(t)
21
+ else
22
+ value = ::Coopy::Coopy.jsonify(t)
23
+ txt = ::Haxe::Format::JsonPrinter._print(value,nil,nil)
24
+ end
25
+ return self.save_text(name,txt)
26
+ end
27
+
28
+ def save_text(name,txt)
29
+ if name != "-"
30
+ @io.save_content(name,txt)
31
+ else
32
+ @io.write_stdout(txt)
33
+ end
34
+ return true
35
+ end
36
+
37
+ def load_table(name)
38
+ txt = @io.get_content(name)
39
+ begin
40
+ json = ::Haxe::Format::JsonParser.new(txt).parse_rec
41
+ @format_preference = "json"
42
+ t = ::Coopy::Coopy.json_to_table(json)
43
+ raise "JSON failed" if t == nil
44
+ return t
45
+ rescue => e
46
+ csv = ::Coopy::Csv.new
47
+ @format_preference = "csv"
48
+ data = csv.parse_table(txt)
49
+ h = data.length
50
+ w = 0
51
+ w = data[0].length if h > 0
52
+ output = ::Coopy::SimpleTable.new(w,h)
53
+ begin
54
+ _g = 0
55
+ while(_g < h)
56
+ i = _g
57
+ _g+=1
58
+ begin
59
+ _g1 = 0
60
+ while(_g1 < w)
61
+ j = _g1
62
+ _g1+=1
63
+ val = data[i][j]
64
+ output.set_cell(j,i,::Coopy::Coopy.cell_for(val))
65
+ end
66
+ end
67
+ end
68
+ end
69
+ output.trim_blank if output != nil
70
+ return output
71
+ end
72
+ end
73
+
74
+ public
75
+
76
+ def Coopy.compare_tables(local,remote)
77
+ ct = ::Coopy::CompareTable.new
78
+ comp = ::Coopy::TableComparisonState.new
79
+ comp.a = local
80
+ comp.b = remote
81
+ ct.attach(comp)
82
+ return ct
83
+ end
84
+
85
+ def Coopy.compare_tables3(parent,local,remote)
86
+ ct = ::Coopy::CompareTable.new
87
+ comp = ::Coopy::TableComparisonState.new
88
+ comp.p = parent
89
+ comp.a = local
90
+ comp.b = remote
91
+ ct.attach(comp)
92
+ return ct
93
+ end
94
+
95
+ # protected - in ruby this doesn't play well with static/inline methods
96
+
97
+ def Coopy.random_tests
98
+ st = ::Coopy::SimpleTable.new(15,6)
99
+ tab = st
100
+ ::Haxe::Log._trace.call("table size is " + _hx_str(tab.get_width) + "x" + _hx_str(tab.get_height),{ file_name: "Coopy.hx", line_number: 42, class_name: "coopy.Coopy", method_name: "randomTests"})
101
+ tab.set_cell(3,4,::Coopy::SimpleCell.new(33))
102
+ ::Haxe::Log._trace.call("element is " + _hx_str(lambda{ s = tab.get_cell(3,4)
103
+ _r = s.to_s}.call()),{ file_name: "Coopy.hx", line_number: 44, class_name: "coopy.Coopy", method_name: "randomTests"})
104
+ compare = ::Coopy::Compare.new
105
+ d1 = ::Coopy::ViewedDatum.get_simple_view(::Coopy::SimpleCell.new(10))
106
+ d2 = ::Coopy::ViewedDatum.get_simple_view(::Coopy::SimpleCell.new(10))
107
+ d3 = ::Coopy::ViewedDatum.get_simple_view(::Coopy::SimpleCell.new(20))
108
+ report = ::Coopy::Report.new
109
+ compare.compare(d1,d2,d3,report)
110
+ ::Haxe::Log._trace.call("report is " + _hx_str(report.to_s),{ file_name: "Coopy.hx", line_number: 52, class_name: "coopy.Coopy", method_name: "randomTests"})
111
+ d2 = ::Coopy::ViewedDatum.get_simple_view(::Coopy::SimpleCell.new(50))
112
+ report.clear
113
+ compare.compare(d1,d2,d3,report)
114
+ ::Haxe::Log._trace.call("report is " + _hx_str(report.to_s),{ file_name: "Coopy.hx", line_number: 56, class_name: "coopy.Coopy", method_name: "randomTests"})
115
+ d2 = ::Coopy::ViewedDatum.get_simple_view(::Coopy::SimpleCell.new(20))
116
+ report.clear
117
+ compare.compare(d1,d2,d3,report)
118
+ ::Haxe::Log._trace.call("report is " + _hx_str(report.to_s),{ file_name: "Coopy.hx", line_number: 60, class_name: "coopy.Coopy", method_name: "randomTests"})
119
+ d1 = ::Coopy::ViewedDatum.get_simple_view(::Coopy::SimpleCell.new(20))
120
+ report.clear
121
+ compare.compare(d1,d2,d3,report)
122
+ ::Haxe::Log._trace.call("report is " + _hx_str(report.to_s),{ file_name: "Coopy.hx", line_number: 64, class_name: "coopy.Coopy", method_name: "randomTests"})
123
+ comp = ::Coopy::TableComparisonState.new
124
+ ct = ::Coopy::CompareTable.new
125
+ comp.a = st
126
+ comp.b = st
127
+ ct.attach(comp)
128
+ ::Haxe::Log._trace.call("comparing tables",{ file_name: "Coopy.hx", line_number: 72, class_name: "coopy.Coopy", method_name: "randomTests"})
129
+ t1 = ::Coopy::SimpleTable.new(3,2)
130
+ t2 = ::Coopy::SimpleTable.new(3,2)
131
+ t3 = ::Coopy::SimpleTable.new(3,2)
132
+ dt1 = ::Coopy::ViewedDatum.new(t1,::Coopy::SimpleView.new)
133
+ dt2 = ::Coopy::ViewedDatum.new(t2,::Coopy::SimpleView.new)
134
+ dt3 = ::Coopy::ViewedDatum.new(t3,::Coopy::SimpleView.new)
135
+ compare.compare(dt1,dt2,dt3,report)
136
+ ::Haxe::Log._trace.call("report is " + _hx_str(report.to_s),{ file_name: "Coopy.hx", line_number: 80, class_name: "coopy.Coopy", method_name: "randomTests"})
137
+ t3.set_cell(1,1,::Coopy::SimpleCell.new("hello"))
138
+ compare.compare(dt1,dt2,dt3,report)
139
+ ::Haxe::Log._trace.call("report is " + _hx_str(report.to_s),{ file_name: "Coopy.hx", line_number: 83, class_name: "coopy.Coopy", method_name: "randomTests"})
140
+ t1.set_cell(1,1,::Coopy::SimpleCell.new("hello"))
141
+ compare.compare(dt1,dt2,dt3,report)
142
+ ::Haxe::Log._trace.call("report is " + _hx_str(report.to_s),{ file_name: "Coopy.hx", line_number: 86, class_name: "coopy.Coopy", method_name: "randomTests"})
143
+ v = ::Coopy::Viterbi.new
144
+ td = ::Coopy::TableDiff.new(nil,nil)
145
+ idx = ::Coopy::Index.new
146
+ dr = ::Coopy::DiffRender.new
147
+ cf = ::Coopy::CompareFlags.new
148
+ hp = ::Coopy::HighlightPatch.new(nil,nil)
149
+ csv = ::Coopy::Csv.new
150
+ tm = ::Coopy::TableModifier.new(nil)
151
+ return 0
152
+ end
153
+
154
+ def Coopy.cell_for(x)
155
+ return nil if x == nil
156
+ return ::Coopy::SimpleCell.new(x)
157
+ end
158
+
159
+ def Coopy.json_to_table(json)
160
+ output = nil
161
+ begin
162
+ _g = 0
163
+ _g1 = Reflect.fields(json)
164
+ while(_g < _g1.length)
165
+ name = _g1[_g]
166
+ _g+=1
167
+ t = Reflect.field(json,name)
168
+ columns = Reflect.field(t,"columns")
169
+ next if columns == nil
170
+ rows = Reflect.field(t,"rows")
171
+ next if rows == nil
172
+ output = ::Coopy::SimpleTable.new(columns.length,rows.length)
173
+ has_hash = false
174
+ has_hash_known = false
175
+ begin
176
+ _g3 = 0
177
+ _g2 = rows.length
178
+ while(_g3 < _g2)
179
+ i = _g3
180
+ _g3+=1
181
+ row = rows[i]
182
+ if !has_hash_known
183
+ has_hash = true if Reflect.fields(row).length == columns.length
184
+ has_hash_known = true
185
+ end
186
+ if !has_hash
187
+ lst = row
188
+ begin
189
+ _g5 = 0
190
+ _g4 = columns.length
191
+ while(_g5 < _g4)
192
+ j = _g5
193
+ _g5+=1
194
+ val = lst[j]
195
+ output.set_cell(j,i,::Coopy::Coopy.cell_for(val))
196
+ end
197
+ end
198
+ else
199
+ _g51 = 0
200
+ _g41 = columns.length
201
+ while(_g51 < _g41)
202
+ j1 = _g51
203
+ _g51+=1
204
+ val1 = Reflect.field(row,columns[j1])
205
+ output.set_cell(j1,i,::Coopy::Coopy.cell_for(val1))
206
+ end
207
+ end
208
+ end
209
+ end
210
+ end
211
+ end
212
+ output.trim_blank if output != nil
213
+ return output
214
+ end
215
+
216
+ public
217
+
218
+ def Coopy.coopyhx(io)
219
+ args = io.args
220
+ return ::Coopy::Coopy.random_tests if args[0] == "--test"
221
+ more = true
222
+ output = nil
223
+ css_output = nil
224
+ fragment = false
225
+ pretty = true
226
+ flags = ::Coopy::CompareFlags.new
227
+ flags.always_show_header = true
228
+ while(more)
229
+ more = false
230
+ begin
231
+ _g1 = 0
232
+ _g = args.length
233
+ while(_g1 < _g)
234
+ i = _g1
235
+ _g1+=1
236
+ tag = args[i]
237
+ if tag == "--output"
238
+ more = true
239
+ output = args[i + 1]
240
+ args.slice!(i,2)
241
+ break
242
+ elsif tag == "--css"
243
+ more = true
244
+ fragment = true
245
+ css_output = args[i + 1]
246
+ args.slice!(i,2)
247
+ break
248
+ elsif tag == "--fragment"
249
+ more = true
250
+ fragment = true
251
+ args.slice!(i,1)
252
+ break
253
+ elsif tag == "--plain"
254
+ more = true
255
+ pretty = false
256
+ args.slice!(i,1)
257
+ break
258
+ elsif tag == "--all"
259
+ more = true
260
+ flags.show_unchanged = true
261
+ args.slice!(i,1)
262
+ break
263
+ elsif tag == "--act"
264
+ more = true
265
+ flags.acts = {} if flags.acts == nil
266
+ begin
267
+ flags.acts[args[i + 1]] = true
268
+ true
269
+ end
270
+ args.slice!(i,2)
271
+ break
272
+ elsif tag == "--context"
273
+ more = true
274
+ context = args[i + 1].to_i
275
+ flags.unchanged_context = context if context >= 0
276
+ args.slice!(i,2)
277
+ break
278
+ end
279
+ end
280
+ end
281
+ end
282
+ cmd = args[0]
283
+ if args.length < 2
284
+ io.write_stderr("daff can produce and apply tabular diffs.\n")
285
+ io.write_stderr("Call as:\n")
286
+ io.write_stderr(" daff [--output OUTPUT.csv] a.csv b.csv\n")
287
+ io.write_stderr(" daff [--output OUTPUT.csv] parent.csv a.csv b.csv\n")
288
+ io.write_stderr(" daff [--output OUTPUT.jsonbook] a.jsonbook b.jsonbook\n")
289
+ io.write_stderr(" daff patch [--output OUTPUT.csv] source.csv patch.csv\n")
290
+ io.write_stderr(" daff trim [--output OUTPUT.csv] source.csv\n")
291
+ io.write_stderr(" daff render [--output OUTPUT.html] diff.csv\n")
292
+ io.write_stderr("\n")
293
+ io.write_stderr("If you need more control, here is the full list of flags:\n")
294
+ io.write_stderr(" daff diff [--output OUTPUT.csv] [--context NUM] [--all] [--act ACT] a.csv b.csv\n")
295
+ io.write_stderr(" --context NUM: show NUM rows of context\n")
296
+ io.write_stderr(" --all: do not prune unchanged rows\n")
297
+ io.write_stderr(" --act ACT: show only a certain kind of change (update, insert, delete)\n")
298
+ io.write_stderr("\n")
299
+ io.write_stderr(" daff render [--output OUTPUT.html] [--css CSS.css] [--fragment] [--plain] diff.csv\n")
300
+ io.write_stderr(" --css CSS.css: generate a suitable css file to go with the html\n")
301
+ io.write_stderr(" --fragment: generate just a html fragment rather than a page\n")
302
+ io.write_stderr(" --plain: do not use fancy utf8 characters to make arrows prettier\n")
303
+ return 1
304
+ end
305
+ output = "-" if output == nil
306
+ cmd1 = args[0]
307
+ offset = 1
308
+ if !Lambda.has(["diff","patch","trim","render"],cmd1)
309
+ if (cmd1.index(".",nil || 0) || -1) != -1 || (cmd1.index("--",nil || 0) || -1) == 0
310
+ cmd1 = "diff"
311
+ offset = 0
312
+ end
313
+ end
314
+ tool = ::Coopy::Coopy.new
315
+ tool.io = io
316
+ parent = nil
317
+ if args.length - offset >= 3
318
+ parent = tool.load_table(args[offset])
319
+ offset+=1
320
+ end
321
+ a = tool.load_table(args[offset])
322
+ b = nil
323
+ b = tool.load_table(args[1 + offset]) if args.length - offset >= 2
324
+ if cmd1 == "diff"
325
+ ct = ::Coopy::Coopy.compare_tables3(parent,a,b)
326
+ align = ct.align
327
+ td = ::Coopy::TableDiff.new(align,flags)
328
+ o = ::Coopy::SimpleTable.new(0,0)
329
+ td.hilite(o)
330
+ tool.save_table(output,o)
331
+ elsif cmd1 == "patch"
332
+ patcher = ::Coopy::HighlightPatch.new(a,b)
333
+ patcher.apply
334
+ tool.save_table(output,a)
335
+ elsif cmd1 == "trim"
336
+ tool.save_table(output,a)
337
+ elsif cmd1 == "render"
338
+ renderer = ::Coopy::DiffRender.new
339
+ renderer.use_pretty_arrows(pretty)
340
+ renderer.render(a)
341
+ renderer.complete_html if !fragment
342
+ tool.save_text(output,renderer.html)
343
+ tool.save_text(css_output,renderer.sample_css) if css_output != nil
344
+ end
345
+ return 0
346
+ end
347
+
348
+ def Coopy.main
349
+ io = ::Coopy::TableIO.new
350
+ return ::Coopy::Coopy.coopyhx(io)
351
+ end
352
+
353
+ def Coopy.show(t)
354
+ w = t.get_width
355
+ h = t.get_height
356
+ txt = ""
357
+ begin
358
+ _g = 0
359
+ while(_g < h)
360
+ y = _g
361
+ _g+=1
362
+ begin
363
+ _g1 = 0
364
+ while(_g1 < w)
365
+ x = _g1
366
+ _g1+=1
367
+ begin
368
+ s = t.get_cell(x,y)
369
+ txt += s.to_s
370
+ end
371
+ txt += " "
372
+ end
373
+ end
374
+ txt += "\n"
375
+ end
376
+ end
377
+ ::Haxe::Log._trace.call(txt,{ file_name: "Coopy.hx", line_number: 353, class_name: "coopy.Coopy", method_name: "show"})
378
+ end
379
+
380
+ def Coopy.jsonify(t)
381
+ workbook = {}
382
+ sheet = Array.new
383
+ w = t.get_width
384
+ h = t.get_height
385
+ txt = ""
386
+ begin
387
+ _g = 0
388
+ while(_g < h)
389
+ y = _g
390
+ _g+=1
391
+ row = Array.new
392
+ begin
393
+ _g1 = 0
394
+ while(_g1 < w)
395
+ x = _g1
396
+ _g1+=1
397
+ v = t.get_cell(x,y)
398
+ if v != nil
399
+ row.push(v[:to_s].call)
400
+ else
401
+ row.push(nil)
402
+ end
403
+ end
404
+ end
405
+ sheet.push(row)
406
+ end
407
+ end
408
+ workbook["sheet"] = sheet
409
+ return workbook
410
+ end
411
+
412
+ end
413
+
414
+ end
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: utf-8
3
+
4
+ module Coopy
5
+ class CrossMatch
6
+
7
+ def initialize
8
+ end
9
+
10
+ attr_accessor :spot_a
11
+ attr_accessor :spot_b
12
+ attr_accessor :item_a
13
+ attr_accessor :item_b
14
+ end
15
+
16
+ end
@@ -0,0 +1,181 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: utf-8
3
+
4
+ module Coopy
5
+ class Csv
6
+
7
+ def initialize
8
+ @cursor = 0
9
+ @row_ended = false
10
+ end
11
+
12
+ protected
13
+
14
+ attr_accessor :cursor
15
+ attr_accessor :row_ended
16
+ attr_accessor :has_structure
17
+
18
+ public
19
+
20
+ def render_table(t)
21
+ result = ""
22
+ w = t.get_width
23
+ h = t.get_height
24
+ txt = ""
25
+ v = t.get_cell_view
26
+ begin
27
+ _g = 0
28
+ while(_g < h)
29
+ y = _g
30
+ _g+=1
31
+ begin
32
+ _g1 = 0
33
+ while(_g1 < w)
34
+ x = _g1
35
+ _g1+=1
36
+ txt += "," if x > 0
37
+ txt += self.render_cell(v,t.get_cell(x,y))
38
+ end
39
+ end
40
+ txt += "\r\n"
41
+ end
42
+ end
43
+ return txt
44
+ end
45
+
46
+ def render_cell(v,d)
47
+ return "NULL" if d == nil
48
+ return "NULL" if v.equals(d,nil)
49
+ str = v.to_s(d)
50
+ delim = ","
51
+ need_quote = false
52
+ begin
53
+ _g1 = 0
54
+ _g = str.length
55
+ while(_g1 < _g)
56
+ i = _g1
57
+ _g1+=1
58
+ ch = str[i]
59
+ if ch == "\"" || ch == "'" || ch == delim || ch == "\r" || ch == "\n" || ch == "\t" || ch == " "
60
+ need_quote = true
61
+ break
62
+ end
63
+ end
64
+ end
65
+ result = ""
66
+ result += "\"" if need_quote
67
+ line_buf = ""
68
+ begin
69
+ _g11 = 0
70
+ _g2 = str.length
71
+ while(_g11 < _g2)
72
+ i1 = _g11
73
+ _g11+=1
74
+ ch1 = str[i1]
75
+ result += "\"" if ch1 == "\""
76
+ if ch1 != "\r" && ch1 != "\n"
77
+ if line_buf.length > 0
78
+ result += line_buf
79
+ line_buf = ""
80
+ end
81
+ result += ch1
82
+ else
83
+ line_buf += ch1
84
+ end
85
+ end
86
+ end
87
+ result += "\"" if need_quote
88
+ return result
89
+ end
90
+
91
+ def parse_table(txt)
92
+ @cursor = 0
93
+ @row_ended = false
94
+ @has_structure = true
95
+ result = Array.new
96
+ row = Array.new
97
+ while(@cursor < txt.length)
98
+ cell = self.parse_cell(txt)
99
+ row.push(cell)
100
+ if @row_ended
101
+ result.push(row)
102
+ row = Array.new
103
+ end
104
+ @cursor+=1
105
+ end
106
+ return result
107
+ end
108
+
109
+ def parse_cell(txt)
110
+ return nil if txt == nil
111
+ @row_ended = false
112
+ first_non_underscore = txt.length
113
+ last_processed = 0
114
+ quoting = false
115
+ quote = 0
116
+ result = ""
117
+ start = @cursor
118
+ begin
119
+ _g1 = @cursor
120
+ _g = txt.length
121
+ while(_g1 < _g)
122
+ i = _g1
123
+ _g1+=1
124
+ ch = (txt[i].ord rescue nil)
125
+ last_processed = i
126
+ first_non_underscore = i if ch != 95 && i < first_non_underscore
127
+ if @has_structure
128
+ if !quoting
129
+ break if ch == 44
130
+ if ch == 13 || ch == 10
131
+ ch2 = (txt[i + 1].ord rescue nil)
132
+ if ch2 != nil
133
+ if ch2 != ch
134
+ last_processed+=1 if ch2 == 13 || ch2 == 10
135
+ end
136
+ end
137
+ @row_ended = true
138
+ break
139
+ end
140
+ if ch == 34 || ch == 39
141
+ if i == @cursor
142
+ quoting = true
143
+ quote = ch
144
+ result += [ch].pack("U") if i != start
145
+ next
146
+ elsif ch == quote
147
+ quoting = true
148
+ end
149
+ end
150
+ result += [ch].pack("U")
151
+ next
152
+ end
153
+ if ch == quote
154
+ quoting = false
155
+ next
156
+ end
157
+ end
158
+ result += [ch].pack("U")
159
+ end
160
+ end
161
+ @cursor = last_processed
162
+ if quote == 0
163
+ return nil if result == "NULL"
164
+ if first_non_underscore > start
165
+ del = first_non_underscore - start
166
+ return result[1..-1] if result[del..-1] == "NULL"
167
+ end
168
+ end
169
+ return result
170
+ end
171
+
172
+ def parse_single_cell(txt)
173
+ @cursor = 0
174
+ @row_ended = false
175
+ @has_structure = false
176
+ return self.parse_cell(txt)
177
+ end
178
+
179
+ end
180
+
181
+ end