dsv 0.12.6 → 0.12.7

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7322674ac0843543bf2f813312290dd2c4d460c7c3d0e8e8d604ccfcb680a196
4
- data.tar.gz: 866e0a95d7854265444854111c0f1b61ed5e0faf9eb1f55ba20061f60fe52447
3
+ metadata.gz: ac547ecbc72cfc0cfb3b4e2a1f9c0c5327ea1f4e064c126a28aa85f8c3a42ded
4
+ data.tar.gz: 5be7f5303ed207575c43dfacac8d7b4e68f259172b48d25aba60104af57b68f7
5
5
  SHA512:
6
- metadata.gz: 219226e29fa873569b197d731813421aa478d18719bb25ede6501b84ab42efd574112a1131c7e3526933fe5099c8c1c3fffb8345d1fcdb26392dd8ef9fe445c9
7
- data.tar.gz: e57b19a5fc7ce1855f4fd40cca7a496bd946464c43f84e00e13f8a3b031d2e8b7c104e6995e749d2955a968c941896d80951f8190f557ff17ea92734c65aba66
6
+ metadata.gz: 022fbe8f4caf5baf90c785ba1ef586574d270331e25b6734e1e982766e1a8836a3182f1f92452734ce1d3316e834e0b07da4b8f9b89f6105c45222e4505dab7b
7
+ data.tar.gz: 19cd8f16d5b72349be0e066f63a5dcbac7cc9ea1ab4736e67cd07507415794ce2f9cc47d9bc747358125c252480018b1a0170efd820bdab8056611f46971cfd0
data/CHANGELOG CHANGED
@@ -2,6 +2,12 @@
2
2
 
3
3
  ## 20261027
4
4
 
5
+ 0.12.7: ~ reassemble_quoted_fields(): an escaped quote before a separator no longer closes a quoted field.
6
+
7
+ 1. ~ reassemble_quoted_fields(): a piece closes a field where it ends in an odd run of quotes; + trailing_quotes().
8
+ 2. ~ test/dsv_test.rb: - the skip on a doubled quote before a separator.
9
+ 3. ~ lib/DSV/VERSION.rb: /0.12.6/0.12.7/.
10
+
5
11
  0.12.6: + quoting examples.
6
12
 
7
13
  1. ~ test/dsv_test.rb: + a doubled quote before a separator, skipped; + a quote not opening a field read as data; + a stray quote not taking in the next line, skipped; + an unclosed quoted field raising UnterminatedQuote, skipped.
data/lib/DSV/VERSION.rb CHANGED
@@ -2,5 +2,5 @@
2
2
  # DSV::VERSION
3
3
 
4
4
  class DSV
5
- VERSION = '0.12.6'
5
+ VERSION = '0.12.7'
6
6
  end
data/lib/dsv.rb CHANGED
@@ -332,19 +332,19 @@ class DSV
332
332
  )
333
333
  end
334
334
 
335
- # Pieces of a row split on the separator, the pieces of a quoted field that held the separator joined back with it, or with the text it matched where the separator is a Regexp; a piece that is a lone quote opens or closes a field.
335
+ # Pieces of a row split on the separator, the pieces of a quoted field that held the separator joined back with it, or with the text it matched where the separator is a Regexp; a piece closes a field where it ends in an odd run of quotes, a doubled quote being escaped, and a piece that is a lone quote opens or closes one.
336
336
  def reassemble_quoted_fields(pieces, separators = nil)
337
337
  fields = []
338
338
  buffer = nil
339
339
  pieces.each_with_index do |piece, i|
340
- if buffer && !piece.end_with?('"')
340
+ if buffer && trailing_quotes(piece, -1).even?
341
341
  buffer << separator_before(i, separators) << piece
342
342
  elsif buffer
343
343
  fields << (buffer << separator_before(i, separators) << piece.delete_suffix('"')).gsub('""', '"')
344
344
  buffer = nil
345
- elsif piece.start_with?('"') && (piece.length == 1 || !piece.end_with?('"'))
345
+ elsif piece.start_with?('"') && trailing_quotes(piece, 0).even?
346
346
  buffer = +piece.delete_prefix('"')
347
- elsif piece.start_with?('"') && piece.end_with?('"')
347
+ elsif piece.start_with?('"')
348
348
  fields << piece.delete_prefix('"').delete_suffix('"').gsub('""', '"')
349
349
  else
350
350
  fields << piece
@@ -353,6 +353,13 @@ class DSV
353
353
  fields
354
354
  end
355
355
 
356
+ # How many quotes a piece ends with, counting back to but not including the byte given, so that a field's opening quote is not taken for part of its closing. Read by byte, a quote being 34 in any ASCII-compatible encoding, so that nothing is allocated per character.
357
+ def trailing_quotes(piece, floor)
358
+ i = piece.bytesize - 1
359
+ i -= 1 while i > floor && piece.getbyte(i) == 34
360
+ piece.bytesize - 1 - i
361
+ end
362
+
356
363
  # What stood between a piece and the one before it: the separator, or the text a Regexp separator matched there.
357
364
  def separator_before(i, separators)
358
365
  separators ? separators[i - 1] : @column_separator
data/test/dsv_test.rb CHANGED
@@ -243,7 +243,6 @@ describe DSV do
243
243
  end
244
244
 
245
245
  it "reads a doubled quote just before a separator inside a quoted field" do
246
- skip "Observation: a piece of a quoted field ending in a quote is taken as the field's end, an escaped quote ending in one as a closing quote does"
247
246
  _(DSV.parse_line('"He said ""no"", then left",x')).must_equal ['He said "no", then left', 'x']
248
247
  _(DSV.parse_line('"a"",""b",c')).must_equal ['a","b', 'c']
249
248
  _(DSV.read("\"a\"\",\"\"b\",\"c\"\n", quote: :double)).must_equal [{0 => 'a","b', 1 => 'c'}]
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dsv
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.12.6
4
+ version: 0.12.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - thoran