carton_db 1.1.2 → 1.1.3

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
  SHA1:
3
- metadata.gz: d16d6802fee28aa151d8eee4811d17d3a5dc00a5
4
- data.tar.gz: 22cb133e4202c80ef89109a24163c41b666ec89c
3
+ metadata.gz: b0569eb04a7231087ac8ba262cc56330a1c61912
4
+ data.tar.gz: aaae82f45cfdeb14e4dea5110e9a09c3b062ab5e
5
5
  SHA512:
6
- metadata.gz: 3ff1b4d0a6a5582d5903093e80051600e119f8c857b9ba32821081113b3cf90b3802c3f10f83a4fba0173b987ef55f699d3ae6289b1dfda47934b5105eb92b15
7
- data.tar.gz: 04747d51836cc9864fc5e5245f884d42c585cb434ba7ce66441f19836c87d841ed74a60765d5b93a5767f13279ae93b3c81da2b59ec853fbda5082961841472e
6
+ metadata.gz: e07e734b21b74e9988654549060f615897fb9b5e57763a61d392bf58ef0ff46845ba43118c805766f9177a117d0c4f7d49d1fa52e13e8e2042f410dd385b18a3
7
+ data.tar.gz: 5c818326762c092a868e9abc642ce1baa3a1b9a2fbe38a17c7932f0ebbbde99a1e0a8d72cd7479a98e61a5c97cc1516968f92e9c655cb0e1758333f02a778b2d
@@ -1,3 +1,6 @@
1
+ # -*- coding: UTF-8 -*-
2
+ # frozen_string_literal: true
3
+
1
4
  require 'digest'
2
5
 
3
6
  module CartonDb
@@ -5,20 +8,22 @@ module CartonDb
5
8
  module Datum
6
9
 
7
10
  def self.for_plain(plain_text, auto_placeholder: false)
8
- return plain_text if plain_text.is_a?(Datum::Base)
9
- if auto_placeholder && plain_text.nil?
11
+ if auto_placeholder && (! plain_text) && plain_text.nil?
10
12
  Datum::Placeholder
13
+ elsif plain_text.is_a?(Datum::Base)
14
+ plain_text
11
15
  else
12
- Datum::ForPlain.new(plain_text)
16
+ Datum::ForPlain.new(plain_text.to_s)
13
17
  end
14
18
  end
15
19
 
16
20
  def self.for_escaped(escaped_text, auto_placeholder: false)
17
- return escaped_text if escaped_text.is_a?(Datum::Base)
18
- if auto_placeholder && escaped_text.nil?
21
+ if auto_placeholder && (! escaped_text) && escaped_text.nil?
19
22
  Datum::Placeholder
23
+ elsif escaped_text.is_a?(Datum::Base)
24
+ escaped_text
20
25
  else
21
- Datum::ForEscaped.new(escaped_text)
26
+ Datum::ForEscaped.new(escaped_text.to_s)
22
27
  end
23
28
  end
24
29
 
@@ -58,8 +63,9 @@ module CartonDb
58
63
  class ForPlain < Datum::Base
59
64
  attr_reader :plain
60
65
 
66
+
61
67
  def initialize(plain)
62
- if plain.nil?
68
+ if (! plain) && plain.nil?
63
69
  raise ArgumentError "A non-nil 'plain' value is required."
64
70
  end
65
71
  @plain = plain
@@ -90,7 +96,7 @@ module CartonDb
90
96
  attr_reader :escaped
91
97
 
92
98
  def initialize(escaped)
93
- if escaped.nil?
99
+ if (! escaped) && escaped.nil?
94
100
  raise ArgumentError "A non-nil 'escaped' value is required."
95
101
  end
96
102
  @escaped = escaped
@@ -1,42 +1,45 @@
1
+ # -*- coding: UTF-8 -*-
2
+ # frozen_string_literal: true
3
+
1
4
  module CartonDb
2
5
 
3
6
  module Escaping
4
7
 
