Skip to content

Commit 1267237

Browse files
committed
add stream method
1 parent 4cf98b5 commit 1267237

File tree

9 files changed

+382
-22
lines changed

9 files changed

+382
-22
lines changed

README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,14 @@ npm install --save node-hdiffpatch
1515
### diff(originBuf, newBuf)
1616

1717
Compare two buffers and return a new hdiffpatch patch as return value.
18+
19+
### diffStream(oldPath, newPath, outDiffPath[, cb])
20+
21+
Create diff file by streaming file paths (low memory). In sync mode returns
22+
`outDiffPath`. In async mode, callback signature is `(err, outDiffPath)`.
23+
The diff format is the streaming compressed format; use `patchStream` to apply it.
24+
25+
### patchStream(oldPath, diffPath, outNewPath[, cb])
26+
27+
Apply diff file to old file and write new file by streaming. In sync mode
28+
returns `outNewPath`. In async mode, callback signature is `(err, outNewPath)`.

binding.gyp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"src/hdiff.cpp",
88
"src/hpatch.cpp",
99
"HDiffPatch/libHDiffPatch/HPatch/patch.c",
10+
"HDiffPatch/file_for_patch.c",
1011
"HDiffPatch/libHDiffPatch/HDiff/diff.cpp",
1112
"HDiffPatch/libHDiffPatch/HDiff/private_diff/bytes_rle.cpp",
1213
"HDiffPatch/libHDiffPatch/HDiff/private_diff/suffix_string.cpp",

index.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@ exports.native = native;
44

55
exports.diff = native.diff;
66
exports.patch = native.patch;
7-
7+
exports.diffStream = native.diffStream;
8+
exports.patchStream = native.patchStream;

src/hdiff.cpp

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "hdiff.h"
22
#include "../HDiffPatch/libHDiffPatch/HDiff/diff.h"
3+
#include "../HDiffPatch/file_for_patch.h"
34
#include <stdexcept>
45

56
#define _CompressPlugin_lzma2
@@ -30,3 +31,79 @@ void hdiff(const uint8_t* old, size_t oldsize, const uint8_t* _new, size_t newsi
3031
throw std::runtime_error("check_single_compressed_diff() failed, diff code error!");
3132
}
3233
}
34+
35+
void hdiff_stream(const char* oldPath,const char* newPath,const char* outDiffPath){
36+
if (!oldPath || !newPath || !outDiffPath) {
37+
throw std::runtime_error("Invalid file path.");
38+
}
39+
40+
const size_t myBestDictSize = (1 << 20) * 8; // 固定 8MB,与 v1.0.6 一致
41+
hpatch_TDecompress* decompressPlugin = &lzma2DecompressPlugin;
42+
TCompressPlugin_lzma2 compressPlugin = lzma2CompressPlugin;
43+
compressPlugin.compress_level = 9;
44+
compressPlugin.dict_size = myBestDictSize;
45+
compressPlugin.thread_num = 1;
46+
47+
hpatch_TFileStreamInput oldStream;
48+
hpatch_TFileStreamInput newStream;
49+
hpatch_TFileStreamOutput diffOutStream;
50+
hpatch_TFileStreamInput diffInStream;
51+
hpatch_TFileStreamInput_init(&oldStream);
52+
hpatch_TFileStreamInput_init(&newStream);
53+
hpatch_TFileStreamOutput_init(&diffOutStream);
54+
hpatch_TFileStreamInput_init(&diffInStream);
55+
56+
bool oldOpened = false;
57+
bool newOpened = false;
58+
bool diffOutOpened = false;
59+
bool diffInOpened = false;
60+
61+
try {
62+
if (!hpatch_TFileStreamInput_open(&oldStream, oldPath)) {
63+
throw std::runtime_error("open old file failed.");
64+
}
65+
oldOpened = true;
66+
if (!hpatch_TFileStreamInput_open(&newStream, newPath)) {
67+
throw std::runtime_error("open new file failed.");
68+
}
69+
newOpened = true;
70+
if (!hpatch_TFileStreamOutput_open(&diffOutStream, outDiffPath, ~(hpatch_StreamPos_t)0)) {
71+
throw std::runtime_error("open diff file for write failed.");
72+
}
73+
diffOutOpened = true;
74+
hpatch_TFileStreamOutput_setRandomOut(&diffOutStream, hpatch_TRUE);
75+
76+
create_compressed_diff_stream(&newStream.base, &oldStream.base, &diffOutStream.base,
77+
&compressPlugin.base, kMatchBlockSize_default);
78+
79+
if (!hpatch_TFileStreamOutput_close(&diffOutStream)) {
80+
throw std::runtime_error("close diff file failed.");
81+
}
82+
diffOutOpened = false;
83+
84+
if (!hpatch_TFileStreamInput_open(&diffInStream, outDiffPath)) {
85+
throw std::runtime_error("open diff file for read failed.");
86+
}
87+
diffInOpened = true;
88+
if (!check_compressed_diff_stream(&newStream.base, &oldStream.base,
89+
&diffInStream.base, decompressPlugin)) {
90+
throw std::runtime_error("check_compressed_diff_stream() failed, diff code error!");
91+
}
92+
} catch (...) {
93+
if (diffInOpened) hpatch_TFileStreamInput_close(&diffInStream);
94+
if (diffOutOpened) hpatch_TFileStreamOutput_close(&diffOutStream);
95+
if (newOpened) hpatch_TFileStreamInput_close(&newStream);
96+
if (oldOpened) hpatch_TFileStreamInput_close(&oldStream);
97+
throw;
98+
}
99+
100+
if (diffInOpened && !hpatch_TFileStreamInput_close(&diffInStream)) {
101+
throw std::runtime_error("close diff file failed.");
102+
}
103+
if (newOpened && !hpatch_TFileStreamInput_close(&newStream)) {
104+
throw std::runtime_error("close new file failed.");
105+
}
106+
if (oldOpened && !hpatch_TFileStreamInput_close(&oldStream)) {
107+
throw std::runtime_error("close old file failed.");
108+
}
109+
}

