diff_match_patch_native 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gemtest ADDED
File without changes
data/History.txt ADDED
@@ -0,0 +1,6 @@
1
+ === 1.0.0 / 2011-10-19
2
+
3
+ * 1 major enhancement
4
+
5
+ * Birthday!
6
+
data/Manifest.txt ADDED
@@ -0,0 +1,12 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.rdoc
4
+ Rakefile
5
+ ext/diff_match_patch/_dmp.cpp
6
+ ext/diff_match_patch/_dmp.h
7
+ ext/diff_match_patch/diff_match_patch.cpp
8
+ ext/diff_match_patch/extconf.rb
9
+ lib/diff_match_patch.rb
10
+ lib/diff_match_patch/diff_match_patch.bundle
11
+ src/include/diff_match_patch-stl/diff_match_patch.h
12
+ test/test_diff_patch_match.rb
data/README.rdoc ADDED
@@ -0,0 +1,73 @@
1
+ = diff_patch_match_native
2
+
3
+ https://github.com/elliotlaster/Ruby-Diff-Match-Patch
4
+
5
+ Ruby bindings for the C++ version of google-diff-match-patch:
6
+ http://code.google.com/p/google-diff-match-patch/
7
+
8
+ == DESCRIPTION:
9
+
10
+ The Diff Match and Patch libraries offer robust algorithms to perform the operations required for synchronizing plain text.
11
+
12
+ == SYNOPSIS:
13
+
14
+ The API conforms to the standard at http://code.google.com/p/google-diff-match-patch/wiki/API
15
+
16
+ dmp = DiffMatchPatch.new
17
+
18
+ # Diff-ing
19
+ dmp.diff_main("Apples are a fruit.", "Bananas are also fruit.", false)
20
+ => [[-1, "Apple"], [1, "Banana"], [0, "s are a"], [1, "lso"], [0, " fruit."]]
21
+
22
+ # Match-ing (return the index of the first match)
23
+ dmp.match_main("abcdef", "de", 3)
24
+ => 3
25
+
26
+ # Patch-ing
27
+ text_1 = "The quick brown fox jumps over the lazy dog."
28
+ text_2 = "That quick brown fox jumped over a lazy dog."
29
+
30
+ patches = dmp.patch_make(text_2, text_1)
31
+
32
+ dmp.patch_to_text(patches)
33
+ => "@@ -1,8 +1,7 @@\n Th\n-at\n+e\n qui\n@@ -21,17 +21,18 @@\n jump\n-ed\n+s\n over \n-a\n+the\n laz\n"
34
+
35
+ dmp.patch_apply(patches, text_2)
36
+ => ["The quick brown fox jumps over the lazy dog.", [true, true]]
37
+
38
+ == REQUIREMENTS:
39
+
40
+ * Rake
41
+ * Rice >= 1.4.2
42
+
43
+ == INSTALL:
44
+
45
+ gem install diff-match-patch
46
+
47
+ == LICENSE:
48
+
49
+
50
+ diff_match_patch-stl.h is Copyright 2008 Google Inc, and licensed under
51
+ the Apache license. See
52
+ src/include/diff_match_patch-stl/diff_match_patch.h
53
+
54
+ Copyright (c) 2011 Elliot Laster
55
+
56
+ Permission is hereby granted, free of charge, to any person obtaining
57
+ a copy of this software and associated documentation files (the
58
+ 'Software'), to deal in the Software without restriction, including
59
+ without limitation the rights to use, copy, modify, merge, publish,
60
+ distribute, sublicense, and/or sell copies of the Software, and to
61
+ permit persons to whom the Software is furnished to do so, subject to
62
+ the following conditions:
63
+
64
+ The above copyright notice and this permission notice shall be
65
+ included in all copies or substantial portions of the Software.
66
+
67
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
68
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
69
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
70
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
71
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
72
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
73
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,28 @@
1
+ # -*- ruby -*-
2
+ require 'rubygems'
3
+ begin
4
+ require 'rake/dsl_definition'
5
+ rescue LoadError
6
+ nil
7
+ end
8
+ require 'hoe'
9
+ require 'rake/extensiontask'
10
+
11
+ Hoe.plugin :bundler, :rubygems, :doofus, :git
12
+
13
+ Hoe.spec 'diff_match_patch_native' do
14
+ developer('Elliot Laster', 'elliotlaster@gmail.com')
15
+ self.version = '1.0.0'
16
+ self.readme_file = 'README.rdoc'
17
+ self.history_file = 'History.txt'
18
+ self.extra_deps << ['rice', '>= 1.4.2']
19
+ self.extra_dev_deps << ['rake-compiler', '>= 0']
20
+
21
+ self.spec_extras = { :extensions => ["ext/diff_match_patch/extconf.rb"] }
22
+
23
+ Rake::ExtensionTask.new('diff_match_patch', spec) do |ext|
24
+ ext.lib_dir = File.join('lib', 'diff_match_patch')
25
+ end
26
+ end
27
+
28
+ Rake::Task[:test].prerequisites << :compile
@@ -0,0 +1,287 @@
1
+ #include "_dmp.h"
2
+
3
+ #define dmp diff_match_patch<std::string>
4
+
5
+
6
+ /*
7
+ * A lightweight wrapper around Patch, so Rice can get at it. Delegates
8
+ * to the patch as necissary
9
+ */
10
+ class rb_patch_wrapper{
11
+
12
+ public:
13
+
14
+ dmp::Patch patch;
15
+
16
+ rb_patch_wrapper(dmp::Patch &the_patch) : patch(the_patch) {}
17
+
18
+ int start1(){
19
+ return patch.start1;
20
+ }
21
+
22
+ int start2(){
23
+ return patch.start2;
24
+ }
25
+
26
+ int length1(){
27
+ return patch.length1;
28
+ }
29
+
30
+ int length2(){
31
+ return patch.length2;
32
+ }
33
+
34
+ std::string toString(){
35
+ return patch.toString();
36
+ }
37
+
38
+ bool isNull(){
39
+ return patch.isNull();
40
+ }
41
+
42
+ };
43
+
44
+
45
+ /*
46
+ * A subclass of diff_match_patch<std::string>, adding methods for
47
+ * translating between C++ and Ruby.
48
+ */
49
+ class rb_diff_match_patch : dmp {
50
+
51
+ protected:
52
+
53
+ Diffs diffsFromRubyArray(Rice::Array &array, bool clearArray=false){
54
+ Diffs diffs;
55
+ size_t arraySize = array.size();
56
+ for (size_t i = 0; i < arraySize; ++i){
57
+ Rice::Array rb_diff;
58
+ if (clearArray) {
59
+ rb_diff = from_ruby<Rice::Array>(array.shift());
60
+ } else {
61
+ rb_diff = from_ruby<Rice::Array>(array[i]);
62
+ }
63
+
64
+ Operation op;
65
+ switch (from_ruby<int>(rb_diff[0])) {
66
+ case 1:
67
+ op = INSERT;
68
+ break;
69
+ case 0:
70
+ op = EQUAL;
71
+ break;
72
+ case -1:
73
+ op = DELETE;
74
+ break;
75
+ }
76
+ diffs.push_back(dmp::Diff(op, from_ruby<std::string>(rb_diff[1])));
77
+
78
+ }
79
+ return diffs;
80
+ }
81
+
82
+ Rice::Array rubyArrayFromDiffsWithArray(dmp::Diffs diffs, Rice::Array &out){
83
+ Diffs::iterator current_diff;
84
+ for (current_diff = diffs.begin(); current_diff != diffs.end(); ++current_diff) {
85
+ Rice::Array rb_diff;
86
+ switch (current_diff->operation){
87
+ case INSERT:
88
+ rb_diff.push(1);
89
+ break;
90
+ case DELETE:
91
+ rb_diff.push(-1);
92
+ break;
93
+ case EQUAL:
94
+ rb_diff.push(0);
95
+ break;
96
+ }
97
+ rb_diff.push(current_diff->text);
98
+ out.push(rb_diff);
99
+ }
100
+
101
+ return out;
102
+ }
103
+
104
+ Rice::Array rubyArrayFromDiffs(const dmp::Diffs &diffs){
105
+ Rice::Array out;
106
+ return rubyArrayFromDiffsWithArray(diffs, out);
107
+ }
108
+
109
+ Rice::Array rubyArrayFromPatches(Patches &patches){
110
+ Rice::Array out;
111
+ Patches::iterator current_patch = patches.begin();
112
+ for (current_patch = patches.begin(); current_patch != patches.end(); ++current_patch){
113
+ rb_patch_wrapper patch = rb_patch_wrapper(*current_patch);
114
+ out.push(patch);
115
+ }
116
+ return out;
117
+ }
118
+
119
+ Patches patchesFromRubyArray(Rice::Array &array){
120
+ Patches patches;
121
+ for (size_t i = 0; i < array.size(); ++i) {
122
+ rb_patch_wrapper wrapper = from_ruby<rb_patch_wrapper>(array[i]);
123
+ patches.push_back(wrapper.patch);
124
+ }
125
+ return patches;
126
+ }
127
+
128
+ public:
129
+
130
+ rb_diff_match_patch(){}
131
+
132
+ Rice::Object rb_diff_main(const std::string &text1, const std::string &text2, bool checklines=false){
133
+ Diffs diffs = diff_main(text1, text2, checklines);
134
+ return rubyArrayFromDiffs(diffs);
135
+ }
136
+
137
+ float GetDiff_Timeout(){
138
+ return Diff_Timeout;
139
+ }
140
+
141
+ void SetDiff_Timeout(float value){
142
+ Diff_Timeout = value;
143
+ }
144
+
145
+ float GetDiff_EditCost(){
146
+ return Diff_EditCost;
147
+ }
148
+
149
+ void SetDiff_EditCost(float value){
150
+ Diff_EditCost = value;
151
+ }
152
+
153
+ Rice::Array rb_diff_cleanupSemantic(Rice::Array array){
154
+ Diffs diffs = diffsFromRubyArray(array, true);
155
+ diff_cleanupSemantic(diffs);
156
+ return rubyArrayFromDiffsWithArray(diffs, array);
157
+ }
158
+
159
+ Rice::Array rb_diff_cleanupEfficiency(Rice::Array array){
160
+ Diffs diffs = diffsFromRubyArray(array, true);
161
+ diff_cleanupEfficiency(diffs);
162
+ return rubyArrayFromDiffsWithArray(diffs, array);
163
+ }
164
+
165
+ int rb_diff_levenshtein(Rice::Array array){
166
+ Diffs diffs = diffsFromRubyArray(array);
167
+ return diff_levenshtein(diffs);
168
+ }
169
+
170
+ std::string rb_diff_prettyHtml(Rice::Array array){
171
+ Diffs diffs = diffsFromRubyArray(array);
172
+ return diff_prettyHtml(diffs);
173
+ }
174
+
175
+ int rb_match_main(const string_t &text, const string_t &pattern, int loc) const {
176
+ return match_main(text, pattern, loc);
177
+ }
178
+
179
+ float GetMatch_Threshold(){
180
+ return Match_Threshold;
181
+ }
182
+
183
+ void SetMatch_Threshold(float value){
184
+ Match_Threshold = value;
185
+ }
186
+
187
+ int GetMatch_Distance(){
188
+ return Match_Distance;
189
+ }
190
+
191
+ void SetMatch_Distance(int value){
192
+ Match_Distance = value;
193
+ }
194
+
195
+ float GetPatch_DeleteThreshold(){
196
+ return Patch_DeleteThreshold;
197
+ }
198
+
199
+ void SetPatch_DeleteThreshold(float value){
200
+ Patch_DeleteThreshold = value;
201
+ }
202
+
203
+ Rice::Array rb_patch_fromText(const std::string &str){
204
+ Patches patches = patch_fromText(str);
205
+ return rubyArrayFromPatches(patches);
206
+ }
207
+
208
+ std::string rb_patch_toText(Rice::Array array){
209
+ Patches patches = patchesFromRubyArray(array);
210
+ return patch_toText(patches);
211
+ }
212
+
213
+ Rice::Array rb_patch_make_from_texts(std::string text1, std::string text2){
214
+ Patches patches = patch_make(text1, text2);
215
+ return rubyArrayFromPatches(patches);
216
+ }
217
+
218
+ Rice::Array rb_patch_make_from_diffs(Rice::Array array){
219
+ Diffs diffs = diffsFromRubyArray(array);
220
+ Patches patches = patch_make(diffs);
221
+ return rubyArrayFromPatches(patches);
222
+ }
223
+
224
+ Rice::Array rb_patch_make_from_text_and_diff(std::string text1, Rice::Array array){
225
+ Diffs diffs = diffsFromRubyArray(array);
226
+ Patches patches = patch_make(text1, diffs);
227
+ return rubyArrayFromPatches(patches);
228
+ }
229
+
230
+ Rice::Array rb_patch_apply(Rice::Array patch_array, std::string text_1){
231
+ Patches patches = patchesFromRubyArray(patch_array);
232
+ std::pair<std::string, std::vector<bool> > results = patch_apply(patches,text_1);
233
+ Rice::Array out;
234
+ out.push(results.first);
235
+
236
+ Rice::Array bool_array;
237
+ for (size_t i = 0; i < results.second.size(); ++i){
238
+ bool_array.push(results.second[i] ? true : false);
239
+ }
240
+ out.push(bool_array);
241
+
242
+ return out;
243
+ }
244
+
245
+ };
246
+
247
+ void register_dmp(){
248
+
249
+ Rice::Data_Type< rb_diff_match_patch > rb_cDMP = Rice::define_class< rb_diff_match_patch >("DiffMatchPatch");
250
+ rb_cDMP.define_constructor(Rice::Constructor<rb_diff_match_patch>());
251
+
252
+ rb_cDMP.define_method("diff_main", &rb_diff_match_patch::rb_diff_main);
253
+ rb_cDMP.define_method("diff_timeout", &rb_diff_match_patch::GetDiff_Timeout);
254
+ rb_cDMP.define_method("diff_timeout=", &rb_diff_match_patch::SetDiff_Timeout);
255
+ rb_cDMP.define_method("diff_edit_cost", &rb_diff_match_patch::GetDiff_EditCost);
256
+ rb_cDMP.define_method("diff_edit_cost=", &rb_diff_match_patch::SetDiff_EditCost);
257
+ rb_cDMP.define_method("diff_cleanup_semantic!", &rb_diff_match_patch::rb_diff_cleanupSemantic);
258
+ rb_cDMP.define_method("diff_cleanup_efficiency!", &rb_diff_match_patch::rb_diff_cleanupEfficiency);
259
+ rb_cDMP.define_method("diff_levenshtein", &rb_diff_match_patch::rb_diff_levenshtein);
260
+ rb_cDMP.define_method("diff_pretty_html", &rb_diff_match_patch::rb_diff_prettyHtml);
261
+
262
+ rb_cDMP.define_method("match_main", &rb_diff_match_patch::rb_match_main);
263
+ rb_cDMP.define_method("match_threshold", &rb_diff_match_patch::GetMatch_Threshold);
264
+ rb_cDMP.define_method("match_threshold=", &rb_diff_match_patch::SetMatch_Threshold);
265
+ rb_cDMP.define_method("match_distance", &rb_diff_match_patch::GetMatch_Distance);
266
+ rb_cDMP.define_method("match_distance=", &rb_diff_match_patch::SetMatch_Distance);
267
+
268
+ rb_cDMP.define_method("patch_delete_threshold", &rb_diff_match_patch::GetPatch_DeleteThreshold);
269
+ rb_cDMP.define_method("patch_delete_threshold=", &rb_diff_match_patch::SetPatch_DeleteThreshold);
270
+ rb_cDMP.define_method("patch_from_text", &rb_diff_match_patch::rb_patch_fromText);
271
+ rb_cDMP.define_method("patch_to_text", &rb_diff_match_patch::rb_patch_toText);
272
+ rb_cDMP.define_method("__patch_make_from_texts__", &rb_diff_match_patch::rb_patch_make_from_texts);
273
+ rb_cDMP.define_method("__patch_make_from_diffs__", &rb_diff_match_patch::rb_patch_make_from_diffs);
274
+ rb_cDMP.define_method("__patch_make_from_text_and_diff__", &rb_diff_match_patch::rb_patch_make_from_text_and_diff);
275
+ rb_cDMP.define_method("patch_apply", &rb_diff_match_patch::rb_patch_apply);
276
+
277
+ Rice::Data_Type< rb_patch_wrapper > rb_cPatch = Rice::define_class< rb_patch_wrapper >("Patch");
278
+ rb_cPatch.define_method("to_string", &rb_patch_wrapper::toString);
279
+ rb_cPatch.define_method("is_null?", &rb_patch_wrapper::isNull);
280
+ rb_cPatch.define_method("start_1", &rb_patch_wrapper::start1);
281
+ rb_cPatch.define_method("start_2", &rb_patch_wrapper::start2);
282
+ rb_cPatch.define_method("length_1", &rb_patch_wrapper::length1);
283
+ rb_cPatch.define_method("length_2", &rb_patch_wrapper::length2);
284
+
285
+ }
286
+
287
+ #undef dmp
@@ -0,0 +1,16 @@
1
+ #ifndef ruby_DMP_HPP
2
+ #define ruby_DMP_HPP
3
+
4
+ #include <rice/Object.hpp>
5
+ #include <rice/Data_Type.hpp>
6
+ #include <rice/Array.hpp>
7
+ #include "diff_match_patch-stl/diff_match_patch.h"
8
+ #include <string>
9
+ #include <rice/Constructor.hpp>
10
+
11
+ #define dmp diff_match_patch<std::string>
12
+
13
+
14
+ void register_dmp();
15
+
16
+ #endif
@@ -0,0 +1,10 @@
1
+ #include <rice/Module.hpp>
2
+ #include "_dmp.h"
3
+
4
+ extern "C"
5
+
6
+ void Init_diff_match_patch() {
7
+ RUBY_TRY {
8
+ register_dmp();
9
+ } RUBY_CATCH
10
+ }
@@ -0,0 +1,8 @@
1
+ # Compile with Rice rather than straight mkmf
2
+ require 'rubygems'
3
+ require 'mkmf-rice'
4
+
5
+ dmp_stl_path = File.join(File.dirname(File.expand_path(__FILE__)), '..', '..', 'src', 'include')
6
+ $INCFLAGS << " " << "-I#{dmp_stl_path}".quote
7
+
8
+ create_makefile("diff_match_patch/diff_match_patch")
@@ -0,0 +1,18 @@
1
+ require File.join(File.dirname(File.expand_path(__FILE__)), 'diff_match_patch', 'diff_match_patch')
2
+ class DiffMatchPatch
3
+ VERSION = '1.0.0'
4
+
5
+ def patch_make(*args)
6
+ case
7
+ when args[0].kind_of?(String) && args[1].kind_of?(String)
8
+ __patch_make_from_texts__(args[0], args[1])
9
+ when args[0].kind_of?(String) && args[1].kind_of?(Array)
10
+ __patch_make_from_text_and_diff__(args[0], args[1])
11
+ when args[0].kind_of?(Array) && args[1].nil?
12
+ __patch_make_from_diffs__(args[0])
13
+ else
14
+ raise ArgumentError.new "patch_make accepts two strings, a string and a diff, or a set of diffs only"
15
+ end
16
+ end
17
+
18
+ end