5
8
  ESCAPING_MAP = {
6
- "\u0000".freeze => '\x00'.freeze,
7
- "\u0001".freeze => '\x01'.freeze,
8
- "\u0002".freeze => '\x02'.freeze,
9
- "\u0003".freeze => '\x03'.freeze,
10
- "\u0004".freeze => '\x04'.freeze,
11
- "\u0005".freeze => '\x05'.freeze,
12
- "\u0006".freeze => '\x06'.freeze,
13
- "\u0007".freeze => '\a'.freeze,
14
- "\u0008".freeze => '\b'.freeze,
15
- "\u0009".freeze => '\t'.freeze,
16
- "\u000A".freeze => '\n'.freeze,
17
- "\u000B".freeze => '\v'.freeze,
18
- "\u000C".freeze => '\f'.freeze,
19
- "\u000D".freeze => '\r'.freeze,
20
- "\u000E".freeze => '\x0E'.freeze,
21
- "\u000F".freeze => '\x0F'.freeze,
22
- "\u0010".freeze => '\x10'.freeze,
23
- "\u0011".freeze => '\x11'.freeze,
24
- "\u0012".freeze => '\x12'.freeze,
25
- "\u0013".freeze => '\x13'.freeze,
26
- "\u0014".freeze => '\x14'.freeze,
27
- "\u0015".freeze => '\x15'.freeze,
28
- "\u0016".freeze => '\x16'.freeze,
29
- "\u0017".freeze => '\x17'.freeze,
30
- "\u0018".freeze => '\x18'.freeze,
31
- "\u0019".freeze => '\x19'.freeze,
32
- "\u001A".freeze => '\x1A'.freeze,
33
- "\u001B".freeze => '\x1B'.freeze,
34
- "\u001C".freeze => '\x1C'.freeze,
35
- "\u001D".freeze => '\x1D'.freeze,
36
- "\u001E".freeze => '\x1E'.freeze,
37
- "\u001F".freeze => '\x1F'.freeze,
38
- "\u007F".freeze => '\x7F'.freeze,
39
- "\\".freeze => "\\\\".freeze,
9
+ "\u0000" => '\x00',
10
+ "\u0001" => '\x01',
11
+ "\u0002" => '\x02',
12
+ "\u0003" => '\x03',
13
+ "\u0004" => '\x04',
14
+ "\u0005" => '\x05',
15
+ "\u0006" => '\x06',
16
+ "\u0007" => '\a',
17
+ "\u0008" => '\b',
18
+ "\u0009" => '\t',
19
+ "\u000A" => '\n',
20
+ "\u000B" => '\v',
21
+ "\u000C" => '\f',
22
+ "\u000D" => '\r',
23
+ "\u000E" => '\x0E',
24
+ "\u000F" => '\x0F',
25
+ "\u0010" => '\x10',
26
+ "\u0011" => '\x11',
27
+ "\u0012" => '\x12',
28
+ "\u0013" => '\x13',
29
+ "\u0014" => '\x14',
30
+ "\u0015" => '\x15',
31
+ "\u0016" => '\x16',
32
+ "\u0017" => '\x17',
33
+ "\u0018" => '\x18',
34
+ "\u0019" => '\x19',
35
+ "\u001A" => '\x1A',
36
+ "\u001B" => '\x1B',
37
+ "\u001C" => '\x1C',
38
+ "\u001D" => '\x1D',
39
+ "\u001E" => '\x1E',
40
+ "\u001F" => '\x1F',
41
+ "\u007F" => '\x7F',
42
+ "\\" => "\\\\",
40
43
  }.freeze
41
44
 
42
45
  UNESCAPING_MAP = ESCAPING_MAP.invert.freeze
@@ -1,5 +1,8 @@
1
1
  # -*- coding: UTF-8 -*-
2
+ # frozen_string_literal: true
3
+
2
4
  require 'fileutils'
5
+ require 'set'
3
6
 
4
7
  module CartonDb
5
8
  class ListMapDb
@@ -58,6 +61,55 @@ module CartonDb
58
61
  ! content?
59
62
  end
60
63
 