src/hdiff.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,6 @@
1010

1111
void hdiff(const uint8_t* old,size_t oldsize,const uint8_t* _new,size_t newsize,
1212
std::vector<uint8_t>& out_codeBuf);
13+
void hdiff_stream(const char* oldPath,const char* newPath,const char* outDiffPath);
1314

1415
#endif

src/hpatch.cpp

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
*/
55
#include "hpatch.h"
66
#include "../HDiffPatch/libHDiffPatch/HPatch/patch.h"
7+
#include "../HDiffPatch/file_for_patch.h"
78
#include <stdexcept>
89

910
#define _CompressPlugin_lzma2
@@ -76,3 +77,68 @@ void hpatch(const uint8_t* old, size_t oldsize,
7677
throw std::runtime_error("patch_single_stream_by_mem() failed!");
7778
}
7879
}
80+
81+
void hpatch_stream(const char* oldPath,const char* diffPath,const char* outNewPath){
82+
if (!oldPath || !diffPath || !outNewPath) {
83+
throw std::runtime_error("Invalid file path.");
84+
}
85+
86+
hpatch_TDecompress* decompressPlugin = &lzma2DecompressPlugin;
87+
88+
hpatch_TFileStreamInput oldStream;
89+
hpatch_TFileStreamInput diffStream;
90+
hpatch_TFileStreamOutput newStream;
91+
hpatch_TFileStreamInput_init(&oldStream);
92+
hpatch_TFileStreamInput_init(&diffStream);
93+
hpatch_TFileStreamOutput_init(&newStream);
94+
95+
bool oldOpened = false;
96+
bool diffOpened = false;
97+
bool newOpened = false;
98+
99+
try {
100+
if (!hpatch_TFileStreamInput_open(&oldStream, oldPath)) {
101+
throw std::runtime_error("open old file failed.");
102+
}
103+
oldOpened = true;
104+
if (!hpatch_TFileStreamInput_open(&diffStream, diffPath)) {
105+
throw std::runtime_error("open diff file failed.");
106+
}
107+
diffOpened = true;
108+
109+
hpatch_compressedDiffInfo diffInfo;
110+
if (!getCompressedDiffInfo(&diffInfo, &diffStream.base)) {
111+
throw std::runtime_error("getCompressedDiffInfo() failed, invalid diff data!");
112+
}
113+
if (diffInfo.oldDataSize != oldStream.base.streamSize) {
114+
throw std::runtime_error("Old data size mismatch!");
115+
}
116+
if (decompressPlugin && !decompressPlugin->is_can_open(diffInfo.compressType)) {
117+
throw std::runtime_error("Unsupported diff compress type.");
118+
}
119+
120+
if (!hpatch_TFileStreamOutput_open(&newStream, outNewPath, diffInfo.newDataSize)) {
121+
throw std::runtime_error("open new file for write failed.");
122+
}
123+
newOpened = true;
124+
125+
if (!patch_decompress(&newStream.base, &oldStream.base, &diffStream.base, decompressPlugin)) {
126+
throw std::runtime_error("patch_decompress() failed!");
127+
}
128+
} catch (...) {
129+
if (newOpened) hpatch_TFileStreamOutput_close(&newStream);
130+
if (diffOpened) hpatch_TFileStreamInput_close(&diffStream);
131+
if (oldOpened) hpatch_TFileStreamInput_close(&oldStream);
132+
throw;
133+
}
134+
135+
if (newOpened && !hpatch_TFileStreamOutput_close(&newStream)) {
136+
throw std::runtime_error("close new file failed.");
137+
}
138+
if (diffOpened && !hpatch_TFileStreamInput_close(&diffStream)) {
139+
throw std::runtime_error("close diff file failed.");
140+
}
141+
if (oldOpened && !hpatch_TFileStreamInput_close(&oldStream)) {
142+
throw std::runtime_error("close old file failed.");
143+
}
144+
}

src/hpatch.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,6 @@
1212
void hpatch(const uint8_t* old, size_t oldsize,
1313
const uint8_t* diff, size_t diffsize,
1414
std::vector<uint8_t>& out_newBuf);
15+
void hpatch_stream(const char* oldPath,const char* diffPath,const char* outNewPath);
1516

1617
#endif

0 commit comments

Comments
 (0)