Skip to content

Commit b68b046

Browse files
committed
support Interface hsync_TDictCompress new API getDictCompressBorder();
(This new api for optimize libdeflate dict compress speed to 10x) close #30
1 parent df19b22 commit b68b046

7 files changed

+70
-63
lines changed

README.md

+12-14
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# [hsynz](https://github.com/sisong/hsynz)
2-
[![release](https://img.shields.io/badge/release-v1.1.0-blue.svg)](https://github.com/sisong/hsynz/releases)
2+
[![release](https://img.shields.io/badge/release-v1.1.1-blue.svg)](https://github.com/sisong/hsynz/releases)
33
[![license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/sisong/hsynz/blob/main/LICENSE)
44
[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-blue.svg)](https://github.com/sisong/hsynz/pulls)
55
[![+issue Welcome](https://img.shields.io/github/issues-raw/sisong/hsynz?color=green&label=%2Bissue%20welcome)](https://github.com/sisong/hsynz/issues)
@@ -83,11 +83,9 @@ options:
8383
-c-gzip[-{1..9}[-dictBits]] DEFAULT level 9
8484
dictBits can 9--15, DEFAULT 15.
8585
compress by zlib, out_hsynz_file is .gz file format.
86-
-c-ldef[-{1..12}[-dictBits]] DEFAULT level 12
87-
dictBits can 9--15, DEFAULT 15.
86+
-c-ldef[-{1..12}] DEFAULT level 12 (dictBits always 15).
8887
compress by libdeflate, compatible with zlib's deflate encoding.
89-
-c-lgzip[-{1..12}[-dictBits]] DEFAULT level 12
90-
dictBits can 9--15, DEFAULT 15.
88+
-c-lgzip[-{1..12}] DEFAULT level 12 (dictBits always 15)
9189
compress by libdeflate, out_hsynz_file is .gz file format.
9290
-c-zstd[-{10..22}[-dictBits]] DEFAULT level 21
9391
dictBits can 15--30, DEFAULT 24.
@@ -206,7 +204,7 @@ case list([download from OneDrive](https://1drv.ms/u/s!Aj8ygMPeifoQgUIZxYac5_ufl
206204

207205

208206
**test PC**: Windows11, CPU R9-7945HX, SSD PCIe4.0x4 4T, DDR5 5200MHz 32Gx2
209-
**Program version**: hsynz 1.1.0, zsync 0.6.2 (more programs's testing see [HDiffPatch](https://github.com/sisong/HDiffPatch))
207+
**Program version**: hsynz 1.1.1, zsync 0.6.2 (more programs's testing see [HDiffPatch](https://github.com/sisong/HDiffPatch))
210208
**test Program**:
211209
**zsync** run make with `zsyncmake -b 2048 -o {out_newi} {new}`,
212210
client sync diff&patch by `zsync -i {old} -o {out_new} {newi}` (all files are local)
@@ -237,10 +235,10 @@ client sync diff&patch by `hsync_demo {old} {newi} {newz} {out_new}` (all files
237235
|hsynz p8 zlib|20.05%|30M|115.1MB/s|13M|29M|435MB/s|
238236
|hsynz p1 gzip|20.12%|6M|17.3MB/s|6M|22M|268MB/s|
239237
|hsynz p8 gzip|20.12%|30M|115.0MB/s|13M|29M|427MB/s|
240-
|hsynz p1 ldef|19.58%|15M|1.0MB/s|6M|22M|272MB/s|
241-
|hsynz p8 ldef|19.58%|96M|7.2MB/s|13M|29M|431MB/s|
242-
|hsynz p1 lgzip|19.66%|15M|1.0MB/s|6M|22M|267MB/s|
243-
|hsynz p8 lgzip|19.66%|96M|7.2MB/s|13M|29M|419MB/s|
238+
|hsynz p1 ldef|19.57%|15M|7.8MB/s|6M|22M|272MB/s|
239+
|hsynz p8 ldef|19.57%|96M|57.0MB/s|13M|29M|431MB/s|
240+
|hsynz p1 lgzip|19.64%|15M|7.9MB/s|6M|22M|267MB/s|
241+
|hsynz p8 lgzip|19.64%|96M|56.9MB/s|13M|29M|419MB/s|
244242
|hsynz p1 zstd|14.96%|532M|1.9MB/s|24M|34M|264MB/s|
245243
|hsynz p8 zstd|14.95%|3349M|10.1MB/s|24M|34M|410MB/s|
246244

@@ -298,10 +296,10 @@ case list:
298296
|hsynz p8 zlib|58.67%|29M|138.6MB/s|12M|19M|410MB/s|
299297
|hsynz p1 gzip|58.95%|5M|22.6MB/s|4M|11M|242MB/s|
300298
|hsynz p8 gzip|58.95%|29M|138.9MB/s|12M|19M|407MB/s|
301-
|hsynz p1 ldef|58.62%|14M|1.9MB/s|4M|11M|242MB/s|
302-
|hsynz p8 ldef|58.62%|96M|11.3MB/s|12M|19M|413MB/s|
303-
|hsynz p1 lgzip|58.90%|14M|1.9MB/s|4M|11M|240MB/s|
304-
|hsynz p8 lgzip|58.90%|96M|11.3MB/s|12M|19M|405MB/s|
299+
|hsynz p1 ldef|58.61%|14M|23.7MB/s|4M|11M|242MB/s|
300+
|hsynz p8 ldef|58.61%|96M|149.1MB/s|12M|19M|413MB/s|
301+
|hsynz p1 lgzip|58.90%|14M|23.6MB/s|4M|11M|240MB/s|
302+
|hsynz p8 lgzip|58.90%|96M|149.1MB/s|12M|19M|405MB/s|
305303
|hsynz p1 zstd|57.74%|534M|2.7MB/s|24M|28M|234MB/s|
306304
|hsynz p8 zstd|57.74%|3434M|13.4MB/s|24M|28M|390MB/s|
307305

README_cn.md

+14-14
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# [hsynz](https://github.com/sisong/hsynz)
2-
[![release](https://img.shields.io/badge/release-v1.1.0-blue.svg)](https://github.com/sisong/hsynz/releases)
2+
[![release](https://img.shields.io/badge/release-v1.1.1-blue.svg)](https://github.com/sisong/hsynz/releases)
33
[![license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/sisong/hsynz/blob/main/LICENSE)
44
[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-blue.svg)](https://github.com/sisong/hsynz/pulls)
55
[![+issue Welcome](https://img.shields.io/github/issues-raw/sisong/hsynz?color=green&label=%2Bissue%20welcome)](https://github.com/sisong/hsynz/issues)
@@ -85,11 +85,11 @@ hsync_make: [options] newDataPath out_hsyni_file [out_hsynz_file]
8585
压缩字典比特数dictBits可以为9到15, 默认为15。
8686
使用zlib算法来压缩, out_hsynz_file输出文件将是一个标准的.gz格式文件。
8787
(会比 -c-zlib 生成的文件稍大一点)
88-
-c-ldef[-{1..12}[-dictBits]] 默认级别 12
89-
压缩字典比特数dictBits可以为9到15, 默认为15
88+
-c-ldef[-{1..12}] 默认级别 12
89+
压缩字典比特数dictBits总是设置为15
9090
使用libdeflate算法来压缩, 兼容zlib的deflate编码。
91-
-c-lgzip[-{1..12}[-dictBits]] 默认级别 12
92-
压缩字典比特数dictBits可以为9到15, 默认为15
91+
-c-lgzip[-{1..12}] 默认级别 12
92+
压缩字典比特数dictBits总是设置为15
9393
使用libdeflate算法来压缩, out_hsynz_file输出文件将是一个标准的.gz格式文件。
9494
-c-zstd[-{10..22}[-dictBits]] 默认级别 21
9595
压缩字典比特数dictBits 可以为15到30, 默认为24。
@@ -202,7 +202,7 @@ hsync_make: [options] newDataPath out_hsyni_file [out_hsynz_file]
202202

203203

204204
**测试PC**: Windows11, CPU R9-7945HX, SSD PCIe4.0x4 4T, DDR5 5200MHz 32Gx2
205-
**参与测试的程序版本**: hsynz 1.1.0, zsync 0.6.2 (更多程序的对比测试结果见 [HDiffPatch](https://github.com/sisong/HDiffPatch))
205+
**参与测试的程序版本**: hsynz 1.1.1, zsync 0.6.2 (更多程序的对比测试结果见 [HDiffPatch](https://github.com/sisong/HDiffPatch))
206206
**程序测试参数**:
207207
**zsync** 运行 make 参数 `zsyncmake -b 2048 -o {out_newi} {new}`,
208208
客户端同步 diff&patch 时参数 `zsync -i {old} -o {out_new} {newi}` (所有文件都在本地)
@@ -233,10 +233,10 @@ hsync_make: [options] newDataPath out_hsyni_file [out_hsynz_file]
233233
|hsynz p8 zlib|20.05%|30M|115.1MB/s|13M|29M|435MB/s|
234234
|hsynz p1 gzip|20.12%|6M|17.3MB/s|6M|22M|268MB/s|
235235
|hsynz p8 gzip|20.12%|30M|115.0MB/s|13M|29M|427MB/s|
236-
|hsynz p1 ldef|19.58%|15M|1.0MB/s|6M|22M|272MB/s|
237-
|hsynz p8 ldef|19.58%|96M|7.2MB/s|13M|29M|431MB/s|
238-
|hsynz p1 lgzip|19.66%|15M|1.0MB/s|6M|22M|267MB/s|
239-
|hsynz p8 lgzip|19.66%|96M|7.2MB/s|13M|29M|419MB/s|
236+
|hsynz p1 ldef|19.57%|15M|7.8MB/s|6M|22M|272MB/s|
237+
|hsynz p8 ldef|19.57%|96M|57.0MB/s|13M|29M|431MB/s|
238+
|hsynz p1 lgzip|19.64%|15M|7.9MB/s|6M|22M|267MB/s|
239+
|hsynz p8 lgzip|19.64%|96M|56.9MB/s|13M|29M|419MB/s|
240240
|hsynz p1 zstd|14.96%|532M|1.9MB/s|24M|34M|264MB/s|
241241
|hsynz p8 zstd|14.95%|3349M|10.1MB/s|24M|34M|410MB/s|
242242

@@ -294,10 +294,10 @@ case list:
294294
|hsynz p8 zlib|58.67%|29M|138.6MB/s|12M|19M|410MB/s|
295295
|hsynz p1 gzip|58.95%|5M|22.6MB/s|4M|11M|242MB/s|
296296
|hsynz p8 gzip|58.95%|29M|138.9MB/s|12M|19M|407MB/s|
297-
|hsynz p1 ldef|58.62%|14M|1.9MB/s|4M|11M|242MB/s|
298-
|hsynz p8 ldef|58.62%|96M|11.3MB/s|12M|19M|413MB/s|
299-
|hsynz p1 lgzip|58.90%|14M|1.9MB/s|4M|11M|240MB/s|
300-
|hsynz p8 lgzip|58.90%|96M|11.3MB/s|12M|19M|405MB/s|
297+
|hsynz p1 ldef|58.61%|14M|23.7MB/s|4M|11M|242MB/s|
298+
|hsynz p8 ldef|58.61%|96M|149.1MB/s|12M|19M|413MB/s|
299+
|hsynz p1 lgzip|58.90%|14M|23.6MB/s|4M|11M|240MB/s|
300+
|hsynz p8 lgzip|58.90%|96M|149.1MB/s|12M|19M|405MB/s|
301301
|hsynz p1 zstd|57.74%|534M|2.7MB/s|24M|28M|234MB/s|
302302
|hsynz p8 zstd|57.74%|3434M|13.4MB/s|24M|28M|390MB/s|
303303

dict_compress_plugin_demo.h

+37-26
Original file line numberDiff line numberDiff line change
@@ -157,9 +157,8 @@ static const char* k_gzip_dictCompressType="gzipD";
157157

158158
static size_t _zlib_dictCompress(hsync_dictCompressHandle dictHandle,size_t blockIndex,
159159
hpatch_byte* out_code,hpatch_byte* out_codeEnd,
160-
const hpatch_byte* in_dataBegin,const hpatch_byte* in_dataEnd){
160+
const hpatch_byte* in_dataBegin,size_t in_dataSize,size_t in_borderSize){
161161
_TDictCompressPlugin_zlib_data* self=(_TDictCompressPlugin_zlib_data*)dictHandle;
162-
const size_t dataSize=in_dataEnd-in_dataBegin;
163162
const hpatch_BOOL in_isEnd=(blockIndex+1==self->cache.blockCount);
164163
size_t result;
165164
if (self->dict_isInReset){ //reset dict
@@ -172,8 +171,8 @@ static const char* k_gzip_dictCompressType="gzipD";
172171
self->dict_isInReset=hpatch_FALSE;
173172
}
174173
self->stream.next_in =(Bytef*)in_dataBegin;
175-
self->stream.avail_in=(uInt)dataSize;
176-
assert(self->stream.avail_in==dataSize);
174+
self->stream.avail_in=(uInt)in_dataSize;
175+
assert(self->stream.avail_in==in_dataSize);
177176
self->stream.next_out =out_code;
178177
self->stream.avail_out=(uInt)(out_codeEnd-out_code);
179178
assert(self->stream.avail_out==(size_t)(out_codeEnd-out_code));
@@ -200,15 +199,15 @@ static const char* k_gzip_dictCompressType="gzipD";
200199
#else
201200
//update dict & deflateSetDictionary every block (NOTE: deflateSetDictionary slow)
202201
_CacheBlockDict_dictUncompress(&self->cache,blockIndex,blockIndex+1,
203-
in_dataBegin,in_dataEnd);
202+
in_dataBegin,in_dataBegin+in_dataSize);
204203
self->dict_isInReset=hpatch_TRUE;
205204
#endif
206205
}
207206
}
208207
result=self->stream.total_out;
209208
self->stream.total_out=0;
210209
assert(self->stream.avail_in==0);
211-
if ((result>=dataSize)&&(!self->is_gzip))
210+
if ((result>=in_dataSize)&&(!self->is_gzip))
212211
return kDictCompressCancel;// cancel compress
213212
return result;
214213
}
@@ -250,9 +249,13 @@ static const char* k_gzip_dictCompressType="gzipD";
250249
struct libdeflate_compressor* c;
251250
_CacheBlockDict_t cache;
252251
hpatch_byte* tempDecBufEnd;
252+
hpatch_BOOL dict_isInReset;
253253
hpatch_BOOL is_gzip;
254254
} _TDictCompressPlugin_ldef_data;
255255

256+
static size_t _ldef_getDictCompressBorder(){
257+
return 258; //deflate max match length
258+
}
256259
static size_t _ldef_getDictSize(struct hsync_TDictCompress* compressPlugin){
257260
TDictCompressPlugin_ldef* plugin=(TDictCompressPlugin_ldef*)compressPlugin;
258261
const size_t dictSize=((size_t)1<<plugin->dict_bits);
@@ -271,10 +274,11 @@ static const char* k_gzip_dictCompressType="gzipD";
271274
const TDictCompressPlugin_ldef* plugin=(const TDictCompressPlugin_ldef*)compressPlugin;
272275
const size_t dictSize=((size_t)1<<plugin->dict_bits);
273276
const size_t cacheDictSize=_getCacheBlockDictSize(dictSize,blockCount,blockSize);
274-
_TDictCompressPlugin_ldef_data* self=(_TDictCompressPlugin_ldef_data*)malloc(sizeof(_TDictCompressPlugin_ldef_data)+cacheDictSize+blockSize);
277+
const size_t memSize=sizeof(_TDictCompressPlugin_ldef_data)+cacheDictSize+blockSize+_ldef_getDictCompressBorder();
278+
_TDictCompressPlugin_ldef_data* self=(_TDictCompressPlugin_ldef_data*)malloc(memSize);
275279
if (self==0) return 0;
276280
memset(self,0,sizeof(*self));
277-
self->tempDecBufEnd=((hpatch_byte*)self)+sizeof(*self) +cacheDictSize+blockSize;
281+
self->tempDecBufEnd=((hpatch_byte*)self)+memSize;
278282
_CacheBlockDict_init(&self->cache,((hpatch_byte*)self)+sizeof(*self),
279283
cacheDictSize,dictSize,blockCount,blockSize);
280284
self->c=libdeflate_alloc_compressor(plugin->compress_level);
@@ -297,37 +301,43 @@ static const char* k_gzip_dictCompressType="gzipD";
297301
static hpatch_byte* _ldef_getResetDictBuffer(hsync_dictCompressHandle dictHandle,size_t blockIndex,
298302
size_t* out_dictSize){
299303
_TDictCompressPlugin_ldef_data* self=(_TDictCompressPlugin_ldef_data*)dictHandle;
304+
assert(!self->dict_isInReset);
305+
self->dict_isInReset=hpatch_TRUE;
300306
return _CacheBlockDict_getResetDictBuffer(&self->cache,blockIndex,out_dictSize);
301307
}
302308

303309
static size_t _ldef_dictCompress(hsync_dictCompressHandle dictHandle,size_t blockIndex,
304310
hpatch_byte* out_code,hpatch_byte* out_codeEnd,
305-
const hpatch_byte* in_dataBegin,const hpatch_byte* in_dataEnd){
311+
const hpatch_byte* in_dataBegin,size_t in_dataSize,size_t in_borderSize){
306312
_TDictCompressPlugin_ldef_data* self=(_TDictCompressPlugin_ldef_data*)dictHandle;
307-
const size_t dataSize=in_dataEnd-in_dataBegin;
308313
const hpatch_BOOL in_isEnd=(blockIndex+1==self->cache.blockCount);
309314
size_t result;
310315
hpatch_byte* dict;
311316
size_t dictSize;
312317
hpatch_BOOL isHaveDict;
313318
const hpatch_BOOL isSetFinalTag=in_isEnd||(!self->is_gzip);
314-
{ //reset dict
319+
{ //reset dict?
315320
_CacheBlockDict_usedDict(&self->cache,blockIndex,&dict,&dictSize);
316321
isHaveDict=(dictSize>0);
317322
if (isHaveDict){
318-
_checkCompress(dataSize<=(size_t)(self->tempDecBufEnd-dict-dictSize));
319-
memcpy(dict+dictSize,in_dataBegin,dataSize);
323+
_checkCompress(in_dataSize+in_borderSize<=(size_t)(self->tempDecBufEnd-dict-dictSize));
324+
memcpy(dict+dictSize,in_dataBegin,in_dataSize+in_borderSize);
325+
}
326+
if (self->dict_isInReset){
327+
self->dict_isInReset=hpatch_FALSE;
328+
libdeflate_deflate_compress_block_reset(self->c);
320329
}
321330
}
322331

323-
result=libdeflate_deflate_compress_block(self->c,
324-
isHaveDict?dict:in_dataBegin,dictSize,dataSize,isSetFinalTag,
325-
out_code,out_codeEnd-out_code,1);
332+
//result=libdeflate_deflate_compress_block(self->c, isHaveDict?dict:in_dataBegin,
333+
// dictSize,in_dataSize,isSetFinalTag, out_code,out_codeEnd-out_code,1);
334+
result=libdeflate_deflate_compress_block_continue(self->c, isHaveDict?dict:in_dataBegin,
335+
dictSize,in_dataSize,in_borderSize,isSetFinalTag, out_code,out_codeEnd-out_code,1);
326336
_checkCompress(result>0);
327337
if (!in_isEnd)
328338
_CacheBlockDict_dictUncompress(&self->cache,blockIndex,blockIndex+1,
329-
in_dataBegin,in_dataEnd);
330-
if ((result>=dataSize)&&(!self->is_gzip))
339+
in_dataBegin,in_dataBegin+in_dataSize);
340+
if ((result>=in_dataSize)&&(!self->is_gzip))
331341
return kDictCompressCancel;// cancel compress
332342
return result;
333343
}
@@ -339,7 +349,8 @@ static const char* k_gzip_dictCompressType="gzipD";
339349
{_ldef_dictCompressType,_default_maxCompressedSize,
340350
_ldef_limitDictSizeByData,_default_getBestWorkBlockCount,
341351
_ldef_getDictSize,_ldef_dictCompressOpen,_ldef_dictCompressClose,0,
342-
_ldef_getResetDictBuffer,_ldef_dictCompress,_ldef_dictCompressTypeForDisplay},
352+
_ldef_getResetDictBuffer,_ldef_dictCompress,
353+
_ldef_dictCompressTypeForDisplay,_ldef_getDictCompressBorder},
343354
12,MAX_WBITS,hpatch_FALSE};
344355
_def_fun_compressType(_lgzip_dictCompressType,k_gzip_dictCompressType);
345356
_def_fun_compressType(_lgzip_dictCompressTypeForDisplay,"lgzipD (gzipD compatible)");
@@ -348,7 +359,8 @@ static const char* k_gzip_dictCompressType="gzipD";
348359
{_lgzip_dictCompressType,_default_maxCompressedSize,
349360
_ldef_limitDictSizeByData,_default_getBestWorkBlockCount,
350361
_ldef_getDictSize,_ldef_dictCompressOpen,_ldef_dictCompressClose,0,
351-
_ldef_getResetDictBuffer,_ldef_dictCompress,_lgzip_dictCompressTypeForDisplay},
362+
_ldef_getResetDictBuffer,_ldef_dictCompress,
363+
_lgzip_dictCompressTypeForDisplay,_ldef_getDictCompressBorder},
352364
12,MAX_WBITS,hpatch_TRUE};
353365

354366
#endif//_CompressPlugin_ldef
@@ -502,12 +514,11 @@ static const char* k_gzip_dictCompressType="gzipD";
502514

503515
static size_t _zstd_dictCompress(hsync_dictCompressHandle dictHandle,size_t blockIndex,
504516
hpatch_byte* out_code,hpatch_byte* out_codeEnd,
505-
const hpatch_byte* in_dataBegin,const hpatch_byte* in_dataEnd){
517+
const hpatch_byte* in_dataBegin,size_t in_dataSize,size_t in_borderSize){
506518
_TDictCompressPlugin_zstd_data* self=(_TDictCompressPlugin_zstd_data*)dictHandle;
507519
ZSTD_CCtx* s=self->s;
508520
ZSTD_inBuffer s_input;
509521
ZSTD_outBuffer s_output;
510-
const size_t dataSize=in_dataEnd-in_dataBegin;
511522
const hpatch_BOOL in_isEnd=blockIndex+1==self->cache.blockCount;
512523
if (_CacheBlockDict_isHaveDict(&self->cache)){ //reset dict
513524
_zstd_checkComp(ZSTD_CCtx_reset(s,ZSTD_reset_session_only));
@@ -525,7 +536,7 @@ static const char* k_gzip_dictCompressType="gzipD";
525536
}
526537

527538
s_input.src=in_dataBegin;
528-
s_input.size=dataSize;
539+
s_input.size=in_dataSize;
529540
s_input.pos=0;
530541
s_output.dst=out_code;
531542
s_output.size=out_codeEnd-out_code;
@@ -534,10 +545,10 @@ static const char* k_gzip_dictCompressType="gzipD";
534545
assert(s_input.pos==s_input.size);
535546
if (!in_isEnd){//update cache & dict
536547
const hpatch_byte* lastUpdated=self->cache.uncompressCur;
537-
_CacheBlockDict_dictUncompress(&self->cache,blockIndex,blockIndex+1,in_dataBegin,in_dataEnd);
548+
_CacheBlockDict_dictUncompress(&self->cache,blockIndex,blockIndex+1,in_dataBegin,in_dataBegin+in_dataSize);
538549
if (self->isDeltaDict){
539-
if ((self->d!=0)&&(lastUpdated+dataSize==self->cache.uncompressCur)){
540-
_zstd_checkComp(ZSTD_updateCDict_delta(self->d,dataSize));
550+
if ((self->d!=0)&&(lastUpdated+in_dataSize==self->cache.uncompressCur)){
551+
_zstd_checkComp(ZSTD_updateCDict_delta(self->d,in_dataSize));
541552
}else{
542553
__zstd_reCreateCDict(self);
543554
_checkCompress(self->d!=0);

hsync_import_patch.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ extern "C" {
1313
#endif
1414
#define HSYNC_VERSION_MAJOR 1
1515
#define HSYNC_VERSION_MINOR 1
16-
#define HSYNC_VERSION_RELEASE 0
16+
#define HSYNC_VERSION_RELEASE 1
1717

1818
#define _HSYNC_VERSION HSYNC_VERSION_MAJOR.HSYNC_VERSION_MINOR.HSYNC_VERSION_RELEASE
1919
#define _HSYNC_QUOTE(str) #str

0 commit comments

Comments
 (0)