64
+ def key_count
65
+ return 0 if empty?
66
+ key_d_set.length
67
+ end
68
+
69
+ def touch_d(key_d, optimization)
70
+ if optimization == :small && content?
71
+ each_entry_element_line do |kd, _ed, _line|
72
+ return if kd == key_d
73
+ end
74
+ end
75
+
76
+ open_append do |io|
77
+ io << key_d.escaped << "\n"
78
+ end
79
+ end
80
+
81
+ def key_d_set
82
+ result = Set.new
83
+ each_entry_element_line do |kd, _ed, _line|
84
+ result << kd
85
+ end
86
+ result
87
+ end
88
+
89
+ def key_d?(key_d)
90
+ each_entry_element_line do |kd, _ed, _line|
91
+ return true if kd = key_d
92
+ end
93
+ false
94
+ end
95
+
96
+ def element_d?(key_d, element_d)
97
+ each_entry_element_line do |kd, ed, _line|
98
+ return true if kd == key_d && ed == element_d
99
+ end
100
+ false
101
+ end
102
+
103
+ def collect_content(key_d, collection_class)
104
+ result = nil
105
+ each_entry_element_line do |kd, ed, _line|
106
+ next unless kd == key_d
107
+ result ||= collection_class.new
108
+ result << ed.plain unless ed.placeholder?
109
+ end
110
+ result
111
+ end
112
+
61
113
  def each_entry
62
114
  entries = nil
63
115
  each_entry_element_line do |key_d, elem_d, _line|
@@ -71,6 +123,13 @@ module CartonDb
71
123
  end
72
124
  end
73
125
 
126
+ def each_element_for_d(key_d)
127
+ each_entry_element_line do |kd, ed, _line|
128
+ next unless kd == key_d
129
+ yield ed
130
+ end
131
+ end
132
+
74
133
  def each_first_element
75
134
  first_entries = nil
76
135
  each_entry_element_line do |key_d, elem_d, _line|
@@ -94,6 +153,41 @@ module CartonDb
94
153
  end
95
154
  end
96
155
 
156
+ def replace
157
+ replacement = self.class.new(
158
+ segment_group, "#{segment_filename}.txt"
159
+ )
160
+ begin
161
+ yield replacement
162
+ rescue StandardError
163
+ File.unlink replacement.filename
164
+ raise
165
+ end
166
+ File.unlink filename
167
+ File.rename replacement.filename, filename
168
+ end
169
+
170
+ def write_key_element_d(key_d, element_d)
171
+ open_append do |io|
172
+ io << "#{key_d.escaped}\t#{element_d.escaped}\n"
173
+ end
174
+ end
175
+
176
+ def write_key_d_elements(key_d, elements)
177
+ open_append do |io|
178
+ elements.each do |element|
179
+ element_d = CartonDb::Datum.for_plain(element)
180
+ io<< "#{key_d.escaped}\t#{element_d.escaped}\n"
181
+ end
182
+ end
183
+ end
184
+
185
+ def copy_entries_except(key_d, to_io)
186
+ each_entry_element_line do |kd, _ed, line|
187
+ to_io << line unless kd == key_d
188
+ end
189
+ end
190
+
97
191
  def open_append
98
192
  touch_dir
99
193
  File.open filename, 'a', **FILE_ENCODING_OPTS do |io|
@@ -1,4 +1,6 @@
1
1
  # -*- coding: UTF-8 -*-
2
+ # frozen_string_literal: true
3
+
2
4
  require 'fileutils'
3
5
 
4
6
  module CartonDb
@@ -1,4 +1,6 @@
1
1
  # -*- coding: UTF-8 -*-
2
+ # frozen_string_literal: true
3
+
2
4
  require 'forwardable'
3
5
  require 'fileutils'
4
6
  require 'carton_db/list_map_db/segment'
@@ -77,14 +79,7 @@ module CartonDb
77
79
  def [](key)
78
80
  key_d = CartonDb::Datum.for_plain(key)
79
81
  segment = segment_containing(key_d)
