daff 1.1.2

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 (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