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 +4 -4
- data/lib/carton_db/datum.rb +14 -8
- data/lib/carton_db/escaping.rb +37 -34
- data/lib/carton_db/list_map_db/segment.rb +94 -0
- data/lib/carton_db/list_map_db/segment_group.rb +2 -0
- data/lib/carton_db/list_map_db.rb +29 -71
- data/lib/carton_db/set_map_db.rb +3 -0
- data/lib/carton_db/simple_map_db.rb +3 -0
- data/lib/carton_db/version.rb +3 -1
- data/lib/carton_db.rb +2 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b0569eb04a7231087ac8ba262cc56330a1c61912
|
4
|
+
data.tar.gz: aaae82f45cfdeb14e4dea5110e9a09c3b062ab5e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e07e734b21b74e9988654549060f615897fb9b5e57763a61d392bf58ef0ff46845ba43118c805766f9177a117d0c4f7d49d1fa52e13e8e2042f410dd385b18a3
|
7
|
+
data.tar.gz: 5c818326762c092a868e9abc642ce1baa3a1b9a2fbe38a17c7932f0ebbbde99a1e0a8d72cd7479a98e61a5c97cc1516968f92e9c655cb0e1758333f02a778b2d
|
data/lib/carton_db/datum.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
data/lib/carton_db/escaping.rb
CHANGED
@@ -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"
|
7
|
-
"\u0001"
|
8
|
-
"\u0002"
|
9
|
-
"\u0003"
|
10
|
-
"\u0004"
|
11
|
-
"\u0005"
|
12
|
-
"\u0006"
|
13
|
-
"\u0007"
|
14
|
-
"\u0008"
|
15
|
-
"\u0009"
|
16
|
-
"\u000A"
|
17
|
-
"\u000B"
|
18
|
-
"\u000C"
|
19
|
-
"\u000D"
|
20
|
-
"\u000E"
|
21
|
-
"\u000F"
|
22
|
-
"\u0010"
|
23
|
-
"\u0011"
|
24
|
-
"\u0012"
|
25
|
-
"\u0013"
|
26
|
-
"\u0014"
|
27
|
-
"\u0015"
|
28
|
-
"\u0016"
|
29
|
-
"\u0017"
|
30
|
-
"\u0018"
|
31
|
-
"\u0019"
|
32
|
-
"\u001A"
|
33
|
-
"\u001B"
|
34
|
-
"\u001C"
|
35
|
-
"\u001D"
|
36
|
-
"\u001E"
|
37
|
-
"\u001F"
|
38
|
-
"\u007F"
|
39
|
-
"\\"
|
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 '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
|
-
|
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
|
-
|
249
|
-
|
250
|
-
|
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
|
-
|
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.
|
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.
|
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
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
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
|
data/lib/carton_db/set_map_db.rb
CHANGED
data/lib/carton_db/version.rb
CHANGED
data/lib/carton_db.rb
CHANGED
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.
|
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-
|
11
|
+
date: 2017-05-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|