80
-
81
- ary = nil
82
- segment.each_entry_element_line do |kd, ed, _line|
83
- next ary unless kd == key_d
84
- ary ||= []
85
- ary << ed.plain unless ed.placeholder?
86
- end
87
- ary
82
+ segment.collect_content(key_d, Array)
88
83
  end
89
84
 
90
85
  # Returns true if an entry with the given key exists.
@@ -97,11 +92,7 @@ module CartonDb
97
92
  def key?(key)
98
93
  key_d = CartonDb::Datum.for_plain(key)
99
94
  segment = segment_containing(key_d)
100
-
101
- segment.each_entry_element_line do |kd, _ed, _line|
102
- return true if kd = key_d
103
- end
104
- false
95
+ segment.key_d?(key_d)
105
96
  end
106
97
 
107
98
  # Returns trus if an entry with the given key exists and its
@@ -116,11 +107,7 @@ module CartonDb
116
107
  key_d = CartonDb::Datum.for_plain(key)
117
108
  element_d = CartonDb::Datum.for_plain(element)
118
109
  segment = segment_containing(key_d)
119
-
120
- segment.each_entry_element_line do |kd, ed, _line|
121
- return true if kd == key_d && ed == element_d
122
- end
123
- false
110
+ segment.element_d?(key_d, element_d)
124
111
  end
125
112
 
126
113
  # Returns true if the map has no entries.
@@ -143,14 +130,8 @@ module CartonDb
143
130
  # @return [Fixnum]
144
131
  def count
145
132
  key_count = 0
146
- file_key_datum_set = Set.new
147
133
  ListMapDb::Segment.each_in_db name do |segment|
148
- next if segment.empty?
149
- file_key_datum_set.clear
150
- segment.each_entry_element_line do |kd, _ed, _line|
151
- file_key_datum_set << kd
152
- end
153
- key_count += file_key_datum_set.length
134
+ key_count += segment.key_count
154
135
  end
155
136
  key_count
156
137
  end
@@ -177,16 +158,7 @@ module CartonDb
177
158
 
178
159
  key_d = CartonDb::Datum.for_plain(key)
179
160
  segment = segment_containing(key_d)
180
-
181
- if optimization == :small && segment.content?
182
- segment.each_entry_element_line do |kd, _ed, _line|
183
- return if kd == key_d
184
- end
185
- end
186
-
187
- segment.open_append do |io|
188
- io << key_d.escaped << "\n"
189
- end
161
+ segment.touch_d key_d, optimization
190
162
  end
191
163
 
192
164
  # Removes all entries from the database, leaving it empty.
@@ -245,16 +217,11 @@ module CartonDb
245
217
  segment = segment_containing(key_d)
246
218
  return if segment.empty?
247
219
 
248
- new_segment = ListMapDb::Segment.new(
249
- segment.segment_group, "#{segment.segment_filename}.new")
250
- new_segment.open_overwrite do |io|
251
- segment.each_entry_element_line do |kd, _ed, line|
252
- io << line unless kd == key_d
220
+ segment.replace do |replacement|
221
+ replacement.open_overwrite do |repl_io|
222
+ segment.copy_entries_except key_d, repl_io
253
223
  end
254
224
  end
255
-
256
- File.unlink segment.filename
257
- File.rename new_segment.filename, segment.filename
258
225
  end
259
226
 
260
227
  # Appends an element string to the content of an entry.
@@ -272,10 +239,7 @@ module CartonDb
272
239
  key_d = CartonDb::Datum.for_plain(key)
273
240
  element_d = CartonDb::Datum.for_plain(element)
274
241
  segment = segment_containing(key_d)
275
- FileUtils.mkpath File.dirname(segment.filename)
276
- segment.open_append do |io|
277
- io << "#{key_d.escaped}\t#{element_d.escaped}\n"
278
- end
242
+ segment.write_key_element_d key_d, element_d
279
243
  end
280
244
 
281
245
  # Appends any number of element strings to the content of an
@@ -313,12 +277,7 @@ module CartonDb
313
277
  def concat_any_elements(key, elements)
