Skip to content

Commit d22f644

Browse files
committed
Merge branch 'master' into python-tests
2 parents 0e858c2 + aae4254 commit d22f644

File tree

16 files changed

+441
-0
lines changed

16 files changed

+441
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@
22
/python3/build
33
/python3/dist
44
/python3/*.egg-info
5+
/dart/.dart_tool

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
## 0.1.6
2+
3+
- Added Dart language implementation in the repo
4+
## 0.1.5
5+
6+
- Initial version with support for TypeScript and Python3

README.md

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ The `diff` and `patch` functions are implemented in the following languages:
1515

1616
* TypeScript
1717
* Python3
18+
* Dart
1819

1920
The `diffData` object **can be used interchangeably between the languages**.\
2021
This makes this library very useful for networked applications, where the client and server are written in different languages.
@@ -114,6 +115,58 @@ obj3 = patch(obj1, diff_data)
114115
print("obj3: ", obj3)
115116
```
116117

118+
### Dart
119+
120+
To install the Dart version of diff-patch, run:
121+
122+
```bash
123+
dart pub add fsoft_diff_patch
124+
```
125+
126+
Then, in your Dart code:
127+
128+
```dart
129+
import 'package:fsoft_diff_patch/fsoft_diff_patch.dart';
130+
131+
void main() {
132+
final a = {
133+
"a": 1,
134+
"b": 2,
135+
"c": {
136+
"d": 3,
137+
"e": 4,
138+
"f": {
139+
"g": 5,
140+
"h": 6,
141+
},
142+
},
143+
};
144+
final b = {
145+
"a": 1,
146+
// "b": 2, // b is deleted
147+
"c": {
148+
"d": 9, // d is changed
149+
"e": 4,
150+
"f": {
151+
"g": 5,
152+
"h": 7, // h is changed
153+
"i": 10, // i is added
154+
},
155+
},
156+
};
157+
// diff a and b and create a diffData object
158+
final diffData = diff(a, b);
159+
// print diffData in the console
160+
print("DIFF DATA\n${json.encode(diffData)}");
161+
// apply diffData to a and create a new object
162+
final patched_a = patch(a, diffData);
163+
// print patched_a in the console
164+
print("\n\nPATCHED OBJ\n${json.encode(patched_a)}");
165+
// check if patched_a is equal to b
166+
print("\n\nSAME OBJECT: ${json.encode(patched_a) == json.encode(b)}");
167+
}
168+
```
169+
117170
### Hint
118171

119172
The `diff` function can be used to see if two objects are the same, by comparing the result of `diff` to an empty object.

dart/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/dart/.dart_tool

dart/CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
## 0.1.1
2+
3+
- Added documentation in the source code
4+
- Added the example folder
5+
6+
## 0.1.0
7+
8+
- Initial version added to the repository

dart/LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2023 Fabio Rotondo
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

dart/README.md

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
# diff-patch
2+
3+
## Introduction
4+
5+
diff-patch is a library that exposes two functions, `diff` and `patch`.
6+
7+
The library does not have any dependencies.
8+
9+
The `diff` function takes two objects (`obj1` and `obj2`) and deep compares them, returning an object that represents the difference between the two (the `diffData`).
10+
`diffData` is an object that can be used to apply the diff to `obj1` to get an object that is the same as `obj2`.
11+
12+
The `patch` function takes an `obj` and a `diffData` object and applies the diff to the object, returning a new object.
13+
14+
The `diff` and `patch` functions are implemented in the following languages:
15+
16+
* TypeScript
17+
* Python3
18+
* Dart
19+
20+
The `diffData` object **can be used interchangeably between the languages**.\
21+
This makes this library very useful for networked applications, where the client and server are written in different languages.
22+
23+
`diffData` can be serialized to JSON and deserialized back to an object. It aims to be as small as possible, and is designed to be used in a networked environment.
24+
25+
More languages will be added in the future, contributions are welcome.
26+
27+
## Usage
28+
29+
### Dart
30+
31+
To install the Dart version of diff-patch, run:
32+
33+
```bash
34+
dart pub add fsoft_diff_patch
35+
```
36+
37+
Then, in your Dart code:
38+
39+
```dart
40+
import 'package:fsoft_diff_patch/fsoft_diff_patch.dart';
41+
42+
void main() {
43+
final a = {
44+
"a": 1,
45+
"b": 2,
46+
"c": {
47+
"d": 3,
48+
"e": 4,
49+
"f": {
50+
"g": 5,
51+
"h": 6,
52+
},
53+
},
54+
};
55+
final b = {
56+
"a": 1,
57+
// "b": 2, // b is deleted
58+
"c": {
59+
"d": 9, // d is changed
60+
"e": 4,
61+
"f": {
62+
"g": 5,
63+
"h": 7, // h is changed
64+
"i": 10, // i is added
65+
},
66+
},
67+
};
68+
// diff a and b and create a diffData object
69+
final diffData = diff(a, b);
70+
// print diffData in the console
71+
print("DIFF DATA\n${json.encode(diffData)}");
72+
// apply diffData to a and create a new object
73+
final patched_a = patch(a, diffData);
74+
// print patched_a in the console
75+
print("\n\nPATCHED OBJ\n${json.encode(patched_a)}");
76+
// check if patched_a is equal to b
77+
print("\n\nSAME OBJECT: ${json.encode(patched_a) == json.encode(b)}");
78+
}
79+
```
80+
81+
## Contributors
82+
83+
This library was created by [Fabio Rotondo](https://github.com/fsoft72).
84+
85+
New language implementations are more than welcome.\
86+
Please open an issue or a pull request if you want to contribute.
87+
88+
**Collaborators**:
89+
90+
* [Nikola Gluhovic](https://github.com/nini-os)
91+
92+
93+
The official repository for this library is [here](https://github.com/fsoft72/diff-patch).
94+
95+
## License
96+
97+
This library is licensed under the MIT License.\
98+
See the [LICENSE](LICENSE) file for details.

dart/analysis_options.yaml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# This file configures the static analysis results for your project (errors,
2+
# warnings, and lints).
3+
#
4+
# This enables the 'recommended' set of lints from `package:lints`.
5+
# This set helps identify many issues that may lead to problems when running
6+
# or consuming Dart code, and enforces writing Dart using a single, idiomatic
7+
# style and format.
8+
#
9+
# If you want a smaller set of lints you can change this to specify
10+
# 'package:lints/core.yaml'. These are just the most critical lints
11+
# (the recommended set includes the core lints).
12+
# The core lints are also what is used by pub.dev for scoring packages.
13+
14+
include: package:lints/recommended.yaml
15+
16+
# Uncomment the following section to specify additional rules.
17+
18+
# linter:
19+
# rules:
20+
# - camel_case_types
21+
22+
# analyzer:
23+
# exclude:
24+
# - path/to/excluded/files/**
25+
26+
# For more information about the core and recommended set of lints, see
27+
# https://dart.dev/go/core-lints
28+
29+
# For additional information about configuring this file, see
30+
# https://dart.dev/guides/language/analysis-options

dart/example/main.dart

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import 'dart:convert';
2+
3+
import 'package:fsoft_diff_patch/fsoft_diff_patch.dart';
4+
5+
void main() {
6+
final a = {
7+
"a": 1,
8+
"b": 2,
9+
"c": {
10+
"d": 3,
11+
"e": 4,
12+
"f": {
13+
"g": 5,
14+
"h": 6,
15+
},
16+
},
17+
};
18+
final b = {
19+
"a": 1,
20+
// "b": 2, // b is deleted
21+
"c": {
22+
"d": 9, // d is changed
23+
"e": 4,
24+
"f": {
25+
"g": 5,
26+
"h": 7, // h is changed
27+
"i": 10, // i is added
28+
},
29+
},
30+
};
31+
// diff a and b and create a diffData object
32+
final diffData = diff(a, b);
33+
// print diffData in the console
34+
print("DIFF DATA\n${json.encode(diffData)}");
35+
// apply diffData to a and create a new object
36+
final patchedObj = patch(a, diffData);
37+
// print patched_a in the console
38+
print("\n\nPATCHED OBJ\n${json.encode(patchedObj)}");
39+
// check if patched_a is equal to b
40+
print("\n\nSAME OBJECT: ${json.encode(patchedObj) == json.encode(b)}");
41+
}

dart/lib/fsoft_diff_patch.dart

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import 'dart:convert';
2+
3+
/// Returns a diffData representing the difference between two JSON objects.
4+
/// The diffData is an object containing only the differences between the two
5+
/// objects. The patch can be applied to the original object using applyPatch
6+
/// to produce the new object.
7+
///
8+
/// @param {Object} oldObject The original object
9+
/// @param {Object} newObject The new object
10+
/// @returns {Object} The diffData object
11+
Map<String, dynamic> diff(dynamic oldObject, dynamic newObject) {
12+
var diffData = <String, dynamic>{};
13+
var keys = newObject.keys.toList();
14+
keys.forEach((key) {
15+
var oldValue = oldObject[key];
16+
var newValue = newObject[key];
17+
if (oldValue == null) {
18+
diffData[key] = newValue;
19+
} else if (newValue == null) {
20+
diffData[key] = null;
21+
} else if (newValue is Map) {
22+
var subPatch = diff(oldValue, newValue);
23+
if (subPatch.isNotEmpty) {
24+
diffData[key] = subPatch;
25+
}
26+
} else if (oldValue != newValue) {
27+
diffData[key] = newValue;
28+
}
29+
});
30+
// now scan oldObject keys and delete the ones that are not present in newObject
31+
keys = oldObject.keys.toList();
32+
keys.forEach((key) {
33+
if (!newObject.containsKey(key)) {
34+
diffData[key] = null;
35+
}
36+
});
37+
return diffData;
38+
}
39+
40+
/// This function takes an object and a diffData object containing the
41+
/// differences between the two objects, and returns a JSON object
42+
/// containing the differences between the two objects.
43+
/// The input object is the original object. The diffData object is the
44+
/// object containing the differences between the two objects.
45+
/// The returned object is the difference between the two objects.
46+
///
47+
/// @param {Object} oldObject The original object
48+
/// @param {Object} diffData The diffData object
49+
/// @returns {Object} The patched object
50+
Map<String, dynamic> patch(dynamic oldObject, dynamic diffData) {
51+
var newObject = json.decode(json.encode(oldObject));
52+
var keys = diffData.keys.toList();
53+
54+
keys.forEach((key) {
55+
var newValue = diffData[key];
56+
var keyNumber = int.tryParse(key) ?? -1;
57+
if (keyNumber >= 0) {
58+
if (keyNumber >= newObject.length) {
59+
newObject.add(newValue);
60+
} else {
61+
newObject[keyNumber] = patch(newObject[keyNumber], newValue);
62+
}
63+
} else {
64+
if (newValue == null) {
65+
newObject.remove(key);
66+
return;
67+
}
68+
if (!newObject.containsKey(key)) {
69+
newObject[key] = newValue;
70+
return;
71+
}
72+
if (newValue is Map) {
73+
newObject[key] = patch(newObject[key], newValue);
74+
} else {
75+
newObject[key] = newValue;
76+
}
77+
}
78+
});
79+
return newObject;
80+
}

dart/pubspec.lock

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Generated by pub
2+
# See https://dart.dev/tools/pub/glossary#lockfile
3+
packages:
4+
lints:
5+
dependency: "direct dev"
6+
description:
7+
name: lints
8+
sha256: "5e4a9cd06d447758280a8ac2405101e0e2094d2a1dbdd3756aec3fe7775ba593"
9+
url: "https://pub.dev"
10+
source: hosted
11+
version: "2.0.1"
12+
sdks:
13+
dart: ">=2.18.0 <3.0.0"

dart/pubspec.yaml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
name: fsoft_diff_patch
2+
description: Deep compare two objects and produces a diffData to transform object1 to object2
3+
version: 0.1.1
4+
repository: https://github.com/fsoft72/diff-patch
5+
license: MIT
6+
7+
environment:
8+
sdk: '>=2.18.0 <3.0.0'
9+
10+
dev_dependencies:
11+
lints: ^2.0.0

0 commit comments

Comments
 (0)