redis-diff_match_patch 1.0.0

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.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in redis-diff_match_patch.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2012 Alex McHale (alex@anticlever.com)
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,75 @@
1
+ Redis: Diff Match Patch
2
+ =======================
3
+
4
+ ## DESCRIPTION
5
+
6
+ Redis: Diff Match Patch is a library for using [Google's diff-match-patch][1]
7
+ on a Redis server.
8
+
9
+ This library uses the Lua port included with diff-match-patch to atomically
10
+ calculate and apply patches of string values stored in Redis.
11
+
12
+ ## PREREQUISITES
13
+
14
+ This library requires a Redis server with Lua scripting support (EVAL and
15
+ EVALSHA commands). This support was added in Redis 2.6.
16
+
17
+ ## INSTALLATION
18
+
19
+ ### To install manually from RubyGems:
20
+
21
+ gem install redis-diff_match_patch
22
+
23
+ ### To use in a project with Bundler, edit your Gemfile to include:
24
+
25
+ gem 'redis-diff_match_patch'
26
+
27
+ ## API
28
+
29
+ dmp = Redis::DiffMatchPatch.new(REDIS_CLIENT)
30
+
31
+ # Calculate a diff of two keys
32
+ dmp.diff ORIGINAL_KEY, CURRENT_KEY, DIFF_OUTPUT_KEY
33
+
34
+ # Patch a key
35
+ dmp.patch ORIGINAL_KEY, DIFF_KEY, RESULT_OUTPUT_KEY
36
+
37
+ # Perform a 3-way merge
38
+ dmp.merge ANCESTOR_KEY, KEY1, KEY2, RESULT_OUTPUT_KEY
39
+
40
+ The output keys are optional. All API methods will return the result value.
41
+
42
+ ## EXAMPLES
43
+
44
+ ### Calculate the diff of an original document and a current version of that document.
45
+
46
+ redis = Redis.new
47
+ dmp = Redis::DiffMatchPatch.new redis
48
+
49
+ redis["original"] = "hello world"
50
+ redis["doc"] = "Hello, world!"
51
+
52
+ dmp.diff "original", "doc", "diff"
53
+
54
+ redis["diff"] #=> "@@ -1,11 +1,13 @@\n-h\n+H\n ello\n+,\n world\n+!\n"
55
+
56
+ ### Perform a 3-way merge on two documents that are variations from an original source.
57
+
58
+ redis = Redis.new
59
+ dmp = Redis::DiffMatchPatch.new redis
60
+
61
+ redis["original"] = "hello world"
62
+ redis["doc1"] = "Howdy, world!"
63
+ redis["doc2"] = "hello my friends"
64
+
65
+ dmp.merge "original", "doc1", "doc2", "result"
66
+
67
+ redis["result"] #=> "Howdy, my friends!"
68
+
69
+ ## REFERENCES
70
+
71
+ * [Google's diff-match-patch][1] provides the meat of the functionality in this library.
72
+ * [Dialectronics BinDecHex][2] for providing functions to enable diff-match-patch on Redis.
73
+
74
+ [1]: http://code.google.com/p/google-diff-match-patch/
75
+ [2]: http://www.dialectronics.com/Lua/
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ task :default => :test
5
+
6
+ Rake::TestTask.new(:test) do |t|
7
+ t.libs << 'lib'
8
+ t.libs << 'test'
9
+ t.pattern = 'test/*_test.rb'
10
+ t.verbose = true
11
+ end
@@ -0,0 +1,542 @@
1
+ --[[
2
+ /*
3
+ * Copyright (c) 2007 Tim Kelly/Dialectronics
4
+ *
5
+ * Permission is hereby granted, free of charge, to any person obtaining
6
+ * a copy of this software and associated documentation files (the
7
+ * "Software"), to deal in the Software without restriction, including
8
+ * without limitation the rights to use, copy, modify, merge, publish,
9
+ * distribute, sublicense, and/or sell copies of the Software, and to permit
10
+ * persons to whom the Software is furnished to do so, subject to the
11
+ * following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice shall be
14
+ * included in all copies or substantial portions of the Software.
15
+ *
16
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
21
+ * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
22
+ * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+ */
24
+
25
+ --]]
26
+
27
+ --[[
28
+ /*
29
+ * Copyright (c) 2007 Tim Kelly/Dialectronics
30
+ *
31
+ * Permission is hereby granted, free of charge, to any person obtaining
32
+ * a copy of this software and associated documentation files (the
33
+ * "Software"), to deal in the Software without restriction, including
34
+ * without limitation the rights to use, copy, modify, merge, publish,
35
+ * distribute, sublicense, and/or sell copies of the Software, and to permit
36
+ * persons to whom the Software is furnished to do so, subject to the
37
+ * following conditions:
38
+ *
39
+ * The above copyright notice and this permission notice shall be
40
+ * included in all copies or substantial portions of the Software.
41
+ *
42
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
43
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
44
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
45
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
46
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
47
+ * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
48
+ * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
49
+ */
50
+
51
+ --]]
52
+
53
+ module(..., package.seeall);
54
+
55
+ local hex2bin = {
56
+ ["0"] = "0000",
57
+ ["1"] = "0001",
58
+ ["2"] = "0010",
59
+ ["3"] = "0011",
60
+ ["4"] = "0100",
61
+ ["5"] = "0101",
62
+ ["6"] = "0110",
63
+ ["7"] = "0111",
64
+ ["8"] = "1000",
65
+ ["9"] = "1001",
66
+ ["a"] = "1010",
67
+ ["b"] = "1011",
68
+ ["c"] = "1100",
69
+ ["d"] = "1101",
70
+ ["e"] = "1110",
71
+ ["f"] = "1111"
72
+ }
73
+
74
+
75
+
76
+ local bin2hex = {
77
+ ["0000"] = "0",
78
+ ["0001"] = "1",
79
+ ["0010"] = "2",
80
+ ["0011"] = "3",
81
+ ["0100"] = "4",
82
+ ["0101"] = "5",
83
+ ["0110"] = "6",
84
+ ["0111"] = "7",
85
+ ["1000"] = "8",
86
+ ["1001"] = "9",
87
+ ["1010"] = "A",
88
+ ["1011"] = "B",
89
+ ["1100"] = "C",
90
+ ["1101"] = "D",
91
+ ["1110"] = "E",
92
+ ["1111"] = "F"
93
+ }
94
+
95
+ --[[
96
+ local dec2hex = {
97
+ ["0"] = "0",
98
+ ["1"] = "1",
99
+ ["2"] = "2",
100
+ ["3"] = "3",
101
+ ["4"] = "4",
102
+ ["5"] = "5",
103
+ ["6"] = "6",
104
+ ["7"] = "7",
105
+ ["8"] = "8",
106
+ ["9"] = "9",
107
+ ["10"] = "A",
108
+ ["11"] = "B",
109
+ ["12"] = "C",
110
+ ["13"] = "D",
111
+ ["14"] = "E",
112
+ ["15"] = "F"
113
+ }
114
+ --]]
115
+
116
+
117
+ -- These functions are big-endian and take up to 32 bits
118
+
119
+ -- Hex2Bin
120
+ -- Bin2Hex
121
+ -- Hex2Dec
122
+ -- Dec2Hex
123
+ -- Bin2Dec
124
+ -- Dec2Bin
125
+
126
+
127
+ function Hex2Bin(s)
128
+
129
+ -- s -> hexadecimal string
130
+
131
+ local ret = ""
132
+ local i = 0
133
+
134
+
135
+ for i in string.gfind(s, ".") do
136
+ i = string.lower(i)
137
+
138
+ ret = ret..hex2bin[i]
139
+
140
+ end
141
+
142
+ return ret
143
+ end
144
+
145
+
146
+ function Bin2Hex(s)
147
+
148
+ -- s -> binary string
149
+
150
+ local l = 0
151
+ local h = ""
152
+ local b = ""
153
+ local rem
154
+
155
+ l = string.len(s)
156
+ rem = l % 4
157
+ l = l-1
158
+ h = ""
159
+
160
+ -- need to prepend zeros to eliminate mod 4
161
+ if (rem > 0) then
162
+ s = string.rep("0", 4 - rem)..s
163
+ end
164
+
165
+ for i = 1, l, 4 do
166
+ b = string.sub(s, i, i+3)
167
+ h = h..bin2hex[b]
168
+ end
169
+
170
+ return h
171
+
172
+ end
173
+
174
+
175
+ function Bin2Dec(s)
176
+
177
+ -- s -> binary string
178
+
179
+ local num = 0
180
+ local ex = string.len(s) - 1
181
+ local l = 0
182
+
183
+ l = ex + 1
184
+ for i = 1, l do
185
+ b = string.sub(s, i, i)
186
+ if b == "1" then
187
+ num = num + 2^ex
188
+ end
189
+ ex = ex - 1
190
+ end
191
+
192
+ return string.format("%u", num)
193
+
194
+ end
195
+
196
+
197
+
198
+ function Dec2Bin(s, num)
199
+
200
+ -- s -> Base10 string
201
+ -- num -> string length to extend to
202
+
203
+ local n
204
+
205
+ if (num == nil) then
206
+ n = 0
207
+ else
208
+ n = num
209
+ end
210
+
211
+ s = string.format("%x", s)
212
+
213
+ s = Hex2Bin(s)
214
+
215
+ while string.len(s) < n do
216
+ s = "0"..s
217
+ end
218
+
219
+ return s
220
+
221
+ end
222
+
223
+
224
+
225
+
226
+ function Hex2Dec(s)
227
+
228
+ -- s -> hexadecimal string
229
+
230
+ local s = Hex2Bin(s)
231
+
232
+ return Bin2Dec(s)
233
+
234
+ end
235
+
236
+
237
+
238
+ function Dec2Hex(s)
239
+
240
+ -- s -> Base10 string
241
+
242
+ s = string.format("%x", s)
243
+
244
+ return s
245
+
246
+ end
247
+
248
+
249
+
250
+
251
+ -- These functions are big-endian and will extend to 32 bits
252
+
253
+ -- BMAnd
254
+ -- BMNAnd
255
+ -- BMOr
256
+ -- BMXOr
257
+ -- BMNot
258
+
259
+
260
+ function BMAnd(v, m)
261
+
262
+ -- v -> hex string to be masked
263
+ -- m -> hex string mask
264
+
265
+ -- s -> hex string as masked
266
+
267
+ -- bv -> binary string of v
268
+ -- bm -> binary string mask
269
+
270
+ local bv = Hex2Bin(v)
271
+ local bm = Hex2Bin(m)
272
+
273
+ local i = 0
274
+ local s = ""
275
+
276
+ while (string.len(bv) < 32) do
277
+ bv = "0000"..bv
278
+ end
279
+
280
+ while (string.len(bm) < 32) do
281
+ bm = "0000"..bm
282
+ end
283
+
284
+
285
+ for i = 1, 32 do
286
+ cv = string.sub(bv, i, i)
287
+ cm = string.sub(bm, i, i)
288
+ if cv == cm then
289
+ if cv == "1" then
290
+ s = s.."1"
291
+ else
292
+ s = s.."0"
293
+ end
294
+ else
295
+ s = s.."0"
296
+
297
+ end
298
+ end
299
+
300
+ return Bin2Hex(s)
301
+
302
+ end
303
+
304
+
305
+ function BMNAnd(v, m)
306
+
307
+ -- v -> hex string to be masked
308
+ -- m -> hex string mask
309
+
310
+ -- s -> hex string as masked
311
+
312
+ -- bv -> binary string of v
313
+ -- bm -> binary string mask
314
+
315
+ local bv = Hex2Bin(v)
316
+ local bm = Hex2Bin(m)
317
+
318
+ local i = 0
319
+ local s = ""
320
+
321
+ while (string.len(bv) < 32) do
322
+ bv = "0000"..bv
323
+ end
324
+
325
+ while (string.len(bm) < 32) do
326
+ bm = "0000"..bm
327
+ end
328
+
329
+
330
+ for i = 1, 32 do
331
+ cv = string.sub(bv, i, i)
332
+ cm = string.sub(bm, i, i)
333
+ if cv == cm then
334
+ if cv == "1" then
335
+ s = s.."0"
336
+ else
337
+ s = s.."1"
338
+ end
339
+ else
340
+ s = s.."1"
341
+
342
+ end
343
+ end
344
+
345
+ return Bin2Hex(s)
346
+
347
+ end
348
+
349
+
350
+
351
+ function BMOr(v, m)
352
+
353
+ -- v -> hex string to be masked
354
+ -- m -> hex string mask
355
+
356
+ -- s -> hex string as masked
357
+
358
+ -- bv -> binary string of v
359
+ -- bm -> binary string mask
360
+
361
+ local bv = Hex2Bin(v)
362
+ local bm = Hex2Bin(m)
363
+
364
+ local i = 0
365
+ local s = ""
366
+
367
+ while (string.len(bv) < 32) do
368
+ bv = "0000"..bv
369
+ end
370
+
371
+ while (string.len(bm) < 32) do
372
+ bm = "0000"..bm
373
+ end
374
+
375
+
376
+ for i = 1, 32 do
377
+ cv = string.sub(bv, i, i)
378
+ cm = string.sub(bm, i, i)
379
+ if cv == "1" then
380
+ s = s.."1"
381
+ elseif cm == "1" then
382
+ s = s.."1"
383
+ else
384
+ s = s.."0"
385
+ end
386
+ end
387
+
388
+ return Bin2Hex(s)
389
+
390
+ end
391
+
392
+ function BMXOr(v, m)
393
+
394
+ -- v -> hex string to be masked
395
+ -- m -> hex string mask
396
+
397
+ -- s -> hex string as masked
398
+
399
+ -- bv -> binary string of v
400
+ -- bm -> binary string mask
401
+
402
+ local bv = Hex2Bin(v)
403
+ local bm = Hex2Bin(m)
404
+
405
+ local i = 0
406
+ local s = ""
407
+
408
+ while (string.len(bv) < 32) do
409
+ bv = "0000"..bv
410
+ end
411
+
412
+ while (string.len(bm) < 32) do
413
+ bm = "0000"..bm
414
+ end
415
+
416
+
417
+ for i = 1, 32 do
418
+ cv = string.sub(bv, i, i)
419
+ cm = string.sub(bm, i, i)
420
+ if cv == "1" then
421
+ if cm == "0" then
422
+ s = s.."1"
423
+ else
424
+ s = s.."0"
425
+ end
426
+ elseif cm == "1" then
427
+ if cv == "0" then
428
+ s = s.."1"
429
+ else
430
+ s = s.."0"
431
+ end
432
+ else
433
+ -- cv and cm == "0"
434
+ s = s.."0"
435
+ end
436
+ end
437
+
438
+ return Bin2Hex(s)
439
+
440
+ end
441
+
442
+
443
+ function BMNot(v, m)
444
+
445
+ -- v -> hex string to be masked
446
+ -- m -> hex string mask
447
+
448
+ -- s -> hex string as masked
449
+
450
+ -- bv -> binary string of v
451
+ -- bm -> binary string mask
452
+
453
+ local bv = Hex2Bin(v)
454
+ local bm = Hex2Bin(m)
455
+
456
+ local i = 0
457
+ local s = ""
458
+
459
+ while (string.len(bv) < 32) do
460
+ bv = "0000"..bv
461
+ end
462
+
463
+ while (string.len(bm) < 32) do
464
+ bm = "0000"..bm
465
+ end
466
+
467
+
468
+ for i = 1, 32 do
469
+ cv = string.sub(bv, i, i)
470
+ cm = string.sub(bm, i, i)
471
+ if cm == "1" then
472
+ if cv == "1" then
473
+ -- turn off
474
+ s = s.."0"
475
+ else
476
+ -- turn on
477
+ s = s.."1"
478
+ end
479
+ else
480
+ -- leave untouched
481
+ s = s..cv
482
+
483
+ end
484
+ end
485
+
486
+ return Bin2Hex(s)
487
+
488
+ end
489
+
490
+
491
+ -- these functions shift right and left, adding zeros to lost or gained bits
492
+ -- returned values are 32 bits long
493
+
494
+ -- BShRight(v, nb)
495
+ -- BShLeft(v, nb)
496
+
497
+
498
+ function BShRight(v, nb)
499
+
500
+ -- v -> hexstring value to be shifted
501
+ -- nb -> number of bits to shift to the right
502
+
503
+ -- s -> binary string of v
504
+
505
+ local s = Hex2Bin(v)
506
+
507
+ while (string.len(s) < 32) do
508
+ s = "0000"..s
509
+ end
510
+
511
+ s = string.sub(s, 1, 32 - nb)
512
+
513
+ while (string.len(s) < 32) do
514
+ s = "0"..s
515
+ end
516
+
517
+ return Bin2Hex(s)
518
+
519
+ end
520
+
521
+ function BShLeft(v, nb)
522
+
523
+ -- v -> hexstring value to be shifted
524
+ -- nb -> number of bits to shift to the right
525
+
526
+ -- s -> binary string of v
527
+
528
+ local s = Hex2Bin(v)
529
+
530
+ while (string.len(s) < 32) do
531
+ s = "0000"..s
532
+ end
533
+
534
+ s = string.sub(s, nb + 1, 32)
535
+
536
+ while (string.len(s) < 32) do
537
+ s = s.."0"
538
+ end
539
+
540
+ return Bin2Hex(s)
541
+
542
+ end