314
278
  key_d = CartonDb::Datum.for_plain(key)
315
279
  segment = segment_containing(key_d)
316
- segment.open_append do |io|
317
- elements.each do |element|
318
- element_d = CartonDb::Datum.for_plain(element)
319
- io<< "#{key_d.escaped}\t#{element_d.escaped}\n"
320
- end
321
- end
280
+ segment.write_key_d_elements key_d, elements
322
281
  end
323
282
 
324
283
  # Appends an element to the content of an entry if no
@@ -353,8 +312,7 @@ module CartonDb
353
312
  CartonDb::Datum.for_plain(el)
354
313
  }
355
314
  segment = segment_containing(key_d)
356
- segment.each_entry_element_line do |kd, ed, _line|
357
- next unless kd == key_d
315
+ segment.each_element_for_d key_d do |ed|
358
316
  eds_idx = element_ds.index(ed)
359
317
  element_ds.delete_at(eds_idx) if eds_idx
360
318
  end
@@ -367,24 +325,14 @@ module CartonDb
367
325
  attr_accessor :name
368
326
 
369
327
  def replace_entry_in_file(segment, key_d, content)
370
- new_segment = ListMapDb::Segment.new(
371
- segment.segment_group, "#{segment.segment_filename}.new")
372
- new_segment.open_overwrite do |nf_io|
373
- segment.each_entry_element_line do |kd, _ed, line|
374
- nf_io.print line unless kd == key_d
375
- end
376
- element_count = 0
377
- content.each do |element|
378
- element_d = CartonDb::Datum.for_plain(element)
379
- element_count += 1
380
- nf_io.puts "#{key_d.escaped}\t#{element_d.escaped}"
381
- end
382
- if element_count.zero?
383
- nf_io.puts key_d.escaped
328
+ segment.replace do |replacement|
329
+ replacement.open_overwrite do |repl_io|
330
+ segment.copy_entries_except key_d, repl_io
331
+ element_count = 0
332
+ count = write_key_elements(key_d, content, repl_io)
333
+ repl_io << "#{key_d.escaped}\n" if count.zero?
384
334
  end
385
335
  end
386
- File.unlink segment.filename
387
- File.rename new_segment.filename, segment.filename
388
336
  end
389
337
 
390
338
  def segment_containing(key)
@@ -399,6 +347,16 @@ module CartonDb
399
347
  ! occupied
400
348
  end
401
349
 
350
+ def write_key_elements(key_d, elements, to_io)
351
+ count = 0
352
+ elements.each do |element|
353
+ element_d = CartonDb::Datum.for_plain(element)
354
+ count += 1
355
+ to_io << "#{key_d.escaped}\t#{element_d.escaped}\n"
356
+ end
357
+ count
358
+ end
359
+
402
360
  end
403
361
 
404
362
  end
@@ -1,3 +1,6 @@
1
+ # -*- coding: UTF-8 -*-
2
+ # frozen_string_literal: true
3
+
1
4
  require 'set'
2
5
  require 'forwardable'
3
6
 
@@ -1,3 +1,6 @@
1
+ # -*- coding: UTF-8 -*-
2
+ # frozen_string_literal: true
3
+
1
4
  require 'forwardable'
2
5
 
3
6
  module CartonDb
@@ -1,4 +1,6 @@
1
1
  # -*- coding: UTF-8 -*-
2
+ # frozen_string_literal: true
3
+
2
4
  module CartonDb
3
- VERSION = "1.1.2"
5
+ VERSION = "1.1.3"
4
6
  end
data/lib/carton_db.rb CHANGED
@@ -1,4 +1,6 @@
1
1
  # -*- coding: UTF-8 -*-
2
+ # frozen_string_literal: true
3
+
2
4
  require "carton_db/version"
3
5
  require "carton_db/escaping"
4
6
  require "carton_db/datum"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: carton_db
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.2
4
+ version: 1.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Steve Jorgensen
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-05-08 00:00:00.000000000 Z
11
+ date: 2017-05-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler