Fossil SCM

Part three of code relocation. All 3rd-party/upstream source files in src/ have been moved to extsrc/. It is very likely that Makefile.msc requires fixing, and a 100% certainty that Makefile.PellesCGMake needed fixing.

stephan 2021-12-25 14:39 code-movement
Commit 9e8c47381e60263a9cd46cf6904db4f69c065389d8bf6b443574ccdb85781c3d
+1 -1
--- auto.def
+++ auto.def
@@ -471,11 +471,11 @@
471471
set sq3path [opt-val with-sqlite]
472472
if {$sq3path in {tree ""}} {
473473
msg-result "Using sqlite3.c from this source tree."
474474
} else {
475475
# SQLITE3_ORIGIN:
476
- # 0 = (local source tree)
476
+ # 0 = local source tree
477477
# 1 = use external lib or sqlite3.o
478478
# 2 = use external sqlite3.c and (if found) shell.c
479479
define USE_SYSTEM_SQLITE 1
480480
define SQLITE3_SRC.2 {}
481481
define SQLITE3_OBJ.2 {}
482482
483483
ADDED extsrc/cson_amalgamation.c
484484
ADDED extsrc/cson_amalgamation.h
485485
ADDED extsrc/linenoise.c
486486
ADDED extsrc/linenoise.h
487487
ADDED extsrc/miniz.c
488488
ADDED extsrc/pikchr.c
489489
ADDED extsrc/shell.c
490490
DELETED src/cson_amalgamation.c
491491
DELETED src/cson_amalgamation.h
492492
DELETED src/linenoise.c
493493
DELETED src/linenoise.h
--- auto.def
+++ auto.def
@@ -471,11 +471,11 @@
471 set sq3path [opt-val with-sqlite]
472 if {$sq3path in {tree ""}} {
473 msg-result "Using sqlite3.c from this source tree."
474 } else {
475 # SQLITE3_ORIGIN:
476 # 0 = (local source tree)
477 # 1 = use external lib or sqlite3.o
478 # 2 = use external sqlite3.c and (if found) shell.c
479 define USE_SYSTEM_SQLITE 1
480 define SQLITE3_SRC.2 {}
481 define SQLITE3_OBJ.2 {}
482
483 DDED extsrc/cson_amalgamation.c
484 DDED extsrc/cson_amalgamation.h
485 DDED extsrc/linenoise.c
486 DDED extsrc/linenoise.h
487 DDED extsrc/miniz.c
488 DDED extsrc/pikchr.c
489 DDED extsrc/shell.c
490 ELETED src/cson_amalgamation.c
491 ELETED src/cson_amalgamation.h
492 ELETED src/linenoise.c
493 ELETED src/linenoise.h
--- auto.def
+++ auto.def
@@ -471,11 +471,11 @@
471 set sq3path [opt-val with-sqlite]
472 if {$sq3path in {tree ""}} {
473 msg-result "Using sqlite3.c from this source tree."
474 } else {
475 # SQLITE3_ORIGIN:
476 # 0 = local source tree
477 # 1 = use external lib or sqlite3.o
478 # 2 = use external sqlite3.c and (if found) shell.c
479 define USE_SYSTEM_SQLITE 1
480 define SQLITE3_SRC.2 {}
481 define SQLITE3_OBJ.2 {}
482
483 DDED extsrc/cson_amalgamation.c
484 DDED extsrc/cson_amalgamation.h
485 DDED extsrc/linenoise.c
486 DDED extsrc/linenoise.h
487 DDED extsrc/miniz.c
488 DDED extsrc/pikchr.c
489 DDED extsrc/shell.c
490 ELETED src/cson_amalgamation.c
491 ELETED src/cson_amalgamation.h
492 ELETED src/linenoise.c
493 ELETED src/linenoise.h

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

D src/cson_amalgamation.c
-560
--- a/src/cson_amalgamation.c
+++ b/src/cson_amalgamation.c
@@ -1,560 +0,0 @@
1
-pack.c */
2
-/* LICENSE
3
-
4
-Copyright (c) 2018 Guido Berhoerster <[email protected]> to NULL to use
5
- the defaul
6
-obtaining a copy by this function,
7
-o it need not outlive the retur in the Software without
8
- \return The parser ob to use,
9
-nd must eventually
10
- be freed by calling delete_JSON_parser().
11
-*/
12
-JSON_PARSER_DLL_API JSON_par
13
-Software is onfig);
14
-
15
-/*! \bri
16
-JSON_PARSER_DLL_API void delete_JSON_parser(JSON_parser jc);
17
-
18
-/*! \brief Pa
19
-included in all \brief Parse a character.
20
-
21
- \return Non-zero, if all characters passed to this fu
22
-EXPRESS OR SON_PARSER_DLL_API int JS
23
-OF MERCHANTABILITY,
24
-l input cha AUTHORS OR COPYRIGHT
25
-zero, if all parsed ch LIABILITY,
26
-.
27
-*/
28
-JSON_PARSER_DLL_API int JSON
29
-FROM, \brief Determine if a given
30
-OTHER DEA cycles are introduced).
31
-
32
- dlib <float.h>
33
-#inclring.h>
34
-
35
-
36
-#if __STDC_VERSION__ >= 199901L
37
-#define INLINE inline
38
-#els__STDC_VERSION__ >= 199901L */
39
-
40
-#define PACK_IGNORED_CHARS " \t\r\n:,"
41
-
42
-enum parser_state {
43
- STATE_INVALID,
44
- STATE_INITIAL,
45
- STATE_END,
46
- STATE_ARRAY_VALUE,
47
- STATE_PROPERTY_NAME,
48
- STATE_PROPERTY_VALUE
49
-};
50
-
51
-struct token
52
-{
53
- int type; /* type specifier */
54
- int optional; /* optional property modifier */
55
- int suppress; /* suppress assignment modifier */
56
- int alloc; /* assignment allocation modifier */
57
- int len_l; /* long length modifier */
58
-};
59
-
60
-struct stateparent_value;
61
- const char * property_name;
62
- enum parser_state parser_state if(0 == rc) return "OK";
63
-#define CHECK(N) else if(cson_rc.N == rc ) return #Nelse)NSE
64
-
65
-Copyright (c) 2018 Guido Berhoerster <[email protected]> to NULL to use
66
- the defaul
67
-obtaining a copy by this function,
68
-o it need not outlive the retur in the Software without
69
- \return The pc)
70
-{
71
-
72
-getcson_rc.IOreturncson_rc.Typepack.c */
73
-/* LICENSE
74
-
75
-Copyright (c) 2018 Guido Berhoerster <[email protected]> to NULL to use
76
- the defaul
77
-obtaining a copy by this function,
78
-o it need not outlive the retur in the Software without
79
- \return The parser ob to use,
80
-nd must eventually
81
- be freed by calcson_rc.Typcson_rc.Typepack.c */
82
-/* LICENSE
83
-
84
-Copyright (c) 2018 Guido Berhoerster <[email protected]> to NULL to use
85
- the defaul
86
-obtaining a copy by this function,
87
-o it need not outlive the retur in the Software without
88
- \return The parser ob to use,
89
-nd must eventually
90
- be freed bystring(val)cson_rc.array(val))
91
-{
92
-n modifier */
93
- int len_l; /* long length modifier */
94
-};
95
-
96
-struct stateparent_value;
97
- const char * property_name;
98
- enum parser_state parser_statepack.c */
99
-/* LICENSE
100
-
101
-Co
102
-
103
-Copyright (c) 2018 Gui
104
-Copyrpack.c */
105
-/* LICENSE
106
-
107
-Copyright (c) 2018 Guido Berhoerster <[email protected]> to NULL to use
108
- the defaul
109
-obtaining a copy by this function,
110
-o it need not outlive the retur in the Software without
111
- \return The parser ob to use,
112
-nd must eventually
113
- be freed by calling delete_JSON_parser().
114
-*/
115
-JSON_PARSER_DLL_API JSON_par
116
-Software is onfig);
117
-
118
-/*! \bri
119
-JSON_PARSER_DLL_API void delete_JSON_parser(JSON_parser jc);
120
-
121
-/*! \brief Pa
122
-included in all \brief Parse a character.
123
-
124
- \return Non-zero, if all characters passed to this fu
125
-EXPRESS OR SON_PARSER_DLL_API int JS
126
-OF MERCHANTABILITY,
127
-l input cha AUTHORS OR COPYRIGHT
128
-zero, if all parsed ch LIABILITY,
129
-.
130
-*/
131
-JSON_PARSER_DLL_API int JSON
132
-FROM, \brief Determine if a given
133
-OTHER DEA cycles are introduced).
134
-
135
- dlib <float.h>
136
-#inclring.h>
137
-
138
-
139
-#if __STDC_VERSION__ >= 199901L
140
-#define INLINE inline
141
-#els__STDC_VERSION__ >= 199901L */
142
-
143
-#define PACK_IGNORED_CHARS " \t\r\n:,"
144
-
145
-enum parser_state {
146
- STATE_INVALID,
147
- STATE_INITIAL,
148
- STATE_END,
149
- STATE_ARRAY_VALUE,
150
- STATE_PROPERTY_NAME,
151
- STATE_PROPERTY_VALUE
152
-};
153
-
154
-struct token
155
-{
156
- int type; /* type specifier */
157
- int optional; /* optional property modifier */
158
- int suppress; /* suppress assignment modifier */
159
- int alloc; /* assignment allocation modifier */
160
- int len_l; /* long length modifier */
161
-};
162
-
163
-struct stateparent_value;
164
- const char * property_name;
165
- enum parser_state parser_stateATE_oldpack.c *
166
-cson_rc.opyright (c) 2018 Guido Berhoerster <[email protected]> to NULL to use
167
- ck.c */
168
-/* LICENSE
169
-
170
-Copycson_rc.}
171
-cson_rc.pack.c */
172
-/*
173
- STATE_PROPERTY_NAME,
174
- pack.c */
175
-/* LICENSE
176
-
177
-Copyrig
178
- STATE_PROPERTY_NAME,
179
- STATE_PROPERTY_VALUE
180
-};
181
-
182
-struct token
183
-{
184
- int type; /* type specifier */
185
- int optional; /* optional property modifier */
186
- int suppress; /* suppress assignment modifier */
187
- int alloc; /* assignment allocation modifier */
188
- int len_l; /* long length modifier */
189
-};
190
-
191
-struct stateparent_value;
192
- const char * property_name;
193
- enum parser_state parser_statepack.c */
194
-/*
195
- STATE_PROPERTY_NAME,
196
- STATE_PROPERTY_VALUE
197
-};
198
-
199
-struct token
200
-{
201
- int type; /* type specifier */
202
- int optional; /* optional property modifier */
203
- int suppress; /* suppress assignment modifier */
204
-
205
-cson_rc.cson_rc.N__ >= 199901L
206
-#depack.c */
207
-/* LICENSE
208
-
209
-CopyriKEYWORD:ESCAPE_SEQUENCE:cson_rc.cson_rc.cson_rc.cson_rc.cson_rc.cson_rc.return cson_rc.}pack.c *cson_rc.printf(ubuf6printf(ubufght (c) 2018 Guido Berhoer
210
-Copyright (c) 2018 Guido Biter->oght (c) 2018 Guido pack.c *printf( binteger(src/* Reminder: snprintf() is C99cson_rc.cson_rc.printf( bsrc/* Reminder: snprintf() is C99<=0cson_rc.cson_rc.Typepack.c */
211
-/* LICErc;
212
- }
213
-}
214
-cson_rc.src)cson_rc.IOFILEpack.c */
215
-/* LICENSE
216
-
217
-dest,"wb"f;
218
-cson_rc.else if( ! npack.c */
219
-/* LICE , 0,cson_rc.cson_rc.cson_rc. pack.c */printf( v pack.c */printf( vpack.c */
220
-/* LICENSE
221
-
222
-Copyright (c) 2018 Guido Berhoerster <[email protected]> to NULL to use
223
- the defaul
224
-obtaining a copy by this function,
225
-o it need not outlive the retur in the Software without
226
- \return The parser ob to use,
227
-nd must eventually
228
- be freed by calling delete_JSON_parser().
229
-*/
230
-JSON_PARSER_DLL_API JSON_par
231
-Software is onfig);
232
-
233
-/*! \bri
234
-JSON_PARSER_DLL_API void delete_JSON_parser(JSON_parser jc);
235
-
236
-/*! \brief Pa
237
-included in all \brief Parse a character.
238
-
239
- \return Non-zero, if all characters passed to this fu
240
-EXPRESS OR SON_PARSER_DLL_API int JS
241
-OF MERCHANTABILITY,
242
-l input cha AUTHORS OR COPYRIGHT
243
-zero, if all parsed ch LIABILITY,
244
-.
245
-*/
246
-JSON_PARSER_DLL_API int JSON
247
-FROM, \brief Determine if a given
248
-OTHER DEA cycles are introduced).
249
-
250
- dlib <float.h>
251
-#inclring.h>
252
-
253
-
254
-#if __STDC_VERSION__ >= 199901L
255
-#define INLINE inline
256
-#els__STDC_VERSION__ >= 199901L */
257
-
258
-#define PACK_IGNORED_CHARS " \t\r\n:,"
259
-
260
-enum parser_state {
261
- STATE_INVALID,
262
- STATE_INITIAL,
263
- STATE_END,
264
- STATE_ARRAY_VALUE,
265
- STATE_PROPERTY_NAME,
266
- STATE_PROPERTY_VALUE
267
-};
268
-
269
-struct token
270
-{
271
- int type; /* type specifier */
272
- int optional; /* optional property modifier */
273
- int suppress; /* suppress assignment modifier */
274
- int alloc; /* assignment allocation modifier */
275
- int len_l; /* long length modifier */
276
-};
277
-
278
-struct stateparent_value;
279
- const char * property_name;
280
- enum parser_state parser_state\brief Determine if a (int)name> to NULL to use
281
- pack.c */
282
-/* LICENSE
283
-
284
-Copyright (c) 2018 Guido Berhoerster <[email protected]> to NULL to use
285
- the defaul
286
-obtaining a copy by this function,
287
-o it need not outlive the retur in the Software without
288
- \return The parser ob to use,
289
-nd must eventually
290
- be freed by calling delete_JSON_parser().
291
-*/
292
-JSON_PARSER_DLL_API JSON_par
293
-Software is onfig);
294
-
295
-/*! \bri
296
-JSON_PARSER_DLL_API void delete_JSON_parser(JSON_parser jc);
297
-
298
-/*! \brief Pa
299
-included in all \brief Parse a character.
300
-
301
- \return Non-zero, if all characters passed to this fu
302
-EXPRESS OR SON_PARSER_DLL_API int JS
303
-OF MERCHANTABILITY,
304
-l input cha AUTHORS OR COPYRIGHT
305
-zero, if all parsed ch LIABILITY,
306
-.
307
-*/
308
-JSON_PARSER_DLL_API int JSON
309
-FROM, \brief Determine if a given
310
-OTHER DEA cycles are introduced).
311
-
312
- dlib <float.h>
313
-#inclring.h>
314
-
315
-
316
-#if __STDC_VERSION__ >= 199901L
317
-#define INLINE inline
318
-#els__STDC_VERSION__ >= 199901L */
319
-
320
-#define PACK_IGNORED_CHARS " \t\r\n:,"
321
-
322
-enum parser_state {
323
- STATE_INVALID,
324
- STATE_INITIAL,
325
- STATE_END,
326
- STATE_ARRAY_VALUE,
327
- STATE_PROPERTY_NAME,
328
- STATE_PROPERTY_VALUE
329
-};
330
-
331
-struct token
332
-{
333
- int type; /* type specifier */
334
- int optional; /* optional property modifier */
335
- int suppress; /* suppress assignment modifier */
336
- int alloc; /* assignment allocation modifier */
337
- int len_l; /* long length modifier */
338
-};
339
-
340
-struct stateparent_value;
341
- const char * property_name;
342
- enum parser_state parser_state if(0 == rc) return "OK";
343
-#define CHECK(N) else if(cson_rc.N == rc ) return #Nelse)NSE
344
-
345
-Copyright (c) 2018 Guido Berhoerster <[email protected]> to NULL to use
346
- the defaul
347
-obtaining a copy by this function,
348
-o it need not outlive the retur in the Software without
349
- \return The pc)
350
-{
351
-
352
-getcson_rc.IOreturncson_rc.Typepack.c */
353
-/* LICENSE
354
-
355
-Copyright (c) 2018 Guido Berhoerster <[email protected]> to NULL to use
356
- the defaul
357
-obtaining a copy by this function,
358
-o it need not outlive the retur in the Software without
359
- \return The parser ob to use,
360
-nd must eventually
361
- be freed by calcson_rc.Typcson_rc.Typepack.c */
362
-/* LICENSE
363
-
364
-Copyright (c) 2018 Guido Berhoerster <[email protected]> to NULL to use
365
- the defaul
366
-obtaining a copy by this function,
367
-o it need not outlive the retur in the Software without
368
- \return The parser ob to use,
369
-nd must eventually
370
- be freed bystring(val)cson_rc.array(val))
371
-{
372
-n modifier */
373
- int len_l; /* long length modifier */
374
-};
375
-
376
-struct stateparent_value;
377
- const char * property_name;
378
- enum parser_state parser_statepack.c */
379
-/* LICENSE
380
-
381
-Co
382
-
383
-Copyright (c) 2018 Gui
384
-Copyrpack.c */
385
-/* LICENSE
386
-
387
-Copyright (c) 2018 Guido Berhoerster <[email protected]> to NULL to use
388
- the defaul
389
-obtaining a copy by this function,
390
-o it need not outlive the retur in the Software without
391
- \return The parser ob to use,
392
-nd must eventually
393
- be freed by calling delete_JSON_parser().
394
-*/
395
-JSON_PARSER_DLL_API JSON_par
396
-Software is onfig);
397
-
398
-/*! \bri
399
-JSON_PARSER_DLL_API void delete_JSON_parser(JSON_parser jc);
400
-
401
-/*! \brief Pa
402
-included in all \brief Parse a character.
403
-
404
- \return Non-zero, if all characters passed to this fu
405
-EXPRESS OR SON_PARSER_DLL_API int JS
406
-OF MERCHANTABILITY,
407
-l input cha AUTHORS OR COPYRIGHT
408
-zero, if all parsed ch LIABILITY,
409
-.
410
-*/
411
-JSON_PARSER_DLL_API int JSON
412
-FROM, \brief Determine if a given
413
-OTHER DEA cycles are introduced).
414
-
415
- dlib <float.h>
416
-#inclring.h>
417
-
418
-
419
-#if __STDC_VERSION__ >= 199901L
420
-#define INLINE inline
421
-#els__STDC_VERSION__ >= 199901L */
422
-
423
-#define PACK_IGNORED_CHARS " \t\r\n:,"
424
-
425
-enum parser_state {
426
- STATE_INVALID,
427
- STATE_INITIAL,
428
- STATE_END,
429
- STATE_ARRAY_VALUE,
430
- STATE_PROPERTY_NAME,
431
- STATE_PROPERTY_VALUE
432
-};
433
-
434
-struct token
435
-{
436
- int type; /* type specifier */
437
- int optional; /* optional property modifier */
438
- int suppress; /* suppress assignment modifier */
439
- int alloc; /* assignment allocation modifier */
440
- int len_l; /* long length modifier */
441
-};
442
-
443
-struct stateparent_value;
444
- const char * property_name;
445
- enum parser_state parser_stateATE_oldpack.c *
446
-cson_rc.opyright (c) 2018 Guido Berhoerster <[email protected]> to NULL to use
447
- ck.c */
448
-/* LICENSE
449
-
450
-Copycson_rc.}
451
-cson_rc.pack.c */
452
-/*
453
- STATE_PROPERTY_NAME,
454
- pack.c */
455
-/* LICENSE
456
-
457
-Copyrig
458
- STATE_PROPERTY_NAME,
459
- STATE_PROPERTY_VALUE
460
-};
461
-
462
-struct token
463
-{
464
- int type; /* type specifier */
465
- int optional; /* optional property modifier */
466
- int suppress; /* suppress assignment modifier */
467
- int alloc; /* assignment allocation modifier */
468
- int len_l; /* long length modifier */
469
-};
470
-
471
-struct stateparent_value;
472
- const char * property_name;
473
- enum parser_state parser_statepack.c */
474
-/*
475
- STATE_PROPERTY_NAME,
476
- STATE_PROPERTY_VALUE
477
-};
478
-
479
-struct token
480
-{
481
- int type; /* type specifier */
482
- int optional; /* optional property modifier */
483
- int suppress; /* suppress assignment modifier */
484
-
485
-cson_rc.cson_rc.N__ >= 199901L
486
-#depack.c */
487
-/* LICENSE
488
-
489
-CopyriKEYWORD:ESCAPE_SEQUENCE:cson_rc.cson_rc.cson_rc.cson_rc.cson_rc.cson_rc.return cson_rc.}pack.c *cson_rc.printf(ubuf6printf(ubufght (c) 2018 Guido Berhoer
490
-Copyright (c) 2018 Guido Biter->oght (c) 2018 Guido pack.c *printf( binteger(src/* Reminder: snprintf() is C99cson_rc.cson_rc.printf( bsrc/* Reminder: snprintf() is C99<=0cson_rc.cson_rc.Typepack.c */
491
-/* LICErc;
492
- }
493
-}
494
-cson_rc.src)cson_rc.IOFILEpack.c */
495
-/* LICENSE
496
-
497
-dest,"wb"f;
498
-cson_rc.else if( ! npack.c */
499
-/* LICE , 0,cson_rc.cson_rc.cson_rc. pack.c */printf( v pack.c */printf( vpack.c */
500
-/* LICENSE
501
-
502
-Copyright (c) 2018 Guido Berhoerster <[email protected]> to NULL to use
503
- the defaul
504
-obtaining a copy by this function,
505
-o it need not outlive the retur in the Software without
506
- \return The parser ob to use,
507
-nd must eventually
508
- be freed by calling delete_JSON_parser().
509
-*/
510
-JSON_PARSER_DLL_API JSON_par
511
-Software is onfig);
512
-
513
-/*! \bri
514
-JSON_PARSER_DLL_API void delete_JSON_parser(JSON_parser jc);
515
-
516
-/*! \brief Pa
517
-included in all \brief Parse a character.
518
-
519
- \return Non-zero, if all characters passed to this fu
520
-EXPRESS OR SON_PARSER_DLL_API int JS
521
-OF MERCHANTABILITY,
522
-l input cha AUTHORS OR COPYRIGHT
523
-zero, if all parsed ch LIABILITY,
524
-.
525
-*/
526
-JSON_PARSER_DLL_API int JSON
527
-FROM, \brief Determine if a given
528
-OTHER DEA cycles are introduced).
529
-
530
- dlib <float.h>
531
-#inclring.h>
532
-
533
-
534
-#if __STDC_VERSION__ >= 199901L
535
-#define INLINE inline
536
-#els__STDC_VERSION__ >= 199901L */
537
-
538
-#define PACK_IGNORED_CHARS " \t\r\n:,"
539
-
540
-enum parser_state {
541
- STATE_INVALID,
542
- STATE_INITIAL,
543
- STATE_END,
544
- STATE_ARRAY_VALUE,
545
- STATE_PROPERTY_NAME,
546
- STATE_PROPERTY_VALUE
547
-};
548
-
549
-struct token
550
-{
551
- int type; /* type specifier */
552
- int optional; /* optional property modifier */
553
- int suppress; /* suppress assignment modifier */
554
- int alloc; /* assignment allocation modifier */
555
- int len_l; /* long length modifier */
556
-};
557
-
558
-struct stateparent_value;
559
- const char * property_name;
560
- enum parser_state parser_state\brief Determine if a (int)
--- a/src/cson_amalgamation.c
+++ b/src/cson_amalgamation.c
@@ -1,560 +0,0 @@
1 pack.c */
2 /* LICENSE
3
4 Copyright (c) 2018 Guido Berhoerster <[email protected]> to NULL to use
5 the defaul
6 obtaining a copy by this function,
7 o it need not outlive the retur in the Software without
8 \return The parser ob to use,
9 nd must eventually
10 be freed by calling delete_JSON_parser().
11 */
12 JSON_PARSER_DLL_API JSON_par
13 Software is onfig);
14
15 /*! \bri
16 JSON_PARSER_DLL_API void delete_JSON_parser(JSON_parser jc);
17
18 /*! \brief Pa
19 included in all \brief Parse a character.
20
21 \return Non-zero, if all characters passed to this fu
22 EXPRESS OR SON_PARSER_DLL_API int JS
23 OF MERCHANTABILITY,
24 l input cha AUTHORS OR COPYRIGHT
25 zero, if all parsed ch LIABILITY,
26 .
27 */
28 JSON_PARSER_DLL_API int JSON
29 FROM, \brief Determine if a given
30 OTHER DEA cycles are introduced).
31
32 dlib <float.h>
33 #inclring.h>
34
35
36 #if __STDC_VERSION__ >= 199901L
37 #define INLINE inline
38 #els__STDC_VERSION__ >= 199901L */
39
40 #define PACK_IGNORED_CHARS " \t\r\n:,"
41
42 enum parser_state {
43 STATE_INVALID,
44 STATE_INITIAL,
45 STATE_END,
46 STATE_ARRAY_VALUE,
47 STATE_PROPERTY_NAME,
48 STATE_PROPERTY_VALUE
49 };
50
51 struct token
52 {
53 int type; /* type specifier */
54 int optional; /* optional property modifier */
55 int suppress; /* suppress assignment modifier */
56 int alloc; /* assignment allocation modifier */
57 int len_l; /* long length modifier */
58 };
59
60 struct stateparent_value;
61 const char * property_name;
62 enum parser_state parser_state if(0 == rc) return "OK";
63 #define CHECK(N) else if(cson_rc.N == rc ) return #Nelse)NSE
64
65 Copyright (c) 2018 Guido Berhoerster <[email protected]> to NULL to use
66 the defaul
67 obtaining a copy by this function,
68 o it need not outlive the retur in the Software without
69 \return The pc)
70 {
71
72 getcson_rc.IOreturncson_rc.Typepack.c */
73 /* LICENSE
74
75 Copyright (c) 2018 Guido Berhoerster <[email protected]> to NULL to use
76 the defaul
77 obtaining a copy by this function,
78 o it need not outlive the retur in the Software without
79 \return The parser ob to use,
80 nd must eventually
81 be freed by calcson_rc.Typcson_rc.Typepack.c */
82 /* LICENSE
83
84 Copyright (c) 2018 Guido Berhoerster <[email protected]> to NULL to use
85 the defaul
86 obtaining a copy by this function,
87 o it need not outlive the retur in the Software without
88 \return The parser ob to use,
89 nd must eventually
90 be freed bystring(val)cson_rc.array(val))
91 {
92 n modifier */
93 int len_l; /* long length modifier */
94 };
95
96 struct stateparent_value;
97 const char * property_name;
98 enum parser_state parser_statepack.c */
99 /* LICENSE
100
101 Co
102
103 Copyright (c) 2018 Gui
104 Copyrpack.c */
105 /* LICENSE
106
107 Copyright (c) 2018 Guido Berhoerster <[email protected]> to NULL to use
108 the defaul
109 obtaining a copy by this function,
110 o it need not outlive the retur in the Software without
111 \return The parser ob to use,
112 nd must eventually
113 be freed by calling delete_JSON_parser().
114 */
115 JSON_PARSER_DLL_API JSON_par
116 Software is onfig);
117
118 /*! \bri
119 JSON_PARSER_DLL_API void delete_JSON_parser(JSON_parser jc);
120
121 /*! \brief Pa
122 included in all \brief Parse a character.
123
124 \return Non-zero, if all characters passed to this fu
125 EXPRESS OR SON_PARSER_DLL_API int JS
126 OF MERCHANTABILITY,
127 l input cha AUTHORS OR COPYRIGHT
128 zero, if all parsed ch LIABILITY,
129 .
130 */
131 JSON_PARSER_DLL_API int JSON
132 FROM, \brief Determine if a given
133 OTHER DEA cycles are introduced).
134
135 dlib <float.h>
136 #inclring.h>
137
138
139 #if __STDC_VERSION__ >= 199901L
140 #define INLINE inline
141 #els__STDC_VERSION__ >= 199901L */
142
143 #define PACK_IGNORED_CHARS " \t\r\n:,"
144
145 enum parser_state {
146 STATE_INVALID,
147 STATE_INITIAL,
148 STATE_END,
149 STATE_ARRAY_VALUE,
150 STATE_PROPERTY_NAME,
151 STATE_PROPERTY_VALUE
152 };
153
154 struct token
155 {
156 int type; /* type specifier */
157 int optional; /* optional property modifier */
158 int suppress; /* suppress assignment modifier */
159 int alloc; /* assignment allocation modifier */
160 int len_l; /* long length modifier */
161 };
162
163 struct stateparent_value;
164 const char * property_name;
165 enum parser_state parser_stateATE_oldpack.c *
166 cson_rc.opyright (c) 2018 Guido Berhoerster <[email protected]> to NULL to use
167 ck.c */
168 /* LICENSE
169
170 Copycson_rc.}
171 cson_rc.pack.c */
172 /*
173 STATE_PROPERTY_NAME,
174 pack.c */
175 /* LICENSE
176
177 Copyrig
178 STATE_PROPERTY_NAME,
179 STATE_PROPERTY_VALUE
180 };
181
182 struct token
183 {
184 int type; /* type specifier */
185 int optional; /* optional property modifier */
186 int suppress; /* suppress assignment modifier */
187 int alloc; /* assignment allocation modifier */
188 int len_l; /* long length modifier */
189 };
190
191 struct stateparent_value;
192 const char * property_name;
193 enum parser_state parser_statepack.c */
194 /*
195 STATE_PROPERTY_NAME,
196 STATE_PROPERTY_VALUE
197 };
198
199 struct token
200 {
201 int type; /* type specifier */
202 int optional; /* optional property modifier */
203 int suppress; /* suppress assignment modifier */
204
205 cson_rc.cson_rc.N__ >= 199901L
206 #depack.c */
207 /* LICENSE
208
209 CopyriKEYWORD:ESCAPE_SEQUENCE:cson_rc.cson_rc.cson_rc.cson_rc.cson_rc.cson_rc.return cson_rc.}pack.c *cson_rc.printf(ubuf6printf(ubufght (c) 2018 Guido Berhoer
210 Copyright (c) 2018 Guido Biter->oght (c) 2018 Guido pack.c *printf( binteger(src/* Reminder: snprintf() is C99cson_rc.cson_rc.printf( bsrc/* Reminder: snprintf() is C99<=0cson_rc.cson_rc.Typepack.c */
211 /* LICErc;
212 }
213 }
214 cson_rc.src)cson_rc.IOFILEpack.c */
215 /* LICENSE
216
217 dest,"wb"f;
218 cson_rc.else if( ! npack.c */
219 /* LICE , 0,cson_rc.cson_rc.cson_rc. pack.c */printf( v pack.c */printf( vpack.c */
220 /* LICENSE
221
222 Copyright (c) 2018 Guido Berhoerster <[email protected]> to NULL to use
223 the defaul
224 obtaining a copy by this function,
225 o it need not outlive the retur in the Software without
226 \return The parser ob to use,
227 nd must eventually
228 be freed by calling delete_JSON_parser().
229 */
230 JSON_PARSER_DLL_API JSON_par
231 Software is onfig);
232
233 /*! \bri
234 JSON_PARSER_DLL_API void delete_JSON_parser(JSON_parser jc);
235
236 /*! \brief Pa
237 included in all \brief Parse a character.
238
239 \return Non-zero, if all characters passed to this fu
240 EXPRESS OR SON_PARSER_DLL_API int JS
241 OF MERCHANTABILITY,
242 l input cha AUTHORS OR COPYRIGHT
243 zero, if all parsed ch LIABILITY,
244 .
245 */
246 JSON_PARSER_DLL_API int JSON
247 FROM, \brief Determine if a given
248 OTHER DEA cycles are introduced).
249
250 dlib <float.h>
251 #inclring.h>
252
253
254 #if __STDC_VERSION__ >= 199901L
255 #define INLINE inline
256 #els__STDC_VERSION__ >= 199901L */
257
258 #define PACK_IGNORED_CHARS " \t\r\n:,"
259
260 enum parser_state {
261 STATE_INVALID,
262 STATE_INITIAL,
263 STATE_END,
264 STATE_ARRAY_VALUE,
265 STATE_PROPERTY_NAME,
266 STATE_PROPERTY_VALUE
267 };
268
269 struct token
270 {
271 int type; /* type specifier */
272 int optional; /* optional property modifier */
273 int suppress; /* suppress assignment modifier */
274 int alloc; /* assignment allocation modifier */
275 int len_l; /* long length modifier */
276 };
277
278 struct stateparent_value;
279 const char * property_name;
280 enum parser_state parser_state\brief Determine if a (int)name> to NULL to use
281 pack.c */
282 /* LICENSE
283
284 Copyright (c) 2018 Guido Berhoerster <[email protected]> to NULL to use
285 the defaul
286 obtaining a copy by this function,
287 o it need not outlive the retur in the Software without
288 \return The parser ob to use,
289 nd must eventually
290 be freed by calling delete_JSON_parser().
291 */
292 JSON_PARSER_DLL_API JSON_par
293 Software is onfig);
294
295 /*! \bri
296 JSON_PARSER_DLL_API void delete_JSON_parser(JSON_parser jc);
297
298 /*! \brief Pa
299 included in all \brief Parse a character.
300
301 \return Non-zero, if all characters passed to this fu
302 EXPRESS OR SON_PARSER_DLL_API int JS
303 OF MERCHANTABILITY,
304 l input cha AUTHORS OR COPYRIGHT
305 zero, if all parsed ch LIABILITY,
306 .
307 */
308 JSON_PARSER_DLL_API int JSON
309 FROM, \brief Determine if a given
310 OTHER DEA cycles are introduced).
311
312 dlib <float.h>
313 #inclring.h>
314
315
316 #if __STDC_VERSION__ >= 199901L
317 #define INLINE inline
318 #els__STDC_VERSION__ >= 199901L */
319
320 #define PACK_IGNORED_CHARS " \t\r\n:,"
321
322 enum parser_state {
323 STATE_INVALID,
324 STATE_INITIAL,
325 STATE_END,
326 STATE_ARRAY_VALUE,
327 STATE_PROPERTY_NAME,
328 STATE_PROPERTY_VALUE
329 };
330
331 struct token
332 {
333 int type; /* type specifier */
334 int optional; /* optional property modifier */
335 int suppress; /* suppress assignment modifier */
336 int alloc; /* assignment allocation modifier */
337 int len_l; /* long length modifier */
338 };
339
340 struct stateparent_value;
341 const char * property_name;
342 enum parser_state parser_state if(0 == rc) return "OK";
343 #define CHECK(N) else if(cson_rc.N == rc ) return #Nelse)NSE
344
345 Copyright (c) 2018 Guido Berhoerster <[email protected]> to NULL to use
346 the defaul
347 obtaining a copy by this function,
348 o it need not outlive the retur in the Software without
349 \return The pc)
350 {
351
352 getcson_rc.IOreturncson_rc.Typepack.c */
353 /* LICENSE
354
355 Copyright (c) 2018 Guido Berhoerster <[email protected]> to NULL to use
356 the defaul
357 obtaining a copy by this function,
358 o it need not outlive the retur in the Software without
359 \return The parser ob to use,
360 nd must eventually
361 be freed by calcson_rc.Typcson_rc.Typepack.c */
362 /* LICENSE
363
364 Copyright (c) 2018 Guido Berhoerster <[email protected]> to NULL to use
365 the defaul
366 obtaining a copy by this function,
367 o it need not outlive the retur in the Software without
368 \return The parser ob to use,
369 nd must eventually
370 be freed bystring(val)cson_rc.array(val))
371 {
372 n modifier */
373 int len_l; /* long length modifier */
374 };
375
376 struct stateparent_value;
377 const char * property_name;
378 enum parser_state parser_statepack.c */
379 /* LICENSE
380
381 Co
382
383 Copyright (c) 2018 Gui
384 Copyrpack.c */
385 /* LICENSE
386
387 Copyright (c) 2018 Guido Berhoerster <[email protected]> to NULL to use
388 the defaul
389 obtaining a copy by this function,
390 o it need not outlive the retur in the Software without
391 \return The parser ob to use,
392 nd must eventually
393 be freed by calling delete_JSON_parser().
394 */
395 JSON_PARSER_DLL_API JSON_par
396 Software is onfig);
397
398 /*! \bri
399 JSON_PARSER_DLL_API void delete_JSON_parser(JSON_parser jc);
400
401 /*! \brief Pa
402 included in all \brief Parse a character.
403
404 \return Non-zero, if all characters passed to this fu
405 EXPRESS OR SON_PARSER_DLL_API int JS
406 OF MERCHANTABILITY,
407 l input cha AUTHORS OR COPYRIGHT
408 zero, if all parsed ch LIABILITY,
409 .
410 */
411 JSON_PARSER_DLL_API int JSON
412 FROM, \brief Determine if a given
413 OTHER DEA cycles are introduced).
414
415 dlib <float.h>
416 #inclring.h>
417
418
419 #if __STDC_VERSION__ >= 199901L
420 #define INLINE inline
421 #els__STDC_VERSION__ >= 199901L */
422
423 #define PACK_IGNORED_CHARS " \t\r\n:,"
424
425 enum parser_state {
426 STATE_INVALID,
427 STATE_INITIAL,
428 STATE_END,
429 STATE_ARRAY_VALUE,
430 STATE_PROPERTY_NAME,
431 STATE_PROPERTY_VALUE
432 };
433
434 struct token
435 {
436 int type; /* type specifier */
437 int optional; /* optional property modifier */
438 int suppress; /* suppress assignment modifier */
439 int alloc; /* assignment allocation modifier */
440 int len_l; /* long length modifier */
441 };
442
443 struct stateparent_value;
444 const char * property_name;
445 enum parser_state parser_stateATE_oldpack.c *
446 cson_rc.opyright (c) 2018 Guido Berhoerster <[email protected]> to NULL to use
447 ck.c */
448 /* LICENSE
449
450 Copycson_rc.}
451 cson_rc.pack.c */
452 /*
453 STATE_PROPERTY_NAME,
454 pack.c */
455 /* LICENSE
456
457 Copyrig
458 STATE_PROPERTY_NAME,
459 STATE_PROPERTY_VALUE
460 };
461
462 struct token
463 {
464 int type; /* type specifier */
465 int optional; /* optional property modifier */
466 int suppress; /* suppress assignment modifier */
467 int alloc; /* assignment allocation modifier */
468 int len_l; /* long length modifier */
469 };
470
471 struct stateparent_value;
472 const char * property_name;
473 enum parser_state parser_statepack.c */
474 /*
475 STATE_PROPERTY_NAME,
476 STATE_PROPERTY_VALUE
477 };
478
479 struct token
480 {
481 int type; /* type specifier */
482 int optional; /* optional property modifier */
483 int suppress; /* suppress assignment modifier */
484
485 cson_rc.cson_rc.N__ >= 199901L
486 #depack.c */
487 /* LICENSE
488
489 CopyriKEYWORD:ESCAPE_SEQUENCE:cson_rc.cson_rc.cson_rc.cson_rc.cson_rc.cson_rc.return cson_rc.}pack.c *cson_rc.printf(ubuf6printf(ubufght (c) 2018 Guido Berhoer
490 Copyright (c) 2018 Guido Biter->oght (c) 2018 Guido pack.c *printf( binteger(src/* Reminder: snprintf() is C99cson_rc.cson_rc.printf( bsrc/* Reminder: snprintf() is C99<=0cson_rc.cson_rc.Typepack.c */
491 /* LICErc;
492 }
493 }
494 cson_rc.src)cson_rc.IOFILEpack.c */
495 /* LICENSE
496
497 dest,"wb"f;
498 cson_rc.else if( ! npack.c */
499 /* LICE , 0,cson_rc.cson_rc.cson_rc. pack.c */printf( v pack.c */printf( vpack.c */
500 /* LICENSE
501
502 Copyright (c) 2018 Guido Berhoerster <[email protected]> to NULL to use
503 the defaul
504 obtaining a copy by this function,
505 o it need not outlive the retur in the Software without
506 \return The parser ob to use,
507 nd must eventually
508 be freed by calling delete_JSON_parser().
509 */
510 JSON_PARSER_DLL_API JSON_par
511 Software is onfig);
512
513 /*! \bri
514 JSON_PARSER_DLL_API void delete_JSON_parser(JSON_parser jc);
515
516 /*! \brief Pa
517 included in all \brief Parse a character.
518
519 \return Non-zero, if all characters passed to this fu
520 EXPRESS OR SON_PARSER_DLL_API int JS
521 OF MERCHANTABILITY,
522 l input cha AUTHORS OR COPYRIGHT
523 zero, if all parsed ch LIABILITY,
524 .
525 */
526 JSON_PARSER_DLL_API int JSON
527 FROM, \brief Determine if a given
528 OTHER DEA cycles are introduced).
529
530 dlib <float.h>
531 #inclring.h>
532
533
534 #if __STDC_VERSION__ >= 199901L
535 #define INLINE inline
536 #els__STDC_VERSION__ >= 199901L */
537
538 #define PACK_IGNORED_CHARS " \t\r\n:,"
539
540 enum parser_state {
541 STATE_INVALID,
542 STATE_INITIAL,
543 STATE_END,
544 STATE_ARRAY_VALUE,
545 STATE_PROPERTY_NAME,
546 STATE_PROPERTY_VALUE
547 };
548
549 struct token
550 {
551 int type; /* type specifier */
552 int optional; /* optional property modifier */
553 int suppress; /* suppress assignment modifier */
554 int alloc; /* assignment allocation modifier */
555 int len_l; /* long length modifier */
556 };
557
558 struct stateparent_value;
559 const char * property_name;
560 enum parser_state parser_state\brief Determine if a (int)
--- a/src/cson_amalgamation.c
+++ b/src/cson_amalgamation.c
@@ -1,560 +0,0 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
D src/cson_amalgamation.h
-2580
--- a/src/cson_amalgamation.h
+++ b/src/cson_amalgamation.h
@@ -1,2582 +0,0 @@
1
-#ifdef FOSSIL_ENABLE_JSON
2
-#ifndef CSON_FOSSIL_MODE
3
-#define CSON_FOSSIL_MODE
4
-#endif
5
-/* auto-generated! Do not edit! */
6
-/* begin file include/wh/cson/cson.h */
7
-#if !defined(WANDERINGHORSE_NET_CSON_H_INCLUDED)
8
-#define WANDERINGHORSE_NET_CSON_H_INCLUDED 1
9
-
10
-/*#include <stdint.h> C99: fixed-size int types. */
11
-#include <stdio.h> /* FILE decl */
12
-
13
-l */
14
-
15
-#include <stdarg.h>
16
-
17
-/** @page page_cson cson JSON API
18
-
19
-cson (pronounced "season") is an object-oriented C API for generating
20
-and consuming JSON (http://www.json.org) data.
21
-
22
-Its main claim to fame is that it can parse JSON from, and output it
23
-to, damned near anywhere. The i/o routines use a callback function to
24
-fetch/emit JSON data, allowing clients to easily plug in their own
25
-implementations. Implementations are provided for string- and
26
-FILE-based i/.
27
-
28
-Project home page: https://epos/cson
29
-
30
-Author: Stephan Beal (httpAuthor: Stephan Beal (https://www.wanderinghorse.net/home/stephan/)
31
-
32
-License: Dual Public Domain/MIT
33
-
34
-The full license text is at the bottom of the main header file
35
-(cson.h).
36
-
37
-Examples of how to use the library are scattered throughout
38
-the API documentation, in the test.c file in the sou
39
-
40
-*/ESS OR IMPLIED, INCLUplus)
41
-extern "C" {
42
-#endif
43
-
44
-#if defined(_WIN32) || defined(_WIN64)
45
-# define CSON_ENABLE_UNIX 0
46
-#else
47
-# define CSON_ENABLE_UNIX 1
48
-#endif
49
-
50
-
51
-/** @typedef some_long_int_type cson_int_t
52
-
53
-Typedef for JSON-like integer types. This is (long long) where feasible,
54
-otherwise (long).
55
-*/
56
-#ifdef _WIN32
57
-typedef __int64 cson_int_t;
58
-#define CSON_INT_T_SFMT "I64d"
59
-#define CSON_INT_T_PFMT "I64d"
60
-#elif (__STDC_VERSION__ >= 199901L) || (HAVE_LONG_LONG == 1)
61
-typedef long long cson_int_t;
62
-#define CSON_INT_T_SFMT "lld"
63
-#define CSON_INT_T_PFMT "lld"
64
-#else
65
-typedef long cson_int_t;
66
-#define CSON_INT_T_SFMT "ld"
67
-#define CSON_INT_T_PFMT "ld"
68
-#endif
69
-
70
-/** @typedef double_or_long_double cson_double_t
71
-
72
- This is the type of double value used by the library.
73
- It is only lightly tested with long double, and when using
74
- long double the memory requirements for such values goes
75
- up.
76
-
77
- Note that by default cson uses C-API defaults for numeric
78
- precision. To use a custom precision throughout the library, one
79
- needs to define the macros CSON_DOUBLE_T_SFMT and/or
80
- CSON_DOUBLE_T_PFMT macros to include their desired precision, and
81
- must build BOTH cson AND the client using these same values. For
82
- example:
83
-
84
- @code
85
- #define CSON_DOUBLE_T_PFMT ".8Lf" // for Modified Julian Day values
86
- #define HAVE_LONG_DOUBLE
87
- @endcode
88
-
89
- (Only CSON_DOUBLE_T_PFTM should be needed for most
90
- purposes.)
91
-*/
92
-
93
-#if defined(HAVE_LONG_DOUBLE)
94
- typedef long double cson_double_t;
95
-# ifndef CSON_DOUBLE_T_SFMT
96
-# define CSON_DOUBLE_T_SFMT "Lf"
97
-# endif
98
-# ifndef CSON_DOUBLE_T_PFMT
99
-# define CSON_DOUBLE_T_PFMT "Lf"
100
-# endif
101
-#else
102
- typedef double cson_double_t;
103
-# ifndef CSON_DOUBLE_T_SFMT
104
-# define CSON_DOUBLE_T_SFMT "f"
105
-# endif
106
-# ifndef CSON_DOUBLE_T_PFMT
107
-# define CSON_DOUBLE_T_PFMT "f"
108
-# endif
109
-#endif
110
-
111
-/** @def CSON_VOID_PTR_IS_BIG
112
-
113
-ONLY define this to a true value if you know that
114
-
115
-(sizeof(cson_int_t) <= sizeof(void*))
116
-
117
-If that is the case, cson does not need to dynamically
118
-allocate integers. However, enabling this may cause
119
-compilation warnings in 32-bit builds even though the code
120
-being warned about cannot ever be called. To get around such
121
-warnings, when building on a 64-bit environment you can define
122
-this to 1 to get "big" integer support. HOWEVER, all clients must
123
-also use the same value for this macro. If i knew a halfway reliable
124
-way to determine this automatically at preprocessor-time, i would
125
-automate this. We might be able to do halfway reliably by looking
126
-for a large INT_MAX value?
127
-*/
128
-#if !defined(CSON_VOID_PTR_IS_BIG)
129
-
130
-/* Largely taken from http://predef.sourceforge.net/prearch.html
131
-
132
-See also: http://poshlib.hookatooka.com/poshlib/trac.cgi/browser/posh.h
133
-*/
134
-# if defined(_WIN64) || defined(__LP64__)/*gcc*/ \
135
- || defined(_M_X64) || defined(__amd64__) || defined(__amd64) \
136
- || defined(__x86_64__) || defined(__x86_64) \
137
- || defined(__ia64__) || defined(__ia64) || defined(_IA64) || defined(__IA64__) \
138
- || defined(_M_IA64) \
139
- || defined(__sparc_v9__) || defined(__sparcv9) || defined(_ADDR64) \
140
- || defined(__64BIT__)
141
-# define CSON_VOID_PTR_IS_BIG 1
142
-# else
143
-# define CSON_VOID_PTR_IS_BIG 0
144
-# endif
145
-#endif
146
-
147
-/** @def CSON_INT_T_SFMT
148
-
149
-scanf()-compatible format token for cson_int_t.
150
-*/
151
-
152
-/** @def CSON_INT_T_PFMT
153
-
154
-printf()-compatible format token for cson_int_t.
155
-*/
156
-
157
-
158
-/** @def CSON_DOUBLE_T_SFMT
159
-
160
-scanf()-compatible format token for cson_double_t.
161
-*/
162
-
163
-/** @def CSON_DOUBLE_T_PFMT
164
-
165
-printf()-compatible format token for cson_double_t.
166
-*/
167
-
168
-/**
169
- Type IDs corresponding to JavaScript/JSON types.
170
-
171
- These are only in the public API to allow O(1) client-side
172
- dispatching based on cson_value types.
173
-*/
174
-enum cson_type_id {
175
- /**
176
- The special "undefined" value constant.
177
-
178
- Its value must be 0 for internal reasons.
179
- */
180
- CSON_TYPE_UNDEF = 0,
181
- /**
182
- The special "null" value constant.
183
- */
184
- CSON_TYPE_NULL = 1,
185
- /**
186
- The bool value type.
187
- */
188
- CSON_TYPE_BOOL = 2,
189
- /**
190
- The integer value type, represented in this library
191
- by cson_int_t.
192
- */
193
- CSON_TYPE_INTEGER = 3,
194
- /**
195
- The double value type, represented in this library
196
- by cson_double_t.
197
- */
198
- CSON_TYPE_DOUBLE = 4,
199
- /** The immutable string type. This library stores strings
200
- as immutable UTF8.
201
- */
202
- CSON_TYPE_STRING = 5,
203
- /** The "Array" type. */
204
- CSON_TYPE_ARRAY = 6,
205
- /** The "Object" type. */
206
- CSON_TYPE_OBJECT = 7
207
-};
208
-/**
209
- Convenience typedef.
210
-*/
211
-typedef enum cson_type_id cson_type_id;
212
-
213
-
214
-/**
215
- Convenience typedef.
216
-*/
217
-typedef struct cson_value cson_value;
218
-
219
-/** @struct cson_value
220
-
221
- The core value type of this API. It is opaque to clients, and
222
- only the cson public API should be used for setting or
223
- inspecting their values.
224
-
225
- This class is opaque because stack-based usage can easily cause
226
- leaks if one does not intimately understand the underlying
227
- internal memory management (which sometimes changes).
228
-
229
- It is (as of 20110323) legal to insert a given value instance into
230
- multiple containers (they will share ownership using reference
231
- counting) as long as those insertions do not cause cycles. However,
232
- be very aware that such value re-use uses a reference to the
233
- original copy, meaning that if its value is changed once, it is
234
- changed everywhere. Also beware that multi-threaded write
235
- operations on such references leads to undefined behaviour.
236
-
237
- PLEASE read the ACHTUNGEN below...
238
-
239
- ACHTUNG #1:
240
-
241
- cson_values MUST NOT form cycles (e.g. via object or array
242
- entries).
243
-
244
- Not abiding th Holy Law Of No Cycles will lead to double-frees and
245
- the like (i.e. undefined behaviour, likely crashes due to infinite
246
- recursion or stepping on invalid (freed) pointers).
247
-
248
- ACHTUNG #2:
249
-
250
- ALL cson_values returned as non-const cson_value pointers from any
251
- public functions in the cson API are to be treated as if they are
252
- heap-allocated, and MUST be freed by client by doing ONE of:
253
-
254
- - Passing it to cson_value_free().
255
-
256
- - Adding it to an ObjecThis object defines the error codes used by cson.
257
-
258
- Library routines which return int values almost always return a
259
- value from this structure. None of the members in this struct have
260
- published values except for the OK member, which has the value 0.
261
- All other values might be incidentally defined where clients
262
- can see them, but the numbers might change from release to
263
- release, so clients should only use the symbolic names.
264
-
265
- Client code is expected to access these values via the shared
266
- cson_rc object, and use them as demonstrated here:
267
-
268
- @code
269
- int rc = cson_some_func(...);
270
- if( 0 == rc ) {...success...}
271
- else if( cson_rc.ArgError == rc ) { ... some argument was wrong ... }
272
- else if( cson_rc.AllocError == rc ) { ... allocation error ... }
273
- ...
274
- @endcode
275
-
276
- ...
277
- }
278
- @endcode
279
-
280
- The entries named Parse_XXX are generally only returned by
281
- */
282
-
283
-/** @struct cson_rc_
284
- See \ref cson_rc for details.
285
-*/
286
-static const struct cson_rc_
287
-{
288
- /** The generic success value. Guaranteed to be 0. */
289
- const int OK;
290
- /** Signifies an error in one or more arguments (e.g. NULL where it is not allowed). */
291
- const int ArgError;
292
- /** Signifies that some argument is not in a valid range. */
293
- const int RangeError;
294
- /** Signifies that some argument is not of the correct logical cson type. */
295
- const int TypeError;
296
- /** Signifies an input/ouput error. */
297
- const int IOError;
298
- /** Signifies an out-of-memory error. */
299
- const int AllocError;
300
- /** Signifies that the called code is "NYI" (Not Yet Implemented). */
301
- const int NYIError;
302
- /** Signifies that an internal error was triggered. If it happens, please report this as a bug! */
303
- const int InternalError;
304
- /** Signifies that the called operation is not supported in the0/*OK*/,
305
-1/*ArgError*/,
306
-2/*RangeError*/,
307
-3/*TypeError*/,
308
-4/*IOError*/,
309
-5/*AllocError*/,
310
-6/*NYIError could not be fo*/,
311
-9/*NotFoundError*/,
312
-10/*UnknownError*/,
313
-11/*Parse_INVALID_CHAR*/,
314
-12/*PaParse_INVALID_ESCAPE_SEQUENCE*/,
315
-14/*def FOSSIL_ENABLE_JSON
316
-#ifndefndef CSOerror code to conver*/,
317
-16/*or;
318
- /**
319
- Signifie*/,
320
-17/* /** Signifies an out-of-*/,
321
-18/*plemented). */
322
- */,
323
-19/*/** Signifies that t*/
324
-}y would add more
325
- Signifies that the parser found an invalid keyword (possibly
326
- an unquoted string).
327
- */
328
- const int Parse_INVALID_KEYWORD;
329
- /**
330
- Signifies that the parser found an invalid escape sequence.
331
- */
332
- const int Parse_INVALID_ESCAPE_SEQUENCE;
333
- /**
334
- Signifies that the parser found an invalid Unicode character
335
- sequence.
336
- */
337
- const int Parse_INVALID_UNICODE_SEQUENCE;
338
- /**
339
- Signifies that the parser found an invalid numeric token.
340
- */
341
- const int Parse_INVALID_NUMBER;
342
- /**
343
- Signifies that the parser reached its maximum defined
344
- parsing depth before finishing the input.
345
- */
346
- const int Parse_NESTING_DEPTH_REACHED;
347
- /**
348
- Signifies that the parser found an unclosed object or array.
349
- */
350
- const int Parse_UNBALANCED_COLLECTION;
351
- /**
352
- Signifies that the parser found an key in an unexpected place.
353
- */
354
- const int Parse_EXPECTED_KEY;
355
- /**
356
- Signifies that the parser expected to find a colon but
357
- found none (e.g. between keys and values in an object).
358
- */
359
- const int Parse_EXPECTED_COLON;
360
-} cson_rc = {
361
- CSON_RC_OK,
362
- CSON_RC_ArgError,
363
- CSON_RC_RangeError,
364
- CSON_RC_TypeError,
365
- CSON_RC_IOError,
366
- CSON_RC_AllocError,
367
- CSON_RC_NYIError,
368
- CSON_RC_InternalError,
369
- CSON_RC_UnsupportedError,
370
- CSON_RC_NotFoundError,
371
- CSON_RC_UnknownError,
372
- CSON_RC_Parse_INVALID_CHAR,
373
- CSON_RC_Parse_INVALID_KEYWORD,
374
- CSON_RC_Parse_INVALID_ESCAPE_SEQUENCE,
375
- CSON_RC_Parse_INVALID_UNICODE_SEQUENCE,
376
- CSON_RC_Parse_INVALID_NUMBER,
377
- CSON_RC_Parse_NESTING_DEPTH_REACHED,
378
- CSON_RC_Parse_UNBALANCED_COLLECTION,
379
- CSON_RC_Parse_EXPECTED_KEY,
380
- CSON_RC_Parse_EXPECTED_COLON
381
-};
382
-
383
-/**
384
- Returns the string form of the cson_rc code corresponding to rc, or
385
- some unspecified, non-NULL string if it is an unknown code.
386
-
387
- The returned bytes are static and do not changing during the
388
- lifetime of the application.
389
-*/
390
-char const * cson_rc_string(int rc);
391
-
392
-/** @struct cson_parse_opt
393
- Client-configurable options for the cson_parse() family of
394
- functions.
395
-*/
396
-struct cson_parse_opt
397
-{
398
- /**
399
- Maximum object/array depth to traverse.
400
- */
401
- unsigned short maxDepth;
402
- /**
403
- Whether or not to allow C-style comments. Do not rely on this
404
- option being available. If the underlying parser is replaced,
405
- this option might no longer be supported.
406
- */
407
- char allowComments;
408
-};
409
-typedef struct cson_parse_opt cson_parse_opt;
410
-
411
-/**
412
- Empty-initialized cson_parse_opt object.
413
-*/
414
-#define cson_parse_opt_empty_m { 25/*maxDepth*/, 0/*allowComments*/}
415
-
416
-
417
-/**
418
- A class for holding JSON parser information. It is primarily
419
- intended for finding the position of a parse error.
420
-*/
421
-struct cson_parse_info
422
-{
423
- /**
424
- 1-based line number.
425
- */
426
- unsigned int line;
427
- /**
428
- 0-based column number.
429
- */
430
- unsigned int col;
431
-
432
- /**
433
- Length, in bytes.
434
- */
435
- unsigned int length;
436
-
437
- /**
438
- Error code of the parse run (0 for no error).
439
- */
440
- int errorCode;
441
-
442
- /**
443
- The total number of object keys successfully processed by the
444
- parser.
445
- */
446
- unsigned int totalKeyCount;
447
-
448
- /**
449
- The total number of object/array values successfully processed
450
- by the parser, including the root node.
451
- */
452
- unsigned int totalValueCount;
453
-};
454
-typedef struct cson_parse_info cson_parse_info;
455
-
456
-/**
457
- Empty-initialized cson_parse_info object.
458
-*/
459
-#define cson_parse_info_empty_m {1/*line*/,\
460
- 0/*col*/, \
461
- 0/*length*/, \
462
- 0/*errorCode*/, \
463
- 0/*totalKeyCount*/, \
464
- 0/*totalValueCount*/ \
465
- }
466
-/**
467
- Empty-initialized cson_parse_info object.
468
-*/
469
-extern const cson_parse_info cson_parse_info_empty;
470
-
471
-/**
472
- Empty-initialized cson_parse_opt object.
473
-*/
474
-extern const cson_parse_opt cson_parse_opt_empty;
475
-
476
-/**
477
- Client-configurable options for the cson_output() family of
478
- functions.
479
-*/
480
-struct cson_output_opt
481
-{
482
- /**
483
- Specifies how to indent (or not) output. The values
484
- are:
485
-
486
- (0) == no extra indentation.
487
-
488
- (1) == 1 TAB character for each level.
489
-
490
- (>1) == that number of SPACES for each level.
491
- */
492
- unsigned char indentation;
493
-
494
- /**
495
- Maximum object/array depth to traverse. Traversing deeply can
496
- be indicative of cycles in the object/array tree, and this
497
- value is used to figure out when to abort the traversal.
498
- */
499
- unsigned short maxDepth;
500
-
501
- /**
502
- If true, a newline will be added to generated output,
503
- else not.
504
- */
505
- char addNewline;
506
-
507
- /**
508
- If true, a space will be added after the colon operator
509
- in objects' key/value pairs.
510
- */
511
- char addSpaceAfterColon;
512
-
513
- /**
514
- If set to 1 then objects/arrays containing only a single value
515
- will not indent an extra level for that value (but will indent
516
- on subsequent levels if that value contains multiple values).
517
- */
518
- char indentSingleMemberValues;
519
-
520
- /**
521
- The JSON format allows, but does not require, JSON generators
522
- to backslash-escape forward slashes. This option enables/disables
523
- that feature. According to JSON's inventor, Douglas Crockford:
524
-
525
- <quote>
526
- It is allowed, not required. It is allowed so that JSON can be
527
- safely embedded in HTML, which can freak out when seeing
528
- strings containing "</". JSON tolerates "<\/" for this reason.
529
- </quote>
530
-
531
- (from an email on 2011-04-08)
532
-
533
- The default value is 0 (because it's just damned ugly).
534
- */
535
- char escapeForwardSlashes;
536
-};
537
-typedef struct cson_output_opt cson_output_opt;
538
-
539
-/**
540
- Empty-initialized cson_output_opt object.
541
-*/
542
-#define cson_output_opt_empty_m { 0/*indentation*/,\
543
- 25/*maxDepth*/, \
544
- 0/*addNewline*/, SON
545
-#ifndef CSONf CSON cson_rc.AllocError on error (preferably a value from
546
- cson_rc).
547
-
548
- These functions are called relatively often during the JSON-output
549
- process, and should try to be fast.
550
-*/
551
-typedef int (*cson_data_dest_f)( void * state, void const * src, unsigned int n );
552
-
553
-/**
554
- Reads JSON-formatted string data (in ASCII, UTF8, or UTF16), using the
555
- src function to fetch all input. This function fetches each input character
556
- from the source function, which is calls like src(srcState, buffer, bufferSize),
557
- and processes them. If anything is not JSON-kosher then this function
558
- fails and returns one of the non-0 cson_rc codes.
559
-
560
- This function is only intended to read root nodes of a JSON tree, either
561
- a single object or a single array, containing any number of child elemSON
562
-#ifndef CSONf CSON_FOSSIL_MODE
563
-#define CSON_cson_rc.e if( !*n ) return CSON_RC_RangeError;
564
- for( i = 0;
565
- (i < *n) && (ss->pos < ss->end);
566
- ++i, ++ss->pos, ++tgt )
567
- {
568
- *tgt = *ss->pos;
569
- }
570
- *n = i;
571
- return 0;
572
- }
573
-
574
- ...
575
- // Now use StringSource together with cson_parse()
576
- StringSource ss;
577
- cson_value * root = NULL;
578
- char const * json = "{\"k1\":123}";
579
- ss.str = ss.pos = json;
580
- ss.end = json + strlen(json);
581
- int rc = cson_parse( &root, cson_data_source_StringSource, &ss, NULL, NULL );
582
- @endcode
583
-
584
- It is recommended that clients wrap such utility code into
585
- type-safe wrapper functions which also initialize the internal
586
- state object and check the user-provided parameters for legality
587
- before passing them on to cson_parse(). For examples of this, see
588
- cson_parse_FILE() or cson_parse_string().
589
-
590
- TODOs:
591
-
592
- - Buffer the input in larger chunks. We currently read
593
- byte-by-byte, but i'm too tired to write/test the looping code for
594
- the buffering.
595
-
596
- @see cson_parse_FILE()
597
- @see cson_parse_string()
598
-*/
599
-int cson_parse( cson_value ** tgt, cson_data_source_f src, void * srcState,
600
- cson_parse_opt const * opt, cson_parse_info * info );
601
-/**
602
- A cson_data_source_f() implementation which requires the state argument
603
- to be a readable (FILE*) handle.
604
-*/
605
-int cson_data_source_FILE( void * state, void * dest, unsigned int * n );
606
-
607
-/**
608
- Equivalent to cson_parse( tgt, cson_data_source_FILE, src, opt ).
609
-
610
- @see cson_parse_filename()
611
-*/
612
-int cson_parse_FILE( cson_value ** tgt, FILE * src,
613
- cson_parse_opt const * opt, cson_parse_info * info );
614
-
615
-/**
616
- Convenience wrapper around cson_parse_FILE() which opens the gcson_rc. contents. Returns CSON_Rt be opened.
617
-
618
- @see cson_parse_FILE()
619
-*/
620
-int cson_parse_filename( cson_value ** tgt, char const * src,
621
- cson_parse_opt const * opt, cson_parse_info * info );
622
-
623
-/**
624
- Uses an internal helper class to pass src through cson_parse().
625
- See that function for the return value and argument semantics.
626
-
627
- src must be a string containing JSON code, at least len bytes long,
628
- and the parser will attempt to parse exactly len bytes from src.
629
-
630
- If len is less than 2 (the minimum length of a legal topcson_rc.rcState,
631
- ich also initialize the internal
632
- state object and check the user-provided parameters for legality
633
- before passing them on to cson_parse(). For examples of this, see
634
- cson_parse_FILE() or cson_parse_string().
635
-
636
- TODOs:
637
-
638
- - Buffer the input in larger chunks. We currently read
639
- byte-by-byte, but i'm too tired to write/test the looping code for
640
- the buffering.
641
-
642
- @see cson_parse_FILE()
643
- @see cson_parse_string()
644
-*/
645
-int cson_parse( cson_value ** tgt, cson_data_source_f src, void * srcState,
646
- cson_rc.rcState,
647
- cson_parse_opt const * opt, cson_parse_info * info );
648
-/**
649
- A cson_data_source_f() implementation which requires the state argument
650
- to be a readable (FILE*) handle.
651
-*/
652
-int cson_data_source_FILE( void * state, void * dest, unsigned int * n );
653
-
654
-/**
655
- Equivalent to cson_parse( tgt, cson_data_source_FILE, src, opt ).
656
-
657
- @see cson_parse_filename()
658
-*/
659
-int cson_parse_FILE( cson_value ** tgt, FILE * src,
660
- cson_parse_opt const * opt, cson_parse_info * info );
661
-
662
-/**
663
- Convenience wrapper around cson_parse_FILE() which opens the given filename.
664
-
665
- Returns CSON_RC_IOError if the file cannot be opened.
666
-
667
- @see cson_parse_FILE()
668
-*/
669
-int cson_parse_filename( cson_value ** tgt, char const * src,
670
- cson_parse_opt const * opt, cson_parse_info * info );
671
-
672
-/**
673
- Uses an internal helper class to pass src through cson_parse().
674
- See that function for the return value and argument semantics.
675
-
676
- src must be a string containing JSON code, at least len bytes long,
677
- and the parser will attempt to parse exactly len bytes from src.
678
-
679
- If len is less than 2 (the minimum length of a legal top-node JSON
680
- object) then CSON_RC_RangeError is returned.
681
-*/
682
-int cson_parse_string( cson_value ** tgt, char const * src, unsigned int len,
683
- cson_rc. contents. Returns CSON_RC_IOError if the file cannot be opened.
684
-
685
- @see cson_output_FILE()
686
-*/
687
-int cson_output_filename( cson_value const * src, char const * dest, cson_output_opt const * fmt );
688
-
689
-/**
690
- Returns the virtual type of v, or CSON_TYPE_UNDEF if !v.
691
-*/
692
-cson_type_id cson_value_type_id( cson_value const * v );
693
-
694
-
695
-/** Returns true if v is null, v->api is NULL, or v holds the special undefined value. */
696
-char cson_value_is_undef( cson_value const * v );
697
-/** Returns true if v contains a null value. */
698
-char cson_value_is_null( cson_value const * v );
699
-/** Returns true if v contains a bool value. */
700
-char cson_value_is_bool( cson_value const * v );
701
-/** Returns true if v contains an integer value. */
702
-char cson_value_is_integer( cson_value const * v );
703
-/** Returns true if v contains a double value. */
704
-char cson_value_is_double( cson_value const * v );
705
-/** Returns true if v contains a number (double, integer) value. */
706
-char cson_value_is_number( cson_value const * v );
707
-/** Returns true if v contains a string value. */
708
-char cson_value_is_string( cson_value const * v );
709
-/** Returns true if v contains an array value. */
710
-char cson_value_is_array( cson_value const * v );
711
-/** Returns true if v contains an object value. */
712
-char cson_value_is_object( cson_value const * v );
713
-
714
-/** @struct cson_object
715
-
716
- cson_object is an opaque handle to an Object value.
717
-
718
- They are used like:
719
-
720
- @code
721
- cson_object * obj = cson_value_get_object(myValue);
722
- ...
723
- @endcode
724
-
725
- They can be created like:
726
-
727
- @code
728
- cson_value * objV = cson_value_new_object();
729
- cson_object * obj = cson_value_get_object(objV);
730
- // obj is owned by objV and objV must eventually be freed
731
- // using cson_value_free() or added to a container
732
- // object/array (which transfers ownership to that container).
733
- @endcode
734
-
735
- @see cson_value_new_object()
736
- @see cson_value_get_object()
737
- @see cson_value_free()
738
-*/
739
-
740
-typedef struct cson_object cson_object;
741
-
742
-/** @struct cson_array
743
-
744
- cson_array is an opaque handle to an Array value.
745
-
746
- They are used like:
747
-
748
- @code
749
- cson_array * obj = cson_value_get_ae a prepared, but not yet traFOSSIL_ENABLE_JSON
750
-#ifndef CSON_FOSSIL_MODE
751
-#define CSON_FOSSIL_MODE
752
-#endif
753
-/* auto-generated! Do not edit! */
754
-/* begin file include/wh/cson/cson.h */
755
-#if !defined(WANDERINGHORSE_NET_CSON_H_INCLUDED)
756
-#define WANDERINGHORSE_NET_CSON_H_INCLUDED 1
757
-
758
-/*#include <stdint.h> C99: fixed-size int types. */
759
-#include <stdio.h> /* FILE decl */
760
-
761
-#include <stdarg.h>
762
-
763
-/** @page page_cson cson JSON API
764
-
765
-cson (pronounced "season") is an object-oriented C API for generating
766
-and consuming JSON (http://www.json.org) data.
767
-
768
-Its main claim to fame is that it can parse JSON from, and output it
769
-to, damned near anywhere. The i/o routines use a callback function to
770
-fetch/emit JSON data, allowing clients to easily plug in their own
771
-implementations. Implementations are provided for string- and
772
-FILE-based i/o.
773
-
774
-Project home page: https://fossil.wanderinghorse.net/r/cson
775
-
776
-Author: Stephan Beal (https://www.wanderinghorse.net/home/stephan/)
777
-
778
-License: Dual Public Domain/MIT
779
-
780
-The full license text is at the bottom of the main header file
781
-(cson.h).
782
-
783
-Examples of how to use the library are scattered throughout
784
-the API documentation, in the test.c file in the source repo,
785
-and in the wiki on the project's home page.
786
-*/
787
-
788
-#if defined(__cplusplus)
789
-extern "C" {
790
-#endif
791
-
792
-#if defined(_WIN32) || defined(_WIN64)
793
-# define CSON_ENABLE_UNIX 0
794
-#else
795
-# define CSON_ENABLE_UNIX 1
796
-#endif
797
-
798
-
799
-/** @typedef some_long_int_type cson_int_t
800
-
801
-Typedef for JSON-like integer types. This is (long long) where feasible,
802
-otherwise (long).
803
-*/
804
-#ifdef _WIN32
805
-typedef __int64 cson_int_t;
806
-#define CSON_INT_T_SFMT "I64d"
807
-#define CSON_INT_T_PFMT "I64d"
808
-#elif (__STDC_VERSION__ >= 199901L) || (HAVE_LONG_LONG == 1)
809
-typedef long long cson_int_t;
810
-#define CSON_INT_T_SFMT "lld"
811
-#define CSON_INT_T_PFMT "lld"
812
-#else
813
-typedef long cson_int_t;
814
-#define CSON_INT_T_SFMT "ld"
815
-#define CSON_INT_T_PFMT "ld"
816
-#endif
817
-
818
-/** @typedef double_or_long_double cson_double_t
819
-
820
- This is the type of double value used by the library.
821
- It is only lightly tested with long double, and when using
822
- long double the memory requirements for such values goes
823
- up.
824
-
825
- Note that by default cson uses C-API defaults for numeric
826
- precision. To use a custom precision throughout the library, one
827
- needs to define the macros CSON_DOUBLE_T_SFMT and/or
828
- CSON_DOUBLE_T_PFMT macros to include their desired precision, and
829
- must build BOTH cson AND the client using these same values. For
830
- example:
831
-
832
- @code
833
- #define CSON_DOUBLE_T_PFMT ".8Lf" // for Modified Julian Day values
834
- #define HAVE_LONG_DOUBLE
835
- @endcode
836
-
837
- (Only CSON_DOUBLE_T_PFTM should be needed for most
838
- purposes.)
839
-*/
840
-
841
-#if defined(HAVE_LONG_DOUBLE)
842
- typedef long double cson_double_t;
843
-# ifndef CSON_DOUBLE_T_SFMT
844
-# define CSON_DOUBLE_T_SFMT "Lf"
845
-# endif
846
-# ifndef CSON_DOUBLE_T_PFMT
847
-# define CSON_DOUBLE_T_PFMT "Lf"
848
-# endif
849
-#else
850
- typedef double cson_double_t;
851
-# ifndef CSON_DOUBLE_T_SFMT
852
-# define CSON_DOUBLE_T_SFMT "f"
853
-# endif
854
-# ifndef CSON_DOUBLE_T_PFMT
855
-# define CSON_DOUBLE_T_PFMT "f"
856
-# endif
857
-#endif
858
-
859
-/** @def CSON_VOID_PTR_IS_BIG
860
-
861
-ONLY define this to a true value if you know that
862
-
863
-(sizeof(cson_int_t) <= sizeof(void*))
864
-
865
-If that is the case, cson does not need to dynamically
866
-allocate integers. However, enabling this may cause
867
-compilation warnings in 32-bit builds even though the code
868
-being warned about cannot ever be called. To get around such
869
-warnings, when building on a 64-bit environment you can define
870
-this to 1 to get "big" integer support. HOWEVER, all clients must
871
-also use the same value for this macro. If i knew a halfway reliable
872
-way to determine this automatically at preprocessor-time, i would
873
-automate this. We might be able to do halfway reliably by looking
874
-for a large INT_MAX value?
875
-*/
876
-#if !defined(CSON_VOID_PTR_IS_BIG)
877
-
878
-/* Largely taken from http://predef.sourceforge.net/prearch.html
879
-
880
-See also: http://poshlib.hookatooka.com/poshlib/trac.cgi/browser/posh.h
881
-*/
882
-# if defined(_WIN64) || defined(__LP64__)/*gcc*/ \
883
- || defined(_M_X64) || defined(__amd64__) || defined(__amd64) \
884
- || defined(__x86_64__) || defined(__x86_64) \
885
- || defined(__ia64__) || defined(__ia64) || defined(_IA64) || defined(__IA64__) \
886
- || defined(_M_IA64) \
887
- || defined(__sparc_v9__) || defined(__sparcv9) || defined(_ADDR64) \
888
- || defined(__64BIT__)
889
-# define CSON_VOID_PTR_IS_BIG 1
890
-# else
891
-# define CSON_VOID_PTR_IS_BIG 0
892
-# endif
893
-#endif
894
-
895
-/** @def CSON_INT_T_SFMT
896
-
897
-scanf()-compatible format token for cson_int_t.
898
-*/
899
-
900
-/** @def CSON_INT_T_PFMT
901
-
902
-printf()-compatible format token for cson_int_t.
903
-*/
904
-
905
-
906
-/** @def CSON_DOUBLE_T_SFMT
907
-
908
-scanf()-compatible format token for cson_double_t.
909
-*/
910
-
911
-/** @def CSON_DOUBLE_T_PFMT
912
-
913
-printf()-compatible format token for cson_double_t.
914
-*/
915
-
916
-/**
917
- Type IDs corresponding to JavaScript/JSON types.
918
-
919
- These are only in the public API to allow O(1) client-side
920
- dispatching based on cson_value types.
921
-*/
922
-enum cson_type_id {
923
- /**
924
- The special "undefined" value constant.
925
-
926
- Its value must be 0 for internal reasons.
927
- */
928
- CSON_TYPE_UNDEF = 0,
929
- /**
930
- The special "null" value constant.
931
- */
932
- CSON_TYPE_NULL = 1,
933
- /**
934
- The bool value type.
935
- */
936
- CSON_TYPE_BOOL = 2,
937
- /**
938
- The integer value type, represented in this library
939
- by cson_int_t.
940
- */
941
- CSON_TYPE_INTEGER = 3,
942
- /**
943
- The double value type, represented in this library
944
- by cson_double_t.
945
- */
946
- CSON_TYPE_DOUBLE = 4,
947
- /** The immutable string type. This library stores strings
948
- as immutable UTF8.
949
- */
950
- CSON_TYPE_STRING = 5,
951
- /** The "Array" type. */
952
- CSON_TYPE_ARRAY = 6,
953
- /** The "Object" type. */
954
- CSON_TYPE_OBJECT = 7
955
-};
956
-/**
957
- Convenience typedef.
958
-*/
959
-typedef enum cson_type_id cson_type_id;
960
-
961
-
962
-/**
963
- Convenience typedef.
964
-*/
965
-typedef struct cson_valueON
966
-#ifndef CSON_f CSON_FOtart with a percent sign '\%'
967
- followed by one or more modifiers and a type character. Object properties
968
- are specified as key-value pairs where the key is specified as a string and
969
- passed as an argument of const char *. Any space, tab, carriage return, line
970
- feed, colon and comma characters between format specifiers are ignored.
971
-
972
- | Type | Description |
973
- | :--: | :---------- |
974
- | s | creates either a property name or a string value, in case of the former the corresponding argument is a pointer to const char which is a sequence of bytes specifying the name of the property that is to be created, in case of the latter the corresponding argument is a pointer to const char |
975
- | d | creates an integer value, the corresponding argument is an int |
976
- | i | ^ |
977
- | f | creates a floating point value, the corresponding argument is a double |
978
- | b | creates a boolean value, the corresponding argument is an int |
979
- | N | creates a null value |
980
- | [...] | creates an array, the corresponding argument is a pointer to a cson_array |
981
- | {...} | creates an array, the corresponding argument is a pointer to a cson_object |
982
-
983
- | Modifier | Description |
984
- | :------: | :---------- |
985
- | l | specifies that the following d or i specifier applies to an argument which is a pointer to long |
986
- | ll | specifies that the following d or i specifier applies to an argument which is a pointer to cson_int_t |
987
-
988
- | Short Form | Expands to
989
- | :--------: | :--------- |
990
- | {...} | %*{...} |
991
- | [...] | %*[...] |
992
- | \%D | \%lld |
993
-
994
-
995
- Returns 0 on success. The error conditions are:
996
-
997
- - CSON_PACK_ARG_ERROR: fmt contains a syntax error
998
-
999
- - CSON_PACK_ALLOC_ERROR: a memory allocation failed
1000
-
1001
- - CSON_PACK_INTERNAL_ERROR: an internal error has occurred, this is a bug in
1002
- cson
1003
-
1004
- Example:
1005
- @code
1006
- cson_value * root_value;
1007
- cson_array * arr;
1008
- ...
1009
- rc = cson_pack( root_value, "{%s: %d, %s: %[]}", "foo", 42, "bar", arr );
1010
- if( 0 != rc ) {
1011
- ... error ...
1012
- }
1013
- @endcode
1014
-*/
1015
-int cson_pack( cson_value **root_valuep, const char *fmt, ... );
1016
-
1017
-/**
1018
- Same as cson_pack() except that it takes a va_list instead of a variable
1019
- number of arguments.
1020
-*/
1021
-int cson_vpack( cson_value **root_valuep, const char *fmt, va_list args );
1022
-
1023
-/**
1024
- Iterate over the given object or array and convert an arbitrary number of
1025
- JSON values into their native C types or validates them according to the
1026
- given format string fmt.
1027
-
1028
- fmt is a format string, it must at least contain an array or object
1029
- specifier as its root value. Format specifiers start with a percent sign '\%'
1030
- followed by one or more modifiers and a type character. Object properties
1031
- are specified as key-value pairs where the key is specified as a string and
1032
- passed as an argument of const char *. Any space, tab, carriage return, line
1033
- feed, colon and comma characters between format specifiers are ignored.
1034
-
1035
- | Type | Description |
1036
- | :--: | :---------- |
1037
- | s | matches a either a property name or a string value, in case of the former the corresponding argument is a pointer to const char which is a sequence of bytes specifying the name of the property that is to be matched, in case of the latter the corresponding argument is a pointer to a pointer to const char unless the 'm' modifier is specified where the the corresponding argument is a pointer to a pointer to char |
1038
- | d | matches an integer value and must be used in with the "ll" modifier, the corresponding argument is a pointer to cson_int_t |
1039
- | i | ^ |
1040
- | f | matches a floating point value, the corresponding argument is a pointer to double |
1041
- | b | matches a boolean value, the corresponding argument is a pointer to int |
1042
- | N | matches a null value |
1043
- | [...] | matches an array, the corresponding argument is a pointer to a pointer to a cson_array |
1044
- | {...} | matches an array, the corresponding argument is a pointer to a pointer to a cson_object |
1045
-
1046
- | Modifier | Description |
1047
- | :------: | :---------- |
1048
- | ? | specifies that the property reffered to by the given property name is optional |
1049
- | * | suppresses assignment, only check for the presence and type of the specified value |
1050
- | m | allocates a memory buffer for the extracted string |
1051
- | ll | specifies that the following d or i specifier applies to an argument which is a pointer to cson_int_t |
1052
-
1053
- | Short Form | Expands to
1054
- | :--------: | :--------- |
1055
- | {...} | %*{...} |
1056
- | [...] | %*[...] |
1057
- | \%D | \%lld |
1058
-
1059
- Returns 0 on success. The error conditions are:
1060
-
1061
- - CSON_PACK_ARG_ERROR: fmt contains a syntax error
1062
-
1063
- - CSON_PACK_ALLOC_ERROR: a memory allocation failed
1064
-
1065
- - CSON_PACK_VALIDATION_ERROR: validation failed, the JSON document structure
1066
- differs from that described by the format string
1067
-
1068
- - CSON_PACK_INTERNAL_ERROR: an internal error has occurred, this
1069
- indicates a bug in this library.
1070
-
1071
- Example:
1072
- @code
1073
- cson_value * root_value;
1074
- cson_int_t x = 0;
1075
- cson_array * arr = NULL;
1076
- const char *str = NULL;
1077
- ...
1078
- rc = cson_unpack( root_value, "{%s: %d, %s: %[], %?s: %s}", "foo", &x, "bar", &arr, "baz", &str );
1079
- if( rc < 3 && rc >= 0 ) {
1080
- ... optional property is missing ...
1081
- } else if ( CSON_PACK_ALLOC_ERROR == rc ) {
1082
- ... out of memory error ...
1083
- } else if ( CSON_PACK_VALIDATION_ERROR == rc ) {
1084
- ... unexpected JSON document structure ...
1085
- } else if ( rc ) {
1086
- ... internal error ...
1087
- }
1088
- @endcode
1089
-
1090
-*/
1091
-int cson_unpack( cson_value *root_value, const char *fmt, ... );
1092
-
1093
-/**
1094
- Same as cson_unpack() except that it takes a va_list instead of a variable
1095
- number of arguments.
1096
-*/
1097
-int cson_vunpack( cson_value *root_value, const char *fmt, va_list args );
1098
-
1099
-/* LICENSE
1100
-
1101
-This software's source code, including accompanying documentation and
1102
-demonstration applications, are licensed under the following
1103
-conditions...
1104
-
1105
-Certain files are imported from external projects and have their own
1106
-licensing terms. Namely, the JSON_parser.* files. See their files for
1107
-their official licenses, but the summary is "do what you want [with
1108
-them] but leave the license text and copyright in place."
1109
-
1110
-The author (Stephan G. Beal [http://wanderinghorse.net/home/stephan/])
1111
-explicitly disclaims copyright in all jurisdictions which recognize
1112
-such a disclaimer. In such jurisdictions, this software is released
1113
-into the Public Domain.
1114
-
1115
-In jurisdictions which do not recognize Public Domain property
1116
-(e.g. Germany as of 2011), this software is Copyright (c) 2011 by
1117
-Stephan G. Beal, and is released under the terms of the MIT License
1118
-(see below).
1119
-
1120
-In jurisdictions which recognize Public Domain property, the user of
1121
-this software may choose to accept it either as 1) Public Domain, 2)
1122
-under the conditions of the MIT License (see below), or 3) under the
1123
-terms of dual Public Domain/MIT License conditions described here, as
1124
-they choose.
1125
-
1126
-The MIT License is about as close to Public Domain as a license can
1127
-get, and is described in clear, concise terms at:
1128
-
1129
- http://en.wikipedia.org/wiki/MIT_License
1130
-
1131
-The full text of the MIT License follows:
1132
-
---
1133
-Copyright (c) 2011 Stephan G. Beal (http://wanderinghorse.net/home/stephan/)
1134
-
1135
-Permission is hereby granted, free of charge, to any person
1136
-obtaining a copy of this software and associated documentation
1137
-files (the "Software"), to deal in the Software without
1138
-restriction, including without limitation the rights to use,
1139
-copy, modify, merge, publish, distribute, sublicense, and/or sell
1140
-copies of the Software, and to permit persons to whom the
1141
-Software is furnished to do so, subject to the following
1142
-conditions:
1143
-
1144
-The above copyright notice and this permission notice shall be
1145
-included in all copies or substantial portions of the Software.
1146
-
1147
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY<sqlite3.h>ESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
1148
-OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
1149
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
1150
-HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
1151
-WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
1152
-FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
1153
-OTHER DEALINGS IN THE SOFTWARE.
1154
-
---END OF MIT LICENSE--
1155
-
1156
-For purposes of the above license, the term "Software" includes
1157
-documentation and demonstration source code which accompanies
1158
-this software. ("Accompanies" = is contained in the Software's
1159
-primary public source code repository.)
1160
-
1161
-*/
1162
-
1163
-#if defined(__cplusplus)
1164
-} /*extern "C"*/
1165
-#endif
1166
-
1167
-#endif /* WANDERINGHORSE_NET_CSON_H_INCLUDED */
1168
-/* end file include/wh/cson/cson.h */
1169
-/* begin file include/wh/cson/cson_sqlite3.h */
1170
-/** @file cson_sqlite3.h
1171
-
1172
-This file contains cson's public sqlite3-to-JSON API declarations
1173
-and API documentation. If CSON_ENABLE_SQLITE3 is not defined,
1174
-or is defined to 0, then including this file will have no side-effects
1175
-other than defining CSON_ENABLE_SQLITE3 (if it was not defined) to 0
1176
-and defining a few include guard macros. i.e. if CSON_ENABLE_SQLITE3
1177
-is not set to a true value then the API is not visible.
1178
-
1179
-This API requires that <sqlite3.h> be in the INCLUDES path and that
1180
-the client eventually link to (or directly embed) the sqlite3 library.
1181
-*/
1182
-#if !defined(WANDERINGHORSE_NET_CSON_SQLITE3_H_INCLUDED)
1183
-#define WANDERINGHORSE_NET_CSON_SQLITE3_H_INCLUDED 1
1184
-#if !defined(CSON_ENABLE_SQLITE3)
1185
-# if defined(DOXYGEN)
1186
-#define CSON_ENABLE_SQLITE3 1
1187
-# else
1188
-#define CSON_ENABLE_SQLITE3 1
1189
-# endif
1190
-#endif
1191
-
1192
-#if CSON_ENABLE_SQLITE3 /* we do this here for the sake of the amalgamation build */
1193
-#include "sqlite3.h"
1194
-
1195
-#if defined(__cplusplus)
1196
-extern "C" {
1197
-#endif
1198
-
1199
-/**
1200
- Converts a single value from a single 0-based column index to its JSON
1201
- equivalent.
1202
-
1203
- On success it returns a new JSON value, which will have a different concrete
1204
- type depending on the field type reported by sqlite3_column_type(st,col):
1205
-
1206
- Integer, double, null, or string (TEXT and BLOB data, though not
1207
- all blob data is legal for a JSON string).
1208
-
1209
- st must be a sqlite3_step()'d row and col must be a 0-based column
1210
- index within that result row.
1211
- */
1212
-cson_value * cson_sqlite3_column_to_value( sqlite3_stmt * st, int col );
1213
-
1214
-/**
1215
- Creates a JSON Array object containing the names of all columns
1216
- of the given prepared statement handle.
1217
-
1218
- Returns a new array value on success, which the caller owns. Its elements
1219
- are in the same order as in the underlying query.
1220
-
1221
- On error NULL is returned.
1222
-
1223
- st is not traversed or freed by this function - only the column
1224
- count and names are read.
1225
-*/
1226
-cson_value * cson_sqlite3_column_names( sqlite3_stmt * st );
1227
-
1228
-/**
1229
- Creates a JSON Object containing key/value pairs corresponding
1230
- to the result columns in the current row of the given statement
1231
- handle. st must be a sqlite3_step()'d row result.
1232
-
1233
- On success a new Object is returned which is owned by the
1234
- caller. On error NULL is returned.
1235
-
1236
- cson_sqlite3_column_to_value() is used to convert each column to a
1237
- JSON value, and the column names are taken from
1238
- sqlite3_column_name().
1239
-*/
1240
-cson_value * cson_sqlite3_row_to_object( sqlite3_stmt * st );
1241
-/**
1242
- Functionally almost identical to cson_sqlite3_row_to_object(), the
1243
- only difference being how the result objects gets its column names.
1244
- st must be a freshly-step()'d handle holding a result row.
1245
- colNames must be an Array with at least the same number of columns
1246
- as st. If it has fewer, NULL is returned and this function has
1247
- no side-effects.
1248
-
1249
- For each column in the result set, the colNames entry at the same
1250
- index is used for the column key. If a given entry is-not-a String
1251
- then conversion will fail and NULL will be returned.
1252
-
1253
- The one reason to prefer this over cson_sqlite3_row_to_object() is
1254
- that this one can share the keys across multiple rows (or even
1255
- other JSON containers), whereas the former makes fresh copies of
1256
- the column names for each row.
1257
-
1258
-*/
1259
-cson_value * cson_sqlite3_row_to_object2( sqlite3_stmt * st,
1260
- cson_array * colNames );
1261
-
1262
-/**
1263
- Similar to cson_sqlite3_row_to_object(), but creates an Array
1264
- value which contains the JSON-form values of the given result
1265
- set row.
1266
-*/
1267
-cson_value * cson_sqlite3_row_to_array( sqlite3_stmt * st );
1268
-/**
1269
- Converts the results of an sqlite3 SELECT statement to JSON,
1270
- in the form of a cson_value object tree.
1271
-
1272
- st must be a prepared, but not yet traversed, SELECT query.
1273
- tgt must be a pointer to NULL (see the example below). If
1274
- either of those arguments are NULL, cson_rc.ArgError is returned.
1275
-
1276
- This walks the query results and returns a JSON object which
1277
- has a different structure depending on the value of the 'fat'
1278
- argument.
1279
-
1280
-
1281
- If 'fat' is 0 then the structure is:
1282
-
1283
- @code
1284
- {
1285
- "columns":["colName1",..."colNameN"],
1286
- "rows":[
1287
- [colVal0, ... colValNs: cson_rc.AllocErroralue_get_object( cs
1288
-char * cson_value_get_string_copy( cson_value const * val );
1289
-
1290
-/**
1291
- Simplified form of cson_value_fetch_object(). Returns NULL if val
1292
- is-not-a objectSON
1293
-#ifndef CSON_Ff CSON_FOSSIL_MODE
1294
-#define CSON_FOSSIL_MODE
1295
-#endif
1296
-/* auto-generated! Do not edit! */
1297
-/* begin file include/wh/cson/cson.h */
1298
-#if !defined(WANDERINGHORSE_NET_CSON_H_INCLUDED)
1299
-#define WANDERINGHORSE_NET_CSON_H_INCLUDED 1
1300
-
1301
-/*#include <stdint.h> C99: fixed-size int types. */
1302
-#include <stdio.h> /* FILE decl */
1303
-
1304
-#include <stdarg.h>
1305
-
1306
-/** @page page_cson cson JSON API
1307
-
1308
-cson (pronounced "season") is an object-oriented C API for generating
1309
-and consuming JSON (http://www.json.org) data.
1310
-
1311
-Its main claim to fame is that it can parse JSON from, and output it
1312
-to, damned near anywhere. The i/o routines use a callback function to
1313
-fetch/emit JSON data, allowing clients to easily plug in their own
1314
-implementations. Implementations are provided for string- and
1315
-FILE-based i/o.
1316
-
1317
-Project home page: https://fossil.wanderinghorse.net/r/cson
1318
-
1319
-Author: Stephan Beal (https://www.wanderinghorse.net/home/stephan/)
1320
-
1321
-License: Dual Public Domain/MIT
1322
-
1323
-The full license text is at the bottom of the main header file
1324
-(cson.h).
1325
-
1326
-Examples of how to use the library are scattered throughout
1327
-the API documentation, in the test.c file in the source repo,
1328
-and in the wiki on the project's home page.
1329
-*/
1330
-
1331
-#if defined(__cplusplus)
1332
-extern "C" {
1333
-#endif
1334
-
1335
-#if defined(_WIN32) || defined(_WIN64)
1336
-# define CSON_ENABLE_UNIX 0
1337
-#else
1338
-# define CSON_ENABLE_UNIX 1
1339
-#endif
1340
-
1341
-
1342
-/** @typedef some_long_int_type cson_int_t
1343
-
1344
-Typedef for JSON-like integer types. This is (long long) where feasible,
1345
-otherwise (long).
1346
-*/
1347
-#ifdef _WIN32
1348
-typedef __int64 cson_int_t;
1349
-#define CSON_INT_T_SFMT "I64d"
1350
-#define CSON_INT_T_PFMT "I64d"
1351
-#elif (__STDC_VERSION__ >= 199901L) || (HAVE_LONG_LONG == 1)
1352
-typedef long long cson_int_t;
1353
-#define CSON_INT_T_SFMT "lld"
1354
-#define CSON_INT_T_PFMT "lld"
1355
-#else
1356
-typedef long cson_SON
1357
-#ifndef CSONf CSON_FOSSIL_MODE
1358
-#define CSOcson_rc.AllocError.
1359
-
1360
- - Appending would cause a numeric overlow in the array's size:
1361
- cson_rc.RangeError. (However, you'll get an AllocError long before
1362
- that happens!)
1363
-
1364
- On error ownership of v is NOT modified, and the caller may still
1365
- need to clean it up. See cson_array_set() for the details.
1366
-
1367
-*/
1368
-int cson_array_append( cson_array * ar, cson_value * v );
1369
-
1370
-
1371
-/**
1372
- Creates a new cson_value from the given boolean value.
1373
-
1374
- Ownership of the new value is passed to the caller, who must
1375
- eventually either free the value using cson_value_free() or
1376
- inserting it into a container (array or object), which transfers
1377
- ownership to the container. See the cson_value class documentation
1378
- for more details.
1379
-
1380
- Semantically speaking this function Returns NULL on allocation
1381
- error, but the implementation never actually allocates for this
1382
- case. Nonetheless, it must be treated as if it were an allocated
1383
- value.
1384
-*/
1385
-cson_value * cson_value_new_bool( char v );
1386
-
1387
-
1388
-/**
1389
- Alias for cson_value_new_bool(v).
1390
-*/
1391
-cson_value * cson_new_bool(char v);
1392
-
1393
-/**
1394
- Returns the special JSON "null" value. When outputing JSON,
1395
- its string representation is "null" (without the quotes).
1396
-
1397
- See cson_value_new_bool() for notes regarding the returned
1398
- value's memory.
1399
-*/
1400
-cson_value * cson_value_null( void );
1401
-
1402
-/**
1403
- Equivalent to cson_value_new_bool(1).
1404
-*/
1405
-cson_value * cson_value_true( void );
1406
-
1407
-/**
1408
- Equivalent to cson_value_new_bool(0).
1409
-*/
1410
-cson_value * cson_value_false( void );
1411
-
1412
-/**
1413
- Semantically the same as cson_value_new_bool(), but for integers.
1414
-*/
1415
-cson_value * cson_value_new_integer( cson_int_t v );
1416
-
1417
-/**
1418
- Alias for cson_value_new_integer(v).
1419
-*/
1420
-cson_value * cson_new_int(cson_int_t v);
1421
-
1422
-/**
1423
- Semantically the same as cson_value_new_bool(), but for doubles.
1424
-*/
1425
-cson_value * cson_value_new_double( cson_double_t v );
1426
-
1427
-/**
1428
- Alias for cson_value_new_double(v).
1429
-*/
1430
-cson_value * cson_new_double(cson_double_t v);
1431
-
1432
-/**
1433
- Semantically the same as cson_value_new_bool(), but for strings.
1434
- This creates a JSON value which copies the first n bytes of str.
1435
- The string will automatically be NUL-terminated.
1436
-
1437
- Note that if str is NULL or n is 0, this function still
1438
- returns non-NULL value representing that empty string.
1439
-
1440
- Returns NULL on allocation error.
1441
-
1442
- See cson_value_new_bool() for important information about the
1443
- returned memory.
1444
-*/
1445
-cson_value * cson_value_new_string( char const * str, unsigned int n );
1446
-
1447
-/**
1448
- Allocates a new "object" value and transfers ownership of it to the
1449
- caller. It must eventually be destroyed, by the caller or its
1450
- owning container, by passing it to cson_value_free().
1451
-
1452
- Returns NULL on allocation error.
1453
-
1454
- Post-conditions: cson_value_is_object(value) will return true.
1455
-
1456
- @see cson_value_new_array()
1457
- @see cson_value_free()
1458
-*/
1459
-cson_value * cson_value_new_object( void );
1460
-
1461
-/**
1462
- This works like cson_value_new_object() but returns an Object
1463
- handle directly.
1464
-
1465
- The value handle for the returned object can be fetched with
1466
- cson_object_value(theObject).
1467
-
1468
- Ownership is transfered to the caller, who must eventually free it
1469
- by passing the Value handle (NOT the Object handle) to
1470
- cson_value_free() or passing ownership to a parent container.
1471
-
1472
- Returns NULL on error (out of memory).
1473
-*/
1474
-cson_object * cson_new_object( void );
1475
-
1476
-/**
1477
- Identical to cson_new_object() except that it creates
1478
- an Array.
1479
-*/
1480
-cson_array * cson_new_array( void );
1481
-
1482
-/**
1483
- Identical to cson_new_object() except that it creates
1484
- a String.
1485
-*/
1486
-cson_string * cson_new_string(char const * val, unsigned int len);
1487
-
1488
-/**
1489
- Equivalent to cson_value_free(cson_object_value(x)).
1490
-*/
1491
-void cson_free_object(cson_object *x);
1492
-
1493
-/**
1494
- Equivalent to cson_value_free(cson_array_value(x)).
1495
-*/
1496
-void cson_free_array(cson_array *x);
1497
-
1498
-/**
1499
- Equivalent to cson_value_free(cson_string_value(x)).
1500
-*/
1501
-void cson_free_string(cson_string *x);
1502
-
1503
-
1504
-/**
1505
- Allocates a new "array" value and transfers ownership of it to the
1506
- caller. It must eventually be destroyed, by the caller or its
1507
- owning container, by passing it to cson_value_free().
1508
-
1509
- Returns NULL on allocation error.
1510
-
1511
- Post-conditions: cson_value_is_array(value) will return true.
1512
-
1513
- @see cson_value_new_object()
1514
- @see cson_value_free()
1515
-*/
1516
-cson_value * cson_value_new_array( void );
1517
-
1518
-/**
1519
- Frees any resources owned by v, then frees v. If v is a container
1520
- type (object or array) its children are also freed (recursively).
1521
-
1522
- If v is NULL, this is a no-op.
1523
-
1524
- This function decrements a reference count and only destroys the
1525
- value if its reference count drops to 0. Reference counts are
1526
- increased by either inserting the value into a container or via
1527
- cson_value_add_reference(). Even if this function does not
1528
- immediately destroy the value, the value must be considered, from
1529
- the perspective of that client code, to have been
1530
- destroyed/invalidated by this call.
1531
-
1532
-
1533
- @see cson_value_new_object()
1534
- @see cson_value_new_array()
1535
- @see cson_value_add_reference()
1536
-*/
1537
-void cson_value_free(cson_value * v);
1538
-
1539
-/**
1540
- Alias for cson_value_free().
1541
-*/
1542
-void cson_free_value(cson_value * v);
1543
-
1544
-
1545
-/**
1546
- Functionally similar to cson_array_set(), but uses a string key
1547
- as an index. Like arrays, if a value already exists for the given key,
1548
- it is destroyed by this function before inserting the new value.
1549
-
1550
- If v is NULL then this call is equivalent to
1551
- cson_object_unset(obj,key). Note that (v==NULL) is treated
1552
- differently from v having the special null value. In the latter
1553
- case, the key is set to the special null value.
1554
-
1555
- The key may be encoded as ASCII or UTF8. Results are undefined
1556
- with other encodings, and the errors won't show up here, but may
1557
- show up later, e.g. during output.
1558
-
1559
- Returns 0 on success, non-0 on error. It has the folloSON
1560
-#ifndef CSONf obj or key are NULL or strlen(key) is 0.
1561
-
1562
- - cson_rc.AllocErrorturn true.
1563
-
1564
- @see cson_value_new_object()
1565
- @see cson_value_free()
1566
-*/
1567
-cson_value * cson_value_new_array( void );
1568
-
1569
-/**
1570
- Frees any resources owned by v, then frees v. If v is a container
1571
- type (object or array) its children are also freed (recursively).
1572
-
1573
- If v is NULL, this is a no-op.
1574
-
1575
- This function decrements a reference count and only destroys the
1576
- value if its reference count drops to 0. Reference counts are
1577
- increased by either inserting the value into a container or via
1578
- cson_value_add_reference(). Even if this function does not
1579
- immediately destroy the value, the value must be considered, from
1580
- the perspective of that client code, to have been
1581
- destroyed/invalidated by this call.
1582
-
1583
-
1584
- @see cson_value_new_object()
1585
- @see cson_value_new_array()
1586
- @see cson_value_add_reference()
1587
-*/
1588
-void cson_value_free(cson_value * v);
1589
-
1590
-/**
1591
- Alias for cson_value_free().
1592
-*/
1593
-void cson_free_value(cson_value * v);
1594
-
1595
-
1596
-/**
1597
- Functionally similar to cson_array_set(), but uses a string key
1598
- as an index. Like arrays, if a value already exists for the given key,
1599
- it is destroyed by this function before inserting the new value.
1600
-
1601
- If v is NULL then this call is equivalent to
1602
- cson_object_unset(obj,key). Note that (v==NULL) is treated
1603
- differently from v having the special null value. In the latter
1604
- case, the key is set to the special null value.
1605
-
1606
- The key may be encoded as ASCII or UTF8. Results are undefined
1607
- with other encodings, and the errors won't show up here, but may
1608
- show up later, e.g. during output.
1609
-
1610
- Returns 0 on success, non-0 on error. It has the following error
1611
- cases:
1612
-
1613
- - CSON_RC_ArgError: obj or kecson_rc. it is not found, CSON_RC_NotFoundError is returned (which can
1614
- normally be igSON
1615
-#ifndef CSON_FOSSIL_MODEf C obj or key are NULL or key has a length
1616
- of 0.
1617
-
1618
- This function reduces the returned value's reference count but has
1619
- the specific property that it does not treat refcounts 0 and 1
1620
- identically, meaning that the returned object may have a refcount
1621
- of 0. This behaviour works around a corner-case where we want to
1622
- extract a child element from its parent and then destroy the parent
1623
- (which leaves us in an undesireable (normally) reference count
1624
- state).
1625
-*/
1626
-cson_value * cson_object_take( cson_object * obj, char const * key );
1627
-
1628
-/**
1629
- Fetches a property from a child (or [great-]*grand-child) object.
1630
-
1631
- obj is the object to search.
1632
-
1633
- path is a delimited string, where the delimiter is the given
1634
- separator character.
1635
-
1636
- This function searches for the given path, starting at the given object
1637
- and traversing its properties as the path specifies. If a given part of the
1638
- path is not found, then this function fails with CSON_RC_NotFoundError.
1639
-
1640
- If it finds the given path, it returns the value by assiging *tgt
1641
- to it. If tgt is NULL then this function has no side-effects but
1642
- will return 0 if the given path is found within the object, so it can be used
1643
- to test for existence without fetching it.
1644
-
1645
- Returns 0 if it finds an entry, CSON_RC_NotFoundError if it finds
1646
- no item, and any other non-zero error code on a "real" error. Errors include:
1647
-
1648
- - obj or path are NULL: CSON_RC_ArgError
1649
-
1650
- - separator is 0, or path is an empty string or contains only
1651
- separator characters: CSON_RC_RangeError
1652
-
1653
- - There is an upper limit on how long a single path component may
1654
- be (some "reasonable" internal size), and CSON_RC_RangeError is
1655
- returned if that length is violated.
1656
-
1657
-
1658
- Limitations:
1659
-
1660
- - It has no way to fetch data from arrays this way. i could
1661
- imagine, e.g., a path of "subobj.subArray.0" for
1662
- subobj.subArray[0], or "0.3.1" for [0][3][1]. But i'm too
1663
- lazy/tired to add this.
1664
-
1665
- Example usage:
1666
-
1667
-
1668
- Assume we have a JSON structure which abstractly looks like:
1669
-
1670
- @code
1671
- {"subobj":{"subsubobj":{"myValue":[1,2,3]}}}
1672
- @endcode
1673
-
1674
- Out goal is to get the value of myValue. We can do that with:
1675
-
1676
- @code
1677
- cson_value * v = NULL;
1678
- int rc = cson_object_fetch_sub( object, &v, "subobj.subsubobj.myValue", '.' );
1679
- @endcode
1680
-
1681
- Note that because keys in JSON may legally contain a '.', the
1682
- separator must be specified by the caller. e.g. the path
1683
- "subobj/subsubobj/myValue" with separator='/' is equivalent the
1684
- path "subobj.subsubobj.myValue" with separator='.'. The value of 0
1685
- is not legal as a separator character because we cannot
1686
- distinguish that use from the real end-of-string without requiring
1687
- the caller to also pass in the length of the string.
1688
-
1689
- Multiple successive separators in the list are collapsed into a
1690
- single separator for parsing purposes. e.g. the path "a...b...c"
1691
- (separator='.') is equivalent to "a.b.c".
1692
-
1693
- @see cson_object_get_sub()
1694
- @see cson_object_get_sub2()
1695
-*/
1696
-int cson_object_fetch_sub( cson_object const * obj, cson_value ** tgt, char const * path, char separator );
1697
-
1698
-/**
1699
- Similar to cson_object_fetch_sub(), but derives the path separator
1700
- character from the first byte of the path argument. e.g. the
1701
- following arg equivalent:
1702
-
1703
- @code
1704
- cson_object_fetch_sub( obj, &tgt, "foo.bar.baz", '.' );
1705
- cson_object_fetch_sub2( obj, &tgt, ".foo.bar.baz" );
1706
- @endcode
1707
-*/
1708
-int cson_object_fetch_sub2( cson_object const * obj, cson_value ** tgt, char const * path );
1709
-
1710
-/**
1711
- Convenience form of cson_object_fetch_sub() which returns NULL if the given
1712
- item is not found.
1713
-*/
1714
-cson_value * cson_object_get_sub( cson_object const * obj, char const * path, char sep );
1715
-
1716
-/**
1717
- Convenience form of cson_object_fetch_sub2() which returns NULL if the given
1718
- item is not found.
1719
-*/
1720
-cson_value * cson_object_get_sub2( cson_object const * obj, char const * path );
1721
-
1722
-/** @enum CSON_MERGE_FLAGS
1723
-
1724
- Flags for cson_object_merge().
1725
-*/
1726
-enum CSON_MERGE_FLAGS {
1727
- CSON_MERGE_DEFAULT = 0,
1728
- CSON_MERGE_REPLACE = 0x01,
1729
- CSON_MERGE_NO_RECURSE = 0x02
1730
-};
1731
-
1732
-/**
1733
- "Merges" the src object's properties into dest. Each property in
1734
- src is copied (using reference counting, not cloning) into dest. If
1735
- dest already has the given property then behaviour depends on the
1736
- flags argument:
1737
-
1738
- If flag has the CSON_MERGE_REPLACE bit set then this function will
1739
- by default replace non-object properties with the src property. If
1740
- src and dest both have the property AND it is an Object then this
1741
- function operates recursively on those objects. If
1742
- CSON_MERGE_NO_RECURSE is set then objects are not recursed in this
1743
- manner, and will be completely replaced if CSON_MERGE_REPLACE is
1744
- set.
1745
-
1746
- Array properties in dest are NOT recursed for merging - they are
1747
- either replaced or left as-is, depending on whether flags contains
1748
- he CSON_MERGE_REPLACE bit.
1749
-
1750
- Returns 0 on success. The error conditions are:
1751
-
1752
- - dest or src are NULL or (dest==src) returns CSON_RC_ArgError.
1753
-
1754
- - dest or src contain cyclic references - this will likely cause a
1755
- crash due to endless recursion.
1756
-
1757
- Potential TODOs:
1758
-
1759
- - Add a flag to copy clones, not the original values.
1760
-*/
1761
-int cson_object_merge( cson_object * dest, cson_object const * src, int flags );
1762
-
1763
-
1764
-/**
1765
- An iterator type for traversing object properties.
1766
-
1767
- Its values must be considered private, not to be touched by client
1768
- code.
1769
-
1770
- @see cson_object_iter_init()
1771
- @see cson_object_iter_next()
1772
-*/
1773
-struct cson_object_iterator
1774
-{
1775
-
1776
- /** @internal
1777
- The underlying object.
1778
- */
1779
- cson_object const * obj;
1780
- /** @internal
1781
- Current position in the property list.
1782
- */
1783
- unsigned int pos;
1784
-};
1785
-typedef struct cson_object_iterator cson_object_iterator;
1786
-
1787
-/**
1788
- Empty-initialized cson_object_iterator object.
1789
-*/
1790
-#define cson_object_iterator_empty_m {NULL/*obj*/,0/*pos*/}
1791
-
1792
-/**
1793
- Empty-initialized cson_object_iterator object.
1794
-*/
1795
-extern const cson_object_iterator cson_object_iterator_empty;
1796
-
1797
-/**
1798
- Initializes the given iterator to point at the start of obj's
1799
- properties. Returns 0 on success or CSON_RC_ArgError if !obj
1800
- or !iter.
1801
-
1802
- obj must outlive iter, or results are undefined. Results are also
1803
- undefined if obj is modified while the iterator is active.
1804
-
1805
- @see cson_object_iter_next()
1806
-*/
1807
-int cson_object_iter_init( cson_object const * obj, cson_object_iterator * iter );
1808
-
1809
-/** @struct cson_kvp
1810
-
1811
-This class represents a key/value pair and is used for storing
1812
-object properties. It is opaque to client code, and the public
1813
-API only uses this type for purposes of iterating over cson_object
1814
-properties using the cson_object_iterator interfaces.
1815
-*/
1816
-
1817
-typedef struct cson_kvp cson_kvp;
1818
-
1819
-/**
1820
- Returns the next property from the given iterator's object, or NULL
1821
- if the end of the property list as been reached.
1822
-
1823
- Note that the order of object properties is undefined by the API,
1824
- and may change from version to version.
1825
-
1826
- The returned memory belongs to the underlying object and may be
1827
- invalidated by any changes to that object.
1828
-
1829
- Example usage:
1830
-
1831
- @code
1832
- cson_object_iterator it;
1833
- cson_object_iter_init( myObject, &it ); // only fails if either arg is 0
1834
- cson_kvp * kvp;
1835
- cson_string const * key;
1836
- cson_value const * val;
1837
- while( (kvp = cson_object_iter_next(&it) ) )
1838
- {
1839
- key = cson_kvp_key(kvp);
1840
- val = cson_kvp_value(kvp);
1841
- ...
1842
- }
1843
- @endcode
1844
-
1845
- There is no need to clean up an iterator, as it holds no dynamic resources.
1846
-
1847
- @see cson_kvp_key()
1848
- @see cson_kvp_value()
1849
-*/
1850
-cson_kvp * cson_object_iter_next( cson_object_iterator * iter );
1851
-
1852
-
1853
-/**
1854
- Returns the key associated with the given key/value pair,
1855
- or NULL if !kvp. The memory is owned by the object which contains
1856
- the key/value pair, and may be invalidated by any modifications
1857
- to that object.
1858
-*/
1859
-cson_string * cson_kvp_key( cson_kvp const * kvp );
1860
-
1861
-/**
1862
- Returns the value associated with the given key/value pair,
1863
- or NULL if !kvp. The memory is owned by the object which contains
1864
- the key/value pair, and may be invalidated by any modifications
1865
- to that object.
1866
-*/
1867
-cson_value * cson_kvp_value( cson_kvp const * kvp );
1868
-
1869
-/** @typedef some unsigned int type cson_size_t
1870
-
1871
-*/
1872
-typedef unsigned int cson_size_t;
1873
-
1874
-/**
1875
- A generic buffer class.
1876
-
1877
- They can be used like this:
1878
-
1879
- @code
1880
- cson_buffer b = cson_buffer_empty;
1881
- int rc = cson_buffer_reserve( &buf, 100 );
1882
- if( 0 != rc ) { ... allocation error ... }
1883
- ... use buf.mem ...
1884
- ... then free it up ...
1885
- cson_buffer_reserve( &buf, 0 );
1886
- @endcode
1887
-
1888
- To take over ownership of a buffer's memory:
1889
-
1890
- @code
1891
- void * mem = b.mem;
1892
- // mem is b.capacity bytes long, but only b.used
1893
- // bytes of it has been "used" by the API.
1894
- b = cson_buffer_empty;
1895
- @endcode
1896
-
1897
- The memory now belongs to the caller and must eventually be
1898
- free()d.
1899
-*/
1900
-struct cson_buffer
1901
-{
1902
- /**
1903
- The number of bytes allocated for this object.
1904
- Use cson_buffer_reserve() to change its value.
1905
- */
1906
- cson_size_t capacity;
1907
- /**
1908
- The number of bytes "used" by this object. It is not needed for
1909
- all use cases, and management of this value (if needed) is up
1910
- to the client. The cson_buffer public API does not use this
1911
- member. The intention is that this can be used to track the
1912
- length of strings which are allocated via cson_buffer, since
1913
- they need an explicit length and/or null terminator.
1914
- */
1915
- cson_size_t used;
1916
-
1917
- /**
1918
- This is a debugging/metric-counting value
1919
- intended to help certain malloc()-conscious
1920
- clients tweak their memory reservation sizes.
1921
- Each time cson_buffer_reserve() expands the
1922
- buffer, it increments this value by 1.
1923
- */
1924
- cson_size_t timesExpanded;
1925
-
1926
- /**
1927
- The memory allocated for and owned by this buffer.
1928
- Use cson_buffer_reserve() to change its size or
1929
- free it. To take over ownership, do:
1930
-
1931
- @code
1932
- void * myptr = buf.mem;
1933
- buf = cson_buffer_empty;
1934
- @endcode
1935
-
1936
- (You might also need to store buf.used and buf.capacity,
1937
- depending on what you want to do with the memory.)
1938
-
1939
- When doing so, the memory must eventually be passed to free()
1940
- to deallocate it.
1941
- */
1942
- unsigned char * mem;
1943
-};
1944
-/** Convenience typedef. */
1945
-typedef struct cson_buffer cson_buffer;
1946
-
1947
-/** An empty-initialized cson_buffer object. */
1948
-#define cson_buffer_empty_m {0/*capacity*/,0/*used*/,0/*timesExpanded*/,NULL/*mem*/}
1949
-/** An empty-initialized cson_buffer object. */
1950
-extern const cson_buffer cson_buffer_empty;
1951
-
1952
-/**
1953
- Uses cson_output() to append all JSON output to the given buffer
1954
- object. The semantics for the (v, opt) parameters, and the return
1955
- value, are as documented for cson_output(). buf must be a non-NULL
1956
- pointer to a properly initialized buffer (see example below).
1957
-
1958
- Ownership of buf is not changed by calling this.
1959
-
1960
- On success 0 is returned and the contents of buf.mem are guaranteed
1961
- to be NULL-terminated. On error the buffer might contain partial
1962
- contents, and it should not be used except to free its contents.
1963
-
1964
- On error non-zero is returned. Errors include:
1965
-
1966
- - Invalid arguments: CSON_RC_ArgError
1967
-
1968
- - Buffer cannot be expanded (runs out of memory): CSON_RC_AllocError
1969
-
1970
- Example usage:
1971
-
1972
- @code
1973
- cson_buffer buf = cson_buffer_empty;
1974
- // optional: cson_buffer_reserve(&buf, 1024 * 10);
1975
- int rc = cson_output_buffer( myValue, &buf, NULL );
1976
- if( 0 != rc ) {
1977
- ... error! ...
1978
- }
1979
- else {
1980
- ... use buffer ...
1981
- puts((char const*)buf.mem);
1982
- }
1983
- // In both cases, we eventually need to clean up the buffer:
1984
- cson_buffer_reserve( &buf, 0 );
1985
- // Or take over ownership of its memory:
1986
- {
1987
- char * mem = (char *)buf.mem;
1988
- buf = cson_buffer_empty;
1989
- ...
1990
- free(mem);
1991
- }
1992
- @endcode
1993
-
1994
- @see cson_output()
1995
-
1996
-*/
1997
-int cson_output_buffer( cson_value const * v, cson_buffer * buf,
1998
- cson_output_opt const * opt );
1999
-
2000
-/**
2001
- This works identically to cson_parse_string(), but takes a
2002
- cson_buffer object as its input. buf->used bytes of buf->mem are
2003
- assumed to be valid JSON input, but it need not be NUL-terminated
2004
- (we only read up to buf->used bytes). The value of buf->used is
2005
- assumed to be the "string length" of buf->mem, i.e. not including
2006
- the NUL terminator.
2007
-
2008
- Returns 0 on success, non-0 on error.
2009
-
2010
- See cson_parse() for the semantics of the tgt, opt, and err
2011
- parameters.
2012
-*/
2013
-int cson_parse_buffer( cson_value ** tgt, cson_buffer const * buf,
2014
- cson_parse_opt const * opt, cson_parse_info * err );
2015
-
2016
-
2017
-/**
2018
- Reserves the given amount of memory for the given buffer object.
2019
-
2020
- If n is 0 then buf->mem is freed and its state is set to
2021
- NULL/0 values.
2022
-
2023
- If buf->capacity is less than or equal to n then 0 is returned and
2024
- buf is not modified.
2025
-
2026
- If n is larger than buf->capacity then buf->mem is (re)allocated
2027
- and buf->capacity contains the new length. Newly-allocated bytes
2028
- are filled with zeroes.
2029
-
2030
- On success 0 is returned. On error non-0 is returned and buf is not
2031
- modified.
2032
-
2033
- buf->mem is owned by buf and must eventually be freed by passing an
2034
- n value of 0 to this function.
2035
-
2036
- buf->used is never modified by this function unless n is 0, in which case
2037
- it is reset.
2038
-*/
2039
-int cson_buffer_reserve( cson_buffer * buf, cson_size_t n );
2040
-
2041
-/**
2042
- Fills all bytes of the given buffer with the given character.
2043
- Returns the number of bytes set (buf->capacity), or 0 if
2044
- !buf or buf has no memory allocated to it.
2045
-*/
2046
-cson_size_t cson_buffer_fill( cson_buffer * buf, char c );
2047
-
2048
-/**
2049
- Uses a cson_data_source_f() function to buffer input into a
2050
- cson_buffer.
2051
-
2052
- dest must be a non-NULL, initialized (though possibly empty)
2053
- cson_buffer object. Its contents, if any, will be overwritten by
2054
- this function, and any memory it holds might be re-used.
2055
-
2056
- The src function is called, and passed the state parameter, to
2057
- fetch the input. If it returns non-0, this function returns that
2058
- error code. src() is called, possibly repeatedly, until it reports
2059
- that there is no more data.
2060
-
2061
- Whether or not this function succeeds, dest still owns any memory
2062
- pointed to by dest->mem, and the client must eventually free it by
2063
- calling cson_buffer_reserve(dest,0).
2064
-
2065
- dest->mem might (and possibly will) be (re)allocated by this
2066
- function, so any pointers to it held from before this call might be
2067
- invalidated by this call.
2068
-
2069
- On error non-0 is returned and dest has almost certainly been
2070
- modified but its state must be considered incomplete.
2071
-
2072
- Errors include:
2073
-
2074
- - dest or src are NULL (CSON_RC_ArgError)
2075
-
2076
- - Allocation error (CSON_RC_AllocError)
2077
-
2078
- - src() returns an error code
2079
-
2080
- Whether or not the state parameter may be NULL depends on
2081
- the src implementation requirements.
2082
-
2083
- On success dest will contain the contents read from the input
2084
- source. dest->used will be the length of the read-in data, and
2085
- dest->mem will point to the memory. dest->mem is automatically
2086
- NUL-terminated if this function succeeds, but dest->used does not
2087
- count that terminator. On error the state of dest->mem must be
2088
- considered incomplete, and is not guaranteed to be NUL-terminated.
2089
-
2090
- Example usage:
2091
-
2092
- @code
2093
- cson_buffer buf = cson_buffer_empty;
2094
- int rc = cson_buffer_fill_from( &buf,
2095
- cson_data_source_FILE,
2096
- stdin );
2097
- if( rc )
2098
- {
2099
- fprintf(stderr,"Error %d (%s) while filling buffer.\n",
2100
- rc, cson_rc_string(rc));
2101
- cson_buffer_reserve( &buf, 0 );
2102
- return ...;
2103
- }
2104
- ... use the buf->mem ...
2105
- ... clean up the buffer ...
2106
- cson_buffer_reserve( &buf, 0 );
2107
- @endcode
2108
-
2109
- To take over ownership of the buffer's memory, do:
2110
-
2111
- @code
2112
- void * mem = buf.mem;
2113
- buf = cson_buffer_empty;
2114
- @endcode
2115
-
2116
- In which case the memory must eventually be passed to free() to
2117
- free it.
2118
-*/
2119
-int cson_buffer_fill_from( cson_buffer * dest, cson_data_source_f src, void * state );
2120
-
2121
-
2122
-/**
2123
- Increments the reference count for the given value. This is a
2124
- low-level operation and should not normally be used by client code
2125
- without understanding exactly what side-effects it introduces.
2126
- Mis-use can lead to premature destruction or cause a value instance
2127
- to never be properly destructed (i.e. a memory leak).
2128
-
2129
- This function is probably only useful for the following cases:
2130
-
2131
- - You want to hold a reference to a value which is itself contained
2132
- in one or more containers, and you need to be sure that your
2133
- reference outlives the container(s) and/or that you can free your
2134
- copy of the reference without invaliding any references to the same
2135
- value held in containers.
2136
-
2137
- - You want to implement "value sharing" behaviour without using an
2138
- object or array to contain the shared value. This can be used to
2139
- ensure the lifetime of the shared value instance. Each sharing
2140
- point adds a reference and simply passed the value to
2141
- cson_value_free() when they're done. The object will be kept alive
2142
- for other sharing points which added a reference.
2143
-
2144
- Normally any such value handles would be invalidated when the
2145
- parent container(s) is/are cleaned up, but this function can be
2146
- used to effectively delay the cleanup.
2147
-
2148
- This function, at its lowest level, increments the value's
2149
- reference count by 1.
2150
-
2151
- To decrement the reference count, pass the value to
2152
- cson_value_free(), after which the value must be considered, from
2153
- the perspective of that client code, to be destroyed (though it
2154
- will not be if there are still other live references to
2155
- it). cson_value_free() will not _actually_ destroy the value until
2156
- its reference count drops to 0.
2157
-
2158
- Returns 0 on success. The only error conditions are if v is NULL
2159
- (CSON_RC_ArgError) or if the reference increment would overflow
2160
- (CSON_RC_RangeError). In theory a client would get allocation
2161
- errors long before the reference count could overflow (assuming
2162
- those reference counts come from container insertions, as opposed
2163
- to via this function).
2164
-
2165
- Insider notes which clients really need to know:
2166
-
2167
- For shared/constant value instances, such as those returned by
2168
- cson_value_true() and cson_value_null(), this function has no side
2169
- effects - it does not actually modify the reference count because
2170
- (A) those instances are shared across all client code and (B) those
2171
- objects are static and never get cleaned up. However, that is an
2172
- implementation detail which client code should not rely on. In
2173
- other words, if you call cson_value_add_reference() 3 times using
2174
- the value returned by cson_value_true() (which is incidentally a
2175
- shared cson_value instance), you must eventually call
2176
- cson_value_free() 3 times to (semantically) remove those
2177
- references. However, internally the reference count for that
2178
- specific cson_value instance will not be modified and those
2179
- objects will never be freed (they're stack-allocated).
2180
-
2181
- It might be interesting to note that newly-created objects
2182
- have a reference count of 0 instead of 1. This is partly because
2183
- if the initial reference is counted then it makes ownership
2184
- problematic when inserting values into containers. e.g. consider the
2185
- following code:
2186
-
2187
- @code
2188
- // ACHTUNG: this code is hypothetical and does not reflect
2189
- // what actually happens!
2190
- cson_value * v =
2191
- cson_value_new_integer( 42 ); // v's refcount = 1
2192
- cson_array_append( myArray, v ); // v's refcount = 2
2193
- @endcode
2194
-
2195
- If that were the case, the client would be forced to free his own
2196
- reference after inserting it into the container (which is a bit
2197
- counter-intuitive as well as intrusive). It would look a bit like
2198
- the following and would have to be done after every create/insert
2199
- operation:
2200
-
2201
- @code
2202
- // ACHTUNG: this code is hypothetical and does not reflect
2203
- // what actually happens!
2204
- cson_array_append( myArray, v ); // v's refcount = 2
2205
- cson_value_free( v ); // v's refcount = 1
2206
- @endcode
2207
-
2208
- (As i said: it's counter-intuitive and intrusive.)
2209
-
2210
- Instead, values start with a refcount of 0 and it is only increased
2211
- when the value is added to an object/array container or when this
2212
- function is used to manually increment it. cson_value_free() treats
2213
- a refcount of 0 or 1 equivalently, destroying the value
2214
- instance. The only semantic difference between 0 and 1, for
2215
- purposes of cleaning up, is that a value with a non-0 refcount has
2216
- been had its refcount adjusted, whereas a 0 refcount indicates a
2217
- fresh, "unowned" reference.
2218
-*/
2219
-int cson_value_add_reference( cson_value * v );
2220
-
2221
-#if 0
2222
-/**
2223
- DO NOT use this unless you know EXACTLY what you're doing.
2224
- It is only in the public API to work around a couple corner
2225
- cases involving extracting child elements and discarding
2226
- their parents.
2227
-
2228
- This function sets v's reference count to the given value.
2229
- It does not clean up the object if rc is 0.
2230
-
2231
- Returns 0 on success, non-0 on error.
2232
-*/
2233
-int cson_value_refcount_set( cson_value * v, unsigned short rc );
2234
-#endif
2235
-
2236
-/**
2237
- Deeply copies a JSON value, be it an object/array or a "plain"
2238
- value (e.g. number/string/boolean). If cv is not NULL then this
2239
- function makes a deep clone of it and returns that clone. Ownership
2240
- of the clone is identical t transfered to the caller, who must
2241
- eventually free the value using cson_value_free() or add it to a
2242
- container object/array to transfer ownership to the container. The
2243
- returned object will be of the same logical type as orig.
2244
-
2245
- ACHTUNG: if orig contains any cyclic references at any depth level
2246
- this function will endlessly recurse. (Having _any_ cyclic
2247
- references violates this library's requirements.)
2248
-
2249
- Returns NULL if orig is NULL or if cloning fails. Assuming that
2250
- orig is in a valid state, the only "likely" error case is that an
2251
- allocation fails while constructing the clone. In other words, if
2252
- cloning fails due to something other than an allocation error then
2253
- either orig is in an invalid state or there is a bug.
2254
-
2255
- When this function clones Objects or Arrays it shares any immutable
2256
- values (including object keys) between the parent and the
2257
- clone. Mutable values (Objects and Arrays) are copied, however.
2258
- For example, if we clone:
2259
-
2260
- @code
2261
- { a: 1, b: 2, c:["hi"] }
2262
- @endcode
2263
-
2264
- The cloned object and the array "c" would be a new Object/Array
2265
- instances but the object keys (a,b,b) and the values of (a,b), as
2266
- well as the string value within the "c" array, would be shared
2267
- between the original and the clone. The "c" array itself would be
2268
- deeply cloned, such that future changes to the clone are not
2269
- visible to the parent, and vice versa, but immutable values within
2270
- the array are shared (in this case the string "hi"). The
2271
- justification for this heuristic is that immutable values can never
2272
- be changed, so there is no harm in sharing them across
2273
- clones. Additionally, such types can never contribute to cycles in
2274
- a JSON tree, so they are safe to share this way. Objects and
2275
- Arrays, on the other hand, can be modified later and can contribute
2276
- to cycles, and thus the clone needs to be an independent instance.
2277
- Note, however, that if this function directly passed a
2278
- non-Object/Array, that value is deeply cloned. The sharing
2279
- behaviour only applies when traversing Objects/Arrays.
2280
-*/
2281
-cson_value * cson_value_clone( cson_value const * orig );
2282
-
2283
-/**
2284
- Returns the value handle associated with s. The handle itself owns
2285
- s, and ownership of the handle is not changed by calling this
2286
- function. If the returned handle is part of a container, calling
2287
- cson_value_free() on the returned handle invoked undefined
2288
- behaviour (quite possibly downstream when the container tries to
2289
- use it).
2290
-
2291
- This function only returns NULL if s is NULL. The length of the
2292
- returned string is cson_string_length_bytes().
2293
-*/
2294
-cson_value * cson_string_value(cson_string const * s);
2295
-/**
2296
- The Object form of cson_string_value(). See that function
2297
- for full details.
2298
-*/
2299
-cson_value * cson_object_value(cson_object const * s);
2300
-
2301
-/**
2302
- The Array form of cson_string_value(). See that function
2303
- for full details.
2304
-*/
2305
-cson_value * cson_array_value(cson_array const * s);
2306
-
2307
-
2308
-/**
2309
- Calculates the approximate in-memory-allocated size of v,
2310
- recursively if it is a container type, with the following caveats
2311
- and limitations:
2312
-
2313
- If a given value is reference counted and encountered multiple
2314
- times within a traversed container, each reference is counted at
2315
- full cost. We have no way of knowing if a given reference has been
2316
- visited already and whether it should or should not be counted, so
2317
- we pessimistically count them even though the _might_ not really
2318
- count for the given object tree (it depends on where the other open
2319
- references live).
2320
-
2321
- This function returns 0 if any of the following are true:
2322
-
2323
- - v is NULL
2324
-
2325
- - v is one of the special singleton values (null, bools, empty
2326
- string, int 0, double 0.0)
2327
-
2328
- All other values require an allocation, and this will return their
2329
- total memory cost, including the cson-specific internals and the
2330
- native value(s).
2331
-
2332
- Note that because arrays and objects might have more internal slots
2333
- allocated than used, the alloced size of a container does not
2334
- necessarily increase when a new item is inserted into it. An interesting
2335
- side-effect of this is that when cson_clone()ing an array or object, the
2336
- size of the clone can actually be less than the original.
2337
-*/
2338
-unsigned int cson_value_msize(cson_value const * v);
2339
-
2340
-/**
2341
- Parses command-line-style arguments into a JSON object.
2342
-
2343
- It expects arguments to be in any of these forms, and any number
2344
- of leading dashes are treated identically:
2345
-
2346
- --key : Treats key as a boolean with a true value.
2347
-
2348
- --key=VAL : Treats VAL as either a double, integer, or string.
2349
-
2350
- --key= : Treats key as a JSON null (not literal NULL) value.
2351
-
2352
- Arguments not starting with a dash are skipped.
2353
-
2354
- Each key/value pair is inserted into an object. If a given key
2355
- appears more than once then only the final entry is actually
2356
- stored.
2357
-
2358
- argc and argv are expected to be values from main() (or similar,
2359
- possibly adjusted to remove argv[0]).
2360
-
2361
- tgt must be either a pointer to NULL or a pointer to a
2362
- client-provided Object. If (NULL==*tgt) then this function
2363
- allocates a new object and on success it stores the new object in
2364
- *tgt (it is owned by the caller). If (NULL!=*tgt) then it is
2365
- assumed to be a properly allocated object. DO NOT pass a pointer to
2366
- an unitialized pointer, as that will fool this function into
2367
- thinking it is a valid object and Undefined Behaviour will ensue.
2368
-
2369
- If count is not NULL then the number of arugments parsed by this
2370
- function are assigned to it. On error, count will be the number of
2371
- options successfully parsed before the error was encountered.
2372
-
2373
- On success:
2374
-
2375
- - 0 is returned.
2376
-
2377
- - If (*tgt==NULL) then *tgt is assigned to a newly-allocated
2378
- object, owned by the caller. Note that even if no arguments are
2379
- parsed, the object is still created.
2380
-
2381
- On error:
2382
-
2383
- - non-0 is returned
2384
-
2385
- - If (*tgt==NULL) then it is not modified.
2386
-
2387
- - If (*tgt!=NULL) (i.e., the caller provides his own object) then
2388
- it might contain partial results.
2389
-*/
2390
-int cson_parse_argv_flags( int argc, char const * const * argv,
2391
- cson_object ** tgt, unsigned int * count );
2392
-
2393
-/**
2394
- Return values for the cson_pack() and cson_unpack() interfaces.
2395
-*/
2396
-enum cson_pack_retval {
2397
- /** Signals an out-of-memory error. */
2398
- CSON_PACK_ALLOC_ERROR = -1,
2399
- /** Signals a syntax error in the format string. */
2400
- CSON_PACK_ARG_ERROR = -2,
2401
- /**
2402
- Signals an that an internal error has occurred.
2403
- This indicates a bug in this library.
2404
- */
2405
- CSON_PACK_INTERNAL_ERROR = -3,
2406
- /**
2407
- Signals that the JSON document does not validate agains the format
2408
- string passed to cson_unpack().
2409
- */
2410
- CSON_PACK_VALIDATION_ERROR = -4
2411
-};
2412
-
2413
-/**
2414
- Construct arbitrarily complex JSON documents from native C types.
2415
-
2416
- Create a new object or array and add or merge the passed values and
2417
- properties to it according to the supplied format string.
2418
-
2419
- fmt is a format string, it must at least contain an array or object
2420
- specifier as its root value. Format specifiers start with a percent sign '\%'
2421
- followed by one or more modifiers and a type character. Object properties
2422
- are specified as key-value pairs where the key is specified as a string and
2423
- passed as an argument of const char *. Any space, tab, carriage return, line
2424
- feed, colon and comma characters between format specifiers are ignored.
2425
-
2426
- | Type | Description |
2427
- | :--: | :---------- |
2428
- | s | creates either a property name or a string value, in case of the former the corresponding argument is a pointer to const char which is a sequence of bytes specifying the name of the property that is to be created, in case of the latter the corresponding argument is a pointer to const char |
2429
- | d | creates an integer value, the corresponding argument is an int |
2430
- | i | ^ |
2431
- | f | creates a floating point value, the corresponding argument is a double |
2432
- | b | creates a boolean value, the corresponding argument is an int |
2433
- | N | creates a null value |
2434
- | [...] | creates an array, the corresponding argument is a pointer to a cson_array |
2435
- | {...} | creates an array, the corresponding argument is a pointer to a cson_object |
2436
-
2437
- | Modifier | Description |
2438
- | :------: | :---------- |
2439
- | l | specifies that the following d or i specifier applies to an argument which is a pointer to long |
2440
- | ll | specifies that the following d or i specifier applies to an argument which is a pointer to cson_int_t |
2441
-
2442
- | Short Form | Expands to
2443
- | :--------: | :--------- |
2444
- | {...} | %*{...} |
2445
- | [...] | %*[...] |
2446
- | \%D | \%lld |
2447
-
2448
-
2449
- Returns 0 on success. The error conditions are:
2450
-
2451
- - CSON_PACK_ARG_ERROR: fmt contains a syntax error
2452
-
2453
- - CSON_PACK_ALLOC_ERROR: a memory allocation failed
2454
-
2455
- - CSON_PACK_INTERNAL_ERROR: an internal error has occurred, this is a bug in
2456
- cson
2457
-
2458
- Example:
2459
- @code
2460
- cson_value * root_value;
2461
- cson_array * arr;
2462
- ...
2463
- rc = cson_pack( root_value, "{%s: %d, %s: %[]}", "foo", 42, "bar", arr );
2464
- if( 0 != rc ) {
2465
- ... error ...
2466
- }
2467
- @endcode
2468
-*/
2469
-int cson_pack( cson_value **root_valuep, const char *fmt, ... );
2470
-
2471
-/**
2472
- Same as cson_pack() except that it takes a va_list instead of a variable
2473
- number of arguments.
2474
-*/
2475
-int cson_vpack( cson_value **root_valuep, const char *fmt, va_list args );
2476
-
2477
-/**
2478
- Iterate over the given object or array and convert an arbitrary number of
2479
- JSON values into their native C types or validates them according to the
2480
- given format string fmt.
2481
-
2482
- fmt is a format string, it must at least contain an array or object
2483
- specifier as its root value. Format specifiers start with a percent sign '\%'
2484
- followed by one or more modifiers and a type character. Object properties
2485
- are specified as key-value pairs where the key is specified as a string and
2486
- passed as an argument of const char *. Any space, tab, carriage return, line
2487
- feed, colon and comma characters between format specifiers are ignored.
2488
-
2489
- | Type | Description |
2490
- | :--: | :---------- |
2491
- | s | matches a either a property name or a string value, in case of the former the corresponding argument is a pointer to const char which is a sequence of bytes specifying the name of the property that is to be matched, in case of the latter the corresponding argument is a pointer to a pointer to const char unless the 'm' modifier is specified where the the corresponding argument is a pointer to a pointer to char |
2492
- | d | matches an integer value and must be used in with the "ll" modifier, the corresponding argument is a pointer to cson_int_t |
2493
- | i | ^ |
2494
- | f | matches a floating point value, the corresponding argument is a pointer to double |
2495
- | b | matches a boolean value, the corresponding argument is a pointer to int |
2496
- | N | matches a null value |
2497
- | [...] | matches an array, the corresponding argument is a pointer to a pointer to a cson_array |
2498
- | {...} | matches an array, the corresponding argument is a pointer to a pointer to a cson_object |
2499
-
2500
- | Modifier | Description |
2501
- | :------: | :---------- |
2502
- | ? | specifies that the property reffered to by the given property name is optional |
2503
- | * | suppresses assignment, only check for the presence and type of the specified value |
2504
- | m | allocates a memory buffer for the extracted string |
2505
- | ll | specifies that the following d or i specifier applies to an argument which is a pointer to cson_int_t |
2506
-
2507
- | Short Form | Expands to
2508
- | :--------: | :--------- |
2509
- | {...} | %*{...} |
2510
- | [...] | %*[...] |
2511
- | \%D | \%lld |
2512
-
2513
- Returns 0 on success. The error conditions are:
2514
-
2515
- - CSON_PACK_ARG_ERROR: fmt contains a syntax error
2516
-
2517
- - CSON_PACK_ALLOC_ERROR: a memory allocation failed
2518
-
2519
- - CSON_PACK_VALIDATION_ERROR: validation failed, the JSON document structure
2520
- differs from that described by the format string
2521
-
2522
- - CSON_PACK_INTERNAL_ERROR: an internal error has occurred, this
2523
- indicates a bug in this library.
2524
-
2525
- Example:
2526
- @code
2527
- cson_value * root_value;
2528
- cson_int_t x = 0;
2529
- cson_array * arr = NULL;
2530
- const char *str = NULL;
2531
- ...
2532
- rc = cson_unpack( root_value, "{%s: %d, %s: %[], %?s: %s}", "foo", &x, "bar", &arr, "baz", &str );
2533
- if( rc < 3 && rc >= 0 ) {
2534
- ... optional property is missing ...
2535
- } else if ( CSON_PACK_ALLOC_ERROR == rc ) {
2536
- ... out of memory error ...
2537
- } else if ( CSON_PACK_VALIDATION_ERROR == rc ) {
2538
- ... unexpected JSON document structure ...
2539
- } else if ( rc ) {
2540
- ... internal error ...
2541
- }
2542
- @endcode
2543
-
2544
-*/
2545
-int cson_unpack( cson_value *root_value, const char *fmt, ... );
2546
-
2547
-/**
2548
- Same as cson_unpack() except that it takes a va_list instead of a variable
2549
- number of arguments.
2550
-*/
2551
-int cson_vunpack( cson_value *root_value, const char *fmt, va_list args );
2552
-
2553
-/* LICENSE
2554
-
2555
-This software's source code, including accompanying documentation and
2556
-demonstration applications, are licensed under the following
2557
-conditions...
2558
-
2559
-Certain files are imported from external projects and have their own
2560
-licensing terms. Namely, the JSON_parser.* files. See their files for
2561
-their official licenses, but the summary is "do what you want [with
2562
-them] but leave the license text and copyright in place."
2563
-
2564
-The author (Stephan G. Beal [http://wanderinghorse.net/home/stephan/])
2565
-explicitly disclaims copyright in all jurisdictions which recognize
2566
-such a disclaimer. In such jurisdictions, this software is released
2567
-into the Public Domain.
2568
-
2569
-In jurisdictions which do not recognize Public Domain property
2570
-(e.g. Germany as of 2011), this software is Copyright (c) 2011 by
2571
-Stephan G. Beal, and is released under the terms of the MIT License
2572
-(see below).
2573
-
2574
-In jurisdictions which recognize Public Domain property, the user of
2575
-this software may choose to accept it either as 1) Public Domain, 2)
2576
-under the conditions of the MIT License (see below), or 3) under the
2577
-terms of dual Public Domain/MIT License conditions described here, as
2578
-they choose.
2579
-
2580
-The MIT License is about as close to Publi
--- a/src/cson_amalgamation.h
+++ b/src/cson_amalgamation.h
@@ -1,2582 +0,0 @@
1 #ifdef FOSSIL_ENABLE_JSON
2 #ifndef CSON_FOSSIL_MODE
3 #define CSON_FOSSIL_MODE
4 #endif
5 /* auto-generated! Do not edit! */
6 /* begin file include/wh/cson/cson.h */
7 #if !defined(WANDERINGHORSE_NET_CSON_H_INCLUDED)
8 #define WANDERINGHORSE_NET_CSON_H_INCLUDED 1
9
10 /*#include <stdint.h> C99: fixed-size int types. */
11 #include <stdio.h> /* FILE decl */
12
13 l */
14
15 #include <stdarg.h>
16
17 /** @page page_cson cson JSON API
18
19 cson (pronounced "season") is an object-oriented C API for generating
20 and consuming JSON (http://www.json.org) data.
21
22 Its main claim to fame is that it can parse JSON from, and output it
23 to, damned near anywhere. The i/o routines use a callback function to
24 fetch/emit JSON data, allowing clients to easily plug in their own
25 implementations. Implementations are provided for string- and
26 FILE-based i/.
27
28 Project home page: https://epos/cson
29
30 Author: Stephan Beal (httpAuthor: Stephan Beal (https://www.wanderinghorse.net/home/stephan/)
31
32 License: Dual Public Domain/MIT
33
34 The full license text is at the bottom of the main header file
35 (cson.h).
36
37 Examples of how to use the library are scattered throughout
38 the API documentation, in the test.c file in the sou
39
40 */ESS OR IMPLIED, INCLUplus)
41 extern "C" {
42 #endif
43
44 #if defined(_WIN32) || defined(_WIN64)
45 # define CSON_ENABLE_UNIX 0
46 #else
47 # define CSON_ENABLE_UNIX 1
48 #endif
49
50
51 /** @typedef some_long_int_type cson_int_t
52
53 Typedef for JSON-like integer types. This is (long long) where feasible,
54 otherwise (long).
55 */
56 #ifdef _WIN32
57 typedef __int64 cson_int_t;
58 #define CSON_INT_T_SFMT "I64d"
59 #define CSON_INT_T_PFMT "I64d"
60 #elif (__STDC_VERSION__ >= 199901L) || (HAVE_LONG_LONG == 1)
61 typedef long long cson_int_t;
62 #define CSON_INT_T_SFMT "lld"
63 #define CSON_INT_T_PFMT "lld"
64 #else
65 typedef long cson_int_t;
66 #define CSON_INT_T_SFMT "ld"
67 #define CSON_INT_T_PFMT "ld"
68 #endif
69
70 /** @typedef double_or_long_double cson_double_t
71
72 This is the type of double value used by the library.
73 It is only lightly tested with long double, and when using
74 long double the memory requirements for such values goes
75 up.
76
77 Note that by default cson uses C-API defaults for numeric
78 precision. To use a custom precision throughout the library, one
79 needs to define the macros CSON_DOUBLE_T_SFMT and/or
80 CSON_DOUBLE_T_PFMT macros to include their desired precision, and
81 must build BOTH cson AND the client using these same values. For
82 example:
83
84 @code
85 #define CSON_DOUBLE_T_PFMT ".8Lf" // for Modified Julian Day values
86 #define HAVE_LONG_DOUBLE
87 @endcode
88
89 (Only CSON_DOUBLE_T_PFTM should be needed for most
90 purposes.)
91 */
92
93 #if defined(HAVE_LONG_DOUBLE)
94 typedef long double cson_double_t;
95 # ifndef CSON_DOUBLE_T_SFMT
96 # define CSON_DOUBLE_T_SFMT "Lf"
97 # endif
98 # ifndef CSON_DOUBLE_T_PFMT
99 # define CSON_DOUBLE_T_PFMT "Lf"
100 # endif
101 #else
102 typedef double cson_double_t;
103 # ifndef CSON_DOUBLE_T_SFMT
104 # define CSON_DOUBLE_T_SFMT "f"
105 # endif
106 # ifndef CSON_DOUBLE_T_PFMT
107 # define CSON_DOUBLE_T_PFMT "f"
108 # endif
109 #endif
110
111 /** @def CSON_VOID_PTR_IS_BIG
112
113 ONLY define this to a true value if you know that
114
115 (sizeof(cson_int_t) <= sizeof(void*))
116
117 If that is the case, cson does not need to dynamically
118 allocate integers. However, enabling this may cause
119 compilation warnings in 32-bit builds even though the code
120 being warned about cannot ever be called. To get around such
121 warnings, when building on a 64-bit environment you can define
122 this to 1 to get "big" integer support. HOWEVER, all clients must
123 also use the same value for this macro. If i knew a halfway reliable
124 way to determine this automatically at preprocessor-time, i would
125 automate this. We might be able to do halfway reliably by looking
126 for a large INT_MAX value?
127 */
128 #if !defined(CSON_VOID_PTR_IS_BIG)
129
130 /* Largely taken from http://predef.sourceforge.net/prearch.html
131
132 See also: http://poshlib.hookatooka.com/poshlib/trac.cgi/browser/posh.h
133 */
134 # if defined(_WIN64) || defined(__LP64__)/*gcc*/ \
135 || defined(_M_X64) || defined(__amd64__) || defined(__amd64) \
136 || defined(__x86_64__) || defined(__x86_64) \
137 || defined(__ia64__) || defined(__ia64) || defined(_IA64) || defined(__IA64__) \
138 || defined(_M_IA64) \
139 || defined(__sparc_v9__) || defined(__sparcv9) || defined(_ADDR64) \
140 || defined(__64BIT__)
141 # define CSON_VOID_PTR_IS_BIG 1
142 # else
143 # define CSON_VOID_PTR_IS_BIG 0
144 # endif
145 #endif
146
147 /** @def CSON_INT_T_SFMT
148
149 scanf()-compatible format token for cson_int_t.
150 */
151
152 /** @def CSON_INT_T_PFMT
153
154 printf()-compatible format token for cson_int_t.
155 */
156
157
158 /** @def CSON_DOUBLE_T_SFMT
159
160 scanf()-compatible format token for cson_double_t.
161 */
162
163 /** @def CSON_DOUBLE_T_PFMT
164
165 printf()-compatible format token for cson_double_t.
166 */
167
168 /**
169 Type IDs corresponding to JavaScript/JSON types.
170
171 These are only in the public API to allow O(1) client-side
172 dispatching based on cson_value types.
173 */
174 enum cson_type_id {
175 /**
176 The special "undefined" value constant.
177
178 Its value must be 0 for internal reasons.
179 */
180 CSON_TYPE_UNDEF = 0,
181 /**
182 The special "null" value constant.
183 */
184 CSON_TYPE_NULL = 1,
185 /**
186 The bool value type.
187 */
188 CSON_TYPE_BOOL = 2,
189 /**
190 The integer value type, represented in this library
191 by cson_int_t.
192 */
193 CSON_TYPE_INTEGER = 3,
194 /**
195 The double value type, represented in this library
196 by cson_double_t.
197 */
198 CSON_TYPE_DOUBLE = 4,
199 /** The immutable string type. This library stores strings
200 as immutable UTF8.
201 */
202 CSON_TYPE_STRING = 5,
203 /** The "Array" type. */
204 CSON_TYPE_ARRAY = 6,
205 /** The "Object" type. */
206 CSON_TYPE_OBJECT = 7
207 };
208 /**
209 Convenience typedef.
210 */
211 typedef enum cson_type_id cson_type_id;
212
213
214 /**
215 Convenience typedef.
216 */
217 typedef struct cson_value cson_value;
218
219 /** @struct cson_value
220
221 The core value type of this API. It is opaque to clients, and
222 only the cson public API should be used for setting or
223 inspecting their values.
224
225 This class is opaque because stack-based usage can easily cause
226 leaks if one does not intimately understand the underlying
227 internal memory management (which sometimes changes).
228
229 It is (as of 20110323) legal to insert a given value instance into
230 multiple containers (they will share ownership using reference
231 counting) as long as those insertions do not cause cycles. However,
232 be very aware that such value re-use uses a reference to the
233 original copy, meaning that if its value is changed once, it is
234 changed everywhere. Also beware that multi-threaded write
235 operations on such references leads to undefined behaviour.
236
237 PLEASE read the ACHTUNGEN below...
238
239 ACHTUNG #1:
240
241 cson_values MUST NOT form cycles (e.g. via object or array
242 entries).
243
244 Not abiding th Holy Law Of No Cycles will lead to double-frees and
245 the like (i.e. undefined behaviour, likely crashes due to infinite
246 recursion or stepping on invalid (freed) pointers).
247
248 ACHTUNG #2:
249
250 ALL cson_values returned as non-const cson_value pointers from any
251 public functions in the cson API are to be treated as if they are
252 heap-allocated, and MUST be freed by client by doing ONE of:
253
254 - Passing it to cson_value_free().
255
256 - Adding it to an ObjecThis object defines the error codes used by cson.
257
258 Library routines which return int values almost always return a
259 value from this structure. None of the members in this struct have
260 published values except for the OK member, which has the value 0.
261 All other values might be incidentally defined where clients
262 can see them, but the numbers might change from release to
263 release, so clients should only use the symbolic names.
264
265 Client code is expected to access these values via the shared
266 cson_rc object, and use them as demonstrated here:
267
268 @code
269 int rc = cson_some_func(...);
270 if( 0 == rc ) {...success...}
271 else if( cson_rc.ArgError == rc ) { ... some argument was wrong ... }
272 else if( cson_rc.AllocError == rc ) { ... allocation error ... }
273 ...
274 @endcode
275
276 ...
277 }
278 @endcode
279
280 The entries named Parse_XXX are generally only returned by
281 */
282
283 /** @struct cson_rc_
284 See \ref cson_rc for details.
285 */
286 static const struct cson_rc_
287 {
288 /** The generic success value. Guaranteed to be 0. */
289 const int OK;
290 /** Signifies an error in one or more arguments (e.g. NULL where it is not allowed). */
291 const int ArgError;
292 /** Signifies that some argument is not in a valid range. */
293 const int RangeError;
294 /** Signifies that some argument is not of the correct logical cson type. */
295 const int TypeError;
296 /** Signifies an input/ouput error. */
297 const int IOError;
298 /** Signifies an out-of-memory error. */
299 const int AllocError;
300 /** Signifies that the called code is "NYI" (Not Yet Implemented). */
301 const int NYIError;
302 /** Signifies that an internal error was triggered. If it happens, please report this as a bug! */
303 const int InternalError;
304 /** Signifies that the called operation is not supported in the0/*OK*/,
305 1/*ArgError*/,
306 2/*RangeError*/,
307 3/*TypeError*/,
308 4/*IOError*/,
309 5/*AllocError*/,
310 6/*NYIError could not be fo*/,
311 9/*NotFoundError*/,
312 10/*UnknownError*/,
313 11/*Parse_INVALID_CHAR*/,
314 12/*PaParse_INVALID_ESCAPE_SEQUENCE*/,
315 14/*def FOSSIL_ENABLE_JSON
316 #ifndefndef CSOerror code to conver*/,
317 16/*or;
318 /**
319 Signifie*/,
320 17/* /** Signifies an out-of-*/,
321 18/*plemented). */
322 */,
323 19/*/** Signifies that t*/
324 }y would add more
325 Signifies that the parser found an invalid keyword (possibly
326 an unquoted string).
327 */
328 const int Parse_INVALID_KEYWORD;
329 /**
330 Signifies that the parser found an invalid escape sequence.
331 */
332 const int Parse_INVALID_ESCAPE_SEQUENCE;
333 /**
334 Signifies that the parser found an invalid Unicode character
335 sequence.
336 */
337 const int Parse_INVALID_UNICODE_SEQUENCE;
338 /**
339 Signifies that the parser found an invalid numeric token.
340 */
341 const int Parse_INVALID_NUMBER;
342 /**
343 Signifies that the parser reached its maximum defined
344 parsing depth before finishing the input.
345 */
346 const int Parse_NESTING_DEPTH_REACHED;
347 /**
348 Signifies that the parser found an unclosed object or array.
349 */
350 const int Parse_UNBALANCED_COLLECTION;
351 /**
352 Signifies that the parser found an key in an unexpected place.
353 */
354 const int Parse_EXPECTED_KEY;
355 /**
356 Signifies that the parser expected to find a colon but
357 found none (e.g. between keys and values in an object).
358 */
359 const int Parse_EXPECTED_COLON;
360 } cson_rc = {
361 CSON_RC_OK,
362 CSON_RC_ArgError,
363 CSON_RC_RangeError,
364 CSON_RC_TypeError,
365 CSON_RC_IOError,
366 CSON_RC_AllocError,
367 CSON_RC_NYIError,
368 CSON_RC_InternalError,
369 CSON_RC_UnsupportedError,
370 CSON_RC_NotFoundError,
371 CSON_RC_UnknownError,
372 CSON_RC_Parse_INVALID_CHAR,
373 CSON_RC_Parse_INVALID_KEYWORD,
374 CSON_RC_Parse_INVALID_ESCAPE_SEQUENCE,
375 CSON_RC_Parse_INVALID_UNICODE_SEQUENCE,
376 CSON_RC_Parse_INVALID_NUMBER,
377 CSON_RC_Parse_NESTING_DEPTH_REACHED,
378 CSON_RC_Parse_UNBALANCED_COLLECTION,
379 CSON_RC_Parse_EXPECTED_KEY,
380 CSON_RC_Parse_EXPECTED_COLON
381 };
382
383 /**
384 Returns the string form of the cson_rc code corresponding to rc, or
385 some unspecified, non-NULL string if it is an unknown code.
386
387 The returned bytes are static and do not changing during the
388 lifetime of the application.
389 */
390 char const * cson_rc_string(int rc);
391
392 /** @struct cson_parse_opt
393 Client-configurable options for the cson_parse() family of
394 functions.
395 */
396 struct cson_parse_opt
397 {
398 /**
399 Maximum object/array depth to traverse.
400 */
401 unsigned short maxDepth;
402 /**
403 Whether or not to allow C-style comments. Do not rely on this
404 option being available. If the underlying parser is replaced,
405 this option might no longer be supported.
406 */
407 char allowComments;
408 };
409 typedef struct cson_parse_opt cson_parse_opt;
410
411 /**
412 Empty-initialized cson_parse_opt object.
413 */
414 #define cson_parse_opt_empty_m { 25/*maxDepth*/, 0/*allowComments*/}
415
416
417 /**
418 A class for holding JSON parser information. It is primarily
419 intended for finding the position of a parse error.
420 */
421 struct cson_parse_info
422 {
423 /**
424 1-based line number.
425 */
426 unsigned int line;
427 /**
428 0-based column number.
429 */
430 unsigned int col;
431
432 /**
433 Length, in bytes.
434 */
435 unsigned int length;
436
437 /**
438 Error code of the parse run (0 for no error).
439 */
440 int errorCode;
441
442 /**
443 The total number of object keys successfully processed by the
444 parser.
445 */
446 unsigned int totalKeyCount;
447
448 /**
449 The total number of object/array values successfully processed
450 by the parser, including the root node.
451 */
452 unsigned int totalValueCount;
453 };
454 typedef struct cson_parse_info cson_parse_info;
455
456 /**
457 Empty-initialized cson_parse_info object.
458 */
459 #define cson_parse_info_empty_m {1/*line*/,\
460 0/*col*/, \
461 0/*length*/, \
462 0/*errorCode*/, \
463 0/*totalKeyCount*/, \
464 0/*totalValueCount*/ \
465 }
466 /**
467 Empty-initialized cson_parse_info object.
468 */
469 extern const cson_parse_info cson_parse_info_empty;
470
471 /**
472 Empty-initialized cson_parse_opt object.
473 */
474 extern const cson_parse_opt cson_parse_opt_empty;
475
476 /**
477 Client-configurable options for the cson_output() family of
478 functions.
479 */
480 struct cson_output_opt
481 {
482 /**
483 Specifies how to indent (or not) output. The values
484 are:
485
486 (0) == no extra indentation.
487
488 (1) == 1 TAB character for each level.
489
490 (>1) == that number of SPACES for each level.
491 */
492 unsigned char indentation;
493
494 /**
495 Maximum object/array depth to traverse. Traversing deeply can
496 be indicative of cycles in the object/array tree, and this
497 value is used to figure out when to abort the traversal.
498 */
499 unsigned short maxDepth;
500
501 /**
502 If true, a newline will be added to generated output,
503 else not.
504 */
505 char addNewline;
506
507 /**
508 If true, a space will be added after the colon operator
509 in objects' key/value pairs.
510 */
511 char addSpaceAfterColon;
512
513 /**
514 If set to 1 then objects/arrays containing only a single value
515 will not indent an extra level for that value (but will indent
516 on subsequent levels if that value contains multiple values).
517 */
518 char indentSingleMemberValues;
519
520 /**
521 The JSON format allows, but does not require, JSON generators
522 to backslash-escape forward slashes. This option enables/disables
523 that feature. According to JSON's inventor, Douglas Crockford:
524
525 <quote>
526 It is allowed, not required. It is allowed so that JSON can be
527 safely embedded in HTML, which can freak out when seeing
528 strings containing "</". JSON tolerates "<\/" for this reason.
529 </quote>
530
531 (from an email on 2011-04-08)
532
533 The default value is 0 (because it's just damned ugly).
534 */
535 char escapeForwardSlashes;
536 };
537 typedef struct cson_output_opt cson_output_opt;
538
539 /**
540 Empty-initialized cson_output_opt object.
541 */
542 #define cson_output_opt_empty_m { 0/*indentation*/,\
543 25/*maxDepth*/, \
544 0/*addNewline*/, SON
545 #ifndef CSONf CSON cson_rc.AllocError on error (preferably a value from
546 cson_rc).
547
548 These functions are called relatively often during the JSON-output
549 process, and should try to be fast.
550 */
551 typedef int (*cson_data_dest_f)( void * state, void const * src, unsigned int n );
552
553 /**
554 Reads JSON-formatted string data (in ASCII, UTF8, or UTF16), using the
555 src function to fetch all input. This function fetches each input character
556 from the source function, which is calls like src(srcState, buffer, bufferSize),
557 and processes them. If anything is not JSON-kosher then this function
558 fails and returns one of the non-0 cson_rc codes.
559
560 This function is only intended to read root nodes of a JSON tree, either
561 a single object or a single array, containing any number of child elemSON
562 #ifndef CSONf CSON_FOSSIL_MODE
563 #define CSON_cson_rc.e if( !*n ) return CSON_RC_RangeError;
564 for( i = 0;
565 (i < *n) && (ss->pos < ss->end);
566 ++i, ++ss->pos, ++tgt )
567 {
568 *tgt = *ss->pos;
569 }
570 *n = i;
571 return 0;
572 }
573
574 ...
575 // Now use StringSource together with cson_parse()
576 StringSource ss;
577 cson_value * root = NULL;
578 char const * json = "{\"k1\":123}";
579 ss.str = ss.pos = json;
580 ss.end = json + strlen(json);
581 int rc = cson_parse( &root, cson_data_source_StringSource, &ss, NULL, NULL );
582 @endcode
583
584 It is recommended that clients wrap such utility code into
585 type-safe wrapper functions which also initialize the internal
586 state object and check the user-provided parameters for legality
587 before passing them on to cson_parse(). For examples of this, see
588 cson_parse_FILE() or cson_parse_string().
589
590 TODOs:
591
592 - Buffer the input in larger chunks. We currently read
593 byte-by-byte, but i'm too tired to write/test the looping code for
594 the buffering.
595
596 @see cson_parse_FILE()
597 @see cson_parse_string()
598 */
599 int cson_parse( cson_value ** tgt, cson_data_source_f src, void * srcState,
600 cson_parse_opt const * opt, cson_parse_info * info );
601 /**
602 A cson_data_source_f() implementation which requires the state argument
603 to be a readable (FILE*) handle.
604 */
605 int cson_data_source_FILE( void * state, void * dest, unsigned int * n );
606
607 /**
608 Equivalent to cson_parse( tgt, cson_data_source_FILE, src, opt ).
609
610 @see cson_parse_filename()
611 */
612 int cson_parse_FILE( cson_value ** tgt, FILE * src,
613 cson_parse_opt const * opt, cson_parse_info * info );
614
615 /**
616 Convenience wrapper around cson_parse_FILE() which opens the gcson_rc. contents. Returns CSON_Rt be opened.
617
618 @see cson_parse_FILE()
619 */
620 int cson_parse_filename( cson_value ** tgt, char const * src,
621 cson_parse_opt const * opt, cson_parse_info * info );
622
623 /**
624 Uses an internal helper class to pass src through cson_parse().
625 See that function for the return value and argument semantics.
626
627 src must be a string containing JSON code, at least len bytes long,
628 and the parser will attempt to parse exactly len bytes from src.
629
630 If len is less than 2 (the minimum length of a legal topcson_rc.rcState,
631 ich also initialize the internal
632 state object and check the user-provided parameters for legality
633 before passing them on to cson_parse(). For examples of this, see
634 cson_parse_FILE() or cson_parse_string().
635
636 TODOs:
637
638 - Buffer the input in larger chunks. We currently read
639 byte-by-byte, but i'm too tired to write/test the looping code for
640 the buffering.
641
642 @see cson_parse_FILE()
643 @see cson_parse_string()
644 */
645 int cson_parse( cson_value ** tgt, cson_data_source_f src, void * srcState,
646 cson_rc.rcState,
647 cson_parse_opt const * opt, cson_parse_info * info );
648 /**
649 A cson_data_source_f() implementation which requires the state argument
650 to be a readable (FILE*) handle.
651 */
652 int cson_data_source_FILE( void * state, void * dest, unsigned int * n );
653
654 /**
655 Equivalent to cson_parse( tgt, cson_data_source_FILE, src, opt ).
656
657 @see cson_parse_filename()
658 */
659 int cson_parse_FILE( cson_value ** tgt, FILE * src,
660 cson_parse_opt const * opt, cson_parse_info * info );
661
662 /**
663 Convenience wrapper around cson_parse_FILE() which opens the given filename.
664
665 Returns CSON_RC_IOError if the file cannot be opened.
666
667 @see cson_parse_FILE()
668 */
669 int cson_parse_filename( cson_value ** tgt, char const * src,
670 cson_parse_opt const * opt, cson_parse_info * info );
671
672 /**
673 Uses an internal helper class to pass src through cson_parse().
674 See that function for the return value and argument semantics.
675
676 src must be a string containing JSON code, at least len bytes long,
677 and the parser will attempt to parse exactly len bytes from src.
678
679 If len is less than 2 (the minimum length of a legal top-node JSON
680 object) then CSON_RC_RangeError is returned.
681 */
682 int cson_parse_string( cson_value ** tgt, char const * src, unsigned int len,
683 cson_rc. contents. Returns CSON_RC_IOError if the file cannot be opened.
684
685 @see cson_output_FILE()
686 */
687 int cson_output_filename( cson_value const * src, char const * dest, cson_output_opt const * fmt );
688
689 /**
690 Returns the virtual type of v, or CSON_TYPE_UNDEF if !v.
691 */
692 cson_type_id cson_value_type_id( cson_value const * v );
693
694
695 /** Returns true if v is null, v->api is NULL, or v holds the special undefined value. */
696 char cson_value_is_undef( cson_value const * v );
697 /** Returns true if v contains a null value. */
698 char cson_value_is_null( cson_value const * v );
699 /** Returns true if v contains a bool value. */
700 char cson_value_is_bool( cson_value const * v );
701 /** Returns true if v contains an integer value. */
702 char cson_value_is_integer( cson_value const * v );
703 /** Returns true if v contains a double value. */
704 char cson_value_is_double( cson_value const * v );
705 /** Returns true if v contains a number (double, integer) value. */
706 char cson_value_is_number( cson_value const * v );
707 /** Returns true if v contains a string value. */
708 char cson_value_is_string( cson_value const * v );
709 /** Returns true if v contains an array value. */
710 char cson_value_is_array( cson_value const * v );
711 /** Returns true if v contains an object value. */
712 char cson_value_is_object( cson_value const * v );
713
714 /** @struct cson_object
715
716 cson_object is an opaque handle to an Object value.
717
718 They are used like:
719
720 @code
721 cson_object * obj = cson_value_get_object(myValue);
722 ...
723 @endcode
724
725 They can be created like:
726
727 @code
728 cson_value * objV = cson_value_new_object();
729 cson_object * obj = cson_value_get_object(objV);
730 // obj is owned by objV and objV must eventually be freed
731 // using cson_value_free() or added to a container
732 // object/array (which transfers ownership to that container).
733 @endcode
734
735 @see cson_value_new_object()
736 @see cson_value_get_object()
737 @see cson_value_free()
738 */
739
740 typedef struct cson_object cson_object;
741
742 /** @struct cson_array
743
744 cson_array is an opaque handle to an Array value.
745
746 They are used like:
747
748 @code
749 cson_array * obj = cson_value_get_ae a prepared, but not yet traFOSSIL_ENABLE_JSON
750 #ifndef CSON_FOSSIL_MODE
751 #define CSON_FOSSIL_MODE
752 #endif
753 /* auto-generated! Do not edit! */
754 /* begin file include/wh/cson/cson.h */
755 #if !defined(WANDERINGHORSE_NET_CSON_H_INCLUDED)
756 #define WANDERINGHORSE_NET_CSON_H_INCLUDED 1
757
758 /*#include <stdint.h> C99: fixed-size int types. */
759 #include <stdio.h> /* FILE decl */
760
761 #include <stdarg.h>
762
763 /** @page page_cson cson JSON API
764
765 cson (pronounced "season") is an object-oriented C API for generating
766 and consuming JSON (http://www.json.org) data.
767
768 Its main claim to fame is that it can parse JSON from, and output it
769 to, damned near anywhere. The i/o routines use a callback function to
770 fetch/emit JSON data, allowing clients to easily plug in their own
771 implementations. Implementations are provided for string- and
772 FILE-based i/o.
773
774 Project home page: https://fossil.wanderinghorse.net/r/cson
775
776 Author: Stephan Beal (https://www.wanderinghorse.net/home/stephan/)
777
778 License: Dual Public Domain/MIT
779
780 The full license text is at the bottom of the main header file
781 (cson.h).
782
783 Examples of how to use the library are scattered throughout
784 the API documentation, in the test.c file in the source repo,
785 and in the wiki on the project's home page.
786 */
787
788 #if defined(__cplusplus)
789 extern "C" {
790 #endif
791
792 #if defined(_WIN32) || defined(_WIN64)
793 # define CSON_ENABLE_UNIX 0
794 #else
795 # define CSON_ENABLE_UNIX 1
796 #endif
797
798
799 /** @typedef some_long_int_type cson_int_t
800
801 Typedef for JSON-like integer types. This is (long long) where feasible,
802 otherwise (long).
803 */
804 #ifdef _WIN32
805 typedef __int64 cson_int_t;
806 #define CSON_INT_T_SFMT "I64d"
807 #define CSON_INT_T_PFMT "I64d"
808 #elif (__STDC_VERSION__ >= 199901L) || (HAVE_LONG_LONG == 1)
809 typedef long long cson_int_t;
810 #define CSON_INT_T_SFMT "lld"
811 #define CSON_INT_T_PFMT "lld"
812 #else
813 typedef long cson_int_t;
814 #define CSON_INT_T_SFMT "ld"
815 #define CSON_INT_T_PFMT "ld"
816 #endif
817
818 /** @typedef double_or_long_double cson_double_t
819
820 This is the type of double value used by the library.
821 It is only lightly tested with long double, and when using
822 long double the memory requirements for such values goes
823 up.
824
825 Note that by default cson uses C-API defaults for numeric
826 precision. To use a custom precision throughout the library, one
827 needs to define the macros CSON_DOUBLE_T_SFMT and/or
828 CSON_DOUBLE_T_PFMT macros to include their desired precision, and
829 must build BOTH cson AND the client using these same values. For
830 example:
831
832 @code
833 #define CSON_DOUBLE_T_PFMT ".8Lf" // for Modified Julian Day values
834 #define HAVE_LONG_DOUBLE
835 @endcode
836
837 (Only CSON_DOUBLE_T_PFTM should be needed for most
838 purposes.)
839 */
840
841 #if defined(HAVE_LONG_DOUBLE)
842 typedef long double cson_double_t;
843 # ifndef CSON_DOUBLE_T_SFMT
844 # define CSON_DOUBLE_T_SFMT "Lf"
845 # endif
846 # ifndef CSON_DOUBLE_T_PFMT
847 # define CSON_DOUBLE_T_PFMT "Lf"
848 # endif
849 #else
850 typedef double cson_double_t;
851 # ifndef CSON_DOUBLE_T_SFMT
852 # define CSON_DOUBLE_T_SFMT "f"
853 # endif
854 # ifndef CSON_DOUBLE_T_PFMT
855 # define CSON_DOUBLE_T_PFMT "f"
856 # endif
857 #endif
858
859 /** @def CSON_VOID_PTR_IS_BIG
860
861 ONLY define this to a true value if you know that
862
863 (sizeof(cson_int_t) <= sizeof(void*))
864
865 If that is the case, cson does not need to dynamically
866 allocate integers. However, enabling this may cause
867 compilation warnings in 32-bit builds even though the code
868 being warned about cannot ever be called. To get around such
869 warnings, when building on a 64-bit environment you can define
870 this to 1 to get "big" integer support. HOWEVER, all clients must
871 also use the same value for this macro. If i knew a halfway reliable
872 way to determine this automatically at preprocessor-time, i would
873 automate this. We might be able to do halfway reliably by looking
874 for a large INT_MAX value?
875 */
876 #if !defined(CSON_VOID_PTR_IS_BIG)
877
878 /* Largely taken from http://predef.sourceforge.net/prearch.html
879
880 See also: http://poshlib.hookatooka.com/poshlib/trac.cgi/browser/posh.h
881 */
882 # if defined(_WIN64) || defined(__LP64__)/*gcc*/ \
883 || defined(_M_X64) || defined(__amd64__) || defined(__amd64) \
884 || defined(__x86_64__) || defined(__x86_64) \
885 || defined(__ia64__) || defined(__ia64) || defined(_IA64) || defined(__IA64__) \
886 || defined(_M_IA64) \
887 || defined(__sparc_v9__) || defined(__sparcv9) || defined(_ADDR64) \
888 || defined(__64BIT__)
889 # define CSON_VOID_PTR_IS_BIG 1
890 # else
891 # define CSON_VOID_PTR_IS_BIG 0
892 # endif
893 #endif
894
895 /** @def CSON_INT_T_SFMT
896
897 scanf()-compatible format token for cson_int_t.
898 */
899
900 /** @def CSON_INT_T_PFMT
901
902 printf()-compatible format token for cson_int_t.
903 */
904
905
906 /** @def CSON_DOUBLE_T_SFMT
907
908 scanf()-compatible format token for cson_double_t.
909 */
910
911 /** @def CSON_DOUBLE_T_PFMT
912
913 printf()-compatible format token for cson_double_t.
914 */
915
916 /**
917 Type IDs corresponding to JavaScript/JSON types.
918
919 These are only in the public API to allow O(1) client-side
920 dispatching based on cson_value types.
921 */
922 enum cson_type_id {
923 /**
924 The special "undefined" value constant.
925
926 Its value must be 0 for internal reasons.
927 */
928 CSON_TYPE_UNDEF = 0,
929 /**
930 The special "null" value constant.
931 */
932 CSON_TYPE_NULL = 1,
933 /**
934 The bool value type.
935 */
936 CSON_TYPE_BOOL = 2,
937 /**
938 The integer value type, represented in this library
939 by cson_int_t.
940 */
941 CSON_TYPE_INTEGER = 3,
942 /**
943 The double value type, represented in this library
944 by cson_double_t.
945 */
946 CSON_TYPE_DOUBLE = 4,
947 /** The immutable string type. This library stores strings
948 as immutable UTF8.
949 */
950 CSON_TYPE_STRING = 5,
951 /** The "Array" type. */
952 CSON_TYPE_ARRAY = 6,
953 /** The "Object" type. */
954 CSON_TYPE_OBJECT = 7
955 };
956 /**
957 Convenience typedef.
958 */
959 typedef enum cson_type_id cson_type_id;
960
961
962 /**
963 Convenience typedef.
964 */
965 typedef struct cson_valueON
966 #ifndef CSON_f CSON_FOtart with a percent sign '\%'
967 followed by one or more modifiers and a type character. Object properties
968 are specified as key-value pairs where the key is specified as a string and
969 passed as an argument of const char *. Any space, tab, carriage return, line
970 feed, colon and comma characters between format specifiers are ignored.
971
972 | Type | Description |
973 | :--: | :---------- |
974 | s | creates either a property name or a string value, in case of the former the corresponding argument is a pointer to const char which is a sequence of bytes specifying the name of the property that is to be created, in case of the latter the corresponding argument is a pointer to const char |
975 | d | creates an integer value, the corresponding argument is an int |
976 | i | ^ |
977 | f | creates a floating point value, the corresponding argument is a double |
978 | b | creates a boolean value, the corresponding argument is an int |
979 | N | creates a null value |
980 | [...] | creates an array, the corresponding argument is a pointer to a cson_array |
981 | {...} | creates an array, the corresponding argument is a pointer to a cson_object |
982
983 | Modifier | Description |
984 | :------: | :---------- |
985 | l | specifies that the following d or i specifier applies to an argument which is a pointer to long |
986 | ll | specifies that the following d or i specifier applies to an argument which is a pointer to cson_int_t |
987
988 | Short Form | Expands to
989 | :--------: | :--------- |
990 | {...} | %*{...} |
991 | [...] | %*[...] |
992 | \%D | \%lld |
993
994
995 Returns 0 on success. The error conditions are:
996
997 - CSON_PACK_ARG_ERROR: fmt contains a syntax error
998
999 - CSON_PACK_ALLOC_ERROR: a memory allocation failed
1000
1001 - CSON_PACK_INTERNAL_ERROR: an internal error has occurred, this is a bug in
1002 cson
1003
1004 Example:
1005 @code
1006 cson_value * root_value;
1007 cson_array * arr;
1008 ...
1009 rc = cson_pack( root_value, "{%s: %d, %s: %[]}", "foo", 42, "bar", arr );
1010 if( 0 != rc ) {
1011 ... error ...
1012 }
1013 @endcode
1014 */
1015 int cson_pack( cson_value **root_valuep, const char *fmt, ... );
1016
1017 /**
1018 Same as cson_pack() except that it takes a va_list instead of a variable
1019 number of arguments.
1020 */
1021 int cson_vpack( cson_value **root_valuep, const char *fmt, va_list args );
1022
1023 /**
1024 Iterate over the given object or array and convert an arbitrary number of
1025 JSON values into their native C types or validates them according to the
1026 given format string fmt.
1027
1028 fmt is a format string, it must at least contain an array or object
1029 specifier as its root value. Format specifiers start with a percent sign '\%'
1030 followed by one or more modifiers and a type character. Object properties
1031 are specified as key-value pairs where the key is specified as a string and
1032 passed as an argument of const char *. Any space, tab, carriage return, line
1033 feed, colon and comma characters between format specifiers are ignored.
1034
1035 | Type | Description |
1036 | :--: | :---------- |
1037 | s | matches a either a property name or a string value, in case of the former the corresponding argument is a pointer to const char which is a sequence of bytes specifying the name of the property that is to be matched, in case of the latter the corresponding argument is a pointer to a pointer to const char unless the 'm' modifier is specified where the the corresponding argument is a pointer to a pointer to char |
1038 | d | matches an integer value and must be used in with the "ll" modifier, the corresponding argument is a pointer to cson_int_t |
1039 | i | ^ |
1040 | f | matches a floating point value, the corresponding argument is a pointer to double |
1041 | b | matches a boolean value, the corresponding argument is a pointer to int |
1042 | N | matches a null value |
1043 | [...] | matches an array, the corresponding argument is a pointer to a pointer to a cson_array |
1044 | {...} | matches an array, the corresponding argument is a pointer to a pointer to a cson_object |
1045
1046 | Modifier | Description |
1047 | :------: | :---------- |
1048 | ? | specifies that the property reffered to by the given property name is optional |
1049 | * | suppresses assignment, only check for the presence and type of the specified value |
1050 | m | allocates a memory buffer for the extracted string |
1051 | ll | specifies that the following d or i specifier applies to an argument which is a pointer to cson_int_t |
1052
1053 | Short Form | Expands to
1054 | :--------: | :--------- |
1055 | {...} | %*{...} |
1056 | [...] | %*[...] |
1057 | \%D | \%lld |
1058
1059 Returns 0 on success. The error conditions are:
1060
1061 - CSON_PACK_ARG_ERROR: fmt contains a syntax error
1062
1063 - CSON_PACK_ALLOC_ERROR: a memory allocation failed
1064
1065 - CSON_PACK_VALIDATION_ERROR: validation failed, the JSON document structure
1066 differs from that described by the format string
1067
1068 - CSON_PACK_INTERNAL_ERROR: an internal error has occurred, this
1069 indicates a bug in this library.
1070
1071 Example:
1072 @code
1073 cson_value * root_value;
1074 cson_int_t x = 0;
1075 cson_array * arr = NULL;
1076 const char *str = NULL;
1077 ...
1078 rc = cson_unpack( root_value, "{%s: %d, %s: %[], %?s: %s}", "foo", &x, "bar", &arr, "baz", &str );
1079 if( rc < 3 && rc >= 0 ) {
1080 ... optional property is missing ...
1081 } else if ( CSON_PACK_ALLOC_ERROR == rc ) {
1082 ... out of memory error ...
1083 } else if ( CSON_PACK_VALIDATION_ERROR == rc ) {
1084 ... unexpected JSON document structure ...
1085 } else if ( rc ) {
1086 ... internal error ...
1087 }
1088 @endcode
1089
1090 */
1091 int cson_unpack( cson_value *root_value, const char *fmt, ... );
1092
1093 /**
1094 Same as cson_unpack() except that it takes a va_list instead of a variable
1095 number of arguments.
1096 */
1097 int cson_vunpack( cson_value *root_value, const char *fmt, va_list args );
1098
1099 /* LICENSE
1100
1101 This software's source code, including accompanying documentation and
1102 demonstration applications, are licensed under the following
1103 conditions...
1104
1105 Certain files are imported from external projects and have their own
1106 licensing terms. Namely, the JSON_parser.* files. See their files for
1107 their official licenses, but the summary is "do what you want [with
1108 them] but leave the license text and copyright in place."
1109
1110 The author (Stephan G. Beal [http://wanderinghorse.net/home/stephan/])
1111 explicitly disclaims copyright in all jurisdictions which recognize
1112 such a disclaimer. In such jurisdictions, this software is released
1113 into the Public Domain.
1114
1115 In jurisdictions which do not recognize Public Domain property
1116 (e.g. Germany as of 2011), this software is Copyright (c) 2011 by
1117 Stephan G. Beal, and is released under the terms of the MIT License
1118 (see below).
1119
1120 In jurisdictions which recognize Public Domain property, the user of
1121 this software may choose to accept it either as 1) Public Domain, 2)
1122 under the conditions of the MIT License (see below), or 3) under the
1123 terms of dual Public Domain/MIT License conditions described here, as
1124 they choose.
1125
1126 The MIT License is about as close to Public Domain as a license can
1127 get, and is described in clear, concise terms at:
1128
1129 http://en.wikipedia.org/wiki/MIT_License
1130
1131 The full text of the MIT License follows:
1132
---
1133 Copyright (c) 2011 Stephan G. Beal (http://wanderinghorse.net/home/stephan/)
1134
1135 Permission is hereby granted, free of charge, to any person
1136 obtaining a copy of this software and associated documentation
1137 files (the "Software"), to deal in the Software without
1138 restriction, including without limitation the rights to use,
1139 copy, modify, merge, publish, distribute, sublicense, and/or sell
1140 copies of the Software, and to permit persons to whom the
1141 Software is furnished to do so, subject to the following
1142 conditions:
1143
1144 The above copyright notice and this permission notice shall be
1145 included in all copies or substantial portions of the Software.
1146
1147 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY<sqlite3.h>ESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
1148 OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
1149 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
1150 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
1151 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
1152 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
1153 OTHER DEALINGS IN THE SOFTWARE.
1154
---END OF MIT LICENSE--
1155
1156 For purposes of the above license, the term "Software" includes
1157 documentation and demonstration source code which accompanies
1158 this software. ("Accompanies" = is contained in the Software's
1159 primary public source code repository.)
1160
1161 */
1162
1163 #if defined(__cplusplus)
1164 } /*extern "C"*/
1165 #endif
1166
1167 #endif /* WANDERINGHORSE_NET_CSON_H_INCLUDED */
1168 /* end file include/wh/cson/cson.h */
1169 /* begin file include/wh/cson/cson_sqlite3.h */
1170 /** @file cson_sqlite3.h
1171
1172 This file contains cson's public sqlite3-to-JSON API declarations
1173 and API documentation. If CSON_ENABLE_SQLITE3 is not defined,
1174 or is defined to 0, then including this file will have no side-effects
1175 other than defining CSON_ENABLE_SQLITE3 (if it was not defined) to 0
1176 and defining a few include guard macros. i.e. if CSON_ENABLE_SQLITE3
1177 is not set to a true value then the API is not visible.
1178
1179 This API requires that <sqlite3.h> be in the INCLUDES path and that
1180 the client eventually link to (or directly embed) the sqlite3 library.
1181 */
1182 #if !defined(WANDERINGHORSE_NET_CSON_SQLITE3_H_INCLUDED)
1183 #define WANDERINGHORSE_NET_CSON_SQLITE3_H_INCLUDED 1
1184 #if !defined(CSON_ENABLE_SQLITE3)
1185 # if defined(DOXYGEN)
1186 #define CSON_ENABLE_SQLITE3 1
1187 # else
1188 #define CSON_ENABLE_SQLITE3 1
1189 # endif
1190 #endif
1191
1192 #if CSON_ENABLE_SQLITE3 /* we do this here for the sake of the amalgamation build */
1193 #include "sqlite3.h"
1194
1195 #if defined(__cplusplus)
1196 extern "C" {
1197 #endif
1198
1199 /**
1200 Converts a single value from a single 0-based column index to its JSON
1201 equivalent.
1202
1203 On success it returns a new JSON value, which will have a different concrete
1204 type depending on the field type reported by sqlite3_column_type(st,col):
1205
1206 Integer, double, null, or string (TEXT and BLOB data, though not
1207 all blob data is legal for a JSON string).
1208
1209 st must be a sqlite3_step()'d row and col must be a 0-based column
1210 index within that result row.
1211 */
1212 cson_value * cson_sqlite3_column_to_value( sqlite3_stmt * st, int col );
1213
1214 /**
1215 Creates a JSON Array object containing the names of all columns
1216 of the given prepared statement handle.
1217
1218 Returns a new array value on success, which the caller owns. Its elements
1219 are in the same order as in the underlying query.
1220
1221 On error NULL is returned.
1222
1223 st is not traversed or freed by this function - only the column
1224 count and names are read.
1225 */
1226 cson_value * cson_sqlite3_column_names( sqlite3_stmt * st );
1227
1228 /**
1229 Creates a JSON Object containing key/value pairs corresponding
1230 to the result columns in the current row of the given statement
1231 handle. st must be a sqlite3_step()'d row result.
1232
1233 On success a new Object is returned which is owned by the
1234 caller. On error NULL is returned.
1235
1236 cson_sqlite3_column_to_value() is used to convert each column to a
1237 JSON value, and the column names are taken from
1238 sqlite3_column_name().
1239 */
1240 cson_value * cson_sqlite3_row_to_object( sqlite3_stmt * st );
1241 /**
1242 Functionally almost identical to cson_sqlite3_row_to_object(), the
1243 only difference being how the result objects gets its column names.
1244 st must be a freshly-step()'d handle holding a result row.
1245 colNames must be an Array with at least the same number of columns
1246 as st. If it has fewer, NULL is returned and this function has
1247 no side-effects.
1248
1249 For each column in the result set, the colNames entry at the same
1250 index is used for the column key. If a given entry is-not-a String
1251 then conversion will fail and NULL will be returned.
1252
1253 The one reason to prefer this over cson_sqlite3_row_to_object() is
1254 that this one can share the keys across multiple rows (or even
1255 other JSON containers), whereas the former makes fresh copies of
1256 the column names for each row.
1257
1258 */
1259 cson_value * cson_sqlite3_row_to_object2( sqlite3_stmt * st,
1260 cson_array * colNames );
1261
1262 /**
1263 Similar to cson_sqlite3_row_to_object(), but creates an Array
1264 value which contains the JSON-form values of the given result
1265 set row.
1266 */
1267 cson_value * cson_sqlite3_row_to_array( sqlite3_stmt * st );
1268 /**
1269 Converts the results of an sqlite3 SELECT statement to JSON,
1270 in the form of a cson_value object tree.
1271
1272 st must be a prepared, but not yet traversed, SELECT query.
1273 tgt must be a pointer to NULL (see the example below). If
1274 either of those arguments are NULL, cson_rc.ArgError is returned.
1275
1276 This walks the query results and returns a JSON object which
1277 has a different structure depending on the value of the 'fat'
1278 argument.
1279
1280
1281 If 'fat' is 0 then the structure is:
1282
1283 @code
1284 {
1285 "columns":["colName1",..."colNameN"],
1286 "rows":[
1287 [colVal0, ... colValNs: cson_rc.AllocErroralue_get_object( cs
1288 char * cson_value_get_string_copy( cson_value const * val );
1289
1290 /**
1291 Simplified form of cson_value_fetch_object(). Returns NULL if val
1292 is-not-a objectSON
1293 #ifndef CSON_Ff CSON_FOSSIL_MODE
1294 #define CSON_FOSSIL_MODE
1295 #endif
1296 /* auto-generated! Do not edit! */
1297 /* begin file include/wh/cson/cson.h */
1298 #if !defined(WANDERINGHORSE_NET_CSON_H_INCLUDED)
1299 #define WANDERINGHORSE_NET_CSON_H_INCLUDED 1
1300
1301 /*#include <stdint.h> C99: fixed-size int types. */
1302 #include <stdio.h> /* FILE decl */
1303
1304 #include <stdarg.h>
1305
1306 /** @page page_cson cson JSON API
1307
1308 cson (pronounced "season") is an object-oriented C API for generating
1309 and consuming JSON (http://www.json.org) data.
1310
1311 Its main claim to fame is that it can parse JSON from, and output it
1312 to, damned near anywhere. The i/o routines use a callback function to
1313 fetch/emit JSON data, allowing clients to easily plug in their own
1314 implementations. Implementations are provided for string- and
1315 FILE-based i/o.
1316
1317 Project home page: https://fossil.wanderinghorse.net/r/cson
1318
1319 Author: Stephan Beal (https://www.wanderinghorse.net/home/stephan/)
1320
1321 License: Dual Public Domain/MIT
1322
1323 The full license text is at the bottom of the main header file
1324 (cson.h).
1325
1326 Examples of how to use the library are scattered throughout
1327 the API documentation, in the test.c file in the source repo,
1328 and in the wiki on the project's home page.
1329 */
1330
1331 #if defined(__cplusplus)
1332 extern "C" {
1333 #endif
1334
1335 #if defined(_WIN32) || defined(_WIN64)
1336 # define CSON_ENABLE_UNIX 0
1337 #else
1338 # define CSON_ENABLE_UNIX 1
1339 #endif
1340
1341
1342 /** @typedef some_long_int_type cson_int_t
1343
1344 Typedef for JSON-like integer types. This is (long long) where feasible,
1345 otherwise (long).
1346 */
1347 #ifdef _WIN32
1348 typedef __int64 cson_int_t;
1349 #define CSON_INT_T_SFMT "I64d"
1350 #define CSON_INT_T_PFMT "I64d"
1351 #elif (__STDC_VERSION__ >= 199901L) || (HAVE_LONG_LONG == 1)
1352 typedef long long cson_int_t;
1353 #define CSON_INT_T_SFMT "lld"
1354 #define CSON_INT_T_PFMT "lld"
1355 #else
1356 typedef long cson_SON
1357 #ifndef CSONf CSON_FOSSIL_MODE
1358 #define CSOcson_rc.AllocError.
1359
1360 - Appending would cause a numeric overlow in the array's size:
1361 cson_rc.RangeError. (However, you'll get an AllocError long before
1362 that happens!)
1363
1364 On error ownership of v is NOT modified, and the caller may still
1365 need to clean it up. See cson_array_set() for the details.
1366
1367 */
1368 int cson_array_append( cson_array * ar, cson_value * v );
1369
1370
1371 /**
1372 Creates a new cson_value from the given boolean value.
1373
1374 Ownership of the new value is passed to the caller, who must
1375 eventually either free the value using cson_value_free() or
1376 inserting it into a container (array or object), which transfers
1377 ownership to the container. See the cson_value class documentation
1378 for more details.
1379
1380 Semantically speaking this function Returns NULL on allocation
1381 error, but the implementation never actually allocates for this
1382 case. Nonetheless, it must be treated as if it were an allocated
1383 value.
1384 */
1385 cson_value * cson_value_new_bool( char v );
1386
1387
1388 /**
1389 Alias for cson_value_new_bool(v).
1390 */
1391 cson_value * cson_new_bool(char v);
1392
1393 /**
1394 Returns the special JSON "null" value. When outputing JSON,
1395 its string representation is "null" (without the quotes).
1396
1397 See cson_value_new_bool() for notes regarding the returned
1398 value's memory.
1399 */
1400 cson_value * cson_value_null( void );
1401
1402 /**
1403 Equivalent to cson_value_new_bool(1).
1404 */
1405 cson_value * cson_value_true( void );
1406
1407 /**
1408 Equivalent to cson_value_new_bool(0).
1409 */
1410 cson_value * cson_value_false( void );
1411
1412 /**
1413 Semantically the same as cson_value_new_bool(), but for integers.
1414 */
1415 cson_value * cson_value_new_integer( cson_int_t v );
1416
1417 /**
1418 Alias for cson_value_new_integer(v).
1419 */
1420 cson_value * cson_new_int(cson_int_t v);
1421
1422 /**
1423 Semantically the same as cson_value_new_bool(), but for doubles.
1424 */
1425 cson_value * cson_value_new_double( cson_double_t v );
1426
1427 /**
1428 Alias for cson_value_new_double(v).
1429 */
1430 cson_value * cson_new_double(cson_double_t v);
1431
1432 /**
1433 Semantically the same as cson_value_new_bool(), but for strings.
1434 This creates a JSON value which copies the first n bytes of str.
1435 The string will automatically be NUL-terminated.
1436
1437 Note that if str is NULL or n is 0, this function still
1438 returns non-NULL value representing that empty string.
1439
1440 Returns NULL on allocation error.
1441
1442 See cson_value_new_bool() for important information about the
1443 returned memory.
1444 */
1445 cson_value * cson_value_new_string( char const * str, unsigned int n );
1446
1447 /**
1448 Allocates a new "object" value and transfers ownership of it to the
1449 caller. It must eventually be destroyed, by the caller or its
1450 owning container, by passing it to cson_value_free().
1451
1452 Returns NULL on allocation error.
1453
1454 Post-conditions: cson_value_is_object(value) will return true.
1455
1456 @see cson_value_new_array()
1457 @see cson_value_free()
1458 */
1459 cson_value * cson_value_new_object( void );
1460
1461 /**
1462 This works like cson_value_new_object() but returns an Object
1463 handle directly.
1464
1465 The value handle for the returned object can be fetched with
1466 cson_object_value(theObject).
1467
1468 Ownership is transfered to the caller, who must eventually free it
1469 by passing the Value handle (NOT the Object handle) to
1470 cson_value_free() or passing ownership to a parent container.
1471
1472 Returns NULL on error (out of memory).
1473 */
1474 cson_object * cson_new_object( void );
1475
1476 /**
1477 Identical to cson_new_object() except that it creates
1478 an Array.
1479 */
1480 cson_array * cson_new_array( void );
1481
1482 /**
1483 Identical to cson_new_object() except that it creates
1484 a String.
1485 */
1486 cson_string * cson_new_string(char const * val, unsigned int len);
1487
1488 /**
1489 Equivalent to cson_value_free(cson_object_value(x)).
1490 */
1491 void cson_free_object(cson_object *x);
1492
1493 /**
1494 Equivalent to cson_value_free(cson_array_value(x)).
1495 */
1496 void cson_free_array(cson_array *x);
1497
1498 /**
1499 Equivalent to cson_value_free(cson_string_value(x)).
1500 */
1501 void cson_free_string(cson_string *x);
1502
1503
1504 /**
1505 Allocates a new "array" value and transfers ownership of it to the
1506 caller. It must eventually be destroyed, by the caller or its
1507 owning container, by passing it to cson_value_free().
1508
1509 Returns NULL on allocation error.
1510
1511 Post-conditions: cson_value_is_array(value) will return true.
1512
1513 @see cson_value_new_object()
1514 @see cson_value_free()
1515 */
1516 cson_value * cson_value_new_array( void );
1517
1518 /**
1519 Frees any resources owned by v, then frees v. If v is a container
1520 type (object or array) its children are also freed (recursively).
1521
1522 If v is NULL, this is a no-op.
1523
1524 This function decrements a reference count and only destroys the
1525 value if its reference count drops to 0. Reference counts are
1526 increased by either inserting the value into a container or via
1527 cson_value_add_reference(). Even if this function does not
1528 immediately destroy the value, the value must be considered, from
1529 the perspective of that client code, to have been
1530 destroyed/invalidated by this call.
1531
1532
1533 @see cson_value_new_object()
1534 @see cson_value_new_array()
1535 @see cson_value_add_reference()
1536 */
1537 void cson_value_free(cson_value * v);
1538
1539 /**
1540 Alias for cson_value_free().
1541 */
1542 void cson_free_value(cson_value * v);
1543
1544
1545 /**
1546 Functionally similar to cson_array_set(), but uses a string key
1547 as an index. Like arrays, if a value already exists for the given key,
1548 it is destroyed by this function before inserting the new value.
1549
1550 If v is NULL then this call is equivalent to
1551 cson_object_unset(obj,key). Note that (v==NULL) is treated
1552 differently from v having the special null value. In the latter
1553 case, the key is set to the special null value.
1554
1555 The key may be encoded as ASCII or UTF8. Results are undefined
1556 with other encodings, and the errors won't show up here, but may
1557 show up later, e.g. during output.
1558
1559 Returns 0 on success, non-0 on error. It has the folloSON
1560 #ifndef CSONf obj or key are NULL or strlen(key) is 0.
1561
1562 - cson_rc.AllocErrorturn true.
1563
1564 @see cson_value_new_object()
1565 @see cson_value_free()
1566 */
1567 cson_value * cson_value_new_array( void );
1568
1569 /**
1570 Frees any resources owned by v, then frees v. If v is a container
1571 type (object or array) its children are also freed (recursively).
1572
1573 If v is NULL, this is a no-op.
1574
1575 This function decrements a reference count and only destroys the
1576 value if its reference count drops to 0. Reference counts are
1577 increased by either inserting the value into a container or via
1578 cson_value_add_reference(). Even if this function does not
1579 immediately destroy the value, the value must be considered, from
1580 the perspective of that client code, to have been
1581 destroyed/invalidated by this call.
1582
1583
1584 @see cson_value_new_object()
1585 @see cson_value_new_array()
1586 @see cson_value_add_reference()
1587 */
1588 void cson_value_free(cson_value * v);
1589
1590 /**
1591 Alias for cson_value_free().
1592 */
1593 void cson_free_value(cson_value * v);
1594
1595
1596 /**
1597 Functionally similar to cson_array_set(), but uses a string key
1598 as an index. Like arrays, if a value already exists for the given key,
1599 it is destroyed by this function before inserting the new value.
1600
1601 If v is NULL then this call is equivalent to
1602 cson_object_unset(obj,key). Note that (v==NULL) is treated
1603 differently from v having the special null value. In the latter
1604 case, the key is set to the special null value.
1605
1606 The key may be encoded as ASCII or UTF8. Results are undefined
1607 with other encodings, and the errors won't show up here, but may
1608 show up later, e.g. during output.
1609
1610 Returns 0 on success, non-0 on error. It has the following error
1611 cases:
1612
1613 - CSON_RC_ArgError: obj or kecson_rc. it is not found, CSON_RC_NotFoundError is returned (which can
1614 normally be igSON
1615 #ifndef CSON_FOSSIL_MODEf C obj or key are NULL or key has a length
1616 of 0.
1617
1618 This function reduces the returned value's reference count but has
1619 the specific property that it does not treat refcounts 0 and 1
1620 identically, meaning that the returned object may have a refcount
1621 of 0. This behaviour works around a corner-case where we want to
1622 extract a child element from its parent and then destroy the parent
1623 (which leaves us in an undesireable (normally) reference count
1624 state).
1625 */
1626 cson_value * cson_object_take( cson_object * obj, char const * key );
1627
1628 /**
1629 Fetches a property from a child (or [great-]*grand-child) object.
1630
1631 obj is the object to search.
1632
1633 path is a delimited string, where the delimiter is the given
1634 separator character.
1635
1636 This function searches for the given path, starting at the given object
1637 and traversing its properties as the path specifies. If a given part of the
1638 path is not found, then this function fails with CSON_RC_NotFoundError.
1639
1640 If it finds the given path, it returns the value by assiging *tgt
1641 to it. If tgt is NULL then this function has no side-effects but
1642 will return 0 if the given path is found within the object, so it can be used
1643 to test for existence without fetching it.
1644
1645 Returns 0 if it finds an entry, CSON_RC_NotFoundError if it finds
1646 no item, and any other non-zero error code on a "real" error. Errors include:
1647
1648 - obj or path are NULL: CSON_RC_ArgError
1649
1650 - separator is 0, or path is an empty string or contains only
1651 separator characters: CSON_RC_RangeError
1652
1653 - There is an upper limit on how long a single path component may
1654 be (some "reasonable" internal size), and CSON_RC_RangeError is
1655 returned if that length is violated.
1656
1657
1658 Limitations:
1659
1660 - It has no way to fetch data from arrays this way. i could
1661 imagine, e.g., a path of "subobj.subArray.0" for
1662 subobj.subArray[0], or "0.3.1" for [0][3][1]. But i'm too
1663 lazy/tired to add this.
1664
1665 Example usage:
1666
1667
1668 Assume we have a JSON structure which abstractly looks like:
1669
1670 @code
1671 {"subobj":{"subsubobj":{"myValue":[1,2,3]}}}
1672 @endcode
1673
1674 Out goal is to get the value of myValue. We can do that with:
1675
1676 @code
1677 cson_value * v = NULL;
1678 int rc = cson_object_fetch_sub( object, &v, "subobj.subsubobj.myValue", '.' );
1679 @endcode
1680
1681 Note that because keys in JSON may legally contain a '.', the
1682 separator must be specified by the caller. e.g. the path
1683 "subobj/subsubobj/myValue" with separator='/' is equivalent the
1684 path "subobj.subsubobj.myValue" with separator='.'. The value of 0
1685 is not legal as a separator character because we cannot
1686 distinguish that use from the real end-of-string without requiring
1687 the caller to also pass in the length of the string.
1688
1689 Multiple successive separators in the list are collapsed into a
1690 single separator for parsing purposes. e.g. the path "a...b...c"
1691 (separator='.') is equivalent to "a.b.c".
1692
1693 @see cson_object_get_sub()
1694 @see cson_object_get_sub2()
1695 */
1696 int cson_object_fetch_sub( cson_object const * obj, cson_value ** tgt, char const * path, char separator );
1697
1698 /**
1699 Similar to cson_object_fetch_sub(), but derives the path separator
1700 character from the first byte of the path argument. e.g. the
1701 following arg equivalent:
1702
1703 @code
1704 cson_object_fetch_sub( obj, &tgt, "foo.bar.baz", '.' );
1705 cson_object_fetch_sub2( obj, &tgt, ".foo.bar.baz" );
1706 @endcode
1707 */
1708 int cson_object_fetch_sub2( cson_object const * obj, cson_value ** tgt, char const * path );
1709
1710 /**
1711 Convenience form of cson_object_fetch_sub() which returns NULL if the given
1712 item is not found.
1713 */
1714 cson_value * cson_object_get_sub( cson_object const * obj, char const * path, char sep );
1715
1716 /**
1717 Convenience form of cson_object_fetch_sub2() which returns NULL if the given
1718 item is not found.
1719 */
1720 cson_value * cson_object_get_sub2( cson_object const * obj, char const * path );
1721
1722 /** @enum CSON_MERGE_FLAGS
1723
1724 Flags for cson_object_merge().
1725 */
1726 enum CSON_MERGE_FLAGS {
1727 CSON_MERGE_DEFAULT = 0,
1728 CSON_MERGE_REPLACE = 0x01,
1729 CSON_MERGE_NO_RECURSE = 0x02
1730 };
1731
1732 /**
1733 "Merges" the src object's properties into dest. Each property in
1734 src is copied (using reference counting, not cloning) into dest. If
1735 dest already has the given property then behaviour depends on the
1736 flags argument:
1737
1738 If flag has the CSON_MERGE_REPLACE bit set then this function will
1739 by default replace non-object properties with the src property. If
1740 src and dest both have the property AND it is an Object then this
1741 function operates recursively on those objects. If
1742 CSON_MERGE_NO_RECURSE is set then objects are not recursed in this
1743 manner, and will be completely replaced if CSON_MERGE_REPLACE is
1744 set.
1745
1746 Array properties in dest are NOT recursed for merging - they are
1747 either replaced or left as-is, depending on whether flags contains
1748 he CSON_MERGE_REPLACE bit.
1749
1750 Returns 0 on success. The error conditions are:
1751
1752 - dest or src are NULL or (dest==src) returns CSON_RC_ArgError.
1753
1754 - dest or src contain cyclic references - this will likely cause a
1755 crash due to endless recursion.
1756
1757 Potential TODOs:
1758
1759 - Add a flag to copy clones, not the original values.
1760 */
1761 int cson_object_merge( cson_object * dest, cson_object const * src, int flags );
1762
1763
1764 /**
1765 An iterator type for traversing object properties.
1766
1767 Its values must be considered private, not to be touched by client
1768 code.
1769
1770 @see cson_object_iter_init()
1771 @see cson_object_iter_next()
1772 */
1773 struct cson_object_iterator
1774 {
1775
1776 /** @internal
1777 The underlying object.
1778 */
1779 cson_object const * obj;
1780 /** @internal
1781 Current position in the property list.
1782 */
1783 unsigned int pos;
1784 };
1785 typedef struct cson_object_iterator cson_object_iterator;
1786
1787 /**
1788 Empty-initialized cson_object_iterator object.
1789 */
1790 #define cson_object_iterator_empty_m {NULL/*obj*/,0/*pos*/}
1791
1792 /**
1793 Empty-initialized cson_object_iterator object.
1794 */
1795 extern const cson_object_iterator cson_object_iterator_empty;
1796
1797 /**
1798 Initializes the given iterator to point at the start of obj's
1799 properties. Returns 0 on success or CSON_RC_ArgError if !obj
1800 or !iter.
1801
1802 obj must outlive iter, or results are undefined. Results are also
1803 undefined if obj is modified while the iterator is active.
1804
1805 @see cson_object_iter_next()
1806 */
1807 int cson_object_iter_init( cson_object const * obj, cson_object_iterator * iter );
1808
1809 /** @struct cson_kvp
1810
1811 This class represents a key/value pair and is used for storing
1812 object properties. It is opaque to client code, and the public
1813 API only uses this type for purposes of iterating over cson_object
1814 properties using the cson_object_iterator interfaces.
1815 */
1816
1817 typedef struct cson_kvp cson_kvp;
1818
1819 /**
1820 Returns the next property from the given iterator's object, or NULL
1821 if the end of the property list as been reached.
1822
1823 Note that the order of object properties is undefined by the API,
1824 and may change from version to version.
1825
1826 The returned memory belongs to the underlying object and may be
1827 invalidated by any changes to that object.
1828
1829 Example usage:
1830
1831 @code
1832 cson_object_iterator it;
1833 cson_object_iter_init( myObject, &it ); // only fails if either arg is 0
1834 cson_kvp * kvp;
1835 cson_string const * key;
1836 cson_value const * val;
1837 while( (kvp = cson_object_iter_next(&it) ) )
1838 {
1839 key = cson_kvp_key(kvp);
1840 val = cson_kvp_value(kvp);
1841 ...
1842 }
1843 @endcode
1844
1845 There is no need to clean up an iterator, as it holds no dynamic resources.
1846
1847 @see cson_kvp_key()
1848 @see cson_kvp_value()
1849 */
1850 cson_kvp * cson_object_iter_next( cson_object_iterator * iter );
1851
1852
1853 /**
1854 Returns the key associated with the given key/value pair,
1855 or NULL if !kvp. The memory is owned by the object which contains
1856 the key/value pair, and may be invalidated by any modifications
1857 to that object.
1858 */
1859 cson_string * cson_kvp_key( cson_kvp const * kvp );
1860
1861 /**
1862 Returns the value associated with the given key/value pair,
1863 or NULL if !kvp. The memory is owned by the object which contains
1864 the key/value pair, and may be invalidated by any modifications
1865 to that object.
1866 */
1867 cson_value * cson_kvp_value( cson_kvp const * kvp );
1868
1869 /** @typedef some unsigned int type cson_size_t
1870
1871 */
1872 typedef unsigned int cson_size_t;
1873
1874 /**
1875 A generic buffer class.
1876
1877 They can be used like this:
1878
1879 @code
1880 cson_buffer b = cson_buffer_empty;
1881 int rc = cson_buffer_reserve( &buf, 100 );
1882 if( 0 != rc ) { ... allocation error ... }
1883 ... use buf.mem ...
1884 ... then free it up ...
1885 cson_buffer_reserve( &buf, 0 );
1886 @endcode
1887
1888 To take over ownership of a buffer's memory:
1889
1890 @code
1891 void * mem = b.mem;
1892 // mem is b.capacity bytes long, but only b.used
1893 // bytes of it has been "used" by the API.
1894 b = cson_buffer_empty;
1895 @endcode
1896
1897 The memory now belongs to the caller and must eventually be
1898 free()d.
1899 */
1900 struct cson_buffer
1901 {
1902 /**
1903 The number of bytes allocated for this object.
1904 Use cson_buffer_reserve() to change its value.
1905 */
1906 cson_size_t capacity;
1907 /**
1908 The number of bytes "used" by this object. It is not needed for
1909 all use cases, and management of this value (if needed) is up
1910 to the client. The cson_buffer public API does not use this
1911 member. The intention is that this can be used to track the
1912 length of strings which are allocated via cson_buffer, since
1913 they need an explicit length and/or null terminator.
1914 */
1915 cson_size_t used;
1916
1917 /**
1918 This is a debugging/metric-counting value
1919 intended to help certain malloc()-conscious
1920 clients tweak their memory reservation sizes.
1921 Each time cson_buffer_reserve() expands the
1922 buffer, it increments this value by 1.
1923 */
1924 cson_size_t timesExpanded;
1925
1926 /**
1927 The memory allocated for and owned by this buffer.
1928 Use cson_buffer_reserve() to change its size or
1929 free it. To take over ownership, do:
1930
1931 @code
1932 void * myptr = buf.mem;
1933 buf = cson_buffer_empty;
1934 @endcode
1935
1936 (You might also need to store buf.used and buf.capacity,
1937 depending on what you want to do with the memory.)
1938
1939 When doing so, the memory must eventually be passed to free()
1940 to deallocate it.
1941 */
1942 unsigned char * mem;
1943 };
1944 /** Convenience typedef. */
1945 typedef struct cson_buffer cson_buffer;
1946
1947 /** An empty-initialized cson_buffer object. */
1948 #define cson_buffer_empty_m {0/*capacity*/,0/*used*/,0/*timesExpanded*/,NULL/*mem*/}
1949 /** An empty-initialized cson_buffer object. */
1950 extern const cson_buffer cson_buffer_empty;
1951
1952 /**
1953 Uses cson_output() to append all JSON output to the given buffer
1954 object. The semantics for the (v, opt) parameters, and the return
1955 value, are as documented for cson_output(). buf must be a non-NULL
1956 pointer to a properly initialized buffer (see example below).
1957
1958 Ownership of buf is not changed by calling this.
1959
1960 On success 0 is returned and the contents of buf.mem are guaranteed
1961 to be NULL-terminated. On error the buffer might contain partial
1962 contents, and it should not be used except to free its contents.
1963
1964 On error non-zero is returned. Errors include:
1965
1966 - Invalid arguments: CSON_RC_ArgError
1967
1968 - Buffer cannot be expanded (runs out of memory): CSON_RC_AllocError
1969
1970 Example usage:
1971
1972 @code
1973 cson_buffer buf = cson_buffer_empty;
1974 // optional: cson_buffer_reserve(&buf, 1024 * 10);
1975 int rc = cson_output_buffer( myValue, &buf, NULL );
1976 if( 0 != rc ) {
1977 ... error! ...
1978 }
1979 else {
1980 ... use buffer ...
1981 puts((char const*)buf.mem);
1982 }
1983 // In both cases, we eventually need to clean up the buffer:
1984 cson_buffer_reserve( &buf, 0 );
1985 // Or take over ownership of its memory:
1986 {
1987 char * mem = (char *)buf.mem;
1988 buf = cson_buffer_empty;
1989 ...
1990 free(mem);
1991 }
1992 @endcode
1993
1994 @see cson_output()
1995
1996 */
1997 int cson_output_buffer( cson_value const * v, cson_buffer * buf,
1998 cson_output_opt const * opt );
1999
2000 /**
2001 This works identically to cson_parse_string(), but takes a
2002 cson_buffer object as its input. buf->used bytes of buf->mem are
2003 assumed to be valid JSON input, but it need not be NUL-terminated
2004 (we only read up to buf->used bytes). The value of buf->used is
2005 assumed to be the "string length" of buf->mem, i.e. not including
2006 the NUL terminator.
2007
2008 Returns 0 on success, non-0 on error.
2009
2010 See cson_parse() for the semantics of the tgt, opt, and err
2011 parameters.
2012 */
2013 int cson_parse_buffer( cson_value ** tgt, cson_buffer const * buf,
2014 cson_parse_opt const * opt, cson_parse_info * err );
2015
2016
2017 /**
2018 Reserves the given amount of memory for the given buffer object.
2019
2020 If n is 0 then buf->mem is freed and its state is set to
2021 NULL/0 values.
2022
2023 If buf->capacity is less than or equal to n then 0 is returned and
2024 buf is not modified.
2025
2026 If n is larger than buf->capacity then buf->mem is (re)allocated
2027 and buf->capacity contains the new length. Newly-allocated bytes
2028 are filled with zeroes.
2029
2030 On success 0 is returned. On error non-0 is returned and buf is not
2031 modified.
2032
2033 buf->mem is owned by buf and must eventually be freed by passing an
2034 n value of 0 to this function.
2035
2036 buf->used is never modified by this function unless n is 0, in which case
2037 it is reset.
2038 */
2039 int cson_buffer_reserve( cson_buffer * buf, cson_size_t n );
2040
2041 /**
2042 Fills all bytes of the given buffer with the given character.
2043 Returns the number of bytes set (buf->capacity), or 0 if
2044 !buf or buf has no memory allocated to it.
2045 */
2046 cson_size_t cson_buffer_fill( cson_buffer * buf, char c );
2047
2048 /**
2049 Uses a cson_data_source_f() function to buffer input into a
2050 cson_buffer.
2051
2052 dest must be a non-NULL, initialized (though possibly empty)
2053 cson_buffer object. Its contents, if any, will be overwritten by
2054 this function, and any memory it holds might be re-used.
2055
2056 The src function is called, and passed the state parameter, to
2057 fetch the input. If it returns non-0, this function returns that
2058 error code. src() is called, possibly repeatedly, until it reports
2059 that there is no more data.
2060
2061 Whether or not this function succeeds, dest still owns any memory
2062 pointed to by dest->mem, and the client must eventually free it by
2063 calling cson_buffer_reserve(dest,0).
2064
2065 dest->mem might (and possibly will) be (re)allocated by this
2066 function, so any pointers to it held from before this call might be
2067 invalidated by this call.
2068
2069 On error non-0 is returned and dest has almost certainly been
2070 modified but its state must be considered incomplete.
2071
2072 Errors include:
2073
2074 - dest or src are NULL (CSON_RC_ArgError)
2075
2076 - Allocation error (CSON_RC_AllocError)
2077
2078 - src() returns an error code
2079
2080 Whether or not the state parameter may be NULL depends on
2081 the src implementation requirements.
2082
2083 On success dest will contain the contents read from the input
2084 source. dest->used will be the length of the read-in data, and
2085 dest->mem will point to the memory. dest->mem is automatically
2086 NUL-terminated if this function succeeds, but dest->used does not
2087 count that terminator. On error the state of dest->mem must be
2088 considered incomplete, and is not guaranteed to be NUL-terminated.
2089
2090 Example usage:
2091
2092 @code
2093 cson_buffer buf = cson_buffer_empty;
2094 int rc = cson_buffer_fill_from( &buf,
2095 cson_data_source_FILE,
2096 stdin );
2097 if( rc )
2098 {
2099 fprintf(stderr,"Error %d (%s) while filling buffer.\n",
2100 rc, cson_rc_string(rc));
2101 cson_buffer_reserve( &buf, 0 );
2102 return ...;
2103 }
2104 ... use the buf->mem ...
2105 ... clean up the buffer ...
2106 cson_buffer_reserve( &buf, 0 );
2107 @endcode
2108
2109 To take over ownership of the buffer's memory, do:
2110
2111 @code
2112 void * mem = buf.mem;
2113 buf = cson_buffer_empty;
2114 @endcode
2115
2116 In which case the memory must eventually be passed to free() to
2117 free it.
2118 */
2119 int cson_buffer_fill_from( cson_buffer * dest, cson_data_source_f src, void * state );
2120
2121
2122 /**
2123 Increments the reference count for the given value. This is a
2124 low-level operation and should not normally be used by client code
2125 without understanding exactly what side-effects it introduces.
2126 Mis-use can lead to premature destruction or cause a value instance
2127 to never be properly destructed (i.e. a memory leak).
2128
2129 This function is probably only useful for the following cases:
2130
2131 - You want to hold a reference to a value which is itself contained
2132 in one or more containers, and you need to be sure that your
2133 reference outlives the container(s) and/or that you can free your
2134 copy of the reference without invaliding any references to the same
2135 value held in containers.
2136
2137 - You want to implement "value sharing" behaviour without using an
2138 object or array to contain the shared value. This can be used to
2139 ensure the lifetime of the shared value instance. Each sharing
2140 point adds a reference and simply passed the value to
2141 cson_value_free() when they're done. The object will be kept alive
2142 for other sharing points which added a reference.
2143
2144 Normally any such value handles would be invalidated when the
2145 parent container(s) is/are cleaned up, but this function can be
2146 used to effectively delay the cleanup.
2147
2148 This function, at its lowest level, increments the value's
2149 reference count by 1.
2150
2151 To decrement the reference count, pass the value to
2152 cson_value_free(), after which the value must be considered, from
2153 the perspective of that client code, to be destroyed (though it
2154 will not be if there are still other live references to
2155 it). cson_value_free() will not _actually_ destroy the value until
2156 its reference count drops to 0.
2157
2158 Returns 0 on success. The only error conditions are if v is NULL
2159 (CSON_RC_ArgError) or if the reference increment would overflow
2160 (CSON_RC_RangeError). In theory a client would get allocation
2161 errors long before the reference count could overflow (assuming
2162 those reference counts come from container insertions, as opposed
2163 to via this function).
2164
2165 Insider notes which clients really need to know:
2166
2167 For shared/constant value instances, such as those returned by
2168 cson_value_true() and cson_value_null(), this function has no side
2169 effects - it does not actually modify the reference count because
2170 (A) those instances are shared across all client code and (B) those
2171 objects are static and never get cleaned up. However, that is an
2172 implementation detail which client code should not rely on. In
2173 other words, if you call cson_value_add_reference() 3 times using
2174 the value returned by cson_value_true() (which is incidentally a
2175 shared cson_value instance), you must eventually call
2176 cson_value_free() 3 times to (semantically) remove those
2177 references. However, internally the reference count for that
2178 specific cson_value instance will not be modified and those
2179 objects will never be freed (they're stack-allocated).
2180
2181 It might be interesting to note that newly-created objects
2182 have a reference count of 0 instead of 1. This is partly because
2183 if the initial reference is counted then it makes ownership
2184 problematic when inserting values into containers. e.g. consider the
2185 following code:
2186
2187 @code
2188 // ACHTUNG: this code is hypothetical and does not reflect
2189 // what actually happens!
2190 cson_value * v =
2191 cson_value_new_integer( 42 ); // v's refcount = 1
2192 cson_array_append( myArray, v ); // v's refcount = 2
2193 @endcode
2194
2195 If that were the case, the client would be forced to free his own
2196 reference after inserting it into the container (which is a bit
2197 counter-intuitive as well as intrusive). It would look a bit like
2198 the following and would have to be done after every create/insert
2199 operation:
2200
2201 @code
2202 // ACHTUNG: this code is hypothetical and does not reflect
2203 // what actually happens!
2204 cson_array_append( myArray, v ); // v's refcount = 2
2205 cson_value_free( v ); // v's refcount = 1
2206 @endcode
2207
2208 (As i said: it's counter-intuitive and intrusive.)
2209
2210 Instead, values start with a refcount of 0 and it is only increased
2211 when the value is added to an object/array container or when this
2212 function is used to manually increment it. cson_value_free() treats
2213 a refcount of 0 or 1 equivalently, destroying the value
2214 instance. The only semantic difference between 0 and 1, for
2215 purposes of cleaning up, is that a value with a non-0 refcount has
2216 been had its refcount adjusted, whereas a 0 refcount indicates a
2217 fresh, "unowned" reference.
2218 */
2219 int cson_value_add_reference( cson_value * v );
2220
2221 #if 0
2222 /**
2223 DO NOT use this unless you know EXACTLY what you're doing.
2224 It is only in the public API to work around a couple corner
2225 cases involving extracting child elements and discarding
2226 their parents.
2227
2228 This function sets v's reference count to the given value.
2229 It does not clean up the object if rc is 0.
2230
2231 Returns 0 on success, non-0 on error.
2232 */
2233 int cson_value_refcount_set( cson_value * v, unsigned short rc );
2234 #endif
2235
2236 /**
2237 Deeply copies a JSON value, be it an object/array or a "plain"
2238 value (e.g. number/string/boolean). If cv is not NULL then this
2239 function makes a deep clone of it and returns that clone. Ownership
2240 of the clone is identical t transfered to the caller, who must
2241 eventually free the value using cson_value_free() or add it to a
2242 container object/array to transfer ownership to the container. The
2243 returned object will be of the same logical type as orig.
2244
2245 ACHTUNG: if orig contains any cyclic references at any depth level
2246 this function will endlessly recurse. (Having _any_ cyclic
2247 references violates this library's requirements.)
2248
2249 Returns NULL if orig is NULL or if cloning fails. Assuming that
2250 orig is in a valid state, the only "likely" error case is that an
2251 allocation fails while constructing the clone. In other words, if
2252 cloning fails due to something other than an allocation error then
2253 either orig is in an invalid state or there is a bug.
2254
2255 When this function clones Objects or Arrays it shares any immutable
2256 values (including object keys) between the parent and the
2257 clone. Mutable values (Objects and Arrays) are copied, however.
2258 For example, if we clone:
2259
2260 @code
2261 { a: 1, b: 2, c:["hi"] }
2262 @endcode
2263
2264 The cloned object and the array "c" would be a new Object/Array
2265 instances but the object keys (a,b,b) and the values of (a,b), as
2266 well as the string value within the "c" array, would be shared
2267 between the original and the clone. The "c" array itself would be
2268 deeply cloned, such that future changes to the clone are not
2269 visible to the parent, and vice versa, but immutable values within
2270 the array are shared (in this case the string "hi"). The
2271 justification for this heuristic is that immutable values can never
2272 be changed, so there is no harm in sharing them across
2273 clones. Additionally, such types can never contribute to cycles in
2274 a JSON tree, so they are safe to share this way. Objects and
2275 Arrays, on the other hand, can be modified later and can contribute
2276 to cycles, and thus the clone needs to be an independent instance.
2277 Note, however, that if this function directly passed a
2278 non-Object/Array, that value is deeply cloned. The sharing
2279 behaviour only applies when traversing Objects/Arrays.
2280 */
2281 cson_value * cson_value_clone( cson_value const * orig );
2282
2283 /**
2284 Returns the value handle associated with s. The handle itself owns
2285 s, and ownership of the handle is not changed by calling this
2286 function. If the returned handle is part of a container, calling
2287 cson_value_free() on the returned handle invoked undefined
2288 behaviour (quite possibly downstream when the container tries to
2289 use it).
2290
2291 This function only returns NULL if s is NULL. The length of the
2292 returned string is cson_string_length_bytes().
2293 */
2294 cson_value * cson_string_value(cson_string const * s);
2295 /**
2296 The Object form of cson_string_value(). See that function
2297 for full details.
2298 */
2299 cson_value * cson_object_value(cson_object const * s);
2300
2301 /**
2302 The Array form of cson_string_value(). See that function
2303 for full details.
2304 */
2305 cson_value * cson_array_value(cson_array const * s);
2306
2307
2308 /**
2309 Calculates the approximate in-memory-allocated size of v,
2310 recursively if it is a container type, with the following caveats
2311 and limitations:
2312
2313 If a given value is reference counted and encountered multiple
2314 times within a traversed container, each reference is counted at
2315 full cost. We have no way of knowing if a given reference has been
2316 visited already and whether it should or should not be counted, so
2317 we pessimistically count them even though the _might_ not really
2318 count for the given object tree (it depends on where the other open
2319 references live).
2320
2321 This function returns 0 if any of the following are true:
2322
2323 - v is NULL
2324
2325 - v is one of the special singleton values (null, bools, empty
2326 string, int 0, double 0.0)
2327
2328 All other values require an allocation, and this will return their
2329 total memory cost, including the cson-specific internals and the
2330 native value(s).
2331
2332 Note that because arrays and objects might have more internal slots
2333 allocated than used, the alloced size of a container does not
2334 necessarily increase when a new item is inserted into it. An interesting
2335 side-effect of this is that when cson_clone()ing an array or object, the
2336 size of the clone can actually be less than the original.
2337 */
2338 unsigned int cson_value_msize(cson_value const * v);
2339
2340 /**
2341 Parses command-line-style arguments into a JSON object.
2342
2343 It expects arguments to be in any of these forms, and any number
2344 of leading dashes are treated identically:
2345
2346 --key : Treats key as a boolean with a true value.
2347
2348 --key=VAL : Treats VAL as either a double, integer, or string.
2349
2350 --key= : Treats key as a JSON null (not literal NULL) value.
2351
2352 Arguments not starting with a dash are skipped.
2353
2354 Each key/value pair is inserted into an object. If a given key
2355 appears more than once then only the final entry is actually
2356 stored.
2357
2358 argc and argv are expected to be values from main() (or similar,
2359 possibly adjusted to remove argv[0]).
2360
2361 tgt must be either a pointer to NULL or a pointer to a
2362 client-provided Object. If (NULL==*tgt) then this function
2363 allocates a new object and on success it stores the new object in
2364 *tgt (it is owned by the caller). If (NULL!=*tgt) then it is
2365 assumed to be a properly allocated object. DO NOT pass a pointer to
2366 an unitialized pointer, as that will fool this function into
2367 thinking it is a valid object and Undefined Behaviour will ensue.
2368
2369 If count is not NULL then the number of arugments parsed by this
2370 function are assigned to it. On error, count will be the number of
2371 options successfully parsed before the error was encountered.
2372
2373 On success:
2374
2375 - 0 is returned.
2376
2377 - If (*tgt==NULL) then *tgt is assigned to a newly-allocated
2378 object, owned by the caller. Note that even if no arguments are
2379 parsed, the object is still created.
2380
2381 On error:
2382
2383 - non-0 is returned
2384
2385 - If (*tgt==NULL) then it is not modified.
2386
2387 - If (*tgt!=NULL) (i.e., the caller provides his own object) then
2388 it might contain partial results.
2389 */
2390 int cson_parse_argv_flags( int argc, char const * const * argv,
2391 cson_object ** tgt, unsigned int * count );
2392
2393 /**
2394 Return values for the cson_pack() and cson_unpack() interfaces.
2395 */
2396 enum cson_pack_retval {
2397 /** Signals an out-of-memory error. */
2398 CSON_PACK_ALLOC_ERROR = -1,
2399 /** Signals a syntax error in the format string. */
2400 CSON_PACK_ARG_ERROR = -2,
2401 /**
2402 Signals an that an internal error has occurred.
2403 This indicates a bug in this library.
2404 */
2405 CSON_PACK_INTERNAL_ERROR = -3,
2406 /**
2407 Signals that the JSON document does not validate agains the format
2408 string passed to cson_unpack().
2409 */
2410 CSON_PACK_VALIDATION_ERROR = -4
2411 };
2412
2413 /**
2414 Construct arbitrarily complex JSON documents from native C types.
2415
2416 Create a new object or array and add or merge the passed values and
2417 properties to it according to the supplied format string.
2418
2419 fmt is a format string, it must at least contain an array or object
2420 specifier as its root value. Format specifiers start with a percent sign '\%'
2421 followed by one or more modifiers and a type character. Object properties
2422 are specified as key-value pairs where the key is specified as a string and
2423 passed as an argument of const char *. Any space, tab, carriage return, line
2424 feed, colon and comma characters between format specifiers are ignored.
2425
2426 | Type | Description |
2427 | :--: | :---------- |
2428 | s | creates either a property name or a string value, in case of the former the corresponding argument is a pointer to const char which is a sequence of bytes specifying the name of the property that is to be created, in case of the latter the corresponding argument is a pointer to const char |
2429 | d | creates an integer value, the corresponding argument is an int |
2430 | i | ^ |
2431 | f | creates a floating point value, the corresponding argument is a double |
2432 | b | creates a boolean value, the corresponding argument is an int |
2433 | N | creates a null value |
2434 | [...] | creates an array, the corresponding argument is a pointer to a cson_array |
2435 | {...} | creates an array, the corresponding argument is a pointer to a cson_object |
2436
2437 | Modifier | Description |
2438 | :------: | :---------- |
2439 | l | specifies that the following d or i specifier applies to an argument which is a pointer to long |
2440 | ll | specifies that the following d or i specifier applies to an argument which is a pointer to cson_int_t |
2441
2442 | Short Form | Expands to
2443 | :--------: | :--------- |
2444 | {...} | %*{...} |
2445 | [...] | %*[...] |
2446 | \%D | \%lld |
2447
2448
2449 Returns 0 on success. The error conditions are:
2450
2451 - CSON_PACK_ARG_ERROR: fmt contains a syntax error
2452
2453 - CSON_PACK_ALLOC_ERROR: a memory allocation failed
2454
2455 - CSON_PACK_INTERNAL_ERROR: an internal error has occurred, this is a bug in
2456 cson
2457
2458 Example:
2459 @code
2460 cson_value * root_value;
2461 cson_array * arr;
2462 ...
2463 rc = cson_pack( root_value, "{%s: %d, %s: %[]}", "foo", 42, "bar", arr );
2464 if( 0 != rc ) {
2465 ... error ...
2466 }
2467 @endcode
2468 */
2469 int cson_pack( cson_value **root_valuep, const char *fmt, ... );
2470
2471 /**
2472 Same as cson_pack() except that it takes a va_list instead of a variable
2473 number of arguments.
2474 */
2475 int cson_vpack( cson_value **root_valuep, const char *fmt, va_list args );
2476
2477 /**
2478 Iterate over the given object or array and convert an arbitrary number of
2479 JSON values into their native C types or validates them according to the
2480 given format string fmt.
2481
2482 fmt is a format string, it must at least contain an array or object
2483 specifier as its root value. Format specifiers start with a percent sign '\%'
2484 followed by one or more modifiers and a type character. Object properties
2485 are specified as key-value pairs where the key is specified as a string and
2486 passed as an argument of const char *. Any space, tab, carriage return, line
2487 feed, colon and comma characters between format specifiers are ignored.
2488
2489 | Type | Description |
2490 | :--: | :---------- |
2491 | s | matches a either a property name or a string value, in case of the former the corresponding argument is a pointer to const char which is a sequence of bytes specifying the name of the property that is to be matched, in case of the latter the corresponding argument is a pointer to a pointer to const char unless the 'm' modifier is specified where the the corresponding argument is a pointer to a pointer to char |
2492 | d | matches an integer value and must be used in with the "ll" modifier, the corresponding argument is a pointer to cson_int_t |
2493 | i | ^ |
2494 | f | matches a floating point value, the corresponding argument is a pointer to double |
2495 | b | matches a boolean value, the corresponding argument is a pointer to int |
2496 | N | matches a null value |
2497 | [...] | matches an array, the corresponding argument is a pointer to a pointer to a cson_array |
2498 | {...} | matches an array, the corresponding argument is a pointer to a pointer to a cson_object |
2499
2500 | Modifier | Description |
2501 | :------: | :---------- |
2502 | ? | specifies that the property reffered to by the given property name is optional |
2503 | * | suppresses assignment, only check for the presence and type of the specified value |
2504 | m | allocates a memory buffer for the extracted string |
2505 | ll | specifies that the following d or i specifier applies to an argument which is a pointer to cson_int_t |
2506
2507 | Short Form | Expands to
2508 | :--------: | :--------- |
2509 | {...} | %*{...} |
2510 | [...] | %*[...] |
2511 | \%D | \%lld |
2512
2513 Returns 0 on success. The error conditions are:
2514
2515 - CSON_PACK_ARG_ERROR: fmt contains a syntax error
2516
2517 - CSON_PACK_ALLOC_ERROR: a memory allocation failed
2518
2519 - CSON_PACK_VALIDATION_ERROR: validation failed, the JSON document structure
2520 differs from that described by the format string
2521
2522 - CSON_PACK_INTERNAL_ERROR: an internal error has occurred, this
2523 indicates a bug in this library.
2524
2525 Example:
2526 @code
2527 cson_value * root_value;
2528 cson_int_t x = 0;
2529 cson_array * arr = NULL;
2530 const char *str = NULL;
2531 ...
2532 rc = cson_unpack( root_value, "{%s: %d, %s: %[], %?s: %s}", "foo", &x, "bar", &arr, "baz", &str );
2533 if( rc < 3 && rc >= 0 ) {
2534 ... optional property is missing ...
2535 } else if ( CSON_PACK_ALLOC_ERROR == rc ) {
2536 ... out of memory error ...
2537 } else if ( CSON_PACK_VALIDATION_ERROR == rc ) {
2538 ... unexpected JSON document structure ...
2539 } else if ( rc ) {
2540 ... internal error ...
2541 }
2542 @endcode
2543
2544 */
2545 int cson_unpack( cson_value *root_value, const char *fmt, ... );
2546
2547 /**
2548 Same as cson_unpack() except that it takes a va_list instead of a variable
2549 number of arguments.
2550 */
2551 int cson_vunpack( cson_value *root_value, const char *fmt, va_list args );
2552
2553 /* LICENSE
2554
2555 This software's source code, including accompanying documentation and
2556 demonstration applications, are licensed under the following
2557 conditions...
2558
2559 Certain files are imported from external projects and have their own
2560 licensing terms. Namely, the JSON_parser.* files. See their files for
2561 their official licenses, but the summary is "do what you want [with
2562 them] but leave the license text and copyright in place."
2563
2564 The author (Stephan G. Beal [http://wanderinghorse.net/home/stephan/])
2565 explicitly disclaims copyright in all jurisdictions which recognize
2566 such a disclaimer. In such jurisdictions, this software is released
2567 into the Public Domain.
2568
2569 In jurisdictions which do not recognize Public Domain property
2570 (e.g. Germany as of 2011), this software is Copyright (c) 2011 by
2571 Stephan G. Beal, and is released under the terms of the MIT License
2572 (see below).
2573
2574 In jurisdictions which recognize Public Domain property, the user of
2575 this software may choose to accept it either as 1) Public Domain, 2)
2576 under the conditions of the MIT License (see below), or 3) under the
2577 terms of dual Public Domain/MIT License conditions described here, as
2578 they choose.
2579
2580 The MIT License is about as close to Publi
--- a/src/cson_amalgamation.h
+++ b/src/cson_amalgamation.h
@@ -1,2582 +0,0 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
---END OF MIT LICENSE--
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
D src/linenoise.c
-1324
--- a/src/linenoise.c
+++ b/src/linenoise.c
@@ -1,1324 +0,0 @@
1
-/* linenoise.c -- guerrilla line editing library against the idea that a
2
- * line editing lib needs to be 20,000 lines of C code.
3
- *
4
- * You can find the latest source code at:
5
- *
6
- * http://github.com/antirez/linenoisethub.com/antirez/linenoise)
7
- *
8
- * Does a number of crazy assumptions that happen to be true in 99.9999% of
9
- * the 2010 UNIX computers around.
10
- *
11
- * -----------------------------------------------------------------------2016, Salvatore Sanfilippo <antirez at gmail dot com>
12
- * Copyright (c) 2010-2013, Pieter Noordhuis <pcnoo
13
- * All rights reserved.
14
- *
15
- * Redistribution and use in source and binary forms, with or without
16
- * modification, are permitted provided that the following conditions are
17
- * met:
18
- *
19
- * * Redistributions of source code must retain the above copyright
20
- * notice, this list of conditions and the following disclaimer.
21
- *
22
- * * Redistributions in binary form must reproduce the above copyright
23
- * notice, this list of conditions and the following disclaimer in the
24
- * documentation and/or other materials provided with the distribution.
25
- *
26
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30
- * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37
- *
38
- * ------------------------------------------------------------------------
39
- *
40
- * References:
41
- * - http://invisible-island.net/xterm/ctlseqs/ctlseqs.html
42
- * - http://www.3waylabs.com/nw/WWW/products/wizcon/vt220.html
43
- *
44
- * Todo list:
45
- * - Filter bogus Ctrl+<char> combinations.
46
- * - Win32 support
47
- *
48
- * Bloat:
49
- * - History search like Ctrl+r in readline?
50
- * 1 "utf8.h"
51
-#ifndef UTF8_UTIL_H
52
-#define UTF8_UTIL_H
53
-
54
-#ifdef __cplusplus
55
-exteh"
56
-#ifndefve Bennett <steveb at workware dot net dot au>
57
- *
58
- * All rights reserved.
59
- *
60
- * Redistribution and use in source and binary forms, with or without
61
- * modification, are permitted provided that the following conditions are
62
- * met:
63
- *
64
- * * Redistributions of source code must retain the above copyright
65
- * notice, this list of conditions and the following disclaimer.
66
- *
67
- * * Redistributions in binary form must reproduce the above copyright
68
- * notice, this list of conditions and the following disclaimer in the
69
- * documentation and/or other materials provided with the distribution.
70
- *
71
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
72
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
73
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
74
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
75
- * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
76
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
77
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
78
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
79
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
80
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
81
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
82
- *
83
- * ------------------------------------------------------------------------
84
- *
85
- * References:
86
- * - http://invisible-island.net/xterm/ctlseqs/ctlseqs.html
87
- * - http://www.3waylabs.com/nw/WWW/products/wizcon/vt220.html
88
- *
89
- * Bloat:
90
- * - Completion?
91
- *
92
- * Unix/termios
93
- * ------------
94
- * List of escape sequences used by this program, we do everything just
95
- * a few sequences. In order to be so cheap we may have some
96
- * flickering effect with some slow terminal, but the lesser sequences
97
- * the more compatible.
98
- *
99
- * EL (Erase Line)
100
- * Sequence: ESC [ 0 K
101
- * Effect: clear from cursor to end of line
102
- *
103
- * CUF (CUrsor Forward)
104
- * Sequence: ESC [ n C
105
- * Effect: moves cursor forward n chars
106
- *
107
- * CR (Carriage Return)
108
- * Sequence: \r
109
- * Effect: moves cursor to column 1
110
- *
111
- * The following are used to clear the screen: ESC [ H ESC [ 2 J
112
- * This is actually composed of two sequences:
113
- *
114
- * cursorhome
115
- * Sequence: ESC [ H
116
- * Effect: moves the cursor to upper left corner
117
- *
118
- * ED2 (Clear entire screen)
119
- * Sequence: ESC [ 2 J
120
- * Effect: clear the whole screen
121
- *
122
- * == For highlighting control characters, we also use the following two ==
123
- * SO (enter StandOut)
124
- * Sequence: ESC [ 7 m
125
- * Effect: Uses some standout mode such as reverse video
126
- *
127
- * SE (Standout End)
128
- * Sequence: ESC [ 0 m
129
- * Effect: Exit standout mode
130
- *
131
- * == Only used if TIOCGWINSZ fails ==
132
- * DSR/CPR (Report cursor position)
133
- * Sequence: ESC [ 6 n
134
- * Effect: reports current cursor position as ESC [ NNN ; MMM R
135
- *
136
- * == Only used in multiline mode ==
137
- * CUU (Cursor Up)
138
- * Sequence: ESC [ n A
139
- * Effect: moves cursor up n chars.
140
- *
141
- * CUD (Cursor Down)
142
- * Sequence: ESC [ n B
143
- * Effect: moves cursor down n chars.
144
- *
145
- * win32/console
146
- * -------------
147
- * If __MINGW32__ is defined, the win32 console API is used.
148
- * This could probably be made to work for the msvc compiler too.
149
- * This support based in part on work by Jon Griffiths.
150
- */
151
-
152
-#ifdef _WIN32 /* Windows platform, either MinGW or Visual Studio (MSVC) */
153
-#include <windows.h>
154
-#include <fcntl.h>
155
-#define USE_WINCONSOLE
156
-#ifdef __MINGW32__
157
-#define HAVE_UNISTD_H
158
-#endif
159
-#else
160
-#include <termios.h>
161
-#include <sys/ioctl.h>
162
-#include <poll.h>
163
-#define USE_TERMIOS
164
-#define HAVE_UNISTD_H
165
-#endif
166
-
167
-#ifdef HAVE_UNISTD_H
168
-#include <unistd.h>
169
-#endif
170
-#include <stdlib.h>
171
-#include <stdarg.h>
172
-#include <stdio.h>
173
-#include <assert.h>
174
-#include <errno.h>
175
-#include <string.h>
176
-#include <signal.h>
177
-#include <stdlib.h>
178
-#include <sys/types.h>
179
-
180
-#if defined(_WIN32) && !defined(__MINGW32__)
181
-/* Microsoft headers don't like old POSIX names */
182
-#define strdup _strdup
183
-#define snprintf _snprintf
184
-#endif
185
-
186
-#include "linenoise.h"
187
-#ifndef STR_UTIL_H
188
-#include "utf8.h"
189
-#endif
190
-
191
-#define LINENOISE_DEFAULT_HISTORY_MAX_LEN 100
192
-
193
-/* ctrl('A') -> 0x01 */
194
-#define ctrl(C) ((C) - '@')
195
-/* meta('a') -> 0xe1 */
196
-#define meta(C) ((C) | 0x80)
197
-
198
-/* Use -ve numbers here to co-exist with normal unicode chars */
199
-enum {
200
- SPECIAL_NONE,
201
- /* don't use -1 here since that indicates error */
202
- SPECIAL_UP = -20,
203
- SPECIAL_DOWN = -21,
204
- SPECIAL_LEFT = -22,
205
- SPECIAL_RIGHT = -23,
206
- SPECIAL_DELETE = -24,
207
- SPECIAL_HOME = -25,
208
- SPECIAL_END = -26,
209
- SPECIAL_INSERT = -27,
210
- SPECIAL_PAGE_UP = -28,
211
- SPECIAL_PAGE_DOWN = -29,
212
-
213
- /* Some handy names for other special keycodes */
214
- CHAR_ESCAPE = 27,
215
- CHAR_DELETE = 127,
216
-};
217
-
218
-static int history_max_len = LINENOISE_DEFAULT_HISTORY_MAX_LEN;
219
-static int history_len = 0;
220
-static int history_index = 0;
221
-static char **history = NULL;
222
-
223
-/* Structure to contain the status of the current (being edited) line */
224
-struct current {
225
- stringbuf *buf; /* Current buffer. Always null terminated */
226
- int pos; /* Cursor position, measured in chars */
227
- int cols; /* Size of the window, in chars */
228
- int nrows; /* How many rows are being used in multiline mode (>= 1) */
229
- int rpos; /* The current row containing the cursor - multiline mode only */
230
- int colsright; /* refreshLine() cached cols for insert_char() optimisation */
231
- int colsleft; /* refreshLine() cached cols for remove_char() optimisation */
232
- const char *prompt;
233
- stringbuf *capture; /* capture buffer, or NULL for none. Always null terminated */
234
- stringbuf *output; /* used only during refreshLine() - output accumulator */
235
-#if defined(USE_TERMIOS)
236
- int fd; /* Terminal fd */
237
- int pending; /* pending char fd_read_char() */
238
-#elif defined(USE_WINCONSOLE)
239
- HANDLE outh; /* Console output handle */
240
- HANDLE inh; /* Console input handle */
241
- int rows; /* Screen rows */
242
- int x; /* Current column during output */
243
- int y; /* Current row */
244
-#ifdef USE_UTF8
245
- #define UBUF_MAX_CHARS 132
246
- WORD ubuf[UBUF_MAX_CHARS + 1]; /* Accumulates utf16 output - one extra for final surrogate pairs */
247
- int ubuflen; /* length used in ubuf */
248
- int ubufcols; /* how many columns are represented by the chars in ubuf? */
249
-#endif
250
-#endif
251
-};
252
-
253
-static int fd_read(struct current *current);
254
-static int getWindowSize(struct current *current);
255
-static void cursorDown(struct current *current, int n);
256
-static void cursorUp(struct current *current, int n);
257
-static void eraseEol(struct current *current);
258
-static void refreshLine(struct current *current);
259
-static void refreshLineAlt(struct current *current, const char *prompt, const char *buf, int cursor_pos);
260
-static void setCursorPos(struct current *current, int x);
261
-static void setOutputHighlight(struct current *current, const int *props, int nprops);
262
-static void set_current(struct current *current, const char *str);
263
-
264
-static int fd_isatty(struct current *current)
265
-{
266
-#ifdef USE_TERMIOS
267
- return isatty(current->fd);
268
-#else
269
- (void)current;
270
- return 0;
271
-#endif
272
-}
273
-
274
-void linenoiseHistoryFree(void) {
275
- if (history) {
276
- int j;
277
-
278
- for (j = 0; j < history_len; j++)
279
- free(history[j]);
280
- free(history);
281
- history = NULL;
282
- history_len = 0;
283
- }
284
-}
285
-
286
-typedef enum {
287
- EP_START, /* looking for ESC */
288
- EP_ESC, /* looking for [ */
289
- EP_DIGITS, /* parsing digits */
290
- EP_PROPS, /* parsing digits or semicolons */
291
- EP_END, /* ok */
292
- EP_ERROR, /* error */
293
-} ep_state_t;
294
-
295
-struct esc_parser {
296
- ep_state_t state;
297
- int props[5]; /* properties are stored here */
298
- int maxprops; /* size of the props[] array */
299
- int numprops; /* number of properties found */
300
- int termchar; /* terminator char, or 0 for any alpha */
301
- int current; /* current (partial) property value */
302
-};
303
-
304
-/**
305
- * Initialise the escape sequence parser at *parser.
306
- *
307
- * If termchar is 0 any alpha char terminates ok. Otherwise only the given
308
- * char terminates successfully.
309
- * Run the parser state machine with calls to parseEscapeSequence() for each char.
310
- */
311
-static void initParseEscapeSeq(struct esc_parser *parser, int termchar)
312
-{
313
- parser->state = EP_START;
314
- parser->maxprops = sizeof(parser->props) / sizeof(*parser->props);
315
- parser->numprops = 0;
316
- parser->current = 0;
317
- parser->termchar = termchar;
318
-}
319
-
320
-/**
321
- * Pass character 'ch' into the state machine to parse:
322
- * 'ESC' '[' <digits> (';' <digits>)* <termchar>
323
- *
324
- * The first character must be ESC.
325
- * Returns the current state. The state machine is done when it returns either EP_END
326
- * or EP_ERROR.
327
- *
328
- * On EP_END, the "property/attribute" values can be read from parser->props[]
329
- * of length parser->numprops.
330
- */
331
-static int parseEscapeSequence(struct esc_parser *parser, int ch)
332
-{
333
- switch (parser->state) {
334
- case EP_START:
335
- parser->state = (ch == '\x1b') ? EP_ESC : EP_ERROR;
336
- break;
337
- case EP_ESC:
338
- parser->state = (ch == '[') ? EP_DIGITS : EP_ERROR;
339
- break;
340
- case EP_PROPS:
341
- if (ch == ';') {
342
- after flushing */
343
- if DRAIN,&raw)ved = 0;
344
-
345
- /*goto fatal;
346
- }
347
- rawmode = 1;
348
- return 0;
349
-}
350
-
351
-static void disableRawMode(struct current *current) {
352
- /* Don't even check the return value as it's too late. */
353
- if (rawmode && tcsetattr(current->fd,TCSADRAINsetattr(current->fd,TCSANOW,&orig_termios) != -1)
354
- rawmode = 0;
355
-}
356
-
357
-/* At exit we'll try to fix the terminal to the initial conditions. */
358
-static void linenoiseAtExit(void) {
359
- if (rawmode) {
360
- tDRAIN, &orig_termios);
361
- }
362
- linenoiseHistoryFree();
363
-}
364
-
365
-/* gcc/glibc insists that we care about the return code of write!
366
- * Clarification: This means that a void-cast like "(void) (EXPR)"
367
- * does not work.
368
- */
369
-#define IGNORE_RC(EXPR) if (EXPR) {}
370
-
371
-/**
372
- * Output bytes directly, or accumulate output (if current->output is set)
373
- */
374
-static void outputChars(struct current *current, const char *buf, int len)
375
-{
376
- if (len < 0) {
377
- len = strlen(buf);
378
- }
379
- if (current->output) {
380
- sb_append_len(current->output, buf, len);
381
- }
382
- else {
383
- IGNORE_RC(write(current->fd, buf, len));
384
- }
385
-}
386
-
387
-/* Like outputChars, but using printf-style formatting
388
- */
389
-static void outputFormatted(struct current *current, const char *format, ...)
390
-{
391
- va_list args;
392
- char buf[64];
393
- int n;
394
-
395
- va_start(args, format);
396
- n = vsnprintf(buf, sizeof(buf), format, args);
397
- /* This will never happen because we are sure to use outputFormatted() only for short sequences */
398
- assert(n < (int)sizeof(buf));
399
- va_end(args);
400
- outputChars(current, buf, n);
401
-}
402
-
403
-static void cursorToLeft(struct current *current)
404
-{
405
- outputChars(current, "\r", -1);
406
-}
407
-
408
-static void setOutputHighlight(struct current *current, const int *props, int nprops)
409
-{
410
- outputChars(current, "\x1b[", -1);
411
- while (nprops--) {
412
- outputFormatted(current, "%d%c", *props, (nprops == 0) ? 'm' : ';');
413
- props++;
414
- }
415
-}
416
-
417
-static void eraseEol(struct current *current)
418
-{
419
- outputChars(current, "\x1b[0K", -1);
420
-}
421
-
422
-static void setCursorPos(struct current *current, int x)
423
-{
424
- if (x == 0) {
425
- cursorToLeft(current);
426
- }
427
- else {
428
- outputFormatted(current, "\r\x1b[%dC", x);
429
- }
430
-}
431
-
432
-static void cursorUp(struct current *current, int n)
433
-{
434
- if (n) {
435
- outputFormatted(current, "\x1b[%dA", n);
436
- }
437
-}
438
-
439
-static void cursorDown(struct current *current, int n)
440
-{
441
- if (n) {
442
- outputFormatted(current, "\x1b[%dB", n);
443
- }
444
-}
445
-
446
-void linenoiseClearScreen(void)
447
-{
448
- IGNORE_RC(write(STDOUT_FILENO, "\x1b[H\x1b[2J", 7));
449
-}
450
-
451
-/**
452
- * Reads a char from 'putChars(struct current *current, const char *buf, int len)
453
-{
454
- if (len < 0) {
455
- len = strlen(buf);
456
- }
457
- if (current->output) {
458
- sb_append_len(current->output, buf, len);
459
- int fd
460
- }
461
- else {
462
- IGNORE_RC(write(current->fd, buf, len)p.fd = }
463
-
464
- p.fd = current->fd;
465
- p.events = POLLIN;
466
-
467
- if (poll(&p, 1, timeout) == 0) {
468
- }
469
- if (read(current->fd, &c, 1) != 1) {
470
- return -1;
471
- }
472
- return c;
473
-}
474
-
475
-/**
476
- * Reads a complete utf-8 character
477
- * and returns the unicode value, or -1 on error.
478
- */
479
-static int fd_read(struct current *current)
480
-{
481
-#ifdef USE_UTF8
482
- char buf[MAX_UTF8_LEN];
483
- int n;
484
- return -1;
485
- }
486
-buf[0], 1) != 1) {
487
- < range->lower) {
488
- n = utf8_charlen(buf[0]);
489
- if (n < 1) {
490
- return -1;
491
- }
492
- for (i = 1; i < n; i++) {
493
- if (read(current->fd, &buf[i], 1) != 1) {
494
- return -1;
495
- }
496
- }
497
- /* decode and return the character */
498
- utf8_tounicode(buf, &c);
499
- return c;
500
-#else
501
- ->fdreturn fd_read_char(current, -1);
502
-#endif
503
-}
504
-
505
-
506
-/**
507
- * Stores the current cursor column in '*cols'.
508
- * Returns 1 if OK, or 0 if failed to determine cursor pos.
509
- */
510
-static int queryCursor(struct current *current, i
511
- /* Should not be buffering this output, it needs to go immediately */
512
- assert(current->output == NULL);
513
-
514
- /* control sequence - report cursor location */
515
- outputChars(current, "\x1b[6n", -1);
516
-
517
- /* Parse the response: ESC [ rows ; cols R */
518
- initParseEscapeSeq(&parser, 'R');
519
- while ((ch = fd_read_char(current->fd, 100)) > 0) {
520
- switch (parseEscapeSequence(&parser, ch)) {
521
- default:
522
- continue;
523
- case EP_END:
524
- if (parser.numprops == 2 && parser.props[1] < 1000) {
525
- *cols = parser.props[1];
526
- return 1;
527
- }
528
- break;
529
- caseifndef UTF8_UTIL_H
530
-#define UTFint fd)
531
-{
532
- int c = fd_read_char(fdfd c2 = fd_read_char(current, 50);
533
- if (c2 < 0) {
534
- return c2;
535
- }
536
- if (c == '[' || c == 'O') {
537
- /* Potential arrow key */
538
- switch (c2) {
539
- case 'A':
540
- return SPECIAL_UP;
541
- case 'B':
542
- return SPECIAL_DOWN;
543
- case 'C':
544
- return SPECIAL_RIGHT;
545
- case 'D':
546
- return SPECIAL_LEFT;
547
- case 'F':
548
- return SPECIAL_END;
549
- case 'H':
550
- return SPECIAL_HOME;
551
- }
552
- }
553
- if (c == '[' && c2 >= '1' && c2 <= '8') {
554
- /* extended escape *fd, 50); history_ind'~ifndef UTF8_UTIL_IL_H
555
-#define UTF8_UTIL_H
556
-
557
-#ifdef __cplusplus
558
-extern "C" {
559
-#endif
560
-
561
-/**
562
- * UTF-8 utility functions
563
- *
564
- * (c) 2010-2019 Steve Bennett <[email protected]>
565
- *
566
- * See utf8.c for licence details.
567
- */
568
-
569
-#ifndef USE_UTF8
570
-#include <ctype.h>
571
-
572
-#define MAX_UTF8_LEN 1
573
-
574
-/* No utf-8 support. 1 byte = 1 char */
575
-#define utf8_strlen(S, B) ((B) < 0 ? (int)strlen(S) : (B))
576
-#define utf8_strwidth(S, B) utf8_strlen((S), (B))
577
-#define utf8_tounicode(S, CP) (*(CP) = (unsigned char)*(S), 1)
578
-#define utf8_index(C, I) (I)
579
-#define utf8_charlen(C) 1
580
- #define utf8_width(C) 1
581
-
582
-#else
583
-
584
-#define MAX_UTF8_LEN 4
585
-
586
-/**
587
- * Co#line 1 1) {
588
- rent, 50);
589
- }
590
- }
591
-
592
- return SPECIAL_NONE;
593
-}
594
-#endif
595
-
596
-static void clearOutputHighlight(struct current *current)
597
-{
598
- int nohighlight = 0;
599
- setOutputHighlight(current, &nohighlight, 1);
600
-}
601
-
602
-static void outputControlChar(struct current *current, char ch)
603
-{
604
- int reverse = 7;
605
- setOutputHighlight(current, &reverse, 1);
606
- outputChars(current, "^", 1);
607
- outputChars(current, &ch, 1);
608
- clearOutputHighlight(current);
609
-}
610
-
611
-#ifndef utf8_getchars
612
-static int utf8_getchars(char *buf, int c)
613
-{
614
-#ifdef USE_UTF8
615
- return utf8_fromunicode(buf, c);
616
-#else
617
- *buf = c;
618
- return 1;
619
-#endif
620
-}
621
-#endif
622
-
623
-/**
624
- * Returns the unicode character at the given offset,
625
- * or -1 if none.
626
- */
627
-static int get_char(struct current *current, int pos)
628
-{
629
- if (pos >= 0 && pos < sb_chars(current->buf)) {
630
- int c;
631
- int i = utf8_index(sb_str(current->buf), pos);
632
- (void)utf8_tounicode(sb_str(current->buf) + i, &c);
633
- return c;
634
- }
635
- return -1;
636
-}
637
-
638
-static int char_display_width(int ch)
639
-{
640
- if (ch < ' ') {
641
- /* control chars take two positions */
642
- return 2;
643
- }
644
- else {
645
- return utf8_width(ch);
646
- }
647
-}
648
-
649
-#ifndef NO_COMPLETION
650
-static linenoiseCompletionCallback *completionCallback = NULL;
651
-static void *completionUserdata = NULL;
652
-static int showhints = 1;
653
-static linenoiseHintsCallback *hintsCallback = NULL;
654
-static linenoiseFreeHintsCallback *freeHintsCallback = NULL;
655
-static void *hintsUserdata = NULL;
656
-
657
-static void beep(void) {
658
-#ifdef USE_TERMIOS
659
- fprintf(stderr, "\x7");
660
- fflush(stderr);
661
-#endif
662
-}
663
-
664
-static void freeCompletions(linenoiseCompletions *lc) {
665
- size_t i;
666
- for (i = 0; i < lc->len; i++)
667
- free(lc->cvec[i]);
668
- free(lc->cvec);
669
-}
670
-
671
-static int completeLine(struct current *current) {
672
- linenoiseCompletions lc = { 0, NULL };
673
- int c = 0;
674
-
675
- completionCallback(sb_str(current->buf),&lc,completionUserdata);
676
- if (lc.len == 0) {
677
- beep();
678
- } else {
679
- size_t stop = 0, i = 0;
680
-
681
- while(!stop) {
682
- /* Show completion or original buffer */
683
- if (i < lc.len) {
684
- int chars = utf8_strlen(lc.cvec[i], -1);
685
- refreshLineAlt(current, current->prompt, lc.cvec[i], chars);
686
- } else {
687
- refreshLine(current);
688
- }
689
-
690
- c = fd_read(current);
691
- if (c == -1) {
692
- break;
693
- }
694
-
695
- switch(c) {
696
- case '\t': /* tab */
697
- i = (i+1) % (lc.len+1);
698
- if (i == lc.len) beep();
699
- break;
700
- case CHAR_ESCAPE: /* escape */
701
- /* Re-show original buffer */
702
- if (i < lc.len) {
703
- refreshLine(current);
704
- }
705
- stop = 1;
706
- break;
707
- default:
708
- /* Update buffer and return */
709
- if (i < lc.len) {
710
- set_current(current,lc.cvec[i]);
711
- }
712
- stop = 1;
713
- break;
714
- }
715
- }
716
- }
717
-
718
- freeCompletions(&lc);
719
- return c; /* Return last read character */
720
-}
721
-
722
-/* Register a callback function to be called for tab-completion.
723
- Returns the prior callback so that the caller may (if needed)
724
- restore it when done. */
725
-linenoiseCompletionCallback * linenoiseSetCompletionCallback(linenoiseCompletionCallback *fn, void *userdata) {
726
- linenoiseCompletionCallback * old = completionCallback;
727
- completionCallback = fn;
728
- completionUserdata = userdata;
729
- return old;
730
-}
731
-
732
-void linenoiseAddCompletion(linenoiseCompletions *lc, const char *str) {
733
- lc->cvec = (char **)realloc(lc->cvec,sizeof(char*)*(lc->len+1));
734
- lc->cvec[lc->len++] = strdup(str);
735
-}
736
-
737
-void linenoiseSetHintsCallback(linenoiseHintsCallback *callback, void *userdata)
738
-{
739
- hintsCallback = callback;
740
- hintsUserdata = userdata;
741
-}
742
-
743
-void linenoiseSetFreeHintsCallback(linenoiseFreeHintsCallback *callback)
744
-{
745
- freeHintsCallback = callback;
746
-}
747
-
748
-#endif
749
-
750
-
751
-static const char *reduceSingleBuf(const char *buf, int availcols, int *cursor_pos)
752
-{
753
- /* We have availcols columns available.
754
- * If necessary, strip chars off the front of buf until *cursor_pos
755
- * fits within availcols
756
- */
757
- int needcols = 0;
758
- int pos = 0;
759
- int new_cursor_pos = *cursor_pos;
760
- const char *pt = buf;
761
-
762
- DRL("reduceSingleBuf: availcols=%d, cursor_pos=%d\n", availcols, *cursor_pos);
763
-
764
- while (*pt) {
765
- int ch;
766
- int n = utf8_tounicode(pt, &ch);
767
- pt += n;
768
-
769
- needcols += char_display_width(ch);
770
-
771
- /* If we need too many cols, strip
772
- * chars off the front of buf to make it fit.
773
- * We keep 3 extra cols to the right of the cursor.
774
- * 2 for possible wide chars, 1 for the last column that
775
- * can't be used.
776
- */
777
- while (needcols >= availcols - 3) {
778
- n = utf8_tounicode(buf, &ch);
779
- buf += n;
780
- needcols -= char_display_width(ch);
781
- DRL_CHAR(ch);
782
-
783
- /* and adjust the apparent cursor position */
784
- new_cursor_pos--;
785
-
786
- if (buf == pt) {
787
- /* can't remove more than this */
788
- break;
789
- }
790
- }
791
-
792
- if (pos++ == *cursor_pos) {
793
- break;
794
- }
795
-
796
- }
797
- DRL("<snip>");
798
- DRL_STR(buf);
799
- DRL("\nafter reduce, needcols=%d, new_cursor_pos=%d\n", needcols, new_cursor_pos);
800
-
801
- /* Done, now new_cursor_pos contains the adjusted cursor position
802
- * and buf points to he adjusted start
803
- */
804
- *cursor_pos = new_cursor_pos;
805
- return buf;
806
-}
807
-
808
-static int mlmode = 0;
809
-
810
-void linenoiseSetMultiLine(int enableml)
811
-{
812
- mlmode = enableml;
813
-}
814
-
815
-/* Helper of refreshSingleLine() and refreshMultiLine() to show hints
816
- * to the right of the prompt.
817
- * Returns 1 if a hint was shown, or 0 if not
818
- * If 'display' is 0, does no output. Just returns the appropriate return code.
819
- */
820
-static int refreshShowHints(struct current *current, const char *buf, int availcols, int display)
821
-{
822
- int rc = 0;
823
- if (showhints && hintsCallback && availcols > 0) {
824
- int bold = 0;
825
- int color = -1;
826
- char *hint = hintsCallback(buf, &color, &bold, hintsUserdata);
827
- if (hint) {
828
- rc = 1;
829
- if (display) {
830
- const char *pt;
831
- if (bold == 1 && color == -1) color = 37;
832
- if (bold || color > 0) {
833
- int props[3] = { bold, color, 49 }; /* bold, color, fgnormal */
834
- setOutputHighlight(current, props, 3);
835
- }
836
- DRL("<hint bold=%d,color=%d>", bold, color);
837
- pt = hint;
838
- while (*pt) {
839
- int ch;
840
- int n = utf8_tounicode(pt, &ch);
841
- int width = char_display_width(ch);
842
-
843
- if (width >= availcols) {
844
- DRL("<hinteol>");
845
- break;
846
- }
847
- DRL_CHAR(ch);
848
-
849
- availcols -= width;
850
- outputChars(current, pt, n);
851
- pt += n;
852
- }
853
- if (bold || color > 0) {
854
- clearOutputHighlight(current);
855
- }
856
- /* Call the function to free the hint returned. */
857
- if (freeHintsCallback) freeHintsCallback(hint, hintsUserdata);
858
- }
859
- }
860
- }
861
- return rc;
862
-}
863
-
864
-#ifdef USE_TERMIOS
865
-static void refreshStart(struct current *current)
866
-{
867
- /* We accumulate all output here */
868
- assert(current->output == NULL);
869
- current->output = sb_alloc();
870
-}
871
-
872
-static void refreshEnd(struct current *current)
873
-{
874
- /* Output everything at once */
875
- IGNORE_RC(write(current->fd, sb_str(current->output), sb_len(current->output)));
876
- sb_free(current->output);
877
- current->output = NULL;
878
-}
879
-
880
-static void refreshStartChars(struct current *current)
881
-{
882
- (void)current;
883
-}
884
-
885
-static void refreshNewline(struct current *current)
886
-{
887
- DRL("<nl>");
888
- outputChars(current, "\n", 1);
889
-}
890
-
891
-static void refreshEndChars(struct current *current)
892
-{
893
- (void)current;
894
-}
895
-#endif
896
-
897
-static void refreshLineAlt(struct current *current, const char *prompt, const char *buf, int cursor_pos)
898
-{
899
- int i;
900
- const char *pt;
901
- int displaycol;
902
- int displayrow;
903
- int visible;
904
- int currentpos;
905
- int notecursor;
906
- int cursorcol = 0;
907
- int cursorrow = 0;
908
- int hint;
909
- struct esc_parser parser;
910
-
911
-#ifdef DEBUG_REFRESHLINE
912
- dfh = fopen("linenoise.debuglog", "a");
913
-#endif
914
-
915
- /* Should intercept SIGWINCH. For now, just get the size every time */
916
- getWindowSize(current);
917
-
918
- refreshStart(current);
919
-
920
- DRL("wincols=%d, cursor_pos=%d, nrows=%d, rpos=%d\n", current->cols, cursor_pos, current->nrows, current->rpos);
921
-
922
- /* Here is the plan:
923
- * (a) move the the bottom row, going down the appropriate number of lines
924
- * (b) move to beginning of line and erase the current line
925
- * (c) go up one line and do the same, until we have erased up to the first row
926
- * (d) output the prompt, counting cols and rows, taking into account escape sequences
927
- * (e) output the buffer, counting cols and rows
928
- * (e') when we hit the current pos, save the cursor position
929
- * (f) move the cursor to the saved cursor position
930
- * (g) save the current cursor row and number of rows
931
- */
932
-
933
- /* (a) - The cursor is currently at row rpos */
934
- cursorDown(current, current->nrows - current->rpos - 1);
935
- DRL("<cud=%d>", current->nrows - current->rpos - 1);
936
-
937
- /* (b), (c) - Erase lines upwards until we get to the first row */
938
- for (i = 0; i < current->nrows; i++) {
939
- if (i) {
940
- DRL("<cup>");
941
- cursorUp(current, 1);
942
- }
943
- DRL("<clearline>");
944
- cursorToLeft(current);
945
- eraseEol(current);
946
- }
947
- DRL("\n");
948
-
949
- /* (d) First output the prompt. control sequences don't take up display space */
950
- pt = prompt;
951
- displaycol = 0; /* current display column */
952
- displayrow = 0; /* current display row */
953
- visible = 1;
954
-
955
- refreshStartChars(current);
956
-
957
- while (*pt) {
958
- int width;
959
- int ch;
960
- int n = utf8_tounicode(pt, &ch);
961
-
962
- if (visible && ch == CHAR_ESCAPE) {
963
- /* The start of an escape sequence, so not visible */
964
- visible = 0;
965
- initParseEscapeSeq(&parser, 'm');
966
- DRL("<esc-seq-start>");
967
- }
968
-
969
- if (ch == '\n' || ch == '\r') {
970
- /* treat both CR and NL the same and force wrap */
971
- refreshNewline(current);
972
- displaycol = 0;
973
- displayrow++;
974
- }
975
- else {
976
- width = visible * utf8_width(ch);
977
-
978
- displaycol += width;
979
- if (displaycol >= current->cols) {
980
- /* need to wrap to the next line because of newline or if it doesn't fit
981
- * XXX this is a problem in single line mode
982
- */
983
- refreshNewline(current);
984
- displaycol = width;
985
- displayrow++;
986
- }
987
-
988
- DRL_CHAR(ch);
989
-#ifdef USE_WINCONSOLE
990
- if (visible) {
991
- outputChars(current, pt, n);
992
- }
993
-#else
994
- outputChars(current, pt, n);
995
-#endif
996
- }
997
- pt += n;
998
-
999
- if (!visible) {
1000
- switch (parseEscapeSequence(&parser, ch)) {
1001
- case EP_END:
1002
- visible = 1;
1003
- setOutputHighlight(current, parser.props, parser.numprops);
1004
- DRL("<esc-seq-end,numprops=%d>", parser.numprops);
1005
- break;
1006
- case EP_ERROR:
1007
- DRL("<esc-seq-err>");
1008
- visible = 1;
1009
- break;
1010
- }
1011
- }
1012
- }
1013
-
1014
- /* Now we are at the first line with all lines erased */
1015
- DRL("\nafter prompt: displaycol=%d, displayrow=%d\n", displaycol, displayrow);
1016
-
1017
-
1018
- /* (e) output the buffer, counting cols and rows */
1019
- if (mlmode == 0) {
1020
- /* In this mode we may need to trim chars from the start of the buffer until the
1021
- * cursor fits in the window.
1022
- */
1023
- pt = reduceSingleBuf(buf, current->cols - displaycol, &cursor_pos);
1024
- }
1025
- else {
1026
- pt = buf;
1027
- }
1028
-
1029
- currentpos = 0;
1030
- notecursor = -1;
1031
-
1032
- while (*pt) {
1033
- int ch;
1034
- int n = utf8_tounicode(pt, &ch);
1035
- int width = char_display_width(ch);
1036
-
1037
- if (currentpos == cursor_pos) {
1038
- /* (e') wherever we output this character is where we want the cursor */
1039
- notecursor = 1;
1040
- }
1041
-
1042
- if (displaycol + width >= current->cols) {
1043
- if (mlmode == 0) {
1044
- /* In single line mode stop once we print as much as we can on one line */
1045
- DRL("<slmode>");
1046
- break;
1047
- }
1048
- /* need to wrap to the next line since it doesn't fit */
1049
- refreshNewline(current);
1050
- displaycol = 0;
1051
- displayrow++;
1052
- }
1053
-
1054
- if (notecursor == 1) {
1055
- /* (e') Save this position as the current cursor position */
1056
- cursorcol = displaycol;
1057
- cursorrow = displayrow;
1058
- notecursor = 0;
1059
- DRL("<cursor>");
1060
- }
1061
-
1062
- displaycol += width;
1063
-
1064
- if (ch < ' ') {
1065
- outputControlChar(current, ch + '@');
1066
- }
1067
- else {
1068
- outputChars(current, pt, n);
1069
- }
1070
- DRL_CHAR(ch);
1071
- if (width != 1) {
1072
- DRL("<w=%d>", width);
1073
- }
1074
-
1075
- pt += n;
1076
- currentpos++;
1077
- }
1078
-
1079
- /* If we didn't see the cursor, it is at the current location */
1080
- if (notecursor) {
1081
- DRL("<cursor>");
1082
- cursorcol = displaycol;
1083
- cursorrow = displayrow;
1084
- }
1085
-
1086
- DRL("\nafter buf: displaycol=%d, displayrow=%d, cursorcol=%d, cursorrow=%d\n", displaycol, displayrow, cursorcol, cursorrow);
1087
-
1088
- /* (f) show hints */
1089
- hint = refreshShowHints(current, buf, current->cols - displaycol, 1);
1090
-
1091
- /* Remember how many many cols are available for insert optimisation */
1092
- if (prompt == current->prompt && hint == 0) {
1093
- current->colsright = current->cols - displaycol;
1094
- current->colsleft = displaycol;
1095
- }
1096
- else {
1097
- /* Can't optimise */
1098
- current->colsright = 0;
1099
- current->colsleft = 0;
1100
- }
1101
- DRL("\nafter hints: colsleft=%d, colsright=%d\n\n", current->colsleft, current->colsright);
1102
-
1103
- refreshEndChars(current);
1104
-
1105
- /* (g) move the cursor to the correct place */
1106
- cursorUp(current, displayrow - cursorrow);
1107
- setCursorPos(current, cursorcol);
1108
-
1109
- /* (h) Update the number of rows if larger, but never reduce this */
1110
- if (displayrow >= current->nrows) {
1111
- current->nrows = displayrow + 1;
1112
- }
1113
- /* And remember the row that the cursor is on */
1114
- current->rpos = cursorrow;
1115
-
1116
- refreshEnd(current);
1117
-
1118
-#ifdef DEBUG_REFRESHLINE
1119
- fclose(dfh);
1120
-#endif
1121
-}
1122
-
1123
-static void refreshLine(struct current *current)
1124
-{
1125
- refreshLineAlt(current, current->prompt, sb_str(current->buf), current->pos);
1126
-}
1127
-
1128
-static void set_current(struct current *current, const char *str)
1129
-{
1130
- sb_clear(current->buf);
1131
- sb_append(current->buf, str);
1132
- current->pos = sb_chars(current->buf);
1133
-}
1134
-
1135
-/**
1136
- * Removes the char at 'pos'.
1137
- *
1138
- * Returns 1 if the line needs to be refreshed, 2 if not
1139
- * and 0 if nothing was removed
1140
- */
1141
-static int remove_char(struct current *current, int pos)
1142
-{
1143
- if (pos >= 0 && pos < sb_chars(current->buf)) {
1144
- int offset = utf8_index(sb_str(current->buf), pos);
1145
- int nbytes = utf8_index(sb_str(current->buf) + offset, 1);
1146
- int rc = 1;
1147
-
1148
- /* Now we try to optimise in the simple but very common case that:
1149
- * - outputChars() can be used directly (not win32)
1150
- * - we are removing the char at EOL
1151
- * - the buffer is not empty
1152
- * - there are columns available to the left
1153
- * - the char being deleted is not a wide or utf-8 character
1154
- * - no hints are being shown
1155
- */
1156
- if (current->output && current->pos == pos + 1 && current->pos == sb_chars(current->buf) && pos > 0) {
1157
-#ifdef USE_UTF8
1158
- /* Could implement utf8_prev_len() but simplest just to not optimise this case */
1159
- char last = sb_str(current->buf)[offset];
1160
-#else
1161
- char last = 0;
1162
-#endif
1163
- if (current->colsleft > 0 && (last & 0x80) == 0) {
1164
- /* Have cols on the left and not a UTF-8 char or continuation */
1165
- /* Yes, can optimise */
1166
- current->colsleft--;
1167
- current->colsright++;
1168
- rc = 2;
1169
- }
1170
- }
1171
-
1172
- sb_delete(current->buf, offset, nbytes);
1173
-
1174
- if (current->pos > pos) {
1175
- current->pos--;
1176
- }
1177
- if (rc == 2) {
1178
- if (refreshShowHints(current, sb_str(current->buf), current->colsright, 0)) {
1179
- /* A hint needs to be shown, so can't optimise after all */
1180
- rc = 1;
1181
- }
1182
- else {
1183
- /* optimised output */
1184
- outputChars(current, "\b \b", 3);
1185
- }
1186
- }
1187
- return rc;
1188
- return 1;
1189
- }
1190
- return 0;
1191
-}
1192
-
1193
-/**
1194
- * Insert 'ch' at position 'pos'
1195
- *
1196
- * Returns 1 if the line needs to be refreshed, 2 if not
1197
- * and 0 if nothing was inserted (no room)
1198
- */
1199
-static int insert_char(struct current *current, int pos, int ch)
1200
-{
1201
- if (pos >= 0 && pos <= sb_chars(current->buf)) {
1202
- char buf[MAX_UTF8_LEN + 1];
1203
- int offset = utf8_index(sb_str(current->buf), pos);
1204
- int n = utf8_getchars(buf, ch);
1205
- int rc = 1;
1206
-
1207
- /* null terminate since sb_insert() requires it */
1208
- buf[n] = 0;
1209
-
1210
- /* Now we try to optimise in the simple but very common case that:
1211
- * - outputChars() can be used directly (not win32)
1212
- * - we are inserting at EOL
1213
- * - there are enough columns available
1214
- * - no hints are being shown
1215
- */
1216
- if (current->output && pos == current->pos && pos == sb_chars(current->buf)) {
1217
- int width = char_display_width(ch);
1218
- if (current->colsright > width) {
1219
- /* Yes, can optimise */
1220
- current->colsright -= width;
1221
- current->colsleft -= width;
1222
- rc = 2;
1223
- }
1224
- }
1225
- sb_insert(current->buf, offset, buf);
1226
- if (current->pos >= pos) {
1227
- current->pos++;
1228
- }
1229
- if (rc == 2) {
1230
- if (refreshShowHints(current, sb_str(current->buf), current->colsright, 0)) {
1231
- /* A hint needs to be shown, so can't optimise after all */
1232
- rc = 1;
1233
- }
1234
- else {
1235
- /* optimised output */
1236
- outputChars(current, buf, n);
1237
- }
1238
- }
1239
- return rc;
1240
- }
1241
- return 0;
1242
-}
1243
-
1244
-/**
1245
- * Captures up to 'n' characters starting at 'pos' for the cut buffer.
1246
- *
1247
- * This replaces any existing characters in the cut buffer.
1248
- */
1249
-static void capture_chars(struct current *current, int pos, int nchars)
1250
-{
1251
- if (pos >= 0 && (pos + nchars - 1) < sb_chars(current->buf)) {
1252
- int offset = utf8_index(sb_str(current->buf), pos);
1253
- int nbytes = utf8_index(sb_str(current->buf) + offset, nchars);
1254
-
1255
- if (nbytes > 0) {
1256
- if (current->capture) {
1257
- sb_clear(current->capture);
1258
- }
1259
- else {
1260
- current->capture = sb_alloc();
1261
- }
1262
- sb_append_len(current->capture, sb_str(current->buf) + offset, nbytes);
1263
- }
1264
- }
1265
-}
1266
-
1267
-/**
1268
- * Removes up to 'n' characters at cursor position 'pos'.
1269
- *
1270
- * Returns 0 if no chars were removed or non-zero otherwise.
1271
- */
1272
-static int remove_chars(struct current *current, int pos, int n)
1273
-{
1274
- int removed = 0;
1275
-
1276
- /* First save any chars which will be removed */
1277
- capture_chars(current, pos, n);
1278
-
1279
- while (n-- && remove_char(current, pos)) {
1280
- removed++;
1281
- }
1282
- return removed;
1283
-}
1284
-/**
1285
- * Inserts the characters (string) 'chars' at the cursor position 'pos'.
1286
- *
1287
- * Returns 0 if no chars were inserted or non-zero otherwise.
1288
- */
1289
-static int insert_chars(struct current *current, int pos, const char *chars)
1290
-{
1291
- int inserted = 0;
1292
-
1293
- while (*chars) {
1294
- int ch;
1295
- int n = utf8_tounicode(chars, &ch);
1296
- if (insert_char(current, pos, ch) == 0) {
1297
- break;
1298
- }
1299
- inserted++;
1300
- pos++;
1301
- chars += n;
1302
- }
1303
- return inserted;
1304
-}
1305
-
1306
-static int skip_space_nonspace(struct current *current, int dir, int check_is_space)
1307
-{
1308
- int moved = 0;
1309
- int checkoffset = (dir < 0) ? -1 : 0;
1310
- int limit = (dir < 0) ? 0 : sb_chars(current->buf);
1311
- while (current->pos != limit && (get_char(current, current->pos + checkoffset) == ' ') == check_is_space) {
1312
- current->pos += dir;
1313
- moved++;
1314
- }
1315
- return moved;
1316
-}
1317
-
1318
-static int skip_space(struct current *current, int dir)
1319
-{
1320
- return skip_space_nonspace(current, dir, 1);
1321
-}
1322
-
1323
-static int skip_nonspace(struct current *current, int dir)
1324
-{
--- a/src/linenoise.c
+++ b/src/linenoise.c
@@ -1,1324 +0,0 @@
1 /* linenoise.c -- guerrilla line editing library against the idea that a
2 * line editing lib needs to be 20,000 lines of C code.
3 *
4 * You can find the latest source code at:
5 *
6 * http://github.com/antirez/linenoisethub.com/antirez/linenoise)
7 *
8 * Does a number of crazy assumptions that happen to be true in 99.9999% of
9 * the 2010 UNIX computers around.
10 *
11 * -----------------------------------------------------------------------2016, Salvatore Sanfilippo <antirez at gmail dot com>
12 * Copyright (c) 2010-2013, Pieter Noordhuis <pcnoo
13 * All rights reserved.
14 *
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions are
17 * met:
18 *
19 * * Redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer.
21 *
22 * * Redistributions in binary form must reproduce the above copyright
23 * notice, this list of conditions and the following disclaimer in the
24 * documentation and/or other materials provided with the distribution.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 *
38 * ------------------------------------------------------------------------
39 *
40 * References:
41 * - http://invisible-island.net/xterm/ctlseqs/ctlseqs.html
42 * - http://www.3waylabs.com/nw/WWW/products/wizcon/vt220.html
43 *
44 * Todo list:
45 * - Filter bogus Ctrl+<char> combinations.
46 * - Win32 support
47 *
48 * Bloat:
49 * - History search like Ctrl+r in readline?
50 * 1 "utf8.h"
51 #ifndef UTF8_UTIL_H
52 #define UTF8_UTIL_H
53
54 #ifdef __cplusplus
55 exteh"
56 #ifndefve Bennett <steveb at workware dot net dot au>
57 *
58 * All rights reserved.
59 *
60 * Redistribution and use in source and binary forms, with or without
61 * modification, are permitted provided that the following conditions are
62 * met:
63 *
64 * * Redistributions of source code must retain the above copyright
65 * notice, this list of conditions and the following disclaimer.
66 *
67 * * Redistributions in binary form must reproduce the above copyright
68 * notice, this list of conditions and the following disclaimer in the
69 * documentation and/or other materials provided with the distribution.
70 *
71 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
72 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
73 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
74 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
75 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
76 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
77 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
78 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
79 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
80 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
81 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
82 *
83 * ------------------------------------------------------------------------
84 *
85 * References:
86 * - http://invisible-island.net/xterm/ctlseqs/ctlseqs.html
87 * - http://www.3waylabs.com/nw/WWW/products/wizcon/vt220.html
88 *
89 * Bloat:
90 * - Completion?
91 *
92 * Unix/termios
93 * ------------
94 * List of escape sequences used by this program, we do everything just
95 * a few sequences. In order to be so cheap we may have some
96 * flickering effect with some slow terminal, but the lesser sequences
97 * the more compatible.
98 *
99 * EL (Erase Line)
100 * Sequence: ESC [ 0 K
101 * Effect: clear from cursor to end of line
102 *
103 * CUF (CUrsor Forward)
104 * Sequence: ESC [ n C
105 * Effect: moves cursor forward n chars
106 *
107 * CR (Carriage Return)
108 * Sequence: \r
109 * Effect: moves cursor to column 1
110 *
111 * The following are used to clear the screen: ESC [ H ESC [ 2 J
112 * This is actually composed of two sequences:
113 *
114 * cursorhome
115 * Sequence: ESC [ H
116 * Effect: moves the cursor to upper left corner
117 *
118 * ED2 (Clear entire screen)
119 * Sequence: ESC [ 2 J
120 * Effect: clear the whole screen
121 *
122 * == For highlighting control characters, we also use the following two ==
123 * SO (enter StandOut)
124 * Sequence: ESC [ 7 m
125 * Effect: Uses some standout mode such as reverse video
126 *
127 * SE (Standout End)
128 * Sequence: ESC [ 0 m
129 * Effect: Exit standout mode
130 *
131 * == Only used if TIOCGWINSZ fails ==
132 * DSR/CPR (Report cursor position)
133 * Sequence: ESC [ 6 n
134 * Effect: reports current cursor position as ESC [ NNN ; MMM R
135 *
136 * == Only used in multiline mode ==
137 * CUU (Cursor Up)
138 * Sequence: ESC [ n A
139 * Effect: moves cursor up n chars.
140 *
141 * CUD (Cursor Down)
142 * Sequence: ESC [ n B
143 * Effect: moves cursor down n chars.
144 *
145 * win32/console
146 * -------------
147 * If __MINGW32__ is defined, the win32 console API is used.
148 * This could probably be made to work for the msvc compiler too.
149 * This support based in part on work by Jon Griffiths.
150 */
151
152 #ifdef _WIN32 /* Windows platform, either MinGW or Visual Studio (MSVC) */
153 #include <windows.h>
154 #include <fcntl.h>
155 #define USE_WINCONSOLE
156 #ifdef __MINGW32__
157 #define HAVE_UNISTD_H
158 #endif
159 #else
160 #include <termios.h>
161 #include <sys/ioctl.h>
162 #include <poll.h>
163 #define USE_TERMIOS
164 #define HAVE_UNISTD_H
165 #endif
166
167 #ifdef HAVE_UNISTD_H
168 #include <unistd.h>
169 #endif
170 #include <stdlib.h>
171 #include <stdarg.h>
172 #include <stdio.h>
173 #include <assert.h>
174 #include <errno.h>
175 #include <string.h>
176 #include <signal.h>
177 #include <stdlib.h>
178 #include <sys/types.h>
179
180 #if defined(_WIN32) && !defined(__MINGW32__)
181 /* Microsoft headers don't like old POSIX names */
182 #define strdup _strdup
183 #define snprintf _snprintf
184 #endif
185
186 #include "linenoise.h"
187 #ifndef STR_UTIL_H
188 #include "utf8.h"
189 #endif
190
191 #define LINENOISE_DEFAULT_HISTORY_MAX_LEN 100
192
193 /* ctrl('A') -> 0x01 */
194 #define ctrl(C) ((C) - '@')
195 /* meta('a') -> 0xe1 */
196 #define meta(C) ((C) | 0x80)
197
198 /* Use -ve numbers here to co-exist with normal unicode chars */
199 enum {
200 SPECIAL_NONE,
201 /* don't use -1 here since that indicates error */
202 SPECIAL_UP = -20,
203 SPECIAL_DOWN = -21,
204 SPECIAL_LEFT = -22,
205 SPECIAL_RIGHT = -23,
206 SPECIAL_DELETE = -24,
207 SPECIAL_HOME = -25,
208 SPECIAL_END = -26,
209 SPECIAL_INSERT = -27,
210 SPECIAL_PAGE_UP = -28,
211 SPECIAL_PAGE_DOWN = -29,
212
213 /* Some handy names for other special keycodes */
214 CHAR_ESCAPE = 27,
215 CHAR_DELETE = 127,
216 };
217
218 static int history_max_len = LINENOISE_DEFAULT_HISTORY_MAX_LEN;
219 static int history_len = 0;
220 static int history_index = 0;
221 static char **history = NULL;
222
223 /* Structure to contain the status of the current (being edited) line */
224 struct current {
225 stringbuf *buf; /* Current buffer. Always null terminated */
226 int pos; /* Cursor position, measured in chars */
227 int cols; /* Size of the window, in chars */
228 int nrows; /* How many rows are being used in multiline mode (>= 1) */
229 int rpos; /* The current row containing the cursor - multiline mode only */
230 int colsright; /* refreshLine() cached cols for insert_char() optimisation */
231 int colsleft; /* refreshLine() cached cols for remove_char() optimisation */
232 const char *prompt;
233 stringbuf *capture; /* capture buffer, or NULL for none. Always null terminated */
234 stringbuf *output; /* used only during refreshLine() - output accumulator */
235 #if defined(USE_TERMIOS)
236 int fd; /* Terminal fd */
237 int pending; /* pending char fd_read_char() */
238 #elif defined(USE_WINCONSOLE)
239 HANDLE outh; /* Console output handle */
240 HANDLE inh; /* Console input handle */
241 int rows; /* Screen rows */
242 int x; /* Current column during output */
243 int y; /* Current row */
244 #ifdef USE_UTF8
245 #define UBUF_MAX_CHARS 132
246 WORD ubuf[UBUF_MAX_CHARS + 1]; /* Accumulates utf16 output - one extra for final surrogate pairs */
247 int ubuflen; /* length used in ubuf */
248 int ubufcols; /* how many columns are represented by the chars in ubuf? */
249 #endif
250 #endif
251 };
252
253 static int fd_read(struct current *current);
254 static int getWindowSize(struct current *current);
255 static void cursorDown(struct current *current, int n);
256 static void cursorUp(struct current *current, int n);
257 static void eraseEol(struct current *current);
258 static void refreshLine(struct current *current);
259 static void refreshLineAlt(struct current *current, const char *prompt, const char *buf, int cursor_pos);
260 static void setCursorPos(struct current *current, int x);
261 static void setOutputHighlight(struct current *current, const int *props, int nprops);
262 static void set_current(struct current *current, const char *str);
263
264 static int fd_isatty(struct current *current)
265 {
266 #ifdef USE_TERMIOS
267 return isatty(current->fd);
268 #else
269 (void)current;
270 return 0;
271 #endif
272 }
273
274 void linenoiseHistoryFree(void) {
275 if (history) {
276 int j;
277
278 for (j = 0; j < history_len; j++)
279 free(history[j]);
280 free(history);
281 history = NULL;
282 history_len = 0;
283 }
284 }
285
286 typedef enum {
287 EP_START, /* looking for ESC */
288 EP_ESC, /* looking for [ */
289 EP_DIGITS, /* parsing digits */
290 EP_PROPS, /* parsing digits or semicolons */
291 EP_END, /* ok */
292 EP_ERROR, /* error */
293 } ep_state_t;
294
295 struct esc_parser {
296 ep_state_t state;
297 int props[5]; /* properties are stored here */
298 int maxprops; /* size of the props[] array */
299 int numprops; /* number of properties found */
300 int termchar; /* terminator char, or 0 for any alpha */
301 int current; /* current (partial) property value */
302 };
303
304 /**
305 * Initialise the escape sequence parser at *parser.
306 *
307 * If termchar is 0 any alpha char terminates ok. Otherwise only the given
308 * char terminates successfully.
309 * Run the parser state machine with calls to parseEscapeSequence() for each char.
310 */
311 static void initParseEscapeSeq(struct esc_parser *parser, int termchar)
312 {
313 parser->state = EP_START;
314 parser->maxprops = sizeof(parser->props) / sizeof(*parser->props);
315 parser->numprops = 0;
316 parser->current = 0;
317 parser->termchar = termchar;
318 }
319
320 /**
321 * Pass character 'ch' into the state machine to parse:
322 * 'ESC' '[' <digits> (';' <digits>)* <termchar>
323 *
324 * The first character must be ESC.
325 * Returns the current state. The state machine is done when it returns either EP_END
326 * or EP_ERROR.
327 *
328 * On EP_END, the "property/attribute" values can be read from parser->props[]
329 * of length parser->numprops.
330 */
331 static int parseEscapeSequence(struct esc_parser *parser, int ch)
332 {
333 switch (parser->state) {
334 case EP_START:
335 parser->state = (ch == '\x1b') ? EP_ESC : EP_ERROR;
336 break;
337 case EP_ESC:
338 parser->state = (ch == '[') ? EP_DIGITS : EP_ERROR;
339 break;
340 case EP_PROPS:
341 if (ch == ';') {
342 after flushing */
343 if DRAIN,&raw)ved = 0;
344
345 /*goto fatal;
346 }
347 rawmode = 1;
348 return 0;
349 }
350
351 static void disableRawMode(struct current *current) {
352 /* Don't even check the return value as it's too late. */
353 if (rawmode && tcsetattr(current->fd,TCSADRAINsetattr(current->fd,TCSANOW,&orig_termios) != -1)
354 rawmode = 0;
355 }
356
357 /* At exit we'll try to fix the terminal to the initial conditions. */
358 static void linenoiseAtExit(void) {
359 if (rawmode) {
360 tDRAIN, &orig_termios);
361 }
362 linenoiseHistoryFree();
363 }
364
365 /* gcc/glibc insists that we care about the return code of write!
366 * Clarification: This means that a void-cast like "(void) (EXPR)"
367 * does not work.
368 */
369 #define IGNORE_RC(EXPR) if (EXPR) {}
370
371 /**
372 * Output bytes directly, or accumulate output (if current->output is set)
373 */
374 static void outputChars(struct current *current, const char *buf, int len)
375 {
376 if (len < 0) {
377 len = strlen(buf);
378 }
379 if (current->output) {
380 sb_append_len(current->output, buf, len);
381 }
382 else {
383 IGNORE_RC(write(current->fd, buf, len));
384 }
385 }
386
387 /* Like outputChars, but using printf-style formatting
388 */
389 static void outputFormatted(struct current *current, const char *format, ...)
390 {
391 va_list args;
392 char buf[64];
393 int n;
394
395 va_start(args, format);
396 n = vsnprintf(buf, sizeof(buf), format, args);
397 /* This will never happen because we are sure to use outputFormatted() only for short sequences */
398 assert(n < (int)sizeof(buf));
399 va_end(args);
400 outputChars(current, buf, n);
401 }
402
403 static void cursorToLeft(struct current *current)
404 {
405 outputChars(current, "\r", -1);
406 }
407
408 static void setOutputHighlight(struct current *current, const int *props, int nprops)
409 {
410 outputChars(current, "\x1b[", -1);
411 while (nprops--) {
412 outputFormatted(current, "%d%c", *props, (nprops == 0) ? 'm' : ';');
413 props++;
414 }
415 }
416
417 static void eraseEol(struct current *current)
418 {
419 outputChars(current, "\x1b[0K", -1);
420 }
421
422 static void setCursorPos(struct current *current, int x)
423 {
424 if (x == 0) {
425 cursorToLeft(current);
426 }
427 else {
428 outputFormatted(current, "\r\x1b[%dC", x);
429 }
430 }
431
432 static void cursorUp(struct current *current, int n)
433 {
434 if (n) {
435 outputFormatted(current, "\x1b[%dA", n);
436 }
437 }
438
439 static void cursorDown(struct current *current, int n)
440 {
441 if (n) {
442 outputFormatted(current, "\x1b[%dB", n);
443 }
444 }
445
446 void linenoiseClearScreen(void)
447 {
448 IGNORE_RC(write(STDOUT_FILENO, "\x1b[H\x1b[2J", 7));
449 }
450
451 /**
452 * Reads a char from 'putChars(struct current *current, const char *buf, int len)
453 {
454 if (len < 0) {
455 len = strlen(buf);
456 }
457 if (current->output) {
458 sb_append_len(current->output, buf, len);
459 int fd
460 }
461 else {
462 IGNORE_RC(write(current->fd, buf, len)p.fd = }
463
464 p.fd = current->fd;
465 p.events = POLLIN;
466
467 if (poll(&p, 1, timeout) == 0) {
468 }
469 if (read(current->fd, &c, 1) != 1) {
470 return -1;
471 }
472 return c;
473 }
474
475 /**
476 * Reads a complete utf-8 character
477 * and returns the unicode value, or -1 on error.
478 */
479 static int fd_read(struct current *current)
480 {
481 #ifdef USE_UTF8
482 char buf[MAX_UTF8_LEN];
483 int n;
484 return -1;
485 }
486 buf[0], 1) != 1) {
487 < range->lower) {
488 n = utf8_charlen(buf[0]);
489 if (n < 1) {
490 return -1;
491 }
492 for (i = 1; i < n; i++) {
493 if (read(current->fd, &buf[i], 1) != 1) {
494 return -1;
495 }
496 }
497 /* decode and return the character */
498 utf8_tounicode(buf, &c);
499 return c;
500 #else
501 ->fdreturn fd_read_char(current, -1);
502 #endif
503 }
504
505
506 /**
507 * Stores the current cursor column in '*cols'.
508 * Returns 1 if OK, or 0 if failed to determine cursor pos.
509 */
510 static int queryCursor(struct current *current, i
511 /* Should not be buffering this output, it needs to go immediately */
512 assert(current->output == NULL);
513
514 /* control sequence - report cursor location */
515 outputChars(current, "\x1b[6n", -1);
516
517 /* Parse the response: ESC [ rows ; cols R */
518 initParseEscapeSeq(&parser, 'R');
519 while ((ch = fd_read_char(current->fd, 100)) > 0) {
520 switch (parseEscapeSequence(&parser, ch)) {
521 default:
522 continue;
523 case EP_END:
524 if (parser.numprops == 2 && parser.props[1] < 1000) {
525 *cols = parser.props[1];
526 return 1;
527 }
528 break;
529 caseifndef UTF8_UTIL_H
530 #define UTFint fd)
531 {
532 int c = fd_read_char(fdfd c2 = fd_read_char(current, 50);
533 if (c2 < 0) {
534 return c2;
535 }
536 if (c == '[' || c == 'O') {
537 /* Potential arrow key */
538 switch (c2) {
539 case 'A':
540 return SPECIAL_UP;
541 case 'B':
542 return SPECIAL_DOWN;
543 case 'C':
544 return SPECIAL_RIGHT;
545 case 'D':
546 return SPECIAL_LEFT;
547 case 'F':
548 return SPECIAL_END;
549 case 'H':
550 return SPECIAL_HOME;
551 }
552 }
553 if (c == '[' && c2 >= '1' && c2 <= '8') {
554 /* extended escape *fd, 50); history_ind'~ifndef UTF8_UTIL_IL_H
555 #define UTF8_UTIL_H
556
557 #ifdef __cplusplus
558 extern "C" {
559 #endif
560
561 /**
562 * UTF-8 utility functions
563 *
564 * (c) 2010-2019 Steve Bennett <[email protected]>
565 *
566 * See utf8.c for licence details.
567 */
568
569 #ifndef USE_UTF8
570 #include <ctype.h>
571
572 #define MAX_UTF8_LEN 1
573
574 /* No utf-8 support. 1 byte = 1 char */
575 #define utf8_strlen(S, B) ((B) < 0 ? (int)strlen(S) : (B))
576 #define utf8_strwidth(S, B) utf8_strlen((S), (B))
577 #define utf8_tounicode(S, CP) (*(CP) = (unsigned char)*(S), 1)
578 #define utf8_index(C, I) (I)
579 #define utf8_charlen(C) 1
580 #define utf8_width(C) 1
581
582 #else
583
584 #define MAX_UTF8_LEN 4
585
586 /**
587 * Co#line 1 1) {
588 rent, 50);
589 }
590 }
591
592 return SPECIAL_NONE;
593 }
594 #endif
595
596 static void clearOutputHighlight(struct current *current)
597 {
598 int nohighlight = 0;
599 setOutputHighlight(current, &nohighlight, 1);
600 }
601
602 static void outputControlChar(struct current *current, char ch)
603 {
604 int reverse = 7;
605 setOutputHighlight(current, &reverse, 1);
606 outputChars(current, "^", 1);
607 outputChars(current, &ch, 1);
608 clearOutputHighlight(current);
609 }
610
611 #ifndef utf8_getchars
612 static int utf8_getchars(char *buf, int c)
613 {
614 #ifdef USE_UTF8
615 return utf8_fromunicode(buf, c);
616 #else
617 *buf = c;
618 return 1;
619 #endif
620 }
621 #endif
622
623 /**
624 * Returns the unicode character at the given offset,
625 * or -1 if none.
626 */
627 static int get_char(struct current *current, int pos)
628 {
629 if (pos >= 0 && pos < sb_chars(current->buf)) {
630 int c;
631 int i = utf8_index(sb_str(current->buf), pos);
632 (void)utf8_tounicode(sb_str(current->buf) + i, &c);
633 return c;
634 }
635 return -1;
636 }
637
638 static int char_display_width(int ch)
639 {
640 if (ch < ' ') {
641 /* control chars take two positions */
642 return 2;
643 }
644 else {
645 return utf8_width(ch);
646 }
647 }
648
649 #ifndef NO_COMPLETION
650 static linenoiseCompletionCallback *completionCallback = NULL;
651 static void *completionUserdata = NULL;
652 static int showhints = 1;
653 static linenoiseHintsCallback *hintsCallback = NULL;
654 static linenoiseFreeHintsCallback *freeHintsCallback = NULL;
655 static void *hintsUserdata = NULL;
656
657 static void beep(void) {
658 #ifdef USE_TERMIOS
659 fprintf(stderr, "\x7");
660 fflush(stderr);
661 #endif
662 }
663
664 static void freeCompletions(linenoiseCompletions *lc) {
665 size_t i;
666 for (i = 0; i < lc->len; i++)
667 free(lc->cvec[i]);
668 free(lc->cvec);
669 }
670
671 static int completeLine(struct current *current) {
672 linenoiseCompletions lc = { 0, NULL };
673 int c = 0;
674
675 completionCallback(sb_str(current->buf),&lc,completionUserdata);
676 if (lc.len == 0) {
677 beep();
678 } else {
679 size_t stop = 0, i = 0;
680
681 while(!stop) {
682 /* Show completion or original buffer */
683 if (i < lc.len) {
684 int chars = utf8_strlen(lc.cvec[i], -1);
685 refreshLineAlt(current, current->prompt, lc.cvec[i], chars);
686 } else {
687 refreshLine(current);
688 }
689
690 c = fd_read(current);
691 if (c == -1) {
692 break;
693 }
694
695 switch(c) {
696 case '\t': /* tab */
697 i = (i+1) % (lc.len+1);
698 if (i == lc.len) beep();
699 break;
700 case CHAR_ESCAPE: /* escape */
701 /* Re-show original buffer */
702 if (i < lc.len) {
703 refreshLine(current);
704 }
705 stop = 1;
706 break;
707 default:
708 /* Update buffer and return */
709 if (i < lc.len) {
710 set_current(current,lc.cvec[i]);
711 }
712 stop = 1;
713 break;
714 }
715 }
716 }
717
718 freeCompletions(&lc);
719 return c; /* Return last read character */
720 }
721
722 /* Register a callback function to be called for tab-completion.
723 Returns the prior callback so that the caller may (if needed)
724 restore it when done. */
725 linenoiseCompletionCallback * linenoiseSetCompletionCallback(linenoiseCompletionCallback *fn, void *userdata) {
726 linenoiseCompletionCallback * old = completionCallback;
727 completionCallback = fn;
728 completionUserdata = userdata;
729 return old;
730 }
731
732 void linenoiseAddCompletion(linenoiseCompletions *lc, const char *str) {
733 lc->cvec = (char **)realloc(lc->cvec,sizeof(char*)*(lc->len+1));
734 lc->cvec[lc->len++] = strdup(str);
735 }
736
737 void linenoiseSetHintsCallback(linenoiseHintsCallback *callback, void *userdata)
738 {
739 hintsCallback = callback;
740 hintsUserdata = userdata;
741 }
742
743 void linenoiseSetFreeHintsCallback(linenoiseFreeHintsCallback *callback)
744 {
745 freeHintsCallback = callback;
746 }
747
748 #endif
749
750
751 static const char *reduceSingleBuf(const char *buf, int availcols, int *cursor_pos)
752 {
753 /* We have availcols columns available.
754 * If necessary, strip chars off the front of buf until *cursor_pos
755 * fits within availcols
756 */
757 int needcols = 0;
758 int pos = 0;
759 int new_cursor_pos = *cursor_pos;
760 const char *pt = buf;
761
762 DRL("reduceSingleBuf: availcols=%d, cursor_pos=%d\n", availcols, *cursor_pos);
763
764 while (*pt) {
765 int ch;
766 int n = utf8_tounicode(pt, &ch);
767 pt += n;
768
769 needcols += char_display_width(ch);
770
771 /* If we need too many cols, strip
772 * chars off the front of buf to make it fit.
773 * We keep 3 extra cols to the right of the cursor.
774 * 2 for possible wide chars, 1 for the last column that
775 * can't be used.
776 */
777 while (needcols >= availcols - 3) {
778 n = utf8_tounicode(buf, &ch);
779 buf += n;
780 needcols -= char_display_width(ch);
781 DRL_CHAR(ch);
782
783 /* and adjust the apparent cursor position */
784 new_cursor_pos--;
785
786 if (buf == pt) {
787 /* can't remove more than this */
788 break;
789 }
790 }
791
792 if (pos++ == *cursor_pos) {
793 break;
794 }
795
796 }
797 DRL("<snip>");
798 DRL_STR(buf);
799 DRL("\nafter reduce, needcols=%d, new_cursor_pos=%d\n", needcols, new_cursor_pos);
800
801 /* Done, now new_cursor_pos contains the adjusted cursor position
802 * and buf points to he adjusted start
803 */
804 *cursor_pos = new_cursor_pos;
805 return buf;
806 }
807
808 static int mlmode = 0;
809
810 void linenoiseSetMultiLine(int enableml)
811 {
812 mlmode = enableml;
813 }
814
815 /* Helper of refreshSingleLine() and refreshMultiLine() to show hints
816 * to the right of the prompt.
817 * Returns 1 if a hint was shown, or 0 if not
818 * If 'display' is 0, does no output. Just returns the appropriate return code.
819 */
820 static int refreshShowHints(struct current *current, const char *buf, int availcols, int display)
821 {
822 int rc = 0;
823 if (showhints && hintsCallback && availcols > 0) {
824 int bold = 0;
825 int color = -1;
826 char *hint = hintsCallback(buf, &color, &bold, hintsUserdata);
827 if (hint) {
828 rc = 1;
829 if (display) {
830 const char *pt;
831 if (bold == 1 && color == -1) color = 37;
832 if (bold || color > 0) {
833 int props[3] = { bold, color, 49 }; /* bold, color, fgnormal */
834 setOutputHighlight(current, props, 3);
835 }
836 DRL("<hint bold=%d,color=%d>", bold, color);
837 pt = hint;
838 while (*pt) {
839 int ch;
840 int n = utf8_tounicode(pt, &ch);
841 int width = char_display_width(ch);
842
843 if (width >= availcols) {
844 DRL("<hinteol>");
845 break;
846 }
847 DRL_CHAR(ch);
848
849 availcols -= width;
850 outputChars(current, pt, n);
851 pt += n;
852 }
853 if (bold || color > 0) {
854 clearOutputHighlight(current);
855 }
856 /* Call the function to free the hint returned. */
857 if (freeHintsCallback) freeHintsCallback(hint, hintsUserdata);
858 }
859 }
860 }
861 return rc;
862 }
863
864 #ifdef USE_TERMIOS
865 static void refreshStart(struct current *current)
866 {
867 /* We accumulate all output here */
868 assert(current->output == NULL);
869 current->output = sb_alloc();
870 }
871
872 static void refreshEnd(struct current *current)
873 {
874 /* Output everything at once */
875 IGNORE_RC(write(current->fd, sb_str(current->output), sb_len(current->output)));
876 sb_free(current->output);
877 current->output = NULL;
878 }
879
880 static void refreshStartChars(struct current *current)
881 {
882 (void)current;
883 }
884
885 static void refreshNewline(struct current *current)
886 {
887 DRL("<nl>");
888 outputChars(current, "\n", 1);
889 }
890
891 static void refreshEndChars(struct current *current)
892 {
893 (void)current;
894 }
895 #endif
896
897 static void refreshLineAlt(struct current *current, const char *prompt, const char *buf, int cursor_pos)
898 {
899 int i;
900 const char *pt;
901 int displaycol;
902 int displayrow;
903 int visible;
904 int currentpos;
905 int notecursor;
906 int cursorcol = 0;
907 int cursorrow = 0;
908 int hint;
909 struct esc_parser parser;
910
911 #ifdef DEBUG_REFRESHLINE
912 dfh = fopen("linenoise.debuglog", "a");
913 #endif
914
915 /* Should intercept SIGWINCH. For now, just get the size every time */
916 getWindowSize(current);
917
918 refreshStart(current);
919
920 DRL("wincols=%d, cursor_pos=%d, nrows=%d, rpos=%d\n", current->cols, cursor_pos, current->nrows, current->rpos);
921
922 /* Here is the plan:
923 * (a) move the the bottom row, going down the appropriate number of lines
924 * (b) move to beginning of line and erase the current line
925 * (c) go up one line and do the same, until we have erased up to the first row
926 * (d) output the prompt, counting cols and rows, taking into account escape sequences
927 * (e) output the buffer, counting cols and rows
928 * (e') when we hit the current pos, save the cursor position
929 * (f) move the cursor to the saved cursor position
930 * (g) save the current cursor row and number of rows
931 */
932
933 /* (a) - The cursor is currently at row rpos */
934 cursorDown(current, current->nrows - current->rpos - 1);
935 DRL("<cud=%d>", current->nrows - current->rpos - 1);
936
937 /* (b), (c) - Erase lines upwards until we get to the first row */
938 for (i = 0; i < current->nrows; i++) {
939 if (i) {
940 DRL("<cup>");
941 cursorUp(current, 1);
942 }
943 DRL("<clearline>");
944 cursorToLeft(current);
945 eraseEol(current);
946 }
947 DRL("\n");
948
949 /* (d) First output the prompt. control sequences don't take up display space */
950 pt = prompt;
951 displaycol = 0; /* current display column */
952 displayrow = 0; /* current display row */
953 visible = 1;
954
955 refreshStartChars(current);
956
957 while (*pt) {
958 int width;
959 int ch;
960 int n = utf8_tounicode(pt, &ch);
961
962 if (visible && ch == CHAR_ESCAPE) {
963 /* The start of an escape sequence, so not visible */
964 visible = 0;
965 initParseEscapeSeq(&parser, 'm');
966 DRL("<esc-seq-start>");
967 }
968
969 if (ch == '\n' || ch == '\r') {
970 /* treat both CR and NL the same and force wrap */
971 refreshNewline(current);
972 displaycol = 0;
973 displayrow++;
974 }
975 else {
976 width = visible * utf8_width(ch);
977
978 displaycol += width;
979 if (displaycol >= current->cols) {
980 /* need to wrap to the next line because of newline or if it doesn't fit
981 * XXX this is a problem in single line mode
982 */
983 refreshNewline(current);
984 displaycol = width;
985 displayrow++;
986 }
987
988 DRL_CHAR(ch);
989 #ifdef USE_WINCONSOLE
990 if (visible) {
991 outputChars(current, pt, n);
992 }
993 #else
994 outputChars(current, pt, n);
995 #endif
996 }
997 pt += n;
998
999 if (!visible) {
1000 switch (parseEscapeSequence(&parser, ch)) {
1001 case EP_END:
1002 visible = 1;
1003 setOutputHighlight(current, parser.props, parser.numprops);
1004 DRL("<esc-seq-end,numprops=%d>", parser.numprops);
1005 break;
1006 case EP_ERROR:
1007 DRL("<esc-seq-err>");
1008 visible = 1;
1009 break;
1010 }
1011 }
1012 }
1013
1014 /* Now we are at the first line with all lines erased */
1015 DRL("\nafter prompt: displaycol=%d, displayrow=%d\n", displaycol, displayrow);
1016
1017
1018 /* (e) output the buffer, counting cols and rows */
1019 if (mlmode == 0) {
1020 /* In this mode we may need to trim chars from the start of the buffer until the
1021 * cursor fits in the window.
1022 */
1023 pt = reduceSingleBuf(buf, current->cols - displaycol, &cursor_pos);
1024 }
1025 else {
1026 pt = buf;
1027 }
1028
1029 currentpos = 0;
1030 notecursor = -1;
1031
1032 while (*pt) {
1033 int ch;
1034 int n = utf8_tounicode(pt, &ch);
1035 int width = char_display_width(ch);
1036
1037 if (currentpos == cursor_pos) {
1038 /* (e') wherever we output this character is where we want the cursor */
1039 notecursor = 1;
1040 }
1041
1042 if (displaycol + width >= current->cols) {
1043 if (mlmode == 0) {
1044 /* In single line mode stop once we print as much as we can on one line */
1045 DRL("<slmode>");
1046 break;
1047 }
1048 /* need to wrap to the next line since it doesn't fit */
1049 refreshNewline(current);
1050 displaycol = 0;
1051 displayrow++;
1052 }
1053
1054 if (notecursor == 1) {
1055 /* (e') Save this position as the current cursor position */
1056 cursorcol = displaycol;
1057 cursorrow = displayrow;
1058 notecursor = 0;
1059 DRL("<cursor>");
1060 }
1061
1062 displaycol += width;
1063
1064 if (ch < ' ') {
1065 outputControlChar(current, ch + '@');
1066 }
1067 else {
1068 outputChars(current, pt, n);
1069 }
1070 DRL_CHAR(ch);
1071 if (width != 1) {
1072 DRL("<w=%d>", width);
1073 }
1074
1075 pt += n;
1076 currentpos++;
1077 }
1078
1079 /* If we didn't see the cursor, it is at the current location */
1080 if (notecursor) {
1081 DRL("<cursor>");
1082 cursorcol = displaycol;
1083 cursorrow = displayrow;
1084 }
1085
1086 DRL("\nafter buf: displaycol=%d, displayrow=%d, cursorcol=%d, cursorrow=%d\n", displaycol, displayrow, cursorcol, cursorrow);
1087
1088 /* (f) show hints */
1089 hint = refreshShowHints(current, buf, current->cols - displaycol, 1);
1090
1091 /* Remember how many many cols are available for insert optimisation */
1092 if (prompt == current->prompt && hint == 0) {
1093 current->colsright = current->cols - displaycol;
1094 current->colsleft = displaycol;
1095 }
1096 else {
1097 /* Can't optimise */
1098 current->colsright = 0;
1099 current->colsleft = 0;
1100 }
1101 DRL("\nafter hints: colsleft=%d, colsright=%d\n\n", current->colsleft, current->colsright);
1102
1103 refreshEndChars(current);
1104
1105 /* (g) move the cursor to the correct place */
1106 cursorUp(current, displayrow - cursorrow);
1107 setCursorPos(current, cursorcol);
1108
1109 /* (h) Update the number of rows if larger, but never reduce this */
1110 if (displayrow >= current->nrows) {
1111 current->nrows = displayrow + 1;
1112 }
1113 /* And remember the row that the cursor is on */
1114 current->rpos = cursorrow;
1115
1116 refreshEnd(current);
1117
1118 #ifdef DEBUG_REFRESHLINE
1119 fclose(dfh);
1120 #endif
1121 }
1122
1123 static void refreshLine(struct current *current)
1124 {
1125 refreshLineAlt(current, current->prompt, sb_str(current->buf), current->pos);
1126 }
1127
1128 static void set_current(struct current *current, const char *str)
1129 {
1130 sb_clear(current->buf);
1131 sb_append(current->buf, str);
1132 current->pos = sb_chars(current->buf);
1133 }
1134
1135 /**
1136 * Removes the char at 'pos'.
1137 *
1138 * Returns 1 if the line needs to be refreshed, 2 if not
1139 * and 0 if nothing was removed
1140 */
1141 static int remove_char(struct current *current, int pos)
1142 {
1143 if (pos >= 0 && pos < sb_chars(current->buf)) {
1144 int offset = utf8_index(sb_str(current->buf), pos);
1145 int nbytes = utf8_index(sb_str(current->buf) + offset, 1);
1146 int rc = 1;
1147
1148 /* Now we try to optimise in the simple but very common case that:
1149 * - outputChars() can be used directly (not win32)
1150 * - we are removing the char at EOL
1151 * - the buffer is not empty
1152 * - there are columns available to the left
1153 * - the char being deleted is not a wide or utf-8 character
1154 * - no hints are being shown
1155 */
1156 if (current->output && current->pos == pos + 1 && current->pos == sb_chars(current->buf) && pos > 0) {
1157 #ifdef USE_UTF8
1158 /* Could implement utf8_prev_len() but simplest just to not optimise this case */
1159 char last = sb_str(current->buf)[offset];
1160 #else
1161 char last = 0;
1162 #endif
1163 if (current->colsleft > 0 && (last & 0x80) == 0) {
1164 /* Have cols on the left and not a UTF-8 char or continuation */
1165 /* Yes, can optimise */
1166 current->colsleft--;
1167 current->colsright++;
1168 rc = 2;
1169 }
1170 }
1171
1172 sb_delete(current->buf, offset, nbytes);
1173
1174 if (current->pos > pos) {
1175 current->pos--;
1176 }
1177 if (rc == 2) {
1178 if (refreshShowHints(current, sb_str(current->buf), current->colsright, 0)) {
1179 /* A hint needs to be shown, so can't optimise after all */
1180 rc = 1;
1181 }
1182 else {
1183 /* optimised output */
1184 outputChars(current, "\b \b", 3);
1185 }
1186 }
1187 return rc;
1188 return 1;
1189 }
1190 return 0;
1191 }
1192
1193 /**
1194 * Insert 'ch' at position 'pos'
1195 *
1196 * Returns 1 if the line needs to be refreshed, 2 if not
1197 * and 0 if nothing was inserted (no room)
1198 */
1199 static int insert_char(struct current *current, int pos, int ch)
1200 {
1201 if (pos >= 0 && pos <= sb_chars(current->buf)) {
1202 char buf[MAX_UTF8_LEN + 1];
1203 int offset = utf8_index(sb_str(current->buf), pos);
1204 int n = utf8_getchars(buf, ch);
1205 int rc = 1;
1206
1207 /* null terminate since sb_insert() requires it */
1208 buf[n] = 0;
1209
1210 /* Now we try to optimise in the simple but very common case that:
1211 * - outputChars() can be used directly (not win32)
1212 * - we are inserting at EOL
1213 * - there are enough columns available
1214 * - no hints are being shown
1215 */
1216 if (current->output && pos == current->pos && pos == sb_chars(current->buf)) {
1217 int width = char_display_width(ch);
1218 if (current->colsright > width) {
1219 /* Yes, can optimise */
1220 current->colsright -= width;
1221 current->colsleft -= width;
1222 rc = 2;
1223 }
1224 }
1225 sb_insert(current->buf, offset, buf);
1226 if (current->pos >= pos) {
1227 current->pos++;
1228 }
1229 if (rc == 2) {
1230 if (refreshShowHints(current, sb_str(current->buf), current->colsright, 0)) {
1231 /* A hint needs to be shown, so can't optimise after all */
1232 rc = 1;
1233 }
1234 else {
1235 /* optimised output */
1236 outputChars(current, buf, n);
1237 }
1238 }
1239 return rc;
1240 }
1241 return 0;
1242 }
1243
1244 /**
1245 * Captures up to 'n' characters starting at 'pos' for the cut buffer.
1246 *
1247 * This replaces any existing characters in the cut buffer.
1248 */
1249 static void capture_chars(struct current *current, int pos, int nchars)
1250 {
1251 if (pos >= 0 && (pos + nchars - 1) < sb_chars(current->buf)) {
1252 int offset = utf8_index(sb_str(current->buf), pos);
1253 int nbytes = utf8_index(sb_str(current->buf) + offset, nchars);
1254
1255 if (nbytes > 0) {
1256 if (current->capture) {
1257 sb_clear(current->capture);
1258 }
1259 else {
1260 current->capture = sb_alloc();
1261 }
1262 sb_append_len(current->capture, sb_str(current->buf) + offset, nbytes);
1263 }
1264 }
1265 }
1266
1267 /**
1268 * Removes up to 'n' characters at cursor position 'pos'.
1269 *
1270 * Returns 0 if no chars were removed or non-zero otherwise.
1271 */
1272 static int remove_chars(struct current *current, int pos, int n)
1273 {
1274 int removed = 0;
1275
1276 /* First save any chars which will be removed */
1277 capture_chars(current, pos, n);
1278
1279 while (n-- && remove_char(current, pos)) {
1280 removed++;
1281 }
1282 return removed;
1283 }
1284 /**
1285 * Inserts the characters (string) 'chars' at the cursor position 'pos'.
1286 *
1287 * Returns 0 if no chars were inserted or non-zero otherwise.
1288 */
1289 static int insert_chars(struct current *current, int pos, const char *chars)
1290 {
1291 int inserted = 0;
1292
1293 while (*chars) {
1294 int ch;
1295 int n = utf8_tounicode(chars, &ch);
1296 if (insert_char(current, pos, ch) == 0) {
1297 break;
1298 }
1299 inserted++;
1300 pos++;
1301 chars += n;
1302 }
1303 return inserted;
1304 }
1305
1306 static int skip_space_nonspace(struct current *current, int dir, int check_is_space)
1307 {
1308 int moved = 0;
1309 int checkoffset = (dir < 0) ? -1 : 0;
1310 int limit = (dir < 0) ? 0 : sb_chars(current->buf);
1311 while (current->pos != limit && (get_char(current, current->pos + checkoffset) == ' ') == check_is_space) {
1312 current->pos += dir;
1313 moved++;
1314 }
1315 return moved;
1316 }
1317
1318 static int skip_space(struct current *current, int dir)
1319 {
1320 return skip_space_nonspace(current, dir, 1);
1321 }
1322
1323 static int skip_nonspace(struct current *current, int dir)
1324 {
--- a/src/linenoise.c
+++ b/src/linenoise.c
@@ -1,1324 +0,0 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
D src/linenoise.h
-27
--- a/src/linenoise.h
+++ b/src/linenoise.h
@@ -1,27 +0,0 @@
1
-/* linenoise.h -- VERSION 1.0
2
- *
3
- * Guerrilla line editing libr line editing lib
4
- * needs to be 20,000 lines of C code.
5
- *
6
- * See linenoise.c for more information.
7
- *
8
- * -----------------------------------------------------------------------2014, Salvatore Sanfilippo <antirez at gmail dot com>
9
- * Copyright (c) 2010-2013, Pieter Noordhuis <pcnoordhuis at gmail dot com>
10
- *
11
- * All rights reserved.
12
- *
13
- * Redistribution and use in source and binary forms, with or without
14
- * modification, are permitted provided that the following conditions are
15
- * met:
16
- *
17
- * * Redistributions of source code must retain the above copyright
18
- * notice, this list of conditions and the following disclaimer.
19
- *
20
- * * Redistributions in binary form must reproduce the above copyright
21
- * notice, this list of conditions and the following disclaimer in the
22
- * documentation and/or other materials provided with the distribution.
23
- *
24
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
27
- * A PARTICULAR PURPOSE ARE DISC
--- a/src/linenoise.h
+++ b/src/linenoise.h
@@ -1,27 +0,0 @@
1 /* linenoise.h -- VERSION 1.0
2 *
3 * Guerrilla line editing libr line editing lib
4 * needs to be 20,000 lines of C code.
5 *
6 * See linenoise.c for more information.
7 *
8 * -----------------------------------------------------------------------2014, Salvatore Sanfilippo <antirez at gmail dot com>
9 * Copyright (c) 2010-2013, Pieter Noordhuis <pcnoordhuis at gmail dot com>
10 *
11 * All rights reserved.
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions are
15 * met:
16 *
17 * * Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 *
20 * * Redistributions in binary form must reproduce the above copyright
21 * notice, this list of conditions and the following disclaimer in the
22 * documentation and/or other materials provided with the distribution.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
27 * A PARTICULAR PURPOSE ARE DISC
--- a/src/linenoise.h
+++ b/src/linenoise.h
@@ -1,27 +0,0 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
+15 -21
--- src/main.mk
+++ src/main.mk
@@ -107,11 +107,10 @@
107107
$(SRCDIR)/moderate.c \
108108
$(SRCDIR)/name.c \
109109
$(SRCDIR)/patch.c \
110110
$(SRCDIR)/path.c \
111111
$(SRCDIR)/piechart.c \
112
- $(SRCDIR)/pikchr.c \
113112
$(SRCDIR)/pikchrshow.c \
114113
$(SRCDIR)/pivot.c \
115114
$(SRCDIR)/popen.c \
116115
$(SRCDIR)/pqueue.c \
117116
$(SRCDIR)/printf.c \
@@ -366,11 +365,10 @@
366365
$(OBJDIR)/moderate_.c \
367366
$(OBJDIR)/name_.c \
368367
$(OBJDIR)/patch_.c \
369368
$(OBJDIR)/path_.c \
370369
$(OBJDIR)/piechart_.c \
371
- $(OBJDIR)/pikchr_.c \
372370
$(OBJDIR)/pikchrshow_.c \
373371
$(OBJDIR)/pivot_.c \
374372
$(OBJDIR)/popen_.c \
375373
$(OBJDIR)/pqueue_.c \
376374
$(OBJDIR)/printf_.c \
@@ -516,11 +514,10 @@
516514
$(OBJDIR)/moderate.o \
517515
$(OBJDIR)/name.o \
518516
$(OBJDIR)/patch.o \
519517
$(OBJDIR)/path.o \
520518
$(OBJDIR)/piechart.o \
521
- $(OBJDIR)/pikchr.o \
522519
$(OBJDIR)/pikchrshow.o \
523520
$(OBJDIR)/pivot.o \
524521
$(OBJDIR)/popen.o \
525522
$(OBJDIR)/pqueue.o \
526523
$(OBJDIR)/printf.o \
@@ -728,14 +725,14 @@
728725
SQLITE3_SRC.0 = $(SRCDIR.extsrc)/sqlite3.c
729726
SQLITE3_SRC.1 = $(SRCDIR.extsrc)/sqlite3-see.c
730727
# SQLITE3_SRC.2 is set by top-level configure/makefile process.
731728
SQLITE3_SRC. = $(SRCDIR.extsrc)/sqlite3.c
732729
SQLITE3_SRC = $(SQLITE3_SRC.$(SQLITE3_ORIGIN))
733
-SQLITE3_SHELL_SRC.0 = $(SRCDIR)/shell.c
734
-SQLITE3_SHELL_SRC.1 = $(SRCDIR)/shell-see.c
730
+SQLITE3_SHELL_SRC.0 = $(SRCDIR.extsrc)/shell.c
731
+SQLITE3_SHELL_SRC.1 = $(SRCDIR.extsrc)/shell-see.c
735732
# SQLITE3_SHELL_SRC.2 comes from the configure process
736
-SQLITE3_SHELL_SRC. = $(SRCDIR)/shell.c
733
+SQLITE3_SHELL_SRC. = $(SRCDIR.extsrc)/shell.c
737734
SQLITE3_SHELL_SRC = $(SQLITE3_SHELL_SRC.$(SQLITE3_ORIGIN))
738735
SEE_FLAGS.0 =
739736
SEE_FLAGS.1 = -DSQLITE_HAS_CODEC -DSQLITE_SHELL_DBKEY_PROC=fossil_key
740737
SEE_FLAGS. =
741738
SEE_FLAGS = $(SEE_FLAGS.$(USE_SEE))
@@ -743,10 +740,11 @@
743740
744741
EXTRAOBJ = \
745742
$(SQLITE3_OBJ.$(SQLITE3_ORIGIN)) \
746743
$(MINIZ_OBJ.$(FOSSIL_ENABLE_MINIZ)) \
747744
$(LINENOISE_OBJ.$(USE_LINENOISE)) \
745
+ $(OBJDIR)/pikchr.o \
748746
$(OBJDIR)/shell.o \
749747
$(OBJDIR)/th.o \
750748
$(OBJDIR)/th_lang.o \
751749
$(OBJDIR)/th_tcl.o \
752750
$(OBJDIR)/cson_amalgamation.o
@@ -864,11 +862,10 @@
864862
$(OBJDIR)/moderate_.c:$(OBJDIR)/moderate.h \
865863
$(OBJDIR)/name_.c:$(OBJDIR)/name.h \
866864
$(OBJDIR)/patch_.c:$(OBJDIR)/patch.h \
867865
$(OBJDIR)/path_.c:$(OBJDIR)/path.h \
868866
$(OBJDIR)/piechart_.c:$(OBJDIR)/piechart.h \
869
- $(OBJDIR)/pikchr_.c:$(OBJDIR)/pikchr.h \
870867
$(OBJDIR)/pikchrshow_.c:$(OBJDIR)/pikchrshow.h \
871868
$(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \
872869
$(OBJDIR)/popen_.c:$(OBJDIR)/popen.h \
873870
$(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h \
874871
$(OBJDIR)/printf_.c:$(OBJDIR)/printf.h \
@@ -919,10 +916,12 @@
919916
$(OBJDIR)/winfile_.c:$(OBJDIR)/winfile.h \
920917
$(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h \
921918
$(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h \
922919
$(OBJDIR)/xfersetup_.c:$(OBJDIR)/xfersetup.h \
923920
$(OBJDIR)/zip_.c:$(OBJDIR)/zip.h \
921
+ $(SRCDIR.extsrc)/miniz.c:$(OBJDIR)/miniz.h \
922
+ $(SRCDIR.extsrc)/pikchr.c:$(OBJDIR)/pikchr.h \
924923
$(SRCDIR.extsrc)/sqlite3.h \
925924
$(SRCDIR)/th.h \
926925
$(OBJDIR)/VERSION.h
927926
touch $(OBJDIR)/headers
928927
$(OBJDIR)/headers: Makefile
@@ -1670,18 +1669,10 @@
16701669
$(OBJDIR)/piechart.o: $(OBJDIR)/piechart_.c $(OBJDIR)/piechart.h $(SRCDIR)/config.h
16711670
$(XTCC) -o $(OBJDIR)/piechart.o -c $(OBJDIR)/piechart_.c
16721671
16731672
$(OBJDIR)/piechart.h: $(OBJDIR)/headers
16741673
1675
-$(OBJDIR)/pikchr_.c: $(SRCDIR)/pikchr.c $(OBJDIR)/translate
1676
- $(OBJDIR)/translate $(SRCDIR)/pikchr.c >$@
1677
-
1678
-$(OBJDIR)/pikchr.o: $(OBJDIR)/pikchr_.c $(OBJDIR)/pikchr.h $(SRCDIR)/config.h
1679
- $(XTCC) -o $(OBJDIR)/pikchr.o -c $(OBJDIR)/pikchr_.c
1680
-
1681
-$(OBJDIR)/pikchr.h: $(OBJDIR)/headers
1682
-
16831674
$(OBJDIR)/pikchrshow_.c: $(SRCDIR)/pikchrshow.c $(OBJDIR)/translate
16841675
$(OBJDIR)/translate $(SRCDIR)/pikchrshow.c >$@
16851676
16861677
$(OBJDIR)/pikchrshow.o: $(OBJDIR)/pikchrshow_.c $(OBJDIR)/pikchrshow.h $(SRCDIR)/config.h
16871678
$(XTCC) -o $(OBJDIR)/pikchrshow.o -c $(OBJDIR)/pikchrshow_.c
@@ -2116,12 +2107,12 @@
21162107
$(XTCC) $(SQLITE_OPTIONS) $(SQLITE_CFLAGS) $(SEE_FLAGS) \
21172108
-c $(SQLITE3_SRC) -o $@
21182109
$(OBJDIR)/shell.o: $(SQLITE3_SHELL_SRC) $(SRCDIR.extsrc)/sqlite3.h
21192110
$(XTCC) $(SHELL_OPTIONS) $(SHELL_CFLAGS) $(SEE_FLAGS) $(LINENOISE_DEF.$(USE_LINENOISE)) -c $(SQLITE3_SHELL_SRC) -o $@
21202111
2121
-$(OBJDIR)/linenoise.o: $(SRCDIR)/linenoise.c $(SRCDIR)/linenoise.h
2122
- $(XTCC) -c $(SRCDIR)/linenoise.c -o $@
2112
+$(OBJDIR)/linenoise.o: $(SRCDIR.extsrc)/linenoise.c $(SRCDIR.extsrc)/linenoise.h
2113
+ $(XTCC) -c $(SRCDIR.extsrc)/linenoise.c -o $@
21232114
21242115
$(OBJDIR)/th.o: $(SRCDIR)/th.c
21252116
$(XTCC) -c $(SRCDIR)/th.c -o $@
21262117
21272118
$(OBJDIR)/th_lang.o: $(SRCDIR)/th_lang.c
@@ -2129,18 +2120,21 @@
21292120
21302121
$(OBJDIR)/th_tcl.o: $(SRCDIR)/th_tcl.c
21312122
$(XTCC) -c $(SRCDIR)/th_tcl.c -o $@
21322123
21332124
2134
-$(OBJDIR)/miniz.o: $(SRCDIR)/miniz.c
2135
- $(XTCC) $(MINIZ_OPTIONS) -c $(SRCDIR)/miniz.c -o $@
2125
+$(OBJDIR)/miniz.o: $(SRCDIR.extsrc)/miniz.c
2126
+ $(XTCC) $(MINIZ_OPTIONS) -c $(SRCDIR.extsrc)/miniz.c -o $@
2127
+
2128
+$(OBJDIR)/pikchr.o: $(SRCDIR.extsrc)/pikchr.c
2129
+ $(XTCC) -c $(SRCDIR.extsrc)/pikchr.c -o $@
21362130
2137
-$(OBJDIR)/cson_amalgamation.o: $(SRCDIR)/cson_amalgamation.c
2138
- $(XTCC) -c $(SRCDIR)/cson_amalgamation.c -o $@
2131
+$(OBJDIR)/cson_amalgamation.o: $(SRCDIR.extsrc)/cson_amalgamation.c
2132
+ $(XTCC) -c $(SRCDIR.extsrc)/cson_amalgamation.c -o $@
21392133
21402134
#
21412135
# The list of all the targets that do not correspond to real files. This stops
21422136
# 'make' from getting confused when someone makes an error in a rule.
21432137
#
21442138
21452139
.PHONY: all install test clean
21462140
21472141
21482142
DELETED src/miniz.c
21492143
DELETED src/pikchr.c
21502144
DELETED src/shell.c
--- src/main.mk
+++ src/main.mk
@@ -107,11 +107,10 @@
107 $(SRCDIR)/moderate.c \
108 $(SRCDIR)/name.c \
109 $(SRCDIR)/patch.c \
110 $(SRCDIR)/path.c \
111 $(SRCDIR)/piechart.c \
112 $(SRCDIR)/pikchr.c \
113 $(SRCDIR)/pikchrshow.c \
114 $(SRCDIR)/pivot.c \
115 $(SRCDIR)/popen.c \
116 $(SRCDIR)/pqueue.c \
117 $(SRCDIR)/printf.c \
@@ -366,11 +365,10 @@
366 $(OBJDIR)/moderate_.c \
367 $(OBJDIR)/name_.c \
368 $(OBJDIR)/patch_.c \
369 $(OBJDIR)/path_.c \
370 $(OBJDIR)/piechart_.c \
371 $(OBJDIR)/pikchr_.c \
372 $(OBJDIR)/pikchrshow_.c \
373 $(OBJDIR)/pivot_.c \
374 $(OBJDIR)/popen_.c \
375 $(OBJDIR)/pqueue_.c \
376 $(OBJDIR)/printf_.c \
@@ -516,11 +514,10 @@
516 $(OBJDIR)/moderate.o \
517 $(OBJDIR)/name.o \
518 $(OBJDIR)/patch.o \
519 $(OBJDIR)/path.o \
520 $(OBJDIR)/piechart.o \
521 $(OBJDIR)/pikchr.o \
522 $(OBJDIR)/pikchrshow.o \
523 $(OBJDIR)/pivot.o \
524 $(OBJDIR)/popen.o \
525 $(OBJDIR)/pqueue.o \
526 $(OBJDIR)/printf.o \
@@ -728,14 +725,14 @@
728 SQLITE3_SRC.0 = $(SRCDIR.extsrc)/sqlite3.c
729 SQLITE3_SRC.1 = $(SRCDIR.extsrc)/sqlite3-see.c
730 # SQLITE3_SRC.2 is set by top-level configure/makefile process.
731 SQLITE3_SRC. = $(SRCDIR.extsrc)/sqlite3.c
732 SQLITE3_SRC = $(SQLITE3_SRC.$(SQLITE3_ORIGIN))
733 SQLITE3_SHELL_SRC.0 = $(SRCDIR)/shell.c
734 SQLITE3_SHELL_SRC.1 = $(SRCDIR)/shell-see.c
735 # SQLITE3_SHELL_SRC.2 comes from the configure process
736 SQLITE3_SHELL_SRC. = $(SRCDIR)/shell.c
737 SQLITE3_SHELL_SRC = $(SQLITE3_SHELL_SRC.$(SQLITE3_ORIGIN))
738 SEE_FLAGS.0 =
739 SEE_FLAGS.1 = -DSQLITE_HAS_CODEC -DSQLITE_SHELL_DBKEY_PROC=fossil_key
740 SEE_FLAGS. =
741 SEE_FLAGS = $(SEE_FLAGS.$(USE_SEE))
@@ -743,10 +740,11 @@
743
744 EXTRAOBJ = \
745 $(SQLITE3_OBJ.$(SQLITE3_ORIGIN)) \
746 $(MINIZ_OBJ.$(FOSSIL_ENABLE_MINIZ)) \
747 $(LINENOISE_OBJ.$(USE_LINENOISE)) \
 
748 $(OBJDIR)/shell.o \
749 $(OBJDIR)/th.o \
750 $(OBJDIR)/th_lang.o \
751 $(OBJDIR)/th_tcl.o \
752 $(OBJDIR)/cson_amalgamation.o
@@ -864,11 +862,10 @@
864 $(OBJDIR)/moderate_.c:$(OBJDIR)/moderate.h \
865 $(OBJDIR)/name_.c:$(OBJDIR)/name.h \
866 $(OBJDIR)/patch_.c:$(OBJDIR)/patch.h \
867 $(OBJDIR)/path_.c:$(OBJDIR)/path.h \
868 $(OBJDIR)/piechart_.c:$(OBJDIR)/piechart.h \
869 $(OBJDIR)/pikchr_.c:$(OBJDIR)/pikchr.h \
870 $(OBJDIR)/pikchrshow_.c:$(OBJDIR)/pikchrshow.h \
871 $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \
872 $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h \
873 $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h \
874 $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h \
@@ -919,10 +916,12 @@
919 $(OBJDIR)/winfile_.c:$(OBJDIR)/winfile.h \
920 $(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h \
921 $(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h \
922 $(OBJDIR)/xfersetup_.c:$(OBJDIR)/xfersetup.h \
923 $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h \
 
 
924 $(SRCDIR.extsrc)/sqlite3.h \
925 $(SRCDIR)/th.h \
926 $(OBJDIR)/VERSION.h
927 touch $(OBJDIR)/headers
928 $(OBJDIR)/headers: Makefile
@@ -1670,18 +1669,10 @@
1670 $(OBJDIR)/piechart.o: $(OBJDIR)/piechart_.c $(OBJDIR)/piechart.h $(SRCDIR)/config.h
1671 $(XTCC) -o $(OBJDIR)/piechart.o -c $(OBJDIR)/piechart_.c
1672
1673 $(OBJDIR)/piechart.h: $(OBJDIR)/headers
1674
1675 $(OBJDIR)/pikchr_.c: $(SRCDIR)/pikchr.c $(OBJDIR)/translate
1676 $(OBJDIR)/translate $(SRCDIR)/pikchr.c >$@
1677
1678 $(OBJDIR)/pikchr.o: $(OBJDIR)/pikchr_.c $(OBJDIR)/pikchr.h $(SRCDIR)/config.h
1679 $(XTCC) -o $(OBJDIR)/pikchr.o -c $(OBJDIR)/pikchr_.c
1680
1681 $(OBJDIR)/pikchr.h: $(OBJDIR)/headers
1682
1683 $(OBJDIR)/pikchrshow_.c: $(SRCDIR)/pikchrshow.c $(OBJDIR)/translate
1684 $(OBJDIR)/translate $(SRCDIR)/pikchrshow.c >$@
1685
1686 $(OBJDIR)/pikchrshow.o: $(OBJDIR)/pikchrshow_.c $(OBJDIR)/pikchrshow.h $(SRCDIR)/config.h
1687 $(XTCC) -o $(OBJDIR)/pikchrshow.o -c $(OBJDIR)/pikchrshow_.c
@@ -2116,12 +2107,12 @@
2116 $(XTCC) $(SQLITE_OPTIONS) $(SQLITE_CFLAGS) $(SEE_FLAGS) \
2117 -c $(SQLITE3_SRC) -o $@
2118 $(OBJDIR)/shell.o: $(SQLITE3_SHELL_SRC) $(SRCDIR.extsrc)/sqlite3.h
2119 $(XTCC) $(SHELL_OPTIONS) $(SHELL_CFLAGS) $(SEE_FLAGS) $(LINENOISE_DEF.$(USE_LINENOISE)) -c $(SQLITE3_SHELL_SRC) -o $@
2120
2121 $(OBJDIR)/linenoise.o: $(SRCDIR)/linenoise.c $(SRCDIR)/linenoise.h
2122 $(XTCC) -c $(SRCDIR)/linenoise.c -o $@
2123
2124 $(OBJDIR)/th.o: $(SRCDIR)/th.c
2125 $(XTCC) -c $(SRCDIR)/th.c -o $@
2126
2127 $(OBJDIR)/th_lang.o: $(SRCDIR)/th_lang.c
@@ -2129,18 +2120,21 @@
2129
2130 $(OBJDIR)/th_tcl.o: $(SRCDIR)/th_tcl.c
2131 $(XTCC) -c $(SRCDIR)/th_tcl.c -o $@
2132
2133
2134 $(OBJDIR)/miniz.o: $(SRCDIR)/miniz.c
2135 $(XTCC) $(MINIZ_OPTIONS) -c $(SRCDIR)/miniz.c -o $@
 
 
 
2136
2137 $(OBJDIR)/cson_amalgamation.o: $(SRCDIR)/cson_amalgamation.c
2138 $(XTCC) -c $(SRCDIR)/cson_amalgamation.c -o $@
2139
2140 #
2141 # The list of all the targets that do not correspond to real files. This stops
2142 # 'make' from getting confused when someone makes an error in a rule.
2143 #
2144
2145 .PHONY: all install test clean
2146
2147
2148 ELETED src/miniz.c
2149 ELETED src/pikchr.c
2150 ELETED src/shell.c
--- src/main.mk
+++ src/main.mk
@@ -107,11 +107,10 @@
107 $(SRCDIR)/moderate.c \
108 $(SRCDIR)/name.c \
109 $(SRCDIR)/patch.c \
110 $(SRCDIR)/path.c \
111 $(SRCDIR)/piechart.c \
 
112 $(SRCDIR)/pikchrshow.c \
113 $(SRCDIR)/pivot.c \
114 $(SRCDIR)/popen.c \
115 $(SRCDIR)/pqueue.c \
116 $(SRCDIR)/printf.c \
@@ -366,11 +365,10 @@
365 $(OBJDIR)/moderate_.c \
366 $(OBJDIR)/name_.c \
367 $(OBJDIR)/patch_.c \
368 $(OBJDIR)/path_.c \
369 $(OBJDIR)/piechart_.c \
 
370 $(OBJDIR)/pikchrshow_.c \
371 $(OBJDIR)/pivot_.c \
372 $(OBJDIR)/popen_.c \
373 $(OBJDIR)/pqueue_.c \
374 $(OBJDIR)/printf_.c \
@@ -516,11 +514,10 @@
514 $(OBJDIR)/moderate.o \
515 $(OBJDIR)/name.o \
516 $(OBJDIR)/patch.o \
517 $(OBJDIR)/path.o \
518 $(OBJDIR)/piechart.o \
 
519 $(OBJDIR)/pikchrshow.o \
520 $(OBJDIR)/pivot.o \
521 $(OBJDIR)/popen.o \
522 $(OBJDIR)/pqueue.o \
523 $(OBJDIR)/printf.o \
@@ -728,14 +725,14 @@
725 SQLITE3_SRC.0 = $(SRCDIR.extsrc)/sqlite3.c
726 SQLITE3_SRC.1 = $(SRCDIR.extsrc)/sqlite3-see.c
727 # SQLITE3_SRC.2 is set by top-level configure/makefile process.
728 SQLITE3_SRC. = $(SRCDIR.extsrc)/sqlite3.c
729 SQLITE3_SRC = $(SQLITE3_SRC.$(SQLITE3_ORIGIN))
730 SQLITE3_SHELL_SRC.0 = $(SRCDIR.extsrc)/shell.c
731 SQLITE3_SHELL_SRC.1 = $(SRCDIR.extsrc)/shell-see.c
732 # SQLITE3_SHELL_SRC.2 comes from the configure process
733 SQLITE3_SHELL_SRC. = $(SRCDIR.extsrc)/shell.c
734 SQLITE3_SHELL_SRC = $(SQLITE3_SHELL_SRC.$(SQLITE3_ORIGIN))
735 SEE_FLAGS.0 =
736 SEE_FLAGS.1 = -DSQLITE_HAS_CODEC -DSQLITE_SHELL_DBKEY_PROC=fossil_key
737 SEE_FLAGS. =
738 SEE_FLAGS = $(SEE_FLAGS.$(USE_SEE))
@@ -743,10 +740,11 @@
740
741 EXTRAOBJ = \
742 $(SQLITE3_OBJ.$(SQLITE3_ORIGIN)) \
743 $(MINIZ_OBJ.$(FOSSIL_ENABLE_MINIZ)) \
744 $(LINENOISE_OBJ.$(USE_LINENOISE)) \
745 $(OBJDIR)/pikchr.o \
746 $(OBJDIR)/shell.o \
747 $(OBJDIR)/th.o \
748 $(OBJDIR)/th_lang.o \
749 $(OBJDIR)/th_tcl.o \
750 $(OBJDIR)/cson_amalgamation.o
@@ -864,11 +862,10 @@
862 $(OBJDIR)/moderate_.c:$(OBJDIR)/moderate.h \
863 $(OBJDIR)/name_.c:$(OBJDIR)/name.h \
864 $(OBJDIR)/patch_.c:$(OBJDIR)/patch.h \
865 $(OBJDIR)/path_.c:$(OBJDIR)/path.h \
866 $(OBJDIR)/piechart_.c:$(OBJDIR)/piechart.h \
 
867 $(OBJDIR)/pikchrshow_.c:$(OBJDIR)/pikchrshow.h \
868 $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \
869 $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h \
870 $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h \
871 $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h \
@@ -919,10 +916,12 @@
916 $(OBJDIR)/winfile_.c:$(OBJDIR)/winfile.h \
917 $(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h \
918 $(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h \
919 $(OBJDIR)/xfersetup_.c:$(OBJDIR)/xfersetup.h \
920 $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h \
921 $(SRCDIR.extsrc)/miniz.c:$(OBJDIR)/miniz.h \
922 $(SRCDIR.extsrc)/pikchr.c:$(OBJDIR)/pikchr.h \
923 $(SRCDIR.extsrc)/sqlite3.h \
924 $(SRCDIR)/th.h \
925 $(OBJDIR)/VERSION.h
926 touch $(OBJDIR)/headers
927 $(OBJDIR)/headers: Makefile
@@ -1670,18 +1669,10 @@
1669 $(OBJDIR)/piechart.o: $(OBJDIR)/piechart_.c $(OBJDIR)/piechart.h $(SRCDIR)/config.h
1670 $(XTCC) -o $(OBJDIR)/piechart.o -c $(OBJDIR)/piechart_.c
1671
1672 $(OBJDIR)/piechart.h: $(OBJDIR)/headers
1673
 
 
 
 
 
 
 
 
1674 $(OBJDIR)/pikchrshow_.c: $(SRCDIR)/pikchrshow.c $(OBJDIR)/translate
1675 $(OBJDIR)/translate $(SRCDIR)/pikchrshow.c >$@
1676
1677 $(OBJDIR)/pikchrshow.o: $(OBJDIR)/pikchrshow_.c $(OBJDIR)/pikchrshow.h $(SRCDIR)/config.h
1678 $(XTCC) -o $(OBJDIR)/pikchrshow.o -c $(OBJDIR)/pikchrshow_.c
@@ -2116,12 +2107,12 @@
2107 $(XTCC) $(SQLITE_OPTIONS) $(SQLITE_CFLAGS) $(SEE_FLAGS) \
2108 -c $(SQLITE3_SRC) -o $@
2109 $(OBJDIR)/shell.o: $(SQLITE3_SHELL_SRC) $(SRCDIR.extsrc)/sqlite3.h
2110 $(XTCC) $(SHELL_OPTIONS) $(SHELL_CFLAGS) $(SEE_FLAGS) $(LINENOISE_DEF.$(USE_LINENOISE)) -c $(SQLITE3_SHELL_SRC) -o $@
2111
2112 $(OBJDIR)/linenoise.o: $(SRCDIR.extsrc)/linenoise.c $(SRCDIR.extsrc)/linenoise.h
2113 $(XTCC) -c $(SRCDIR.extsrc)/linenoise.c -o $@
2114
2115 $(OBJDIR)/th.o: $(SRCDIR)/th.c
2116 $(XTCC) -c $(SRCDIR)/th.c -o $@
2117
2118 $(OBJDIR)/th_lang.o: $(SRCDIR)/th_lang.c
@@ -2129,18 +2120,21 @@
2120
2121 $(OBJDIR)/th_tcl.o: $(SRCDIR)/th_tcl.c
2122 $(XTCC) -c $(SRCDIR)/th_tcl.c -o $@
2123
2124
2125 $(OBJDIR)/miniz.o: $(SRCDIR.extsrc)/miniz.c
2126 $(XTCC) $(MINIZ_OPTIONS) -c $(SRCDIR.extsrc)/miniz.c -o $@
2127
2128 $(OBJDIR)/pikchr.o: $(SRCDIR.extsrc)/pikchr.c
2129 $(XTCC) -c $(SRCDIR.extsrc)/pikchr.c -o $@
2130
2131 $(OBJDIR)/cson_amalgamation.o: $(SRCDIR.extsrc)/cson_amalgamation.c
2132 $(XTCC) -c $(SRCDIR.extsrc)/cson_amalgamation.c -o $@
2133
2134 #
2135 # The list of all the targets that do not correspond to real files. This stops
2136 # 'make' from getting confused when someone makes an error in a rule.
2137 #
2138
2139 .PHONY: all install test clean
2140
2141
2142 ELETED src/miniz.c
2143 ELETED src/pikchr.c
2144 ELETED src/shell.c
D src/miniz.c
-4916
--- a/src/miniz.c
+++ b/src/miniz.c
@@ -1,4916 +0,0 @@
1
-/* miniz.c v1.15 - public domain deflate/inflate, zlib-subset, ZIP reading/writing/appending, PNG writing
2
- See "unlicense" statement at the end of this file.
3
- Rich Geldreich <[email protected]>, last updated Oct. 13, 2013
4
- Implements RFC 1950: http://www.ietf.org/rfc/rfc1950.txt and RFC 1951: http://www.ietf.org/rfc/rfc1951.txt
5
-
6
- Most API's defined in miniz.c are optional. For example, to disable the archive related functions just define
7
- MINIZ_NO_ARCHIVE_APIS, or to get rid of all stdio usage define MINIZ_NO_STDIO (see the list below for more macros).
8
-
9
- * Change History
10
- 10/13/13 v1.15 r4 - Interim bugfix release while I work on the next major release with Zip64 support (almost there!):
11
- - Critical fix for the MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY bug (thanks [email protected]) which could cause locate files to not find files. This bug
12
- would only have occured in earlier versions if you explicitly used this flag, OR if you used mz_zip_extract_archive_file_to_heap() or mz_zip_add_mem_to_archive_file_in_place()
13
- (which used this flag). If you can't switch to v1.15 but want to fix this bug, just remove the uses of this flag from both helper funcs (and of course don't use the flag).
14
- - Bugfix in mz_zip_reader_extract_to_mem_no_alloc() from kymoon when pUser_read_buf is not NULL and compressed size is > uncompressed size
15
- - Fixing mz_zip_reader_extract_*() funcs so they don't try to extract compressed data from directory entries, to account for weird zipfiles which contain zero-size compressed data on dir entries.
16
- Hopefully this fix won't cause any issues on weird zip archives, because it assumes the low 16-bits of zip external attributes are DOS attributes (which I believe they always are in practice).
17
- - Fixing mz_zip_reader_is_file_a_directory() so it doesn't check the internal attributes, just the filename and external attributes
18
- - mz_zip_reader_init_file() - missing MZ_FCLOSE() call if the seek failed
19
- - Added cmake support for Linux builds which builds all the examples, tested with clang v3.3 and gcc v4.6.
20
- - Clang fix for tdefl_write_image_to_png_file_in_memory() from toffaletti
21
- - Merged MZ_FORCEINLINE fix from hdeanclark
22
- - Fix <time.h> include before config #ifdef, thanks emil.brink
23
- - Added tdefl_write_image_to_png_file_in_memory_ex(): supports Y flipping (super useful for OpenGL apps), and explicit control over the compression level (so you can
24
- set it to 1 for real-time compression).
25
- - Merged in some compiler fixes from paulharris's github repro.
26
- - Retested this build under Windows (VS 2010, including static analysis), tcc 0.9.26, gcc v4.6 and clang v3.3.
27
- - Added example6.c, which dumps an image of the mandelbrot set to a PNG file.
28
- - Modified example2 to help test the MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY flag more.
29
- - In r3: Bugfix to mz_zip_writer_add_file() found during merge: Fix possible src file fclose() leak if alignment bytes+local header file write faiiled
30
- - In r4: Minor bugfix to mz_zip_writer_add_from_zip_reader(): Was pushing the wrong central dir header offset, appears harmless in this release, but it became a problem in the zip64 branch
31
- 5/20/12 v1.14 - MinGW32/64 GCC 4.6.1 compiler fixes: added MZ_FORCEINLINE, #include <time.h> (thanks fermtect).
32
- 5/19/12 v1.13 - From [email protected] and [email protected] - Fix mz_crc32() so it doesn't compute the wrong CRC-32's when mz_ulong is 64-bit.
33
- - Temporarily/locally slammed in "typedef unsigned long mz_ulong" and re-ran a randomized regression test on ~500k files.
34
- - Eliminated a bunch of warnings when compiling with GCC 32-bit/64.
35
- - Ran all examples, miniz.c, and tinfl.c through MSVC 2008's /analyze (static analysis) option and fixed all warnings (except for the silly
36
- "Use of the comma-operator in a tested expression.." analysis warning, which I purposely use to work around a MSVC compiler warning).
37
- - Created 32-bit and 64-bit Codeblocks projects/workspace. Built and tested Linux executables. The codeblocks workspace is compatible with Linux+Win32/x64.
38
- - Added miniz_tester solution/project, which is a useful little app derived from LZHAM's tester app that I use as part of the regression test.
39
- - Ran miniz.c and tinfl.c through another series of regression testing on ~500,000 files and archives.
40
- - Modified example5.c so it purposely disables a bunch of high-level functionality (MINIZ_NO_STDIO, etc.). (Thanks to corysama for the MINIZ_NO_STDIO bug report.)
41
- - Fix ftell() usage in examples so they exit with an error on files which are too large (a limitation of the examples, not miniz itself).
42
- 4/12/12 v1.12 - More comments, added low-level example5.c, fixed a couple minor level_and_flags issues in the archive API's.
43
- level_and_flags can now be set to MZ_DEFAULT_COMPRESSION. Thanks to Bruce Dawson <[email protected]> for the feedback/bug report.
44
- 5/28/11 v1.11 - Added statement from unlicense.org
45
- 5/27/11 v1.10 - Substantial compressor optimizations:
46
- - Level 1 is now ~4x faster than before. The L1 compressor's throughput now varies between 70-110MB/sec. on a
47
- - Core i7 (actual throughput varies depending on the type of data, and x64 vs. x86).
48
- - Improved baseline L2-L9 compression perf. Also, greatly improved compression perf. issues on some file types.
49
- - Refactored the compression code for better readability and maintainability.
50
- - Added level 10 compression level (L10 has slightly better ratio than level 9, but could have a potentially large
51
- drop in throughput on some files).
52
- 5/15/11 v1.09 - Initial stable release.
53
-
54
- * Low-level Deflate/Inflate implementation notes:
55
-
56
- Compression: Use the "tdefl" API's. The compressor supports raw, static, and dynamic blocks, lazy or
57
- greedy parsing, match length filtering, RLE-only, and Huffman-only streams. It performs and compresses
58
- approximately as well as zlib.
59
-
60
- Decompression: Use the "tinfl" API's. The entire decompressor is implemented as a single function
61
- coroutine: see tinfl_decompress(). It supports decompression into a 32KB (or larger power of 2) wrapping buffer, or into a memory
62
- block large enough to hold the entire file.
63
-
64
- The low-level tdefl/tinfl API's do not make any use of dynamic memory allocation.
65
-
66
- * zlib-style API notes:
67
-
68
- miniz.c implements a fairly large subset of zlib. There's enough functionality present for it to be a drop-in
69
- zlib replacement in many apps:
70
- The z_stream struct, optional memory allocation callbacks
71
- deflateInit/deflateInit2/deflate/deflateReset/deflateEnd/deflateBound
72
- inflateInit/inflateInit2/inflate/inflateEnd
73
- compress, compress2, compressBound, uncompress
74
- CRC-32, Adler-32 - Using modern, minimal code size, CPU cache friendly routines.
75
- Supports raw deflate streams or standard zlib streams with adler-32 checking.
76
-
77
- Limitations:
78
- The callback API's are not implemented yet. No support for gzip headers or zlib static dictionaries.
79
- I've tried to closely emulate zlib's various flavors of stream flushing and return status codes, but
80
- there are no guarantees that miniz.c pulls this off perfectly.
81
-
82
- * PNG writing: See the tdefl_write_image_to_png_file_in_memory() function, originally written by
83
- Alex Evans. Supports 1-4 bytes/pixel images.
84
-
85
- * ZIP archive API notes:
86
-
87
- The ZIP archive API's where designed with simplicity and efficiency in mind, with just enough abstraction to
88
- get the job done with minimal fuss. There are simple API's to retrieve file information, read files from
89
- existing archives, create new archives, append new files to existing archives, or clone archive data from
90
- one archive to another. It supports archives located in memory or the heap, on disk (using stdio.h),
91
- or you can specify custom file read/write callbacks.
92
-
93
- - Archive reading: Just call this function to read a single file from a disk archive:
94
-
95
- void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const char *pArchive_name,
96
- size_t *pSize, mz_uint zip_flags);
97
-
98
- For more complex cases, use the "mz_zip_reader" functions. Upon opening an archive, the entire central
99
- directory is located and read as-is into memory, and subsequent file access only occurs when reading individual files.
100
-
101
- - Archives file scanning: The simple way is to use this function to scan a loaded archive for a specific file:
102
-
103
- int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags);
104
-
105
- The locate operation can optionally check file comments too, which (as one example) can be used to identify
106
- multiple versions of the same file in an archive. This function uses a simple linear search through the central
107
- directory, so it's not very fast.
108
-
109
- Alternately, you can iterate through all the files in an archive (using mz_zip_reader_get_num_files()) and
110
- retrieve detailed info on each file by calling mz_zip_reader_file_stat().
111
-
112
- - Archive creation: Use the "mz_zip_writer" functions. The ZIP writer immediately writes compressed file data
113
- to disk and builds an exact image of the central directory in memory. The central directory image is written
114
- all at once at the end of the archive file when the archive is finalized.
115
-
116
- The archive writer can optionally align each file's local header and file data to any power of 2 alignment,
117
- which can be useful when the archive will be read from optical media. Also, the writer supports placing
118
- arbitrary data blobs at the very beginning of ZIP archives. Archives written using either feature are still
119
- readable by any ZIP tool.
120
-
121
- - Archive appending: The simple way to add a single file to an archive is to call this function:
122
-
123
- mz_bool mz_zip_add_mem_to_archive_file_in_place(const char *pZip_filename, const char *pArchive_name,
124
- const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags);
125
-
126
- The archive will be created if it doesn't already exist, otherwise it'll be appended to.
127
- Note the appending is done in-place and is not an atomic operation, so if something goes wrong
128
- during the operation it's possible the archive could be left without a central directory (although the local
129
- file headers and file data will be fine, so the archive will be recoverable).
130
-
131
- For more complex archive modification scenarios:
132
- 1. The safest way is to use a mz_zip_reader to read the existing archive, cloning only those bits you want to
133
- preserve into a new archive using using the mz_zip_writer_add_from_zip_reader() function (which compiles the
134
- compressed file data as-is). When you're done, delete the old archive and rename the newly written archive, and
135
- you're done. This is safe but requires a bunch of temporary disk space or heap memory.
136
-
137
- 2. Or, you can convert an mz_zip_reader in-place to an mz_zip_writer using mz_zip_writer_init_from_reader(),
138
- append new files as needed, then finalize the archive which will write an updated central directory to the
139
- original archive. (This is basically what mz_zip_add_mem_to_archive_file_in_place() does.) There's a
140
- possibility that the archive's central directory could be lost with this method if anything goes wrong, though.
141
-
142
- - ZIP archive support limitations:
143
- No zip64 or spanning support. Extraction functions can only handle unencrypted, stored or deflated files.
144
- Requires streams capable of seeking.
145
-
146
- * This is a header file library, like stb_image.c. To get only a header file, either cut and paste the
147
- below header, or create miniz.h, #define MINIZ_HEADER_FILE_ONLY, and then include miniz.c from it.
148
-
149
- * Important: For best perf. be sure to customize the below macros for your target platform:
150
- #define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 1
151
- #define MINIZ_LITTLE_ENDIAN 1
152
- #define MINIZ_HAS_64BIT_REGISTERS 1
153
-
154
- * On platforms using glibc, Be sure to "#define _LARGEFILE64_SOURCE 1" before including miniz.c to ensure miniz
155
- uses the 64-bit variants: fopen64(), stat64(), etc. Otherwise you won't be able to process large files
156
- (i.e. 32-bit stat() fails for me on files > 0x7FFFFFFF bytes).
157
-*/
158
-
159
-#ifndef MINIZ_HEADER_INCLUDED
160
-#define MINIZ_HEADER_INCLUDED
161
-
162
-#include <stdlib.h>
163
-
164
-// Defines to completely disable specific portions of miniz.c:
165
-// If all macros here are defined the only functionality remaining will be CRC-32, adler-32, tinfl, and tdefl.
166
-
167
-// Define MINIZ_NO_STDIO to disable all usage and any functions which rely on stdio for file I/O.
168
-//#define MINIZ_NO_STDIO
169
-
170
-// If MINIZ_NO_TIME is specified then the ZIP archive functions will not be able to get the current time, or
171
-// get/set file times, and the C run-time funcs that get/set times won't be called.
172
-// The current downside is the times written to your archives will be from 1979.
173
-//#define MINIZ_NO_TIME
174
-
175
-// Define MINIZ_NO_ARCHIVE_APIS to disable all ZIP archive API's.
176
-//#define MINIZ_NO_ARCHIVE_APIS
177
-
178
-// Define MINIZ_NO_ARCHIVE_APIS to disable all writing related ZIP archive API's.
179
-//#define MINIZ_NO_ARCHIVE_WRITING_APIS
180
-
181
-// Define MINIZ_NO_ZLIB_APIS to remove all ZLIB-style compression/decompression API's.
182
-//#define MINIZ_NO_ZLIB_APIS
183
-
184
-// Define MINIZ_NO_ZLIB_COMPATIBLE_NAME to disable zlib names, to prevent conflicts against stock zlib.
185
-//#define MINIZ_NO_ZLIB_COMPATIBLE_NAMES
186
-
187
-// Define MINIZ_NO_MALLOC to disable all calls to malloc, free, and realloc.
188
-// Note if MINIZ_NO_MALLOC is defined then the user must always provide custom user alloc/free/realloc
189
-// callbacks to the zlib and archive API's, and a few stand-alone helper API's which don't provide custom user
190
-// functions (such as tdefl_compress_mem_to_heap() and tinfl_decompress_mem_to_heap()) won't work.
191
-//#define MINIZ_NO_MALLOC
192
-
193
-#if defined(__TINYC__) && (defined(__linux) || defined(__linux__))
194
- // TODO: Work around "error: include file 'sys\utime.h' when compiling with tcc on Linux
195
- #define MINIZ_NO_TIME
196
-#endif
197
-
198
-#if !defined(MINIZ_NO_TIME) && !defined(MINIZ_NO_ARCHIVE_APIS)
199
- #include <time.h>
200
-#endif
201
-
202
-#if defined(_M_IX86) || defined(_M_X64) || defined(__i386__) || defined(__i386) || defined(__i486__) || defined(__i486) || defined(i386) || defined(__ia64__) || defined(__x86_64__)
203
-// MINIZ_X86_OR_X64_CPU is only used to help set the below macros.
204
-#define MINIZ_X86_OR_X64_CPU 1
205
-#endif
206
-
207
-#if (__BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__) || MINIZ_X86_OR_X64_CPU
208
-// Set MINIZ_LITTLE_ENDIAN to 1 if the processor is little endian.
209
-#define MINIZ_LITTLE_ENDIAN 1
210
-#endif
211
-
212
-#if MINIZ_X86_OR_X64_CPU
213
-// Set MINIZ_USE_UNALIGNED_LOADS_AND_STORES to 1 on CPU's that permit efficient integer loads and stores from unaligned addresses.
214
-#define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 1
215
-#endif
216
-
217
-#if defined(_M_X64) || defined(_WIN64) || defined(__MINGW64__) || defined(_LP64) || defined(__LP64__) || defined(__ia64__) || defined(__x86_64__)
218
-// Set MINIZ_HAS_64BIT_REGISTERS to 1 if operations on 64-bit integers are reasonably fast (and don't involve compiler generated calls to helper functions).
219
-#define MINIZ_HAS_64BIT_REGISTERS 1
220
-#endif
221
-
222
-#ifdef __cplusplus
223
-extern "C" {
224
-#endif
225
-
226
-// ------------------- zlib-style API Definitions.
227
-
228
-// For more compatibility with zlib, miniz.c uses unsigned long for some parameters/struct members. Beware: mz_ulong can be either 32 or 64-bits!
229
-typedef unsigned long mz_ulong;
230
-
231
-// mz_free() internally uses the MZ_FREE() macro (which by default calls free() unless you've modified the MZ_MALLOC macro) to release a block allocated from the heap.
232
-void mz_free(void *p);
233
-
234
-#define MZ_ADLER32_INIT (1)
235
-// mz_adler32() returns the initial adler-32 value to use when called with ptr==NULL.
236
-mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len);
237
-
238
-#define MZ_CRC32_INIT (0)
239
-// mz_crc32() returns the initial CRC-32 value to use when called with ptr==NULL.
240
-mz_ulong mz_crc32(mz_ulong crc, const unsigned char *ptr, size_t buf_len);
241
-
242
-// Compression strategies.
243
-enum { MZ_DEFAULT_STRATEGY = 0, MZ_FILTERED = 1, MZ_HUFFMAN_ONLY = 2, MZ_RLE = 3, MZ_FIXED = 4 };
244
-
245
-// Method
246
-#define MZ_DEFLATED 8
247
-
248
-#ifndef MINIZ_NO_ZLIB_APIS
249
-
250
-// Heap allocation callbacks.
251
-// Note that mz_alloc_func parameter types purpsosely differ from zlib's: items/size is size_t, not unsigned long.
252
-typedef void *(*mz_alloc_func)(void *opaque, size_t items, size_t size);
253
-typedef void (*mz_free_func)(void *opaque, void *address);
254
-typedef void *(*mz_realloc_func)(void *opaque, void *address, size_t items, size_t size);
255
-
256
-#define MZ_VERSION "9.1.15"
257
-#define MZ_VERNUM 0x91F0
258
-#define MZ_VER_MAJOR 9
259
-#define MZ_VER_MINOR 1
260
-#define MZ_VER_REVISION 15
261
-#define MZ_VER_SUBREVISION 0
262
-
263
-// Flush values. For typical usage you only need MZ_NO_FLUSH and MZ_FINISH. The other values are for advanced use (refer to the zlib docs).
264
-enum { MZ_NO_FLUSH = 0, MZ_PARTIAL_FLUSH = 1, MZ_SYNC_FLUSH = 2, MZ_FULL_FLUSH = 3, MZ_FINISH = 4, MZ_BLOCK = 5 };
265
-
266
-// Return status codes. MZ_PARAM_ERROR is non-standard.
267
-enum { MZ_OK = 0, MZ_STREAM_END = 1, MZ_NEED_DICT = 2, MZ_ERRNO = -1, MZ_STREAM_ERROR = -2, MZ_DATA_ERROR = -3, MZ_MEM_ERROR = -4, MZ_BUF_ERROR = -5, MZ_VERSION_ERROR = -6, MZ_PARAM_ERROR = -10000 };
268
-
269
-// Compression levels: 0-9 are the standard zlib-style levels, 10 is best possible compression (not zlib compatible, and may be very slow), MZ_DEFAULT_COMPRESSION=MZ_DEFAULT_LEVEL.
270
-enum { MZ_NO_COMPRESSION = 0, MZ_BEST_SPEED = 1, MZ_BEST_COMPRESSION = 9, MZ_UBER_COMPRESSION = 10, MZ_DEFAULT_LEVEL = 6, MZ_DEFAULT_COMPRESSION = -1 };
271
-
272
-// Window bits
273
-#define MZ_DEFAULT_WINDOW_BITS 15
274
-
275
-struct mz_internal_state;
276
-
277
-// Compression/decompression stream struct.
278
-typedef struct mz_stream_s
279
-{
280
- const unsigned char *next_in; // pointer to next byte to read
281
- unsigned int avail_in; // number of bytes available at next_in
282
- mz_ulong total_in; // total number of bytes consumed so far
283
-
284
- unsigned char *next_out; // pointer to next byte to write
285
- unsigned int avail_out; // number of bytes that can be written to next_out
286
- mz_ulong total_out; // total number of bytes produced so far
287
-
288
- char *msg; // error msg (unused)
289
- struct mz_internal_state *state; // internal state, allocated by zalloc/zfree
290
-
291
- mz_alloc_func zalloc; // optional heap allocation function (defaults to malloc)
292
- mz_free_func zfree; // optional heap free function (defaults to free)
293
- void *opaque; // heap alloc function user pointer
294
-
295
- int data_type; // data_type (unused)
296
- mz_ulong adler; // adler32 of the source or uncompressed data
297
- mz_ulong reserved; // not used
298
-} mz_stream;
299
-
300
-typedef mz_stream *mz_streamp;
301
-
302
-// Returns the version string of miniz.c.
303
-const char *mz_version(void);
304
-
305
-// mz_deflateInit() initializes a compressor with default options:
306
-// Parameters:
307
-// pStream must point to an initialized mz_stream struct.
308
-// level must be between [MZ_NO_COMPRESSION, MZ_BEST_COMPRESSION].
309
-// level 1 enables a specially optimized compression function that's been optimized purely for performance, not ratio.
310
-// (This special func. is currently only enabled when MINIZ_USE_UNALIGNED_LOADS_AND_STORES and MINIZ_LITTLE_ENDIAN are defined.)
311
-// Return values:
312
-// MZ_OK on success.
313
-// MZ_STREAM_ERROR if the stream is bogus.
314
-// MZ_PARAM_ERROR if the input parameters are bogus.
315
-// MZ_MEM_ERROR on out of memory.
316
-int mz_deflateInit(mz_streamp pStream, int level);
317
-
318
-// mz_deflateInit2() is like mz_deflate(), except with more control:
319
-// Additional parameters:
320
-// method must be MZ_DEFLATED
321
-// window_bits must be MZ_DEFAULT_WINDOW_BITS (to wrap the deflate stream with zlib header/adler-32 footer) or -MZ_DEFAULT_WINDOW_BITS (raw deflate/no header or footer)
322
-// mem_level must be between [1, 9] (it's checked but ignored by miniz.c)
323
-int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits, int mem_level, int strategy);
324
-
325
-// Quickly resets a compressor without having to reallocate anything. Same as calling mz_deflateEnd() followed by mz_deflateInit()/mz_deflateInit2().
326
-int mz_deflateReset(mz_streamp pStream);
327
-
328
-// mz_deflate() compresses the input to output, consuming as much of the input and producing as much output as possible.
329
-// Parameters:
330
-// pStream is the stream to read from and write to. You must initialize/update the next_in, avail_in, next_out, and avail_out members.
331
-// flush may be MZ_NO_FLUSH, MZ_PARTIAL_FLUSH/MZ_SYNC_FLUSH, MZ_FULL_FLUSH, or MZ_FINISH.
332
-// Return values:
333
-// MZ_OK on success (when flushing, or if more input is needed but not available, and/or there's more output to be written but the output buffer is full).
334
-// MZ_STREAM_END if all input has been consumed and all output bytes have been written. Don't call mz_deflate() on the stream anymore.
335
-// MZ_STREAM_ERROR if the stream is bogus.
336
-// MZ_PARAM_ERROR if one of the parameters is invalid.
337
-// MZ_BUF_ERROR if no forward progress is possible because the input and/or output buffers are empty. (Fill up the input buffer or free up some output space and try again.)
338
-int mz_deflate(mz_streamp pStream, int flush);
339
-
340
-// mz_deflateEnd() deinitializes a compressor:
341
-// Return values:
342
-// MZ_OK on success.
343
-// MZ_STREAM_ERROR if the stream is bogus.
344
-int mz_deflateEnd(mz_streamp pStream);
345
-
346
-// mz_deflateBound() returns a (very) conservative upper bound on the amount of data that could be generated by deflate(), assuming flush is set to only MZ_NO_FLUSH or MZ_FINISH.
347
-mz_ulong mz_deflateBound(mz_streamp pStream, mz_ulong source_len);
348
-
349
-// Single-call compression functions mz_compress() and mz_compress2():
350
-// Returns MZ_OK on success, or one of the error codes from mz_deflate() on failure.
351
-int mz_compress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len);
352
-int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len, int level);
353
-
354
-// mz_compressBound() returns a (very) conservative upper bound on the amount of data that could be generated by calling mz_compress().
355
-mz_ulong mz_compressBound(mz_ulong source_len);
356
-
357
-// Initializes a decompressor.
358
-int mz_inflateInit(mz_streamp pStream);
359
-
360
-// mz_inflateInit2() is like mz_inflateInit() with an additional option that controls the window size and whether or not the stream has been wrapped with a zlib header/footer:
361
-// window_bits must be MZ_DEFAULT_WINDOW_BITS (to parse zlib header/footer) or -MZ_DEFAULT_WINDOW_BITS (raw deflate).
362
-int mz_inflateInit2(mz_streamp pStream, int window_bits);
363
-
364
-// Decompresses the input stream to the output, consuming only as much of the input as needed, and writing as much to the output as possible.
365
-// Parameters:
366
-// pStream is the stream to read from and write to. You must initialize/update the next_in, avail_in, next_out, and avail_out members.
367
-// flush may be MZ_NO_FLUSH, MZ_SYNC_FLUSH, or MZ_FINISH.
368
-// On the first call, if flush is MZ_FINISH it's assumed the input and output buffers are both sized large enough to decompress the entire stream in a single call (this is slightly faster).
369
-// MZ_FINISH implies that there are no more source bytes available beside what's already in the input buffer, and that the output buffer is large enough to hold the rest of the decompressed data.
370
-// Return values:
371
-// MZ_OK on success. Either more input is needed but not available, and/or there's more output to be written but the output buffer is full.
372
-// MZ_STREAM_END if all needed input has been consumed and all output bytes have been written. For zlib streams, the adler-32 of the decompressed data has also been verified.
373
-// MZ_STREAM_ERROR if the stream is bogus.
374
-// MZ_DATA_ERROR if the deflate stream is invalid.
375
-// MZ_PARAM_ERROR if one of the parameters is invalid.
376
-// MZ_BUF_ERROR if no forward progress is possible because the input buffer is empty but the inflater needs more input to continue, or if the output buffer is not large enough. Call mz_inflate() again
377
-// with more input data, or with more room in the output buffer (except when using single call decompression, described above).
378
-int mz_inflate(mz_streamp pStream, int flush);
379
-
380
-// Deinitializes a decompressor.
381
-int mz_inflateEnd(mz_streamp pStream);
382
-
383
-// Single-call decompression.
384
-// Returns MZ_OK on success, or one of the error codes from mz_inflate() on failure.
385
-int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len);
386
-
387
-// Returns a string description of the specified error code, or NULL if the error code is invalid.
388
-const char *mz_error(int err);
389
-
390
-// Redefine zlib-compatible names to miniz equivalents, so miniz.c can be used as a drop-in replacement for the subset of zlib that miniz.c supports.
391
-// Define MINIZ_NO_ZLIB_COMPATIBLE_NAMES to disable zlib-compatibility if you use zlib in the same project.
392
-#ifndef MINIZ_NO_ZLIB_COMPATIBLE_NAMES
393
- typedef unsigned char Byte;
394
- typedef unsigned int uInt;
395
- typedef mz_ulong uLong;
396
- typedef Byte Bytef;
397
- typedef uInt uIntf;
398
- typedef char charf;
399
- typedef int intf;
400
- typedef void *voidpf;
401
- typedef uLong uLongf;
402
- typedef void *voidp;
403
- typedef void *const voidpc;
404
- #define Z_NULL 0
405
- #define Z_NO_FLUSH MZ_NO_FLUSH
406
- #define Z_PARTIAL_FLUSH MZ_PARTIAL_FLUSH
407
- #define Z_SYNC_FLUSH MZ_SYNC_FLUSH
408
- #define Z_FULL_FLUSH MZ_FULL_FLUSH
409
- #define Z_FINISH MZ_FINISH
410
- #define Z_BLOCK MZ_BLOCK
411
- #define Z_OK MZ_OK
412
- #define Z_STREAM_END MZ_STREAM_END
413
- #define Z_NEED_DICT MZ_NEED_DICT
414
- #define Z_ERRNO MZ_ERRNO
415
- #define Z_STREAM_ERROR MZ_STREAM_ERROR
416
- #define Z_DATA_ERROR MZ_DATA_ERROR
417
- #define Z_MEM_ERROR MZ_MEM_ERROR
418
- #define Z_BUF_ERROR MZ_BUF_ERROR
419
- #define Z_VERSION_ERROR MZ_VERSION_ERROR
420
- #define Z_PARAM_ERROR MZ_PARAM_ERROR
421
- #define Z_NO_COMPRESSION MZ_NO_COMPRESSION
422
- #define Z_BEST_SPEED MZ_BEST_SPEED
423
- #define Z_BEST_COMPRESSION MZ_BEST_COMPRESSION
424
- #define Z_DEFAULT_COMPRESSION MZ_DEFAULT_COMPRESSION
425
- #define Z_DEFAULT_STRATEGY MZ_DEFAULT_STRATEGY
426
- #define Z_FILTERED MZ_FILTERED
427
- #define Z_HUFFMAN_ONLY MZ_HUFFMAN_ONLY
428
- #define Z_RLE MZ_RLE
429
- #define Z_FIXED MZ_FIXED
430
- #define Z_DEFLATED MZ_DEFLATED
431
- #define Z_DEFAULT_WINDOW_BITS MZ_DEFAULT_WINDOW_BITS
432
- #define alloc_func mz_alloc_func
433
- #define free_func mz_free_func
434
- #define internal_state mz_internal_state
435
- #define z_stream mz_stream
436
- #define deflateInit mz_deflateInit
437
- #define deflateInit2 mz_deflateInit2
438
- #define deflateReset mz_deflateReset
439
- #define deflate mz_deflate
440
- #define deflateEnd mz_deflateEnd
441
- #define deflateBound mz_deflateBound
442
- #define compress mz_compress
443
- #define compress2 mz_compress2
444
- #define compressBound mz_compressBound
445
- #define inflateInit mz_inflateInit
446
- #define inflateInit2 mz_inflateInit2
447
- #define inflate mz_inflate
448
- #define inflateEnd mz_inflateEnd
449
- #define uncompress mz_uncompress
450
- #define crc32 mz_crc32
451
- #define adler32 mz_adler32
452
- #define MAX_WBITS 15
453
- #define MAX_MEM_LEVEL 9
454
- #define zError mz_error
455
- #define ZLIB_VERSION MZ_VERSION
456
- #define ZLIB_VERNUM MZ_VERNUM
457
- #define ZLIB_VER_MAJOR MZ_VER_MAJOR
458
- #define ZLIB_VER_MINOR MZ_VER_MINOR
459
- #define ZLIB_VER_REVISION MZ_VER_REVISION
460
- #define ZLIB_VER_SUBREVISION MZ_VER_SUBREVISION
461
- #define zlibVersion mz_version
462
- #define zlib_version mz_version()
463
-#endif // #ifndef MINIZ_NO_ZLIB_COMPATIBLE_NAMES
464
-
465
-#endif // MINIZ_NO_ZLIB_APIS
466
-
467
-// ------------------- Types and macros
468
-
469
-typedef unsigned char mz_uint8;
470
-typedef signed short mz_int16;
471
-typedef unsigned short mz_uint16;
472
-typedef unsigned int mz_uint32;
473
-typedef unsigned int mz_uint;
474
-typedef long long mz_int64;
475
-typedef unsigned long long mz_uint64;
476
-typedef int mz_bool;
477
-
478
-#define MZ_FALSE (0)
479
-#define MZ_TRUE (1)
480
-
481
-// An attempt to work around MSVC's spammy "warning C4127: conditional expression is constant" message.
482
-#ifdef _MSC_VER
483
- #define MZ_MACRO_END while (0, 0)
484
-#else
485
- #define MZ_MACRO_END while (0)
486
-#endif
487
-
488
-// ------------------- ZIP archive reading/writing
489
-
490
-#ifndef MINIZ_NO_ARCHIVE_APIS
491
-
492
-enum
493
-{
494
- MZ_ZIP_MAX_IO_BUF_SIZE = 64*1024,
495
- MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE = 260,
496
- MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE = 256
497
-};
498
-
499
-typedef struct
500
-{
501
- mz_uint32 m_file_index;
502
- mz_uint32 m_central_dir_ofs;
503
- mz_uint16 m_version_made_by;
504
- mz_uint16 m_version_needed;
505
- mz_uint16 m_bit_flag;
506
- mz_uint16 m_method;
507
-#ifndef MINIZ_NO_TIME
508
- time_t m_time;
509
-#endif
510
- mz_uint32 m_crc32;
511
- mz_uint64 m_comp_size;
512
- mz_uint64 m_uncomp_size;
513
- mz_uint16 m_internal_attr;
514
- mz_uint32 m_external_attr;
515
- mz_uint64 m_local_header_ofs;
516
- mz_uint32 m_comment_size;
517
- char m_filename[MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE];
518
- char m_comment[MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE];
519
-} mz_zip_archive_file_stat;
520
-
521
-typedef size_t (*mz_file_read_func)(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n);
522
-typedef size_t (*mz_file_write_func)(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n);
523
-
524
-struct mz_zip_internal_state_tag;
525
-typedef struct mz_zip_internal_state_tag mz_zip_internal_state;
526
-
527
-typedef enum
528
-{
529
- MZ_ZIP_MODE_INVALID = 0,
530
- MZ_ZIP_MODE_READING = 1,
531
- MZ_ZIP_MODE_WRITING = 2,
532
- MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED = 3
533
-} mz_zip_mode;
534
-
535
-typedef struct mz_zip_archive_tag
536
-{
537
- mz_uint64 m_archive_size;
538
- mz_uint64 m_central_directory_file_ofs;
539
- mz_uint m_total_files;
540
- mz_zip_mode m_zip_mode;
541
-
542
- mz_uint m_file_offset_alignment;
543
-
544
- mz_alloc_func m_pAlloc;
545
- mz_free_func m_pFree;
546
- mz_realloc_func m_pRealloc;
547
- void *m_pAlloc_opaque;
548
-
549
- mz_file_read_func m_pRead;
550
- mz_file_write_func m_pWrite;
551
- void *m_pIO_opaque;
552
-
553
- mz_zip_internal_state *m_pState;
554
-
555
-} mz_zip_archive;
556
-
557
-typedef enum
558
-{
559
- MZ_ZIP_FLAG_CASE_SENSITIVE = 0x0100,
560
- MZ_ZIP_FLAG_IGNORE_PATH = 0x0200,
561
- MZ_ZIP_FLAG_COMPRESSED_DATA = 0x0400,
562
- MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY = 0x0800
563
-} mz_zip_flags;
564
-
565
-// ZIP archive reading
566
-
567
-// Inits a ZIP archive reader.
568
-// These functions read and validate the archive's central directory.
569
-mz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size, mz_uint32 flags);
570
-mz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem, size_t size, mz_uint32 flags);
571
-
572
-#ifndef MINIZ_NO_STDIO
573
-mz_bool mz_zip_reader_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint32 flags);
574
-#endif
575
-
576
-// Returns the total number of files in the archive.
577
-mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip);
578
-
579
-// Returns detailed information about an archive file entry.
580
-mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index, mz_zip_archive_file_stat *pStat);
581
-
582
-// Determines if an archive file entry is a directory entry.
583
-mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip, mz_uint file_index);
584
-mz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive *pZip, mz_uint file_index);
585
-
586
-// Retrieves the filename of an archive file entry.
587
-// Returns the number of bytes written to pFilename, or if filename_buf_size is 0 this function returns the number of bytes needed to fully store the filename.
588
-mz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, mz_uint file_index, char *pFilename, mz_uint filename_buf_size);
589
-
590
-// Attempts to locates a file in the archive's central directory.
591
-// Valid flags: MZ_ZIP_FLAG_CASE_SENSITIVE, MZ_ZIP_FLAG_IGNORE_PATH
592
-// Returns -1 if the file cannot be found.
593
-int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags);
594
-
595
-// Extracts a archive file to a memory buffer using no memory allocation.
596
-mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size);
597
-mz_bool mz_zip_reader_extract_file_to_mem_no_alloc(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size);
598
-
599
-// Extracts a archive file to a memory buffer.
600
-mz_bool mz_zip_reader_extract_to_mem(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags);
601
-mz_bool mz_zip_reader_extract_file_to_mem(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags);
602
-
603
-// Extracts a archive file to a dynamically allocated heap buffer.
604
-void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index, size_t *pSize, mz_uint flags);
605
-void *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip, const char *pFilename, size_t *pSize, mz_uint flags);
606
-
607
-// Extracts a archive file using a callback function to output the file's data.
608
-mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip, mz_uint file_index, mz_file_write_func pCallback, void *pOpaque, mz_uint flags);
609
-mz_bool mz_zip_reader_extract_file_to_callback(mz_zip_archive *pZip, const char *pFilename, mz_file_write_func pCallback, void *pOpaque, mz_uint flags);
610
-
611
-#ifndef MINIZ_NO_STDIO
612
-// Extracts a archive file to a disk file and sets its last accessed and modified times.
613
-// This function only extracts files, not archive directory records.
614
-mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index, const char *pDst_filename, mz_uint flags);
615
-mz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive *pZip, const char *pArchive_filename, const char *pDst_filename, mz_uint flags);
616
-#endif
617
-
618
-// Ends archive reading, freeing all allocations, and closing the input archive file if mz_zip_reader_init_file() was used.
619
-mz_bool mz_zip_reader_end(mz_zip_archive *pZip);
620
-
621
-// ZIP archive writing
622
-
623
-#ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
624
-
625
-// Inits a ZIP archive writer.
626
-mz_bool mz_zip_writer_init(mz_zip_archive *pZip, mz_uint64 existing_size);
627
-mz_bool mz_zip_writer_init_heap(mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size);
628
-
629
-#ifndef MINIZ_NO_STDIO
630
-mz_bool mz_zip_writer_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint64 size_to_reserve_at_beginning);
631
-#endif
632
-
633
-// Converts a ZIP archive reader object into a writer object, to allow efficient in-place file appends to occur on an existing archive.
634
-// For archives opened using mz_zip_reader_init_file, pFilename must be the archive's filename so it can be reopened for writing. If the file can't be reopened, mz_zip_reader_end() will be called.
635
-// For archives opened using mz_zip_reader_init_mem, the memory block must be growable using the realloc callback (which defaults to realloc unless you've overridden it).
636
-// Finally, for archives opened using mz_zip_reader_init, the mz_zip_archive's user provided m_pWrite function cannot be NULL.
637
-// Note: In-place archive modification is not recommended unless you know what you're doing, because if execution stops or something goes wrong before
638
-// the archive is finalized the file's central directory will be hosed.
639
-mz_bool mz_zip_writer_init_from_reader(mz_zip_archive *pZip, const char *pFilename);
640
-
641
-// Adds the contents of a memory buffer to an archive. These functions record the current local time into the archive.
642
-// To add a directory entry, call this method with an archive name ending in a forwardslash with empty buffer.
643
-// level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION.
644
-mz_bool mz_zip_writer_add_mem(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, mz_uint level_and_flags);
645
-mz_bool mz_zip_writer_add_mem_ex(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, mz_uint64 uncomp_size, mz_uint32 uncomp_crc32);
646
-
647
-#ifndef MINIZ_NO_STDIO
648
-// Adds the contents of a disk file to an archive. This function also records the disk file's modified time into the archive.
649
-// level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION.
650
-mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name, const char *pSrc_filename, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags);
651
-#endif
652
-
653
-// Adds a file to an archive by fully cloning the data from another archive.
654
-// This function fully clones the source file's compressed data (no recompression), along with its full filename, extra data, and comment fields.
655
-mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive *pSource_zip, mz_uint file_index);
656
-
657
-// Finalizes the archive by writing the central directory records followed by the end of central directory record.
658
-// After an archive is finalized, the only valid call on the mz_zip_archive struct is mz_zip_writer_end().
659
-// An archive must be manually finalized by calling this function for it to be valid.
660
-mz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip);
661
-mz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive *pZip, void **pBuf, size_t *pSize);
662
-
663
-// Ends archive writing, freeing all allocations, and closing the output file if mz_zip_writer_init_file() was used.
664
-// Note for the archive to be valid, it must have been finalized before ending.
665
-mz_bool mz_zip_writer_end(mz_zip_archive *pZip);
666
-
667
-// Misc. high-level helper functions:
668
-
669
-// mz_zip_add_mem_to_archive_file_in_place() efficiently (but not atomically) appends a memory blob to a ZIP archive.
670
-// level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION.
671
-mz_bool mz_zip_add_mem_to_archive_file_in_place(const char *pZip_filename, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags);
672
-
673
-// Reads a single file from an archive into a heap block.
674
-// Returns NULL on failure.
675
-void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const char *pArchive_name, size_t *pSize, mz_uint zip_flags);
676
-
677
-#endif // #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
678
-
679
-#endif // #ifndef MINIZ_NO_ARCHIVE_APIS
680
-
681
-// ------------------- Low-level Decompression API Definitions
682
-
683
-// Decompression flags used by tinfl_decompress().
684
-// TINFL_FLAG_PARSE_ZLIB_HEADER: If set, the input has a valid zlib header and ends with an adler32 checksum (it's a valid zlib stream). Otherwise, the input is a raw deflate stream.
685
-// TINFL_FLAG_HAS_MORE_INPUT: If set, there are more input bytes available beyond the end of the supplied input buffer. If clear, the input buffer contains all remaining input.
686
-// TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF: If set, the output buffer is large enough to hold the entire decompressed stream. If clear, the output buffer is at least the size of the dictionary (typically 32KB).
687
-// TINFL_FLAG_COMPUTE_ADLER32: Force adler-32 checksum computation of the decompressed bytes.
688
-enum
689
-{
690
- TINFL_FLAG_PARSE_ZLIB_HEADER = 1,
691
- TINFL_FLAG_HAS_MORE_INPUT = 2,
692
- TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF = 4,
693
- TINFL_FLAG_COMPUTE_ADLER32 = 8
694
-};
695
-
696
-// High level decompression functions:
697
-// tinfl_decompress_mem_to_heap() decompresses a block in memory to a heap block allocated via malloc().
698
-// On entry:
699
-// pSrc_buf, src_buf_len: Pointer and size of the Deflate or zlib source data to decompress.
700
-// On return:
701
-// Function returns a pointer to the decompressed data, or NULL on failure.
702
-// *pOut_len will be set to the decompressed data's size, which could be larger than src_buf_len on uncompressible data.
703
-// The caller must call mz_free() on the returned block when it's no longer needed.
704
-void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags);
705
-
706
-// tinfl_decompress_mem_to_mem() decompresses a block in memory to another block in memory.
707
-// Returns TINFL_DECOMPRESS_MEM_TO_MEM_FAILED on failure, or the number of bytes written on success.
708
-#define TINFL_DECOMPRESS_MEM_TO_MEM_FAILED ((size_t)(-1))
709
-size_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags);
710
-
711
-// tinfl_decompress_mem_to_callback() decompresses a block in memory to an internal 32KB buffer, and a user provided callback function will be called to flush the buffer.
712
-// Returns 1 on success or 0 on failure.
713
-typedef int (*tinfl_put_buf_func_ptr)(const void* pBuf, int len, void *pUser);
714
-int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size, tinfl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags);
715
-
716
-struct tinfl_decompressor_tag; typedef struct tinfl_decompressor_tag tinfl_decompressor;
717
-
718
-// Max size of LZ dictionary.
719
-#define TINFL_LZ_DICT_SIZE 32768
720
-
721
-// Return status.
722
-typedef enum
723
-{
724
- TINFL_STATUS_BAD_PARAM = -3,
725
- TINFL_STATUS_ADLER32_MISMATCH = -2,
726
- TINFL_STATUS_FAILED = -1,
727
- TINFL_STATUS_DONE = 0,
728
- TINFL_STATUS_NEEDS_MORE_INPUT = 1,
729
- TINFL_STATUS_HAS_MORE_OUTPUT = 2
730
-} tinfl_status;
731
-
732
-// Initializes the decompressor to its initial state.
733
-#define tinfl_init(r) do { (r)->m_state = 0; } MZ_MACRO_END
734
-#define tinfl_get_adler32(r) (r)->m_check_adler32
735
-
736
-// Main low-level decompressor coroutine function. This is the only function actually needed for decompression. All the other functions are just high-level helpers for improved usability.
737
-// This is a universal API, i.e. it can be used as a building block to build any desired higher level decompression API. In the limit case, it can be called once per every byte input or output.
738
-tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_next, size_t *pIn_buf_size, mz_uint8 *pOut_buf_start, mz_uint8 *pOut_buf_next, size_t *pOut_buf_size, const mz_uint32 decomp_flags);
739
-
740
-// Internal/private bits follow.
741
-enum
742
-{
743
- TINFL_MAX_HUFF_TABLES = 3, TINFL_MAX_HUFF_SYMBOLS_0 = 288, TINFL_MAX_HUFF_SYMBOLS_1 = 32, TINFL_MAX_HUFF_SYMBOLS_2 = 19,
744
- TINFL_FAST_LOOKUP_BITS = 10, TINFL_FAST_LOOKUP_SIZE = 1 << TINFL_FAST_LOOKUP_BITS
745
-};
746
-
747
-typedef struct
748
-{
749
- mz_uint8 m_code_size[TINFL_MAX_HUFF_SYMBOLS_0];
750
- mz_int16 m_look_up[TINFL_FAST_LOOKUP_SIZE], m_tree[TINFL_MAX_HUFF_SYMBOLS_0 * 2];
751
-} tinfl_huff_table;
752
-
753
-#if MINIZ_HAS_64BIT_REGISTERS
754
- #define TINFL_USE_64BIT_BITBUF 1
755
-#endif
756
-
757
-#if TINFL_USE_64BIT_BITBUF
758
- typedef mz_uint64 tinfl_bit_buf_t;
759
- #define TINFL_BITBUF_SIZE (64)
760
-#else
761
- typedef mz_uint32 tinfl_bit_buf_t;
762
- #define TINFL_BITBUF_SIZE (32)
763
-#endif
764
-
765
-struct tinfl_decompressor_tag
766
-{
767
- mz_uint32 m_state, m_num_bits, m_zhdr0, m_zhdr1, m_z_adler32, m_final, m_type, m_check_adler32, m_dist, m_counter, m_num_extra, m_table_sizes[TINFL_MAX_HUFF_TABLES];
768
- tinfl_bit_buf_t m_bit_buf;
769
- size_t m_dist_from_out_buf_start;
770
- tinfl_huff_table m_tables[TINFL_MAX_HUFF_TABLES];
771
- mz_uint8 m_raw_header[4], m_len_codes[TINFL_MAX_HUFF_SYMBOLS_0 + TINFL_MAX_HUFF_SYMBOLS_1 + 137];
772
-};
773
-
774
-// ------------------- Low-level Compression API Definitions
775
-
776
-// Set TDEFL_LESS_MEMORY to 1 to use less memory (compression will be slightly slower, and raw/dynamic blocks will be output more frequently).
777
-#define TDEFL_LESS_MEMORY 0
778
-
779
-// tdefl_init() compression flags logically OR'd together (low 12 bits contain the max. number of probes per dictionary search):
780
-// TDEFL_DEFAULT_MAX_PROBES: The compressor defaults to 128 dictionary probes per dictionary search. 0=Huffman only, 1=Huffman+LZ (fastest/crap compression), 4095=Huffman+LZ (slowest/best compression).
781
-enum
782
-{
783
- TDEFL_HUFFMAN_ONLY = 0, TDEFL_DEFAULT_MAX_PROBES = 128, TDEFL_MAX_PROBES_MASK = 0xFFF
784
-};
785
-
786
-// TDEFL_WRITE_ZLIB_HEADER: If set, the compressor outputs a zlib header before the deflate data, and the Adler-32 of the source data at the end. Otherwise, you'll get raw deflate data.
787
-// TDEFL_COMPUTE_ADLER32: Always compute the adler-32 of the input data (even when not writing zlib headers).
788
-// TDEFL_GREEDY_PARSING_FLAG: Set to use faster greedy parsing, instead of more efficient lazy parsing.
789
-// TDEFL_NONDETERMINISTIC_PARSING_FLAG: Enable to decrease the compressor's initialization time to the minimum, but the output may vary from run to run given the same input (depending on the contents of memory).
790
-// TDEFL_RLE_MATCHES: Only look for RLE matches (matches with a distance of 1)
791
-// TDEFL_FILTER_MATCHES: Discards matches <= 5 chars if enabled.
792
-// TDEFL_FORCE_ALL_STATIC_BLOCKS: Disable usage of optimized Huffman tables.
793
-// TDEFL_FORCE_ALL_RAW_BLOCKS: Only use raw (uncompressed) deflate blocks.
794
-// The low 12 bits are reserved to control the max # of hash probes per dictionary lookup (see TDEFL_MAX_PROBES_MASK).
795
-enum
796
-{
797
- TDEFL_WRITE_ZLIB_HEADER = 0x01000,
798
- TDEFL_COMPUTE_ADLER32 = 0x02000,
799
- TDEFL_GREEDY_PARSING_FLAG = 0x04000,
800
- TDEFL_NONDETERMINISTIC_PARSING_FLAG = 0x08000,
801
- TDEFL_RLE_MATCHES = 0x10000,
802
- TDEFL_FILTER_MATCHES = 0x20000,
803
- TDEFL_FORCE_ALL_STATIC_BLOCKS = 0x40000,
804
- TDEFL_FORCE_ALL_RAW_BLOCKS = 0x80000
805
-};
806
-
807
-// High level compression functions:
808
-// tdefl_compress_mem_to_heap() compresses a block in memory to a heap block allocated via malloc().
809
-// On entry:
810
-// pSrc_buf, src_buf_len: Pointer and size of source block to compress.
811
-// flags: The max match finder probes (default is 128) logically OR'd against the above flags. Higher probes are slower but improve compression.
812
-// On return:
813
-// Function returns a pointer to the compressed data, or NULL on failure.
814
-// *pOut_len will be set to the compressed data's size, which could be larger than src_buf_len on uncompressible data.
815
-// The caller must free() the returned block when it's no longer needed.
816
-void *tdefl_compress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags);
817
-
818
-// tdefl_compress_mem_to_mem() compresses a block in memory to another block in memory.
819
-// Returns 0 on failure.
820
-size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags);
821
-
822
-// Compresses an image to a compressed PNG file in memory.
823
-// On entry:
824
-// pImage, w, h, and num_chans describe the image to compress. num_chans may be 1, 2, 3, or 4.
825
-// The image pitch in bytes per scanline will be w*num_chans. The leftmost pixel on the top scanline is stored first in memory.
826
-// level may range from [0,10], use MZ_NO_COMPRESSION, MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc. or a decent default is MZ_DEFAULT_LEVEL
827
-// If flip is true, the image will be flipped on the Y axis (useful for OpenGL apps).
828
-// On return:
829
-// Function returns a pointer to the compressed data, or NULL on failure.
830
-// *pLen_out will be set to the size of the PNG image file.
831
-// The caller must mz_free() the returned heap block (which will typically be larger than *pLen_out) when it's no longer needed.
832
-void *tdefl_write_image_to_png_file_in_memory_ex(const void *pImage, int w, int h, int num_chans, size_t *pLen_out, mz_uint level, mz_bool flip);
833
-void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h, int num_chans, size_t *pLen_out);
834
-
835
-// Output stream interface. The compressor uses this interface to write compressed data. It'll typically be called TDEFL_OUT_BUF_SIZE at a time.
836
-typedef mz_bool (*tdefl_put_buf_func_ptr)(const void* pBuf, int len, void *pUser);
837
-
838
-// tdefl_compress_mem_to_output() compresses a block to an output stream. The above helpers use this function internally.
839
-mz_bool tdefl_compress_mem_to_output(const void *pBuf, size_t buf_len, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags);
840
-
841
-enum { TDEFL_MAX_HUFF_TABLES = 3, TDEFL_MAX_HUFF_SYMBOLS_0 = 288, TDEFL_MAX_HUFF_SYMBOLS_1 = 32, TDEFL_MAX_HUFF_SYMBOLS_2 = 19, TDEFL_LZ_DICT_SIZE = 32768, TDEFL_LZ_DICT_SIZE_MASK = TDEFL_LZ_DICT_SIZE - 1, TDEFL_MIN_MATCH_LEN = 3, TDEFL_MAX_MATCH_LEN = 258 };
842
-
843
-// TDEFL_OUT_BUF_SIZE MUST be large enough to hold a single entire compressed output block (using static/fixed Huffman codes).
844
-#if TDEFL_LESS_MEMORY
845
-enum { TDEFL_LZ_CODE_BUF_SIZE = 24 * 1024, TDEFL_OUT_BUF_SIZE = (TDEFL_LZ_CODE_BUF_SIZE * 13 ) / 10, TDEFL_MAX_HUFF_SYMBOLS = 288, TDEFL_LZ_HASH_BITS = 12, TDEFL_LEVEL1_HASH_SIZE_MASK = 4095, TDEFL_LZ_HASH_SHIFT = (TDEFL_LZ_HASH_BITS + 2) / 3, TDEFL_LZ_HASH_SIZE = 1 << TDEFL_LZ_HASH_BITS };
846
-#else
847
-enum { TDEFL_LZ_CODE_BUF_SIZE = 64 * 1024, TDEFL_OUT_BUF_SIZE = (TDEFL_LZ_CODE_BUF_SIZE * 13 ) / 10, TDEFL_MAX_HUFF_SYMBOLS = 288, TDEFL_LZ_HASH_BITS = 15, TDEFL_LEVEL1_HASH_SIZE_MASK = 4095, TDEFL_LZ_HASH_SHIFT = (TDEFL_LZ_HASH_BITS + 2) / 3, TDEFL_LZ_HASH_SIZE = 1 << TDEFL_LZ_HASH_BITS };
848
-#endif
849
-
850
-// The low-level tdefl functions below may be used directly if the above helper functions aren't flexible enough. The low-level functions don't make any heap allocations, unlike the above helper functions.
851
-typedef enum
852
-{
853
- TDEFL_STATUS_BAD_PARAM = -2,
854
- TDEFL_STATUS_PUT_BUF_FAILED = -1,
855
- TDEFL_STATUS_OKAY = 0,
856
- TDEFL_STATUS_DONE = 1,
857
-} tdefl_status;
858
-
859
-// Must map to MZ_NO_FLUSH, MZ_SYNC_FLUSH, etc. enums
860
-typedef enum
861
-{
862
- TDEFL_NO_FLUSH = 0,
863
- TDEFL_SYNC_FLUSH = 2,
864
- TDEFL_FULL_FLUSH = 3,
865
- TDEFL_FINISH = 4
866
-} tdefl_flush;
867
-
868
-// tdefl's compression state structure.
869
-typedef struct
870
-{
871
- tdefl_put_buf_func_ptr m_pPut_buf_func;
872
- void *m_pPut_buf_user;
873
- mz_uint m_flags, m_max_probes[2];
874
- int m_greedy_parsing;
875
- mz_uint m_adler32, m_lookahead_pos, m_lookahead_size, m_dict_size;
876
- mz_uint8 *m_pLZ_code_buf, *m_pLZ_flags, *m_pOutput_buf, *m_pOutput_buf_end;
877
- mz_uint m_num_flags_left, m_total_lz_bytes, m_lz_code_buf_dict_pos, m_bits_in, m_bit_buffer;
878
- mz_uint m_saved_match_dist, m_saved_match_len, m_saved_lit, m_output_flush_ofs, m_output_flush_remaining, m_finished, m_block_index, m_wants_to_finish;
879
- tdefl_status m_prev_return_status;
880
- const void *m_pIn_buf;
881
- void *m_pOut_buf;
882
- size_t *m_pIn_buf_size, *m_pOut_buf_size;
883
- tdefl_flush m_flush;
884
- const mz_uint8 *m_pSrc;
885
- size_t m_src_buf_left, m_out_buf_ofs;
886
- mz_uint8 m_dict[TDEFL_LZ_DICT_SIZE + TDEFL_MAX_MATCH_LEN - 1];
887
- mz_uint16 m_huff_count[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS];
888
- mz_uint16 m_huff_codes[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS];
889
- mz_uint8 m_huff_code_sizes[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS];
890
- mz_uint8 m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE];
891
- mz_uint16 m_next[TDEFL_LZ_DICT_SIZE];
892
- mz_uint16 m_hash[TDEFL_LZ_HASH_SIZE];
893
- mz_uint8 m_output_buf[TDEFL_OUT_BUF_SIZE];
894
-} tdefl_compressor;
895
-
896
-// Initializes the compressor.
897
-// There is no corresponding deinit() function because the tdefl API's do not dynamically allocate memory.
898
-// pBut_buf_func: If NULL, output data will be supplied to the specified callback. In this case, the user should call the tdefl_compress_buffer() API for compression.
899
-// If pBut_buf_func is NULL the user should always call the tdefl_compress() API.
900
-// flags: See the above enums (TDEFL_HUFFMAN_ONLY, TDEFL_WRITE_ZLIB_HEADER, etc.)
901
-tdefl_status tdefl_init(tdefl_compressor *d, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags);
902
-
903
-// Compresses a block of data, consuming as much of the specified input buffer as possible, and writing as much compressed data to the specified output buffer as possible.
904
-tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf, size_t *pIn_buf_size, void *pOut_buf, size_t *pOut_buf_size, tdefl_flush flush);
905
-
906
-// tdefl_compress_buffer() is only usable when the tdefl_init() is called with a non-NULL tdefl_put_buf_func_ptr.
907
-// tdefl_compress_buffer() always consumes the entire input buffer.
908
-tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf, size_t in_buf_size, tdefl_flush flush);
909
-
910
-tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d);
911
-mz_uint32 tdefl_get_adler32(tdefl_compressor *d);
912
-
913
-// Can't use tdefl_create_comp_flags_from_zip_params if MINIZ_NO_ZLIB_APIS isn't defined, because it uses some of its macros.
914
-#ifndef MINIZ_NO_ZLIB_APIS
915
-// Create tdefl_compress() flags given zlib-style compression parameters.
916
-// level may range from [0,10] (where 10 is absolute max compression, but may be much slower on some files)
917
-// window_bits may be -15 (raw deflate) or 15 (zlib)
918
-// strategy may be either MZ_DEFAULT_STRATEGY, MZ_FILTERED, MZ_HUFFMAN_ONLY, MZ_RLE, or MZ_FIXED
919
-mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits, int strategy);
920
-#endif // #ifndef MINIZ_NO_ZLIB_APIS
921
-
922
-#ifdef __cplusplus
923
-}
924
-#endif
925
-
926
-#endif // MINIZ_HEADER_INCLUDED
927
-
928
-// ------------------- End of Header: Implementation follows. (If you only want the header, define MINIZ_HEADER_FILE_ONLY.)
929
-
930
-#ifndef MINIZ_HEADER_FILE_ONLY
931
-
932
-typedef unsigned char mz_validate_uint16[sizeof(mz_uint16)==2 ? 1 : -1];
933
-typedef unsigned char mz_validate_uint32[sizeof(mz_uint32)==4 ? 1 : -1];
934
-typedef unsigned char mz_validate_uint64[sizeof(mz_uint64)==8 ? 1 : -1];
935
-
936
-#include <string.h>
937
-#include <assert.h>
938
-
939
-#define MZ_ASSERT(x) assert(x)
940
-
941
-#ifdef MINIZ_NO_MALLOC
942
- #define MZ_MALLOC(x) NULL
943
- #define MZ_FREE(x) (void)x, ((void)0)
944
- #define MZ_REALLOC(p, x) NULL
945
-#else
946
- #define MZ_MALLOC(x) malloc(x)
947
- #define MZ_FREE(x) free(x)
948
- #define MZ_REALLOC(p, x) realloc(p, x)
949
-#endif
950
-
951
-#define MZ_MAX(a,b) (((a)>(b))?(a):(b))
952
-#define MZ_MIN(a,b) (((a)<(b))?(a):(b))
953
-#define MZ_CLEAR_OBJ(obj) memset(&(obj), 0, sizeof(obj))
954
-
955
-#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
956
- #define MZ_READ_LE16(p) *((const mz_uint16 *)(p))
957
- #define MZ_READ_LE32(p) *((const mz_uint32 *)(p))
958
-#else
959
- #define MZ_READ_LE16(p) ((mz_uint32)(((const mz_uint8 *)(p))[0]) | ((mz_uint32)(((const mz_uint8 *)(p))[1]) << 8U))
960
- #define MZ_READ_LE32(p) ((mz_uint32)(((const mz_uint8 *)(p))[0]) | ((mz_uint32)(((const mz_uint8 *)(p))[1]) << 8U) | ((mz_uint32)(((const mz_uint8 *)(p))[2]) << 16U) | ((mz_uint32)(((const mz_uint8 *)(p))[3]) << 24U))
961
-#endif
962
-
963
-#ifdef _MSC_VER
964
- #define MZ_FORCEINLINE __forceinline
965
-#elif defined(__GNUC__)
966
- #define MZ_FORCEINLINE inline __attribute__((__always_inline__))
967
-#else
968
- #define MZ_FORCEINLINE inline
969
-#endif
970
-
971
-#ifdef __cplusplus
972
- extern "C" {
973
-#endif
974
-
975
-// ------------------- zlib-style API's
976
-
977
-mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len)
978
-{
979
- mz_uint32 i, s1 = (mz_uint32)(adler & 0xffff), s2 = (mz_uint32)(adler >> 16); size_t block_len = buf_len % 5552;
980
- if (!ptr) return MZ_ADLER32_INIT;
981
- while (buf_len) {
982
- for (i = 0; i + 7 < block_len; i += 8, ptr += 8) {
983
- s1 += ptr[0], s2 += s1; s1 += ptr[1], s2 += s1; s1 += ptr[2], s2 += s1; s1 += ptr[3], s2 += s1;
984
- s1 += ptr[4], s2 += s1; s1 += ptr[5], s2 += s1; s1 += ptr[6], s2 += s1; s1 += ptr[7], s2 += s1;
985
- }
986
- for ( ; i < block_len; ++i) s1 += *ptr++, s2 += s1;
987
- s1 %= 65521U, s2 %= 65521U; buf_len -= block_len; block_len = 5552;
988
- }
989
- return (s2 << 16) + s1;
990
-}
991
-
992
-// Karl Malbrain's compact CRC-32. See "A compact CCITT crc16 and crc32 C implementation that balances processor cache usage against speed": http://www.geocities.com/malbrain/
993
-mz_ulong mz_crc32(mz_ulong crc, const mz_uint8 *ptr, size_t buf_len)
994
-{
995
- static const mz_uint32 s_crc32[16] = { 0, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
996
- 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c };
997
- mz_uint32 crcu32 = (mz_uint32)crc;
998
- if (!ptr) return MZ_CRC32_INIT;
999
- crcu32 = ~crcu32; while (buf_len--) { mz_uint8 b = *ptr++; crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b & 0xF)]; crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b >> 4)]; }
1000
- return ~crcu32;
1001
-}
1002
-
1003
-void mz_free(void *p)
1004
-{
1005
- MZ_FREE(p);
1006
-}
1007
-
1008
-#ifndef MINIZ_NO_ZLIB_APIS
1009
-
1010
-static void *def_alloc_func(void *opaque, size_t items, size_t size) { (void)opaque, (void)items, (void)size; return MZ_MALLOC(items * size); }
1011
-static void def_free_func(void *opaque, void *address) { (void)opaque, (void)address; MZ_FREE(address); }
1012
-static void *def_realloc_func(void *opaque, void *address, size_t items, size_t size) { (void)opaque, (void)address, (void)items, (void)size; return MZ_REALLOC(address, items * size); }
1013
-
1014
-const char *mz_version(void)
1015
-{
1016
- return MZ_VERSION;
1017
-}
1018
-
1019
-int mz_deflateInit(mz_streamp pStream, int level)
1020
-{
1021
- return mz_deflateInit2(pStream, level, MZ_DEFLATED, MZ_DEFAULT_WINDOW_BITS, 9, MZ_DEFAULT_STRATEGY);
1022
-}
1023
-
1024
-int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits, int mem_level, int strategy)
1025
-{
1026
- tdefl_compressor *pComp;
1027
- mz_uint comp_flags = TDEFL_COMPUTE_ADLER32 | tdefl_create_comp_flags_from_zip_params(level, window_bits, strategy);
1028
-
1029
- if (!pStream) return MZ_STREAM_ERROR;
1030
- if ((method != MZ_DEFLATED) || ((mem_level < 1) || (mem_level > 9)) || ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS))) return MZ_PARAM_ERROR;
1031
-
1032
- pStream->data_type = 0;
1033
- pStream->adler = MZ_ADLER32_INIT;
1034
- pStream->msg = NULL;
1035
- pStream->reserved = 0;
1036
- pStream->total_in = 0;
1037
- pStream->total_out = 0;
1038
- if (!pStream->zalloc) pStream->zalloc = def_alloc_func;
1039
- if (!pStream->zfree) pStream->zfree = def_free_func;
1040
-
1041
- pComp = (tdefl_compressor *)pStream->zalloc(pStream->opaque, 1, sizeof(tdefl_compressor));
1042
- if (!pComp)
1043
- return MZ_MEM_ERROR;
1044
-
1045
- pStream->state = (struct mz_internal_state *)pComp;
1046
-
1047
- if (tdefl_init(pComp, NULL, NULL, comp_flags) != TDEFL_STATUS_OKAY)
1048
- {
1049
- mz_deflateEnd(pStream);
1050
- return MZ_PARAM_ERROR;
1051
- }
1052
-
1053
- return MZ_OK;
1054
-}
1055
-
1056
-int mz_deflateReset(mz_streamp pStream)
1057
-{
1058
- if ((!pStream) || (!pStream->state) || (!pStream->zalloc) || (!pStream->zfree)) return MZ_STREAM_ERROR;
1059
- pStream->total_in = pStream->total_out = 0;
1060
- tdefl_init((tdefl_compressor*)pStream->state, NULL, NULL, ((tdefl_compressor*)pStream->state)->m_flags);
1061
- return MZ_OK;
1062
-}
1063
-
1064
-int mz_deflate(mz_streamp pStream, int flush)
1065
-{
1066
- size_t in_bytes, out_bytes;
1067
- mz_ulong orig_total_in, orig_total_out;
1068
- int mz_status = MZ_OK;
1069
-
1070
- if ((!pStream) || (!pStream->state) || (flush < 0) || (flush > MZ_FINISH) || (!pStream->next_out)) return MZ_STREAM_ERROR;
1071
- if (!pStream->avail_out) return MZ_BUF_ERROR;
1072
-
1073
- if (flush == MZ_PARTIAL_FLUSH) flush = MZ_SYNC_FLUSH;
1074
-
1075
- if (((tdefl_compressor*)pStream->state)->m_prev_return_status == TDEFL_STATUS_DONE)
1076
- return (flush == MZ_FINISH) ? MZ_STREAM_END : MZ_BUF_ERROR;
1077
-
1078
- orig_total_in = pStream->total_in; orig_total_out = pStream->total_out;
1079
- for ( ; ; )
1080
- {
1081
- tdefl_status defl_status;
1082
- in_bytes = pStream->avail_in; out_bytes = pStream->avail_out;
1083
-
1084
- defl_status = tdefl_compress((tdefl_compressor*)pStream->state, pStream->next_in, &in_bytes, pStream->next_out, &out_bytes, (tdefl_flush)flush);
1085
- pStream->next_in += (mz_uint)in_bytes; pStream->avail_in -= (mz_uint)in_bytes;
1086
- pStream->total_in += (mz_uint)in_bytes; pStream->adler = tdefl_get_adler32((tdefl_compressor*)pStream->state);
1087
-
1088
- pStream->next_out += (mz_uint)out_bytes; pStream->avail_out -= (mz_uint)out_bytes;
1089
- pStream->total_out += (mz_uint)out_bytes;
1090
-
1091
- if (defl_status < 0)
1092
- {
1093
- mz_status = MZ_STREAM_ERROR;
1094
- break;
1095
- }
1096
- else if (defl_status == TDEFL_STATUS_DONE)
1097
- {
1098
- mz_status = MZ_STREAM_END;
1099
- break;
1100
- }
1101
- else if (!pStream->avail_out)
1102
- break;
1103
- else if ((!pStream->avail_in) && (flush != MZ_FINISH))
1104
- {
1105
- if ((flush) || (pStream->total_in != orig_total_in) || (pStream->total_out != orig_total_out))
1106
- break;
1107
- return MZ_BUF_ERROR; // Can't make forward progress without some input.
1108
- }
1109
- }
1110
- return mz_status;
1111
-}
1112
-
1113
-int mz_deflateEnd(mz_streamp pStream)
1114
-{
1115
- if (!pStream) return MZ_STREAM_ERROR;
1116
- if (pStream->state)
1117
- {
1118
- pStream->zfree(pStream->opaque, pStream->state);
1119
- pStream->state = NULL;
1120
- }
1121
- return MZ_OK;
1122
-}
1123
-
1124
-mz_ulong mz_deflateBound(mz_streamp pStream, mz_ulong source_len)
1125
-{
1126
- (void)pStream;
1127
- // This is really over conservative. (And lame, but it's actually pretty tricky to compute a true upper bound given the way tdefl's blocking works.)
1128
- return MZ_MAX(128 + (source_len * 110) / 100, 128 + source_len + ((source_len / (31 * 1024)) + 1) * 5);
1129
-}
1130
-
1131
-int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len, int level)
1132
-{
1133
- int status;
1134
- mz_stream stream;
1135
- memset(&stream, 0, sizeof(stream));
1136
-
1137
- // In case mz_ulong is 64-bits (argh I hate longs).
1138
- if ((source_len | *pDest_len) > 0xFFFFFFFFU) return MZ_PARAM_ERROR;
1139
-
1140
- stream.next_in = pSource;
1141
- stream.avail_in = (mz_uint32)source_len;
1142
- stream.next_out = pDest;
1143
- stream.avail_out = (mz_uint32)*pDest_len;
1144
-
1145
- status = mz_deflateInit(&stream, level);
1146
- if (status != MZ_OK) return status;
1147
-
1148
- status = mz_deflate(&stream, MZ_FINISH);
1149
- if (status != MZ_STREAM_END)
1150
- {
1151
- mz_deflateEnd(&stream);
1152
- return (status == MZ_OK) ? MZ_BUF_ERROR : status;
1153
- }
1154
-
1155
- *pDest_len = stream.total_out;
1156
- return mz_deflateEnd(&stream);
1157
-}
1158
-
1159
-int mz_compress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len)
1160
-{
1161
- return mz_compress2(pDest, pDest_len, pSource, source_len, MZ_DEFAULT_COMPRESSION);
1162
-}
1163
-
1164
-mz_ulong mz_compressBound(mz_ulong source_len)
1165
-{
1166
- return mz_deflateBound(NULL, source_len);
1167
-}
1168
-
1169
-typedef struct
1170
-{
1171
- tinfl_decompressor m_decomp;
1172
- mz_uint m_dict_ofs, m_dict_avail, m_first_call, m_has_flushed; int m_window_bits;
1173
- mz_uint8 m_dict[TINFL_LZ_DICT_SIZE];
1174
- tinfl_status m_last_status;
1175
-} inflate_state;
1176
-
1177
-int mz_inflateInit2(mz_streamp pStream, int window_bits)
1178
-{
1179
- inflate_state *pDecomp;
1180
- if (!pStream) return MZ_STREAM_ERROR;
1181
- if ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS)) return MZ_PARAM_ERROR;
1182
-
1183
- pStream->data_type = 0;
1184
- pStream->adler = 0;
1185
- pStream->msg = NULL;
1186
- pStream->total_in = 0;
1187
- pStream->total_out = 0;
1188
- pStream->reserved = 0;
1189
- if (!pStream->zalloc) pStream->zalloc = def_alloc_func;
1190
- if (!pStream->zfree) pStream->zfree = def_free_func;
1191
-
1192
- pDecomp = (inflate_state*)pStream->zalloc(pStream->opaque, 1, sizeof(inflate_state));
1193
- if (!pDecomp) return MZ_MEM_ERROR;
1194
-
1195
- pStream->state = (struct mz_internal_state *)pDecomp;
1196
-
1197
- tinfl_init(&pDecomp->m_decomp);
1198
- pDecomp->m_dict_ofs = 0;
1199
- pDecomp->m_dict_avail = 0;
1200
- pDecomp->m_last_status = TINFL_STATUS_NEEDS_MORE_INPUT;
1201
- pDecomp->m_first_call = 1;
1202
- pDecomp->m_has_flushed = 0;
1203
- pDecomp->m_window_bits = window_bits;
1204
-
1205
- return MZ_OK;
1206
-}
1207
-
1208
-int mz_inflateInit(mz_streamp pStream)
1209
-{
1210
- return mz_inflateInit2(pStream, MZ_DEFAULT_WINDOW_BITS);
1211
-}
1212
-
1213
-int mz_inflate(mz_streamp pStream, int flush)
1214
-{
1215
- inflate_state* pState;
1216
- mz_uint n, first_call, decomp_flags = TINFL_FLAG_COMPUTE_ADLER32;
1217
- size_t in_bytes, out_bytes, orig_avail_in;
1218
- tinfl_status status;
1219
-
1220
- if ((!pStream) || (!pStream->state)) return MZ_STREAM_ERROR;
1221
- if (flush == MZ_PARTIAL_FLUSH) flush = MZ_SYNC_FLUSH;
1222
- if ((flush) && (flush != MZ_SYNC_FLUSH) && (flush != MZ_FINISH)) return MZ_STREAM_ERROR;
1223
-
1224
- pState = (inflate_state*)pStream->state;
1225
- if (pState->m_window_bits > 0) decomp_flags |= TINFL_FLAG_PARSE_ZLIB_HEADER;
1226
- orig_avail_in = pStream->avail_in;
1227
-
1228
- first_call = pState->m_first_call; pState->m_first_call = 0;
1229
- if (pState->m_last_status < 0) return MZ_DATA_ERROR;
1230
-
1231
- if (pState->m_has_flushed && (flush != MZ_FINISH)) return MZ_STREAM_ERROR;
1232
- pState->m_has_flushed |= (flush == MZ_FINISH);
1233
-
1234
- if ((flush == MZ_FINISH) && (first_call))
1235
- {
1236
- // MZ_FINISH on the first call implies that the input and output buffers are large enough to hold the entire compressed/decompressed file.
1237
- decomp_flags |= TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF;
1238
- in_bytes = pStream->avail_in; out_bytes = pStream->avail_out;
1239
- status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes, pStream->next_out, pStream->next_out, &out_bytes, decomp_flags);
1240
- pState->m_last_status = status;
1241
- pStream->next_in += (mz_uint)in_bytes; pStream->avail_in -= (mz_uint)in_bytes; pStream->total_in += (mz_uint)in_bytes;
1242
- pStream->adler = tinfl_get_adler32(&pState->m_decomp);
1243
- pStream->next_out += (mz_uint)out_bytes; pStream->avail_out -= (mz_uint)out_bytes; pStream->total_out += (mz_uint)out_bytes;
1244
-
1245
- if (status < 0)
1246
- return MZ_DATA_ERROR;
1247
- else if (status != TINFL_STATUS_DONE)
1248
- {
1249
- pState->m_last_status = TINFL_STATUS_FAILED;
1250
- return MZ_BUF_ERROR;
1251
- }
1252
- return MZ_STREAM_END;
1253
- }
1254
- // flush != MZ_FINISH then we must assume there's more input.
1255
- if (flush != MZ_FINISH) decomp_flags |= TINFL_FLAG_HAS_MORE_INPUT;
1256
-
1257
- if (pState->m_dict_avail)
1258
- {
1259
- n = MZ_MIN(pState->m_dict_avail, pStream->avail_out);
1260
- memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n);
1261
- pStream->next_out += n; pStream->avail_out -= n; pStream->total_out += n;
1262
- pState->m_dict_avail -= n; pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1);
1263
- return ((pState->m_last_status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK;
1264
- }
1265
-
1266
- for ( ; ; )
1267
- {
1268
- in_bytes = pStream->avail_in;
1269
- out_bytes = TINFL_LZ_DICT_SIZE - pState->m_dict_ofs;
1270
-
1271
- status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes, pState->m_dict, pState->m_dict + pState->m_dict_ofs, &out_bytes, decomp_flags);
1272
- pState->m_last_status = status;
1273
-
1274
- pStream->next_in += (mz_uint)in_bytes; pStream->avail_in -= (mz_uint)in_bytes;
1275
- pStream->total_in += (mz_uint)in_bytes; pStream->adler = tinfl_get_adler32(&pState->m_decomp);
1276
-
1277
- pState->m_dict_avail = (mz_uint)out_bytes;
1278
-
1279
- n = MZ_MIN(pState->m_dict_avail, pStream->avail_out);
1280
- memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n);
1281
- pStream->next_out += n; pStream->avail_out -= n; pStream->total_out += n;
1282
- pState->m_dict_avail -= n; pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1);
1283
-
1284
- if (status < 0)
1285
- return MZ_DATA_ERROR; // Stream is corrupted (there could be some uncompressed data left in the output dictionary - oh well).
1286
- else if ((status == TINFL_STATUS_NEEDS_MORE_INPUT) && (!orig_avail_in))
1287
- return MZ_BUF_ERROR; // Signal caller that we can't make forward progress without supplying more input or by setting flush to MZ_FINISH.
1288
- else if (flush == MZ_FINISH)
1289
- {
1290
- // The output buffer MUST be large to hold the remaining uncompressed data when flush==MZ_FINISH.
1291
- if (status == TINFL_STATUS_DONE)
1292
- return pState->m_dict_avail ? MZ_BUF_ERROR : MZ_STREAM_END;
1293
- // status here must be TINFL_STATUS_HAS_MORE_OUTPUT, which means there's at least 1 more byte on the way. If there's no more room left in the output buffer then something is wrong.
1294
- else if (!pStream->avail_out)
1295
- return MZ_BUF_ERROR;
1296
- }
1297
- else if ((status == TINFL_STATUS_DONE) || (!pStream->avail_in) || (!pStream->avail_out) || (pState->m_dict_avail))
1298
- break;
1299
- }
1300
-
1301
- return ((status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK;
1302
-}
1303
-
1304
-int mz_inflateEnd(mz_streamp pStream)
1305
-{
1306
- if (!pStream)
1307
- return MZ_STREAM_ERROR;
1308
- if (pStream->state)
1309
- {
1310
- pStream->zfree(pStream->opaque, pStream->state);
1311
- pStream->state = NULL;
1312
- }
1313
- return MZ_OK;
1314
-}
1315
-
1316
-int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len)
1317
-{
1318
- mz_stream stream;
1319
- int status;
1320
- memset(&stream, 0, sizeof(stream));
1321
-
1322
- // In case mz_ulong is 64-bits (argh I hate longs).
1323
- if ((source_len | *pDest_len) > 0xFFFFFFFFU) return MZ_PARAM_ERROR;
1324
-
1325
- stream.next_in = pSource;
1326
- stream.avail_in = (mz_uint32)source_len;
1327
- stream.next_out = pDest;
1328
- stream.avail_out = (mz_uint32)*pDest_len;
1329
-
1330
- status = mz_inflateInit(&stream);
1331
- if (status != MZ_OK)
1332
- return status;
1333
-
1334
- status = mz_inflate(&stream, MZ_FINISH);
1335
- if (status != MZ_STREAM_END)
1336
- {
1337
- mz_inflateEnd(&stream);
1338
- return ((status == MZ_BUF_ERROR) && (!stream.avail_in)) ? MZ_DATA_ERROR : status;
1339
- }
1340
- *pDest_len = stream.total_out;
1341
-
1342
- return mz_inflateEnd(&stream);
1343
-}
1344
-
1345
-const char *mz_error(int err)
1346
-{
1347
- static const struct { int m_err; const char *m_pDesc; } s_error_descs[] =
1348
- {
1349
- { MZ_OK, "" }, { MZ_STREAM_END, "stream end" }, { MZ_NEED_DICT, "need dictionary" }, { MZ_ERRNO, "file error" }, { MZ_STREAM_ERROR, "stream error" },
1350
- { MZ_DATA_ERROR, "data error" }, { MZ_MEM_ERROR, "out of memory" }, { MZ_BUF_ERROR, "buf error" }, { MZ_VERSION_ERROR, "version error" }, { MZ_PARAM_ERROR, "parameter error" }
1351
- };
1352
- mz_uint i; for (i = 0; i < sizeof(s_error_descs) / sizeof(s_error_descs[0]); ++i) if (s_error_descs[i].m_err == err) return s_error_descs[i].m_pDesc;
1353
- return NULL;
1354
-}
1355
-
1356
-#endif //MINIZ_NO_ZLIB_APIS
1357
-
1358
-// ------------------- Low-level Decompression (completely independent from all compression API's)
1359
-
1360
-#define TINFL_MEMCPY(d, s, l) memcpy(d, s, l)
1361
-#define TINFL_MEMSET(p, c, l) memset(p, c, l)
1362
-
1363
-#define TINFL_CR_BEGIN switch(r->m_state) { case 0:
1364
-#define TINFL_CR_RETURN(state_index, result) do { status = result; r->m_state = state_index; goto common_exit; case state_index:; } MZ_MACRO_END
1365
-#define TINFL_CR_RETURN_FOREVER(state_index, result) do { for ( ; ; ) { TINFL_CR_RETURN(state_index, result); } } MZ_MACRO_END
1366
-#define TINFL_CR_FINISH }
1367
-
1368
-// TODO: If the caller has indicated that there's no more input, and we attempt to read beyond the input buf, then something is wrong with the input because the inflator never
1369
-// reads ahead more than it needs to. Currently TINFL_GET_BYTE() pads the end of the stream with 0's in this scenario.
1370
-#define TINFL_GET_BYTE(state_index, c) do { \
1371
- if (pIn_buf_cur >= pIn_buf_end) { \
1372
- for ( ; ; ) { \
1373
- if (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) { \
1374
- TINFL_CR_RETURN(state_index, TINFL_STATUS_NEEDS_MORE_INPUT); \
1375
- if (pIn_buf_cur < pIn_buf_end) { \
1376
- c = *pIn_buf_cur++; \
1377
- break; \
1378
- } \
1379
- } else { \
1380
- c = 0; \
1381
- break; \
1382
- } \
1383
- } \
1384
- } else c = *pIn_buf_cur++; } MZ_MACRO_END
1385
-
1386
-#define TINFL_NEED_BITS(state_index, n) do { mz_uint c; TINFL_GET_BYTE(state_index, c); bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); num_bits += 8; } while (num_bits < (mz_uint)(n))
1387
-#define TINFL_SKIP_BITS(state_index, n) do { if (num_bits < (mz_uint)(n)) { TINFL_NEED_BITS(state_index, n); } bit_buf >>= (n); num_bits -= (n); } MZ_MACRO_END
1388
-#define TINFL_GET_BITS(state_index, b, n) do { if (num_bits < (mz_uint)(n)) { TINFL_NEED_BITS(state_index, n); } b = bit_buf & ((1 << (n)) - 1); bit_buf >>= (n); num_bits -= (n); } MZ_MACRO_END
1389
-
1390
-// TINFL_HUFF_BITBUF_FILL() is only used rarely, when the number of bytes remaining in the input buffer falls below 2.
1391
-// It reads just enough bytes from the input stream that are needed to decode the next Huffman code (and absolutely no more). It works by trying to fully decode a
1392
-// Huffman code by using whatever bits are currently present in the bit buffer. If this fails, it reads another byte, and tries again until it succeeds or until the
1393
-// bit buffer contains >=15 bits (deflate's max. Huffman code size).
1394
-#define TINFL_HUFF_BITBUF_FILL(state_index, pHuff) \
1395
- do { \
1396
- temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]; \
1397
- if (temp >= 0) { \
1398
- code_len = temp >> 9; \
1399
- if ((code_len) && (num_bits >= code_len)) \
1400
- break; \
1401
- } else if (num_bits > TINFL_FAST_LOOKUP_BITS) { \
1402
- code_len = TINFL_FAST_LOOKUP_BITS; \
1403
- do { \
1404
- temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; \
1405
- } while ((temp < 0) && (num_bits >= (code_len + 1))); if (temp >= 0) break; \
1406
- } TINFL_GET_BYTE(state_index, c); bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); num_bits += 8; \
1407
- } while (num_bits < 15);
1408
-
1409
-// TINFL_HUFF_DECODE() decodes the next Huffman coded symbol. It's more complex than you would initially expect because the zlib API expects the decompressor to never read
1410
-// beyond the final byte of the deflate stream. (In other words, when this macro wants to read another byte from the input, it REALLY needs another byte in order to fully
1411
-// decode the next Huffman code.) Handling this properly is particularly important on raw deflate (non-zlib) streams, which aren't followed by a byte aligned adler-32.
1412
-// The slow path is only executed at the very end of the input buffer.
1413
-#define TINFL_HUFF_DECODE(state_index, sym, pHuff) do { \
1414
- int temp; mz_uint code_len, c; \
1415
- if (num_bits < 15) { \
1416
- if ((pIn_buf_end - pIn_buf_cur) < 2) { \
1417
- TINFL_HUFF_BITBUF_FILL(state_index, pHuff); \
1418
- } else { \
1419
- bit_buf |= (((tinfl_bit_buf_t)pIn_buf_cur[0]) << num_bits) | (((tinfl_bit_buf_t)pIn_buf_cur[1]) << (num_bits + 8)); pIn_buf_cur += 2; num_bits += 16; \
1420
- } \
1421
- } \
1422
- if ((temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0) \
1423
- code_len = temp >> 9, temp &= 511; \
1424
- else { \
1425
- code_len = TINFL_FAST_LOOKUP_BITS; do { temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; } while (temp < 0); \
1426
- } sym = temp; bit_buf >>= code_len; num_bits -= code_len; } MZ_MACRO_END
1427
-
1428
-tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_next, size_t *pIn_buf_size, mz_uint8 *pOut_buf_start, mz_uint8 *pOut_buf_next, size_t *pOut_buf_size, const mz_uint32 decomp_flags)
1429
-{
1430
- static const int s_length_base[31] = { 3,4,5,6,7,8,9,10,11,13, 15,17,19,23,27,31,35,43,51,59, 67,83,99,115,131,163,195,227,258,0,0 };
1431
- static const int s_length_extra[31]= { 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0 };
1432
- static const int s_dist_base[32] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193, 257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0};
1433
- static const int s_dist_extra[32] = { 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13};
1434
- static const mz_uint8 s_length_dezigzag[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 };
1435
- static const int s_min_table_sizes[3] = { 257, 1, 4 };
1436
-
1437
- tinfl_status status = TINFL_STATUS_FAILED; mz_uint32 num_bits, dist, counter, num_extra; tinfl_bit_buf_t bit_buf;
1438
- const mz_uint8 *pIn_buf_cur = pIn_buf_next, *const pIn_buf_end = pIn_buf_next + *pIn_buf_size;
1439
- mz_uint8 *pOut_buf_cur = pOut_buf_next, *const pOut_buf_end = pOut_buf_next + *pOut_buf_size;
1440
- size_t out_buf_size_mask = (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF) ? (size_t)-1 : ((pOut_buf_next - pOut_buf_start) + *pOut_buf_size) - 1, dist_from_out_buf_start;
1441
-
1442
- // Ensure the output buffer's size is a power of 2, unless the output buffer is large enough to hold the entire output file (in which case it doesn't matter).
1443
- if (((out_buf_size_mask + 1) & out_buf_size_mask) || (pOut_buf_next < pOut_buf_start)) { *pIn_buf_size = *pOut_buf_size = 0; return TINFL_STATUS_BAD_PARAM; }
1444
-
1445
- num_bits = r->m_num_bits; bit_buf = r->m_bit_buf; dist = r->m_dist; counter = r->m_counter; num_extra = r->m_num_extra; dist_from_out_buf_start = r->m_dist_from_out_buf_start;
1446
- TINFL_CR_BEGIN
1447
-
1448
- bit_buf = num_bits = dist = counter = num_extra = r->m_zhdr0 = r->m_zhdr1 = 0; r->m_z_adler32 = r->m_check_adler32 = 1;
1449
- if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER)
1450
- {
1451
- TINFL_GET_BYTE(1, r->m_zhdr0); TINFL_GET_BYTE(2, r->m_zhdr1);
1452
- counter = (((r->m_zhdr0 * 256 + r->m_zhdr1) % 31 != 0) || (r->m_zhdr1 & 32) || ((r->m_zhdr0 & 15) != 8));
1453
- if (!(decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)) counter |= (((1U << (8U + (r->m_zhdr0 >> 4))) > 32768U) || ((out_buf_size_mask + 1) < (size_t)(1U << (8U + (r->m_zhdr0 >> 4)))));
1454
- if (counter) { TINFL_CR_RETURN_FOREVER(36, TINFL_STATUS_FAILED); }
1455
- }
1456
-
1457
- do
1458
- {
1459
- TINFL_GET_BITS(3, r->m_final, 3); r->m_type = r->m_final >> 1;
1460
- if (r->m_type == 0)
1461
- {
1462
- TINFL_SKIP_BITS(5, num_bits & 7);
1463
- for (counter = 0; counter < 4; ++counter) { if (num_bits) TINFL_GET_BITS(6, r->m_raw_header[counter], 8); else TINFL_GET_BYTE(7, r->m_raw_header[counter]); }
1464
- if ((counter = (r->m_raw_header[0] | (r->m_raw_header[1] << 8))) != (mz_uint)(0xFFFF ^ (r->m_raw_header[2] | (r->m_raw_header[3] << 8)))) { TINFL_CR_RETURN_FOREVER(39, TINFL_STATUS_FAILED); }
1465
- while ((counter) && (num_bits))
1466
- {
1467
- TINFL_GET_BITS(51, dist, 8);
1468
- while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(52, TINFL_STATUS_HAS_MORE_OUTPUT); }
1469
- *pOut_buf_cur++ = (mz_uint8)dist;
1470
- counter--;
1471
- }
1472
- while (counter)
1473
- {
1474
- size_t n; while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(9, TINFL_STATUS_HAS_MORE_OUTPUT); }
1475
- while (pIn_buf_cur >= pIn_buf_end)
1476
- {
1477
- if (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT)
1478
- {
1479
- TINFL_CR_RETURN(38, TINFL_STATUS_NEEDS_MORE_INPUT);
1480
- }
1481
- else
1482
- {
1483
- TINFL_CR_RETURN_FOREVER(40, TINFL_STATUS_FAILED);
1484
- }
1485
- }
1486
- n = MZ_MIN(MZ_MIN((size_t)(pOut_buf_end - pOut_buf_cur), (size_t)(pIn_buf_end - pIn_buf_cur)), counter);
1487
- TINFL_MEMCPY(pOut_buf_cur, pIn_buf_cur, n); pIn_buf_cur += n; pOut_buf_cur += n; counter -= (mz_uint)n;
1488
- }
1489
- }
1490
- else if (r->m_type == 3)
1491
- {
1492
- TINFL_CR_RETURN_FOREVER(10, TINFL_STATUS_FAILED);
1493
- }
1494
- else
1495
- {
1496
- if (r->m_type == 1)
1497
- {
1498
- mz_uint8 *p = r->m_tables[0].m_code_size; mz_uint i;
1499
- r->m_table_sizes[0] = 288; r->m_table_sizes[1] = 32; TINFL_MEMSET(r->m_tables[1].m_code_size, 5, 32);
1500
- for ( i = 0; i <= 143; ++i) *p++ = 8; for ( ; i <= 255; ++i) *p++ = 9; for ( ; i <= 279; ++i) *p++ = 7; for ( ; i <= 287; ++i) *p++ = 8;
1501
- }
1502
- else
1503
- {
1504
- for (counter = 0; counter < 3; counter++) { TINFL_GET_BITS(11, r->m_table_sizes[counter], "\05\05\04"[counter]); r->m_table_sizes[counter] += s_min_table_sizes[counter]; }
1505
- MZ_CLEAR_OBJ(r->m_tables[2].m_code_size); for (counter = 0; counter < r->m_table_sizes[2]; counter++) { mz_uint s; TINFL_GET_BITS(14, s, 3); r->m_tables[2].m_code_size[s_length_dezigzag[counter]] = (mz_uint8)s; }
1506
- r->m_table_sizes[2] = 19;
1507
- }
1508
- for ( ; (int)r->m_type >= 0; r->m_type--)
1509
- {
1510
- int tree_next, tree_cur; tinfl_huff_table *pTable;
1511
- mz_uint i, j, used_syms, total, sym_index, next_code[17], total_syms[16]; pTable = &r->m_tables[r->m_type]; MZ_CLEAR_OBJ(total_syms); MZ_CLEAR_OBJ(pTable->m_look_up); MZ_CLEAR_OBJ(pTable->m_tree);
1512
- for (i = 0; i < r->m_table_sizes[r->m_type]; ++i) total_syms[pTable->m_code_size[i]]++;
1513
- used_syms = 0, total = 0; next_code[0] = next_code[1] = 0;
1514
- for (i = 1; i <= 15; ++i) { used_syms += total_syms[i]; next_code[i + 1] = (total = ((total + total_syms[i]) << 1)); }
1515
- if ((65536 != total) && (used_syms > 1))
1516
- {
1517
- TINFL_CR_RETURN_FOREVER(35, TINFL_STATUS_FAILED);
1518
- }
1519
- for (tree_next = -1, sym_index = 0; sym_index < r->m_table_sizes[r->m_type]; ++sym_index)
1520
- {
1521
- mz_uint rev_code = 0, l, cur_code, code_size = pTable->m_code_size[sym_index]; if (!code_size) continue;
1522
- cur_code = next_code[code_size]++; for (l = code_size; l > 0; l--, cur_code >>= 1) rev_code = (rev_code << 1) | (cur_code & 1);
1523
- if (code_size <= TINFL_FAST_LOOKUP_BITS) { mz_int16 k = (mz_int16)((code_size << 9) | sym_index); while (rev_code < TINFL_FAST_LOOKUP_SIZE) { pTable->m_look_up[rev_code] = k; rev_code += (1 << code_size); } continue; }
1524
- if (0 == (tree_cur = pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)])) { pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)] = (mz_int16)tree_next; tree_cur = tree_next; tree_next -= 2; }
1525
- rev_code >>= (TINFL_FAST_LOOKUP_BITS - 1);
1526
- for (j = code_size; j > (TINFL_FAST_LOOKUP_BITS + 1); j--)
1527
- {
1528
- tree_cur -= ((rev_code >>= 1) & 1);
1529
- if (!pTable->m_tree[-tree_cur - 1]) { pTable->m_tree[-tree_cur - 1] = (mz_int16)tree_next; tree_cur = tree_next; tree_next -= 2; } else tree_cur = pTable->m_tree[-tree_cur - 1];
1530
- }
1531
- tree_cur -= ((rev_code >>= 1) & 1); pTable->m_tree[-tree_cur - 1] = (mz_int16)sym_index;
1532
- }
1533
- if (r->m_type == 2)
1534
- {
1535
- for (counter = 0; counter < (r->m_table_sizes[0] + r->m_table_sizes[1]); )
1536
- {
1537
- mz_uint s; TINFL_HUFF_DECODE(16, dist, &r->m_tables[2]); if (dist < 16) { r->m_len_codes[counter++] = (mz_uint8)dist; continue; }
1538
- if ((dist == 16) && (!counter))
1539
- {
1540
- TINFL_CR_RETURN_FOREVER(17, TINFL_STATUS_FAILED);
1541
- }
1542
- num_extra = "\02\03\07"[dist - 16]; TINFL_GET_BITS(18, s, num_extra); s += "\03\03\013"[dist - 16];
1543
- TINFL_MEMSET(r->m_len_codes + counter, (dist == 16) ? r->m_len_codes[counter - 1] : 0, s); counter += s;
1544
- }
1545
- if ((r->m_table_sizes[0] + r->m_table_sizes[1]) != counter)
1546
- {
1547
- TINFL_CR_RETURN_FOREVER(21, TINFL_STATUS_FAILED);
1548
- }
1549
- TINFL_MEMCPY(r->m_tables[0].m_code_size, r->m_len_codes, r->m_table_sizes[0]); TINFL_MEMCPY(r->m_tables[1].m_code_size, r->m_len_codes + r->m_table_sizes[0], r->m_table_sizes[1]);
1550
- }
1551
- }
1552
- for ( ; ; )
1553
- {
1554
- mz_uint8 *pSrc;
1555
- for ( ; ; )
1556
- {
1557
- if (((pIn_buf_end - pIn_buf_cur) < 4) || ((pOut_buf_end - pOut_buf_cur) < 2))
1558
- {
1559
- TINFL_HUFF_DECODE(23, counter, &r->m_tables[0]);
1560
- if (counter >= 256)
1561
- break;
1562
- while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(24, TINFL_STATUS_HAS_MORE_OUTPUT); }
1563
- *pOut_buf_cur++ = (mz_uint8)counter;
1564
- }
1565
- else
1566
- {
1567
- int sym2; mz_uint code_len;
1568
-#if TINFL_USE_64BIT_BITBUF
1569
- if (num_bits < 30) { bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE32(pIn_buf_cur)) << num_bits); pIn_buf_cur += 4; num_bits += 32; }
1570
-#else
1571
- if (num_bits < 15) { bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits); pIn_buf_cur += 2; num_bits += 16; }
1572
-#endif
1573
- if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0)
1574
- code_len = sym2 >> 9;
1575
- else
1576
- {
1577
- code_len = TINFL_FAST_LOOKUP_BITS; do { sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)]; } while (sym2 < 0);
1578
- }
1579
- counter = sym2; bit_buf >>= code_len; num_bits -= code_len;
1580
- if (counter & 256)
1581
- break;
1582
-
1583
-#if !TINFL_USE_64BIT_BITBUF
1584
- if (num_bits < 15) { bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits); pIn_buf_cur += 2; num_bits += 16; }
1585
-#endif
1586
- if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0)
1587
- code_len = sym2 >> 9;
1588
- else
1589
- {
1590
- code_len = TINFL_FAST_LOOKUP_BITS; do { sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)]; } while (sym2 < 0);
1591
- }
1592
- bit_buf >>= code_len; num_bits -= code_len;
1593
-
1594
- pOut_buf_cur[0] = (mz_uint8)counter;
1595
- if (sym2 & 256)
1596
- {
1597
- pOut_buf_cur++;
1598
- counter = sym2;
1599
- break;
1600
- }
1601
- pOut_buf_cur[1] = (mz_uint8)sym2;
1602
- pOut_buf_cur += 2;
1603
- }
1604
- }
1605
- if ((counter &= 511) == 256) break;
1606
-
1607
- num_extra = s_length_extra[counter - 257]; counter = s_length_base[counter - 257];
1608
- if (num_extra) { mz_uint extra_bits; TINFL_GET_BITS(25, extra_bits, num_extra); counter += extra_bits; }
1609
-
1610
- TINFL_HUFF_DECODE(26, dist, &r->m_tables[1]);
1611
- num_extra = s_dist_extra[dist]; dist = s_dist_base[dist];
1612
- if (num_extra) { mz_uint extra_bits; TINFL_GET_BITS(27, extra_bits, num_extra); dist += extra_bits; }
1613
-
1614
- dist_from_out_buf_start = pOut_buf_cur - pOut_buf_start;
1615
- if ((dist > dist_from_out_buf_start) && (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF))
1616
- {
1617
- TINFL_CR_RETURN_FOREVER(37, TINFL_STATUS_FAILED);
1618
- }
1619
-
1620
- pSrc = pOut_buf_start + ((dist_from_out_buf_start - dist) & out_buf_size_mask);
1621
-
1622
- if ((MZ_MAX(pOut_buf_cur, pSrc) + counter) > pOut_buf_end)
1623
- {
1624
- while (counter--)
1625
- {
1626
- while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(53, TINFL_STATUS_HAS_MORE_OUTPUT); }
1627
- *pOut_buf_cur++ = pOut_buf_start[(dist_from_out_buf_start++ - dist) & out_buf_size_mask];
1628
- }
1629
- continue;
1630
- }
1631
-#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES
1632
- else if ((counter >= 9) && (counter <= dist))
1633
- {
1634
- const mz_uint8 *pSrc_end = pSrc + (counter & ~7);
1635
- do
1636
- {
1637
- ((mz_uint32 *)pOut_buf_cur)[0] = ((const mz_uint32 *)pSrc)[0];
1638
- ((mz_uint32 *)pOut_buf_cur)[1] = ((const mz_uint32 *)pSrc)[1];
1639
- pOut_buf_cur += 8;
1640
- } while ((pSrc += 8) < pSrc_end);
1641
- if ((counter &= 7) < 3)
1642
- {
1643
- if (counter)
1644
- {
1645
- pOut_buf_cur[0] = pSrc[0];
1646
- if (counter > 1)
1647
- pOut_buf_cur[1] = pSrc[1];
1648
- pOut_buf_cur += counter;
1649
- }
1650
- continue;
1651
- }
1652
- }
1653
-#endif
1654
- do
1655
- {
1656
- pOut_buf_cur[0] = pSrc[0];
1657
- pOut_buf_cur[1] = pSrc[1];
1658
- pOut_buf_cur[2] = pSrc[2];
1659
- pOut_buf_cur += 3; pSrc += 3;
1660
- } while ((int)(counter -= 3) > 2);
1661
- if ((int)counter > 0)
1662
- {
1663
- pOut_buf_cur[0] = pSrc[0];
1664
- if ((int)counter > 1)
1665
- pOut_buf_cur[1] = pSrc[1];
1666
- pOut_buf_cur += counter;
1667
- }
1668
- }
1669
- }
1670
- } while (!(r->m_final & 1));
1671
- if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER)
1672
- {
1673
- TINFL_SKIP_BITS(32, num_bits & 7); for (counter = 0; counter < 4; ++counter) { mz_uint s; if (num_bits) TINFL_GET_BITS(41, s, 8); else TINFL_GET_BYTE(42, s); r->m_z_adler32 = (r->m_z_adler32 << 8) | s; }
1674
- }
1675
- TINFL_CR_RETURN_FOREVER(34, TINFL_STATUS_DONE);
1676
- TINFL_CR_FINISH
1677
-
1678
-common_exit:
1679
- r->m_num_bits = num_bits; r->m_bit_buf = bit_buf; r->m_dist = dist; r->m_counter = counter; r->m_num_extra = num_extra; r->m_dist_from_out_buf_start = dist_from_out_buf_start;
1680
- *pIn_buf_size = pIn_buf_cur - pIn_buf_next; *pOut_buf_size = pOut_buf_cur - pOut_buf_next;
1681
- if ((decomp_flags & (TINFL_FLAG_PARSE_ZLIB_HEADER | TINFL_FLAG_COMPUTE_ADLER32)) && (status >= 0))
1682
- {
1683
- const mz_uint8 *ptr = pOut_buf_next; size_t buf_len = *pOut_buf_size;
1684
- mz_uint32 i, s1 = r->m_check_adler32 & 0xffff, s2 = r->m_check_adler32 >> 16; size_t block_len = buf_len % 5552;
1685
- while (buf_len)
1686
- {
1687
- for (i = 0; i + 7 < block_len; i += 8, ptr += 8)
1688
- {
1689
- s1 += ptr[0], s2 += s1; s1 += ptr[1], s2 += s1; s1 += ptr[2], s2 += s1; s1 += ptr[3], s2 += s1;
1690
- s1 += ptr[4], s2 += s1; s1 += ptr[5], s2 += s1; s1 += ptr[6], s2 += s1; s1 += ptr[7], s2 += s1;
1691
- }
1692
- for ( ; i < block_len; ++i) s1 += *ptr++, s2 += s1;
1693
- s1 %= 65521U, s2 %= 65521U; buf_len -= block_len; block_len = 5552;
1694
- }
1695
- r->m_check_adler32 = (s2 << 16) + s1; if ((status == TINFL_STATUS_DONE) && (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) && (r->m_check_adler32 != r->m_z_adler32)) status = TINFL_STATUS_ADLER32_MISMATCH;
1696
- }
1697
- return status;
1698
-}
1699
-
1700
-// Higher level helper functions.
1701
-void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags)
1702
-{
1703
- tinfl_decompressor decomp; void *pBuf = NULL, *pNew_buf; size_t src_buf_ofs = 0, out_buf_capacity = 0;
1704
- *pOut_len = 0;
1705
- tinfl_init(&decomp);
1706
- for ( ; ; )
1707
- {
1708
- size_t src_buf_size = src_buf_len - src_buf_ofs, dst_buf_size = out_buf_capacity - *pOut_len, new_out_buf_capacity;
1709
- tinfl_status status = tinfl_decompress(&decomp, (const mz_uint8*)pSrc_buf + src_buf_ofs, &src_buf_size, (mz_uint8*)pBuf, pBuf ? (mz_uint8*)pBuf + *pOut_len : NULL, &dst_buf_size,
1710
- (flags & ~TINFL_FLAG_HAS_MORE_INPUT) | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF);
1711
- if ((status < 0) || (status == TINFL_STATUS_NEEDS_MORE_INPUT))
1712
- {
1713
- MZ_FREE(pBuf); *pOut_len = 0; return NULL;
1714
- }
1715
- src_buf_ofs += src_buf_size;
1716
- *pOut_len += dst_buf_size;
1717
- if (status == TINFL_STATUS_DONE) break;
1718
- new_out_buf_capacity = out_buf_capacity * 2; if (new_out_buf_capacity < 128) new_out_buf_capacity = 128;
1719
- pNew_buf = MZ_REALLOC(pBuf, new_out_buf_capacity);
1720
- if (!pNew_buf)
1721
- {
1722
- MZ_FREE(pBuf); *pOut_len = 0; return NULL;
1723
- }
1724
- pBuf = pNew_buf; out_buf_capacity = new_out_buf_capacity;
1725
- }
1726
- return pBuf;
1727
-}
1728
-
1729
-size_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags)
1730
-{
1731
- tinfl_decompressor decomp; tinfl_status status; tinfl_init(&decomp);
1732
- status = tinfl_decompress(&decomp, (const mz_uint8*)pSrc_buf, &src_buf_len, (mz_uint8*)pOut_buf, (mz_uint8*)pOut_buf, &out_buf_len, (flags & ~TINFL_FLAG_HAS_MORE_INPUT) | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF);
1733
- return (status != TINFL_STATUS_DONE) ? TINFL_DECOMPRESS_MEM_TO_MEM_FAILED : out_buf_len;
1734
-}
1735
-
1736
-int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size, tinfl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags)
1737
-{
1738
- int result = 0;
1739
- tinfl_decompressor decomp;
1740
- mz_uint8 *pDict = (mz_uint8*)MZ_MALLOC(TINFL_LZ_DICT_SIZE); size_t in_buf_ofs = 0, dict_ofs = 0;
1741
- if (!pDict)
1742
- return TINFL_STATUS_FAILED;
1743
- tinfl_init(&decomp);
1744
- for ( ; ; )
1745
- {
1746
- size_t in_buf_size = *pIn_buf_size - in_buf_ofs, dst_buf_size = TINFL_LZ_DICT_SIZE - dict_ofs;
1747
- tinfl_status status = tinfl_decompress(&decomp, (const mz_uint8*)pIn_buf + in_buf_ofs, &in_buf_size, pDict, pDict + dict_ofs, &dst_buf_size,
1748
- (flags & ~(TINFL_FLAG_HAS_MORE_INPUT | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)));
1749
- in_buf_ofs += in_buf_size;
1750
- if ((dst_buf_size) && (!(*pPut_buf_func)(pDict + dict_ofs, (int)dst_buf_size, pPut_buf_user)))
1751
- break;
1752
- if (status != TINFL_STATUS_HAS_MORE_OUTPUT)
1753
- {
1754
- result = (status == TINFL_STATUS_DONE);
1755
- break;
1756
- }
1757
- dict_ofs = (dict_ofs + dst_buf_size) & (TINFL_LZ_DICT_SIZE - 1);
1758
- }
1759
- MZ_FREE(pDict);
1760
- *pIn_buf_size = in_buf_ofs;
1761
- return result;
1762
-}
1763
-
1764
-// ------------------- Low-level Compression (independent from all decompression API's)
1765
-
1766
-// Purposely making these tables static for faster init and thread safety.
1767
-static const mz_uint16 s_tdefl_len_sym[256] = {
1768
- 257,258,259,260,261,262,263,264,265,265,266,266,267,267,268,268,269,269,269,269,270,270,270,270,271,271,271,271,272,272,272,272,
1769
- 273,273,273,273,273,273,273,273,274,274,274,274,274,274,274,274,275,275,275,275,275,275,275,275,276,276,276,276,276,276,276,276,
1770
- 277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,
1771
- 279,279,279,279,279,279,279,279,279,279,279,279,279,279,279,279,280,280,280,280,280,280,280,280,280,280,280,280,280,280,280,280,
1772
- 281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,
1773
- 282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,
1774
- 283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,
1775
- 284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,285 };
1776
-
1777
-static const mz_uint8 s_tdefl_len_extra[256] = {
1778
- 0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
1779
- 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
1780
- 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
1781
- 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0 };
1782
-
1783
-static const mz_uint8 s_tdefl_small_dist_sym[512] = {
1784
- 0,1,2,3,4,4,5,5,6,6,6,6,7,7,7,7,8,8,8,8,8,8,8,8,9,9,9,9,9,9,9,9,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,11,11,11,11,11,11,
1785
- 11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,13,
1786
- 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,14,14,14,14,14,14,14,14,14,14,14,14,
1787
- 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,
1788
- 14,14,14,14,14,14,14,14,14,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
1789
- 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,16,16,16,16,16,16,16,16,16,16,16,16,16,
1790
- 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
1791
- 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
1792
- 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
1793
- 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
1794
- 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
1795
- 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17 };
1796
-
1797
-static const mz_uint8 s_tdefl_small_dist_extra[512] = {
1798
- 0,0,0,0,1,1,1,1,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,
1799
- 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1800
- 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1801
- 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1802
- 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1803
- 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1804
- 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1805
- 7,7,7,7,7,7,7,7 };
1806
-
1807
-static const mz_uint8 s_tdefl_large_dist_sym[128] = {
1808
- 0,0,18,19,20,20,21,21,22,22,22,22,23,23,23,23,24,24,24,24,24,24,24,24,25,25,25,25,25,25,25,25,26,26,26,26,26,26,26,26,26,26,26,26,
1809
- 26,26,26,26,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,
1810
- 28,28,28,28,28,28,28,28,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29 };
1811
-
1812
-static const mz_uint8 s_tdefl_large_dist_extra[128] = {
1813
- 0,0,8,8,9,9,9,9,10,10,10,10,10,10,10,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
1814
- 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,
1815
- 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13 };
1816
-
1817
-// Radix sorts tdefl_sym_freq[] array by 16-bit key m_key. Returns ptr to sorted values.
1818
-typedef struct { mz_uint16 m_key, m_sym_index; } tdefl_sym_freq;
1819
-static tdefl_sym_freq* tdefl_radix_sort_syms(mz_uint num_syms, tdefl_sym_freq* pSyms0, tdefl_sym_freq* pSyms1)
1820
-{
1821
- mz_uint32 total_passes = 2, pass_shift, pass, i, hist[256 * 2]; tdefl_sym_freq* pCur_syms = pSyms0, *pNew_syms = pSyms1; MZ_CLEAR_OBJ(hist);
1822
- for (i = 0; i < num_syms; i++) { mz_uint freq = pSyms0[i].m_key; hist[freq & 0xFF]++; hist[256 + ((freq >> 8) & 0xFF)]++; }
1823
- while ((total_passes > 1) && (num_syms == hist[(total_passes - 1) * 256])) total_passes--;
1824
- for (pass_shift = 0, pass = 0; pass < total_passes; pass++, pass_shift += 8)
1825
- {
1826
- const mz_uint32* pHist = &hist[pass << 8];
1827
- mz_uint offsets[256], cur_ofs = 0;
1828
- for (i = 0; i < 256; i++) { offsets[i] = cur_ofs; cur_ofs += pHist[i]; }
1829
- for (i = 0; i < num_syms; i++) pNew_syms[offsets[(pCur_syms[i].m_key >> pass_shift) & 0xFF]++] = pCur_syms[i];
1830
- { tdefl_sym_freq* t = pCur_syms; pCur_syms = pNew_syms; pNew_syms = t; }
1831
- }
1832
- return pCur_syms;
1833
-}
1834
-
1835
-// tdefl_calculate_minimum_redundancy() originally written by: Alistair Moffat, [email protected], Jyrki Katajainen, [email protected], November 1996.
1836
-static void tdefl_calculate_minimum_redundancy(tdefl_sym_freq *A, int n)
1837
-{
1838
- int root, leaf, next, avbl, used, dpth;
1839
- if (n==0) return; else if (n==1) { A[0].m_key = 1; return; }
1840
- A[0].m_key += A[1].m_key; root = 0; leaf = 2;
1841
- for (next=1; next < n-1; next++)
1842
- {
1843
- if (leaf>=n || A[root].m_key<A[leaf].m_key) { A[next].m_key = A[root].m_key; A[root++].m_key = (mz_uint16)next; } else A[next].m_key = A[leaf++].m_key;
1844
- if (leaf>=n || (root<next && A[root].m_key<A[leaf].m_key)) { A[next].m_key = (mz_uint16)(A[next].m_key + A[root].m_key); A[root++].m_key = (mz_uint16)next; } else A[next].m_key = (mz_uint16)(A[next].m_key + A[leaf++].m_key);
1845
- }
1846
- A[n-2].m_key = 0; for (next=n-3; next>=0; next--) A[next].m_key = A[A[next].m_key].m_key+1;
1847
- avbl = 1; used = dpth = 0; root = n-2; next = n-1;
1848
- while (avbl>0)
1849
- {
1850
- while (root>=0 && (int)A[root].m_key==dpth) { used++; root--; }
1851
- while (avbl>used) { A[next--].m_key = (mz_uint16)(dpth); avbl--; }
1852
- avbl = 2*used; dpth++; used = 0;
1853
- }
1854
-}
1855
-
1856
-// Limits canonical Huffman code table's max code size.
1857
-enum { TDEFL_MAX_SUPPORTED_HUFF_CODESIZE = 32 };
1858
-static void tdefl_huffman_enforce_max_code_size(int *pNum_codes, int code_list_len, int max_code_size)
1859
-{
1860
- int i; mz_uint32 total = 0; if (code_list_len <= 1) return;
1861
- for (i = max_code_size + 1; i <= TDEFL_MAX_SUPPORTED_HUFF_CODESIZE; i++) pNum_codes[max_code_size] += pNum_codes[i];
1862
- for (i = max_code_size; i > 0; i--) total += (((mz_uint32)pNum_codes[i]) << (max_code_size - i));
1863
- while (total != (1UL << max_code_size))
1864
- {
1865
- pNum_codes[max_code_size]--;
1866
- for (i = max_code_size - 1; i > 0; i--) if (pNum_codes[i]) { pNum_codes[i]--; pNum_codes[i + 1] += 2; break; }
1867
- total--;
1868
- }
1869
-}
1870
-
1871
-static void tdefl_optimize_huffman_table(tdefl_compressor *d, int table_num, int table_len, int code_size_limit, int static_table)
1872
-{
1873
- int i, j, l, num_codes[1 + TDEFL_MAX_SUPPORTED_HUFF_CODESIZE]; mz_uint next_code[TDEFL_MAX_SUPPORTED_HUFF_CODESIZE + 1]; MZ_CLEAR_OBJ(num_codes);
1874
- if (static_table)
1875
- {
1876
- for (i = 0; i < table_len; i++) num_codes[d->m_huff_code_sizes[table_num][i]]++;
1877
- }
1878
- else
1879
- {
1880
- tdefl_sym_freq syms0[TDEFL_MAX_HUFF_SYMBOLS], syms1[TDEFL_MAX_HUFF_SYMBOLS], *pSyms;
1881
- int num_used_syms = 0;
1882
- const mz_uint16 *pSym_count = &d->m_huff_count[table_num][0];
1883
- for (i = 0; i < table_len; i++) if (pSym_count[i]) { syms0[num_used_syms].m_key = (mz_uint16)pSym_count[i]; syms0[num_used_syms++].m_sym_index = (mz_uint16)i; }
1884
-
1885
- pSyms = tdefl_radix_sort_syms(num_used_syms, syms0, syms1); tdefl_calculate_minimum_redundancy(pSyms, num_used_syms);
1886
-
1887
- for (i = 0; i < num_used_syms; i++) num_codes[pSyms[i].m_key]++;
1888
-
1889
- tdefl_huffman_enforce_max_code_size(num_codes, num_used_syms, code_size_limit);
1890
-
1891
- MZ_CLEAR_OBJ(d->m_huff_code_sizes[table_num]); MZ_CLEAR_OBJ(d->m_huff_codes[table_num]);
1892
- for (i = 1, j = num_used_syms; i <= code_size_limit; i++)
1893
- for (l = num_codes[i]; l > 0; l--) d->m_huff_code_sizes[table_num][pSyms[--j].m_sym_index] = (mz_uint8)(i);
1894
- }
1895
-
1896
- next_code[1] = 0; for (j = 0, i = 2; i <= code_size_limit; i++) next_code[i] = j = ((j + num_codes[i - 1]) << 1);
1897
-
1898
- for (i = 0; i < table_len; i++)
1899
- {
1900
- mz_uint rev_code = 0, code, code_size; if ((code_size = d->m_huff_code_sizes[table_num][i]) == 0) continue;
1901
- code = next_code[code_size]++; for (l = code_size; l > 0; l--, code >>= 1) rev_code = (rev_code << 1) | (code & 1);
1902
- d->m_huff_codes[table_num][i] = (mz_uint16)rev_code;
1903
- }
1904
-}
1905
-
1906
-#define TDEFL_PUT_BITS(b, l) do { \
1907
- mz_uint bits = b; mz_uint len = l; MZ_ASSERT(bits <= ((1U << len) - 1U)); \
1908
- d->m_bit_buffer |= (bits << d->m_bits_in); d->m_bits_in += len; \
1909
- while (d->m_bits_in >= 8) { \
1910
- if (d->m_pOutput_buf < d->m_pOutput_buf_end) \
1911
- *d->m_pOutput_buf++ = (mz_uint8)(d->m_bit_buffer); \
1912
- d->m_bit_buffer >>= 8; \
1913
- d->m_bits_in -= 8; \
1914
- } \
1915
-} MZ_MACRO_END
1916
-
1917
-#define TDEFL_RLE_PREV_CODE_SIZE() { if (rle_repeat_count) { \
1918
- if (rle_repeat_count < 3) { \
1919
- d->m_huff_count[2][prev_code_size] = (mz_uint16)(d->m_huff_count[2][prev_code_size] + rle_repeat_count); \
1920
- while (rle_repeat_count--) packed_code_sizes[num_packed_code_sizes++] = prev_code_size; \
1921
- } else { \
1922
- d->m_huff_count[2][16] = (mz_uint16)(d->m_huff_count[2][16] + 1); packed_code_sizes[num_packed_code_sizes++] = 16; packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_repeat_count - 3); \
1923
-} rle_repeat_count = 0; } }
1924
-
1925
-#define TDEFL_RLE_ZERO_CODE_SIZE() { if (rle_z_count) { \
1926
- if (rle_z_count < 3) { \
1927
- d->m_huff_count[2][0] = (mz_uint16)(d->m_huff_count[2][0] + rle_z_count); while (rle_z_count--) packed_code_sizes[num_packed_code_sizes++] = 0; \
1928
- } else if (rle_z_count <= 10) { \
1929
- d->m_huff_count[2][17] = (mz_uint16)(d->m_huff_count[2][17] + 1); packed_code_sizes[num_packed_code_sizes++] = 17; packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_z_count - 3); \
1930
- } else { \
1931
- d->m_huff_count[2][18] = (mz_uint16)(d->m_huff_count[2][18] + 1); packed_code_sizes[num_packed_code_sizes++] = 18; packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_z_count - 11); \
1932
-} rle_z_count = 0; } }
1933
-
1934
-static mz_uint8 s_tdefl_packed_code_size_syms_swizzle[] = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 };
1935
-
1936
-static void tdefl_start_dynamic_block(tdefl_compressor *d)
1937
-{
1938
- int num_lit_codes, num_dist_codes, num_bit_lengths; mz_uint i, total_code_sizes_to_pack, num_packed_code_sizes, rle_z_count, rle_repeat_count, packed_code_sizes_index;
1939
- mz_uint8 code_sizes_to_pack[TDEFL_MAX_HUFF_SYMBOLS_0 + TDEFL_MAX_HUFF_SYMBOLS_1], packed_code_sizes[TDEFL_MAX_HUFF_SYMBOLS_0 + TDEFL_MAX_HUFF_SYMBOLS_1], prev_code_size = 0xFF;
1940
-
1941
- d->m_huff_count[0][256] = 1;
1942
-
1943
- tdefl_optimize_huffman_table(d, 0, TDEFL_MAX_HUFF_SYMBOLS_0, 15, MZ_FALSE);
1944
- tdefl_optimize_huffman_table(d, 1, TDEFL_MAX_HUFF_SYMBOLS_1, 15, MZ_FALSE);
1945
-
1946
- for (num_lit_codes = 286; num_lit_codes > 257; num_lit_codes--) if (d->m_huff_code_sizes[0][num_lit_codes - 1]) break;
1947
- for (num_dist_codes = 30; num_dist_codes > 1; num_dist_codes--) if (d->m_huff_code_sizes[1][num_dist_codes - 1]) break;
1948
-
1949
- memcpy(code_sizes_to_pack, &d->m_huff_code_sizes[0][0], num_lit_codes);
1950
- memcpy(code_sizes_to_pack + num_lit_codes, &d->m_huff_code_sizes[1][0], num_dist_codes);
1951
- total_code_sizes_to_pack = num_lit_codes + num_dist_codes; num_packed_code_sizes = 0; rle_z_count = 0; rle_repeat_count = 0;
1952
-
1953
- memset(&d->m_huff_count[2][0], 0, sizeof(d->m_huff_count[2][0]) * TDEFL_MAX_HUFF_SYMBOLS_2);
1954
- for (i = 0; i < total_code_sizes_to_pack; i++)
1955
- {
1956
- mz_uint8 code_size = code_sizes_to_pack[i];
1957
- if (!code_size)
1958
- {
1959
- TDEFL_RLE_PREV_CODE_SIZE();
1960
- if (++rle_z_count == 138) { TDEFL_RLE_ZERO_CODE_SIZE(); }
1961
- }
1962
- else
1963
- {
1964
- TDEFL_RLE_ZERO_CODE_SIZE();
1965
- if (code_size != prev_code_size)
1966
- {
1967
- TDEFL_RLE_PREV_CODE_SIZE();
1968
- d->m_huff_count[2][code_size] = (mz_uint16)(d->m_huff_count[2][code_size] + 1); packed_code_sizes[num_packed_code_sizes++] = code_size;
1969
- }
1970
- else if (++rle_repeat_count == 6)
1971
- {
1972
- TDEFL_RLE_PREV_CODE_SIZE();
1973
- }
1974
- }
1975
- prev_code_size = code_size;
1976
- }
1977
- if (rle_repeat_count) { TDEFL_RLE_PREV_CODE_SIZE(); } else { TDEFL_RLE_ZERO_CODE_SIZE(); }
1978
-
1979
- tdefl_optimize_huffman_table(d, 2, TDEFL_MAX_HUFF_SYMBOLS_2, 7, MZ_FALSE);
1980
-
1981
- TDEFL_PUT_BITS(2, 2);
1982
-
1983
- TDEFL_PUT_BITS(num_lit_codes - 257, 5);
1984
- TDEFL_PUT_BITS(num_dist_codes - 1, 5);
1985
-
1986
- for (num_bit_lengths = 18; num_bit_lengths >= 0; num_bit_lengths--) if (d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[num_bit_lengths]]) break;
1987
- num_bit_lengths = MZ_MAX(4, (num_bit_lengths + 1)); TDEFL_PUT_BITS(num_bit_lengths - 4, 4);
1988
- for (i = 0; (int)i < num_bit_lengths; i++) TDEFL_PUT_BITS(d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[i]], 3);
1989
-
1990
- for (packed_code_sizes_index = 0; packed_code_sizes_index < num_packed_code_sizes; )
1991
- {
1992
- mz_uint code = packed_code_sizes[packed_code_sizes_index++]; MZ_ASSERT(code < TDEFL_MAX_HUFF_SYMBOLS_2);
1993
- TDEFL_PUT_BITS(d->m_huff_codes[2][code], d->m_huff_code_sizes[2][code]);
1994
- if (code >= 16) TDEFL_PUT_BITS(packed_code_sizes[packed_code_sizes_index++], "\02\03\07"[code - 16]);
1995
- }
1996
-}
1997
-
1998
-static void tdefl_start_static_block(tdefl_compressor *d)
1999
-{
2000
- mz_uint i;
2001
- mz_uint8 *p = &d->m_huff_code_sizes[0][0];
2002
-
2003
- for (i = 0; i <= 143; ++i) *p++ = 8;
2004
- for ( ; i <= 255; ++i) *p++ = 9;
2005
- for ( ; i <= 279; ++i) *p++ = 7;
2006
- for ( ; i <= 287; ++i) *p++ = 8;
2007
-
2008
- memset(d->m_huff_code_sizes[1], 5, 32);
2009
-
2010
- tdefl_optimize_huffman_table(d, 0, 288, 15, MZ_TRUE);
2011
- tdefl_optimize_huffman_table(d, 1, 32, 15, MZ_TRUE);
2012
-
2013
- TDEFL_PUT_BITS(1, 2);
2014
-}
2015
-
2016
-static const mz_uint mz_bitmasks[17] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };
2017
-
2018
-#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN && MINIZ_HAS_64BIT_REGISTERS
2019
-static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d)
2020
-{
2021
- mz_uint flags;
2022
- mz_uint8 *pLZ_codes;
2023
- mz_uint8 *pOutput_buf = d->m_pOutput_buf;
2024
- mz_uint8 *pLZ_code_buf_end = d->m_pLZ_code_buf;
2025
- mz_uint64 bit_buffer = d->m_bit_buffer;
2026
- mz_uint bits_in = d->m_bits_in;
2027
-
2028
-#define TDEFL_PUT_BITS_FAST(b, l) { bit_buffer |= (((mz_uint64)(b)) << bits_in); bits_in += (l); }
2029
-
2030
- flags = 1;
2031
- for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < pLZ_code_buf_end; flags >>= 1)
2032
- {
2033
- if (flags == 1)
2034
- flags = *pLZ_codes++ | 0x100;
2035
-
2036
- if (flags & 1)
2037
- {
2038
- mz_uint s0, s1, n0, n1, sym, num_extra_bits;
2039
- mz_uint match_len = pLZ_codes[0], match_dist = *(const mz_uint16 *)(pLZ_codes + 1); pLZ_codes += 3;
2040
-
2041
- MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
2042
- TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][s_tdefl_len_sym[match_len]], d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
2043
- TDEFL_PUT_BITS_FAST(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], s_tdefl_len_extra[match_len]);
2044
-
2045
- // This sequence coaxes MSVC into using cmov's vs. jmp's.
2046
- s0 = s_tdefl_small_dist_sym[match_dist & 511];
2047
- n0 = s_tdefl_small_dist_extra[match_dist & 511];
2048
- s1 = s_tdefl_large_dist_sym[match_dist >> 8];
2049
- n1 = s_tdefl_large_dist_extra[match_dist >> 8];
2050
- sym = (match_dist < 512) ? s0 : s1;
2051
- num_extra_bits = (match_dist < 512) ? n0 : n1;
2052
-
2053
- MZ_ASSERT(d->m_huff_code_sizes[1][sym]);
2054
- TDEFL_PUT_BITS_FAST(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]);
2055
- TDEFL_PUT_BITS_FAST(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits);
2056
- }
2057
- else
2058
- {
2059
- mz_uint lit = *pLZ_codes++;
2060
- MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
2061
- TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
2062
-
2063
- if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end))
2064
- {
2065
- flags >>= 1;
2066
- lit = *pLZ_codes++;
2067
- MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
2068
- TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
2069
-
2070
- if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end))
2071
- {
2072
- flags >>= 1;
2073
- lit = *pLZ_codes++;
2074
- MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
2075
- TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
2076
- }
2077
- }
2078
- }
2079
-
2080
- if (pOutput_buf >= d->m_pOutput_buf_end)
2081
- return MZ_FALSE;
2082
-
2083
- *(mz_uint64*)pOutput_buf = bit_buffer;
2084
- pOutput_buf += (bits_in >> 3);
2085
- bit_buffer >>= (bits_in & ~7);
2086
- bits_in &= 7;
2087
- }
2088
-
2089
-#undef TDEFL_PUT_BITS_FAST
2090
-
2091
- d->m_pOutput_buf = pOutput_buf;
2092
- d->m_bits_in = 0;
2093
- d->m_bit_buffer = 0;
2094
-
2095
- while (bits_in)
2096
- {
2097
- mz_uint32 n = MZ_MIN(bits_in, 16);
2098
- TDEFL_PUT_BITS((mz_uint)bit_buffer & mz_bitmasks[n], n);
2099
- bit_buffer >>= n;
2100
- bits_in -= n;
2101
- }
2102
-
2103
- TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]);
2104
-
2105
- return (d->m_pOutput_buf < d->m_pOutput_buf_end);
2106
-}
2107
-#else
2108
-static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d)
2109
-{
2110
- mz_uint flags;
2111
- mz_uint8 *pLZ_codes;
2112
-
2113
- flags = 1;
2114
- for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < d->m_pLZ_code_buf; flags >>= 1)
2115
- {
2116
- if (flags == 1)
2117
- flags = *pLZ_codes++ | 0x100;
2118
- if (flags & 1)
2119
- {
2120
- mz_uint sym, num_extra_bits;
2121
- mz_uint match_len = pLZ_codes[0], match_dist = (pLZ_codes[1] | (pLZ_codes[2] << 8)); pLZ_codes += 3;
2122
-
2123
- MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
2124
- TDEFL_PUT_BITS(d->m_huff_codes[0][s_tdefl_len_sym[match_len]], d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
2125
- TDEFL_PUT_BITS(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], s_tdefl_len_extra[match_len]);
2126
-
2127
- if (match_dist < 512)
2128
- {
2129
- sym = s_tdefl_small_dist_sym[match_dist]; num_extra_bits = s_tdefl_small_dist_extra[match_dist];
2130
- }
2131
- else
2132
- {
2133
- sym = s_tdefl_large_dist_sym[match_dist >> 8]; num_extra_bits = s_tdefl_large_dist_extra[match_dist >> 8];
2134
- }
2135
- MZ_ASSERT(d->m_huff_code_sizes[1][sym]);
2136
- TDEFL_PUT_BITS(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]);
2137
- TDEFL_PUT_BITS(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits);
2138
- }
2139
- else
2140
- {
2141
- mz_uint lit = *pLZ_codes++;
2142
- MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
2143
- TDEFL_PUT_BITS(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
2144
- }
2145
- }
2146
-
2147
- TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]);
2148
-
2149
- return (d->m_pOutput_buf < d->m_pOutput_buf_end);
2150
-}
2151
-#endif // MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN && MINIZ_HAS_64BIT_REGISTERS
2152
-
2153
-static mz_bool tdefl_compress_block(tdefl_compressor *d, mz_bool static_block)
2154
-{
2155
- if (static_block)
2156
- tdefl_start_static_block(d);
2157
- else
2158
- tdefl_start_dynamic_block(d);
2159
- return tdefl_compress_lz_codes(d);
2160
-}
2161
-
2162
-static int tdefl_flush_block(tdefl_compressor *d, int flush)
2163
-{
2164
- mz_uint saved_bit_buf, saved_bits_in;
2165
- mz_uint8 *pSaved_output_buf;
2166
- mz_bool comp_block_succeeded = MZ_FALSE;
2167
- int n, use_raw_block = ((d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS) != 0) && (d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size;
2168
- mz_uint8 *pOutput_buf_start = ((d->m_pPut_buf_func == NULL) && ((*d->m_pOut_buf_size - d->m_out_buf_ofs) >= TDEFL_OUT_BUF_SIZE)) ? ((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs) : d->m_output_buf;
2169
-
2170
- d->m_pOutput_buf = pOutput_buf_start;
2171
- d->m_pOutput_buf_end = d->m_pOutput_buf + TDEFL_OUT_BUF_SIZE - 16;
2172
-
2173
- MZ_ASSERT(!d->m_output_flush_remaining);
2174
- d->m_output_flush_ofs = 0;
2175
- d->m_output_flush_remaining = 0;
2176
-
2177
- *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> d->m_num_flags_left);
2178
- d->m_pLZ_code_buf -= (d->m_num_flags_left == 8);
2179
-
2180
- if ((d->m_flags & TDEFL_WRITE_ZLIB_HEADER) && (!d->m_block_index))
2181
- {
2182
- TDEFL_PUT_BITS(0x78, 8); TDEFL_PUT_BITS(0x01, 8);
2183
- }
2184
-
2185
- TDEFL_PUT_BITS(flush == TDEFL_FINISH, 1);
2186
-
2187
- pSaved_output_buf = d->m_pOutput_buf; saved_bit_buf = d->m_bit_buffer; saved_bits_in = d->m_bits_in;
2188
-
2189
- if (!use_raw_block)
2190
- comp_block_succeeded = tdefl_compress_block(d, (d->m_flags & TDEFL_FORCE_ALL_STATIC_BLOCKS) || (d->m_total_lz_bytes < 48));
2191
-
2192
- // If the block gets expanded, forget the current contents of the output buffer and send a raw block instead.
2193
- if ( ((use_raw_block) || ((d->m_total_lz_bytes) && ((d->m_pOutput_buf - pSaved_output_buf + 1U) >= d->m_total_lz_bytes))) &&
2194
- ((d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size) )
2195
- {
2196
- mz_uint i; d->m_pOutput_buf = pSaved_output_buf; d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in;
2197
- TDEFL_PUT_BITS(0, 2);
2198
- if (d->m_bits_in) { TDEFL_PUT_BITS(0, 8 - d->m_bits_in); }
2199
- for (i = 2; i; --i, d->m_total_lz_bytes ^= 0xFFFF)
2200
- {
2201
- TDEFL_PUT_BITS(d->m_total_lz_bytes & 0xFFFF, 16);
2202
- }
2203
- for (i = 0; i < d->m_total_lz_bytes; ++i)
2204
- {
2205
- TDEFL_PUT_BITS(d->m_dict[(d->m_lz_code_buf_dict_pos + i) & TDEFL_LZ_DICT_SIZE_MASK], 8);
2206
- }
2207
- }
2208
- // Check for the extremely unlikely (if not impossible) case of the compressed block not fitting into the output buffer when using dynamic codes.
2209
- else if (!comp_block_succeeded)
2210
- {
2211
- d->m_pOutput_buf = pSaved_output_buf; d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in;
2212
- tdefl_compress_block(d, MZ_TRUE);
2213
- }
2214
-
2215
- if (flush)
2216
- {
2217
- if (flush == TDEFL_FINISH)
2218
- {
2219
- if (d->m_bits_in) { TDEFL_PUT_BITS(0, 8 - d->m_bits_in); }
2220
- if (d->m_flags & TDEFL_WRITE_ZLIB_HEADER) { mz_uint i, a = d->m_adler32; for (i = 0; i < 4; i++) { TDEFL_PUT_BITS((a >> 24) & 0xFF, 8); a <<= 8; } }
2221
- }
2222
- else
2223
- {
2224
- mz_uint i, z = 0; TDEFL_PUT_BITS(0, 3); if (d->m_bits_in) { TDEFL_PUT_BITS(0, 8 - d->m_bits_in); } for (i = 2; i; --i, z ^= 0xFFFF) { TDEFL_PUT_BITS(z & 0xFFFF, 16); }
2225
- }
2226
- }
2227
-
2228
- MZ_ASSERT(d->m_pOutput_buf < d->m_pOutput_buf_end);
2229
-
2230
- memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0);
2231
- memset(&d->m_huff_count[1][0], 0, sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1);
2232
-
2233
- d->m_pLZ_code_buf = d->m_lz_code_buf + 1; d->m_pLZ_flags = d->m_lz_code_buf; d->m_num_flags_left = 8; d->m_lz_code_buf_dict_pos += d->m_total_lz_bytes; d->m_total_lz_bytes = 0; d->m_block_index++;
2234
-
2235
- if ((n = (int)(d->m_pOutput_buf - pOutput_buf_start)) != 0)
2236
- {
2237
- if (d->m_pPut_buf_func)
2238
- {
2239
- *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf;
2240
- if (!(*d->m_pPut_buf_func)(d->m_output_buf, n, d->m_pPut_buf_user))
2241
- return (d->m_prev_return_status = TDEFL_STATUS_PUT_BUF_FAILED);
2242
- }
2243
- else if (pOutput_buf_start == d->m_output_buf)
2244
- {
2245
- int bytes_to_copy = (int)MZ_MIN((size_t)n, (size_t)(*d->m_pOut_buf_size - d->m_out_buf_ofs));
2246
- memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf, bytes_to_copy);
2247
- d->m_out_buf_ofs += bytes_to_copy;
2248
- if ((n -= bytes_to_copy) != 0)
2249
- {
2250
- d->m_output_flush_ofs = bytes_to_copy;
2251
- d->m_output_flush_remaining = n;
2252
- }
2253
- }
2254
- else
2255
- {
2256
- d->m_out_buf_ofs += n;
2257
- }
2258
- }
2259
-
2260
- return d->m_output_flush_remaining;
2261
-}
2262
-
2263
-#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES
2264
-#define TDEFL_READ_UNALIGNED_WORD(p) *(const mz_uint16*)(p)
2265
-static MZ_FORCEINLINE void tdefl_find_match(tdefl_compressor *d, mz_uint lookahead_pos, mz_uint max_dist, mz_uint max_match_len, mz_uint *pMatch_dist, mz_uint *pMatch_len)
2266
-{
2267
- mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK, match_len = *pMatch_len, probe_pos = pos, next_probe_pos, probe_len;
2268
- mz_uint num_probes_left = d->m_max_probes[match_len >= 32];
2269
- const mz_uint16 *s = (const mz_uint16*)(d->m_dict + pos), *p, *q;
2270
- mz_uint16 c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]), s01 = TDEFL_READ_UNALIGNED_WORD(s);
2271
- MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN); if (max_match_len <= match_len) return;
2272
- for ( ; ; )
2273
- {
2274
- for ( ; ; )
2275
- {
2276
- if (--num_probes_left == 0) return;
2277
- #define TDEFL_PROBE \
2278
- next_probe_pos = d->m_next[probe_pos]; \
2279
- if ((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) return; \
2280
- probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK; \
2281
- if (TDEFL_READ_UNALIGNED_WORD(&d->m_dict[probe_pos + match_len - 1]) == c01) break;
2282
- TDEFL_PROBE; TDEFL_PROBE; TDEFL_PROBE;
2283
- }
2284
- if (!dist) break; q = (const mz_uint16*)(d->m_dict + probe_pos); if (TDEFL_READ_UNALIGNED_WORD(q) != s01) continue; p = s; probe_len = 32;
2285
- do { } while ( (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) &&
2286
- (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (--probe_len > 0) );
2287
- if (!probe_len)
2288
- {
2289
- *pMatch_dist = dist; *pMatch_len = MZ_MIN(max_match_len, TDEFL_MAX_MATCH_LEN); break;
2290
- }
2291
- else if ((probe_len = ((mz_uint)(p - s) * 2) + (mz_uint)(*(const mz_uint8*)p == *(const mz_uint8*)q)) > match_len)
2292
- {
2293
- *pMatch_dist = dist; if ((*pMatch_len = match_len = MZ_MIN(max_match_len, probe_len)) == max_match_len) break;
2294
- c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]);
2295
- }
2296
- }
2297
-}
2298
-#else
2299
-static MZ_FORCEINLINE void tdefl_find_match(tdefl_compressor *d, mz_uint lookahead_pos, mz_uint max_dist, mz_uint max_match_len, mz_uint *pMatch_dist, mz_uint *pMatch_len)
2300
-{
2301
- mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK, match_len = *pMatch_len, probe_pos = pos, next_probe_pos, probe_len;
2302
- mz_uint num_probes_left = d->m_max_probes[match_len >= 32];
2303
- const mz_uint8 *s = d->m_dict + pos, *p, *q;
2304
- mz_uint8 c0 = d->m_dict[pos + match_len], c1 = d->m_dict[pos + match_len - 1];
2305
- MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN); if (max_match_len <= match_len) return;
2306
- for ( ; ; )
2307
- {
2308
- for ( ; ; )
2309
- {
2310
- if (--num_probes_left == 0) return;
2311
- #define TDEFL_PROBE \
2312
- next_probe_pos = d->m_next[probe_pos]; \
2313
- if ((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) return; \
2314
- probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK; \
2315
- if ((d->m_dict[probe_pos + match_len] == c0) && (d->m_dict[probe_pos + match_len - 1] == c1)) break;
2316
- TDEFL_PROBE; TDEFL_PROBE; TDEFL_PROBE;
2317
- }
2318
- if (!dist) break; p = s; q = d->m_dict + probe_pos; for (probe_len = 0; probe_len < max_match_len; probe_len++) if (*p++ != *q++) break;
2319
- if (probe_len > match_len)
2320
- {
2321
- *pMatch_dist = dist; if ((*pMatch_len = match_len = probe_len) == max_match_len) return;
2322
- c0 = d->m_dict[pos + match_len]; c1 = d->m_dict[pos + match_len - 1];
2323
- }
2324
- }
2325
-}
2326
-#endif // #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES
2327
-
2328
-#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
2329
-static mz_bool tdefl_compress_fast(tdefl_compressor *d)
2330
-{
2331
- // Faster, minimally featured LZRW1-style match+parse loop with better register utilization. Intended for applications where raw throughput is valued more highly than ratio.
2332
- mz_uint lookahead_pos = d->m_lookahead_pos, lookahead_size = d->m_lookahead_size, dict_size = d->m_dict_size, total_lz_bytes = d->m_total_lz_bytes, num_flags_left = d->m_num_flags_left;
2333
- mz_uint8 *pLZ_code_buf = d->m_pLZ_code_buf, *pLZ_flags = d->m_pLZ_flags;
2334
- mz_uint cur_pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK;
2335
-
2336
- while ((d->m_src_buf_left) || ((d->m_flush) && (lookahead_size)))
2337
- {
2338
- const mz_uint TDEFL_COMP_FAST_LOOKAHEAD_SIZE = 4096;
2339
- mz_uint dst_pos = (lookahead_pos + lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK;
2340
- mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(d->m_src_buf_left, TDEFL_COMP_FAST_LOOKAHEAD_SIZE - lookahead_size);
2341
- d->m_src_buf_left -= num_bytes_to_process;
2342
- lookahead_size += num_bytes_to_process;
2343
-
2344
- while (num_bytes_to_process)
2345
- {
2346
- mz_uint32 n = MZ_MIN(TDEFL_LZ_DICT_SIZE - dst_pos, num_bytes_to_process);
2347
- memcpy(d->m_dict + dst_pos, d->m_pSrc, n);
2348
- if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1))
2349
- memcpy(d->m_dict + TDEFL_LZ_DICT_SIZE + dst_pos, d->m_pSrc, MZ_MIN(n, (TDEFL_MAX_MATCH_LEN - 1) - dst_pos));
2350
- d->m_pSrc += n;
2351
- dst_pos = (dst_pos + n) & TDEFL_LZ_DICT_SIZE_MASK;
2352
- num_bytes_to_process -= n;
2353
- }
2354
-
2355
- dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - lookahead_size, dict_size);
2356
- if ((!d->m_flush) && (lookahead_size < TDEFL_COMP_FAST_LOOKAHEAD_SIZE)) break;
2357
-
2358
- while (lookahead_size >= 4)
2359
- {
2360
- mz_uint cur_match_dist, cur_match_len = 1;
2361
- mz_uint8 *pCur_dict = d->m_dict + cur_pos;
2362
- mz_uint first_trigram = (*(const mz_uint32 *)pCur_dict) & 0xFFFFFF;
2363
- mz_uint hash = (first_trigram ^ (first_trigram >> (24 - (TDEFL_LZ_HASH_BITS - 8)))) & TDEFL_LEVEL1_HASH_SIZE_MASK;
2364
- mz_uint probe_pos = d->m_hash[hash];
2365
- d->m_hash[hash] = (mz_uint16)lookahead_pos;
2366
-
2367
- if (((cur_match_dist = (mz_uint16)(lookahead_pos - probe_pos)) <= dict_size) && ((*(const mz_uint32 *)(d->m_dict + (probe_pos &= TDEFL_LZ_DICT_SIZE_MASK)) & 0xFFFFFF) == first_trigram))
2368
- {
2369
- const mz_uint16 *p = (const mz_uint16 *)pCur_dict;
2370
- const mz_uint16 *q = (const mz_uint16 *)(d->m_dict + probe_pos);
2371
- mz_uint32 probe_len = 32;
2372
- do { } while ( (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) &&
2373
- (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (--probe_len > 0) );
2374
- cur_match_len = ((mz_uint)(p - (const mz_uint16 *)pCur_dict) * 2) + (mz_uint)(*(const mz_uint8 *)p == *(const mz_uint8 *)q);
2375
- if (!probe_len)
2376
- cur_match_len = cur_match_dist ? TDEFL_MAX_MATCH_LEN : 0;
2377
-
2378
- if ((cur_match_len < TDEFL_MIN_MATCH_LEN) || ((cur_match_len == TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 8U*1024U)))
2379
- {
2380
- cur_match_len = 1;
2381
- *pLZ_code_buf++ = (mz_uint8)first_trigram;
2382
- *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
2383
- d->m_huff_count[0][(mz_uint8)first_trigram]++;
2384
- }
2385
- else
2386
- {
2387
- mz_uint32 s0, s1;
2388
- cur_match_len = MZ_MIN(cur_match_len, lookahead_size);
2389
-
2390
- MZ_ASSERT((cur_match_len >= TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 1) && (cur_match_dist <= TDEFL_LZ_DICT_SIZE));
2391
-
2392
- cur_match_dist--;
2393
-
2394
- pLZ_code_buf[0] = (mz_uint8)(cur_match_len - TDEFL_MIN_MATCH_LEN);
2395
- *(mz_uint16 *)(&pLZ_code_buf[1]) = (mz_uint16)cur_match_dist;
2396
- pLZ_code_buf += 3;
2397
- *pLZ_flags = (mz_uint8)((*pLZ_flags >> 1) | 0x80);
2398
-
2399
- s0 = s_tdefl_small_dist_sym[cur_match_dist & 511];
2400
- s1 = s_tdefl_large_dist_sym[cur_match_dist >> 8];
2401
- d->m_huff_count[1][(cur_match_dist < 512) ? s0 : s1]++;
2402
-
2403
- d->m_huff_count[0][s_tdefl_len_sym[cur_match_len - TDEFL_MIN_MATCH_LEN]]++;
2404
- }
2405
- }
2406
- else
2407
- {
2408
- *pLZ_code_buf++ = (mz_uint8)first_trigram;
2409
- *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
2410
- d->m_huff_count[0][(mz_uint8)first_trigram]++;
2411
- }
2412
-
2413
- if (--num_flags_left == 0) { num_flags_left = 8; pLZ_flags = pLZ_code_buf++; }
2414
-
2415
- total_lz_bytes += cur_match_len;
2416
- lookahead_pos += cur_match_len;
2417
- dict_size = MZ_MIN(dict_size + cur_match_len, TDEFL_LZ_DICT_SIZE);
2418
- cur_pos = (cur_pos + cur_match_len) & TDEFL_LZ_DICT_SIZE_MASK;
2419
- MZ_ASSERT(lookahead_size >= cur_match_len);
2420
- lookahead_size -= cur_match_len;
2421
-
2422
- if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8])
2423
- {
2424
- int n;
2425
- d->m_lookahead_pos = lookahead_pos; d->m_lookahead_size = lookahead_size; d->m_dict_size = dict_size;
2426
- d->m_total_lz_bytes = total_lz_bytes; d->m_pLZ_code_buf = pLZ_code_buf; d->m_pLZ_flags = pLZ_flags; d->m_num_flags_left = num_flags_left;
2427
- if ((n = tdefl_flush_block(d, 0)) != 0)
2428
- return (n < 0) ? MZ_FALSE : MZ_TRUE;
2429
- total_lz_bytes = d->m_total_lz_bytes; pLZ_code_buf = d->m_pLZ_code_buf; pLZ_flags = d->m_pLZ_flags; num_flags_left = d->m_num_flags_left;
2430
- }
2431
- }
2432
-
2433
- while (lookahead_size)
2434
- {
2435
- mz_uint8 lit = d->m_dict[cur_pos];
2436
-
2437
- total_lz_bytes++;
2438
- *pLZ_code_buf++ = lit;
2439
- *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
2440
- if (--num_flags_left == 0) { num_flags_left = 8; pLZ_flags = pLZ_code_buf++; }
2441
-
2442
- d->m_huff_count[0][lit]++;
2443
-
2444
- lookahead_pos++;
2445
- dict_size = MZ_MIN(dict_size + 1, TDEFL_LZ_DICT_SIZE);
2446
- cur_pos = (cur_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK;
2447
- lookahead_size--;
2448
-
2449
- if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8])
2450
- {
2451
- int n;
2452
- d->m_lookahead_pos = lookahead_pos; d->m_lookahead_size = lookahead_size; d->m_dict_size = dict_size;
2453
- d->m_total_lz_bytes = total_lz_bytes; d->m_pLZ_code_buf = pLZ_code_buf; d->m_pLZ_flags = pLZ_flags; d->m_num_flags_left = num_flags_left;
2454
- if ((n = tdefl_flush_block(d, 0)) != 0)
2455
- return (n < 0) ? MZ_FALSE : MZ_TRUE;
2456
- total_lz_bytes = d->m_total_lz_bytes; pLZ_code_buf = d->m_pLZ_code_buf; pLZ_flags = d->m_pLZ_flags; num_flags_left = d->m_num_flags_left;
2457
- }
2458
- }
2459
- }
2460
-
2461
- d->m_lookahead_pos = lookahead_pos; d->m_lookahead_size = lookahead_size; d->m_dict_size = dict_size;
2462
- d->m_total_lz_bytes = total_lz_bytes; d->m_pLZ_code_buf = pLZ_code_buf; d->m_pLZ_flags = pLZ_flags; d->m_num_flags_left = num_flags_left;
2463
- return MZ_TRUE;
2464
-}
2465
-#endif // MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
2466
-
2467
-static MZ_FORCEINLINE void tdefl_record_literal(tdefl_compressor *d, mz_uint8 lit)
2468
-{
2469
- d->m_total_lz_bytes++;
2470
- *d->m_pLZ_code_buf++ = lit;
2471
- *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> 1); if (--d->m_num_flags_left == 0) { d->m_num_flags_left = 8; d->m_pLZ_flags = d->m_pLZ_code_buf++; }
2472
- d->m_huff_count[0][lit]++;
2473
-}
2474
-
2475
-static MZ_FORCEINLINE void tdefl_record_match(tdefl_compressor *d, mz_uint match_len, mz_uint match_dist)
2476
-{
2477
- mz_uint32 s0, s1;
2478
-
2479
- MZ_ASSERT((match_len >= TDEFL_MIN_MATCH_LEN) && (match_dist >= 1) && (match_dist <= TDEFL_LZ_DICT_SIZE));
2480
-
2481
- d->m_total_lz_bytes += match_len;
2482
-
2483
- d->m_pLZ_code_buf[0] = (mz_uint8)(match_len - TDEFL_MIN_MATCH_LEN);
2484
-
2485
- match_dist -= 1;
2486
- d->m_pLZ_code_buf[1] = (mz_uint8)(match_dist & 0xFF);
2487
- d->m_pLZ_code_buf[2] = (mz_uint8)(match_dist >> 8); d->m_pLZ_code_buf += 3;
2488
-
2489
- *d->m_pLZ_flags = (mz_uint8)((*d->m_pLZ_flags >> 1) | 0x80); if (--d->m_num_flags_left == 0) { d->m_num_flags_left = 8; d->m_pLZ_flags = d->m_pLZ_code_buf++; }
2490
-
2491
- s0 = s_tdefl_small_dist_sym[match_dist & 511]; s1 = s_tdefl_large_dist_sym[(match_dist >> 8) & 127];
2492
- d->m_huff_count[1][(match_dist < 512) ? s0 : s1]++;
2493
-
2494
- if (match_len >= TDEFL_MIN_MATCH_LEN) d->m_huff_count[0][s_tdefl_len_sym[match_len - TDEFL_MIN_MATCH_LEN]]++;
2495
-}
2496
-
2497
-static mz_bool tdefl_compress_normal(tdefl_compressor *d)
2498
-{
2499
- const mz_uint8 *pSrc = d->m_pSrc; size_t src_buf_left = d->m_src_buf_left;
2500
- tdefl_flush flush = d->m_flush;
2501
-
2502
- while ((src_buf_left) || ((flush) && (d->m_lookahead_size)))
2503
- {
2504
- mz_uint len_to_move, cur_match_dist, cur_match_len, cur_pos;
2505
- // Update dictionary and hash chains. Keeps the lookahead size equal to TDEFL_MAX_MATCH_LEN.
2506
- if ((d->m_lookahead_size + d->m_dict_size) >= (TDEFL_MIN_MATCH_LEN - 1))
2507
- {
2508
- mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK, ins_pos = d->m_lookahead_pos + d->m_lookahead_size - 2;
2509
- mz_uint hash = (d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] << TDEFL_LZ_HASH_SHIFT) ^ d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK];
2510
- mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(src_buf_left, TDEFL_MAX_MATCH_LEN - d->m_lookahead_size);
2511
- const mz_uint8 *pSrc_end = pSrc + num_bytes_to_process;
2512
- src_buf_left -= num_bytes_to_process;
2513
- d->m_lookahead_size += num_bytes_to_process;
2514
- while (pSrc != pSrc_end)
2515
- {
2516
- mz_uint8 c = *pSrc++; d->m_dict[dst_pos] = c; if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1)) d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c;
2517
- hash = ((hash << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1);
2518
- d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash]; d->m_hash[hash] = (mz_uint16)(ins_pos);
2519
- dst_pos = (dst_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK; ins_pos++;
2520
- }
2521
- }
2522
- else
2523
- {
2524
- while ((src_buf_left) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN))
2525
- {
2526
- mz_uint8 c = *pSrc++;
2527
- mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK;
2528
- src_buf_left--;
2529
- d->m_dict[dst_pos] = c;
2530
- if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1))
2531
- d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c;
2532
- if ((++d->m_lookahead_size + d->m_dict_size) >= TDEFL_MIN_MATCH_LEN)
2533
- {
2534
- mz_uint ins_pos = d->m_lookahead_pos + (d->m_lookahead_size - 1) - 2;
2535
- mz_uint hash = ((d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] << (TDEFL_LZ_HASH_SHIFT * 2)) ^ (d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK] << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1);
2536
- d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash]; d->m_hash[hash] = (mz_uint16)(ins_pos);
2537
- }
2538
- }
2539
- }
2540
- d->m_dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - d->m_lookahead_size, d->m_dict_size);
2541
- if ((!flush) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN))
2542
- break;
2543
-
2544
- // Simple lazy/greedy parsing state machine.
2545
- len_to_move = 1; cur_match_dist = 0; cur_match_len = d->m_saved_match_len ? d->m_saved_match_len : (TDEFL_MIN_MATCH_LEN - 1); cur_pos = d->m_lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK;
2546
- if (d->m_flags & (TDEFL_RLE_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS))
2547
- {
2548
- if ((d->m_dict_size) && (!(d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS)))
2549
- {
2550
- mz_uint8 c = d->m_dict[(cur_pos - 1) & TDEFL_LZ_DICT_SIZE_MASK];
2551
- cur_match_len = 0; while (cur_match_len < d->m_lookahead_size) { if (d->m_dict[cur_pos + cur_match_len] != c) break; cur_match_len++; }
2552
- if (cur_match_len < TDEFL_MIN_MATCH_LEN) cur_match_len = 0; else cur_match_dist = 1;
2553
- }
2554
- }
2555
- else
2556
- {
2557
- tdefl_find_match(d, d->m_lookahead_pos, d->m_dict_size, d->m_lookahead_size, &cur_match_dist, &cur_match_len);
2558
- }
2559
- if (((cur_match_len == TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 8U*1024U)) || (cur_pos == cur_match_dist) || ((d->m_flags & TDEFL_FILTER_MATCHES) && (cur_match_len <= 5)))
2560
- {
2561
- cur_match_dist = cur_match_len = 0;
2562
- }
2563
- if (d->m_saved_match_len)
2564
- {
2565
- if (cur_match_len > d->m_saved_match_len)
2566
- {
2567
- tdefl_record_literal(d, (mz_uint8)d->m_saved_lit);
2568
- if (cur_match_len >= 128)
2569
- {
2570
- tdefl_record_match(d, cur_match_len, cur_match_dist);
2571
- d->m_saved_match_len = 0; len_to_move = cur_match_len;
2572
- }
2573
- else
2574
- {
2575
- d->m_saved_lit = d->m_dict[cur_pos]; d->m_saved_match_dist = cur_match_dist; d->m_saved_match_len = cur_match_len;
2576
- }
2577
- }
2578
- else
2579
- {
2580
- tdefl_record_match(d, d->m_saved_match_len, d->m_saved_match_dist);
2581
- len_to_move = d->m_saved_match_len - 1; d->m_saved_match_len = 0;
2582
- }
2583
- }
2584
- else if (!cur_match_dist)
2585
- tdefl_record_literal(d, d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)]);
2586
- else if ((d->m_greedy_parsing) || (d->m_flags & TDEFL_RLE_MATCHES) || (cur_match_len >= 128))
2587
- {
2588
- tdefl_record_match(d, cur_match_len, cur_match_dist);
2589
- len_to_move = cur_match_len;
2590
- }
2591
- else
2592
- {
2593
- d->m_saved_lit = d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)]; d->m_saved_match_dist = cur_match_dist; d->m_saved_match_len = cur_match_len;
2594
- }
2595
- // Move the lookahead forward by len_to_move bytes.
2596
- d->m_lookahead_pos += len_to_move;
2597
- MZ_ASSERT(d->m_lookahead_size >= len_to_move);
2598
- d->m_lookahead_size -= len_to_move;
2599
- d->m_dict_size = MZ_MIN(d->m_dict_size + len_to_move, TDEFL_LZ_DICT_SIZE);
2600
- // Check if it's time to flush the current LZ codes to the internal output buffer.
2601
- if ( (d->m_pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) ||
2602
- ( (d->m_total_lz_bytes > 31*1024) && (((((mz_uint)(d->m_pLZ_code_buf - d->m_lz_code_buf) * 115) >> 7) >= d->m_total_lz_bytes) || (d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS))) )
2603
- {
2604
- int n;
2605
- d->m_pSrc = pSrc; d->m_src_buf_left = src_buf_left;
2606
- if ((n = tdefl_flush_block(d, 0)) != 0)
2607
- return (n < 0) ? MZ_FALSE : MZ_TRUE;
2608
- }
2609
- }
2610
-
2611
- d->m_pSrc = pSrc; d->m_src_buf_left = src_buf_left;
2612
- return MZ_TRUE;
2613
-}
2614
-
2615
-static tdefl_status tdefl_flush_output_buffer(tdefl_compressor *d)
2616
-{
2617
- if (d->m_pIn_buf_size)
2618
- {
2619
- *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf;
2620
- }
2621
-
2622
- if (d->m_pOut_buf_size)
2623
- {
2624
- size_t n = MZ_MIN(*d->m_pOut_buf_size - d->m_out_buf_ofs, d->m_output_flush_remaining);
2625
- memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf + d->m_output_flush_ofs, n);
2626
- d->m_output_flush_ofs += (mz_uint)n;
2627
- d->m_output_flush_remaining -= (mz_uint)n;
2628
- d->m_out_buf_ofs += n;
2629
-
2630
- *d->m_pOut_buf_size = d->m_out_buf_ofs;
2631
- }
2632
-
2633
- return (d->m_finished && !d->m_output_flush_remaining) ? TDEFL_STATUS_DONE : TDEFL_STATUS_OKAY;
2634
-}
2635
-
2636
-tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf, size_t *pIn_buf_size, void *pOut_buf, size_t *pOut_buf_size, tdefl_flush flush)
2637
-{
2638
- if (!d)
2639
- {
2640
- if (pIn_buf_size) *pIn_buf_size = 0;
2641
- if (pOut_buf_size) *pOut_buf_size = 0;
2642
- return TDEFL_STATUS_BAD_PARAM;
2643
- }
2644
-
2645
- d->m_pIn_buf = pIn_buf; d->m_pIn_buf_size = pIn_buf_size;
2646
- d->m_pOut_buf = pOut_buf; d->m_pOut_buf_size = pOut_buf_size;
2647
- d->m_pSrc = (const mz_uint8 *)(pIn_buf); d->m_src_buf_left = pIn_buf_size ? *pIn_buf_size : 0;
2648
- d->m_out_buf_ofs = 0;
2649
- d->m_flush = flush;
2650
-
2651
- if ( ((d->m_pPut_buf_func != NULL) == ((pOut_buf != NULL) || (pOut_buf_size != NULL))) || (d->m_prev_return_status != TDEFL_STATUS_OKAY) ||
2652
- (d->m_wants_to_finish && (flush != TDEFL_FINISH)) || (pIn_buf_size && *pIn_buf_size && !pIn_buf) || (pOut_buf_size && *pOut_buf_size && !pOut_buf) )
2653
- {
2654
- if (pIn_buf_size) *pIn_buf_size = 0;
2655
- if (pOut_buf_size) *pOut_buf_size = 0;
2656
- return (d->m_prev_return_status = TDEFL_STATUS_BAD_PARAM);
2657
- }
2658
- d->m_wants_to_finish |= (flush == TDEFL_FINISH);
2659
-
2660
- if ((d->m_output_flush_remaining) || (d->m_finished))
2661
- return (d->m_prev_return_status = tdefl_flush_output_buffer(d));
2662
-
2663
-#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
2664
- if (((d->m_flags & TDEFL_MAX_PROBES_MASK) == 1) &&
2665
- ((d->m_flags & TDEFL_GREEDY_PARSING_FLAG) != 0) &&
2666
- ((d->m_flags & (TDEFL_FILTER_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS | TDEFL_RLE_MATCHES)) == 0))
2667
- {
2668
- if (!tdefl_compress_fast(d))
2669
- return d->m_prev_return_status;
2670
- }
2671
- else
2672
-#endif // #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
2673
- {
2674
- if (!tdefl_compress_normal(d))
2675
- return d->m_prev_return_status;
2676
- }
2677
-
2678
- if ((d->m_flags & (TDEFL_WRITE_ZLIB_HEADER | TDEFL_COMPUTE_ADLER32)) && (pIn_buf))
2679
- d->m_adler32 = (mz_uint32)mz_adler32(d->m_adler32, (const mz_uint8 *)pIn_buf, d->m_pSrc - (const mz_uint8 *)pIn_buf);
2680
-
2681
- if ((flush) && (!d->m_lookahead_size) && (!d->m_src_buf_left) && (!d->m_output_flush_remaining))
2682
- {
2683
- if (tdefl_flush_block(d, flush) < 0)
2684
- return d->m_prev_return_status;
2685
- d->m_finished = (flush == TDEFL_FINISH);
2686
- if (flush == TDEFL_FULL_FLUSH) { MZ_CLEAR_OBJ(d->m_hash); MZ_CLEAR_OBJ(d->m_next); d->m_dict_size = 0; }
2687
- }
2688
-
2689
- return (d->m_prev_return_status = tdefl_flush_output_buffer(d));
2690
-}
2691
-
2692
-tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf, size_t in_buf_size, tdefl_flush flush)
2693
-{
2694
- MZ_ASSERT(d->m_pPut_buf_func); return tdefl_compress(d, pIn_buf, &in_buf_size, NULL, NULL, flush);
2695
-}
2696
-
2697
-tdefl_status tdefl_init(tdefl_compressor *d, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags)
2698
-{
2699
- d->m_pPut_buf_func = pPut_buf_func; d->m_pPut_buf_user = pPut_buf_user;
2700
- d->m_flags = (mz_uint)(flags); d->m_max_probes[0] = 1 + ((flags & 0xFFF) + 2) / 3; d->m_greedy_parsing = (flags & TDEFL_GREEDY_PARSING_FLAG) != 0;
2701
- d->m_max_probes[1] = 1 + (((flags & 0xFFF) >> 2) + 2) / 3;
2702
- if (!(flags & TDEFL_NONDETERMINISTIC_PARSING_FLAG)) MZ_CLEAR_OBJ(d->m_hash);
2703
- d->m_lookahead_pos = d->m_lookahead_size = d->m_dict_size = d->m_total_lz_bytes = d->m_lz_code_buf_dict_pos = d->m_bits_in = 0;
2704
- d->m_output_flush_ofs = d->m_output_flush_remaining = d->m_finished = d->m_block_index = d->m_bit_buffer = d->m_wants_to_finish = 0;
2705
- d->m_pLZ_code_buf = d->m_lz_code_buf + 1; d->m_pLZ_flags = d->m_lz_code_buf; d->m_num_flags_left = 8;
2706
- d->m_pOutput_buf = d->m_output_buf; d->m_pOutput_buf_end = d->m_output_buf; d->m_prev_return_status = TDEFL_STATUS_OKAY;
2707
- d->m_saved_match_dist = d->m_saved_match_len = d->m_saved_lit = 0; d->m_adler32 = 1;
2708
- d->m_pIn_buf = NULL; d->m_pOut_buf = NULL;
2709
- d->m_pIn_buf_size = NULL; d->m_pOut_buf_size = NULL;
2710
- d->m_flush = TDEFL_NO_FLUSH; d->m_pSrc = NULL; d->m_src_buf_left = 0; d->m_out_buf_ofs = 0;
2711
- memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0);
2712
- memset(&d->m_huff_count[1][0], 0, sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1);
2713
- return TDEFL_STATUS_OKAY;
2714
-}
2715
-
2716
-tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d)
2717
-{
2718
- return d->m_prev_return_status;
2719
-}
2720
-
2721
-mz_uint32 tdefl_get_adler32(tdefl_compressor *d)
2722
-{
2723
- return d->m_adler32;
2724
-}
2725
-
2726
-mz_bool tdefl_compress_mem_to_output(const void *pBuf, size_t buf_len, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags)
2727
-{
2728
- tdefl_compressor *pComp; mz_bool succeeded; if (((buf_len) && (!pBuf)) || (!pPut_buf_func)) return MZ_FALSE;
2729
- pComp = (tdefl_compressor*)MZ_MALLOC(sizeof(tdefl_compressor)); if (!pComp) return MZ_FALSE;
2730
- succeeded = (tdefl_init(pComp, pPut_buf_func, pPut_buf_user, flags) == TDEFL_STATUS_OKAY);
2731
- succeeded = succeeded && (tdefl_compress_buffer(pComp, pBuf, buf_len, TDEFL_FINISH) == TDEFL_STATUS_DONE);
2732
- MZ_FREE(pComp); return succeeded;
2733
-}
2734
-
2735
-typedef struct
2736
-{
2737
- size_t m_size, m_capacity;
2738
- mz_uint8 *m_pBuf;
2739
- mz_bool m_expandable;
2740
-} tdefl_output_buffer;
2741
-
2742
-static mz_bool tdefl_output_buffer_putter(const void *pBuf, int len, void *pUser)
2743
-{
2744
- tdefl_output_buffer *p = (tdefl_output_buffer *)pUser;
2745
- size_t new_size = p->m_size + len;
2746
- if (new_size > p->m_capacity)
2747
- {
2748
- size_t new_capacity = p->m_capacity; mz_uint8 *pNew_buf; if (!p->m_expandable) return MZ_FALSE;
2749
- do { new_capacity = MZ_MAX(128U, new_capacity << 1U); } while (new_size > new_capacity);
2750
- pNew_buf = (mz_uint8*)MZ_REALLOC(p->m_pBuf, new_capacity); if (!pNew_buf) return MZ_FALSE;
2751
- p->m_pBuf = pNew_buf; p->m_capacity = new_capacity;
2752
- }
2753
- memcpy((mz_uint8*)p->m_pBuf + p->m_size, pBuf, len); p->m_size = new_size;
2754
- return MZ_TRUE;
2755
-}
2756
-
2757
-void *tdefl_compress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags)
2758
-{
2759
- tdefl_output_buffer out_buf; MZ_CLEAR_OBJ(out_buf);
2760
- if (!pOut_len) return MZ_FALSE; else *pOut_len = 0;
2761
- out_buf.m_expandable = MZ_TRUE;
2762
- if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags)) return NULL;
2763
- *pOut_len = out_buf.m_size; return out_buf.m_pBuf;
2764
-}
2765
-
2766
-size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags)
2767
-{
2768
- tdefl_output_buffer out_buf; MZ_CLEAR_OBJ(out_buf);
2769
- if (!pOut_buf) return 0;
2770
- out_buf.m_pBuf = (mz_uint8*)pOut_buf; out_buf.m_capacity = out_buf_len;
2771
- if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags)) return 0;
2772
- return out_buf.m_size;
2773
-}
2774
-
2775
-#ifndef MINIZ_NO_ZLIB_APIS
2776
-static const mz_uint s_tdefl_num_probes[11] = { 0, 1, 6, 32, 16, 32, 128, 256, 512, 768, 1500 };
2777
-
2778
-// level may actually range from [0,10] (10 is a "hidden" max level, where we want a bit more compression and it's fine if throughput to fall off a cliff on some files).
2779
-mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits, int strategy)
2780
-{
2781
- mz_uint comp_flags = s_tdefl_num_probes[(level >= 0) ? MZ_MIN(10, level) : MZ_DEFAULT_LEVEL] | ((level <= 3) ? TDEFL_GREEDY_PARSING_FLAG : 0);
2782
- if (window_bits > 0) comp_flags |= TDEFL_WRITE_ZLIB_HEADER;
2783
-
2784
- if (!level) comp_flags |= TDEFL_FORCE_ALL_RAW_BLOCKS;
2785
- else if (strategy == MZ_FILTERED) comp_flags |= TDEFL_FILTER_MATCHES;
2786
- else if (strategy == MZ_HUFFMAN_ONLY) comp_flags &= ~TDEFL_MAX_PROBES_MASK;
2787
- else if (strategy == MZ_FIXED) comp_flags |= TDEFL_FORCE_ALL_STATIC_BLOCKS;
2788
- else if (strategy == MZ_RLE) comp_flags |= TDEFL_RLE_MATCHES;
2789
-
2790
- return comp_flags;
2791
-}
2792
-#endif //MINIZ_NO_ZLIB_APIS
2793
-
2794
-#ifdef _MSC_VER
2795
-#pragma warning (push)
2796
-#pragma warning (disable:4204) // nonstandard extension used : non-constant aggregate initializer (also supported by GNU C and C99, so no big deal)
2797
-#endif
2798
-
2799
-// Simple PNG writer function by Alex Evans, 2011. Released into the public domain: https://gist.github.com/908299, more context at
2800
-// http://altdevblogaday.org/2011/04/06/a-smaller-jpg-encoder/.
2801
-// This is actually a modification of Alex's original code so PNG files generated by this function pass pngcheck.
2802
-void *tdefl_write_image_to_png_file_in_memory_ex(const void *pImage, int w, int h, int num_chans, size_t *pLen_out, mz_uint level, mz_bool flip)
2803
-{
2804
- // Using a local copy of this array here in case MINIZ_NO_ZLIB_APIS was defined.
2805
- static const mz_uint s_tdefl_png_num_probes[11] = { 0, 1, 6, 32, 16, 32, 128, 256, 512, 768, 1500 };
2806
- tdefl_compressor *pComp = (tdefl_compressor *)MZ_MALLOC(sizeof(tdefl_compressor)); tdefl_output_buffer out_buf; int i, bpl = w * num_chans, y, z; mz_uint32 c; *pLen_out = 0;
2807
- if (!pComp) return NULL;
2808
- MZ_CLEAR_OBJ(out_buf); out_buf.m_expandable = MZ_TRUE; out_buf.m_capacity = 57+MZ_MAX(64, (1+bpl)*h); if (NULL == (out_buf.m_pBuf = (mz_uint8*)MZ_MALLOC(out_buf.m_capacity))) { MZ_FREE(pComp); return NULL; }
2809
- // write dummy header
2810
- for (z = 41; z; --z) tdefl_output_buffer_putter(&z, 1, &out_buf);
2811
- // compress image data
2812
- tdefl_init(pComp, tdefl_output_buffer_putter, &out_buf, s_tdefl_png_num_probes[MZ_MIN(10, level)] | TDEFL_WRITE_ZLIB_HEADER);
2813
- for (y = 0; y < h; ++y) { tdefl_compress_buffer(pComp, &z, 1, TDEFL_NO_FLUSH); tdefl_compress_buffer(pComp, (mz_uint8*)pImage + (flip ? (h - 1 - y) : y) * bpl, bpl, TDEFL_NO_FLUSH); }
2814
- if (tdefl_compress_buffer(pComp, NULL, 0, TDEFL_FINISH) != TDEFL_STATUS_DONE) { MZ_FREE(pComp); MZ_FREE(out_buf.m_pBuf); return NULL; }
2815
- // write real header
2816
- *pLen_out = out_buf.m_size-41;
2817
- {
2818
- static const mz_uint8 chans[] = {0x00, 0x00, 0x04, 0x02, 0x06};
2819
- mz_uint8 pnghdr[41]={0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d,0x49,0x48,0x44,0x52,
2820
- 0,0,(mz_uint8)(w>>8),(mz_uint8)w,0,0,(mz_uint8)(h>>8),(mz_uint8)h,8,chans[num_chans],0,0,0,0,0,0,0,
2821
- (mz_uint8)(*pLen_out>>24),(mz_uint8)(*pLen_out>>16),(mz_uint8)(*pLen_out>>8),(mz_uint8)*pLen_out,0x49,0x44,0x41,0x54};
2822
- c=(mz_uint32)mz_crc32(MZ_CRC32_INIT,pnghdr+12,17); for (i=0; i<4; ++i, c<<=8) ((mz_uint8*)(pnghdr+29))[i]=(mz_uint8)(c>>24);
2823
- memcpy(out_buf.m_pBuf, pnghdr, 41);
2824
- }
2825
- // write footer (IDAT CRC-32, followed by IEND chunk)
2826
- if (!tdefl_output_buffer_putter("\0\0\0\0\0\0\0\0\x49\x45\x4e\x44\xae\x42\x60\x82", 16, &out_buf)) { *pLen_out = 0; MZ_FREE(pComp); MZ_FREE(out_buf.m_pBuf); return NULL; }
2827
- c = (mz_uint32)mz_crc32(MZ_CRC32_INIT,out_buf.m_pBuf+41-4, *pLen_out+4); for (i=0; i<4; ++i, c<<=8) (out_buf.m_pBuf+out_buf.m_size-16)[i] = (mz_uint8)(c >> 24);
2828
- // compute final size of file, grab compressed data buffer and return
2829
- *pLen_out += 57; MZ_FREE(pComp); return out_buf.m_pBuf;
2830
-}
2831
-void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h, int num_chans, size_t *pLen_out)
2832
-{
2833
- // Level 6 corresponds to TDEFL_DEFAULT_MAX_PROBES or MZ_DEFAULT_LEVEL (but we can't depend on MZ_DEFAULT_LEVEL being available in case the zlib API's where #defined out)
2834
- return tdefl_write_image_to_png_file_in_memory_ex(pImage, w, h, num_chans, pLen_out, 6, MZ_FALSE);
2835
-}
2836
-
2837
-#ifdef _MSC_VER
2838
-#pragma warning (pop)
2839
-#endif
2840
-
2841
-// ------------------- .ZIP archive reading
2842
-
2843
-#ifndef MINIZ_NO_ARCHIVE_APIS
2844
-
2845
-#ifdef MINIZ_NO_STDIO
2846
- #define MZ_FILE void *
2847
-#else
2848
- #include <stdio.h>
2849
- #include <sys/stat.h>
2850
-
2851
- #if defined(_MSC_VER) || defined(__MINGW64__)
2852
- static FILE *mz_fopen(const char *pFilename, const char *pMode)
2853
- {
2854
- FILE* pFile = NULL;
2855
- fopen_s(&pFile, pFilename, pMode);
2856
- return pFile;
2857
- }
2858
- static FILE *mz_freopen(const char *pPath, const char *pMode, FILE *pStream)
2859
- {
2860
- FILE* pFile = NULL;
2861
- if (freopen_s(&pFile, pPath, pMode, pStream))
2862
- return NULL;
2863
- return pFile;
2864
- }
2865
- #ifndef MINIZ_NO_TIME
2866
- #include <sys/utime.h>
2867
- #endif
2868
- #define MZ_FILE FILE
2869
- #define MZ_FOPEN mz_fopen
2870
- #define MZ_FCLOSE fclose
2871
- #define MZ_FREAD fread
2872
- #define MZ_FWRITE fwrite
2873
- #define MZ_FTELL64 _ftelli64
2874
- #define MZ_FSEEK64 _fseeki64
2875
- #define MZ_FILE_STAT_STRUCT _stat
2876
- #define MZ_FILE_STAT _stat
2877
- #define MZ_FFLUSH fflush
2878
- #define MZ_FREOPEN mz_freopen
2879
- #define MZ_DELETE_FILE remove
2880
- #elif defined(__MINGW32__)
2881
- #ifndef MINIZ_NO_TIME
2882
- #include <sys/utime.h>
2883
- #endif
2884
- #define MZ_FILE FILE
2885
- #define MZ_FOPEN(f, m) fopen(f, m)
2886
- #define MZ_FCLOSE fclose
2887
- #define MZ_FREAD fread
2888
- #define MZ_FWRITE fwrite
2889
- #define MZ_FTELL64 ftello64
2890
- #define MZ_FSEEK64 fseeko64
2891
- #define MZ_FILE_STAT_STRUCT _stat
2892
- #define MZ_FILE_STAT _stat
2893
- #define MZ_FFLUSH fflush
2894
- #define MZ_FREOPEN(f, m, s) freopen(f, m, s)
2895
- #define MZ_DELETE_FILE remove
2896
- #elif defined(__TINYC__)
2897
- #ifndef MINIZ_NO_TIME
2898
- #include <sys/utime.h>
2899
- #endif
2900
- #define MZ_FILE FILE
2901
- #define MZ_FOPEN(f, m) fopen(f, m)
2902
- #define MZ_FCLOSE fclose
2903
- #define MZ_FREAD fread
2904
- #define MZ_FWRITE fwrite
2905
- #define MZ_FTELL64 ftell
2906
- #define MZ_FSEEK64 fseek
2907
- #define MZ_FILE_STAT_STRUCT stat
2908
- #define MZ_FILE_STAT stat
2909
- #define MZ_FFLUSH fflush
2910
- #define MZ_FREOPEN(f, m, s) freopen(f, m, s)
2911
- #define MZ_DELETE_FILE remove
2912
- #elif defined(__GNUC__) && _LARGEFILE64_SOURCE
2913
- #ifndef MINIZ_NO_TIME
2914
- #include <utime.h>
2915
- #endif
2916
- #define MZ_FILE FILE
2917
- #define MZ_FOPEN(f, m) fopen64(f, m)
2918
- #define MZ_FCLOSE fclose
2919
- #define MZ_FREAD fread
2920
- #define MZ_FWRITE fwrite
2921
- #define MZ_FTELL64 ftello64
2922
- #define MZ_FSEEK64 fseeko64
2923
- #define MZ_FILE_STAT_STRUCT stat64
2924
- #define MZ_FILE_STAT stat64
2925
- #define MZ_FFLUSH fflush
2926
- #define MZ_FREOPEN(p, m, s) freopen64(p, m, s)
2927
- #define MZ_DELETE_FILE remove
2928
- #else
2929
- #ifndef MINIZ_NO_TIME
2930
- #include <utime.h>
2931
- #endif
2932
- #define MZ_FILE FILE
2933
- #define MZ_FOPEN(f, m) fopen(f, m)
2934
- #define MZ_FCLOSE fclose
2935
- #define MZ_FREAD fread
2936
- #define MZ_FWRITE fwrite
2937
- #define MZ_FTELL64 ftello
2938
- #define MZ_FSEEK64 fseeko
2939
- #define MZ_FILE_STAT_STRUCT stat
2940
- #define MZ_FILE_STAT stat
2941
- #define MZ_FFLUSH fflush
2942
- #define MZ_FREOPEN(f, m, s) freopen(f, m, s)
2943
- #define MZ_DELETE_FILE remove
2944
- #endif // #ifdef _MSC_VER
2945
-#endif // #ifdef MINIZ_NO_STDIO
2946
-
2947
-#define MZ_TOLOWER(c) ((((c) >= 'A') && ((c) <= 'Z')) ? ((c) - 'A' + 'a') : (c))
2948
-
2949
-// Various ZIP archive enums. To completely avoid cross platform compiler alignment and platform endian issues, miniz.c doesn't use structs for any of this stuff.
2950
-enum
2951
-{
2952
- // ZIP archive identifiers and record sizes
2953
- MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG = 0x06054b50, MZ_ZIP_CENTRAL_DIR_HEADER_SIG = 0x02014b50, MZ_ZIP_LOCAL_DIR_HEADER_SIG = 0x04034b50,
2954
- MZ_ZIP_LOCAL_DIR_HEADER_SIZE = 30, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE = 46, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE = 22,
2955
- // Central directory header record offsets
2956
- MZ_ZIP_CDH_SIG_OFS = 0, MZ_ZIP_CDH_VERSION_MADE_BY_OFS = 4, MZ_ZIP_CDH_VERSION_NEEDED_OFS = 6, MZ_ZIP_CDH_BIT_FLAG_OFS = 8,
2957
- MZ_ZIP_CDH_METHOD_OFS = 10, MZ_ZIP_CDH_FILE_TIME_OFS = 12, MZ_ZIP_CDH_FILE_DATE_OFS = 14, MZ_ZIP_CDH_CRC32_OFS = 16,
2958
- MZ_ZIP_CDH_COMPRESSED_SIZE_OFS = 20, MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS = 24, MZ_ZIP_CDH_FILENAME_LEN_OFS = 28, MZ_ZIP_CDH_EXTRA_LEN_OFS = 30,
2959
- MZ_ZIP_CDH_COMMENT_LEN_OFS = 32, MZ_ZIP_CDH_DISK_START_OFS = 34, MZ_ZIP_CDH_INTERNAL_ATTR_OFS = 36, MZ_ZIP_CDH_EXTERNAL_ATTR_OFS = 38, MZ_ZIP_CDH_LOCAL_HEADER_OFS = 42,
2960
- // Local directory header offsets
2961
- MZ_ZIP_LDH_SIG_OFS = 0, MZ_ZIP_LDH_VERSION_NEEDED_OFS = 4, MZ_ZIP_LDH_BIT_FLAG_OFS = 6, MZ_ZIP_LDH_METHOD_OFS = 8, MZ_ZIP_LDH_FILE_TIME_OFS = 10,
2962
- MZ_ZIP_LDH_FILE_DATE_OFS = 12, MZ_ZIP_LDH_CRC32_OFS = 14, MZ_ZIP_LDH_COMPRESSED_SIZE_OFS = 18, MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS = 22,
2963
- MZ_ZIP_LDH_FILENAME_LEN_OFS = 26, MZ_ZIP_LDH_EXTRA_LEN_OFS = 28,
2964
- // End of central directory offsets
2965
- MZ_ZIP_ECDH_SIG_OFS = 0, MZ_ZIP_ECDH_NUM_THIS_DISK_OFS = 4, MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS = 6, MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS = 8,
2966
- MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS = 10, MZ_ZIP_ECDH_CDIR_SIZE_OFS = 12, MZ_ZIP_ECDH_CDIR_OFS_OFS = 16, MZ_ZIP_ECDH_COMMENT_SIZE_OFS = 20,
2967
-};
2968
-
2969
-typedef struct
2970
-{
2971
- void *m_p;
2972
- size_t m_size, m_capacity;
2973
- mz_uint m_element_size;
2974
-} mz_zip_array;
2975
-
2976
-struct mz_zip_internal_state_tag
2977
-{
2978
- mz_zip_array m_central_dir;
2979
- mz_zip_array m_central_dir_offsets;
2980
- mz_zip_array m_sorted_central_dir_offsets;
2981
- MZ_FILE *m_pFile;
2982
- void *m_pMem;
2983
- size_t m_mem_size;
2984
- size_t m_mem_capacity;
2985
-};
2986
-
2987
-#define MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(array_ptr, element_size) (array_ptr)->m_element_size = element_size
2988
-#define MZ_ZIP_ARRAY_ELEMENT(array_ptr, element_type, index) ((element_type *)((array_ptr)->m_p))[index]
2989
-
2990
-static MZ_FORCEINLINE void mz_zip_array_clear(mz_zip_archive *pZip, mz_zip_array *pArray)
2991
-{
2992
- pZip->m_pFree(pZip->m_pAlloc_opaque, pArray->m_p);
2993
- memset(pArray, 0, sizeof(mz_zip_array));
2994
-}
2995
-
2996
-static mz_bool mz_zip_array_ensure_capacity(mz_zip_archive *pZip, mz_zip_array *pArray, size_t min_new_capacity, mz_uint growing)
2997
-{
2998
- void *pNew_p; size_t new_capacity = min_new_capacity; MZ_ASSERT(pArray->m_element_size); if (pArray->m_capacity >= min_new_capacity) return MZ_TRUE;
2999
- if (growing) { new_capacity = MZ_MAX(1, pArray->m_capacity); while (new_capacity < min_new_capacity) new_capacity *= 2; }
3000
- if (NULL == (pNew_p = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pArray->m_p, pArray->m_element_size, new_capacity))) return MZ_FALSE;
3001
- pArray->m_p = pNew_p; pArray->m_capacity = new_capacity;
3002
- return MZ_TRUE;
3003
-}
3004
-
3005
-static MZ_FORCEINLINE mz_bool mz_zip_array_reserve(mz_zip_archive *pZip, mz_zip_array *pArray, size_t new_capacity, mz_uint growing)
3006
-{
3007
- if (new_capacity > pArray->m_capacity) { if (!mz_zip_array_ensure_capacity(pZip, pArray, new_capacity, growing)) return MZ_FALSE; }
3008
- return MZ_TRUE;
3009
-}
3010
-
3011
-static MZ_FORCEINLINE mz_bool mz_zip_array_resize(mz_zip_archive *pZip, mz_zip_array *pArray, size_t new_size, mz_uint growing)
3012
-{
3013
- if (new_size > pArray->m_capacity) { if (!mz_zip_array_ensure_capacity(pZip, pArray, new_size, growing)) return MZ_FALSE; }
3014
- pArray->m_size = new_size;
3015
- return MZ_TRUE;
3016
-}
3017
-
3018
-static MZ_FORCEINLINE mz_bool mz_zip_array_ensure_room(mz_zip_archive *pZip, mz_zip_array *pArray, size_t n)
3019
-{
3020
- return mz_zip_array_reserve(pZip, pArray, pArray->m_size + n, MZ_TRUE);
3021
-}
3022
-
3023
-static MZ_FORCEINLINE mz_bool mz_zip_array_push_back(mz_zip_archive *pZip, mz_zip_array *pArray, const void *pElements, size_t n)
3024
-{
3025
- size_t orig_size = pArray->m_size; if (!mz_zip_array_resize(pZip, pArray, orig_size + n, MZ_TRUE)) return MZ_FALSE;
3026
- memcpy((mz_uint8*)pArray->m_p + orig_size * pArray->m_element_size, pElements, n * pArray->m_element_size);
3027
- return MZ_TRUE;
3028
-}
3029
-
3030
-#ifndef MINIZ_NO_TIME
3031
-static time_t mz_zip_dos_to_time_t(int dos_time, int dos_date)
3032
-{
3033
- struct tm tm;
3034
- memset(&tm, 0, sizeof(tm)); tm.tm_isdst = -1;
3035
- tm.tm_year = ((dos_date >> 9) & 127) + 1980 - 1900; tm.tm_mon = ((dos_date >> 5) & 15) - 1; tm.tm_mday = dos_date & 31;
3036
- tm.tm_hour = (dos_time >> 11) & 31; tm.tm_min = (dos_time >> 5) & 63; tm.tm_sec = (dos_time << 1) & 62;
3037
- return mktime(&tm);
3038
-}
3039
-
3040
-static void mz_zip_time_to_dos_time(time_t time, mz_uint16 *pDOS_time, mz_uint16 *pDOS_date)
3041
-{
3042
-#ifdef _MSC_VER
3043
- struct tm tm_struct;
3044
- struct tm *tm = &tm_struct;
3045
- errno_t err = localtime_s(tm, &time);
3046
- if (err)
3047
- {
3048
- *pDOS_date = 0; *pDOS_time = 0;
3049
- return;
3050
- }
3051
-#else
3052
- struct tm *tm = localtime(&time);
3053
-#endif
3054
- *pDOS_time = (mz_uint16)(((tm->tm_hour) << 11) + ((tm->tm_min) << 5) + ((tm->tm_sec) >> 1));
3055
- *pDOS_date = (mz_uint16)(((tm->tm_year + 1900 - 1980) << 9) + ((tm->tm_mon + 1) << 5) + tm->tm_mday);
3056
-}
3057
-#endif
3058
-
3059
-#ifndef MINIZ_NO_STDIO
3060
-static mz_bool mz_zip_get_file_modified_time(const char *pFilename, mz_uint16 *pDOS_time, mz_uint16 *pDOS_date)
3061
-{
3062
-#ifdef MINIZ_NO_TIME
3063
- (void)pFilename; *pDOS_date = *pDOS_time = 0;
3064
-#else
3065
- struct MZ_FILE_STAT_STRUCT file_stat;
3066
- // On Linux with x86 glibc, this call will fail on large files (>= 0x80000000 bytes) unless you compiled with _LARGEFILE64_SOURCE. Argh.
3067
- if (MZ_FILE_STAT(pFilename, &file_stat) != 0)
3068
- return MZ_FALSE;
3069
- mz_zip_time_to_dos_time(file_stat.st_mtime, pDOS_time, pDOS_date);
3070
-#endif // #ifdef MINIZ_NO_TIME
3071
- return MZ_TRUE;
3072
-}
3073
-
3074
-#ifndef MINIZ_NO_TIME
3075
-static mz_bool mz_zip_set_file_times(const char *pFilename, time_t access_time, time_t modified_time)
3076
-{
3077
- struct utimbuf t; t.actime = access_time; t.modtime = modified_time;
3078
- return !utime(pFilename, &t);
3079
-}
3080
-#endif // #ifndef MINIZ_NO_TIME
3081
-#endif // #ifndef MINIZ_NO_STDIO
3082
-
3083
-static mz_bool mz_zip_reader_init_internal(mz_zip_archive *pZip, mz_uint32 flags)
3084
-{
3085
- (void)flags;
3086
- if ((!pZip) || (pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID))
3087
- return MZ_FALSE;
3088
-
3089
- if (!pZip->m_pAlloc) pZip->m_pAlloc = def_alloc_func;
3090
- if (!pZip->m_pFree) pZip->m_pFree = def_free_func;
3091
- if (!pZip->m_pRealloc) pZip->m_pRealloc = def_realloc_func;
3092
-
3093
- pZip->m_zip_mode = MZ_ZIP_MODE_READING;
3094
- pZip->m_archive_size = 0;
3095
- pZip->m_central_directory_file_ofs = 0;
3096
- pZip->m_total_files = 0;
3097
-
3098
- if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state))))
3099
- return MZ_FALSE;
3100
- memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state));
3101
- MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir, sizeof(mz_uint8));
3102
- MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets, sizeof(mz_uint32));
3103
- MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets, sizeof(mz_uint32));
3104
- return MZ_TRUE;
3105
-}
3106
-
3107
-static MZ_FORCEINLINE mz_bool mz_zip_reader_filename_less(const mz_zip_array *pCentral_dir_array, const mz_zip_array *pCentral_dir_offsets, mz_uint l_index, mz_uint r_index)
3108
-{
3109
- const mz_uint8 *pL = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, l_index)), *pE;
3110
- const mz_uint8 *pR = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, r_index));
3111
- mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS), r_len = MZ_READ_LE16(pR + MZ_ZIP_CDH_FILENAME_LEN_OFS);
3112
- mz_uint8 l = 0, r = 0;
3113
- pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE; pR += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
3114
- pE = pL + MZ_MIN(l_len, r_len);
3115
- while (pL < pE)
3116
- {
3117
- if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR)))
3118
- break;
3119
- pL++; pR++;
3120
- }
3121
- return (pL == pE) ? (l_len < r_len) : (l < r);
3122
-}
3123
-
3124
-#define MZ_SWAP_UINT32(a, b) do { mz_uint32 t = a; a = b; b = t; } MZ_MACRO_END
3125
-
3126
-// Heap sort of lowercased filenames, used to help accelerate plain central directory searches by mz_zip_reader_locate_file(). (Could also use qsort(), but it could allocate memory.)
3127
-static void mz_zip_reader_sort_central_dir_offsets_by_filename(mz_zip_archive *pZip)
3128
-{
3129
- mz_zip_internal_state *pState = pZip->m_pState;
3130
- const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets;
3131
- const mz_zip_array *pCentral_dir = &pState->m_central_dir;
3132
- mz_uint32 *pIndices = &MZ_ZIP_ARRAY_ELEMENT(&pState->m_sorted_central_dir_offsets, mz_uint32, 0);
3133
- const int size = pZip->m_total_files;
3134
- int start = (size - 2) >> 1, end;
3135
- while (start >= 0)
3136
- {
3137
- int child, root = start;
3138
- for ( ; ; )
3139
- {
3140
- if ((child = (root << 1) + 1) >= size)
3141
- break;
3142
- child += (((child + 1) < size) && (mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[child], pIndices[child + 1])));
3143
- if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[root], pIndices[child]))
3144
- break;
3145
- MZ_SWAP_UINT32(pIndices[root], pIndices[child]); root = child;
3146
- }
3147
- start--;
3148
- }
3149
-
3150
- end = size - 1;
3151
- while (end > 0)
3152
- {
3153
- int child, root = 0;
3154
- MZ_SWAP_UINT32(pIndices[end], pIndices[0]);
3155
- for ( ; ; )
3156
- {
3157
- if ((child = (root << 1) + 1) >= end)
3158
- break;
3159
- child += (((child + 1) < end) && mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[child], pIndices[child + 1]));
3160
- if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[root], pIndices[child]))
3161
- break;
3162
- MZ_SWAP_UINT32(pIndices[root], pIndices[child]); root = child;
3163
- }
3164
- end--;
3165
- }
3166
-}
3167
-
3168
-static mz_bool mz_zip_reader_read_central_dir(mz_zip_archive *pZip, mz_uint32 flags)
3169
-{
3170
- mz_uint cdir_size, num_this_disk, cdir_disk_index;
3171
- mz_uint64 cdir_ofs;
3172
- mz_int64 cur_file_ofs;
3173
- const mz_uint8 *p;
3174
- mz_uint32 buf_u32[4096 / sizeof(mz_uint32)]; mz_uint8 *pBuf = (mz_uint8 *)buf_u32;
3175
- mz_bool sort_central_dir = ((flags & MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY) == 0);
3176
- // Basic sanity checks - reject files which are too small, and check the first 4 bytes of the file to make sure a local header is there.
3177
- if (pZip->m_archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
3178
- return MZ_FALSE;
3179
- // Find the end of central directory record by scanning the file from the end towards the beginning.
3180
- cur_file_ofs = MZ_MAX((mz_int64)pZip->m_archive_size - (mz_int64)sizeof(buf_u32), 0);
3181
- for ( ; ; )
3182
- {
3183
- int i, n = (int)MZ_MIN(sizeof(buf_u32), pZip->m_archive_size - cur_file_ofs);
3184
- if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, n) != (mz_uint)n)
3185
- return MZ_FALSE;
3186
- for (i = n - 4; i >= 0; --i)
3187
- if (MZ_READ_LE32(pBuf + i) == MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG)
3188
- break;
3189
- if (i >= 0)
3190
- {
3191
- cur_file_ofs += i;
3192
- break;
3193
- }
3194
- if ((!cur_file_ofs) || ((pZip->m_archive_size - cur_file_ofs) >= (0xFFFF + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)))
3195
- return MZ_FALSE;
3196
- cur_file_ofs = MZ_MAX(cur_file_ofs - (sizeof(buf_u32) - 3), 0);
3197
- }
3198
- // Read and verify the end of central directory record.
3199
- if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) != MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
3200
- return MZ_FALSE;
3201
- if ((MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_SIG_OFS) != MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG) ||
3202
- ((pZip->m_total_files = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS)) != MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS)))
3203
- return MZ_FALSE;
3204
-
3205
- num_this_disk = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_THIS_DISK_OFS);
3206
- cdir_disk_index = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS);
3207
- if (((num_this_disk | cdir_disk_index) != 0) && ((num_this_disk != 1) || (cdir_disk_index != 1)))
3208
- return MZ_FALSE;
3209
-
3210
- if ((cdir_size = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_SIZE_OFS)) < pZip->m_total_files * MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)
3211
- return MZ_FALSE;
3212
-
3213
- cdir_ofs = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_OFS_OFS);
3214
- if ((cdir_ofs + (mz_uint64)cdir_size) > pZip->m_archive_size)
3215
- return MZ_FALSE;
3216
-
3217
- pZip->m_central_directory_file_ofs = cdir_ofs;
3218
-
3219
- if (pZip->m_total_files)
3220
- {
3221
- mz_uint i, n;
3222
-
3223
- // Read the entire central directory into a heap block, and allocate another heap block to hold the unsorted central dir file record offsets, and another to hold the sorted indices.
3224
- if ((!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir, cdir_size, MZ_FALSE)) ||
3225
- (!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir_offsets, pZip->m_total_files, MZ_FALSE)))
3226
- return MZ_FALSE;
3227
-
3228
- if (sort_central_dir)
3229
- {
3230
- if (!mz_zip_array_resize(pZip, &pZip->m_pState->m_sorted_central_dir_offsets, pZip->m_total_files, MZ_FALSE))
3231
- return MZ_FALSE;
3232
- }
3233
-
3234
- if (pZip->m_pRead(pZip->m_pIO_opaque, cdir_ofs, pZip->m_pState->m_central_dir.m_p, cdir_size) != cdir_size)
3235
- return MZ_FALSE;
3236
-
3237
- // Now create an index into the central directory file records, do some basic sanity checking on each record, and check for zip64 entries (which are not yet supported).
3238
- p = (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p;
3239
- for (n = cdir_size, i = 0; i < pZip->m_total_files; ++i)
3240
- {
3241
- mz_uint total_header_size, comp_size, decomp_size, disk_index;
3242
- if ((n < MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) || (MZ_READ_LE32(p) != MZ_ZIP_CENTRAL_DIR_HEADER_SIG))
3243
- return MZ_FALSE;
3244
- MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, i) = (mz_uint32)(p - (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p);
3245
- if (sort_central_dir)
3246
- MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_sorted_central_dir_offsets, mz_uint32, i) = i;
3247
- comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
3248
- decomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
3249
- if (((!MZ_READ_LE32(p + MZ_ZIP_CDH_METHOD_OFS)) && (decomp_size != comp_size)) || (decomp_size && !comp_size) || (decomp_size == 0xFFFFFFFF) || (comp_size == 0xFFFFFFFF))
3250
- return MZ_FALSE;
3251
- disk_index = MZ_READ_LE16(p + MZ_ZIP_CDH_DISK_START_OFS);
3252
- if ((disk_index != num_this_disk) && (disk_index != 1))
3253
- return MZ_FALSE;
3254
- if (((mz_uint64)MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS) + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + comp_size) > pZip->m_archive_size)
3255
- return MZ_FALSE;
3256
- if ((total_header_size = MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS)) > n)
3257
- return MZ_FALSE;
3258
- n -= total_header_size; p += total_header_size;
3259
- }
3260
- }
3261
-
3262
- if (sort_central_dir)
3263
- mz_zip_reader_sort_central_dir_offsets_by_filename(pZip);
3264
-
3265
- return MZ_TRUE;
3266
-}
3267
-
3268
-mz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size, mz_uint32 flags)
3269
-{
3270
- if ((!pZip) || (!pZip->m_pRead))
3271
- return MZ_FALSE;
3272
- if (!mz_zip_reader_init_internal(pZip, flags))
3273
- return MZ_FALSE;
3274
- pZip->m_archive_size = size;
3275
- if (!mz_zip_reader_read_central_dir(pZip, flags))
3276
- {
3277
- mz_zip_reader_end(pZip);
3278
- return MZ_FALSE;
3279
- }
3280
- return MZ_TRUE;
3281
-}
3282
-
3283
-static size_t mz_zip_mem_read_func(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n)
3284
-{
3285
- mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
3286
- size_t s = (file_ofs >= pZip->m_archive_size) ? 0 : (size_t)MZ_MIN(pZip->m_archive_size - file_ofs, n);
3287
- memcpy(pBuf, (const mz_uint8 *)pZip->m_pState->m_pMem + file_ofs, s);
3288
- return s;
3289
-}
3290
-
3291
-mz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem, size_t size, mz_uint32 flags)
3292
-{
3293
- if (!mz_zip_reader_init_internal(pZip, flags))
3294
- return MZ_FALSE;
3295
- pZip->m_archive_size = size;
3296
- pZip->m_pRead = mz_zip_mem_read_func;
3297
- pZip->m_pIO_opaque = pZip;
3298
-#ifdef __cplusplus
3299
- pZip->m_pState->m_pMem = const_cast<void *>(pMem);
3300
-#else
3301
- pZip->m_pState->m_pMem = (void *)pMem;
3302
-#endif
3303
- pZip->m_pState->m_mem_size = size;
3304
- if (!mz_zip_reader_read_central_dir(pZip, flags))
3305
- {
3306
- mz_zip_reader_end(pZip);
3307
- return MZ_FALSE;
3308
- }
3309
- return MZ_TRUE;
3310
-}
3311
-
3312
-#ifndef MINIZ_NO_STDIO
3313
-static size_t mz_zip_file_read_func(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n)
3314
-{
3315
- mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
3316
- mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile);
3317
- if (((mz_int64)file_ofs < 0) || (((cur_ofs != (mz_int64)file_ofs)) && (MZ_FSEEK64(pZip->m_pState->m_pFile, (mz_int64)file_ofs, SEEK_SET))))
3318
- return 0;
3319
- return MZ_FREAD(pBuf, 1, n, pZip->m_pState->m_pFile);
3320
-}
3321
-
3322
-mz_bool mz_zip_reader_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint32 flags)
3323
-{
3324
- mz_uint64 file_size;
3325
- MZ_FILE *pFile = MZ_FOPEN(pFilename, "rb");
3326
- if (!pFile)
3327
- return MZ_FALSE;
3328
- if (MZ_FSEEK64(pFile, 0, SEEK_END))
3329
- {
3330
- MZ_FCLOSE(pFile);
3331
- return MZ_FALSE;
3332
- }
3333
- file_size = MZ_FTELL64(pFile);
3334
- if (!mz_zip_reader_init_internal(pZip, flags))
3335
- {
3336
- MZ_FCLOSE(pFile);
3337
- return MZ_FALSE;
3338
- }
3339
- pZip->m_pRead = mz_zip_file_read_func;
3340
- pZip->m_pIO_opaque = pZip;
3341
- pZip->m_pState->m_pFile = pFile;
3342
- pZip->m_archive_size = file_size;
3343
- if (!mz_zip_reader_read_central_dir(pZip, flags))
3344
- {
3345
- mz_zip_reader_end(pZip);
3346
- return MZ_FALSE;
3347
- }
3348
- return MZ_TRUE;
3349
-}
3350
-#endif // #ifndef MINIZ_NO_STDIO
3351
-
3352
-mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip)
3353
-{
3354
- return pZip ? pZip->m_total_files : 0;
3355
-}
3356
-
3357
-static MZ_FORCEINLINE const mz_uint8 *mz_zip_reader_get_cdh(mz_zip_archive *pZip, mz_uint file_index)
3358
-{
3359
- if ((!pZip) || (!pZip->m_pState) || (file_index >= pZip->m_total_files) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
3360
- return NULL;
3361
- return &MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index));
3362
-}
3363
-
3364
-mz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive *pZip, mz_uint file_index)
3365
-{
3366
- mz_uint m_bit_flag;
3367
- const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index);
3368
- if (!p)
3369
- return MZ_FALSE;
3370
- m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
3371
- return (m_bit_flag & 1);
3372
-}
3373
-
3374
-mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip, mz_uint file_index)
3375
-{
3376
- mz_uint filename_len, external_attr;
3377
- const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index);
3378
- if (!p)
3379
- return MZ_FALSE;
3380
-
3381
- // First see if the filename ends with a '/' character.
3382
- filename_len = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
3383
- if (filename_len)
3384
- {
3385
- if (*(p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_len - 1) == '/')
3386
- return MZ_TRUE;
3387
- }
3388
-
3389
- // Bugfix: This code was also checking if the internal attribute was non-zero, which wasn't correct.
3390
- // Most/all zip writers (hopefully) set DOS file/directory attributes in the low 16-bits, so check for the DOS directory flag and ignore the source OS ID in the created by field.
3391
- // FIXME: Remove this check? Is it necessary - we already check the filename.
3392
- external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS);
3393
- if ((external_attr & 0x10) != 0)
3394
- return MZ_TRUE;
3395
-
3396
- return MZ_FALSE;
3397
-}
3398
-
3399
-mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index, mz_zip_archive_file_stat *pStat)
3400
-{
3401
- mz_uint n;
3402
- const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index);
3403
- if ((!p) || (!pStat))
3404
- return MZ_FALSE;
3405
-
3406
- // Unpack the central directory record.
3407
- pStat->m_file_index = file_index;
3408
- pStat->m_central_dir_ofs = MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index);
3409
- pStat->m_version_made_by = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_MADE_BY_OFS);
3410
- pStat->m_version_needed = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_NEEDED_OFS);
3411
- pStat->m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
3412
- pStat->m_method = MZ_READ_LE16(p + MZ_ZIP_CDH_METHOD_OFS);
3413
-#ifndef MINIZ_NO_TIME
3414
- pStat->m_time = mz_zip_dos_to_time_t(MZ_READ_LE16(p + MZ_ZIP_CDH_FILE_TIME_OFS), MZ_READ_LE16(p + MZ_ZIP_CDH_FILE_DATE_OFS));
3415
-#endif
3416
- pStat->m_crc32 = MZ_READ_LE32(p + MZ_ZIP_CDH_CRC32_OFS);
3417
- pStat->m_comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
3418
- pStat->m_uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
3419
- pStat->m_internal_attr = MZ_READ_LE16(p + MZ_ZIP_CDH_INTERNAL_ATTR_OFS);
3420
- pStat->m_external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS);
3421
- pStat->m_local_header_ofs = MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS);
3422
-
3423
- // Copy as much of the filename and comment as possible.
3424
- n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS); n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE - 1);
3425
- memcpy(pStat->m_filename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n); pStat->m_filename[n] = '\0';
3426
-
3427
- n = MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS); n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE - 1);
3428
- pStat->m_comment_size = n;
3429
- memcpy(pStat->m_comment, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS), n); pStat->m_comment[n] = '\0';
3430
-
3431
- return MZ_TRUE;
3432
-}
3433
-
3434
-mz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, mz_uint file_index, char *pFilename, mz_uint filename_buf_size)
3435
-{
3436
- mz_uint n;
3437
- const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index);
3438
- if (!p) { if (filename_buf_size) pFilename[0] = '\0'; return 0; }
3439
- n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
3440
- if (filename_buf_size)
3441
- {
3442
- n = MZ_MIN(n, filename_buf_size - 1);
3443
- memcpy(pFilename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n);
3444
- pFilename[n] = '\0';
3445
- }
3446
- return n + 1;
3447
-}
3448
-
3449
-static MZ_FORCEINLINE mz_bool mz_zip_reader_string_equal(const char *pA, const char *pB, mz_uint len, mz_uint flags)
3450
-{
3451
- mz_uint i;
3452
- if (flags & MZ_ZIP_FLAG_CASE_SENSITIVE)
3453
- return 0 == memcmp(pA, pB, len);
3454
- for (i = 0; i < len; ++i)
3455
- if (MZ_TOLOWER(pA[i]) != MZ_TOLOWER(pB[i]))
3456
- return MZ_FALSE;
3457
- return MZ_TRUE;
3458
-}
3459
-
3460
-static MZ_FORCEINLINE int mz_zip_reader_filename_compare(const mz_zip_array *pCentral_dir_array, const mz_zip_array *pCentral_dir_offsets, mz_uint l_index, const char *pR, mz_uint r_len)
3461
-{
3462
- const mz_uint8 *pL = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, l_index)), *pE;
3463
- mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS);
3464
- mz_uint8 l = 0, r = 0;
3465
- pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
3466
- pE = pL + MZ_MIN(l_len, r_len);
3467
- while (pL < pE)
3468
- {
3469
- if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR)))
3470
- break;
3471
- pL++; pR++;
3472
- }
3473
- return (pL == pE) ? (int)(l_len - r_len) : (l - r);
3474
-}
3475
-
3476
-static int mz_zip_reader_locate_file_binary_search(mz_zip_archive *pZip, const char *pFilename)
3477
-{
3478
- mz_zip_internal_state *pState = pZip->m_pState;
3479
- const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets;
3480
- const mz_zip_array *pCentral_dir = &pState->m_central_dir;
3481
- mz_uint32 *pIndices = &MZ_ZIP_ARRAY_ELEMENT(&pState->m_sorted_central_dir_offsets, mz_uint32, 0);
3482
- const int size = pZip->m_total_files;
3483
- const mz_uint filename_len = (mz_uint)strlen(pFilename);
3484
- int l = 0, h = size - 1;
3485
- while (l <= h)
3486
- {
3487
- int m = (l + h) >> 1, file_index = pIndices[m], comp = mz_zip_reader_filename_compare(pCentral_dir, pCentral_dir_offsets, file_index, pFilename, filename_len);
3488
- if (!comp)
3489
- return file_index;
3490
- else if (comp < 0)
3491
- l = m + 1;
3492
- else
3493
- h = m - 1;
3494
- }
3495
- return -1;
3496
-}
3497
-
3498
-int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags)
3499
-{
3500
- mz_uint file_index; size_t name_len, comment_len;
3501
- if ((!pZip) || (!pZip->m_pState) || (!pName) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
3502
- return -1;
3503
- if (((flags & (MZ_ZIP_FLAG_IGNORE_PATH | MZ_ZIP_FLAG_CASE_SENSITIVE)) == 0) && (!pComment) && (pZip->m_pState->m_sorted_central_dir_offsets.m_size))
3504
- return mz_zip_reader_locate_file_binary_search(pZip, pName);
3505
- name_len = strlen(pName); if (name_len > 0xFFFF) return -1;
3506
- comment_len = pComment ? strlen(pComment) : 0; if (comment_len > 0xFFFF) return -1;
3507
- for (file_index = 0; file_index < pZip->m_total_files; file_index++)
3508
- {
3509
- const mz_uint8 *pHeader = &MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index));
3510
- mz_uint filename_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_FILENAME_LEN_OFS);
3511
- const char *pFilename = (const char *)pHeader + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
3512
- if (filename_len < name_len)
3513
- continue;
3514
- if (comment_len)
3515
- {
3516
- mz_uint file_extra_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_EXTRA_LEN_OFS), file_comment_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_COMMENT_LEN_OFS);
3517
- const char *pFile_comment = pFilename + filename_len + file_extra_len;
3518
- if ((file_comment_len != comment_len) || (!mz_zip_reader_string_equal(pComment, pFile_comment, file_comment_len, flags)))
3519
- continue;
3520
- }
3521
- if ((flags & MZ_ZIP_FLAG_IGNORE_PATH) && (filename_len))
3522
- {
3523
- int ofs = filename_len - 1;
3524
- do
3525
- {
3526
- if ((pFilename[ofs] == '/') || (pFilename[ofs] == '\\') || (pFilename[ofs] == ':'))
3527
- break;
3528
- } while (--ofs >= 0);
3529
- ofs++;
3530
- pFilename += ofs; filename_len -= ofs;
3531
- }
3532
- if ((filename_len == name_len) && (mz_zip_reader_string_equal(pName, pFilename, filename_len, flags)))
3533
- return file_index;
3534
- }
3535
- return -1;
3536
-}
3537
-
3538
-mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size)
3539
-{
3540
- int status = TINFL_STATUS_DONE;
3541
- mz_uint64 needed_size, cur_file_ofs, comp_remaining, out_buf_ofs = 0, read_buf_size, read_buf_ofs = 0, read_buf_avail;
3542
- mz_zip_archive_file_stat file_stat;
3543
- void *pRead_buf;
3544
- mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)]; mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
3545
- tinfl_decompressor inflator;
3546
-
3547
- if ((buf_size) && (!pBuf))
3548
- return MZ_FALSE;
3549
-
3550
- if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
3551
- return MZ_FALSE;
3552
-
3553
- // Empty file, or a directory (but not always a directory - I've seen odd zips with directories that have compressed data which inflates to 0 bytes)
3554
- if (!file_stat.m_comp_size)
3555
- return MZ_TRUE;
3556
-
3557
- // Entry is a subdirectory (I've seen old zips with dir entries which have compressed deflate data which inflates to 0 bytes, but these entries claim to uncompress to 512 bytes in the headers).
3558
- // I'm torn how to handle this case - should it fail instead?
3559
- if (mz_zip_reader_is_file_a_directory(pZip, file_index))
3560
- return MZ_TRUE;
3561
-
3562
- // Encryption and patch files are not supported.
3563
- if (file_stat.m_bit_flag & (1 | 32))
3564
- return MZ_FALSE;
3565
-
3566
- // This function only supports stored and deflate.
3567
- if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED))
3568
- return MZ_FALSE;
3569
-
3570
- // Ensure supplied output buffer is large enough.
3571
- needed_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? file_stat.m_comp_size : file_stat.m_uncomp_size;
3572
- if (buf_size < needed_size)
3573
- return MZ_FALSE;
3574
-
3575
- // Read and parse the local directory entry.
3576
- cur_file_ofs = file_stat.m_local_header_ofs;
3577
- if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
3578
- return MZ_FALSE;
3579
- if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
3580
- return MZ_FALSE;
3581
-
3582
- cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
3583
- if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size)
3584
- return MZ_FALSE;
3585
-
3586
- if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method))
3587
- {
3588
- // The file is stored or the caller has requested the compressed data.
3589
- if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, (size_t)needed_size) != needed_size)
3590
- return MZ_FALSE;
3591
- return ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) != 0) || (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, (size_t)file_stat.m_uncomp_size) == file_stat.m_crc32);
3592
- }
3593
-
3594
- // Decompress the file either directly from memory or from a file input buffer.
3595
- tinfl_init(&inflator);
3596
-
3597
- if (pZip->m_pState->m_pMem)
3598
- {
3599
- // Read directly from the archive in memory.
3600
- pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs;
3601
- read_buf_size = read_buf_avail = file_stat.m_comp_size;
3602
- comp_remaining = 0;
3603
- }
3604
- else if (pUser_read_buf)
3605
- {
3606
- // Use a user provided read buffer.
3607
- if (!user_read_buf_size)
3608
- return MZ_FALSE;
3609
- pRead_buf = (mz_uint8 *)pUser_read_buf;
3610
- read_buf_size = user_read_buf_size;
3611
- read_buf_avail = 0;
3612
- comp_remaining = file_stat.m_comp_size;
3613
- }
3614
- else
3615
- {
3616
- // Temporarily allocate a read buffer.
3617
- read_buf_size = MZ_MIN(file_stat.m_comp_size, MZ_ZIP_MAX_IO_BUF_SIZE);
3618
-#ifdef _MSC_VER
3619
- if (((0, sizeof(size_t) == sizeof(mz_uint32))) && (read_buf_size > 0x7FFFFFFF))
3620
-#else
3621
- if (((sizeof(size_t) == sizeof(mz_uint32))) && (read_buf_size > 0x7FFFFFFF))
3622
-#endif
3623
- return MZ_FALSE;
3624
- if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)read_buf_size)))
3625
- return MZ_FALSE;
3626
- read_buf_avail = 0;
3627
- comp_remaining = file_stat.m_comp_size;
3628
- }
3629
-
3630
- do
3631
- {
3632
- size_t in_buf_size, out_buf_size = (size_t)(file_stat.m_uncomp_size - out_buf_ofs);
3633
- if ((!read_buf_avail) && (!pZip->m_pState->m_pMem))
3634
- {
3635
- read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
3636
- if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)
3637
- {
3638
- status = TINFL_STATUS_FAILED;
3639
- break;
3640
- }
3641
- cur_file_ofs += read_buf_avail;
3642
- comp_remaining -= read_buf_avail;
3643
- read_buf_ofs = 0;
3644
- }
3645
- in_buf_size = (size_t)read_buf_avail;
3646
- status = tinfl_decompress(&inflator, (mz_uint8 *)pRead_buf + read_buf_ofs, &in_buf_size, (mz_uint8 *)pBuf, (mz_uint8 *)pBuf + out_buf_ofs, &out_buf_size, TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF | (comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0));
3647
- read_buf_avail -= in_buf_size;
3648
- read_buf_ofs += in_buf_size;
3649
- out_buf_ofs += out_buf_size;
3650
- } while (status == TINFL_STATUS_NEEDS_MORE_INPUT);
3651
-
3652
- if (status == TINFL_STATUS_DONE)
3653
- {
3654
- // Make sure the entire file was decompressed, and check its CRC.
3655
- if ((out_buf_ofs != file_stat.m_uncomp_size) || (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, (size_t)file_stat.m_uncomp_size) != file_stat.m_crc32))
3656
- status = TINFL_STATUS_FAILED;
3657
- }
3658
-
3659
- if ((!pZip->m_pState->m_pMem) && (!pUser_read_buf))
3660
- pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
3661
-
3662
- return status == TINFL_STATUS_DONE;
3663
-}
3664
-
3665
-mz_bool mz_zip_reader_extract_file_to_mem_no_alloc(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size)
3666
-{
3667
- int file_index = mz_zip_reader_locate_file(pZip, pFilename, NULL, flags);
3668
- if (file_index < 0)
3669
- return MZ_FALSE;
3670
- return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size, flags, pUser_read_buf, user_read_buf_size);
3671
-}
3672
-
3673
-mz_bool mz_zip_reader_extract_to_mem(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags)
3674
-{
3675
- return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size, flags, NULL, 0);
3676
-}
3677
-
3678
-mz_bool mz_zip_reader_extract_file_to_mem(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags)
3679
-{
3680
- return mz_zip_reader_extract_file_to_mem_no_alloc(pZip, pFilename, pBuf, buf_size, flags, NULL, 0);
3681
-}
3682
-
3683
-void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index, size_t *pSize, mz_uint flags)
3684
-{
3685
- mz_uint64 comp_size, uncomp_size, alloc_size;
3686
- const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index);
3687
- void *pBuf;
3688
-
3689
- if (pSize)
3690
- *pSize = 0;
3691
- if (!p)
3692
- return NULL;
3693
-
3694
- comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
3695
- uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
3696
-
3697
- alloc_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? comp_size : uncomp_size;
3698
-#ifdef _MSC_VER
3699
- if (((0, sizeof(size_t) == sizeof(mz_uint32))) && (alloc_size > 0x7FFFFFFF))
3700
-#else
3701
- if (((sizeof(size_t) == sizeof(mz_uint32))) && (alloc_size > 0x7FFFFFFF))
3702
-#endif
3703
- return NULL;
3704
- if (NULL == (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)alloc_size)))
3705
- return NULL;
3706
-
3707
- if (!mz_zip_reader_extract_to_mem(pZip, file_index, pBuf, (size_t)alloc_size, flags))
3708
- {
3709
- pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
3710
- return NULL;
3711
- }
3712
-
3713
- if (pSize) *pSize = (size_t)alloc_size;
3714
- return pBuf;
3715
-}
3716
-
3717
-void *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip, const char *pFilename, size_t *pSize, mz_uint flags)
3718
-{
3719
- int file_index = mz_zip_reader_locate_file(pZip, pFilename, NULL, flags);
3720
- if (file_index < 0)
3721
- {
3722
- if (pSize) *pSize = 0;
3723
- return MZ_FALSE;
3724
- }
3725
- return mz_zip_reader_extract_to_heap(pZip, file_index, pSize, flags);
3726
-}
3727
-
3728
-mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip, mz_uint file_index, mz_file_write_func pCallback, void *pOpaque, mz_uint flags)
3729
-{
3730
- int status = TINFL_STATUS_DONE; mz_uint file_crc32 = MZ_CRC32_INIT;
3731
- mz_uint64 read_buf_size, read_buf_ofs = 0, read_buf_avail, comp_remaining, out_buf_ofs = 0, cur_file_ofs;
3732
- mz_zip_archive_file_stat file_stat;
3733
- void *pRead_buf = NULL; void *pWrite_buf = NULL;
3734
- mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)]; mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
3735
-
3736
- if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
3737
- return MZ_FALSE;
3738
-
3739
- // Empty file, or a directory (but not always a directory - I've seen odd zips with directories that have compressed data which inflates to 0 bytes)
3740
- if (!file_stat.m_comp_size)
3741
- return MZ_TRUE;
3742
-
3743
- // Entry is a subdirectory (I've seen old zips with dir entries which have compressed deflate data which inflates to 0 bytes, but these entries claim to uncompress to 512 bytes in the headers).
3744
- // I'm torn how to handle this case - should it fail instead?
3745
- if (mz_zip_reader_is_file_a_directory(pZip, file_index))
3746
- return MZ_TRUE;
3747
-
3748
- // Encryption and patch files are not supported.
3749
- if (file_stat.m_bit_flag & (1 | 32))
3750
- return MZ_FALSE;
3751
-
3752
- // This function only supports stored and deflate.
3753
- if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED))
3754
- return MZ_FALSE;
3755
-
3756
- // Read and parse the local directory entry.
3757
- cur_file_ofs = file_stat.m_local_header_ofs;
3758
- if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
3759
- return MZ_FALSE;
3760
- if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
3761
- return MZ_FALSE;
3762
-
3763
- cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
3764
- if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size)
3765
- return MZ_FALSE;
3766
-
3767
- // Decompress the file either directly from memory or from a file input buffer.
3768
- if (pZip->m_pState->m_pMem)
3769
- {
3770
- pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs;
3771
- read_buf_size = read_buf_avail = file_stat.m_comp_size;
3772
- comp_remaining = 0;
3773
- }
3774
- else
3775
- {
3776
- read_buf_size = MZ_MIN(file_stat.m_comp_size, MZ_ZIP_MAX_IO_BUF_SIZE);
3777
- if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)read_buf_size)))
3778
- return MZ_FALSE;
3779
- read_buf_avail = 0;
3780
- comp_remaining = file_stat.m_comp_size;
3781
- }
3782
-
3783
- if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method))
3784
- {
3785
- // The file is stored or the caller has requested the compressed data.
3786
- if (pZip->m_pState->m_pMem)
3787
- {
3788
-#ifdef _MSC_VER
3789
- if (((0, sizeof(size_t) == sizeof(mz_uint32))) && (file_stat.m_comp_size > 0xFFFFFFFF))
3790
-#else
3791
- if (((sizeof(size_t) == sizeof(mz_uint32))) && (file_stat.m_comp_size > 0xFFFFFFFF))
3792
-#endif
3793
- return MZ_FALSE;
3794
- if (pCallback(pOpaque, out_buf_ofs, pRead_buf, (size_t)file_stat.m_comp_size) != file_stat.m_comp_size)
3795
- status = TINFL_STATUS_FAILED;
3796
- else if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
3797
- file_crc32 = (mz_uint32)mz_crc32(file_crc32, (const mz_uint8 *)pRead_buf, (size_t)file_stat.m_comp_size);
3798
- cur_file_ofs += file_stat.m_comp_size;
3799
- out_buf_ofs += file_stat.m_comp_size;
3800
- comp_remaining = 0;
3801
- }
3802
- else
3803
- {
3804
- while (comp_remaining)
3805
- {
3806
- read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
3807
- if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)
3808
- {
3809
- status = TINFL_STATUS_FAILED;
3810
- break;
3811
- }
3812
-
3813
- if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
3814
- file_crc32 = (mz_uint32)mz_crc32(file_crc32, (const mz_uint8 *)pRead_buf, (size_t)read_buf_avail);
3815
-
3816
- if (pCallback(pOpaque, out_buf_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)
3817
- {
3818
- status = TINFL_STATUS_FAILED;
3819
- break;
3820
- }
3821
- cur_file_ofs += read_buf_avail;
3822
- out_buf_ofs += read_buf_avail;
3823
- comp_remaining -= read_buf_avail;
3824
- }
3825
- }
3826
- }
3827
- else
3828
- {
3829
- tinfl_decompressor inflator;
3830
- tinfl_init(&inflator);
3831
-
3832
- if (NULL == (pWrite_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, TINFL_LZ_DICT_SIZE)))
3833
- status = TINFL_STATUS_FAILED;
3834
- else
3835
- {
3836
- do
3837
- {
3838
- mz_uint8 *pWrite_buf_cur = (mz_uint8 *)pWrite_buf + (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));
3839
- size_t in_buf_size, out_buf_size = TINFL_LZ_DICT_SIZE - (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));
3840
- if ((!read_buf_avail) && (!pZip->m_pState->m_pMem))
3841
- {
3842
- read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
3843
- if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)
3844
- {
3845
- status = TINFL_STATUS_FAILED;
3846
- break;
3847
- }
3848
- cur_file_ofs += read_buf_avail;
3849
- comp_remaining -= read_buf_avail;
3850
- read_buf_ofs = 0;
3851
- }
3852
-
3853
- in_buf_size = (size_t)read_buf_avail;
3854
- status = tinfl_decompress(&inflator, (const mz_uint8 *)pRead_buf + read_buf_ofs, &in_buf_size, (mz_uint8 *)pWrite_buf, pWrite_buf_cur, &out_buf_size, comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0);
3855
- read_buf_avail -= in_buf_size;
3856
- read_buf_ofs += in_buf_size;
3857
-
3858
- if (out_buf_size)
3859
- {
3860
- if (pCallback(pOpaque, out_buf_ofs, pWrite_buf_cur, out_buf_size) != out_buf_size)
3861
- {
3862
- status = TINFL_STATUS_FAILED;
3863
- break;
3864
- }
3865
- file_crc32 = (mz_uint32)mz_crc32(file_crc32, pWrite_buf_cur, out_buf_size);
3866
- if ((out_buf_ofs += out_buf_size) > file_stat.m_uncomp_size)
3867
- {
3868
- status = TINFL_STATUS_FAILED;
3869
- break;
3870
- }
3871
- }
3872
- } while ((status == TINFL_STATUS_NEEDS_MORE_INPUT) || (status == TINFL_STATUS_HAS_MORE_OUTPUT));
3873
- }
3874
- }
3875
-
3876
- if ((status == TINFL_STATUS_DONE) && (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)))
3877
- {
3878
- // Make sure the entire file was decompressed, and check its CRC.
3879
- if ((out_buf_ofs != file_stat.m_uncomp_size) || (file_crc32 != file_stat.m_crc32))
3880
- status = TINFL_STATUS_FAILED;
3881
- }
3882
-
3883
- if (!pZip->m_pState->m_pMem)
3884
- pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
3885
- if (pWrite_buf)
3886
- pZip->m_pFree(pZip->m_pAlloc_opaque, pWrite_buf);
3887
-
3888
- return status == TINFL_STATUS_DONE;
3889
-}
3890
-
3891
-mz_bool mz_zip_reader_extract_file_to_callback(mz_zip_archive *pZip, const char *pFilename, mz_file_write_func pCallback, void *pOpaque, mz_uint flags)
3892
-{
3893
- int file_index = mz_zip_reader_locate_file(pZip, pFilename, NULL, flags);
3894
- if (file_index < 0)
3895
- return MZ_FALSE;
3896
- return mz_zip_reader_extract_to_callback(pZip, file_index, pCallback, pOpaque, flags);
3897
-}
3898
-
3899
-#ifndef MINIZ_NO_STDIO
3900
-static size_t mz_zip_file_write_callback(void *pOpaque, mz_uint64 ofs, const void *pBuf, size_t n)
3901
-{
3902
- (void)ofs; return MZ_FWRITE(pBuf, 1, n, (MZ_FILE*)pOpaque);
3903
-}
3904
-
3905
-mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index, const char *pDst_filename, mz_uint flags)
3906
-{
3907
- mz_bool status;
3908
- mz_zip_archive_file_stat file_stat;
3909
- MZ_FILE *pFile;
3910
- if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
3911
- return MZ_FALSE;
3912
- pFile = MZ_FOPEN(pDst_filename, "wb");
3913
- if (!pFile)
3914
- return MZ_FALSE;
3915
- status = mz_zip_reader_extract_to_callback(pZip, file_index, mz_zip_file_write_callback, pFile, flags);
3916
- if (MZ_FCLOSE(pFile) == EOF)
3917
- return MZ_FALSE;
3918
-#ifndef MINIZ_NO_TIME
3919
- if (status)
3920
- mz_zip_set_file_times(pDst_filename, file_stat.m_time, file_stat.m_time);
3921
-#endif
3922
- return status;
3923
-}
3924
-#endif // #ifndef MINIZ_NO_STDIO
3925
-
3926
-mz_bool mz_zip_reader_end(mz_zip_archive *pZip)
3927
-{
3928
- if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
3929
- return MZ_FALSE;
3930
-
3931
- if (pZip->m_pState)
3932
- {
3933
- mz_zip_internal_state *pState = pZip->m_pState; pZip->m_pState = NULL;
3934
- mz_zip_array_clear(pZip, &pState->m_central_dir);
3935
- mz_zip_array_clear(pZip, &pState->m_central_dir_offsets);
3936
- mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets);
3937
-
3938
-#ifndef MINIZ_NO_STDIO
3939
- if (pState->m_pFile)
3940
- {
3941
- MZ_FCLOSE(pState->m_pFile);
3942
- pState->m_pFile = NULL;
3943
- }
3944
-#endif // #ifndef MINIZ_NO_STDIO
3945
-
3946
- pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
3947
- }
3948
- pZip->m_zip_mode = MZ_ZIP_MODE_INVALID;
3949
-
3950
- return MZ_TRUE;
3951
-}
3952
-
3953
-#ifndef MINIZ_NO_STDIO
3954
-mz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive *pZip, const char *pArchive_filename, const char *pDst_filename, mz_uint flags)
3955
-{
3956
- int file_index = mz_zip_reader_locate_file(pZip, pArchive_filename, NULL, flags);
3957
- if (file_index < 0)
3958
- return MZ_FALSE;
3959
- return mz_zip_reader_extract_to_file(pZip, file_index, pDst_filename, flags);
3960
-}
3961
-#endif
3962
-
3963
-// ------------------- .ZIP archive writing
3964
-
3965
-#ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
3966
-
3967
-static void mz_write_le16(mz_uint8 *p, mz_uint16 v) { p[0] = (mz_uint8)v; p[1] = (mz_uint8)(v >> 8); }
3968
-static void mz_write_le32(mz_uint8 *p, mz_uint32 v) { p[0] = (mz_uint8)v; p[1] = (mz_uint8)(v >> 8); p[2] = (mz_uint8)(v >> 16); p[3] = (mz_uint8)(v >> 24); }
3969
-#define MZ_WRITE_LE16(p, v) mz_write_le16((mz_uint8 *)(p), (mz_uint16)(v))
3970
-#define MZ_WRITE_LE32(p, v) mz_write_le32((mz_uint8 *)(p), (mz_uint32)(v))
3971
-
3972
-mz_bool mz_zip_writer_init(mz_zip_archive *pZip, mz_uint64 existing_size)
3973
-{
3974
- if ((!pZip) || (pZip->m_pState) || (!pZip->m_pWrite) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID))
3975
- return MZ_FALSE;
3976
-
3977
- if (pZip->m_file_offset_alignment)
3978
- {
3979
- // Ensure user specified file offset alignment is a power of 2.
3980
- if (pZip->m_file_offset_alignment & (pZip->m_file_offset_alignment - 1))
3981
- return MZ_FALSE;
3982
- }
3983
-
3984
- if (!pZip->m_pAlloc) pZip->m_pAlloc = def_alloc_func;
3985
- if (!pZip->m_pFree) pZip->m_pFree = def_free_func;
3986
- if (!pZip->m_pRealloc) pZip->m_pRealloc = def_realloc_func;
3987
-
3988
- pZip->m_zip_mode = MZ_ZIP_MODE_WRITING;
3989
- pZip->m_archive_size = existing_size;
3990
- pZip->m_central_directory_file_ofs = 0;
3991
- pZip->m_total_files = 0;
3992
-
3993
- if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state))))
3994
- return MZ_FALSE;
3995
- memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state));
3996
- MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir, sizeof(mz_uint8));
3997
- MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets, sizeof(mz_uint32));
3998
- MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets, sizeof(mz_uint32));
3999
- return MZ_TRUE;
4000
-}
4001
-
4002
-static size_t mz_zip_heap_write_func(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n)
4003
-{
4004
- mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
4005
- mz_zip_internal_state *pState = pZip->m_pState;
4006
- mz_uint64 new_size = MZ_MAX(file_ofs + n, pState->m_mem_size);
4007
-#ifdef _MSC_VER
4008
- if ((!n) || ((0, sizeof(size_t) == sizeof(mz_uint32)) && (new_size > 0x7FFFFFFF)))
4009
-#else
4010
- if ((!n) || ((sizeof(size_t) == sizeof(mz_uint32)) && (new_size > 0x7FFFFFFF)))
4011
-#endif
4012
- return 0;
4013
- if (new_size > pState->m_mem_capacity)
4014
- {
4015
- void *pNew_block;
4016
- size_t new_capacity = MZ_MAX(64, pState->m_mem_capacity); while (new_capacity < new_size) new_capacity *= 2;
4017
- if (NULL == (pNew_block = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pState->m_pMem, 1, new_capacity)))
4018
- return 0;
4019
- pState->m_pMem = pNew_block; pState->m_mem_capacity = new_capacity;
4020
- }
4021
- memcpy((mz_uint8 *)pState->m_pMem + file_ofs, pBuf, n);
4022
- pState->m_mem_size = (size_t)new_size;
4023
- return n;
4024
-}
4025
-
4026
-mz_bool mz_zip_writer_init_heap(mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size)
4027
-{
4028
- pZip->m_pWrite = mz_zip_heap_write_func;
4029
- pZip->m_pIO_opaque = pZip;
4030
- if (!mz_zip_writer_init(pZip, size_to_reserve_at_beginning))
4031
- return MZ_FALSE;
4032
- if (0 != (initial_allocation_size = MZ_MAX(initial_allocation_size, size_to_reserve_at_beginning)))
4033
- {
4034
- if (NULL == (pZip->m_pState->m_pMem = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, initial_allocation_size)))
4035
- {
4036
- mz_zip_writer_end(pZip);
4037
- return MZ_FALSE;
4038
- }
4039
- pZip->m_pState->m_mem_capacity = initial_allocation_size;
4040
- }
4041
- return MZ_TRUE;
4042
-}
4043
-
4044
-#ifndef MINIZ_NO_STDIO
4045
-static size_t mz_zip_file_write_func(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n)
4046
-{
4047
- mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
4048
- mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile);
4049
- if (((mz_int64)file_ofs < 0) || (((cur_ofs != (mz_int64)file_ofs)) && (MZ_FSEEK64(pZip->m_pState->m_pFile, (mz_int64)file_ofs, SEEK_SET))))
4050
- return 0;
4051
- return MZ_FWRITE(pBuf, 1, n, pZip->m_pState->m_pFile);
4052
-}
4053
-
4054
-mz_bool mz_zip_writer_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint64 size_to_reserve_at_beginning)
4055
-{
4056
- MZ_FILE *pFile;
4057
- pZip->m_pWrite = mz_zip_file_write_func;
4058
- pZip->m_pIO_opaque = pZip;
4059
- if (!mz_zip_writer_init(pZip, size_to_reserve_at_beginning))
4060
- return MZ_FALSE;
4061
- if (NULL == (pFile = MZ_FOPEN(pFilename, "wb")))
4062
- {
4063
- mz_zip_writer_end(pZip);
4064
- return MZ_FALSE;
4065
- }
4066
- pZip->m_pState->m_pFile = pFile;
4067
- if (size_to_reserve_at_beginning)
4068
- {
4069
- mz_uint64 cur_ofs = 0; char buf[4096]; MZ_CLEAR_OBJ(buf);
4070
- do
4071
- {
4072
- size_t n = (size_t)MZ_MIN(sizeof(buf), size_to_reserve_at_beginning);
4073
- if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_ofs, buf, n) != n)
4074
- {
4075
- mz_zip_writer_end(pZip);
4076
- return MZ_FALSE;
4077
- }
4078
- cur_ofs += n; size_to_reserve_at_beginning -= n;
4079
- } while (size_to_reserve_at_beginning);
4080
- }
4081
- return MZ_TRUE;
4082
-}
4083
-#endif // #ifndef MINIZ_NO_STDIO
4084
-
4085
-mz_bool mz_zip_writer_init_from_reader(mz_zip_archive *pZip, const char *pFilename)
4086
-{
4087
- mz_zip_internal_state *pState;
4088
- if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
4089
- return MZ_FALSE;
4090
- // No sense in trying to write to an archive that's already at the support max size
4091
- if ((pZip->m_total_files == 0xFFFF) || ((pZip->m_archive_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_ZIP_LOCAL_DIR_HEADER_SIZE) > 0xFFFFFFFF))
4092
- return MZ_FALSE;
4093
-
4094
- pState = pZip->m_pState;
4095
-
4096
- if (pState->m_pFile)
4097
- {
4098
-#ifdef MINIZ_NO_STDIO
4099
- pFilename; return MZ_FALSE;
4100
-#else
4101
- // Archive is being read from stdio - try to reopen as writable.
4102
- if (pZip->m_pIO_opaque != pZip)
4103
- return MZ_FALSE;
4104
- if (!pFilename)
4105
- return MZ_FALSE;
4106
- pZip->m_pWrite = mz_zip_file_write_func;
4107
- if (NULL == (pState->m_pFile = MZ_FREOPEN(pFilename, "r+b", pState->m_pFile)))
4108
- {
4109
- // The mz_zip_archive is now in a bogus state because pState->m_pFile is NULL, so just close it.
4110
- mz_zip_reader_end(pZip);
4111
- return MZ_FALSE;
4112
- }
4113
-#endif // #ifdef MINIZ_NO_STDIO
4114
- }
4115
- else if (pState->m_pMem)
4116
- {
4117
- // Archive lives in a memory block. Assume it's from the heap that we can resize using the realloc callback.
4118
- if (pZip->m_pIO_opaque != pZip)
4119
- return MZ_FALSE;
4120
- pState->m_mem_capacity = pState->m_mem_size;
4121
- pZip->m_pWrite = mz_zip_heap_write_func;
4122
- }
4123
- // Archive is being read via a user provided read function - make sure the user has specified a write function too.
4124
- else if (!pZip->m_pWrite)
4125
- return MZ_FALSE;
4126
-
4127
- // Start writing new files at the archive's current central directory location.
4128
- pZip->m_archive_size = pZip->m_central_directory_file_ofs;
4129
- pZip->m_zip_mode = MZ_ZIP_MODE_WRITING;
4130
- pZip->m_central_directory_file_ofs = 0;
4131
-
4132
- return MZ_TRUE;
4133
-}
4134
-
4135
-mz_bool mz_zip_writer_add_mem(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, mz_uint level_and_flags)
4136
-{
4137
- return mz_zip_writer_add_mem_ex(pZip, pArchive_name, pBuf, buf_size, NULL, 0, level_and_flags, 0, 0);
4138
-}
4139
-
4140
-typedef struct
4141
-{
4142
- mz_zip_archive *m_pZip;
4143
- mz_uint64 m_cur_archive_file_ofs;
4144
- mz_uint64 m_comp_size;
4145
-} mz_zip_writer_add_state;
4146
-
4147
-static mz_bool mz_zip_writer_add_put_buf_callback(const void* pBuf, int len, void *pUser)
4148
-{
4149
- mz_zip_writer_add_state *pState = (mz_zip_writer_add_state *)pUser;
4150
- if ((int)pState->m_pZip->m_pWrite(pState->m_pZip->m_pIO_opaque, pState->m_cur_archive_file_ofs, pBuf, len) != len)
4151
- return MZ_FALSE;
4152
- pState->m_cur_archive_file_ofs += len;
4153
- pState->m_comp_size += len;
4154
- return MZ_TRUE;
4155
-}
4156
-
4157
-static mz_bool mz_zip_writer_create_local_dir_header(mz_zip_archive *pZip, mz_uint8 *pDst, mz_uint16 filename_size, mz_uint16 extra_size, mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date)
4158
-{
4159
- (void)pZip;
4160
- memset(pDst, 0, MZ_ZIP_LOCAL_DIR_HEADER_SIZE);
4161
- MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_SIG_OFS, MZ_ZIP_LOCAL_DIR_HEADER_SIG);
4162
- MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_VERSION_NEEDED_OFS, method ? 20 : 0);
4163
- MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_BIT_FLAG_OFS, bit_flags);
4164
- MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_METHOD_OFS, method);
4165
- MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_TIME_OFS, dos_time);
4166
- MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_DATE_OFS, dos_date);
4167
- MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_CRC32_OFS, uncomp_crc32);
4168
- MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS, comp_size);
4169
- MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS, uncomp_size);
4170
- MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILENAME_LEN_OFS, filename_size);
4171
- MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_EXTRA_LEN_OFS, extra_size);
4172
- return MZ_TRUE;
4173
-}
4174
-
4175
-static mz_bool mz_zip_writer_create_central_dir_header(mz_zip_archive *pZip, mz_uint8 *pDst, mz_uint16 filename_size, mz_uint16 extra_size, mz_uint16 comment_size, mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date, mz_uint64 local_header_ofs, mz_uint32 ext_attributes)
4176
-{
4177
- (void)pZip;
4178
- memset(pDst, 0, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE);
4179
- MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_SIG_OFS, MZ_ZIP_CENTRAL_DIR_HEADER_SIG);
4180
- MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_VERSION_NEEDED_OFS, method ? 20 : 0);
4181
- MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_BIT_FLAG_OFS, bit_flags);
4182
- MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_METHOD_OFS, method);
4183
- MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_TIME_OFS, dos_time);
4184
- MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_DATE_OFS, dos_date);
4185
- MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_CRC32_OFS, uncomp_crc32);
4186
- MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS, comp_size);
4187
- MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS, uncomp_size);
4188
- MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILENAME_LEN_OFS, filename_size);
4189
- MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_EXTRA_LEN_OFS, extra_size);
4190
- MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_COMMENT_LEN_OFS, comment_size);
4191
- MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS, ext_attributes);
4192
- MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_LOCAL_HEADER_OFS, local_header_ofs);
4193
- return MZ_TRUE;
4194
-}
4195
-
4196
-static mz_bool mz_zip_writer_add_to_central_dir(mz_zip_archive *pZip, const char *pFilename, mz_uint16 filename_size, const void *pExtra, mz_uint16 extra_size, const void *pComment, mz_uint16 comment_size, mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date, mz_uint64 local_header_ofs, mz_uint32 ext_attributes)
4197
-{
4198
- mz_zip_internal_state *pState = pZip->m_pState;
4199
- mz_uint32 central_dir_ofs = (mz_uint32)pState->m_central_dir.m_size;
4200
- size_t orig_central_dir_size = pState->m_central_dir.m_size;
4201
- mz_uint8 central_dir_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE];
4202
-
4203
- // No zip64 support yet
4204
- if ((local_header_ofs > 0xFFFFFFFF) || (((mz_uint64)pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size + extra_size + comment_size) > 0xFFFFFFFF))
4205
- return MZ_FALSE;
4206
-
4207
- if (!mz_zip_writer_create_central_dir_header(pZip, central_dir_header, filename_size, extra_size, comment_size, uncomp_size, comp_size, uncomp_crc32, method, bit_flags, dos_time, dos_date, local_header_ofs, ext_attributes))
4208
- return MZ_FALSE;
4209
-
4210
- if ((!mz_zip_array_push_back(pZip, &pState->m_central_dir, central_dir_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)) ||
4211
- (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pFilename, filename_size)) ||
4212
- (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pExtra, extra_size)) ||
4213
- (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pComment, comment_size)) ||
4214
- (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, &central_dir_ofs, 1)))
4215
- {
4216
- // Try to push the central directory array back into its original state.
4217
- mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
4218
- return MZ_FALSE;
4219
- }
4220
-
4221
- return MZ_TRUE;
4222
-}
4223
-
4224
-static mz_bool mz_zip_writer_validate_archive_name(const char *pArchive_name)
4225
-{
4226
- // Basic ZIP archive filename validity checks: Valid filenames cannot start with a forward slash, cannot contain a drive letter, and cannot use DOS-style backward slashes.
4227
- if (*pArchive_name == '/')
4228
- return MZ_FALSE;
4229
- while (*pArchive_name)
4230
- {
4231
- if ((*pArchive_name == '\\') || (*pArchive_name == ':'))
4232
- return MZ_FALSE;
4233
- pArchive_name++;
4234
- }
4235
- return MZ_TRUE;
4236
-}
4237
-
4238
-static mz_uint mz_zip_writer_compute_padding_needed_for_file_alignment(mz_zip_archive *pZip)
4239
-{
4240
- mz_uint32 n;
4241
- if (!pZip->m_file_offset_alignment)
4242
- return 0;
4243
- n = (mz_uint32)(pZip->m_archive_size & (pZip->m_file_offset_alignment - 1));
4244
- return (pZip->m_file_offset_alignment - n) & (pZip->m_file_offset_alignment - 1);
4245
-}
4246
-
4247
-static mz_bool mz_zip_writer_write_zeros(mz_zip_archive *pZip, mz_uint64 cur_file_ofs, mz_uint32 n)
4248
-{
4249
- char buf[4096];
4250
- memset(buf, 0, MZ_MIN(sizeof(buf), n));
4251
- while (n)
4252
- {
4253
- mz_uint32 s = MZ_MIN(sizeof(buf), n);
4254
- if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_file_ofs, buf, s) != s)
4255
- return MZ_FALSE;
4256
- cur_file_ofs += s; n -= s;
4257
- }
4258
- return MZ_TRUE;
4259
-}
4260
-
4261
-mz_bool mz_zip_writer_add_mem_ex(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, mz_uint64 uncomp_size, mz_uint32 uncomp_crc32)
4262
-{
4263
- mz_uint16 method = 0, dos_time = 0, dos_date = 0;
4264
- mz_uint level, ext_attributes = 0, num_alignment_padding_bytes;
4265
- mz_uint64 local_dir_header_ofs = pZip->m_archive_size, cur_archive_file_ofs = pZip->m_archive_size, comp_size = 0;
4266
- size_t archive_name_size;
4267
- mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE];
4268
- tdefl_compressor *pComp = NULL;
4269
- mz_bool store_data_uncompressed;
4270
- mz_zip_internal_state *pState;
4271
-
4272
- if ((int)level_and_flags < 0)
4273
- level_and_flags = MZ_DEFAULT_LEVEL;
4274
- level = level_and_flags & 0xF;
4275
- store_data_uncompressed = ((!level) || (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA));
4276
-
4277
- if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || ((buf_size) && (!pBuf)) || (!pArchive_name) || ((comment_size) && (!pComment)) || (pZip->m_total_files == 0xFFFF) || (level > MZ_UBER_COMPRESSION))
4278
- return MZ_FALSE;
4279
-
4280
- pState = pZip->m_pState;
4281
-
4282
- if ((!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (uncomp_size))
4283
- return MZ_FALSE;
4284
- // No zip64 support yet
4285
- if ((buf_size > 0xFFFFFFFF) || (uncomp_size > 0xFFFFFFFF))
4286
- return MZ_FALSE;
4287
- if (!mz_zip_writer_validate_archive_name(pArchive_name))
4288
- return MZ_FALSE;
4289
-
4290
-#ifndef MINIZ_NO_TIME
4291
- {
4292
- time_t cur_time; time(&cur_time);
4293
- mz_zip_time_to_dos_time(cur_time, &dos_time, &dos_date);
4294
- }
4295
-#endif // #ifndef MINIZ_NO_TIME
4296
-
4297
- archive_name_size = strlen(pArchive_name);
4298
- if (archive_name_size > 0xFFFF)
4299
- return MZ_FALSE;
4300
-
4301
- num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
4302
-
4303
- // no zip64 support yet
4304
- if ((pZip->m_total_files == 0xFFFF) || ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + comment_size + archive_name_size) > 0xFFFFFFFF))
4305
- return MZ_FALSE;
4306
-
4307
- if ((archive_name_size) && (pArchive_name[archive_name_size - 1] == '/'))
4308
- {
4309
- // Set DOS Subdirectory attribute bit.
4310
- ext_attributes |= 0x10;
4311
- // Subdirectories cannot contain data.
4312
- if ((buf_size) || (uncomp_size))
4313
- return MZ_FALSE;
4314
- }
4315
-
4316
- // Try to do any allocations before writing to the archive, so if an allocation fails the file remains unmodified. (A good idea if we're doing an in-place modification.)
4317
- if ((!mz_zip_array_ensure_room(pZip, &pState->m_central_dir, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + comment_size)) || (!mz_zip_array_ensure_room(pZip, &pState->m_central_dir_offsets, 1)))
4318
- return MZ_FALSE;
4319
-
4320
- if ((!store_data_uncompressed) && (buf_size))
4321
- {
4322
- if (NULL == (pComp = (tdefl_compressor *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor))))
4323
- return MZ_FALSE;
4324
- }
4325
-
4326
- if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs, num_alignment_padding_bytes + sizeof(local_dir_header)))
4327
- {
4328
- pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
4329
- return MZ_FALSE;
4330
- }
4331
- local_dir_header_ofs += num_alignment_padding_bytes;
4332
- if (pZip->m_file_offset_alignment) { MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0); }
4333
- cur_archive_file_ofs += num_alignment_padding_bytes + sizeof(local_dir_header);
4334
-
4335
- MZ_CLEAR_OBJ(local_dir_header);
4336
- if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size)
4337
- {
4338
- pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
4339
- return MZ_FALSE;
4340
- }
4341
- cur_archive_file_ofs += archive_name_size;
4342
-
4343
- if (!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
4344
- {
4345
- uncomp_crc32 = (mz_uint32)mz_crc32(MZ_CRC32_INIT, (const mz_uint8*)pBuf, buf_size);
4346
- uncomp_size = buf_size;
4347
- if (uncomp_size <= 3)
4348
- {
4349
- level = 0;
4350
- store_data_uncompressed = MZ_TRUE;
4351
- }
4352
- }
4353
-
4354
- if (store_data_uncompressed)
4355
- {
4356
- if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pBuf, buf_size) != buf_size)
4357
- {
4358
- pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
4359
- return MZ_FALSE;
4360
- }
4361
-
4362
- cur_archive_file_ofs += buf_size;
4363
- comp_size = buf_size;
4364
-
4365
- if (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)
4366
- method = MZ_DEFLATED;
4367
- }
4368
- else if (buf_size)
4369
- {
4370
- mz_zip_writer_add_state state;
4371
-
4372
- state.m_pZip = pZip;
4373
- state.m_cur_archive_file_ofs = cur_archive_file_ofs;
4374
- state.m_comp_size = 0;
4375
-
4376
- if ((tdefl_init(pComp, mz_zip_writer_add_put_buf_callback, &state, tdefl_create_comp_flags_from_zip_params(level, -15, MZ_DEFAULT_STRATEGY)) != TDEFL_STATUS_OKAY) ||
4377
- (tdefl_compress_buffer(pComp, pBuf, buf_size, TDEFL_FINISH) != TDEFL_STATUS_DONE))
4378
- {
4379
- pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
4380
- return MZ_FALSE;
4381
- }
4382
-
4383
- comp_size = state.m_comp_size;
4384
- cur_archive_file_ofs = state.m_cur_archive_file_ofs;
4385
-
4386
- method = MZ_DEFLATED;
4387
- }
4388
-
4389
- pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
4390
- pComp = NULL;
4391
-
4392
- // no zip64 support yet
4393
- if ((comp_size > 0xFFFFFFFF) || (cur_archive_file_ofs > 0xFFFFFFFF))
4394
- return MZ_FALSE;
4395
-
4396
- if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, 0, uncomp_size, comp_size, uncomp_crc32, method, 0, dos_time, dos_date))
4397
- return MZ_FALSE;
4398
-
4399
- if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header))
4400
- return MZ_FALSE;
4401
-
4402
- if (!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, NULL, 0, pComment, comment_size, uncomp_size, comp_size, uncomp_crc32, method, 0, dos_time, dos_date, local_dir_header_ofs, ext_attributes))
4403
- return MZ_FALSE;
4404
-
4405
- pZip->m_total_files++;
4406
- pZip->m_archive_size = cur_archive_file_ofs;
4407
-
4408
- return MZ_TRUE;
4409
-}
4410
-
4411
-#ifndef MINIZ_NO_STDIO
4412
-mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name, const char *pSrc_filename, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags)
4413
-{
4414
- mz_uint uncomp_crc32 = MZ_CRC32_INIT, level, num_alignment_padding_bytes;
4415
- mz_uint16 method = 0, dos_time = 0, dos_date = 0, ext_attributes = 0;
4416
- mz_uint64 local_dir_header_ofs = pZip->m_archive_size, cur_archive_file_ofs = pZip->m_archive_size, uncomp_size = 0, comp_size = 0;
4417
- size_t archive_name_size;
4418
- mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE];
4419
- MZ_FILE *pSrc_file = NULL;
4420
-
4421
- if ((int)level_and_flags < 0)
4422
- level_and_flags = MZ_DEFAULT_LEVEL;
4423
- level = level_and_flags & 0xF;
4424
-
4425
- if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || (!pArchive_name) || ((comment_size) && (!pComment)) || (level > MZ_UBER_COMPRESSION))
4426
- return MZ_FALSE;
4427
- if (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)
4428
- return MZ_FALSE;
4429
- if (!mz_zip_writer_validate_archive_name(pArchive_name))
4430
- return MZ_FALSE;
4431
-
4432
- archive_name_size = strlen(pArchive_name);
4433
- if (archive_name_size > 0xFFFF)
4434
- return MZ_FALSE;
4435
-
4436
- num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
4437
-
4438
- // no zip64 support yet
4439
- if ((pZip->m_total_files == 0xFFFF) || ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + comment_size + archive_name_size) > 0xFFFFFFFF))
4440
- return MZ_FALSE;
4441
-
4442
- if (!mz_zip_get_file_modified_time(pSrc_filename, &dos_time, &dos_date))
4443
- return MZ_FALSE;
4444
-
4445
- pSrc_file = MZ_FOPEN(pSrc_filename, "rb");
4446
- if (!pSrc_file)
4447
- return MZ_FALSE;
4448
- MZ_FSEEK64(pSrc_file, 0, SEEK_END);
4449
- uncomp_size = MZ_FTELL64(pSrc_file);
4450
- MZ_FSEEK64(pSrc_file, 0, SEEK_SET);
4451
-
4452
- if (uncomp_size > 0xFFFFFFFF)
4453
- {
4454
- // No zip64 support yet
4455
- MZ_FCLOSE(pSrc_file);
4456
- return MZ_FALSE;
4457
- }
4458
- if (uncomp_size <= 3)
4459
- level = 0;
4460
-
4461
- if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs, num_alignment_padding_bytes + sizeof(local_dir_header)))
4462
- {
4463
- MZ_FCLOSE(pSrc_file);
4464
- return MZ_FALSE;
4465
- }
4466
- local_dir_header_ofs += num_alignment_padding_bytes;
4467
- if (pZip->m_file_offset_alignment) { MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0); }
4468
- cur_archive_file_ofs += num_alignment_padding_bytes + sizeof(local_dir_header);
4469
-
4470
- MZ_CLEAR_OBJ(local_dir_header);
4471
- if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size)
4472
- {
4473
- MZ_FCLOSE(pSrc_file);
4474
- return MZ_FALSE;
4475
- }
4476
- cur_archive_file_ofs += archive_name_size;
4477
-
4478
- if (uncomp_size)
4479
- {
4480
- mz_uint64 uncomp_remaining = uncomp_size;
4481
- void *pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, MZ_ZIP_MAX_IO_BUF_SIZE);
4482
- if (!pRead_buf)
4483
- {
4484
- MZ_FCLOSE(pSrc_file);
4485
- return MZ_FALSE;
4486
- }
4487
-
4488
- if (!level)
4489
- {
4490
- while (uncomp_remaining)
4491
- {
4492
- mz_uint n = (mz_uint)MZ_MIN(MZ_ZIP_MAX_IO_BUF_SIZE, uncomp_remaining);
4493
- if ((MZ_FREAD(pRead_buf, 1, n, pSrc_file) != n) || (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pRead_buf, n) != n))
4494
- {
4495
- pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
4496
- MZ_FCLOSE(pSrc_file);
4497
- return MZ_FALSE;
4498
- }
4499
- uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, n);
4500
- uncomp_remaining -= n;
4501
- cur_archive_file_ofs += n;
4502
- }
4503
- comp_size = uncomp_size;
4504
- }
4505
- else
4506
- {
4507
- mz_bool result = MZ_FALSE;
4508
- mz_zip_writer_add_state state;
4509
- tdefl_compressor *pComp = (tdefl_compressor *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor));
4510
- if (!pComp)
4511
- {
4512
- pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
4513
- MZ_FCLOSE(pSrc_file);
4514
- return MZ_FALSE;
4515
- }
4516
-
4517
- state.m_pZip = pZip;
4518
- state.m_cur_archive_file_ofs = cur_archive_file_ofs;
4519
- state.m_comp_size = 0;
4520
-
4521
- if (tdefl_init(pComp, mz_zip_writer_add_put_buf_callback, &state, tdefl_create_comp_flags_from_zip_params(level, -15, MZ_DEFAULT_STRATEGY)) != TDEFL_STATUS_OKAY)
4522
- {
4523
- pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
4524
- pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
4525
- MZ_FCLOSE(pSrc_file);
4526
- return MZ_FALSE;
4527
- }
4528
-
4529
- for ( ; ; )
4530
- {
4531
- size_t in_buf_size = (mz_uint32)MZ_MIN(uncomp_remaining, MZ_ZIP_MAX_IO_BUF_SIZE);
4532
- tdefl_status status;
4533
-
4534
- if (MZ_FREAD(pRead_buf, 1, in_buf_size, pSrc_file) != in_buf_size)
4535
- break;
4536
-
4537
- uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, in_buf_size);
4538
- uncomp_remaining -= in_buf_size;
4539
-
4540
- status = tdefl_compress_buffer(pComp, pRead_buf, in_buf_size, uncomp_remaining ? TDEFL_NO_FLUSH : TDEFL_FINISH);
4541
- if (status == TDEFL_STATUS_DONE)
4542
- {
4543
- result = MZ_TRUE;
4544
- break;
4545
- }
4546
- else if (status != TDEFL_STATUS_OKAY)
4547
- break;
4548
- }
4549
-
4550
- pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
4551
-
4552
- if (!result)
4553
- {
4554
- pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
4555
- MZ_FCLOSE(pSrc_file);
4556
- return MZ_FALSE;
4557
- }
4558
-
4559
- comp_size = state.m_comp_size;
4560
- cur_archive_file_ofs = state.m_cur_archive_file_ofs;
4561
-
4562
- method = MZ_DEFLATED;
4563
- }
4564
-
4565
- pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
4566
- }
4567
-
4568
- MZ_FCLOSE(pSrc_file); pSrc_file = NULL;
4569
-
4570
- // no zip64 support yet
4571
- if ((comp_size > 0xFFFFFFFF) || (cur_archive_file_ofs > 0xFFFFFFFF))
4572
- return MZ_FALSE;
4573
-
4574
- if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, 0, uncomp_size, comp_size, uncomp_crc32, method, 0, dos_time, dos_date))
4575
- return MZ_FALSE;
4576
-
4577
- if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header))
4578
- return MZ_FALSE;
4579
-
4580
- if (!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, NULL, 0, pComment, comment_size, uncomp_size, comp_size, uncomp_crc32, method, 0, dos_time, dos_date, local_dir_header_ofs, ext_attributes))
4581
- return MZ_FALSE;
4582
-
4583
- pZip->m_total_files++;
4584
- pZip->m_archive_size = cur_archive_file_ofs;
4585
-
4586
- return MZ_TRUE;
4587
-}
4588
-#endif // #ifndef MINIZ_NO_STDIO
4589
-
4590
-mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive *pSource_zip, mz_uint file_index)
4591
-{
4592
- mz_uint n, bit_flags, num_alignment_padding_bytes;
4593
- mz_uint64 comp_bytes_remaining, local_dir_header_ofs;
4594
- mz_uint64 cur_src_file_ofs, cur_dst_file_ofs;
4595
- mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)]; mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
4596
- mz_uint8 central_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE];
4597
- size_t orig_central_dir_size;
4598
- mz_zip_internal_state *pState;
4599
- void *pBuf; const mz_uint8 *pSrc_central_header;
4600
-
4601
- if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING))
4602
- return MZ_FALSE;
4603
- if (NULL == (pSrc_central_header = mz_zip_reader_get_cdh(pSource_zip, file_index)))
4604
- return MZ_FALSE;
4605
- pState = pZip->m_pState;
4606
-
4607
- num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
4608
-
4609
- // no zip64 support yet
4610
- if ((pZip->m_total_files == 0xFFFF) || ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) > 0xFFFFFFFF))
4611
- return MZ_FALSE;
4612
-
4613
- cur_src_file_ofs = MZ_READ_LE32(pSrc_central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS);
4614
- cur_dst_file_ofs = pZip->m_archive_size;
4615
-
4616
- if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
4617
- return MZ_FALSE;
4618
- if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
4619
- return MZ_FALSE;
4620
- cur_src_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE;
4621
-
4622
- if (!mz_zip_writer_write_zeros(pZip, cur_dst_file_ofs, num_alignment_padding_bytes))
4623
- return MZ_FALSE;
4624
- cur_dst_file_ofs += num_alignment_padding_bytes;
4625
- local_dir_header_ofs = cur_dst_file_ofs;
4626
- if (pZip->m_file_offset_alignment) { MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0); }
4627
-
4628
- if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
4629
- return MZ_FALSE;
4630
- cur_dst_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE;
4631
-
4632
- n = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
4633
- comp_bytes_remaining = n + MZ_READ_LE32(pSrc_central_header + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
4634
-
4635
- if (NULL == (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)MZ_MAX(sizeof(mz_uint32) * 4, MZ_MIN(MZ_ZIP_MAX_IO_BUF_SIZE, comp_bytes_remaining)))))
4636
- return MZ_FALSE;
4637
-
4638
- while (comp_bytes_remaining)
4639
- {
4640
- n = (mz_uint)MZ_MIN(MZ_ZIP_MAX_IO_BUF_SIZE, comp_bytes_remaining);
4641
- if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, n) != n)
4642
- {
4643
- pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
4644
- return MZ_FALSE;
4645
- }
4646
- cur_src_file_ofs += n;
4647
-
4648
- if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n)
4649
- {
4650
- pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
4651
- return MZ_FALSE;
4652
- }
4653
- cur_dst_file_ofs += n;
4654
-
4655
- comp_bytes_remaining -= n;
4656
- }
4657
-
4658
- bit_flags = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_BIT_FLAG_OFS);
4659
- if (bit_flags & 8)
4660
- {
4661
- // Copy data descriptor
4662
- if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, sizeof(mz_uint32) * 4) != sizeof(mz_uint32) * 4)
4663
- {
4664
- pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
4665
- return MZ_FALSE;
4666
- }
4667
-
4668
- n = sizeof(mz_uint32) * ((MZ_READ_LE32(pBuf) == 0x08074b50) ? 4 : 3);
4669
- if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n)
4670
- {
4671
- pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
4672
- return MZ_FALSE;
4673
- }
4674
-
4675
- cur_src_file_ofs += n;
4676
- cur_dst_file_ofs += n;
4677
- }
4678
- pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
4679
-
4680
- // no zip64 support yet
4681
- if (cur_dst_file_ofs > 0xFFFFFFFF)
4682
- return MZ_FALSE;
4683
-
4684
- orig_central_dir_size = pState->m_central_dir.m_size;
4685
-
4686
- memcpy(central_header, pSrc_central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE);
4687
- MZ_WRITE_LE32(central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS, local_dir_header_ofs);
4688
- if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE))
4689
- return MZ_FALSE;
4690
-
4691
- n = MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_EXTRA_LEN_OFS) + MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_COMMENT_LEN_OFS);
4692
- if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n))
4693
- {
4694
- mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
4695
- return MZ_FALSE;
4696
- }
4697
-
4698
- if (pState->m_central_dir.m_size > 0xFFFFFFFF)
4699
- return MZ_FALSE;
4700
- n = (mz_uint32)orig_central_dir_size;
4701
- if (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, &n, 1))
4702
- {
4703
- mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
4704
- return MZ_FALSE;
4705
- }
4706
-
4707
- pZip->m_total_files++;
4708
- pZip->m_archive_size = cur_dst_file_ofs;
4709
-
4710
- return MZ_TRUE;
4711
-}
4712
-
4713
-mz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip)
4714
-{
4715
- mz_zip_internal_state *pState;
4716
- mz_uint64 central_dir_ofs, central_dir_size;
4717
- mz_uint8 hdr[MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE];
4718
-
4719
- if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING))
4720
- return MZ_FALSE;
4721
-
4722
- pState = pZip->m_pState;
4723
-
4724
- // no zip64 support yet
4725
- if ((pZip->m_total_files > 0xFFFF) || ((pZip->m_archive_size + pState->m_central_dir.m_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) > 0xFFFFFFFF))
4726
- return MZ_FALSE;
4727
-
4728
- central_dir_ofs = 0;
4729
- central_dir_size = 0;
4730
- if (pZip->m_total_files)
4731
- {
4732
- // Write central directory
4733
- central_dir_ofs = pZip->m_archive_size;
4734
- central_dir_size = pState->m_central_dir.m_size;
4735
- pZip->m_central_directory_file_ofs = central_dir_ofs;
4736
- if (pZip->m_pWrite(pZip->m_pIO_opaque, central_dir_ofs, pState->m_central_dir.m_p, (size_t)central_dir_size) != central_dir_size)
4737
- return MZ_FALSE;
4738
- pZip->m_archive_size += central_dir_size;
4739
- }
4740
-
4741
- // Write end of central directory record
4742
- MZ_CLEAR_OBJ(hdr);
4743
- MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_SIG_OFS, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG);
4744
- MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS, pZip->m_total_files);
4745
- MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS, pZip->m_total_files);
4746
- MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_SIZE_OFS, central_dir_size);
4747
- MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_OFS_OFS, central_dir_ofs);
4748
-
4749
- if (pZip->m_pWrite(pZip->m_pIO_opaque, pZip->m_archive_size, hdr, sizeof(hdr)) != sizeof(hdr))
4750
- return MZ_FALSE;
4751
-#ifndef MINIZ_NO_STDIO
4752
- if ((pState->m_pFile) && (MZ_FFLUSH(pState->m_pFile) == EOF))
4753
- return MZ_FALSE;
4754
-#endif // #ifndef MINIZ_NO_STDIO
4755
-
4756
- pZip->m_archive_size += sizeof(hdr);
4757
-
4758
- pZip->m_zip_mode = MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED;
4759
- return MZ_TRUE;
4760
-}
4761
-
4762
-mz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive *pZip, void **pBuf, size_t *pSize)
4763
-{
4764
- if ((!pZip) || (!pZip->m_pState) || (!pBuf) || (!pSize))
4765
- return MZ_FALSE;
4766
- if (pZip->m_pWrite != mz_zip_heap_write_func)
4767
- return MZ_FALSE;
4768
- if (!mz_zip_writer_finalize_archive(pZip))
4769
- return MZ_FALSE;
4770
-
4771
- *pBuf = pZip->m_pState->m_pMem;
4772
- *pSize = pZip->m_pState->m_mem_size;
4773
- pZip->m_pState->m_pMem = NULL;
4774
- pZip->m_pState->m_mem_size = pZip->m_pState->m_mem_capacity = 0;
4775
- return MZ_TRUE;
4776
-}
4777
-
4778
-mz_bool mz_zip_writer_end(mz_zip_archive *pZip)
4779
-{
4780
- mz_zip_internal_state *pState;
4781
- mz_bool status = MZ_TRUE;
4782
- if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || ((pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) && (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED)))
4783
- return MZ_FALSE;
4784
-
4785
- pState = pZip->m_pState;
4786
- pZip->m_pState = NULL;
4787
- mz_zip_array_clear(pZip, &pState->m_central_dir);
4788
- mz_zip_array_clear(pZip, &pState->m_central_dir_offsets);
4789
- mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets);
4790
-
4791
-#ifndef MINIZ_NO_STDIO
4792
- if (pState->m_pFile)
4793
- {
4794
- MZ_FCLOSE(pState->m_pFile);
4795
- pState->m_pFile = NULL;
4796
- }
4797
-#endif // #ifndef MINIZ_NO_STDIO
4798
-
4799
- if ((pZip->m_pWrite == mz_zip_heap_write_func) && (pState->m_pMem))
4800
- {
4801
- pZip->m_pFree(pZip->m_pAlloc_opaque, pState->m_pMem);
4802
- pState->m_pMem = NULL;
4803
- }
4804
-
4805
- pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
4806
- pZip->m_zip_mode = MZ_ZIP_MODE_INVALID;
4807
- return status;
4808
-}
4809
-
4810
-#ifndef MINIZ_NO_STDIO
4811
-mz_bool mz_zip_add_mem_to_archive_file_in_place(const char *pZip_filename, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags)
4812
-{
4813
- mz_bool status, created_new_archive = MZ_FALSE;
4814
- mz_zip_archive zip_archive;
4815
- struct MZ_FILE_STAT_STRUCT file_stat;
4816
- MZ_CLEAR_OBJ(zip_archive);
4817
- if ((int)level_and_flags < 0)
4818
- level_and_flags = MZ_DEFAULT_LEVEL;
4819
- if ((!pZip_filename) || (!pArchive_name) || ((buf_size) && (!pBuf)) || ((comment_size) && (!pComment)) || ((level_and_flags & 0xF) > MZ_UBER_COMPRESSION))
4820
- return MZ_FALSE;
4821
- if (!mz_zip_writer_validate_archive_name(pArchive_name))
4822
- return MZ_FALSE;
4823
- if (MZ_FILE_STAT(pZip_filename, &file_stat) != 0)
4824
- {
4825
- // Create a new archive.
4826
- if (!mz_zip_writer_init_file(&zip_archive, pZip_filename, 0))
4827
- return MZ_FALSE;
4828
- created_new_archive = MZ_TRUE;
4829
- }
4830
- else
4831
- {
4832
- // Append to an existing archive.
4833
- if (!mz_zip_reader_init_file(&zip_archive, pZip_filename, level_and_flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY))
4834
- return MZ_FALSE;
4835
- if (!mz_zip_writer_init_from_reader(&zip_archive, pZip_filename))
4836
- {
4837
- mz_zip_reader_end(&zip_archive);
4838
- return MZ_FALSE;
4839
- }
4840
- }
4841
- status = mz_zip_writer_add_mem_ex(&zip_archive, pArchive_name, pBuf, buf_size, pComment, comment_size, level_and_flags, 0, 0);
4842
- // Always finalize, even if adding failed for some reason, so we have a valid central directory. (This may not always succeed, but we can try.)
4843
- if (!mz_zip_writer_finalize_archive(&zip_archive))
4844
- status = MZ_FALSE;
4845
- if (!mz_zip_writer_end(&zip_archive))
4846
- status = MZ_FALSE;
4847
- if ((!status) && (created_new_archive))
4848
- {
4849
- // It's a new archive and something went wrong, so just delete it.
4850
- int ignoredStatus = MZ_DELETE_FILE(pZip_filename);
4851
- (void)ignoredStatus;
4852
- }
4853
- return status;
4854
-}
4855
-
4856
-void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const char *pArchive_name, size_t *pSize, mz_uint flags)
4857
-{
4858
- int file_index;
4859
- mz_zip_archive zip_archive;
4860
- void *p = NULL;
4861
-
4862
- if (pSize)
4863
- *pSize = 0;
4864
-
4865
- if ((!pZip_filename) || (!pArchive_name))
4866
- return NULL;
4867
-
4868
- MZ_CLEAR_OBJ(zip_archive);
4869
- if (!mz_zip_reader_init_file(&zip_archive, pZip_filename, flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY))
4870
- return NULL;
4871
-
4872
- if ((file_index = mz_zip_reader_locate_file(&zip_archive, pArchive_name, NULL, flags)) >= 0)
4873
- p = mz_zip_reader_extract_to_heap(&zip_archive, file_index, pSize, flags);
4874
-
4875
- mz_zip_reader_end(&zip_archive);
4876
- return p;
4877
-}
4878
-
4879
-#endif // #ifndef MINIZ_NO_STDIO
4880
-
4881
-#endif // #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
4882
-
4883
-#endif // #ifndef MINIZ_NO_ARCHIVE_APIS
4884
-
4885
-#ifdef __cplusplus
4886
-}
4887
-#endif
4888
-
4889
-#endif // MINIZ_HEADER_FILE_ONLY
4890
-
4891
-/*
4892
- This is free and unencumbered software released into the public domain.
4893
-
4894
- Anyone is free to copy, modify, publish, use, compile, sell, or
4895
- distribute this software, either in source code form or as a compiled
4896
- binary, for any purpose, commercial or non-commercial, and by any
4897
- means.
4898
-
4899
- In jurisdictions that recognize copyright laws, the author or authors
4900
- of this software dedicate any and all copyright interest in the
4901
- software to the public domain. We make this dedication for the benefit
4902
- of the public at large and to the detriment of our heirs and
4903
- successors. We intend this dedication to be an overt act of
4904
- relinquishment in perpetuity of all present and future rights to this
4905
- software under copyright law.
4906
-
4907
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
4908
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
4909
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
4910
- IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
4911
- OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
4912
- ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
4913
- OTHER DEALINGS IN THE SOFTWARE.
4914
-
4915
- For more information, please refer to <http://unlicense.org/>
4916
-*/
--- a/src/miniz.c
+++ b/src/miniz.c
@@ -1,4916 +0,0 @@
1 /* miniz.c v1.15 - public domain deflate/inflate, zlib-subset, ZIP reading/writing/appending, PNG writing
2 See "unlicense" statement at the end of this file.
3 Rich Geldreich <[email protected]>, last updated Oct. 13, 2013
4 Implements RFC 1950: http://www.ietf.org/rfc/rfc1950.txt and RFC 1951: http://www.ietf.org/rfc/rfc1951.txt
5
6 Most API's defined in miniz.c are optional. For example, to disable the archive related functions just define
7 MINIZ_NO_ARCHIVE_APIS, or to get rid of all stdio usage define MINIZ_NO_STDIO (see the list below for more macros).
8
9 * Change History
10 10/13/13 v1.15 r4 - Interim bugfix release while I work on the next major release with Zip64 support (almost there!):
11 - Critical fix for the MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY bug (thanks [email protected]) which could cause locate files to not find files. This bug
12 would only have occured in earlier versions if you explicitly used this flag, OR if you used mz_zip_extract_archive_file_to_heap() or mz_zip_add_mem_to_archive_file_in_place()
13 (which used this flag). If you can't switch to v1.15 but want to fix this bug, just remove the uses of this flag from both helper funcs (and of course don't use the flag).
14 - Bugfix in mz_zip_reader_extract_to_mem_no_alloc() from kymoon when pUser_read_buf is not NULL and compressed size is > uncompressed size
15 - Fixing mz_zip_reader_extract_*() funcs so they don't try to extract compressed data from directory entries, to account for weird zipfiles which contain zero-size compressed data on dir entries.
16 Hopefully this fix won't cause any issues on weird zip archives, because it assumes the low 16-bits of zip external attributes are DOS attributes (which I believe they always are in practice).
17 - Fixing mz_zip_reader_is_file_a_directory() so it doesn't check the internal attributes, just the filename and external attributes
18 - mz_zip_reader_init_file() - missing MZ_FCLOSE() call if the seek failed
19 - Added cmake support for Linux builds which builds all the examples, tested with clang v3.3 and gcc v4.6.
20 - Clang fix for tdefl_write_image_to_png_file_in_memory() from toffaletti
21 - Merged MZ_FORCEINLINE fix from hdeanclark
22 - Fix <time.h> include before config #ifdef, thanks emil.brink
23 - Added tdefl_write_image_to_png_file_in_memory_ex(): supports Y flipping (super useful for OpenGL apps), and explicit control over the compression level (so you can
24 set it to 1 for real-time compression).
25 - Merged in some compiler fixes from paulharris's github repro.
26 - Retested this build under Windows (VS 2010, including static analysis), tcc 0.9.26, gcc v4.6 and clang v3.3.
27 - Added example6.c, which dumps an image of the mandelbrot set to a PNG file.
28 - Modified example2 to help test the MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY flag more.
29 - In r3: Bugfix to mz_zip_writer_add_file() found during merge: Fix possible src file fclose() leak if alignment bytes+local header file write faiiled
30 - In r4: Minor bugfix to mz_zip_writer_add_from_zip_reader(): Was pushing the wrong central dir header offset, appears harmless in this release, but it became a problem in the zip64 branch
31 5/20/12 v1.14 - MinGW32/64 GCC 4.6.1 compiler fixes: added MZ_FORCEINLINE, #include <time.h> (thanks fermtect).
32 5/19/12 v1.13 - From [email protected] and [email protected] - Fix mz_crc32() so it doesn't compute the wrong CRC-32's when mz_ulong is 64-bit.
33 - Temporarily/locally slammed in "typedef unsigned long mz_ulong" and re-ran a randomized regression test on ~500k files.
34 - Eliminated a bunch of warnings when compiling with GCC 32-bit/64.
35 - Ran all examples, miniz.c, and tinfl.c through MSVC 2008's /analyze (static analysis) option and fixed all warnings (except for the silly
36 "Use of the comma-operator in a tested expression.." analysis warning, which I purposely use to work around a MSVC compiler warning).
37 - Created 32-bit and 64-bit Codeblocks projects/workspace. Built and tested Linux executables. The codeblocks workspace is compatible with Linux+Win32/x64.
38 - Added miniz_tester solution/project, which is a useful little app derived from LZHAM's tester app that I use as part of the regression test.
39 - Ran miniz.c and tinfl.c through another series of regression testing on ~500,000 files and archives.
40 - Modified example5.c so it purposely disables a bunch of high-level functionality (MINIZ_NO_STDIO, etc.). (Thanks to corysama for the MINIZ_NO_STDIO bug report.)
41 - Fix ftell() usage in examples so they exit with an error on files which are too large (a limitation of the examples, not miniz itself).
42 4/12/12 v1.12 - More comments, added low-level example5.c, fixed a couple minor level_and_flags issues in the archive API's.
43 level_and_flags can now be set to MZ_DEFAULT_COMPRESSION. Thanks to Bruce Dawson <[email protected]> for the feedback/bug report.
44 5/28/11 v1.11 - Added statement from unlicense.org
45 5/27/11 v1.10 - Substantial compressor optimizations:
46 - Level 1 is now ~4x faster than before. The L1 compressor's throughput now varies between 70-110MB/sec. on a
47 - Core i7 (actual throughput varies depending on the type of data, and x64 vs. x86).
48 - Improved baseline L2-L9 compression perf. Also, greatly improved compression perf. issues on some file types.
49 - Refactored the compression code for better readability and maintainability.
50 - Added level 10 compression level (L10 has slightly better ratio than level 9, but could have a potentially large
51 drop in throughput on some files).
52 5/15/11 v1.09 - Initial stable release.
53
54 * Low-level Deflate/Inflate implementation notes:
55
56 Compression: Use the "tdefl" API's. The compressor supports raw, static, and dynamic blocks, lazy or
57 greedy parsing, match length filtering, RLE-only, and Huffman-only streams. It performs and compresses
58 approximately as well as zlib.
59
60 Decompression: Use the "tinfl" API's. The entire decompressor is implemented as a single function
61 coroutine: see tinfl_decompress(). It supports decompression into a 32KB (or larger power of 2) wrapping buffer, or into a memory
62 block large enough to hold the entire file.
63
64 The low-level tdefl/tinfl API's do not make any use of dynamic memory allocation.
65
66 * zlib-style API notes:
67
68 miniz.c implements a fairly large subset of zlib. There's enough functionality present for it to be a drop-in
69 zlib replacement in many apps:
70 The z_stream struct, optional memory allocation callbacks
71 deflateInit/deflateInit2/deflate/deflateReset/deflateEnd/deflateBound
72 inflateInit/inflateInit2/inflate/inflateEnd
73 compress, compress2, compressBound, uncompress
74 CRC-32, Adler-32 - Using modern, minimal code size, CPU cache friendly routines.
75 Supports raw deflate streams or standard zlib streams with adler-32 checking.
76
77 Limitations:
78 The callback API's are not implemented yet. No support for gzip headers or zlib static dictionaries.
79 I've tried to closely emulate zlib's various flavors of stream flushing and return status codes, but
80 there are no guarantees that miniz.c pulls this off perfectly.
81
82 * PNG writing: See the tdefl_write_image_to_png_file_in_memory() function, originally written by
83 Alex Evans. Supports 1-4 bytes/pixel images.
84
85 * ZIP archive API notes:
86
87 The ZIP archive API's where designed with simplicity and efficiency in mind, with just enough abstraction to
88 get the job done with minimal fuss. There are simple API's to retrieve file information, read files from
89 existing archives, create new archives, append new files to existing archives, or clone archive data from
90 one archive to another. It supports archives located in memory or the heap, on disk (using stdio.h),
91 or you can specify custom file read/write callbacks.
92
93 - Archive reading: Just call this function to read a single file from a disk archive:
94
95 void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const char *pArchive_name,
96 size_t *pSize, mz_uint zip_flags);
97
98 For more complex cases, use the "mz_zip_reader" functions. Upon opening an archive, the entire central
99 directory is located and read as-is into memory, and subsequent file access only occurs when reading individual files.
100
101 - Archives file scanning: The simple way is to use this function to scan a loaded archive for a specific file:
102
103 int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags);
104
105 The locate operation can optionally check file comments too, which (as one example) can be used to identify
106 multiple versions of the same file in an archive. This function uses a simple linear search through the central
107 directory, so it's not very fast.
108
109 Alternately, you can iterate through all the files in an archive (using mz_zip_reader_get_num_files()) and
110 retrieve detailed info on each file by calling mz_zip_reader_file_stat().
111
112 - Archive creation: Use the "mz_zip_writer" functions. The ZIP writer immediately writes compressed file data
113 to disk and builds an exact image of the central directory in memory. The central directory image is written
114 all at once at the end of the archive file when the archive is finalized.
115
116 The archive writer can optionally align each file's local header and file data to any power of 2 alignment,
117 which can be useful when the archive will be read from optical media. Also, the writer supports placing
118 arbitrary data blobs at the very beginning of ZIP archives. Archives written using either feature are still
119 readable by any ZIP tool.
120
121 - Archive appending: The simple way to add a single file to an archive is to call this function:
122
123 mz_bool mz_zip_add_mem_to_archive_file_in_place(const char *pZip_filename, const char *pArchive_name,
124 const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags);
125
126 The archive will be created if it doesn't already exist, otherwise it'll be appended to.
127 Note the appending is done in-place and is not an atomic operation, so if something goes wrong
128 during the operation it's possible the archive could be left without a central directory (although the local
129 file headers and file data will be fine, so the archive will be recoverable).
130
131 For more complex archive modification scenarios:
132 1. The safest way is to use a mz_zip_reader to read the existing archive, cloning only those bits you want to
133 preserve into a new archive using using the mz_zip_writer_add_from_zip_reader() function (which compiles the
134 compressed file data as-is). When you're done, delete the old archive and rename the newly written archive, and
135 you're done. This is safe but requires a bunch of temporary disk space or heap memory.
136
137 2. Or, you can convert an mz_zip_reader in-place to an mz_zip_writer using mz_zip_writer_init_from_reader(),
138 append new files as needed, then finalize the archive which will write an updated central directory to the
139 original archive. (This is basically what mz_zip_add_mem_to_archive_file_in_place() does.) There's a
140 possibility that the archive's central directory could be lost with this method if anything goes wrong, though.
141
142 - ZIP archive support limitations:
143 No zip64 or spanning support. Extraction functions can only handle unencrypted, stored or deflated files.
144 Requires streams capable of seeking.
145
146 * This is a header file library, like stb_image.c. To get only a header file, either cut and paste the
147 below header, or create miniz.h, #define MINIZ_HEADER_FILE_ONLY, and then include miniz.c from it.
148
149 * Important: For best perf. be sure to customize the below macros for your target platform:
150 #define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 1
151 #define MINIZ_LITTLE_ENDIAN 1
152 #define MINIZ_HAS_64BIT_REGISTERS 1
153
154 * On platforms using glibc, Be sure to "#define _LARGEFILE64_SOURCE 1" before including miniz.c to ensure miniz
155 uses the 64-bit variants: fopen64(), stat64(), etc. Otherwise you won't be able to process large files
156 (i.e. 32-bit stat() fails for me on files > 0x7FFFFFFF bytes).
157 */
158
159 #ifndef MINIZ_HEADER_INCLUDED
160 #define MINIZ_HEADER_INCLUDED
161
162 #include <stdlib.h>
163
164 // Defines to completely disable specific portions of miniz.c:
165 // If all macros here are defined the only functionality remaining will be CRC-32, adler-32, tinfl, and tdefl.
166
167 // Define MINIZ_NO_STDIO to disable all usage and any functions which rely on stdio for file I/O.
168 //#define MINIZ_NO_STDIO
169
170 // If MINIZ_NO_TIME is specified then the ZIP archive functions will not be able to get the current time, or
171 // get/set file times, and the C run-time funcs that get/set times won't be called.
172 // The current downside is the times written to your archives will be from 1979.
173 //#define MINIZ_NO_TIME
174
175 // Define MINIZ_NO_ARCHIVE_APIS to disable all ZIP archive API's.
176 //#define MINIZ_NO_ARCHIVE_APIS
177
178 // Define MINIZ_NO_ARCHIVE_APIS to disable all writing related ZIP archive API's.
179 //#define MINIZ_NO_ARCHIVE_WRITING_APIS
180
181 // Define MINIZ_NO_ZLIB_APIS to remove all ZLIB-style compression/decompression API's.
182 //#define MINIZ_NO_ZLIB_APIS
183
184 // Define MINIZ_NO_ZLIB_COMPATIBLE_NAME to disable zlib names, to prevent conflicts against stock zlib.
185 //#define MINIZ_NO_ZLIB_COMPATIBLE_NAMES
186
187 // Define MINIZ_NO_MALLOC to disable all calls to malloc, free, and realloc.
188 // Note if MINIZ_NO_MALLOC is defined then the user must always provide custom user alloc/free/realloc
189 // callbacks to the zlib and archive API's, and a few stand-alone helper API's which don't provide custom user
190 // functions (such as tdefl_compress_mem_to_heap() and tinfl_decompress_mem_to_heap()) won't work.
191 //#define MINIZ_NO_MALLOC
192
193 #if defined(__TINYC__) && (defined(__linux) || defined(__linux__))
194 // TODO: Work around "error: include file 'sys\utime.h' when compiling with tcc on Linux
195 #define MINIZ_NO_TIME
196 #endif
197
198 #if !defined(MINIZ_NO_TIME) && !defined(MINIZ_NO_ARCHIVE_APIS)
199 #include <time.h>
200 #endif
201
202 #if defined(_M_IX86) || defined(_M_X64) || defined(__i386__) || defined(__i386) || defined(__i486__) || defined(__i486) || defined(i386) || defined(__ia64__) || defined(__x86_64__)
203 // MINIZ_X86_OR_X64_CPU is only used to help set the below macros.
204 #define MINIZ_X86_OR_X64_CPU 1
205 #endif
206
207 #if (__BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__) || MINIZ_X86_OR_X64_CPU
208 // Set MINIZ_LITTLE_ENDIAN to 1 if the processor is little endian.
209 #define MINIZ_LITTLE_ENDIAN 1
210 #endif
211
212 #if MINIZ_X86_OR_X64_CPU
213 // Set MINIZ_USE_UNALIGNED_LOADS_AND_STORES to 1 on CPU's that permit efficient integer loads and stores from unaligned addresses.
214 #define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 1
215 #endif
216
217 #if defined(_M_X64) || defined(_WIN64) || defined(__MINGW64__) || defined(_LP64) || defined(__LP64__) || defined(__ia64__) || defined(__x86_64__)
218 // Set MINIZ_HAS_64BIT_REGISTERS to 1 if operations on 64-bit integers are reasonably fast (and don't involve compiler generated calls to helper functions).
219 #define MINIZ_HAS_64BIT_REGISTERS 1
220 #endif
221
222 #ifdef __cplusplus
223 extern "C" {
224 #endif
225
226 // ------------------- zlib-style API Definitions.
227
228 // For more compatibility with zlib, miniz.c uses unsigned long for some parameters/struct members. Beware: mz_ulong can be either 32 or 64-bits!
229 typedef unsigned long mz_ulong;
230
231 // mz_free() internally uses the MZ_FREE() macro (which by default calls free() unless you've modified the MZ_MALLOC macro) to release a block allocated from the heap.
232 void mz_free(void *p);
233
234 #define MZ_ADLER32_INIT (1)
235 // mz_adler32() returns the initial adler-32 value to use when called with ptr==NULL.
236 mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len);
237
238 #define MZ_CRC32_INIT (0)
239 // mz_crc32() returns the initial CRC-32 value to use when called with ptr==NULL.
240 mz_ulong mz_crc32(mz_ulong crc, const unsigned char *ptr, size_t buf_len);
241
242 // Compression strategies.
243 enum { MZ_DEFAULT_STRATEGY = 0, MZ_FILTERED = 1, MZ_HUFFMAN_ONLY = 2, MZ_RLE = 3, MZ_FIXED = 4 };
244
245 // Method
246 #define MZ_DEFLATED 8
247
248 #ifndef MINIZ_NO_ZLIB_APIS
249
250 // Heap allocation callbacks.
251 // Note that mz_alloc_func parameter types purpsosely differ from zlib's: items/size is size_t, not unsigned long.
252 typedef void *(*mz_alloc_func)(void *opaque, size_t items, size_t size);
253 typedef void (*mz_free_func)(void *opaque, void *address);
254 typedef void *(*mz_realloc_func)(void *opaque, void *address, size_t items, size_t size);
255
256 #define MZ_VERSION "9.1.15"
257 #define MZ_VERNUM 0x91F0
258 #define MZ_VER_MAJOR 9
259 #define MZ_VER_MINOR 1
260 #define MZ_VER_REVISION 15
261 #define MZ_VER_SUBREVISION 0
262
263 // Flush values. For typical usage you only need MZ_NO_FLUSH and MZ_FINISH. The other values are for advanced use (refer to the zlib docs).
264 enum { MZ_NO_FLUSH = 0, MZ_PARTIAL_FLUSH = 1, MZ_SYNC_FLUSH = 2, MZ_FULL_FLUSH = 3, MZ_FINISH = 4, MZ_BLOCK = 5 };
265
266 // Return status codes. MZ_PARAM_ERROR is non-standard.
267 enum { MZ_OK = 0, MZ_STREAM_END = 1, MZ_NEED_DICT = 2, MZ_ERRNO = -1, MZ_STREAM_ERROR = -2, MZ_DATA_ERROR = -3, MZ_MEM_ERROR = -4, MZ_BUF_ERROR = -5, MZ_VERSION_ERROR = -6, MZ_PARAM_ERROR = -10000 };
268
269 // Compression levels: 0-9 are the standard zlib-style levels, 10 is best possible compression (not zlib compatible, and may be very slow), MZ_DEFAULT_COMPRESSION=MZ_DEFAULT_LEVEL.
270 enum { MZ_NO_COMPRESSION = 0, MZ_BEST_SPEED = 1, MZ_BEST_COMPRESSION = 9, MZ_UBER_COMPRESSION = 10, MZ_DEFAULT_LEVEL = 6, MZ_DEFAULT_COMPRESSION = -1 };
271
272 // Window bits
273 #define MZ_DEFAULT_WINDOW_BITS 15
274
275 struct mz_internal_state;
276
277 // Compression/decompression stream struct.
278 typedef struct mz_stream_s
279 {
280 const unsigned char *next_in; // pointer to next byte to read
281 unsigned int avail_in; // number of bytes available at next_in
282 mz_ulong total_in; // total number of bytes consumed so far
283
284 unsigned char *next_out; // pointer to next byte to write
285 unsigned int avail_out; // number of bytes that can be written to next_out
286 mz_ulong total_out; // total number of bytes produced so far
287
288 char *msg; // error msg (unused)
289 struct mz_internal_state *state; // internal state, allocated by zalloc/zfree
290
291 mz_alloc_func zalloc; // optional heap allocation function (defaults to malloc)
292 mz_free_func zfree; // optional heap free function (defaults to free)
293 void *opaque; // heap alloc function user pointer
294
295 int data_type; // data_type (unused)
296 mz_ulong adler; // adler32 of the source or uncompressed data
297 mz_ulong reserved; // not used
298 } mz_stream;
299
300 typedef mz_stream *mz_streamp;
301
302 // Returns the version string of miniz.c.
303 const char *mz_version(void);
304
305 // mz_deflateInit() initializes a compressor with default options:
306 // Parameters:
307 // pStream must point to an initialized mz_stream struct.
308 // level must be between [MZ_NO_COMPRESSION, MZ_BEST_COMPRESSION].
309 // level 1 enables a specially optimized compression function that's been optimized purely for performance, not ratio.
310 // (This special func. is currently only enabled when MINIZ_USE_UNALIGNED_LOADS_AND_STORES and MINIZ_LITTLE_ENDIAN are defined.)
311 // Return values:
312 // MZ_OK on success.
313 // MZ_STREAM_ERROR if the stream is bogus.
314 // MZ_PARAM_ERROR if the input parameters are bogus.
315 // MZ_MEM_ERROR on out of memory.
316 int mz_deflateInit(mz_streamp pStream, int level);
317
318 // mz_deflateInit2() is like mz_deflate(), except with more control:
319 // Additional parameters:
320 // method must be MZ_DEFLATED
321 // window_bits must be MZ_DEFAULT_WINDOW_BITS (to wrap the deflate stream with zlib header/adler-32 footer) or -MZ_DEFAULT_WINDOW_BITS (raw deflate/no header or footer)
322 // mem_level must be between [1, 9] (it's checked but ignored by miniz.c)
323 int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits, int mem_level, int strategy);
324
325 // Quickly resets a compressor without having to reallocate anything. Same as calling mz_deflateEnd() followed by mz_deflateInit()/mz_deflateInit2().
326 int mz_deflateReset(mz_streamp pStream);
327
328 // mz_deflate() compresses the input to output, consuming as much of the input and producing as much output as possible.
329 // Parameters:
330 // pStream is the stream to read from and write to. You must initialize/update the next_in, avail_in, next_out, and avail_out members.
331 // flush may be MZ_NO_FLUSH, MZ_PARTIAL_FLUSH/MZ_SYNC_FLUSH, MZ_FULL_FLUSH, or MZ_FINISH.
332 // Return values:
333 // MZ_OK on success (when flushing, or if more input is needed but not available, and/or there's more output to be written but the output buffer is full).
334 // MZ_STREAM_END if all input has been consumed and all output bytes have been written. Don't call mz_deflate() on the stream anymore.
335 // MZ_STREAM_ERROR if the stream is bogus.
336 // MZ_PARAM_ERROR if one of the parameters is invalid.
337 // MZ_BUF_ERROR if no forward progress is possible because the input and/or output buffers are empty. (Fill up the input buffer or free up some output space and try again.)
338 int mz_deflate(mz_streamp pStream, int flush);
339
340 // mz_deflateEnd() deinitializes a compressor:
341 // Return values:
342 // MZ_OK on success.
343 // MZ_STREAM_ERROR if the stream is bogus.
344 int mz_deflateEnd(mz_streamp pStream);
345
346 // mz_deflateBound() returns a (very) conservative upper bound on the amount of data that could be generated by deflate(), assuming flush is set to only MZ_NO_FLUSH or MZ_FINISH.
347 mz_ulong mz_deflateBound(mz_streamp pStream, mz_ulong source_len);
348
349 // Single-call compression functions mz_compress() and mz_compress2():
350 // Returns MZ_OK on success, or one of the error codes from mz_deflate() on failure.
351 int mz_compress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len);
352 int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len, int level);
353
354 // mz_compressBound() returns a (very) conservative upper bound on the amount of data that could be generated by calling mz_compress().
355 mz_ulong mz_compressBound(mz_ulong source_len);
356
357 // Initializes a decompressor.
358 int mz_inflateInit(mz_streamp pStream);
359
360 // mz_inflateInit2() is like mz_inflateInit() with an additional option that controls the window size and whether or not the stream has been wrapped with a zlib header/footer:
361 // window_bits must be MZ_DEFAULT_WINDOW_BITS (to parse zlib header/footer) or -MZ_DEFAULT_WINDOW_BITS (raw deflate).
362 int mz_inflateInit2(mz_streamp pStream, int window_bits);
363
364 // Decompresses the input stream to the output, consuming only as much of the input as needed, and writing as much to the output as possible.
365 // Parameters:
366 // pStream is the stream to read from and write to. You must initialize/update the next_in, avail_in, next_out, and avail_out members.
367 // flush may be MZ_NO_FLUSH, MZ_SYNC_FLUSH, or MZ_FINISH.
368 // On the first call, if flush is MZ_FINISH it's assumed the input and output buffers are both sized large enough to decompress the entire stream in a single call (this is slightly faster).
369 // MZ_FINISH implies that there are no more source bytes available beside what's already in the input buffer, and that the output buffer is large enough to hold the rest of the decompressed data.
370 // Return values:
371 // MZ_OK on success. Either more input is needed but not available, and/or there's more output to be written but the output buffer is full.
372 // MZ_STREAM_END if all needed input has been consumed and all output bytes have been written. For zlib streams, the adler-32 of the decompressed data has also been verified.
373 // MZ_STREAM_ERROR if the stream is bogus.
374 // MZ_DATA_ERROR if the deflate stream is invalid.
375 // MZ_PARAM_ERROR if one of the parameters is invalid.
376 // MZ_BUF_ERROR if no forward progress is possible because the input buffer is empty but the inflater needs more input to continue, or if the output buffer is not large enough. Call mz_inflate() again
377 // with more input data, or with more room in the output buffer (except when using single call decompression, described above).
378 int mz_inflate(mz_streamp pStream, int flush);
379
380 // Deinitializes a decompressor.
381 int mz_inflateEnd(mz_streamp pStream);
382
383 // Single-call decompression.
384 // Returns MZ_OK on success, or one of the error codes from mz_inflate() on failure.
385 int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len);
386
387 // Returns a string description of the specified error code, or NULL if the error code is invalid.
388 const char *mz_error(int err);
389
390 // Redefine zlib-compatible names to miniz equivalents, so miniz.c can be used as a drop-in replacement for the subset of zlib that miniz.c supports.
391 // Define MINIZ_NO_ZLIB_COMPATIBLE_NAMES to disable zlib-compatibility if you use zlib in the same project.
392 #ifndef MINIZ_NO_ZLIB_COMPATIBLE_NAMES
393 typedef unsigned char Byte;
394 typedef unsigned int uInt;
395 typedef mz_ulong uLong;
396 typedef Byte Bytef;
397 typedef uInt uIntf;
398 typedef char charf;
399 typedef int intf;
400 typedef void *voidpf;
401 typedef uLong uLongf;
402 typedef void *voidp;
403 typedef void *const voidpc;
404 #define Z_NULL 0
405 #define Z_NO_FLUSH MZ_NO_FLUSH
406 #define Z_PARTIAL_FLUSH MZ_PARTIAL_FLUSH
407 #define Z_SYNC_FLUSH MZ_SYNC_FLUSH
408 #define Z_FULL_FLUSH MZ_FULL_FLUSH
409 #define Z_FINISH MZ_FINISH
410 #define Z_BLOCK MZ_BLOCK
411 #define Z_OK MZ_OK
412 #define Z_STREAM_END MZ_STREAM_END
413 #define Z_NEED_DICT MZ_NEED_DICT
414 #define Z_ERRNO MZ_ERRNO
415 #define Z_STREAM_ERROR MZ_STREAM_ERROR
416 #define Z_DATA_ERROR MZ_DATA_ERROR
417 #define Z_MEM_ERROR MZ_MEM_ERROR
418 #define Z_BUF_ERROR MZ_BUF_ERROR
419 #define Z_VERSION_ERROR MZ_VERSION_ERROR
420 #define Z_PARAM_ERROR MZ_PARAM_ERROR
421 #define Z_NO_COMPRESSION MZ_NO_COMPRESSION
422 #define Z_BEST_SPEED MZ_BEST_SPEED
423 #define Z_BEST_COMPRESSION MZ_BEST_COMPRESSION
424 #define Z_DEFAULT_COMPRESSION MZ_DEFAULT_COMPRESSION
425 #define Z_DEFAULT_STRATEGY MZ_DEFAULT_STRATEGY
426 #define Z_FILTERED MZ_FILTERED
427 #define Z_HUFFMAN_ONLY MZ_HUFFMAN_ONLY
428 #define Z_RLE MZ_RLE
429 #define Z_FIXED MZ_FIXED
430 #define Z_DEFLATED MZ_DEFLATED
431 #define Z_DEFAULT_WINDOW_BITS MZ_DEFAULT_WINDOW_BITS
432 #define alloc_func mz_alloc_func
433 #define free_func mz_free_func
434 #define internal_state mz_internal_state
435 #define z_stream mz_stream
436 #define deflateInit mz_deflateInit
437 #define deflateInit2 mz_deflateInit2
438 #define deflateReset mz_deflateReset
439 #define deflate mz_deflate
440 #define deflateEnd mz_deflateEnd
441 #define deflateBound mz_deflateBound
442 #define compress mz_compress
443 #define compress2 mz_compress2
444 #define compressBound mz_compressBound
445 #define inflateInit mz_inflateInit
446 #define inflateInit2 mz_inflateInit2
447 #define inflate mz_inflate
448 #define inflateEnd mz_inflateEnd
449 #define uncompress mz_uncompress
450 #define crc32 mz_crc32
451 #define adler32 mz_adler32
452 #define MAX_WBITS 15
453 #define MAX_MEM_LEVEL 9
454 #define zError mz_error
455 #define ZLIB_VERSION MZ_VERSION
456 #define ZLIB_VERNUM MZ_VERNUM
457 #define ZLIB_VER_MAJOR MZ_VER_MAJOR
458 #define ZLIB_VER_MINOR MZ_VER_MINOR
459 #define ZLIB_VER_REVISION MZ_VER_REVISION
460 #define ZLIB_VER_SUBREVISION MZ_VER_SUBREVISION
461 #define zlibVersion mz_version
462 #define zlib_version mz_version()
463 #endif // #ifndef MINIZ_NO_ZLIB_COMPATIBLE_NAMES
464
465 #endif // MINIZ_NO_ZLIB_APIS
466
467 // ------------------- Types and macros
468
469 typedef unsigned char mz_uint8;
470 typedef signed short mz_int16;
471 typedef unsigned short mz_uint16;
472 typedef unsigned int mz_uint32;
473 typedef unsigned int mz_uint;
474 typedef long long mz_int64;
475 typedef unsigned long long mz_uint64;
476 typedef int mz_bool;
477
478 #define MZ_FALSE (0)
479 #define MZ_TRUE (1)
480
481 // An attempt to work around MSVC's spammy "warning C4127: conditional expression is constant" message.
482 #ifdef _MSC_VER
483 #define MZ_MACRO_END while (0, 0)
484 #else
485 #define MZ_MACRO_END while (0)
486 #endif
487
488 // ------------------- ZIP archive reading/writing
489
490 #ifndef MINIZ_NO_ARCHIVE_APIS
491
492 enum
493 {
494 MZ_ZIP_MAX_IO_BUF_SIZE = 64*1024,
495 MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE = 260,
496 MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE = 256
497 };
498
499 typedef struct
500 {
501 mz_uint32 m_file_index;
502 mz_uint32 m_central_dir_ofs;
503 mz_uint16 m_version_made_by;
504 mz_uint16 m_version_needed;
505 mz_uint16 m_bit_flag;
506 mz_uint16 m_method;
507 #ifndef MINIZ_NO_TIME
508 time_t m_time;
509 #endif
510 mz_uint32 m_crc32;
511 mz_uint64 m_comp_size;
512 mz_uint64 m_uncomp_size;
513 mz_uint16 m_internal_attr;
514 mz_uint32 m_external_attr;
515 mz_uint64 m_local_header_ofs;
516 mz_uint32 m_comment_size;
517 char m_filename[MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE];
518 char m_comment[MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE];
519 } mz_zip_archive_file_stat;
520
521 typedef size_t (*mz_file_read_func)(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n);
522 typedef size_t (*mz_file_write_func)(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n);
523
524 struct mz_zip_internal_state_tag;
525 typedef struct mz_zip_internal_state_tag mz_zip_internal_state;
526
527 typedef enum
528 {
529 MZ_ZIP_MODE_INVALID = 0,
530 MZ_ZIP_MODE_READING = 1,
531 MZ_ZIP_MODE_WRITING = 2,
532 MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED = 3
533 } mz_zip_mode;
534
535 typedef struct mz_zip_archive_tag
536 {
537 mz_uint64 m_archive_size;
538 mz_uint64 m_central_directory_file_ofs;
539 mz_uint m_total_files;
540 mz_zip_mode m_zip_mode;
541
542 mz_uint m_file_offset_alignment;
543
544 mz_alloc_func m_pAlloc;
545 mz_free_func m_pFree;
546 mz_realloc_func m_pRealloc;
547 void *m_pAlloc_opaque;
548
549 mz_file_read_func m_pRead;
550 mz_file_write_func m_pWrite;
551 void *m_pIO_opaque;
552
553 mz_zip_internal_state *m_pState;
554
555 } mz_zip_archive;
556
557 typedef enum
558 {
559 MZ_ZIP_FLAG_CASE_SENSITIVE = 0x0100,
560 MZ_ZIP_FLAG_IGNORE_PATH = 0x0200,
561 MZ_ZIP_FLAG_COMPRESSED_DATA = 0x0400,
562 MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY = 0x0800
563 } mz_zip_flags;
564
565 // ZIP archive reading
566
567 // Inits a ZIP archive reader.
568 // These functions read and validate the archive's central directory.
569 mz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size, mz_uint32 flags);
570 mz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem, size_t size, mz_uint32 flags);
571
572 #ifndef MINIZ_NO_STDIO
573 mz_bool mz_zip_reader_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint32 flags);
574 #endif
575
576 // Returns the total number of files in the archive.
577 mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip);
578
579 // Returns detailed information about an archive file entry.
580 mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index, mz_zip_archive_file_stat *pStat);
581
582 // Determines if an archive file entry is a directory entry.
583 mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip, mz_uint file_index);
584 mz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive *pZip, mz_uint file_index);
585
586 // Retrieves the filename of an archive file entry.
587 // Returns the number of bytes written to pFilename, or if filename_buf_size is 0 this function returns the number of bytes needed to fully store the filename.
588 mz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, mz_uint file_index, char *pFilename, mz_uint filename_buf_size);
589
590 // Attempts to locates a file in the archive's central directory.
591 // Valid flags: MZ_ZIP_FLAG_CASE_SENSITIVE, MZ_ZIP_FLAG_IGNORE_PATH
592 // Returns -1 if the file cannot be found.
593 int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags);
594
595 // Extracts a archive file to a memory buffer using no memory allocation.
596 mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size);
597 mz_bool mz_zip_reader_extract_file_to_mem_no_alloc(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size);
598
599 // Extracts a archive file to a memory buffer.
600 mz_bool mz_zip_reader_extract_to_mem(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags);
601 mz_bool mz_zip_reader_extract_file_to_mem(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags);
602
603 // Extracts a archive file to a dynamically allocated heap buffer.
604 void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index, size_t *pSize, mz_uint flags);
605 void *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip, const char *pFilename, size_t *pSize, mz_uint flags);
606
607 // Extracts a archive file using a callback function to output the file's data.
608 mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip, mz_uint file_index, mz_file_write_func pCallback, void *pOpaque, mz_uint flags);
609 mz_bool mz_zip_reader_extract_file_to_callback(mz_zip_archive *pZip, const char *pFilename, mz_file_write_func pCallback, void *pOpaque, mz_uint flags);
610
611 #ifndef MINIZ_NO_STDIO
612 // Extracts a archive file to a disk file and sets its last accessed and modified times.
613 // This function only extracts files, not archive directory records.
614 mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index, const char *pDst_filename, mz_uint flags);
615 mz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive *pZip, const char *pArchive_filename, const char *pDst_filename, mz_uint flags);
616 #endif
617
618 // Ends archive reading, freeing all allocations, and closing the input archive file if mz_zip_reader_init_file() was used.
619 mz_bool mz_zip_reader_end(mz_zip_archive *pZip);
620
621 // ZIP archive writing
622
623 #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
624
625 // Inits a ZIP archive writer.
626 mz_bool mz_zip_writer_init(mz_zip_archive *pZip, mz_uint64 existing_size);
627 mz_bool mz_zip_writer_init_heap(mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size);
628
629 #ifndef MINIZ_NO_STDIO
630 mz_bool mz_zip_writer_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint64 size_to_reserve_at_beginning);
631 #endif
632
633 // Converts a ZIP archive reader object into a writer object, to allow efficient in-place file appends to occur on an existing archive.
634 // For archives opened using mz_zip_reader_init_file, pFilename must be the archive's filename so it can be reopened for writing. If the file can't be reopened, mz_zip_reader_end() will be called.
635 // For archives opened using mz_zip_reader_init_mem, the memory block must be growable using the realloc callback (which defaults to realloc unless you've overridden it).
636 // Finally, for archives opened using mz_zip_reader_init, the mz_zip_archive's user provided m_pWrite function cannot be NULL.
637 // Note: In-place archive modification is not recommended unless you know what you're doing, because if execution stops or something goes wrong before
638 // the archive is finalized the file's central directory will be hosed.
639 mz_bool mz_zip_writer_init_from_reader(mz_zip_archive *pZip, const char *pFilename);
640
641 // Adds the contents of a memory buffer to an archive. These functions record the current local time into the archive.
642 // To add a directory entry, call this method with an archive name ending in a forwardslash with empty buffer.
643 // level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION.
644 mz_bool mz_zip_writer_add_mem(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, mz_uint level_and_flags);
645 mz_bool mz_zip_writer_add_mem_ex(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, mz_uint64 uncomp_size, mz_uint32 uncomp_crc32);
646
647 #ifndef MINIZ_NO_STDIO
648 // Adds the contents of a disk file to an archive. This function also records the disk file's modified time into the archive.
649 // level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION.
650 mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name, const char *pSrc_filename, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags);
651 #endif
652
653 // Adds a file to an archive by fully cloning the data from another archive.
654 // This function fully clones the source file's compressed data (no recompression), along with its full filename, extra data, and comment fields.
655 mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive *pSource_zip, mz_uint file_index);
656
657 // Finalizes the archive by writing the central directory records followed by the end of central directory record.
658 // After an archive is finalized, the only valid call on the mz_zip_archive struct is mz_zip_writer_end().
659 // An archive must be manually finalized by calling this function for it to be valid.
660 mz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip);
661 mz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive *pZip, void **pBuf, size_t *pSize);
662
663 // Ends archive writing, freeing all allocations, and closing the output file if mz_zip_writer_init_file() was used.
664 // Note for the archive to be valid, it must have been finalized before ending.
665 mz_bool mz_zip_writer_end(mz_zip_archive *pZip);
666
667 // Misc. high-level helper functions:
668
669 // mz_zip_add_mem_to_archive_file_in_place() efficiently (but not atomically) appends a memory blob to a ZIP archive.
670 // level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION.
671 mz_bool mz_zip_add_mem_to_archive_file_in_place(const char *pZip_filename, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags);
672
673 // Reads a single file from an archive into a heap block.
674 // Returns NULL on failure.
675 void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const char *pArchive_name, size_t *pSize, mz_uint zip_flags);
676
677 #endif // #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
678
679 #endif // #ifndef MINIZ_NO_ARCHIVE_APIS
680
681 // ------------------- Low-level Decompression API Definitions
682
683 // Decompression flags used by tinfl_decompress().
684 // TINFL_FLAG_PARSE_ZLIB_HEADER: If set, the input has a valid zlib header and ends with an adler32 checksum (it's a valid zlib stream). Otherwise, the input is a raw deflate stream.
685 // TINFL_FLAG_HAS_MORE_INPUT: If set, there are more input bytes available beyond the end of the supplied input buffer. If clear, the input buffer contains all remaining input.
686 // TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF: If set, the output buffer is large enough to hold the entire decompressed stream. If clear, the output buffer is at least the size of the dictionary (typically 32KB).
687 // TINFL_FLAG_COMPUTE_ADLER32: Force adler-32 checksum computation of the decompressed bytes.
688 enum
689 {
690 TINFL_FLAG_PARSE_ZLIB_HEADER = 1,
691 TINFL_FLAG_HAS_MORE_INPUT = 2,
692 TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF = 4,
693 TINFL_FLAG_COMPUTE_ADLER32 = 8
694 };
695
696 // High level decompression functions:
697 // tinfl_decompress_mem_to_heap() decompresses a block in memory to a heap block allocated via malloc().
698 // On entry:
699 // pSrc_buf, src_buf_len: Pointer and size of the Deflate or zlib source data to decompress.
700 // On return:
701 // Function returns a pointer to the decompressed data, or NULL on failure.
702 // *pOut_len will be set to the decompressed data's size, which could be larger than src_buf_len on uncompressible data.
703 // The caller must call mz_free() on the returned block when it's no longer needed.
704 void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags);
705
706 // tinfl_decompress_mem_to_mem() decompresses a block in memory to another block in memory.
707 // Returns TINFL_DECOMPRESS_MEM_TO_MEM_FAILED on failure, or the number of bytes written on success.
708 #define TINFL_DECOMPRESS_MEM_TO_MEM_FAILED ((size_t)(-1))
709 size_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags);
710
711 // tinfl_decompress_mem_to_callback() decompresses a block in memory to an internal 32KB buffer, and a user provided callback function will be called to flush the buffer.
712 // Returns 1 on success or 0 on failure.
713 typedef int (*tinfl_put_buf_func_ptr)(const void* pBuf, int len, void *pUser);
714 int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size, tinfl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags);
715
716 struct tinfl_decompressor_tag; typedef struct tinfl_decompressor_tag tinfl_decompressor;
717
718 // Max size of LZ dictionary.
719 #define TINFL_LZ_DICT_SIZE 32768
720
721 // Return status.
722 typedef enum
723 {
724 TINFL_STATUS_BAD_PARAM = -3,
725 TINFL_STATUS_ADLER32_MISMATCH = -2,
726 TINFL_STATUS_FAILED = -1,
727 TINFL_STATUS_DONE = 0,
728 TINFL_STATUS_NEEDS_MORE_INPUT = 1,
729 TINFL_STATUS_HAS_MORE_OUTPUT = 2
730 } tinfl_status;
731
732 // Initializes the decompressor to its initial state.
733 #define tinfl_init(r) do { (r)->m_state = 0; } MZ_MACRO_END
734 #define tinfl_get_adler32(r) (r)->m_check_adler32
735
736 // Main low-level decompressor coroutine function. This is the only function actually needed for decompression. All the other functions are just high-level helpers for improved usability.
737 // This is a universal API, i.e. it can be used as a building block to build any desired higher level decompression API. In the limit case, it can be called once per every byte input or output.
738 tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_next, size_t *pIn_buf_size, mz_uint8 *pOut_buf_start, mz_uint8 *pOut_buf_next, size_t *pOut_buf_size, const mz_uint32 decomp_flags);
739
740 // Internal/private bits follow.
741 enum
742 {
743 TINFL_MAX_HUFF_TABLES = 3, TINFL_MAX_HUFF_SYMBOLS_0 = 288, TINFL_MAX_HUFF_SYMBOLS_1 = 32, TINFL_MAX_HUFF_SYMBOLS_2 = 19,
744 TINFL_FAST_LOOKUP_BITS = 10, TINFL_FAST_LOOKUP_SIZE = 1 << TINFL_FAST_LOOKUP_BITS
745 };
746
747 typedef struct
748 {
749 mz_uint8 m_code_size[TINFL_MAX_HUFF_SYMBOLS_0];
750 mz_int16 m_look_up[TINFL_FAST_LOOKUP_SIZE], m_tree[TINFL_MAX_HUFF_SYMBOLS_0 * 2];
751 } tinfl_huff_table;
752
753 #if MINIZ_HAS_64BIT_REGISTERS
754 #define TINFL_USE_64BIT_BITBUF 1
755 #endif
756
757 #if TINFL_USE_64BIT_BITBUF
758 typedef mz_uint64 tinfl_bit_buf_t;
759 #define TINFL_BITBUF_SIZE (64)
760 #else
761 typedef mz_uint32 tinfl_bit_buf_t;
762 #define TINFL_BITBUF_SIZE (32)
763 #endif
764
765 struct tinfl_decompressor_tag
766 {
767 mz_uint32 m_state, m_num_bits, m_zhdr0, m_zhdr1, m_z_adler32, m_final, m_type, m_check_adler32, m_dist, m_counter, m_num_extra, m_table_sizes[TINFL_MAX_HUFF_TABLES];
768 tinfl_bit_buf_t m_bit_buf;
769 size_t m_dist_from_out_buf_start;
770 tinfl_huff_table m_tables[TINFL_MAX_HUFF_TABLES];
771 mz_uint8 m_raw_header[4], m_len_codes[TINFL_MAX_HUFF_SYMBOLS_0 + TINFL_MAX_HUFF_SYMBOLS_1 + 137];
772 };
773
774 // ------------------- Low-level Compression API Definitions
775
776 // Set TDEFL_LESS_MEMORY to 1 to use less memory (compression will be slightly slower, and raw/dynamic blocks will be output more frequently).
777 #define TDEFL_LESS_MEMORY 0
778
779 // tdefl_init() compression flags logically OR'd together (low 12 bits contain the max. number of probes per dictionary search):
780 // TDEFL_DEFAULT_MAX_PROBES: The compressor defaults to 128 dictionary probes per dictionary search. 0=Huffman only, 1=Huffman+LZ (fastest/crap compression), 4095=Huffman+LZ (slowest/best compression).
781 enum
782 {
783 TDEFL_HUFFMAN_ONLY = 0, TDEFL_DEFAULT_MAX_PROBES = 128, TDEFL_MAX_PROBES_MASK = 0xFFF
784 };
785
786 // TDEFL_WRITE_ZLIB_HEADER: If set, the compressor outputs a zlib header before the deflate data, and the Adler-32 of the source data at the end. Otherwise, you'll get raw deflate data.
787 // TDEFL_COMPUTE_ADLER32: Always compute the adler-32 of the input data (even when not writing zlib headers).
788 // TDEFL_GREEDY_PARSING_FLAG: Set to use faster greedy parsing, instead of more efficient lazy parsing.
789 // TDEFL_NONDETERMINISTIC_PARSING_FLAG: Enable to decrease the compressor's initialization time to the minimum, but the output may vary from run to run given the same input (depending on the contents of memory).
790 // TDEFL_RLE_MATCHES: Only look for RLE matches (matches with a distance of 1)
791 // TDEFL_FILTER_MATCHES: Discards matches <= 5 chars if enabled.
792 // TDEFL_FORCE_ALL_STATIC_BLOCKS: Disable usage of optimized Huffman tables.
793 // TDEFL_FORCE_ALL_RAW_BLOCKS: Only use raw (uncompressed) deflate blocks.
794 // The low 12 bits are reserved to control the max # of hash probes per dictionary lookup (see TDEFL_MAX_PROBES_MASK).
795 enum
796 {
797 TDEFL_WRITE_ZLIB_HEADER = 0x01000,
798 TDEFL_COMPUTE_ADLER32 = 0x02000,
799 TDEFL_GREEDY_PARSING_FLAG = 0x04000,
800 TDEFL_NONDETERMINISTIC_PARSING_FLAG = 0x08000,
801 TDEFL_RLE_MATCHES = 0x10000,
802 TDEFL_FILTER_MATCHES = 0x20000,
803 TDEFL_FORCE_ALL_STATIC_BLOCKS = 0x40000,
804 TDEFL_FORCE_ALL_RAW_BLOCKS = 0x80000
805 };
806
807 // High level compression functions:
808 // tdefl_compress_mem_to_heap() compresses a block in memory to a heap block allocated via malloc().
809 // On entry:
810 // pSrc_buf, src_buf_len: Pointer and size of source block to compress.
811 // flags: The max match finder probes (default is 128) logically OR'd against the above flags. Higher probes are slower but improve compression.
812 // On return:
813 // Function returns a pointer to the compressed data, or NULL on failure.
814 // *pOut_len will be set to the compressed data's size, which could be larger than src_buf_len on uncompressible data.
815 // The caller must free() the returned block when it's no longer needed.
816 void *tdefl_compress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags);
817
818 // tdefl_compress_mem_to_mem() compresses a block in memory to another block in memory.
819 // Returns 0 on failure.
820 size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags);
821
822 // Compresses an image to a compressed PNG file in memory.
823 // On entry:
824 // pImage, w, h, and num_chans describe the image to compress. num_chans may be 1, 2, 3, or 4.
825 // The image pitch in bytes per scanline will be w*num_chans. The leftmost pixel on the top scanline is stored first in memory.
826 // level may range from [0,10], use MZ_NO_COMPRESSION, MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc. or a decent default is MZ_DEFAULT_LEVEL
827 // If flip is true, the image will be flipped on the Y axis (useful for OpenGL apps).
828 // On return:
829 // Function returns a pointer to the compressed data, or NULL on failure.
830 // *pLen_out will be set to the size of the PNG image file.
831 // The caller must mz_free() the returned heap block (which will typically be larger than *pLen_out) when it's no longer needed.
832 void *tdefl_write_image_to_png_file_in_memory_ex(const void *pImage, int w, int h, int num_chans, size_t *pLen_out, mz_uint level, mz_bool flip);
833 void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h, int num_chans, size_t *pLen_out);
834
835 // Output stream interface. The compressor uses this interface to write compressed data. It'll typically be called TDEFL_OUT_BUF_SIZE at a time.
836 typedef mz_bool (*tdefl_put_buf_func_ptr)(const void* pBuf, int len, void *pUser);
837
838 // tdefl_compress_mem_to_output() compresses a block to an output stream. The above helpers use this function internally.
839 mz_bool tdefl_compress_mem_to_output(const void *pBuf, size_t buf_len, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags);
840
841 enum { TDEFL_MAX_HUFF_TABLES = 3, TDEFL_MAX_HUFF_SYMBOLS_0 = 288, TDEFL_MAX_HUFF_SYMBOLS_1 = 32, TDEFL_MAX_HUFF_SYMBOLS_2 = 19, TDEFL_LZ_DICT_SIZE = 32768, TDEFL_LZ_DICT_SIZE_MASK = TDEFL_LZ_DICT_SIZE - 1, TDEFL_MIN_MATCH_LEN = 3, TDEFL_MAX_MATCH_LEN = 258 };
842
843 // TDEFL_OUT_BUF_SIZE MUST be large enough to hold a single entire compressed output block (using static/fixed Huffman codes).
844 #if TDEFL_LESS_MEMORY
845 enum { TDEFL_LZ_CODE_BUF_SIZE = 24 * 1024, TDEFL_OUT_BUF_SIZE = (TDEFL_LZ_CODE_BUF_SIZE * 13 ) / 10, TDEFL_MAX_HUFF_SYMBOLS = 288, TDEFL_LZ_HASH_BITS = 12, TDEFL_LEVEL1_HASH_SIZE_MASK = 4095, TDEFL_LZ_HASH_SHIFT = (TDEFL_LZ_HASH_BITS + 2) / 3, TDEFL_LZ_HASH_SIZE = 1 << TDEFL_LZ_HASH_BITS };
846 #else
847 enum { TDEFL_LZ_CODE_BUF_SIZE = 64 * 1024, TDEFL_OUT_BUF_SIZE = (TDEFL_LZ_CODE_BUF_SIZE * 13 ) / 10, TDEFL_MAX_HUFF_SYMBOLS = 288, TDEFL_LZ_HASH_BITS = 15, TDEFL_LEVEL1_HASH_SIZE_MASK = 4095, TDEFL_LZ_HASH_SHIFT = (TDEFL_LZ_HASH_BITS + 2) / 3, TDEFL_LZ_HASH_SIZE = 1 << TDEFL_LZ_HASH_BITS };
848 #endif
849
850 // The low-level tdefl functions below may be used directly if the above helper functions aren't flexible enough. The low-level functions don't make any heap allocations, unlike the above helper functions.
851 typedef enum
852 {
853 TDEFL_STATUS_BAD_PARAM = -2,
854 TDEFL_STATUS_PUT_BUF_FAILED = -1,
855 TDEFL_STATUS_OKAY = 0,
856 TDEFL_STATUS_DONE = 1,
857 } tdefl_status;
858
859 // Must map to MZ_NO_FLUSH, MZ_SYNC_FLUSH, etc. enums
860 typedef enum
861 {
862 TDEFL_NO_FLUSH = 0,
863 TDEFL_SYNC_FLUSH = 2,
864 TDEFL_FULL_FLUSH = 3,
865 TDEFL_FINISH = 4
866 } tdefl_flush;
867
868 // tdefl's compression state structure.
869 typedef struct
870 {
871 tdefl_put_buf_func_ptr m_pPut_buf_func;
872 void *m_pPut_buf_user;
873 mz_uint m_flags, m_max_probes[2];
874 int m_greedy_parsing;
875 mz_uint m_adler32, m_lookahead_pos, m_lookahead_size, m_dict_size;
876 mz_uint8 *m_pLZ_code_buf, *m_pLZ_flags, *m_pOutput_buf, *m_pOutput_buf_end;
877 mz_uint m_num_flags_left, m_total_lz_bytes, m_lz_code_buf_dict_pos, m_bits_in, m_bit_buffer;
878 mz_uint m_saved_match_dist, m_saved_match_len, m_saved_lit, m_output_flush_ofs, m_output_flush_remaining, m_finished, m_block_index, m_wants_to_finish;
879 tdefl_status m_prev_return_status;
880 const void *m_pIn_buf;
881 void *m_pOut_buf;
882 size_t *m_pIn_buf_size, *m_pOut_buf_size;
883 tdefl_flush m_flush;
884 const mz_uint8 *m_pSrc;
885 size_t m_src_buf_left, m_out_buf_ofs;
886 mz_uint8 m_dict[TDEFL_LZ_DICT_SIZE + TDEFL_MAX_MATCH_LEN - 1];
887 mz_uint16 m_huff_count[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS];
888 mz_uint16 m_huff_codes[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS];
889 mz_uint8 m_huff_code_sizes[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS];
890 mz_uint8 m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE];
891 mz_uint16 m_next[TDEFL_LZ_DICT_SIZE];
892 mz_uint16 m_hash[TDEFL_LZ_HASH_SIZE];
893 mz_uint8 m_output_buf[TDEFL_OUT_BUF_SIZE];
894 } tdefl_compressor;
895
896 // Initializes the compressor.
897 // There is no corresponding deinit() function because the tdefl API's do not dynamically allocate memory.
898 // pBut_buf_func: If NULL, output data will be supplied to the specified callback. In this case, the user should call the tdefl_compress_buffer() API for compression.
899 // If pBut_buf_func is NULL the user should always call the tdefl_compress() API.
900 // flags: See the above enums (TDEFL_HUFFMAN_ONLY, TDEFL_WRITE_ZLIB_HEADER, etc.)
901 tdefl_status tdefl_init(tdefl_compressor *d, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags);
902
903 // Compresses a block of data, consuming as much of the specified input buffer as possible, and writing as much compressed data to the specified output buffer as possible.
904 tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf, size_t *pIn_buf_size, void *pOut_buf, size_t *pOut_buf_size, tdefl_flush flush);
905
906 // tdefl_compress_buffer() is only usable when the tdefl_init() is called with a non-NULL tdefl_put_buf_func_ptr.
907 // tdefl_compress_buffer() always consumes the entire input buffer.
908 tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf, size_t in_buf_size, tdefl_flush flush);
909
910 tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d);
911 mz_uint32 tdefl_get_adler32(tdefl_compressor *d);
912
913 // Can't use tdefl_create_comp_flags_from_zip_params if MINIZ_NO_ZLIB_APIS isn't defined, because it uses some of its macros.
914 #ifndef MINIZ_NO_ZLIB_APIS
915 // Create tdefl_compress() flags given zlib-style compression parameters.
916 // level may range from [0,10] (where 10 is absolute max compression, but may be much slower on some files)
917 // window_bits may be -15 (raw deflate) or 15 (zlib)
918 // strategy may be either MZ_DEFAULT_STRATEGY, MZ_FILTERED, MZ_HUFFMAN_ONLY, MZ_RLE, or MZ_FIXED
919 mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits, int strategy);
920 #endif // #ifndef MINIZ_NO_ZLIB_APIS
921
922 #ifdef __cplusplus
923 }
924 #endif
925
926 #endif // MINIZ_HEADER_INCLUDED
927
928 // ------------------- End of Header: Implementation follows. (If you only want the header, define MINIZ_HEADER_FILE_ONLY.)
929
930 #ifndef MINIZ_HEADER_FILE_ONLY
931
932 typedef unsigned char mz_validate_uint16[sizeof(mz_uint16)==2 ? 1 : -1];
933 typedef unsigned char mz_validate_uint32[sizeof(mz_uint32)==4 ? 1 : -1];
934 typedef unsigned char mz_validate_uint64[sizeof(mz_uint64)==8 ? 1 : -1];
935
936 #include <string.h>
937 #include <assert.h>
938
939 #define MZ_ASSERT(x) assert(x)
940
941 #ifdef MINIZ_NO_MALLOC
942 #define MZ_MALLOC(x) NULL
943 #define MZ_FREE(x) (void)x, ((void)0)
944 #define MZ_REALLOC(p, x) NULL
945 #else
946 #define MZ_MALLOC(x) malloc(x)
947 #define MZ_FREE(x) free(x)
948 #define MZ_REALLOC(p, x) realloc(p, x)
949 #endif
950
951 #define MZ_MAX(a,b) (((a)>(b))?(a):(b))
952 #define MZ_MIN(a,b) (((a)<(b))?(a):(b))
953 #define MZ_CLEAR_OBJ(obj) memset(&(obj), 0, sizeof(obj))
954
955 #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
956 #define MZ_READ_LE16(p) *((const mz_uint16 *)(p))
957 #define MZ_READ_LE32(p) *((const mz_uint32 *)(p))
958 #else
959 #define MZ_READ_LE16(p) ((mz_uint32)(((const mz_uint8 *)(p))[0]) | ((mz_uint32)(((const mz_uint8 *)(p))[1]) << 8U))
960 #define MZ_READ_LE32(p) ((mz_uint32)(((const mz_uint8 *)(p))[0]) | ((mz_uint32)(((const mz_uint8 *)(p))[1]) << 8U) | ((mz_uint32)(((const mz_uint8 *)(p))[2]) << 16U) | ((mz_uint32)(((const mz_uint8 *)(p))[3]) << 24U))
961 #endif
962
963 #ifdef _MSC_VER
964 #define MZ_FORCEINLINE __forceinline
965 #elif defined(__GNUC__)
966 #define MZ_FORCEINLINE inline __attribute__((__always_inline__))
967 #else
968 #define MZ_FORCEINLINE inline
969 #endif
970
971 #ifdef __cplusplus
972 extern "C" {
973 #endif
974
975 // ------------------- zlib-style API's
976
977 mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len)
978 {
979 mz_uint32 i, s1 = (mz_uint32)(adler & 0xffff), s2 = (mz_uint32)(adler >> 16); size_t block_len = buf_len % 5552;
980 if (!ptr) return MZ_ADLER32_INIT;
981 while (buf_len) {
982 for (i = 0; i + 7 < block_len; i += 8, ptr += 8) {
983 s1 += ptr[0], s2 += s1; s1 += ptr[1], s2 += s1; s1 += ptr[2], s2 += s1; s1 += ptr[3], s2 += s1;
984 s1 += ptr[4], s2 += s1; s1 += ptr[5], s2 += s1; s1 += ptr[6], s2 += s1; s1 += ptr[7], s2 += s1;
985 }
986 for ( ; i < block_len; ++i) s1 += *ptr++, s2 += s1;
987 s1 %= 65521U, s2 %= 65521U; buf_len -= block_len; block_len = 5552;
988 }
989 return (s2 << 16) + s1;
990 }
991
992 // Karl Malbrain's compact CRC-32. See "A compact CCITT crc16 and crc32 C implementation that balances processor cache usage against speed": http://www.geocities.com/malbrain/
993 mz_ulong mz_crc32(mz_ulong crc, const mz_uint8 *ptr, size_t buf_len)
994 {
995 static const mz_uint32 s_crc32[16] = { 0, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
996 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c };
997 mz_uint32 crcu32 = (mz_uint32)crc;
998 if (!ptr) return MZ_CRC32_INIT;
999 crcu32 = ~crcu32; while (buf_len--) { mz_uint8 b = *ptr++; crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b & 0xF)]; crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b >> 4)]; }
1000 return ~crcu32;
1001 }
1002
1003 void mz_free(void *p)
1004 {
1005 MZ_FREE(p);
1006 }
1007
1008 #ifndef MINIZ_NO_ZLIB_APIS
1009
1010 static void *def_alloc_func(void *opaque, size_t items, size_t size) { (void)opaque, (void)items, (void)size; return MZ_MALLOC(items * size); }
1011 static void def_free_func(void *opaque, void *address) { (void)opaque, (void)address; MZ_FREE(address); }
1012 static void *def_realloc_func(void *opaque, void *address, size_t items, size_t size) { (void)opaque, (void)address, (void)items, (void)size; return MZ_REALLOC(address, items * size); }
1013
1014 const char *mz_version(void)
1015 {
1016 return MZ_VERSION;
1017 }
1018
1019 int mz_deflateInit(mz_streamp pStream, int level)
1020 {
1021 return mz_deflateInit2(pStream, level, MZ_DEFLATED, MZ_DEFAULT_WINDOW_BITS, 9, MZ_DEFAULT_STRATEGY);
1022 }
1023
1024 int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits, int mem_level, int strategy)
1025 {
1026 tdefl_compressor *pComp;
1027 mz_uint comp_flags = TDEFL_COMPUTE_ADLER32 | tdefl_create_comp_flags_from_zip_params(level, window_bits, strategy);
1028
1029 if (!pStream) return MZ_STREAM_ERROR;
1030 if ((method != MZ_DEFLATED) || ((mem_level < 1) || (mem_level > 9)) || ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS))) return MZ_PARAM_ERROR;
1031
1032 pStream->data_type = 0;
1033 pStream->adler = MZ_ADLER32_INIT;
1034 pStream->msg = NULL;
1035 pStream->reserved = 0;
1036 pStream->total_in = 0;
1037 pStream->total_out = 0;
1038 if (!pStream->zalloc) pStream->zalloc = def_alloc_func;
1039 if (!pStream->zfree) pStream->zfree = def_free_func;
1040
1041 pComp = (tdefl_compressor *)pStream->zalloc(pStream->opaque, 1, sizeof(tdefl_compressor));
1042 if (!pComp)
1043 return MZ_MEM_ERROR;
1044
1045 pStream->state = (struct mz_internal_state *)pComp;
1046
1047 if (tdefl_init(pComp, NULL, NULL, comp_flags) != TDEFL_STATUS_OKAY)
1048 {
1049 mz_deflateEnd(pStream);
1050 return MZ_PARAM_ERROR;
1051 }
1052
1053 return MZ_OK;
1054 }
1055
1056 int mz_deflateReset(mz_streamp pStream)
1057 {
1058 if ((!pStream) || (!pStream->state) || (!pStream->zalloc) || (!pStream->zfree)) return MZ_STREAM_ERROR;
1059 pStream->total_in = pStream->total_out = 0;
1060 tdefl_init((tdefl_compressor*)pStream->state, NULL, NULL, ((tdefl_compressor*)pStream->state)->m_flags);
1061 return MZ_OK;
1062 }
1063
1064 int mz_deflate(mz_streamp pStream, int flush)
1065 {
1066 size_t in_bytes, out_bytes;
1067 mz_ulong orig_total_in, orig_total_out;
1068 int mz_status = MZ_OK;
1069
1070 if ((!pStream) || (!pStream->state) || (flush < 0) || (flush > MZ_FINISH) || (!pStream->next_out)) return MZ_STREAM_ERROR;
1071 if (!pStream->avail_out) return MZ_BUF_ERROR;
1072
1073 if (flush == MZ_PARTIAL_FLUSH) flush = MZ_SYNC_FLUSH;
1074
1075 if (((tdefl_compressor*)pStream->state)->m_prev_return_status == TDEFL_STATUS_DONE)
1076 return (flush == MZ_FINISH) ? MZ_STREAM_END : MZ_BUF_ERROR;
1077
1078 orig_total_in = pStream->total_in; orig_total_out = pStream->total_out;
1079 for ( ; ; )
1080 {
1081 tdefl_status defl_status;
1082 in_bytes = pStream->avail_in; out_bytes = pStream->avail_out;
1083
1084 defl_status = tdefl_compress((tdefl_compressor*)pStream->state, pStream->next_in, &in_bytes, pStream->next_out, &out_bytes, (tdefl_flush)flush);
1085 pStream->next_in += (mz_uint)in_bytes; pStream->avail_in -= (mz_uint)in_bytes;
1086 pStream->total_in += (mz_uint)in_bytes; pStream->adler = tdefl_get_adler32((tdefl_compressor*)pStream->state);
1087
1088 pStream->next_out += (mz_uint)out_bytes; pStream->avail_out -= (mz_uint)out_bytes;
1089 pStream->total_out += (mz_uint)out_bytes;
1090
1091 if (defl_status < 0)
1092 {
1093 mz_status = MZ_STREAM_ERROR;
1094 break;
1095 }
1096 else if (defl_status == TDEFL_STATUS_DONE)
1097 {
1098 mz_status = MZ_STREAM_END;
1099 break;
1100 }
1101 else if (!pStream->avail_out)
1102 break;
1103 else if ((!pStream->avail_in) && (flush != MZ_FINISH))
1104 {
1105 if ((flush) || (pStream->total_in != orig_total_in) || (pStream->total_out != orig_total_out))
1106 break;
1107 return MZ_BUF_ERROR; // Can't make forward progress without some input.
1108 }
1109 }
1110 return mz_status;
1111 }
1112
1113 int mz_deflateEnd(mz_streamp pStream)
1114 {
1115 if (!pStream) return MZ_STREAM_ERROR;
1116 if (pStream->state)
1117 {
1118 pStream->zfree(pStream->opaque, pStream->state);
1119 pStream->state = NULL;
1120 }
1121 return MZ_OK;
1122 }
1123
1124 mz_ulong mz_deflateBound(mz_streamp pStream, mz_ulong source_len)
1125 {
1126 (void)pStream;
1127 // This is really over conservative. (And lame, but it's actually pretty tricky to compute a true upper bound given the way tdefl's blocking works.)
1128 return MZ_MAX(128 + (source_len * 110) / 100, 128 + source_len + ((source_len / (31 * 1024)) + 1) * 5);
1129 }
1130
1131 int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len, int level)
1132 {
1133 int status;
1134 mz_stream stream;
1135 memset(&stream, 0, sizeof(stream));
1136
1137 // In case mz_ulong is 64-bits (argh I hate longs).
1138 if ((source_len | *pDest_len) > 0xFFFFFFFFU) return MZ_PARAM_ERROR;
1139
1140 stream.next_in = pSource;
1141 stream.avail_in = (mz_uint32)source_len;
1142 stream.next_out = pDest;
1143 stream.avail_out = (mz_uint32)*pDest_len;
1144
1145 status = mz_deflateInit(&stream, level);
1146 if (status != MZ_OK) return status;
1147
1148 status = mz_deflate(&stream, MZ_FINISH);
1149 if (status != MZ_STREAM_END)
1150 {
1151 mz_deflateEnd(&stream);
1152 return (status == MZ_OK) ? MZ_BUF_ERROR : status;
1153 }
1154
1155 *pDest_len = stream.total_out;
1156 return mz_deflateEnd(&stream);
1157 }
1158
1159 int mz_compress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len)
1160 {
1161 return mz_compress2(pDest, pDest_len, pSource, source_len, MZ_DEFAULT_COMPRESSION);
1162 }
1163
1164 mz_ulong mz_compressBound(mz_ulong source_len)
1165 {
1166 return mz_deflateBound(NULL, source_len);
1167 }
1168
1169 typedef struct
1170 {
1171 tinfl_decompressor m_decomp;
1172 mz_uint m_dict_ofs, m_dict_avail, m_first_call, m_has_flushed; int m_window_bits;
1173 mz_uint8 m_dict[TINFL_LZ_DICT_SIZE];
1174 tinfl_status m_last_status;
1175 } inflate_state;
1176
1177 int mz_inflateInit2(mz_streamp pStream, int window_bits)
1178 {
1179 inflate_state *pDecomp;
1180 if (!pStream) return MZ_STREAM_ERROR;
1181 if ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS)) return MZ_PARAM_ERROR;
1182
1183 pStream->data_type = 0;
1184 pStream->adler = 0;
1185 pStream->msg = NULL;
1186 pStream->total_in = 0;
1187 pStream->total_out = 0;
1188 pStream->reserved = 0;
1189 if (!pStream->zalloc) pStream->zalloc = def_alloc_func;
1190 if (!pStream->zfree) pStream->zfree = def_free_func;
1191
1192 pDecomp = (inflate_state*)pStream->zalloc(pStream->opaque, 1, sizeof(inflate_state));
1193 if (!pDecomp) return MZ_MEM_ERROR;
1194
1195 pStream->state = (struct mz_internal_state *)pDecomp;
1196
1197 tinfl_init(&pDecomp->m_decomp);
1198 pDecomp->m_dict_ofs = 0;
1199 pDecomp->m_dict_avail = 0;
1200 pDecomp->m_last_status = TINFL_STATUS_NEEDS_MORE_INPUT;
1201 pDecomp->m_first_call = 1;
1202 pDecomp->m_has_flushed = 0;
1203 pDecomp->m_window_bits = window_bits;
1204
1205 return MZ_OK;
1206 }
1207
1208 int mz_inflateInit(mz_streamp pStream)
1209 {
1210 return mz_inflateInit2(pStream, MZ_DEFAULT_WINDOW_BITS);
1211 }
1212
1213 int mz_inflate(mz_streamp pStream, int flush)
1214 {
1215 inflate_state* pState;
1216 mz_uint n, first_call, decomp_flags = TINFL_FLAG_COMPUTE_ADLER32;
1217 size_t in_bytes, out_bytes, orig_avail_in;
1218 tinfl_status status;
1219
1220 if ((!pStream) || (!pStream->state)) return MZ_STREAM_ERROR;
1221 if (flush == MZ_PARTIAL_FLUSH) flush = MZ_SYNC_FLUSH;
1222 if ((flush) && (flush != MZ_SYNC_FLUSH) && (flush != MZ_FINISH)) return MZ_STREAM_ERROR;
1223
1224 pState = (inflate_state*)pStream->state;
1225 if (pState->m_window_bits > 0) decomp_flags |= TINFL_FLAG_PARSE_ZLIB_HEADER;
1226 orig_avail_in = pStream->avail_in;
1227
1228 first_call = pState->m_first_call; pState->m_first_call = 0;
1229 if (pState->m_last_status < 0) return MZ_DATA_ERROR;
1230
1231 if (pState->m_has_flushed && (flush != MZ_FINISH)) return MZ_STREAM_ERROR;
1232 pState->m_has_flushed |= (flush == MZ_FINISH);
1233
1234 if ((flush == MZ_FINISH) && (first_call))
1235 {
1236 // MZ_FINISH on the first call implies that the input and output buffers are large enough to hold the entire compressed/decompressed file.
1237 decomp_flags |= TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF;
1238 in_bytes = pStream->avail_in; out_bytes = pStream->avail_out;
1239 status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes, pStream->next_out, pStream->next_out, &out_bytes, decomp_flags);
1240 pState->m_last_status = status;
1241 pStream->next_in += (mz_uint)in_bytes; pStream->avail_in -= (mz_uint)in_bytes; pStream->total_in += (mz_uint)in_bytes;
1242 pStream->adler = tinfl_get_adler32(&pState->m_decomp);
1243 pStream->next_out += (mz_uint)out_bytes; pStream->avail_out -= (mz_uint)out_bytes; pStream->total_out += (mz_uint)out_bytes;
1244
1245 if (status < 0)
1246 return MZ_DATA_ERROR;
1247 else if (status != TINFL_STATUS_DONE)
1248 {
1249 pState->m_last_status = TINFL_STATUS_FAILED;
1250 return MZ_BUF_ERROR;
1251 }
1252 return MZ_STREAM_END;
1253 }
1254 // flush != MZ_FINISH then we must assume there's more input.
1255 if (flush != MZ_FINISH) decomp_flags |= TINFL_FLAG_HAS_MORE_INPUT;
1256
1257 if (pState->m_dict_avail)
1258 {
1259 n = MZ_MIN(pState->m_dict_avail, pStream->avail_out);
1260 memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n);
1261 pStream->next_out += n; pStream->avail_out -= n; pStream->total_out += n;
1262 pState->m_dict_avail -= n; pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1);
1263 return ((pState->m_last_status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK;
1264 }
1265
1266 for ( ; ; )
1267 {
1268 in_bytes = pStream->avail_in;
1269 out_bytes = TINFL_LZ_DICT_SIZE - pState->m_dict_ofs;
1270
1271 status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes, pState->m_dict, pState->m_dict + pState->m_dict_ofs, &out_bytes, decomp_flags);
1272 pState->m_last_status = status;
1273
1274 pStream->next_in += (mz_uint)in_bytes; pStream->avail_in -= (mz_uint)in_bytes;
1275 pStream->total_in += (mz_uint)in_bytes; pStream->adler = tinfl_get_adler32(&pState->m_decomp);
1276
1277 pState->m_dict_avail = (mz_uint)out_bytes;
1278
1279 n = MZ_MIN(pState->m_dict_avail, pStream->avail_out);
1280 memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n);
1281 pStream->next_out += n; pStream->avail_out -= n; pStream->total_out += n;
1282 pState->m_dict_avail -= n; pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1);
1283
1284 if (status < 0)
1285 return MZ_DATA_ERROR; // Stream is corrupted (there could be some uncompressed data left in the output dictionary - oh well).
1286 else if ((status == TINFL_STATUS_NEEDS_MORE_INPUT) && (!orig_avail_in))
1287 return MZ_BUF_ERROR; // Signal caller that we can't make forward progress without supplying more input or by setting flush to MZ_FINISH.
1288 else if (flush == MZ_FINISH)
1289 {
1290 // The output buffer MUST be large to hold the remaining uncompressed data when flush==MZ_FINISH.
1291 if (status == TINFL_STATUS_DONE)
1292 return pState->m_dict_avail ? MZ_BUF_ERROR : MZ_STREAM_END;
1293 // status here must be TINFL_STATUS_HAS_MORE_OUTPUT, which means there's at least 1 more byte on the way. If there's no more room left in the output buffer then something is wrong.
1294 else if (!pStream->avail_out)
1295 return MZ_BUF_ERROR;
1296 }
1297 else if ((status == TINFL_STATUS_DONE) || (!pStream->avail_in) || (!pStream->avail_out) || (pState->m_dict_avail))
1298 break;
1299 }
1300
1301 return ((status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK;
1302 }
1303
1304 int mz_inflateEnd(mz_streamp pStream)
1305 {
1306 if (!pStream)
1307 return MZ_STREAM_ERROR;
1308 if (pStream->state)
1309 {
1310 pStream->zfree(pStream->opaque, pStream->state);
1311 pStream->state = NULL;
1312 }
1313 return MZ_OK;
1314 }
1315
1316 int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len)
1317 {
1318 mz_stream stream;
1319 int status;
1320 memset(&stream, 0, sizeof(stream));
1321
1322 // In case mz_ulong is 64-bits (argh I hate longs).
1323 if ((source_len | *pDest_len) > 0xFFFFFFFFU) return MZ_PARAM_ERROR;
1324
1325 stream.next_in = pSource;
1326 stream.avail_in = (mz_uint32)source_len;
1327 stream.next_out = pDest;
1328 stream.avail_out = (mz_uint32)*pDest_len;
1329
1330 status = mz_inflateInit(&stream);
1331 if (status != MZ_OK)
1332 return status;
1333
1334 status = mz_inflate(&stream, MZ_FINISH);
1335 if (status != MZ_STREAM_END)
1336 {
1337 mz_inflateEnd(&stream);
1338 return ((status == MZ_BUF_ERROR) && (!stream.avail_in)) ? MZ_DATA_ERROR : status;
1339 }
1340 *pDest_len = stream.total_out;
1341
1342 return mz_inflateEnd(&stream);
1343 }
1344
1345 const char *mz_error(int err)
1346 {
1347 static const struct { int m_err; const char *m_pDesc; } s_error_descs[] =
1348 {
1349 { MZ_OK, "" }, { MZ_STREAM_END, "stream end" }, { MZ_NEED_DICT, "need dictionary" }, { MZ_ERRNO, "file error" }, { MZ_STREAM_ERROR, "stream error" },
1350 { MZ_DATA_ERROR, "data error" }, { MZ_MEM_ERROR, "out of memory" }, { MZ_BUF_ERROR, "buf error" }, { MZ_VERSION_ERROR, "version error" }, { MZ_PARAM_ERROR, "parameter error" }
1351 };
1352 mz_uint i; for (i = 0; i < sizeof(s_error_descs) / sizeof(s_error_descs[0]); ++i) if (s_error_descs[i].m_err == err) return s_error_descs[i].m_pDesc;
1353 return NULL;
1354 }
1355
1356 #endif //MINIZ_NO_ZLIB_APIS
1357
1358 // ------------------- Low-level Decompression (completely independent from all compression API's)
1359
1360 #define TINFL_MEMCPY(d, s, l) memcpy(d, s, l)
1361 #define TINFL_MEMSET(p, c, l) memset(p, c, l)
1362
1363 #define TINFL_CR_BEGIN switch(r->m_state) { case 0:
1364 #define TINFL_CR_RETURN(state_index, result) do { status = result; r->m_state = state_index; goto common_exit; case state_index:; } MZ_MACRO_END
1365 #define TINFL_CR_RETURN_FOREVER(state_index, result) do { for ( ; ; ) { TINFL_CR_RETURN(state_index, result); } } MZ_MACRO_END
1366 #define TINFL_CR_FINISH }
1367
1368 // TODO: If the caller has indicated that there's no more input, and we attempt to read beyond the input buf, then something is wrong with the input because the inflator never
1369 // reads ahead more than it needs to. Currently TINFL_GET_BYTE() pads the end of the stream with 0's in this scenario.
1370 #define TINFL_GET_BYTE(state_index, c) do { \
1371 if (pIn_buf_cur >= pIn_buf_end) { \
1372 for ( ; ; ) { \
1373 if (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) { \
1374 TINFL_CR_RETURN(state_index, TINFL_STATUS_NEEDS_MORE_INPUT); \
1375 if (pIn_buf_cur < pIn_buf_end) { \
1376 c = *pIn_buf_cur++; \
1377 break; \
1378 } \
1379 } else { \
1380 c = 0; \
1381 break; \
1382 } \
1383 } \
1384 } else c = *pIn_buf_cur++; } MZ_MACRO_END
1385
1386 #define TINFL_NEED_BITS(state_index, n) do { mz_uint c; TINFL_GET_BYTE(state_index, c); bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); num_bits += 8; } while (num_bits < (mz_uint)(n))
1387 #define TINFL_SKIP_BITS(state_index, n) do { if (num_bits < (mz_uint)(n)) { TINFL_NEED_BITS(state_index, n); } bit_buf >>= (n); num_bits -= (n); } MZ_MACRO_END
1388 #define TINFL_GET_BITS(state_index, b, n) do { if (num_bits < (mz_uint)(n)) { TINFL_NEED_BITS(state_index, n); } b = bit_buf & ((1 << (n)) - 1); bit_buf >>= (n); num_bits -= (n); } MZ_MACRO_END
1389
1390 // TINFL_HUFF_BITBUF_FILL() is only used rarely, when the number of bytes remaining in the input buffer falls below 2.
1391 // It reads just enough bytes from the input stream that are needed to decode the next Huffman code (and absolutely no more). It works by trying to fully decode a
1392 // Huffman code by using whatever bits are currently present in the bit buffer. If this fails, it reads another byte, and tries again until it succeeds or until the
1393 // bit buffer contains >=15 bits (deflate's max. Huffman code size).
1394 #define TINFL_HUFF_BITBUF_FILL(state_index, pHuff) \
1395 do { \
1396 temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]; \
1397 if (temp >= 0) { \
1398 code_len = temp >> 9; \
1399 if ((code_len) && (num_bits >= code_len)) \
1400 break; \
1401 } else if (num_bits > TINFL_FAST_LOOKUP_BITS) { \
1402 code_len = TINFL_FAST_LOOKUP_BITS; \
1403 do { \
1404 temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; \
1405 } while ((temp < 0) && (num_bits >= (code_len + 1))); if (temp >= 0) break; \
1406 } TINFL_GET_BYTE(state_index, c); bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); num_bits += 8; \
1407 } while (num_bits < 15);
1408
1409 // TINFL_HUFF_DECODE() decodes the next Huffman coded symbol. It's more complex than you would initially expect because the zlib API expects the decompressor to never read
1410 // beyond the final byte of the deflate stream. (In other words, when this macro wants to read another byte from the input, it REALLY needs another byte in order to fully
1411 // decode the next Huffman code.) Handling this properly is particularly important on raw deflate (non-zlib) streams, which aren't followed by a byte aligned adler-32.
1412 // The slow path is only executed at the very end of the input buffer.
1413 #define TINFL_HUFF_DECODE(state_index, sym, pHuff) do { \
1414 int temp; mz_uint code_len, c; \
1415 if (num_bits < 15) { \
1416 if ((pIn_buf_end - pIn_buf_cur) < 2) { \
1417 TINFL_HUFF_BITBUF_FILL(state_index, pHuff); \
1418 } else { \
1419 bit_buf |= (((tinfl_bit_buf_t)pIn_buf_cur[0]) << num_bits) | (((tinfl_bit_buf_t)pIn_buf_cur[1]) << (num_bits + 8)); pIn_buf_cur += 2; num_bits += 16; \
1420 } \
1421 } \
1422 if ((temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0) \
1423 code_len = temp >> 9, temp &= 511; \
1424 else { \
1425 code_len = TINFL_FAST_LOOKUP_BITS; do { temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; } while (temp < 0); \
1426 } sym = temp; bit_buf >>= code_len; num_bits -= code_len; } MZ_MACRO_END
1427
1428 tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_next, size_t *pIn_buf_size, mz_uint8 *pOut_buf_start, mz_uint8 *pOut_buf_next, size_t *pOut_buf_size, const mz_uint32 decomp_flags)
1429 {
1430 static const int s_length_base[31] = { 3,4,5,6,7,8,9,10,11,13, 15,17,19,23,27,31,35,43,51,59, 67,83,99,115,131,163,195,227,258,0,0 };
1431 static const int s_length_extra[31]= { 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0 };
1432 static const int s_dist_base[32] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193, 257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0};
1433 static const int s_dist_extra[32] = { 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13};
1434 static const mz_uint8 s_length_dezigzag[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 };
1435 static const int s_min_table_sizes[3] = { 257, 1, 4 };
1436
1437 tinfl_status status = TINFL_STATUS_FAILED; mz_uint32 num_bits, dist, counter, num_extra; tinfl_bit_buf_t bit_buf;
1438 const mz_uint8 *pIn_buf_cur = pIn_buf_next, *const pIn_buf_end = pIn_buf_next + *pIn_buf_size;
1439 mz_uint8 *pOut_buf_cur = pOut_buf_next, *const pOut_buf_end = pOut_buf_next + *pOut_buf_size;
1440 size_t out_buf_size_mask = (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF) ? (size_t)-1 : ((pOut_buf_next - pOut_buf_start) + *pOut_buf_size) - 1, dist_from_out_buf_start;
1441
1442 // Ensure the output buffer's size is a power of 2, unless the output buffer is large enough to hold the entire output file (in which case it doesn't matter).
1443 if (((out_buf_size_mask + 1) & out_buf_size_mask) || (pOut_buf_next < pOut_buf_start)) { *pIn_buf_size = *pOut_buf_size = 0; return TINFL_STATUS_BAD_PARAM; }
1444
1445 num_bits = r->m_num_bits; bit_buf = r->m_bit_buf; dist = r->m_dist; counter = r->m_counter; num_extra = r->m_num_extra; dist_from_out_buf_start = r->m_dist_from_out_buf_start;
1446 TINFL_CR_BEGIN
1447
1448 bit_buf = num_bits = dist = counter = num_extra = r->m_zhdr0 = r->m_zhdr1 = 0; r->m_z_adler32 = r->m_check_adler32 = 1;
1449 if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER)
1450 {
1451 TINFL_GET_BYTE(1, r->m_zhdr0); TINFL_GET_BYTE(2, r->m_zhdr1);
1452 counter = (((r->m_zhdr0 * 256 + r->m_zhdr1) % 31 != 0) || (r->m_zhdr1 & 32) || ((r->m_zhdr0 & 15) != 8));
1453 if (!(decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)) counter |= (((1U << (8U + (r->m_zhdr0 >> 4))) > 32768U) || ((out_buf_size_mask + 1) < (size_t)(1U << (8U + (r->m_zhdr0 >> 4)))));
1454 if (counter) { TINFL_CR_RETURN_FOREVER(36, TINFL_STATUS_FAILED); }
1455 }
1456
1457 do
1458 {
1459 TINFL_GET_BITS(3, r->m_final, 3); r->m_type = r->m_final >> 1;
1460 if (r->m_type == 0)
1461 {
1462 TINFL_SKIP_BITS(5, num_bits & 7);
1463 for (counter = 0; counter < 4; ++counter) { if (num_bits) TINFL_GET_BITS(6, r->m_raw_header[counter], 8); else TINFL_GET_BYTE(7, r->m_raw_header[counter]); }
1464 if ((counter = (r->m_raw_header[0] | (r->m_raw_header[1] << 8))) != (mz_uint)(0xFFFF ^ (r->m_raw_header[2] | (r->m_raw_header[3] << 8)))) { TINFL_CR_RETURN_FOREVER(39, TINFL_STATUS_FAILED); }
1465 while ((counter) && (num_bits))
1466 {
1467 TINFL_GET_BITS(51, dist, 8);
1468 while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(52, TINFL_STATUS_HAS_MORE_OUTPUT); }
1469 *pOut_buf_cur++ = (mz_uint8)dist;
1470 counter--;
1471 }
1472 while (counter)
1473 {
1474 size_t n; while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(9, TINFL_STATUS_HAS_MORE_OUTPUT); }
1475 while (pIn_buf_cur >= pIn_buf_end)
1476 {
1477 if (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT)
1478 {
1479 TINFL_CR_RETURN(38, TINFL_STATUS_NEEDS_MORE_INPUT);
1480 }
1481 else
1482 {
1483 TINFL_CR_RETURN_FOREVER(40, TINFL_STATUS_FAILED);
1484 }
1485 }
1486 n = MZ_MIN(MZ_MIN((size_t)(pOut_buf_end - pOut_buf_cur), (size_t)(pIn_buf_end - pIn_buf_cur)), counter);
1487 TINFL_MEMCPY(pOut_buf_cur, pIn_buf_cur, n); pIn_buf_cur += n; pOut_buf_cur += n; counter -= (mz_uint)n;
1488 }
1489 }
1490 else if (r->m_type == 3)
1491 {
1492 TINFL_CR_RETURN_FOREVER(10, TINFL_STATUS_FAILED);
1493 }
1494 else
1495 {
1496 if (r->m_type == 1)
1497 {
1498 mz_uint8 *p = r->m_tables[0].m_code_size; mz_uint i;
1499 r->m_table_sizes[0] = 288; r->m_table_sizes[1] = 32; TINFL_MEMSET(r->m_tables[1].m_code_size, 5, 32);
1500 for ( i = 0; i <= 143; ++i) *p++ = 8; for ( ; i <= 255; ++i) *p++ = 9; for ( ; i <= 279; ++i) *p++ = 7; for ( ; i <= 287; ++i) *p++ = 8;
1501 }
1502 else
1503 {
1504 for (counter = 0; counter < 3; counter++) { TINFL_GET_BITS(11, r->m_table_sizes[counter], "\05\05\04"[counter]); r->m_table_sizes[counter] += s_min_table_sizes[counter]; }
1505 MZ_CLEAR_OBJ(r->m_tables[2].m_code_size); for (counter = 0; counter < r->m_table_sizes[2]; counter++) { mz_uint s; TINFL_GET_BITS(14, s, 3); r->m_tables[2].m_code_size[s_length_dezigzag[counter]] = (mz_uint8)s; }
1506 r->m_table_sizes[2] = 19;
1507 }
1508 for ( ; (int)r->m_type >= 0; r->m_type--)
1509 {
1510 int tree_next, tree_cur; tinfl_huff_table *pTable;
1511 mz_uint i, j, used_syms, total, sym_index, next_code[17], total_syms[16]; pTable = &r->m_tables[r->m_type]; MZ_CLEAR_OBJ(total_syms); MZ_CLEAR_OBJ(pTable->m_look_up); MZ_CLEAR_OBJ(pTable->m_tree);
1512 for (i = 0; i < r->m_table_sizes[r->m_type]; ++i) total_syms[pTable->m_code_size[i]]++;
1513 used_syms = 0, total = 0; next_code[0] = next_code[1] = 0;
1514 for (i = 1; i <= 15; ++i) { used_syms += total_syms[i]; next_code[i + 1] = (total = ((total + total_syms[i]) << 1)); }
1515 if ((65536 != total) && (used_syms > 1))
1516 {
1517 TINFL_CR_RETURN_FOREVER(35, TINFL_STATUS_FAILED);
1518 }
1519 for (tree_next = -1, sym_index = 0; sym_index < r->m_table_sizes[r->m_type]; ++sym_index)
1520 {
1521 mz_uint rev_code = 0, l, cur_code, code_size = pTable->m_code_size[sym_index]; if (!code_size) continue;
1522 cur_code = next_code[code_size]++; for (l = code_size; l > 0; l--, cur_code >>= 1) rev_code = (rev_code << 1) | (cur_code & 1);
1523 if (code_size <= TINFL_FAST_LOOKUP_BITS) { mz_int16 k = (mz_int16)((code_size << 9) | sym_index); while (rev_code < TINFL_FAST_LOOKUP_SIZE) { pTable->m_look_up[rev_code] = k; rev_code += (1 << code_size); } continue; }
1524 if (0 == (tree_cur = pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)])) { pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)] = (mz_int16)tree_next; tree_cur = tree_next; tree_next -= 2; }
1525 rev_code >>= (TINFL_FAST_LOOKUP_BITS - 1);
1526 for (j = code_size; j > (TINFL_FAST_LOOKUP_BITS + 1); j--)
1527 {
1528 tree_cur -= ((rev_code >>= 1) & 1);
1529 if (!pTable->m_tree[-tree_cur - 1]) { pTable->m_tree[-tree_cur - 1] = (mz_int16)tree_next; tree_cur = tree_next; tree_next -= 2; } else tree_cur = pTable->m_tree[-tree_cur - 1];
1530 }
1531 tree_cur -= ((rev_code >>= 1) & 1); pTable->m_tree[-tree_cur - 1] = (mz_int16)sym_index;
1532 }
1533 if (r->m_type == 2)
1534 {
1535 for (counter = 0; counter < (r->m_table_sizes[0] + r->m_table_sizes[1]); )
1536 {
1537 mz_uint s; TINFL_HUFF_DECODE(16, dist, &r->m_tables[2]); if (dist < 16) { r->m_len_codes[counter++] = (mz_uint8)dist; continue; }
1538 if ((dist == 16) && (!counter))
1539 {
1540 TINFL_CR_RETURN_FOREVER(17, TINFL_STATUS_FAILED);
1541 }
1542 num_extra = "\02\03\07"[dist - 16]; TINFL_GET_BITS(18, s, num_extra); s += "\03\03\013"[dist - 16];
1543 TINFL_MEMSET(r->m_len_codes + counter, (dist == 16) ? r->m_len_codes[counter - 1] : 0, s); counter += s;
1544 }
1545 if ((r->m_table_sizes[0] + r->m_table_sizes[1]) != counter)
1546 {
1547 TINFL_CR_RETURN_FOREVER(21, TINFL_STATUS_FAILED);
1548 }
1549 TINFL_MEMCPY(r->m_tables[0].m_code_size, r->m_len_codes, r->m_table_sizes[0]); TINFL_MEMCPY(r->m_tables[1].m_code_size, r->m_len_codes + r->m_table_sizes[0], r->m_table_sizes[1]);
1550 }
1551 }
1552 for ( ; ; )
1553 {
1554 mz_uint8 *pSrc;
1555 for ( ; ; )
1556 {
1557 if (((pIn_buf_end - pIn_buf_cur) < 4) || ((pOut_buf_end - pOut_buf_cur) < 2))
1558 {
1559 TINFL_HUFF_DECODE(23, counter, &r->m_tables[0]);
1560 if (counter >= 256)
1561 break;
1562 while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(24, TINFL_STATUS_HAS_MORE_OUTPUT); }
1563 *pOut_buf_cur++ = (mz_uint8)counter;
1564 }
1565 else
1566 {
1567 int sym2; mz_uint code_len;
1568 #if TINFL_USE_64BIT_BITBUF
1569 if (num_bits < 30) { bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE32(pIn_buf_cur)) << num_bits); pIn_buf_cur += 4; num_bits += 32; }
1570 #else
1571 if (num_bits < 15) { bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits); pIn_buf_cur += 2; num_bits += 16; }
1572 #endif
1573 if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0)
1574 code_len = sym2 >> 9;
1575 else
1576 {
1577 code_len = TINFL_FAST_LOOKUP_BITS; do { sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)]; } while (sym2 < 0);
1578 }
1579 counter = sym2; bit_buf >>= code_len; num_bits -= code_len;
1580 if (counter & 256)
1581 break;
1582
1583 #if !TINFL_USE_64BIT_BITBUF
1584 if (num_bits < 15) { bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits); pIn_buf_cur += 2; num_bits += 16; }
1585 #endif
1586 if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0)
1587 code_len = sym2 >> 9;
1588 else
1589 {
1590 code_len = TINFL_FAST_LOOKUP_BITS; do { sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)]; } while (sym2 < 0);
1591 }
1592 bit_buf >>= code_len; num_bits -= code_len;
1593
1594 pOut_buf_cur[0] = (mz_uint8)counter;
1595 if (sym2 & 256)
1596 {
1597 pOut_buf_cur++;
1598 counter = sym2;
1599 break;
1600 }
1601 pOut_buf_cur[1] = (mz_uint8)sym2;
1602 pOut_buf_cur += 2;
1603 }
1604 }
1605 if ((counter &= 511) == 256) break;
1606
1607 num_extra = s_length_extra[counter - 257]; counter = s_length_base[counter - 257];
1608 if (num_extra) { mz_uint extra_bits; TINFL_GET_BITS(25, extra_bits, num_extra); counter += extra_bits; }
1609
1610 TINFL_HUFF_DECODE(26, dist, &r->m_tables[1]);
1611 num_extra = s_dist_extra[dist]; dist = s_dist_base[dist];
1612 if (num_extra) { mz_uint extra_bits; TINFL_GET_BITS(27, extra_bits, num_extra); dist += extra_bits; }
1613
1614 dist_from_out_buf_start = pOut_buf_cur - pOut_buf_start;
1615 if ((dist > dist_from_out_buf_start) && (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF))
1616 {
1617 TINFL_CR_RETURN_FOREVER(37, TINFL_STATUS_FAILED);
1618 }
1619
1620 pSrc = pOut_buf_start + ((dist_from_out_buf_start - dist) & out_buf_size_mask);
1621
1622 if ((MZ_MAX(pOut_buf_cur, pSrc) + counter) > pOut_buf_end)
1623 {
1624 while (counter--)
1625 {
1626 while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(53, TINFL_STATUS_HAS_MORE_OUTPUT); }
1627 *pOut_buf_cur++ = pOut_buf_start[(dist_from_out_buf_start++ - dist) & out_buf_size_mask];
1628 }
1629 continue;
1630 }
1631 #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES
1632 else if ((counter >= 9) && (counter <= dist))
1633 {
1634 const mz_uint8 *pSrc_end = pSrc + (counter & ~7);
1635 do
1636 {
1637 ((mz_uint32 *)pOut_buf_cur)[0] = ((const mz_uint32 *)pSrc)[0];
1638 ((mz_uint32 *)pOut_buf_cur)[1] = ((const mz_uint32 *)pSrc)[1];
1639 pOut_buf_cur += 8;
1640 } while ((pSrc += 8) < pSrc_end);
1641 if ((counter &= 7) < 3)
1642 {
1643 if (counter)
1644 {
1645 pOut_buf_cur[0] = pSrc[0];
1646 if (counter > 1)
1647 pOut_buf_cur[1] = pSrc[1];
1648 pOut_buf_cur += counter;
1649 }
1650 continue;
1651 }
1652 }
1653 #endif
1654 do
1655 {
1656 pOut_buf_cur[0] = pSrc[0];
1657 pOut_buf_cur[1] = pSrc[1];
1658 pOut_buf_cur[2] = pSrc[2];
1659 pOut_buf_cur += 3; pSrc += 3;
1660 } while ((int)(counter -= 3) > 2);
1661 if ((int)counter > 0)
1662 {
1663 pOut_buf_cur[0] = pSrc[0];
1664 if ((int)counter > 1)
1665 pOut_buf_cur[1] = pSrc[1];
1666 pOut_buf_cur += counter;
1667 }
1668 }
1669 }
1670 } while (!(r->m_final & 1));
1671 if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER)
1672 {
1673 TINFL_SKIP_BITS(32, num_bits & 7); for (counter = 0; counter < 4; ++counter) { mz_uint s; if (num_bits) TINFL_GET_BITS(41, s, 8); else TINFL_GET_BYTE(42, s); r->m_z_adler32 = (r->m_z_adler32 << 8) | s; }
1674 }
1675 TINFL_CR_RETURN_FOREVER(34, TINFL_STATUS_DONE);
1676 TINFL_CR_FINISH
1677
1678 common_exit:
1679 r->m_num_bits = num_bits; r->m_bit_buf = bit_buf; r->m_dist = dist; r->m_counter = counter; r->m_num_extra = num_extra; r->m_dist_from_out_buf_start = dist_from_out_buf_start;
1680 *pIn_buf_size = pIn_buf_cur - pIn_buf_next; *pOut_buf_size = pOut_buf_cur - pOut_buf_next;
1681 if ((decomp_flags & (TINFL_FLAG_PARSE_ZLIB_HEADER | TINFL_FLAG_COMPUTE_ADLER32)) && (status >= 0))
1682 {
1683 const mz_uint8 *ptr = pOut_buf_next; size_t buf_len = *pOut_buf_size;
1684 mz_uint32 i, s1 = r->m_check_adler32 & 0xffff, s2 = r->m_check_adler32 >> 16; size_t block_len = buf_len % 5552;
1685 while (buf_len)
1686 {
1687 for (i = 0; i + 7 < block_len; i += 8, ptr += 8)
1688 {
1689 s1 += ptr[0], s2 += s1; s1 += ptr[1], s2 += s1; s1 += ptr[2], s2 += s1; s1 += ptr[3], s2 += s1;
1690 s1 += ptr[4], s2 += s1; s1 += ptr[5], s2 += s1; s1 += ptr[6], s2 += s1; s1 += ptr[7], s2 += s1;
1691 }
1692 for ( ; i < block_len; ++i) s1 += *ptr++, s2 += s1;
1693 s1 %= 65521U, s2 %= 65521U; buf_len -= block_len; block_len = 5552;
1694 }
1695 r->m_check_adler32 = (s2 << 16) + s1; if ((status == TINFL_STATUS_DONE) && (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) && (r->m_check_adler32 != r->m_z_adler32)) status = TINFL_STATUS_ADLER32_MISMATCH;
1696 }
1697 return status;
1698 }
1699
1700 // Higher level helper functions.
1701 void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags)
1702 {
1703 tinfl_decompressor decomp; void *pBuf = NULL, *pNew_buf; size_t src_buf_ofs = 0, out_buf_capacity = 0;
1704 *pOut_len = 0;
1705 tinfl_init(&decomp);
1706 for ( ; ; )
1707 {
1708 size_t src_buf_size = src_buf_len - src_buf_ofs, dst_buf_size = out_buf_capacity - *pOut_len, new_out_buf_capacity;
1709 tinfl_status status = tinfl_decompress(&decomp, (const mz_uint8*)pSrc_buf + src_buf_ofs, &src_buf_size, (mz_uint8*)pBuf, pBuf ? (mz_uint8*)pBuf + *pOut_len : NULL, &dst_buf_size,
1710 (flags & ~TINFL_FLAG_HAS_MORE_INPUT) | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF);
1711 if ((status < 0) || (status == TINFL_STATUS_NEEDS_MORE_INPUT))
1712 {
1713 MZ_FREE(pBuf); *pOut_len = 0; return NULL;
1714 }
1715 src_buf_ofs += src_buf_size;
1716 *pOut_len += dst_buf_size;
1717 if (status == TINFL_STATUS_DONE) break;
1718 new_out_buf_capacity = out_buf_capacity * 2; if (new_out_buf_capacity < 128) new_out_buf_capacity = 128;
1719 pNew_buf = MZ_REALLOC(pBuf, new_out_buf_capacity);
1720 if (!pNew_buf)
1721 {
1722 MZ_FREE(pBuf); *pOut_len = 0; return NULL;
1723 }
1724 pBuf = pNew_buf; out_buf_capacity = new_out_buf_capacity;
1725 }
1726 return pBuf;
1727 }
1728
1729 size_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags)
1730 {
1731 tinfl_decompressor decomp; tinfl_status status; tinfl_init(&decomp);
1732 status = tinfl_decompress(&decomp, (const mz_uint8*)pSrc_buf, &src_buf_len, (mz_uint8*)pOut_buf, (mz_uint8*)pOut_buf, &out_buf_len, (flags & ~TINFL_FLAG_HAS_MORE_INPUT) | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF);
1733 return (status != TINFL_STATUS_DONE) ? TINFL_DECOMPRESS_MEM_TO_MEM_FAILED : out_buf_len;
1734 }
1735
1736 int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size, tinfl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags)
1737 {
1738 int result = 0;
1739 tinfl_decompressor decomp;
1740 mz_uint8 *pDict = (mz_uint8*)MZ_MALLOC(TINFL_LZ_DICT_SIZE); size_t in_buf_ofs = 0, dict_ofs = 0;
1741 if (!pDict)
1742 return TINFL_STATUS_FAILED;
1743 tinfl_init(&decomp);
1744 for ( ; ; )
1745 {
1746 size_t in_buf_size = *pIn_buf_size - in_buf_ofs, dst_buf_size = TINFL_LZ_DICT_SIZE - dict_ofs;
1747 tinfl_status status = tinfl_decompress(&decomp, (const mz_uint8*)pIn_buf + in_buf_ofs, &in_buf_size, pDict, pDict + dict_ofs, &dst_buf_size,
1748 (flags & ~(TINFL_FLAG_HAS_MORE_INPUT | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)));
1749 in_buf_ofs += in_buf_size;
1750 if ((dst_buf_size) && (!(*pPut_buf_func)(pDict + dict_ofs, (int)dst_buf_size, pPut_buf_user)))
1751 break;
1752 if (status != TINFL_STATUS_HAS_MORE_OUTPUT)
1753 {
1754 result = (status == TINFL_STATUS_DONE);
1755 break;
1756 }
1757 dict_ofs = (dict_ofs + dst_buf_size) & (TINFL_LZ_DICT_SIZE - 1);
1758 }
1759 MZ_FREE(pDict);
1760 *pIn_buf_size = in_buf_ofs;
1761 return result;
1762 }
1763
1764 // ------------------- Low-level Compression (independent from all decompression API's)
1765
1766 // Purposely making these tables static for faster init and thread safety.
1767 static const mz_uint16 s_tdefl_len_sym[256] = {
1768 257,258,259,260,261,262,263,264,265,265,266,266,267,267,268,268,269,269,269,269,270,270,270,270,271,271,271,271,272,272,272,272,
1769 273,273,273,273,273,273,273,273,274,274,274,274,274,274,274,274,275,275,275,275,275,275,275,275,276,276,276,276,276,276,276,276,
1770 277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,
1771 279,279,279,279,279,279,279,279,279,279,279,279,279,279,279,279,280,280,280,280,280,280,280,280,280,280,280,280,280,280,280,280,
1772 281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,
1773 282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,
1774 283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,
1775 284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,285 };
1776
1777 static const mz_uint8 s_tdefl_len_extra[256] = {
1778 0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
1779 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
1780 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
1781 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0 };
1782
1783 static const mz_uint8 s_tdefl_small_dist_sym[512] = {
1784 0,1,2,3,4,4,5,5,6,6,6,6,7,7,7,7,8,8,8,8,8,8,8,8,9,9,9,9,9,9,9,9,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,11,11,11,11,11,11,
1785 11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,13,
1786 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,14,14,14,14,14,14,14,14,14,14,14,14,
1787 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,
1788 14,14,14,14,14,14,14,14,14,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
1789 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,16,16,16,16,16,16,16,16,16,16,16,16,16,
1790 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
1791 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
1792 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
1793 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
1794 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
1795 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17 };
1796
1797 static const mz_uint8 s_tdefl_small_dist_extra[512] = {
1798 0,0,0,0,1,1,1,1,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,
1799 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1800 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1801 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1802 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1803 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1804 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1805 7,7,7,7,7,7,7,7 };
1806
1807 static const mz_uint8 s_tdefl_large_dist_sym[128] = {
1808 0,0,18,19,20,20,21,21,22,22,22,22,23,23,23,23,24,24,24,24,24,24,24,24,25,25,25,25,25,25,25,25,26,26,26,26,26,26,26,26,26,26,26,26,
1809 26,26,26,26,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,
1810 28,28,28,28,28,28,28,28,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29 };
1811
1812 static const mz_uint8 s_tdefl_large_dist_extra[128] = {
1813 0,0,8,8,9,9,9,9,10,10,10,10,10,10,10,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
1814 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,
1815 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13 };
1816
1817 // Radix sorts tdefl_sym_freq[] array by 16-bit key m_key. Returns ptr to sorted values.
1818 typedef struct { mz_uint16 m_key, m_sym_index; } tdefl_sym_freq;
1819 static tdefl_sym_freq* tdefl_radix_sort_syms(mz_uint num_syms, tdefl_sym_freq* pSyms0, tdefl_sym_freq* pSyms1)
1820 {
1821 mz_uint32 total_passes = 2, pass_shift, pass, i, hist[256 * 2]; tdefl_sym_freq* pCur_syms = pSyms0, *pNew_syms = pSyms1; MZ_CLEAR_OBJ(hist);
1822 for (i = 0; i < num_syms; i++) { mz_uint freq = pSyms0[i].m_key; hist[freq & 0xFF]++; hist[256 + ((freq >> 8) & 0xFF)]++; }
1823 while ((total_passes > 1) && (num_syms == hist[(total_passes - 1) * 256])) total_passes--;
1824 for (pass_shift = 0, pass = 0; pass < total_passes; pass++, pass_shift += 8)
1825 {
1826 const mz_uint32* pHist = &hist[pass << 8];
1827 mz_uint offsets[256], cur_ofs = 0;
1828 for (i = 0; i < 256; i++) { offsets[i] = cur_ofs; cur_ofs += pHist[i]; }
1829 for (i = 0; i < num_syms; i++) pNew_syms[offsets[(pCur_syms[i].m_key >> pass_shift) & 0xFF]++] = pCur_syms[i];
1830 { tdefl_sym_freq* t = pCur_syms; pCur_syms = pNew_syms; pNew_syms = t; }
1831 }
1832 return pCur_syms;
1833 }
1834
1835 // tdefl_calculate_minimum_redundancy() originally written by: Alistair Moffat, [email protected], Jyrki Katajainen, [email protected], November 1996.
1836 static void tdefl_calculate_minimum_redundancy(tdefl_sym_freq *A, int n)
1837 {
1838 int root, leaf, next, avbl, used, dpth;
1839 if (n==0) return; else if (n==1) { A[0].m_key = 1; return; }
1840 A[0].m_key += A[1].m_key; root = 0; leaf = 2;
1841 for (next=1; next < n-1; next++)
1842 {
1843 if (leaf>=n || A[root].m_key<A[leaf].m_key) { A[next].m_key = A[root].m_key; A[root++].m_key = (mz_uint16)next; } else A[next].m_key = A[leaf++].m_key;
1844 if (leaf>=n || (root<next && A[root].m_key<A[leaf].m_key)) { A[next].m_key = (mz_uint16)(A[next].m_key + A[root].m_key); A[root++].m_key = (mz_uint16)next; } else A[next].m_key = (mz_uint16)(A[next].m_key + A[leaf++].m_key);
1845 }
1846 A[n-2].m_key = 0; for (next=n-3; next>=0; next--) A[next].m_key = A[A[next].m_key].m_key+1;
1847 avbl = 1; used = dpth = 0; root = n-2; next = n-1;
1848 while (avbl>0)
1849 {
1850 while (root>=0 && (int)A[root].m_key==dpth) { used++; root--; }
1851 while (avbl>used) { A[next--].m_key = (mz_uint16)(dpth); avbl--; }
1852 avbl = 2*used; dpth++; used = 0;
1853 }
1854 }
1855
1856 // Limits canonical Huffman code table's max code size.
1857 enum { TDEFL_MAX_SUPPORTED_HUFF_CODESIZE = 32 };
1858 static void tdefl_huffman_enforce_max_code_size(int *pNum_codes, int code_list_len, int max_code_size)
1859 {
1860 int i; mz_uint32 total = 0; if (code_list_len <= 1) return;
1861 for (i = max_code_size + 1; i <= TDEFL_MAX_SUPPORTED_HUFF_CODESIZE; i++) pNum_codes[max_code_size] += pNum_codes[i];
1862 for (i = max_code_size; i > 0; i--) total += (((mz_uint32)pNum_codes[i]) << (max_code_size - i));
1863 while (total != (1UL << max_code_size))
1864 {
1865 pNum_codes[max_code_size]--;
1866 for (i = max_code_size - 1; i > 0; i--) if (pNum_codes[i]) { pNum_codes[i]--; pNum_codes[i + 1] += 2; break; }
1867 total--;
1868 }
1869 }
1870
1871 static void tdefl_optimize_huffman_table(tdefl_compressor *d, int table_num, int table_len, int code_size_limit, int static_table)
1872 {
1873 int i, j, l, num_codes[1 + TDEFL_MAX_SUPPORTED_HUFF_CODESIZE]; mz_uint next_code[TDEFL_MAX_SUPPORTED_HUFF_CODESIZE + 1]; MZ_CLEAR_OBJ(num_codes);
1874 if (static_table)
1875 {
1876 for (i = 0; i < table_len; i++) num_codes[d->m_huff_code_sizes[table_num][i]]++;
1877 }
1878 else
1879 {
1880 tdefl_sym_freq syms0[TDEFL_MAX_HUFF_SYMBOLS], syms1[TDEFL_MAX_HUFF_SYMBOLS], *pSyms;
1881 int num_used_syms = 0;
1882 const mz_uint16 *pSym_count = &d->m_huff_count[table_num][0];
1883 for (i = 0; i < table_len; i++) if (pSym_count[i]) { syms0[num_used_syms].m_key = (mz_uint16)pSym_count[i]; syms0[num_used_syms++].m_sym_index = (mz_uint16)i; }
1884
1885 pSyms = tdefl_radix_sort_syms(num_used_syms, syms0, syms1); tdefl_calculate_minimum_redundancy(pSyms, num_used_syms);
1886
1887 for (i = 0; i < num_used_syms; i++) num_codes[pSyms[i].m_key]++;
1888
1889 tdefl_huffman_enforce_max_code_size(num_codes, num_used_syms, code_size_limit);
1890
1891 MZ_CLEAR_OBJ(d->m_huff_code_sizes[table_num]); MZ_CLEAR_OBJ(d->m_huff_codes[table_num]);
1892 for (i = 1, j = num_used_syms; i <= code_size_limit; i++)
1893 for (l = num_codes[i]; l > 0; l--) d->m_huff_code_sizes[table_num][pSyms[--j].m_sym_index] = (mz_uint8)(i);
1894 }
1895
1896 next_code[1] = 0; for (j = 0, i = 2; i <= code_size_limit; i++) next_code[i] = j = ((j + num_codes[i - 1]) << 1);
1897
1898 for (i = 0; i < table_len; i++)
1899 {
1900 mz_uint rev_code = 0, code, code_size; if ((code_size = d->m_huff_code_sizes[table_num][i]) == 0) continue;
1901 code = next_code[code_size]++; for (l = code_size; l > 0; l--, code >>= 1) rev_code = (rev_code << 1) | (code & 1);
1902 d->m_huff_codes[table_num][i] = (mz_uint16)rev_code;
1903 }
1904 }
1905
1906 #define TDEFL_PUT_BITS(b, l) do { \
1907 mz_uint bits = b; mz_uint len = l; MZ_ASSERT(bits <= ((1U << len) - 1U)); \
1908 d->m_bit_buffer |= (bits << d->m_bits_in); d->m_bits_in += len; \
1909 while (d->m_bits_in >= 8) { \
1910 if (d->m_pOutput_buf < d->m_pOutput_buf_end) \
1911 *d->m_pOutput_buf++ = (mz_uint8)(d->m_bit_buffer); \
1912 d->m_bit_buffer >>= 8; \
1913 d->m_bits_in -= 8; \
1914 } \
1915 } MZ_MACRO_END
1916
1917 #define TDEFL_RLE_PREV_CODE_SIZE() { if (rle_repeat_count) { \
1918 if (rle_repeat_count < 3) { \
1919 d->m_huff_count[2][prev_code_size] = (mz_uint16)(d->m_huff_count[2][prev_code_size] + rle_repeat_count); \
1920 while (rle_repeat_count--) packed_code_sizes[num_packed_code_sizes++] = prev_code_size; \
1921 } else { \
1922 d->m_huff_count[2][16] = (mz_uint16)(d->m_huff_count[2][16] + 1); packed_code_sizes[num_packed_code_sizes++] = 16; packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_repeat_count - 3); \
1923 } rle_repeat_count = 0; } }
1924
1925 #define TDEFL_RLE_ZERO_CODE_SIZE() { if (rle_z_count) { \
1926 if (rle_z_count < 3) { \
1927 d->m_huff_count[2][0] = (mz_uint16)(d->m_huff_count[2][0] + rle_z_count); while (rle_z_count--) packed_code_sizes[num_packed_code_sizes++] = 0; \
1928 } else if (rle_z_count <= 10) { \
1929 d->m_huff_count[2][17] = (mz_uint16)(d->m_huff_count[2][17] + 1); packed_code_sizes[num_packed_code_sizes++] = 17; packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_z_count - 3); \
1930 } else { \
1931 d->m_huff_count[2][18] = (mz_uint16)(d->m_huff_count[2][18] + 1); packed_code_sizes[num_packed_code_sizes++] = 18; packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_z_count - 11); \
1932 } rle_z_count = 0; } }
1933
1934 static mz_uint8 s_tdefl_packed_code_size_syms_swizzle[] = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 };
1935
1936 static void tdefl_start_dynamic_block(tdefl_compressor *d)
1937 {
1938 int num_lit_codes, num_dist_codes, num_bit_lengths; mz_uint i, total_code_sizes_to_pack, num_packed_code_sizes, rle_z_count, rle_repeat_count, packed_code_sizes_index;
1939 mz_uint8 code_sizes_to_pack[TDEFL_MAX_HUFF_SYMBOLS_0 + TDEFL_MAX_HUFF_SYMBOLS_1], packed_code_sizes[TDEFL_MAX_HUFF_SYMBOLS_0 + TDEFL_MAX_HUFF_SYMBOLS_1], prev_code_size = 0xFF;
1940
1941 d->m_huff_count[0][256] = 1;
1942
1943 tdefl_optimize_huffman_table(d, 0, TDEFL_MAX_HUFF_SYMBOLS_0, 15, MZ_FALSE);
1944 tdefl_optimize_huffman_table(d, 1, TDEFL_MAX_HUFF_SYMBOLS_1, 15, MZ_FALSE);
1945
1946 for (num_lit_codes = 286; num_lit_codes > 257; num_lit_codes--) if (d->m_huff_code_sizes[0][num_lit_codes - 1]) break;
1947 for (num_dist_codes = 30; num_dist_codes > 1; num_dist_codes--) if (d->m_huff_code_sizes[1][num_dist_codes - 1]) break;
1948
1949 memcpy(code_sizes_to_pack, &d->m_huff_code_sizes[0][0], num_lit_codes);
1950 memcpy(code_sizes_to_pack + num_lit_codes, &d->m_huff_code_sizes[1][0], num_dist_codes);
1951 total_code_sizes_to_pack = num_lit_codes + num_dist_codes; num_packed_code_sizes = 0; rle_z_count = 0; rle_repeat_count = 0;
1952
1953 memset(&d->m_huff_count[2][0], 0, sizeof(d->m_huff_count[2][0]) * TDEFL_MAX_HUFF_SYMBOLS_2);
1954 for (i = 0; i < total_code_sizes_to_pack; i++)
1955 {
1956 mz_uint8 code_size = code_sizes_to_pack[i];
1957 if (!code_size)
1958 {
1959 TDEFL_RLE_PREV_CODE_SIZE();
1960 if (++rle_z_count == 138) { TDEFL_RLE_ZERO_CODE_SIZE(); }
1961 }
1962 else
1963 {
1964 TDEFL_RLE_ZERO_CODE_SIZE();
1965 if (code_size != prev_code_size)
1966 {
1967 TDEFL_RLE_PREV_CODE_SIZE();
1968 d->m_huff_count[2][code_size] = (mz_uint16)(d->m_huff_count[2][code_size] + 1); packed_code_sizes[num_packed_code_sizes++] = code_size;
1969 }
1970 else if (++rle_repeat_count == 6)
1971 {
1972 TDEFL_RLE_PREV_CODE_SIZE();
1973 }
1974 }
1975 prev_code_size = code_size;
1976 }
1977 if (rle_repeat_count) { TDEFL_RLE_PREV_CODE_SIZE(); } else { TDEFL_RLE_ZERO_CODE_SIZE(); }
1978
1979 tdefl_optimize_huffman_table(d, 2, TDEFL_MAX_HUFF_SYMBOLS_2, 7, MZ_FALSE);
1980
1981 TDEFL_PUT_BITS(2, 2);
1982
1983 TDEFL_PUT_BITS(num_lit_codes - 257, 5);
1984 TDEFL_PUT_BITS(num_dist_codes - 1, 5);
1985
1986 for (num_bit_lengths = 18; num_bit_lengths >= 0; num_bit_lengths--) if (d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[num_bit_lengths]]) break;
1987 num_bit_lengths = MZ_MAX(4, (num_bit_lengths + 1)); TDEFL_PUT_BITS(num_bit_lengths - 4, 4);
1988 for (i = 0; (int)i < num_bit_lengths; i++) TDEFL_PUT_BITS(d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[i]], 3);
1989
1990 for (packed_code_sizes_index = 0; packed_code_sizes_index < num_packed_code_sizes; )
1991 {
1992 mz_uint code = packed_code_sizes[packed_code_sizes_index++]; MZ_ASSERT(code < TDEFL_MAX_HUFF_SYMBOLS_2);
1993 TDEFL_PUT_BITS(d->m_huff_codes[2][code], d->m_huff_code_sizes[2][code]);
1994 if (code >= 16) TDEFL_PUT_BITS(packed_code_sizes[packed_code_sizes_index++], "\02\03\07"[code - 16]);
1995 }
1996 }
1997
1998 static void tdefl_start_static_block(tdefl_compressor *d)
1999 {
2000 mz_uint i;
2001 mz_uint8 *p = &d->m_huff_code_sizes[0][0];
2002
2003 for (i = 0; i <= 143; ++i) *p++ = 8;
2004 for ( ; i <= 255; ++i) *p++ = 9;
2005 for ( ; i <= 279; ++i) *p++ = 7;
2006 for ( ; i <= 287; ++i) *p++ = 8;
2007
2008 memset(d->m_huff_code_sizes[1], 5, 32);
2009
2010 tdefl_optimize_huffman_table(d, 0, 288, 15, MZ_TRUE);
2011 tdefl_optimize_huffman_table(d, 1, 32, 15, MZ_TRUE);
2012
2013 TDEFL_PUT_BITS(1, 2);
2014 }
2015
2016 static const mz_uint mz_bitmasks[17] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };
2017
2018 #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN && MINIZ_HAS_64BIT_REGISTERS
2019 static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d)
2020 {
2021 mz_uint flags;
2022 mz_uint8 *pLZ_codes;
2023 mz_uint8 *pOutput_buf = d->m_pOutput_buf;
2024 mz_uint8 *pLZ_code_buf_end = d->m_pLZ_code_buf;
2025 mz_uint64 bit_buffer = d->m_bit_buffer;
2026 mz_uint bits_in = d->m_bits_in;
2027
2028 #define TDEFL_PUT_BITS_FAST(b, l) { bit_buffer |= (((mz_uint64)(b)) << bits_in); bits_in += (l); }
2029
2030 flags = 1;
2031 for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < pLZ_code_buf_end; flags >>= 1)
2032 {
2033 if (flags == 1)
2034 flags = *pLZ_codes++ | 0x100;
2035
2036 if (flags & 1)
2037 {
2038 mz_uint s0, s1, n0, n1, sym, num_extra_bits;
2039 mz_uint match_len = pLZ_codes[0], match_dist = *(const mz_uint16 *)(pLZ_codes + 1); pLZ_codes += 3;
2040
2041 MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
2042 TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][s_tdefl_len_sym[match_len]], d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
2043 TDEFL_PUT_BITS_FAST(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], s_tdefl_len_extra[match_len]);
2044
2045 // This sequence coaxes MSVC into using cmov's vs. jmp's.
2046 s0 = s_tdefl_small_dist_sym[match_dist & 511];
2047 n0 = s_tdefl_small_dist_extra[match_dist & 511];
2048 s1 = s_tdefl_large_dist_sym[match_dist >> 8];
2049 n1 = s_tdefl_large_dist_extra[match_dist >> 8];
2050 sym = (match_dist < 512) ? s0 : s1;
2051 num_extra_bits = (match_dist < 512) ? n0 : n1;
2052
2053 MZ_ASSERT(d->m_huff_code_sizes[1][sym]);
2054 TDEFL_PUT_BITS_FAST(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]);
2055 TDEFL_PUT_BITS_FAST(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits);
2056 }
2057 else
2058 {
2059 mz_uint lit = *pLZ_codes++;
2060 MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
2061 TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
2062
2063 if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end))
2064 {
2065 flags >>= 1;
2066 lit = *pLZ_codes++;
2067 MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
2068 TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
2069
2070 if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end))
2071 {
2072 flags >>= 1;
2073 lit = *pLZ_codes++;
2074 MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
2075 TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
2076 }
2077 }
2078 }
2079
2080 if (pOutput_buf >= d->m_pOutput_buf_end)
2081 return MZ_FALSE;
2082
2083 *(mz_uint64*)pOutput_buf = bit_buffer;
2084 pOutput_buf += (bits_in >> 3);
2085 bit_buffer >>= (bits_in & ~7);
2086 bits_in &= 7;
2087 }
2088
2089 #undef TDEFL_PUT_BITS_FAST
2090
2091 d->m_pOutput_buf = pOutput_buf;
2092 d->m_bits_in = 0;
2093 d->m_bit_buffer = 0;
2094
2095 while (bits_in)
2096 {
2097 mz_uint32 n = MZ_MIN(bits_in, 16);
2098 TDEFL_PUT_BITS((mz_uint)bit_buffer & mz_bitmasks[n], n);
2099 bit_buffer >>= n;
2100 bits_in -= n;
2101 }
2102
2103 TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]);
2104
2105 return (d->m_pOutput_buf < d->m_pOutput_buf_end);
2106 }
2107 #else
2108 static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d)
2109 {
2110 mz_uint flags;
2111 mz_uint8 *pLZ_codes;
2112
2113 flags = 1;
2114 for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < d->m_pLZ_code_buf; flags >>= 1)
2115 {
2116 if (flags == 1)
2117 flags = *pLZ_codes++ | 0x100;
2118 if (flags & 1)
2119 {
2120 mz_uint sym, num_extra_bits;
2121 mz_uint match_len = pLZ_codes[0], match_dist = (pLZ_codes[1] | (pLZ_codes[2] << 8)); pLZ_codes += 3;
2122
2123 MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
2124 TDEFL_PUT_BITS(d->m_huff_codes[0][s_tdefl_len_sym[match_len]], d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
2125 TDEFL_PUT_BITS(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], s_tdefl_len_extra[match_len]);
2126
2127 if (match_dist < 512)
2128 {
2129 sym = s_tdefl_small_dist_sym[match_dist]; num_extra_bits = s_tdefl_small_dist_extra[match_dist];
2130 }
2131 else
2132 {
2133 sym = s_tdefl_large_dist_sym[match_dist >> 8]; num_extra_bits = s_tdefl_large_dist_extra[match_dist >> 8];
2134 }
2135 MZ_ASSERT(d->m_huff_code_sizes[1][sym]);
2136 TDEFL_PUT_BITS(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]);
2137 TDEFL_PUT_BITS(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits);
2138 }
2139 else
2140 {
2141 mz_uint lit = *pLZ_codes++;
2142 MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
2143 TDEFL_PUT_BITS(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
2144 }
2145 }
2146
2147 TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]);
2148
2149 return (d->m_pOutput_buf < d->m_pOutput_buf_end);
2150 }
2151 #endif // MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN && MINIZ_HAS_64BIT_REGISTERS
2152
2153 static mz_bool tdefl_compress_block(tdefl_compressor *d, mz_bool static_block)
2154 {
2155 if (static_block)
2156 tdefl_start_static_block(d);
2157 else
2158 tdefl_start_dynamic_block(d);
2159 return tdefl_compress_lz_codes(d);
2160 }
2161
2162 static int tdefl_flush_block(tdefl_compressor *d, int flush)
2163 {
2164 mz_uint saved_bit_buf, saved_bits_in;
2165 mz_uint8 *pSaved_output_buf;
2166 mz_bool comp_block_succeeded = MZ_FALSE;
2167 int n, use_raw_block = ((d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS) != 0) && (d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size;
2168 mz_uint8 *pOutput_buf_start = ((d->m_pPut_buf_func == NULL) && ((*d->m_pOut_buf_size - d->m_out_buf_ofs) >= TDEFL_OUT_BUF_SIZE)) ? ((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs) : d->m_output_buf;
2169
2170 d->m_pOutput_buf = pOutput_buf_start;
2171 d->m_pOutput_buf_end = d->m_pOutput_buf + TDEFL_OUT_BUF_SIZE - 16;
2172
2173 MZ_ASSERT(!d->m_output_flush_remaining);
2174 d->m_output_flush_ofs = 0;
2175 d->m_output_flush_remaining = 0;
2176
2177 *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> d->m_num_flags_left);
2178 d->m_pLZ_code_buf -= (d->m_num_flags_left == 8);
2179
2180 if ((d->m_flags & TDEFL_WRITE_ZLIB_HEADER) && (!d->m_block_index))
2181 {
2182 TDEFL_PUT_BITS(0x78, 8); TDEFL_PUT_BITS(0x01, 8);
2183 }
2184
2185 TDEFL_PUT_BITS(flush == TDEFL_FINISH, 1);
2186
2187 pSaved_output_buf = d->m_pOutput_buf; saved_bit_buf = d->m_bit_buffer; saved_bits_in = d->m_bits_in;
2188
2189 if (!use_raw_block)
2190 comp_block_succeeded = tdefl_compress_block(d, (d->m_flags & TDEFL_FORCE_ALL_STATIC_BLOCKS) || (d->m_total_lz_bytes < 48));
2191
2192 // If the block gets expanded, forget the current contents of the output buffer and send a raw block instead.
2193 if ( ((use_raw_block) || ((d->m_total_lz_bytes) && ((d->m_pOutput_buf - pSaved_output_buf + 1U) >= d->m_total_lz_bytes))) &&
2194 ((d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size) )
2195 {
2196 mz_uint i; d->m_pOutput_buf = pSaved_output_buf; d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in;
2197 TDEFL_PUT_BITS(0, 2);
2198 if (d->m_bits_in) { TDEFL_PUT_BITS(0, 8 - d->m_bits_in); }
2199 for (i = 2; i; --i, d->m_total_lz_bytes ^= 0xFFFF)
2200 {
2201 TDEFL_PUT_BITS(d->m_total_lz_bytes & 0xFFFF, 16);
2202 }
2203 for (i = 0; i < d->m_total_lz_bytes; ++i)
2204 {
2205 TDEFL_PUT_BITS(d->m_dict[(d->m_lz_code_buf_dict_pos + i) & TDEFL_LZ_DICT_SIZE_MASK], 8);
2206 }
2207 }
2208 // Check for the extremely unlikely (if not impossible) case of the compressed block not fitting into the output buffer when using dynamic codes.
2209 else if (!comp_block_succeeded)
2210 {
2211 d->m_pOutput_buf = pSaved_output_buf; d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in;
2212 tdefl_compress_block(d, MZ_TRUE);
2213 }
2214
2215 if (flush)
2216 {
2217 if (flush == TDEFL_FINISH)
2218 {
2219 if (d->m_bits_in) { TDEFL_PUT_BITS(0, 8 - d->m_bits_in); }
2220 if (d->m_flags & TDEFL_WRITE_ZLIB_HEADER) { mz_uint i, a = d->m_adler32; for (i = 0; i < 4; i++) { TDEFL_PUT_BITS((a >> 24) & 0xFF, 8); a <<= 8; } }
2221 }
2222 else
2223 {
2224 mz_uint i, z = 0; TDEFL_PUT_BITS(0, 3); if (d->m_bits_in) { TDEFL_PUT_BITS(0, 8 - d->m_bits_in); } for (i = 2; i; --i, z ^= 0xFFFF) { TDEFL_PUT_BITS(z & 0xFFFF, 16); }
2225 }
2226 }
2227
2228 MZ_ASSERT(d->m_pOutput_buf < d->m_pOutput_buf_end);
2229
2230 memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0);
2231 memset(&d->m_huff_count[1][0], 0, sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1);
2232
2233 d->m_pLZ_code_buf = d->m_lz_code_buf + 1; d->m_pLZ_flags = d->m_lz_code_buf; d->m_num_flags_left = 8; d->m_lz_code_buf_dict_pos += d->m_total_lz_bytes; d->m_total_lz_bytes = 0; d->m_block_index++;
2234
2235 if ((n = (int)(d->m_pOutput_buf - pOutput_buf_start)) != 0)
2236 {
2237 if (d->m_pPut_buf_func)
2238 {
2239 *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf;
2240 if (!(*d->m_pPut_buf_func)(d->m_output_buf, n, d->m_pPut_buf_user))
2241 return (d->m_prev_return_status = TDEFL_STATUS_PUT_BUF_FAILED);
2242 }
2243 else if (pOutput_buf_start == d->m_output_buf)
2244 {
2245 int bytes_to_copy = (int)MZ_MIN((size_t)n, (size_t)(*d->m_pOut_buf_size - d->m_out_buf_ofs));
2246 memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf, bytes_to_copy);
2247 d->m_out_buf_ofs += bytes_to_copy;
2248 if ((n -= bytes_to_copy) != 0)
2249 {
2250 d->m_output_flush_ofs = bytes_to_copy;
2251 d->m_output_flush_remaining = n;
2252 }
2253 }
2254 else
2255 {
2256 d->m_out_buf_ofs += n;
2257 }
2258 }
2259
2260 return d->m_output_flush_remaining;
2261 }
2262
2263 #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES
2264 #define TDEFL_READ_UNALIGNED_WORD(p) *(const mz_uint16*)(p)
2265 static MZ_FORCEINLINE void tdefl_find_match(tdefl_compressor *d, mz_uint lookahead_pos, mz_uint max_dist, mz_uint max_match_len, mz_uint *pMatch_dist, mz_uint *pMatch_len)
2266 {
2267 mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK, match_len = *pMatch_len, probe_pos = pos, next_probe_pos, probe_len;
2268 mz_uint num_probes_left = d->m_max_probes[match_len >= 32];
2269 const mz_uint16 *s = (const mz_uint16*)(d->m_dict + pos), *p, *q;
2270 mz_uint16 c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]), s01 = TDEFL_READ_UNALIGNED_WORD(s);
2271 MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN); if (max_match_len <= match_len) return;
2272 for ( ; ; )
2273 {
2274 for ( ; ; )
2275 {
2276 if (--num_probes_left == 0) return;
2277 #define TDEFL_PROBE \
2278 next_probe_pos = d->m_next[probe_pos]; \
2279 if ((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) return; \
2280 probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK; \
2281 if (TDEFL_READ_UNALIGNED_WORD(&d->m_dict[probe_pos + match_len - 1]) == c01) break;
2282 TDEFL_PROBE; TDEFL_PROBE; TDEFL_PROBE;
2283 }
2284 if (!dist) break; q = (const mz_uint16*)(d->m_dict + probe_pos); if (TDEFL_READ_UNALIGNED_WORD(q) != s01) continue; p = s; probe_len = 32;
2285 do { } while ( (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) &&
2286 (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (--probe_len > 0) );
2287 if (!probe_len)
2288 {
2289 *pMatch_dist = dist; *pMatch_len = MZ_MIN(max_match_len, TDEFL_MAX_MATCH_LEN); break;
2290 }
2291 else if ((probe_len = ((mz_uint)(p - s) * 2) + (mz_uint)(*(const mz_uint8*)p == *(const mz_uint8*)q)) > match_len)
2292 {
2293 *pMatch_dist = dist; if ((*pMatch_len = match_len = MZ_MIN(max_match_len, probe_len)) == max_match_len) break;
2294 c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]);
2295 }
2296 }
2297 }
2298 #else
2299 static MZ_FORCEINLINE void tdefl_find_match(tdefl_compressor *d, mz_uint lookahead_pos, mz_uint max_dist, mz_uint max_match_len, mz_uint *pMatch_dist, mz_uint *pMatch_len)
2300 {
2301 mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK, match_len = *pMatch_len, probe_pos = pos, next_probe_pos, probe_len;
2302 mz_uint num_probes_left = d->m_max_probes[match_len >= 32];
2303 const mz_uint8 *s = d->m_dict + pos, *p, *q;
2304 mz_uint8 c0 = d->m_dict[pos + match_len], c1 = d->m_dict[pos + match_len - 1];
2305 MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN); if (max_match_len <= match_len) return;
2306 for ( ; ; )
2307 {
2308 for ( ; ; )
2309 {
2310 if (--num_probes_left == 0) return;
2311 #define TDEFL_PROBE \
2312 next_probe_pos = d->m_next[probe_pos]; \
2313 if ((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) return; \
2314 probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK; \
2315 if ((d->m_dict[probe_pos + match_len] == c0) && (d->m_dict[probe_pos + match_len - 1] == c1)) break;
2316 TDEFL_PROBE; TDEFL_PROBE; TDEFL_PROBE;
2317 }
2318 if (!dist) break; p = s; q = d->m_dict + probe_pos; for (probe_len = 0; probe_len < max_match_len; probe_len++) if (*p++ != *q++) break;
2319 if (probe_len > match_len)
2320 {
2321 *pMatch_dist = dist; if ((*pMatch_len = match_len = probe_len) == max_match_len) return;
2322 c0 = d->m_dict[pos + match_len]; c1 = d->m_dict[pos + match_len - 1];
2323 }
2324 }
2325 }
2326 #endif // #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES
2327
2328 #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
2329 static mz_bool tdefl_compress_fast(tdefl_compressor *d)
2330 {
2331 // Faster, minimally featured LZRW1-style match+parse loop with better register utilization. Intended for applications where raw throughput is valued more highly than ratio.
2332 mz_uint lookahead_pos = d->m_lookahead_pos, lookahead_size = d->m_lookahead_size, dict_size = d->m_dict_size, total_lz_bytes = d->m_total_lz_bytes, num_flags_left = d->m_num_flags_left;
2333 mz_uint8 *pLZ_code_buf = d->m_pLZ_code_buf, *pLZ_flags = d->m_pLZ_flags;
2334 mz_uint cur_pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK;
2335
2336 while ((d->m_src_buf_left) || ((d->m_flush) && (lookahead_size)))
2337 {
2338 const mz_uint TDEFL_COMP_FAST_LOOKAHEAD_SIZE = 4096;
2339 mz_uint dst_pos = (lookahead_pos + lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK;
2340 mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(d->m_src_buf_left, TDEFL_COMP_FAST_LOOKAHEAD_SIZE - lookahead_size);
2341 d->m_src_buf_left -= num_bytes_to_process;
2342 lookahead_size += num_bytes_to_process;
2343
2344 while (num_bytes_to_process)
2345 {
2346 mz_uint32 n = MZ_MIN(TDEFL_LZ_DICT_SIZE - dst_pos, num_bytes_to_process);
2347 memcpy(d->m_dict + dst_pos, d->m_pSrc, n);
2348 if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1))
2349 memcpy(d->m_dict + TDEFL_LZ_DICT_SIZE + dst_pos, d->m_pSrc, MZ_MIN(n, (TDEFL_MAX_MATCH_LEN - 1) - dst_pos));
2350 d->m_pSrc += n;
2351 dst_pos = (dst_pos + n) & TDEFL_LZ_DICT_SIZE_MASK;
2352 num_bytes_to_process -= n;
2353 }
2354
2355 dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - lookahead_size, dict_size);
2356 if ((!d->m_flush) && (lookahead_size < TDEFL_COMP_FAST_LOOKAHEAD_SIZE)) break;
2357
2358 while (lookahead_size >= 4)
2359 {
2360 mz_uint cur_match_dist, cur_match_len = 1;
2361 mz_uint8 *pCur_dict = d->m_dict + cur_pos;
2362 mz_uint first_trigram = (*(const mz_uint32 *)pCur_dict) & 0xFFFFFF;
2363 mz_uint hash = (first_trigram ^ (first_trigram >> (24 - (TDEFL_LZ_HASH_BITS - 8)))) & TDEFL_LEVEL1_HASH_SIZE_MASK;
2364 mz_uint probe_pos = d->m_hash[hash];
2365 d->m_hash[hash] = (mz_uint16)lookahead_pos;
2366
2367 if (((cur_match_dist = (mz_uint16)(lookahead_pos - probe_pos)) <= dict_size) && ((*(const mz_uint32 *)(d->m_dict + (probe_pos &= TDEFL_LZ_DICT_SIZE_MASK)) & 0xFFFFFF) == first_trigram))
2368 {
2369 const mz_uint16 *p = (const mz_uint16 *)pCur_dict;
2370 const mz_uint16 *q = (const mz_uint16 *)(d->m_dict + probe_pos);
2371 mz_uint32 probe_len = 32;
2372 do { } while ( (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) &&
2373 (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (--probe_len > 0) );
2374 cur_match_len = ((mz_uint)(p - (const mz_uint16 *)pCur_dict) * 2) + (mz_uint)(*(const mz_uint8 *)p == *(const mz_uint8 *)q);
2375 if (!probe_len)
2376 cur_match_len = cur_match_dist ? TDEFL_MAX_MATCH_LEN : 0;
2377
2378 if ((cur_match_len < TDEFL_MIN_MATCH_LEN) || ((cur_match_len == TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 8U*1024U)))
2379 {
2380 cur_match_len = 1;
2381 *pLZ_code_buf++ = (mz_uint8)first_trigram;
2382 *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
2383 d->m_huff_count[0][(mz_uint8)first_trigram]++;
2384 }
2385 else
2386 {
2387 mz_uint32 s0, s1;
2388 cur_match_len = MZ_MIN(cur_match_len, lookahead_size);
2389
2390 MZ_ASSERT((cur_match_len >= TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 1) && (cur_match_dist <= TDEFL_LZ_DICT_SIZE));
2391
2392 cur_match_dist--;
2393
2394 pLZ_code_buf[0] = (mz_uint8)(cur_match_len - TDEFL_MIN_MATCH_LEN);
2395 *(mz_uint16 *)(&pLZ_code_buf[1]) = (mz_uint16)cur_match_dist;
2396 pLZ_code_buf += 3;
2397 *pLZ_flags = (mz_uint8)((*pLZ_flags >> 1) | 0x80);
2398
2399 s0 = s_tdefl_small_dist_sym[cur_match_dist & 511];
2400 s1 = s_tdefl_large_dist_sym[cur_match_dist >> 8];
2401 d->m_huff_count[1][(cur_match_dist < 512) ? s0 : s1]++;
2402
2403 d->m_huff_count[0][s_tdefl_len_sym[cur_match_len - TDEFL_MIN_MATCH_LEN]]++;
2404 }
2405 }
2406 else
2407 {
2408 *pLZ_code_buf++ = (mz_uint8)first_trigram;
2409 *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
2410 d->m_huff_count[0][(mz_uint8)first_trigram]++;
2411 }
2412
2413 if (--num_flags_left == 0) { num_flags_left = 8; pLZ_flags = pLZ_code_buf++; }
2414
2415 total_lz_bytes += cur_match_len;
2416 lookahead_pos += cur_match_len;
2417 dict_size = MZ_MIN(dict_size + cur_match_len, TDEFL_LZ_DICT_SIZE);
2418 cur_pos = (cur_pos + cur_match_len) & TDEFL_LZ_DICT_SIZE_MASK;
2419 MZ_ASSERT(lookahead_size >= cur_match_len);
2420 lookahead_size -= cur_match_len;
2421
2422 if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8])
2423 {
2424 int n;
2425 d->m_lookahead_pos = lookahead_pos; d->m_lookahead_size = lookahead_size; d->m_dict_size = dict_size;
2426 d->m_total_lz_bytes = total_lz_bytes; d->m_pLZ_code_buf = pLZ_code_buf; d->m_pLZ_flags = pLZ_flags; d->m_num_flags_left = num_flags_left;
2427 if ((n = tdefl_flush_block(d, 0)) != 0)
2428 return (n < 0) ? MZ_FALSE : MZ_TRUE;
2429 total_lz_bytes = d->m_total_lz_bytes; pLZ_code_buf = d->m_pLZ_code_buf; pLZ_flags = d->m_pLZ_flags; num_flags_left = d->m_num_flags_left;
2430 }
2431 }
2432
2433 while (lookahead_size)
2434 {
2435 mz_uint8 lit = d->m_dict[cur_pos];
2436
2437 total_lz_bytes++;
2438 *pLZ_code_buf++ = lit;
2439 *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
2440 if (--num_flags_left == 0) { num_flags_left = 8; pLZ_flags = pLZ_code_buf++; }
2441
2442 d->m_huff_count[0][lit]++;
2443
2444 lookahead_pos++;
2445 dict_size = MZ_MIN(dict_size + 1, TDEFL_LZ_DICT_SIZE);
2446 cur_pos = (cur_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK;
2447 lookahead_size--;
2448
2449 if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8])
2450 {
2451 int n;
2452 d->m_lookahead_pos = lookahead_pos; d->m_lookahead_size = lookahead_size; d->m_dict_size = dict_size;
2453 d->m_total_lz_bytes = total_lz_bytes; d->m_pLZ_code_buf = pLZ_code_buf; d->m_pLZ_flags = pLZ_flags; d->m_num_flags_left = num_flags_left;
2454 if ((n = tdefl_flush_block(d, 0)) != 0)
2455 return (n < 0) ? MZ_FALSE : MZ_TRUE;
2456 total_lz_bytes = d->m_total_lz_bytes; pLZ_code_buf = d->m_pLZ_code_buf; pLZ_flags = d->m_pLZ_flags; num_flags_left = d->m_num_flags_left;
2457 }
2458 }
2459 }
2460
2461 d->m_lookahead_pos = lookahead_pos; d->m_lookahead_size = lookahead_size; d->m_dict_size = dict_size;
2462 d->m_total_lz_bytes = total_lz_bytes; d->m_pLZ_code_buf = pLZ_code_buf; d->m_pLZ_flags = pLZ_flags; d->m_num_flags_left = num_flags_left;
2463 return MZ_TRUE;
2464 }
2465 #endif // MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
2466
2467 static MZ_FORCEINLINE void tdefl_record_literal(tdefl_compressor *d, mz_uint8 lit)
2468 {
2469 d->m_total_lz_bytes++;
2470 *d->m_pLZ_code_buf++ = lit;
2471 *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> 1); if (--d->m_num_flags_left == 0) { d->m_num_flags_left = 8; d->m_pLZ_flags = d->m_pLZ_code_buf++; }
2472 d->m_huff_count[0][lit]++;
2473 }
2474
2475 static MZ_FORCEINLINE void tdefl_record_match(tdefl_compressor *d, mz_uint match_len, mz_uint match_dist)
2476 {
2477 mz_uint32 s0, s1;
2478
2479 MZ_ASSERT((match_len >= TDEFL_MIN_MATCH_LEN) && (match_dist >= 1) && (match_dist <= TDEFL_LZ_DICT_SIZE));
2480
2481 d->m_total_lz_bytes += match_len;
2482
2483 d->m_pLZ_code_buf[0] = (mz_uint8)(match_len - TDEFL_MIN_MATCH_LEN);
2484
2485 match_dist -= 1;
2486 d->m_pLZ_code_buf[1] = (mz_uint8)(match_dist & 0xFF);
2487 d->m_pLZ_code_buf[2] = (mz_uint8)(match_dist >> 8); d->m_pLZ_code_buf += 3;
2488
2489 *d->m_pLZ_flags = (mz_uint8)((*d->m_pLZ_flags >> 1) | 0x80); if (--d->m_num_flags_left == 0) { d->m_num_flags_left = 8; d->m_pLZ_flags = d->m_pLZ_code_buf++; }
2490
2491 s0 = s_tdefl_small_dist_sym[match_dist & 511]; s1 = s_tdefl_large_dist_sym[(match_dist >> 8) & 127];
2492 d->m_huff_count[1][(match_dist < 512) ? s0 : s1]++;
2493
2494 if (match_len >= TDEFL_MIN_MATCH_LEN) d->m_huff_count[0][s_tdefl_len_sym[match_len - TDEFL_MIN_MATCH_LEN]]++;
2495 }
2496
2497 static mz_bool tdefl_compress_normal(tdefl_compressor *d)
2498 {
2499 const mz_uint8 *pSrc = d->m_pSrc; size_t src_buf_left = d->m_src_buf_left;
2500 tdefl_flush flush = d->m_flush;
2501
2502 while ((src_buf_left) || ((flush) && (d->m_lookahead_size)))
2503 {
2504 mz_uint len_to_move, cur_match_dist, cur_match_len, cur_pos;
2505 // Update dictionary and hash chains. Keeps the lookahead size equal to TDEFL_MAX_MATCH_LEN.
2506 if ((d->m_lookahead_size + d->m_dict_size) >= (TDEFL_MIN_MATCH_LEN - 1))
2507 {
2508 mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK, ins_pos = d->m_lookahead_pos + d->m_lookahead_size - 2;
2509 mz_uint hash = (d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] << TDEFL_LZ_HASH_SHIFT) ^ d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK];
2510 mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(src_buf_left, TDEFL_MAX_MATCH_LEN - d->m_lookahead_size);
2511 const mz_uint8 *pSrc_end = pSrc + num_bytes_to_process;
2512 src_buf_left -= num_bytes_to_process;
2513 d->m_lookahead_size += num_bytes_to_process;
2514 while (pSrc != pSrc_end)
2515 {
2516 mz_uint8 c = *pSrc++; d->m_dict[dst_pos] = c; if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1)) d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c;
2517 hash = ((hash << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1);
2518 d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash]; d->m_hash[hash] = (mz_uint16)(ins_pos);
2519 dst_pos = (dst_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK; ins_pos++;
2520 }
2521 }
2522 else
2523 {
2524 while ((src_buf_left) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN))
2525 {
2526 mz_uint8 c = *pSrc++;
2527 mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK;
2528 src_buf_left--;
2529 d->m_dict[dst_pos] = c;
2530 if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1))
2531 d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c;
2532 if ((++d->m_lookahead_size + d->m_dict_size) >= TDEFL_MIN_MATCH_LEN)
2533 {
2534 mz_uint ins_pos = d->m_lookahead_pos + (d->m_lookahead_size - 1) - 2;
2535 mz_uint hash = ((d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] << (TDEFL_LZ_HASH_SHIFT * 2)) ^ (d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK] << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1);
2536 d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash]; d->m_hash[hash] = (mz_uint16)(ins_pos);
2537 }
2538 }
2539 }
2540 d->m_dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - d->m_lookahead_size, d->m_dict_size);
2541 if ((!flush) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN))
2542 break;
2543
2544 // Simple lazy/greedy parsing state machine.
2545 len_to_move = 1; cur_match_dist = 0; cur_match_len = d->m_saved_match_len ? d->m_saved_match_len : (TDEFL_MIN_MATCH_LEN - 1); cur_pos = d->m_lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK;
2546 if (d->m_flags & (TDEFL_RLE_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS))
2547 {
2548 if ((d->m_dict_size) && (!(d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS)))
2549 {
2550 mz_uint8 c = d->m_dict[(cur_pos - 1) & TDEFL_LZ_DICT_SIZE_MASK];
2551 cur_match_len = 0; while (cur_match_len < d->m_lookahead_size) { if (d->m_dict[cur_pos + cur_match_len] != c) break; cur_match_len++; }
2552 if (cur_match_len < TDEFL_MIN_MATCH_LEN) cur_match_len = 0; else cur_match_dist = 1;
2553 }
2554 }
2555 else
2556 {
2557 tdefl_find_match(d, d->m_lookahead_pos, d->m_dict_size, d->m_lookahead_size, &cur_match_dist, &cur_match_len);
2558 }
2559 if (((cur_match_len == TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 8U*1024U)) || (cur_pos == cur_match_dist) || ((d->m_flags & TDEFL_FILTER_MATCHES) && (cur_match_len <= 5)))
2560 {
2561 cur_match_dist = cur_match_len = 0;
2562 }
2563 if (d->m_saved_match_len)
2564 {
2565 if (cur_match_len > d->m_saved_match_len)
2566 {
2567 tdefl_record_literal(d, (mz_uint8)d->m_saved_lit);
2568 if (cur_match_len >= 128)
2569 {
2570 tdefl_record_match(d, cur_match_len, cur_match_dist);
2571 d->m_saved_match_len = 0; len_to_move = cur_match_len;
2572 }
2573 else
2574 {
2575 d->m_saved_lit = d->m_dict[cur_pos]; d->m_saved_match_dist = cur_match_dist; d->m_saved_match_len = cur_match_len;
2576 }
2577 }
2578 else
2579 {
2580 tdefl_record_match(d, d->m_saved_match_len, d->m_saved_match_dist);
2581 len_to_move = d->m_saved_match_len - 1; d->m_saved_match_len = 0;
2582 }
2583 }
2584 else if (!cur_match_dist)
2585 tdefl_record_literal(d, d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)]);
2586 else if ((d->m_greedy_parsing) || (d->m_flags & TDEFL_RLE_MATCHES) || (cur_match_len >= 128))
2587 {
2588 tdefl_record_match(d, cur_match_len, cur_match_dist);
2589 len_to_move = cur_match_len;
2590 }
2591 else
2592 {
2593 d->m_saved_lit = d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)]; d->m_saved_match_dist = cur_match_dist; d->m_saved_match_len = cur_match_len;
2594 }
2595 // Move the lookahead forward by len_to_move bytes.
2596 d->m_lookahead_pos += len_to_move;
2597 MZ_ASSERT(d->m_lookahead_size >= len_to_move);
2598 d->m_lookahead_size -= len_to_move;
2599 d->m_dict_size = MZ_MIN(d->m_dict_size + len_to_move, TDEFL_LZ_DICT_SIZE);
2600 // Check if it's time to flush the current LZ codes to the internal output buffer.
2601 if ( (d->m_pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) ||
2602 ( (d->m_total_lz_bytes > 31*1024) && (((((mz_uint)(d->m_pLZ_code_buf - d->m_lz_code_buf) * 115) >> 7) >= d->m_total_lz_bytes) || (d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS))) )
2603 {
2604 int n;
2605 d->m_pSrc = pSrc; d->m_src_buf_left = src_buf_left;
2606 if ((n = tdefl_flush_block(d, 0)) != 0)
2607 return (n < 0) ? MZ_FALSE : MZ_TRUE;
2608 }
2609 }
2610
2611 d->m_pSrc = pSrc; d->m_src_buf_left = src_buf_left;
2612 return MZ_TRUE;
2613 }
2614
2615 static tdefl_status tdefl_flush_output_buffer(tdefl_compressor *d)
2616 {
2617 if (d->m_pIn_buf_size)
2618 {
2619 *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf;
2620 }
2621
2622 if (d->m_pOut_buf_size)
2623 {
2624 size_t n = MZ_MIN(*d->m_pOut_buf_size - d->m_out_buf_ofs, d->m_output_flush_remaining);
2625 memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf + d->m_output_flush_ofs, n);
2626 d->m_output_flush_ofs += (mz_uint)n;
2627 d->m_output_flush_remaining -= (mz_uint)n;
2628 d->m_out_buf_ofs += n;
2629
2630 *d->m_pOut_buf_size = d->m_out_buf_ofs;
2631 }
2632
2633 return (d->m_finished && !d->m_output_flush_remaining) ? TDEFL_STATUS_DONE : TDEFL_STATUS_OKAY;
2634 }
2635
2636 tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf, size_t *pIn_buf_size, void *pOut_buf, size_t *pOut_buf_size, tdefl_flush flush)
2637 {
2638 if (!d)
2639 {
2640 if (pIn_buf_size) *pIn_buf_size = 0;
2641 if (pOut_buf_size) *pOut_buf_size = 0;
2642 return TDEFL_STATUS_BAD_PARAM;
2643 }
2644
2645 d->m_pIn_buf = pIn_buf; d->m_pIn_buf_size = pIn_buf_size;
2646 d->m_pOut_buf = pOut_buf; d->m_pOut_buf_size = pOut_buf_size;
2647 d->m_pSrc = (const mz_uint8 *)(pIn_buf); d->m_src_buf_left = pIn_buf_size ? *pIn_buf_size : 0;
2648 d->m_out_buf_ofs = 0;
2649 d->m_flush = flush;
2650
2651 if ( ((d->m_pPut_buf_func != NULL) == ((pOut_buf != NULL) || (pOut_buf_size != NULL))) || (d->m_prev_return_status != TDEFL_STATUS_OKAY) ||
2652 (d->m_wants_to_finish && (flush != TDEFL_FINISH)) || (pIn_buf_size && *pIn_buf_size && !pIn_buf) || (pOut_buf_size && *pOut_buf_size && !pOut_buf) )
2653 {
2654 if (pIn_buf_size) *pIn_buf_size = 0;
2655 if (pOut_buf_size) *pOut_buf_size = 0;
2656 return (d->m_prev_return_status = TDEFL_STATUS_BAD_PARAM);
2657 }
2658 d->m_wants_to_finish |= (flush == TDEFL_FINISH);
2659
2660 if ((d->m_output_flush_remaining) || (d->m_finished))
2661 return (d->m_prev_return_status = tdefl_flush_output_buffer(d));
2662
2663 #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
2664 if (((d->m_flags & TDEFL_MAX_PROBES_MASK) == 1) &&
2665 ((d->m_flags & TDEFL_GREEDY_PARSING_FLAG) != 0) &&
2666 ((d->m_flags & (TDEFL_FILTER_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS | TDEFL_RLE_MATCHES)) == 0))
2667 {
2668 if (!tdefl_compress_fast(d))
2669 return d->m_prev_return_status;
2670 }
2671 else
2672 #endif // #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
2673 {
2674 if (!tdefl_compress_normal(d))
2675 return d->m_prev_return_status;
2676 }
2677
2678 if ((d->m_flags & (TDEFL_WRITE_ZLIB_HEADER | TDEFL_COMPUTE_ADLER32)) && (pIn_buf))
2679 d->m_adler32 = (mz_uint32)mz_adler32(d->m_adler32, (const mz_uint8 *)pIn_buf, d->m_pSrc - (const mz_uint8 *)pIn_buf);
2680
2681 if ((flush) && (!d->m_lookahead_size) && (!d->m_src_buf_left) && (!d->m_output_flush_remaining))
2682 {
2683 if (tdefl_flush_block(d, flush) < 0)
2684 return d->m_prev_return_status;
2685 d->m_finished = (flush == TDEFL_FINISH);
2686 if (flush == TDEFL_FULL_FLUSH) { MZ_CLEAR_OBJ(d->m_hash); MZ_CLEAR_OBJ(d->m_next); d->m_dict_size = 0; }
2687 }
2688
2689 return (d->m_prev_return_status = tdefl_flush_output_buffer(d));
2690 }
2691
2692 tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf, size_t in_buf_size, tdefl_flush flush)
2693 {
2694 MZ_ASSERT(d->m_pPut_buf_func); return tdefl_compress(d, pIn_buf, &in_buf_size, NULL, NULL, flush);
2695 }
2696
2697 tdefl_status tdefl_init(tdefl_compressor *d, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags)
2698 {
2699 d->m_pPut_buf_func = pPut_buf_func; d->m_pPut_buf_user = pPut_buf_user;
2700 d->m_flags = (mz_uint)(flags); d->m_max_probes[0] = 1 + ((flags & 0xFFF) + 2) / 3; d->m_greedy_parsing = (flags & TDEFL_GREEDY_PARSING_FLAG) != 0;
2701 d->m_max_probes[1] = 1 + (((flags & 0xFFF) >> 2) + 2) / 3;
2702 if (!(flags & TDEFL_NONDETERMINISTIC_PARSING_FLAG)) MZ_CLEAR_OBJ(d->m_hash);
2703 d->m_lookahead_pos = d->m_lookahead_size = d->m_dict_size = d->m_total_lz_bytes = d->m_lz_code_buf_dict_pos = d->m_bits_in = 0;
2704 d->m_output_flush_ofs = d->m_output_flush_remaining = d->m_finished = d->m_block_index = d->m_bit_buffer = d->m_wants_to_finish = 0;
2705 d->m_pLZ_code_buf = d->m_lz_code_buf + 1; d->m_pLZ_flags = d->m_lz_code_buf; d->m_num_flags_left = 8;
2706 d->m_pOutput_buf = d->m_output_buf; d->m_pOutput_buf_end = d->m_output_buf; d->m_prev_return_status = TDEFL_STATUS_OKAY;
2707 d->m_saved_match_dist = d->m_saved_match_len = d->m_saved_lit = 0; d->m_adler32 = 1;
2708 d->m_pIn_buf = NULL; d->m_pOut_buf = NULL;
2709 d->m_pIn_buf_size = NULL; d->m_pOut_buf_size = NULL;
2710 d->m_flush = TDEFL_NO_FLUSH; d->m_pSrc = NULL; d->m_src_buf_left = 0; d->m_out_buf_ofs = 0;
2711 memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0);
2712 memset(&d->m_huff_count[1][0], 0, sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1);
2713 return TDEFL_STATUS_OKAY;
2714 }
2715
2716 tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d)
2717 {
2718 return d->m_prev_return_status;
2719 }
2720
2721 mz_uint32 tdefl_get_adler32(tdefl_compressor *d)
2722 {
2723 return d->m_adler32;
2724 }
2725
2726 mz_bool tdefl_compress_mem_to_output(const void *pBuf, size_t buf_len, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags)
2727 {
2728 tdefl_compressor *pComp; mz_bool succeeded; if (((buf_len) && (!pBuf)) || (!pPut_buf_func)) return MZ_FALSE;
2729 pComp = (tdefl_compressor*)MZ_MALLOC(sizeof(tdefl_compressor)); if (!pComp) return MZ_FALSE;
2730 succeeded = (tdefl_init(pComp, pPut_buf_func, pPut_buf_user, flags) == TDEFL_STATUS_OKAY);
2731 succeeded = succeeded && (tdefl_compress_buffer(pComp, pBuf, buf_len, TDEFL_FINISH) == TDEFL_STATUS_DONE);
2732 MZ_FREE(pComp); return succeeded;
2733 }
2734
2735 typedef struct
2736 {
2737 size_t m_size, m_capacity;
2738 mz_uint8 *m_pBuf;
2739 mz_bool m_expandable;
2740 } tdefl_output_buffer;
2741
2742 static mz_bool tdefl_output_buffer_putter(const void *pBuf, int len, void *pUser)
2743 {
2744 tdefl_output_buffer *p = (tdefl_output_buffer *)pUser;
2745 size_t new_size = p->m_size + len;
2746 if (new_size > p->m_capacity)
2747 {
2748 size_t new_capacity = p->m_capacity; mz_uint8 *pNew_buf; if (!p->m_expandable) return MZ_FALSE;
2749 do { new_capacity = MZ_MAX(128U, new_capacity << 1U); } while (new_size > new_capacity);
2750 pNew_buf = (mz_uint8*)MZ_REALLOC(p->m_pBuf, new_capacity); if (!pNew_buf) return MZ_FALSE;
2751 p->m_pBuf = pNew_buf; p->m_capacity = new_capacity;
2752 }
2753 memcpy((mz_uint8*)p->m_pBuf + p->m_size, pBuf, len); p->m_size = new_size;
2754 return MZ_TRUE;
2755 }
2756
2757 void *tdefl_compress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags)
2758 {
2759 tdefl_output_buffer out_buf; MZ_CLEAR_OBJ(out_buf);
2760 if (!pOut_len) return MZ_FALSE; else *pOut_len = 0;
2761 out_buf.m_expandable = MZ_TRUE;
2762 if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags)) return NULL;
2763 *pOut_len = out_buf.m_size; return out_buf.m_pBuf;
2764 }
2765
2766 size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags)
2767 {
2768 tdefl_output_buffer out_buf; MZ_CLEAR_OBJ(out_buf);
2769 if (!pOut_buf) return 0;
2770 out_buf.m_pBuf = (mz_uint8*)pOut_buf; out_buf.m_capacity = out_buf_len;
2771 if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags)) return 0;
2772 return out_buf.m_size;
2773 }
2774
2775 #ifndef MINIZ_NO_ZLIB_APIS
2776 static const mz_uint s_tdefl_num_probes[11] = { 0, 1, 6, 32, 16, 32, 128, 256, 512, 768, 1500 };
2777
2778 // level may actually range from [0,10] (10 is a "hidden" max level, where we want a bit more compression and it's fine if throughput to fall off a cliff on some files).
2779 mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits, int strategy)
2780 {
2781 mz_uint comp_flags = s_tdefl_num_probes[(level >= 0) ? MZ_MIN(10, level) : MZ_DEFAULT_LEVEL] | ((level <= 3) ? TDEFL_GREEDY_PARSING_FLAG : 0);
2782 if (window_bits > 0) comp_flags |= TDEFL_WRITE_ZLIB_HEADER;
2783
2784 if (!level) comp_flags |= TDEFL_FORCE_ALL_RAW_BLOCKS;
2785 else if (strategy == MZ_FILTERED) comp_flags |= TDEFL_FILTER_MATCHES;
2786 else if (strategy == MZ_HUFFMAN_ONLY) comp_flags &= ~TDEFL_MAX_PROBES_MASK;
2787 else if (strategy == MZ_FIXED) comp_flags |= TDEFL_FORCE_ALL_STATIC_BLOCKS;
2788 else if (strategy == MZ_RLE) comp_flags |= TDEFL_RLE_MATCHES;
2789
2790 return comp_flags;
2791 }
2792 #endif //MINIZ_NO_ZLIB_APIS
2793
2794 #ifdef _MSC_VER
2795 #pragma warning (push)
2796 #pragma warning (disable:4204) // nonstandard extension used : non-constant aggregate initializer (also supported by GNU C and C99, so no big deal)
2797 #endif
2798
2799 // Simple PNG writer function by Alex Evans, 2011. Released into the public domain: https://gist.github.com/908299, more context at
2800 // http://altdevblogaday.org/2011/04/06/a-smaller-jpg-encoder/.
2801 // This is actually a modification of Alex's original code so PNG files generated by this function pass pngcheck.
2802 void *tdefl_write_image_to_png_file_in_memory_ex(const void *pImage, int w, int h, int num_chans, size_t *pLen_out, mz_uint level, mz_bool flip)
2803 {
2804 // Using a local copy of this array here in case MINIZ_NO_ZLIB_APIS was defined.
2805 static const mz_uint s_tdefl_png_num_probes[11] = { 0, 1, 6, 32, 16, 32, 128, 256, 512, 768, 1500 };
2806 tdefl_compressor *pComp = (tdefl_compressor *)MZ_MALLOC(sizeof(tdefl_compressor)); tdefl_output_buffer out_buf; int i, bpl = w * num_chans, y, z; mz_uint32 c; *pLen_out = 0;
2807 if (!pComp) return NULL;
2808 MZ_CLEAR_OBJ(out_buf); out_buf.m_expandable = MZ_TRUE; out_buf.m_capacity = 57+MZ_MAX(64, (1+bpl)*h); if (NULL == (out_buf.m_pBuf = (mz_uint8*)MZ_MALLOC(out_buf.m_capacity))) { MZ_FREE(pComp); return NULL; }
2809 // write dummy header
2810 for (z = 41; z; --z) tdefl_output_buffer_putter(&z, 1, &out_buf);
2811 // compress image data
2812 tdefl_init(pComp, tdefl_output_buffer_putter, &out_buf, s_tdefl_png_num_probes[MZ_MIN(10, level)] | TDEFL_WRITE_ZLIB_HEADER);
2813 for (y = 0; y < h; ++y) { tdefl_compress_buffer(pComp, &z, 1, TDEFL_NO_FLUSH); tdefl_compress_buffer(pComp, (mz_uint8*)pImage + (flip ? (h - 1 - y) : y) * bpl, bpl, TDEFL_NO_FLUSH); }
2814 if (tdefl_compress_buffer(pComp, NULL, 0, TDEFL_FINISH) != TDEFL_STATUS_DONE) { MZ_FREE(pComp); MZ_FREE(out_buf.m_pBuf); return NULL; }
2815 // write real header
2816 *pLen_out = out_buf.m_size-41;
2817 {
2818 static const mz_uint8 chans[] = {0x00, 0x00, 0x04, 0x02, 0x06};
2819 mz_uint8 pnghdr[41]={0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d,0x49,0x48,0x44,0x52,
2820 0,0,(mz_uint8)(w>>8),(mz_uint8)w,0,0,(mz_uint8)(h>>8),(mz_uint8)h,8,chans[num_chans],0,0,0,0,0,0,0,
2821 (mz_uint8)(*pLen_out>>24),(mz_uint8)(*pLen_out>>16),(mz_uint8)(*pLen_out>>8),(mz_uint8)*pLen_out,0x49,0x44,0x41,0x54};
2822 c=(mz_uint32)mz_crc32(MZ_CRC32_INIT,pnghdr+12,17); for (i=0; i<4; ++i, c<<=8) ((mz_uint8*)(pnghdr+29))[i]=(mz_uint8)(c>>24);
2823 memcpy(out_buf.m_pBuf, pnghdr, 41);
2824 }
2825 // write footer (IDAT CRC-32, followed by IEND chunk)
2826 if (!tdefl_output_buffer_putter("\0\0\0\0\0\0\0\0\x49\x45\x4e\x44\xae\x42\x60\x82", 16, &out_buf)) { *pLen_out = 0; MZ_FREE(pComp); MZ_FREE(out_buf.m_pBuf); return NULL; }
2827 c = (mz_uint32)mz_crc32(MZ_CRC32_INIT,out_buf.m_pBuf+41-4, *pLen_out+4); for (i=0; i<4; ++i, c<<=8) (out_buf.m_pBuf+out_buf.m_size-16)[i] = (mz_uint8)(c >> 24);
2828 // compute final size of file, grab compressed data buffer and return
2829 *pLen_out += 57; MZ_FREE(pComp); return out_buf.m_pBuf;
2830 }
2831 void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h, int num_chans, size_t *pLen_out)
2832 {
2833 // Level 6 corresponds to TDEFL_DEFAULT_MAX_PROBES or MZ_DEFAULT_LEVEL (but we can't depend on MZ_DEFAULT_LEVEL being available in case the zlib API's where #defined out)
2834 return tdefl_write_image_to_png_file_in_memory_ex(pImage, w, h, num_chans, pLen_out, 6, MZ_FALSE);
2835 }
2836
2837 #ifdef _MSC_VER
2838 #pragma warning (pop)
2839 #endif
2840
2841 // ------------------- .ZIP archive reading
2842
2843 #ifndef MINIZ_NO_ARCHIVE_APIS
2844
2845 #ifdef MINIZ_NO_STDIO
2846 #define MZ_FILE void *
2847 #else
2848 #include <stdio.h>
2849 #include <sys/stat.h>
2850
2851 #if defined(_MSC_VER) || defined(__MINGW64__)
2852 static FILE *mz_fopen(const char *pFilename, const char *pMode)
2853 {
2854 FILE* pFile = NULL;
2855 fopen_s(&pFile, pFilename, pMode);
2856 return pFile;
2857 }
2858 static FILE *mz_freopen(const char *pPath, const char *pMode, FILE *pStream)
2859 {
2860 FILE* pFile = NULL;
2861 if (freopen_s(&pFile, pPath, pMode, pStream))
2862 return NULL;
2863 return pFile;
2864 }
2865 #ifndef MINIZ_NO_TIME
2866 #include <sys/utime.h>
2867 #endif
2868 #define MZ_FILE FILE
2869 #define MZ_FOPEN mz_fopen
2870 #define MZ_FCLOSE fclose
2871 #define MZ_FREAD fread
2872 #define MZ_FWRITE fwrite
2873 #define MZ_FTELL64 _ftelli64
2874 #define MZ_FSEEK64 _fseeki64
2875 #define MZ_FILE_STAT_STRUCT _stat
2876 #define MZ_FILE_STAT _stat
2877 #define MZ_FFLUSH fflush
2878 #define MZ_FREOPEN mz_freopen
2879 #define MZ_DELETE_FILE remove
2880 #elif defined(__MINGW32__)
2881 #ifndef MINIZ_NO_TIME
2882 #include <sys/utime.h>
2883 #endif
2884 #define MZ_FILE FILE
2885 #define MZ_FOPEN(f, m) fopen(f, m)
2886 #define MZ_FCLOSE fclose
2887 #define MZ_FREAD fread
2888 #define MZ_FWRITE fwrite
2889 #define MZ_FTELL64 ftello64
2890 #define MZ_FSEEK64 fseeko64
2891 #define MZ_FILE_STAT_STRUCT _stat
2892 #define MZ_FILE_STAT _stat
2893 #define MZ_FFLUSH fflush
2894 #define MZ_FREOPEN(f, m, s) freopen(f, m, s)
2895 #define MZ_DELETE_FILE remove
2896 #elif defined(__TINYC__)
2897 #ifndef MINIZ_NO_TIME
2898 #include <sys/utime.h>
2899 #endif
2900 #define MZ_FILE FILE
2901 #define MZ_FOPEN(f, m) fopen(f, m)
2902 #define MZ_FCLOSE fclose
2903 #define MZ_FREAD fread
2904 #define MZ_FWRITE fwrite
2905 #define MZ_FTELL64 ftell
2906 #define MZ_FSEEK64 fseek
2907 #define MZ_FILE_STAT_STRUCT stat
2908 #define MZ_FILE_STAT stat
2909 #define MZ_FFLUSH fflush
2910 #define MZ_FREOPEN(f, m, s) freopen(f, m, s)
2911 #define MZ_DELETE_FILE remove
2912 #elif defined(__GNUC__) && _LARGEFILE64_SOURCE
2913 #ifndef MINIZ_NO_TIME
2914 #include <utime.h>
2915 #endif
2916 #define MZ_FILE FILE
2917 #define MZ_FOPEN(f, m) fopen64(f, m)
2918 #define MZ_FCLOSE fclose
2919 #define MZ_FREAD fread
2920 #define MZ_FWRITE fwrite
2921 #define MZ_FTELL64 ftello64
2922 #define MZ_FSEEK64 fseeko64
2923 #define MZ_FILE_STAT_STRUCT stat64
2924 #define MZ_FILE_STAT stat64
2925 #define MZ_FFLUSH fflush
2926 #define MZ_FREOPEN(p, m, s) freopen64(p, m, s)
2927 #define MZ_DELETE_FILE remove
2928 #else
2929 #ifndef MINIZ_NO_TIME
2930 #include <utime.h>
2931 #endif
2932 #define MZ_FILE FILE
2933 #define MZ_FOPEN(f, m) fopen(f, m)
2934 #define MZ_FCLOSE fclose
2935 #define MZ_FREAD fread
2936 #define MZ_FWRITE fwrite
2937 #define MZ_FTELL64 ftello
2938 #define MZ_FSEEK64 fseeko
2939 #define MZ_FILE_STAT_STRUCT stat
2940 #define MZ_FILE_STAT stat
2941 #define MZ_FFLUSH fflush
2942 #define MZ_FREOPEN(f, m, s) freopen(f, m, s)
2943 #define MZ_DELETE_FILE remove
2944 #endif // #ifdef _MSC_VER
2945 #endif // #ifdef MINIZ_NO_STDIO
2946
2947 #define MZ_TOLOWER(c) ((((c) >= 'A') && ((c) <= 'Z')) ? ((c) - 'A' + 'a') : (c))
2948
2949 // Various ZIP archive enums. To completely avoid cross platform compiler alignment and platform endian issues, miniz.c doesn't use structs for any of this stuff.
2950 enum
2951 {
2952 // ZIP archive identifiers and record sizes
2953 MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG = 0x06054b50, MZ_ZIP_CENTRAL_DIR_HEADER_SIG = 0x02014b50, MZ_ZIP_LOCAL_DIR_HEADER_SIG = 0x04034b50,
2954 MZ_ZIP_LOCAL_DIR_HEADER_SIZE = 30, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE = 46, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE = 22,
2955 // Central directory header record offsets
2956 MZ_ZIP_CDH_SIG_OFS = 0, MZ_ZIP_CDH_VERSION_MADE_BY_OFS = 4, MZ_ZIP_CDH_VERSION_NEEDED_OFS = 6, MZ_ZIP_CDH_BIT_FLAG_OFS = 8,
2957 MZ_ZIP_CDH_METHOD_OFS = 10, MZ_ZIP_CDH_FILE_TIME_OFS = 12, MZ_ZIP_CDH_FILE_DATE_OFS = 14, MZ_ZIP_CDH_CRC32_OFS = 16,
2958 MZ_ZIP_CDH_COMPRESSED_SIZE_OFS = 20, MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS = 24, MZ_ZIP_CDH_FILENAME_LEN_OFS = 28, MZ_ZIP_CDH_EXTRA_LEN_OFS = 30,
2959 MZ_ZIP_CDH_COMMENT_LEN_OFS = 32, MZ_ZIP_CDH_DISK_START_OFS = 34, MZ_ZIP_CDH_INTERNAL_ATTR_OFS = 36, MZ_ZIP_CDH_EXTERNAL_ATTR_OFS = 38, MZ_ZIP_CDH_LOCAL_HEADER_OFS = 42,
2960 // Local directory header offsets
2961 MZ_ZIP_LDH_SIG_OFS = 0, MZ_ZIP_LDH_VERSION_NEEDED_OFS = 4, MZ_ZIP_LDH_BIT_FLAG_OFS = 6, MZ_ZIP_LDH_METHOD_OFS = 8, MZ_ZIP_LDH_FILE_TIME_OFS = 10,
2962 MZ_ZIP_LDH_FILE_DATE_OFS = 12, MZ_ZIP_LDH_CRC32_OFS = 14, MZ_ZIP_LDH_COMPRESSED_SIZE_OFS = 18, MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS = 22,
2963 MZ_ZIP_LDH_FILENAME_LEN_OFS = 26, MZ_ZIP_LDH_EXTRA_LEN_OFS = 28,
2964 // End of central directory offsets
2965 MZ_ZIP_ECDH_SIG_OFS = 0, MZ_ZIP_ECDH_NUM_THIS_DISK_OFS = 4, MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS = 6, MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS = 8,
2966 MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS = 10, MZ_ZIP_ECDH_CDIR_SIZE_OFS = 12, MZ_ZIP_ECDH_CDIR_OFS_OFS = 16, MZ_ZIP_ECDH_COMMENT_SIZE_OFS = 20,
2967 };
2968
2969 typedef struct
2970 {
2971 void *m_p;
2972 size_t m_size, m_capacity;
2973 mz_uint m_element_size;
2974 } mz_zip_array;
2975
2976 struct mz_zip_internal_state_tag
2977 {
2978 mz_zip_array m_central_dir;
2979 mz_zip_array m_central_dir_offsets;
2980 mz_zip_array m_sorted_central_dir_offsets;
2981 MZ_FILE *m_pFile;
2982 void *m_pMem;
2983 size_t m_mem_size;
2984 size_t m_mem_capacity;
2985 };
2986
2987 #define MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(array_ptr, element_size) (array_ptr)->m_element_size = element_size
2988 #define MZ_ZIP_ARRAY_ELEMENT(array_ptr, element_type, index) ((element_type *)((array_ptr)->m_p))[index]
2989
2990 static MZ_FORCEINLINE void mz_zip_array_clear(mz_zip_archive *pZip, mz_zip_array *pArray)
2991 {
2992 pZip->m_pFree(pZip->m_pAlloc_opaque, pArray->m_p);
2993 memset(pArray, 0, sizeof(mz_zip_array));
2994 }
2995
2996 static mz_bool mz_zip_array_ensure_capacity(mz_zip_archive *pZip, mz_zip_array *pArray, size_t min_new_capacity, mz_uint growing)
2997 {
2998 void *pNew_p; size_t new_capacity = min_new_capacity; MZ_ASSERT(pArray->m_element_size); if (pArray->m_capacity >= min_new_capacity) return MZ_TRUE;
2999 if (growing) { new_capacity = MZ_MAX(1, pArray->m_capacity); while (new_capacity < min_new_capacity) new_capacity *= 2; }
3000 if (NULL == (pNew_p = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pArray->m_p, pArray->m_element_size, new_capacity))) return MZ_FALSE;
3001 pArray->m_p = pNew_p; pArray->m_capacity = new_capacity;
3002 return MZ_TRUE;
3003 }
3004
3005 static MZ_FORCEINLINE mz_bool mz_zip_array_reserve(mz_zip_archive *pZip, mz_zip_array *pArray, size_t new_capacity, mz_uint growing)
3006 {
3007 if (new_capacity > pArray->m_capacity) { if (!mz_zip_array_ensure_capacity(pZip, pArray, new_capacity, growing)) return MZ_FALSE; }
3008 return MZ_TRUE;
3009 }
3010
3011 static MZ_FORCEINLINE mz_bool mz_zip_array_resize(mz_zip_archive *pZip, mz_zip_array *pArray, size_t new_size, mz_uint growing)
3012 {
3013 if (new_size > pArray->m_capacity) { if (!mz_zip_array_ensure_capacity(pZip, pArray, new_size, growing)) return MZ_FALSE; }
3014 pArray->m_size = new_size;
3015 return MZ_TRUE;
3016 }
3017
3018 static MZ_FORCEINLINE mz_bool mz_zip_array_ensure_room(mz_zip_archive *pZip, mz_zip_array *pArray, size_t n)
3019 {
3020 return mz_zip_array_reserve(pZip, pArray, pArray->m_size + n, MZ_TRUE);
3021 }
3022
3023 static MZ_FORCEINLINE mz_bool mz_zip_array_push_back(mz_zip_archive *pZip, mz_zip_array *pArray, const void *pElements, size_t n)
3024 {
3025 size_t orig_size = pArray->m_size; if (!mz_zip_array_resize(pZip, pArray, orig_size + n, MZ_TRUE)) return MZ_FALSE;
3026 memcpy((mz_uint8*)pArray->m_p + orig_size * pArray->m_element_size, pElements, n * pArray->m_element_size);
3027 return MZ_TRUE;
3028 }
3029
3030 #ifndef MINIZ_NO_TIME
3031 static time_t mz_zip_dos_to_time_t(int dos_time, int dos_date)
3032 {
3033 struct tm tm;
3034 memset(&tm, 0, sizeof(tm)); tm.tm_isdst = -1;
3035 tm.tm_year = ((dos_date >> 9) & 127) + 1980 - 1900; tm.tm_mon = ((dos_date >> 5) & 15) - 1; tm.tm_mday = dos_date & 31;
3036 tm.tm_hour = (dos_time >> 11) & 31; tm.tm_min = (dos_time >> 5) & 63; tm.tm_sec = (dos_time << 1) & 62;
3037 return mktime(&tm);
3038 }
3039
3040 static void mz_zip_time_to_dos_time(time_t time, mz_uint16 *pDOS_time, mz_uint16 *pDOS_date)
3041 {
3042 #ifdef _MSC_VER
3043 struct tm tm_struct;
3044 struct tm *tm = &tm_struct;
3045 errno_t err = localtime_s(tm, &time);
3046 if (err)
3047 {
3048 *pDOS_date = 0; *pDOS_time = 0;
3049 return;
3050 }
3051 #else
3052 struct tm *tm = localtime(&time);
3053 #endif
3054 *pDOS_time = (mz_uint16)(((tm->tm_hour) << 11) + ((tm->tm_min) << 5) + ((tm->tm_sec) >> 1));
3055 *pDOS_date = (mz_uint16)(((tm->tm_year + 1900 - 1980) << 9) + ((tm->tm_mon + 1) << 5) + tm->tm_mday);
3056 }
3057 #endif
3058
3059 #ifndef MINIZ_NO_STDIO
3060 static mz_bool mz_zip_get_file_modified_time(const char *pFilename, mz_uint16 *pDOS_time, mz_uint16 *pDOS_date)
3061 {
3062 #ifdef MINIZ_NO_TIME
3063 (void)pFilename; *pDOS_date = *pDOS_time = 0;
3064 #else
3065 struct MZ_FILE_STAT_STRUCT file_stat;
3066 // On Linux with x86 glibc, this call will fail on large files (>= 0x80000000 bytes) unless you compiled with _LARGEFILE64_SOURCE. Argh.
3067 if (MZ_FILE_STAT(pFilename, &file_stat) != 0)
3068 return MZ_FALSE;
3069 mz_zip_time_to_dos_time(file_stat.st_mtime, pDOS_time, pDOS_date);
3070 #endif // #ifdef MINIZ_NO_TIME
3071 return MZ_TRUE;
3072 }
3073
3074 #ifndef MINIZ_NO_TIME
3075 static mz_bool mz_zip_set_file_times(const char *pFilename, time_t access_time, time_t modified_time)
3076 {
3077 struct utimbuf t; t.actime = access_time; t.modtime = modified_time;
3078 return !utime(pFilename, &t);
3079 }
3080 #endif // #ifndef MINIZ_NO_TIME
3081 #endif // #ifndef MINIZ_NO_STDIO
3082
3083 static mz_bool mz_zip_reader_init_internal(mz_zip_archive *pZip, mz_uint32 flags)
3084 {
3085 (void)flags;
3086 if ((!pZip) || (pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID))
3087 return MZ_FALSE;
3088
3089 if (!pZip->m_pAlloc) pZip->m_pAlloc = def_alloc_func;
3090 if (!pZip->m_pFree) pZip->m_pFree = def_free_func;
3091 if (!pZip->m_pRealloc) pZip->m_pRealloc = def_realloc_func;
3092
3093 pZip->m_zip_mode = MZ_ZIP_MODE_READING;
3094 pZip->m_archive_size = 0;
3095 pZip->m_central_directory_file_ofs = 0;
3096 pZip->m_total_files = 0;
3097
3098 if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state))))
3099 return MZ_FALSE;
3100 memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state));
3101 MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir, sizeof(mz_uint8));
3102 MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets, sizeof(mz_uint32));
3103 MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets, sizeof(mz_uint32));
3104 return MZ_TRUE;
3105 }
3106
3107 static MZ_FORCEINLINE mz_bool mz_zip_reader_filename_less(const mz_zip_array *pCentral_dir_array, const mz_zip_array *pCentral_dir_offsets, mz_uint l_index, mz_uint r_index)
3108 {
3109 const mz_uint8 *pL = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, l_index)), *pE;
3110 const mz_uint8 *pR = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, r_index));
3111 mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS), r_len = MZ_READ_LE16(pR + MZ_ZIP_CDH_FILENAME_LEN_OFS);
3112 mz_uint8 l = 0, r = 0;
3113 pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE; pR += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
3114 pE = pL + MZ_MIN(l_len, r_len);
3115 while (pL < pE)
3116 {
3117 if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR)))
3118 break;
3119 pL++; pR++;
3120 }
3121 return (pL == pE) ? (l_len < r_len) : (l < r);
3122 }
3123
3124 #define MZ_SWAP_UINT32(a, b) do { mz_uint32 t = a; a = b; b = t; } MZ_MACRO_END
3125
3126 // Heap sort of lowercased filenames, used to help accelerate plain central directory searches by mz_zip_reader_locate_file(). (Could also use qsort(), but it could allocate memory.)
3127 static void mz_zip_reader_sort_central_dir_offsets_by_filename(mz_zip_archive *pZip)
3128 {
3129 mz_zip_internal_state *pState = pZip->m_pState;
3130 const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets;
3131 const mz_zip_array *pCentral_dir = &pState->m_central_dir;
3132 mz_uint32 *pIndices = &MZ_ZIP_ARRAY_ELEMENT(&pState->m_sorted_central_dir_offsets, mz_uint32, 0);
3133 const int size = pZip->m_total_files;
3134 int start = (size - 2) >> 1, end;
3135 while (start >= 0)
3136 {
3137 int child, root = start;
3138 for ( ; ; )
3139 {
3140 if ((child = (root << 1) + 1) >= size)
3141 break;
3142 child += (((child + 1) < size) && (mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[child], pIndices[child + 1])));
3143 if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[root], pIndices[child]))
3144 break;
3145 MZ_SWAP_UINT32(pIndices[root], pIndices[child]); root = child;
3146 }
3147 start--;
3148 }
3149
3150 end = size - 1;
3151 while (end > 0)
3152 {
3153 int child, root = 0;
3154 MZ_SWAP_UINT32(pIndices[end], pIndices[0]);
3155 for ( ; ; )
3156 {
3157 if ((child = (root << 1) + 1) >= end)
3158 break;
3159 child += (((child + 1) < end) && mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[child], pIndices[child + 1]));
3160 if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[root], pIndices[child]))
3161 break;
3162 MZ_SWAP_UINT32(pIndices[root], pIndices[child]); root = child;
3163 }
3164 end--;
3165 }
3166 }
3167
3168 static mz_bool mz_zip_reader_read_central_dir(mz_zip_archive *pZip, mz_uint32 flags)
3169 {
3170 mz_uint cdir_size, num_this_disk, cdir_disk_index;
3171 mz_uint64 cdir_ofs;
3172 mz_int64 cur_file_ofs;
3173 const mz_uint8 *p;
3174 mz_uint32 buf_u32[4096 / sizeof(mz_uint32)]; mz_uint8 *pBuf = (mz_uint8 *)buf_u32;
3175 mz_bool sort_central_dir = ((flags & MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY) == 0);
3176 // Basic sanity checks - reject files which are too small, and check the first 4 bytes of the file to make sure a local header is there.
3177 if (pZip->m_archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
3178 return MZ_FALSE;
3179 // Find the end of central directory record by scanning the file from the end towards the beginning.
3180 cur_file_ofs = MZ_MAX((mz_int64)pZip->m_archive_size - (mz_int64)sizeof(buf_u32), 0);
3181 for ( ; ; )
3182 {
3183 int i, n = (int)MZ_MIN(sizeof(buf_u32), pZip->m_archive_size - cur_file_ofs);
3184 if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, n) != (mz_uint)n)
3185 return MZ_FALSE;
3186 for (i = n - 4; i >= 0; --i)
3187 if (MZ_READ_LE32(pBuf + i) == MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG)
3188 break;
3189 if (i >= 0)
3190 {
3191 cur_file_ofs += i;
3192 break;
3193 }
3194 if ((!cur_file_ofs) || ((pZip->m_archive_size - cur_file_ofs) >= (0xFFFF + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)))
3195 return MZ_FALSE;
3196 cur_file_ofs = MZ_MAX(cur_file_ofs - (sizeof(buf_u32) - 3), 0);
3197 }
3198 // Read and verify the end of central directory record.
3199 if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) != MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
3200 return MZ_FALSE;
3201 if ((MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_SIG_OFS) != MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG) ||
3202 ((pZip->m_total_files = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS)) != MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS)))
3203 return MZ_FALSE;
3204
3205 num_this_disk = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_THIS_DISK_OFS);
3206 cdir_disk_index = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS);
3207 if (((num_this_disk | cdir_disk_index) != 0) && ((num_this_disk != 1) || (cdir_disk_index != 1)))
3208 return MZ_FALSE;
3209
3210 if ((cdir_size = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_SIZE_OFS)) < pZip->m_total_files * MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)
3211 return MZ_FALSE;
3212
3213 cdir_ofs = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_OFS_OFS);
3214 if ((cdir_ofs + (mz_uint64)cdir_size) > pZip->m_archive_size)
3215 return MZ_FALSE;
3216
3217 pZip->m_central_directory_file_ofs = cdir_ofs;
3218
3219 if (pZip->m_total_files)
3220 {
3221 mz_uint i, n;
3222
3223 // Read the entire central directory into a heap block, and allocate another heap block to hold the unsorted central dir file record offsets, and another to hold the sorted indices.
3224 if ((!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir, cdir_size, MZ_FALSE)) ||
3225 (!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir_offsets, pZip->m_total_files, MZ_FALSE)))
3226 return MZ_FALSE;
3227
3228 if (sort_central_dir)
3229 {
3230 if (!mz_zip_array_resize(pZip, &pZip->m_pState->m_sorted_central_dir_offsets, pZip->m_total_files, MZ_FALSE))
3231 return MZ_FALSE;
3232 }
3233
3234 if (pZip->m_pRead(pZip->m_pIO_opaque, cdir_ofs, pZip->m_pState->m_central_dir.m_p, cdir_size) != cdir_size)
3235 return MZ_FALSE;
3236
3237 // Now create an index into the central directory file records, do some basic sanity checking on each record, and check for zip64 entries (which are not yet supported).
3238 p = (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p;
3239 for (n = cdir_size, i = 0; i < pZip->m_total_files; ++i)
3240 {
3241 mz_uint total_header_size, comp_size, decomp_size, disk_index;
3242 if ((n < MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) || (MZ_READ_LE32(p) != MZ_ZIP_CENTRAL_DIR_HEADER_SIG))
3243 return MZ_FALSE;
3244 MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, i) = (mz_uint32)(p - (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p);
3245 if (sort_central_dir)
3246 MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_sorted_central_dir_offsets, mz_uint32, i) = i;
3247 comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
3248 decomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
3249 if (((!MZ_READ_LE32(p + MZ_ZIP_CDH_METHOD_OFS)) && (decomp_size != comp_size)) || (decomp_size && !comp_size) || (decomp_size == 0xFFFFFFFF) || (comp_size == 0xFFFFFFFF))
3250 return MZ_FALSE;
3251 disk_index = MZ_READ_LE16(p + MZ_ZIP_CDH_DISK_START_OFS);
3252 if ((disk_index != num_this_disk) && (disk_index != 1))
3253 return MZ_FALSE;
3254 if (((mz_uint64)MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS) + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + comp_size) > pZip->m_archive_size)
3255 return MZ_FALSE;
3256 if ((total_header_size = MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS)) > n)
3257 return MZ_FALSE;
3258 n -= total_header_size; p += total_header_size;
3259 }
3260 }
3261
3262 if (sort_central_dir)
3263 mz_zip_reader_sort_central_dir_offsets_by_filename(pZip);
3264
3265 return MZ_TRUE;
3266 }
3267
3268 mz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size, mz_uint32 flags)
3269 {
3270 if ((!pZip) || (!pZip->m_pRead))
3271 return MZ_FALSE;
3272 if (!mz_zip_reader_init_internal(pZip, flags))
3273 return MZ_FALSE;
3274 pZip->m_archive_size = size;
3275 if (!mz_zip_reader_read_central_dir(pZip, flags))
3276 {
3277 mz_zip_reader_end(pZip);
3278 return MZ_FALSE;
3279 }
3280 return MZ_TRUE;
3281 }
3282
3283 static size_t mz_zip_mem_read_func(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n)
3284 {
3285 mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
3286 size_t s = (file_ofs >= pZip->m_archive_size) ? 0 : (size_t)MZ_MIN(pZip->m_archive_size - file_ofs, n);
3287 memcpy(pBuf, (const mz_uint8 *)pZip->m_pState->m_pMem + file_ofs, s);
3288 return s;
3289 }
3290
3291 mz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem, size_t size, mz_uint32 flags)
3292 {
3293 if (!mz_zip_reader_init_internal(pZip, flags))
3294 return MZ_FALSE;
3295 pZip->m_archive_size = size;
3296 pZip->m_pRead = mz_zip_mem_read_func;
3297 pZip->m_pIO_opaque = pZip;
3298 #ifdef __cplusplus
3299 pZip->m_pState->m_pMem = const_cast<void *>(pMem);
3300 #else
3301 pZip->m_pState->m_pMem = (void *)pMem;
3302 #endif
3303 pZip->m_pState->m_mem_size = size;
3304 if (!mz_zip_reader_read_central_dir(pZip, flags))
3305 {
3306 mz_zip_reader_end(pZip);
3307 return MZ_FALSE;
3308 }
3309 return MZ_TRUE;
3310 }
3311
3312 #ifndef MINIZ_NO_STDIO
3313 static size_t mz_zip_file_read_func(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n)
3314 {
3315 mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
3316 mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile);
3317 if (((mz_int64)file_ofs < 0) || (((cur_ofs != (mz_int64)file_ofs)) && (MZ_FSEEK64(pZip->m_pState->m_pFile, (mz_int64)file_ofs, SEEK_SET))))
3318 return 0;
3319 return MZ_FREAD(pBuf, 1, n, pZip->m_pState->m_pFile);
3320 }
3321
3322 mz_bool mz_zip_reader_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint32 flags)
3323 {
3324 mz_uint64 file_size;
3325 MZ_FILE *pFile = MZ_FOPEN(pFilename, "rb");
3326 if (!pFile)
3327 return MZ_FALSE;
3328 if (MZ_FSEEK64(pFile, 0, SEEK_END))
3329 {
3330 MZ_FCLOSE(pFile);
3331 return MZ_FALSE;
3332 }
3333 file_size = MZ_FTELL64(pFile);
3334 if (!mz_zip_reader_init_internal(pZip, flags))
3335 {
3336 MZ_FCLOSE(pFile);
3337 return MZ_FALSE;
3338 }
3339 pZip->m_pRead = mz_zip_file_read_func;
3340 pZip->m_pIO_opaque = pZip;
3341 pZip->m_pState->m_pFile = pFile;
3342 pZip->m_archive_size = file_size;
3343 if (!mz_zip_reader_read_central_dir(pZip, flags))
3344 {
3345 mz_zip_reader_end(pZip);
3346 return MZ_FALSE;
3347 }
3348 return MZ_TRUE;
3349 }
3350 #endif // #ifndef MINIZ_NO_STDIO
3351
3352 mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip)
3353 {
3354 return pZip ? pZip->m_total_files : 0;
3355 }
3356
3357 static MZ_FORCEINLINE const mz_uint8 *mz_zip_reader_get_cdh(mz_zip_archive *pZip, mz_uint file_index)
3358 {
3359 if ((!pZip) || (!pZip->m_pState) || (file_index >= pZip->m_total_files) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
3360 return NULL;
3361 return &MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index));
3362 }
3363
3364 mz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive *pZip, mz_uint file_index)
3365 {
3366 mz_uint m_bit_flag;
3367 const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index);
3368 if (!p)
3369 return MZ_FALSE;
3370 m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
3371 return (m_bit_flag & 1);
3372 }
3373
3374 mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip, mz_uint file_index)
3375 {
3376 mz_uint filename_len, external_attr;
3377 const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index);
3378 if (!p)
3379 return MZ_FALSE;
3380
3381 // First see if the filename ends with a '/' character.
3382 filename_len = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
3383 if (filename_len)
3384 {
3385 if (*(p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_len - 1) == '/')
3386 return MZ_TRUE;
3387 }
3388
3389 // Bugfix: This code was also checking if the internal attribute was non-zero, which wasn't correct.
3390 // Most/all zip writers (hopefully) set DOS file/directory attributes in the low 16-bits, so check for the DOS directory flag and ignore the source OS ID in the created by field.
3391 // FIXME: Remove this check? Is it necessary - we already check the filename.
3392 external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS);
3393 if ((external_attr & 0x10) != 0)
3394 return MZ_TRUE;
3395
3396 return MZ_FALSE;
3397 }
3398
3399 mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index, mz_zip_archive_file_stat *pStat)
3400 {
3401 mz_uint n;
3402 const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index);
3403 if ((!p) || (!pStat))
3404 return MZ_FALSE;
3405
3406 // Unpack the central directory record.
3407 pStat->m_file_index = file_index;
3408 pStat->m_central_dir_ofs = MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index);
3409 pStat->m_version_made_by = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_MADE_BY_OFS);
3410 pStat->m_version_needed = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_NEEDED_OFS);
3411 pStat->m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
3412 pStat->m_method = MZ_READ_LE16(p + MZ_ZIP_CDH_METHOD_OFS);
3413 #ifndef MINIZ_NO_TIME
3414 pStat->m_time = mz_zip_dos_to_time_t(MZ_READ_LE16(p + MZ_ZIP_CDH_FILE_TIME_OFS), MZ_READ_LE16(p + MZ_ZIP_CDH_FILE_DATE_OFS));
3415 #endif
3416 pStat->m_crc32 = MZ_READ_LE32(p + MZ_ZIP_CDH_CRC32_OFS);
3417 pStat->m_comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
3418 pStat->m_uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
3419 pStat->m_internal_attr = MZ_READ_LE16(p + MZ_ZIP_CDH_INTERNAL_ATTR_OFS);
3420 pStat->m_external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS);
3421 pStat->m_local_header_ofs = MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS);
3422
3423 // Copy as much of the filename and comment as possible.
3424 n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS); n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE - 1);
3425 memcpy(pStat->m_filename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n); pStat->m_filename[n] = '\0';
3426
3427 n = MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS); n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE - 1);
3428 pStat->m_comment_size = n;
3429 memcpy(pStat->m_comment, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS), n); pStat->m_comment[n] = '\0';
3430
3431 return MZ_TRUE;
3432 }
3433
3434 mz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, mz_uint file_index, char *pFilename, mz_uint filename_buf_size)
3435 {
3436 mz_uint n;
3437 const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index);
3438 if (!p) { if (filename_buf_size) pFilename[0] = '\0'; return 0; }
3439 n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
3440 if (filename_buf_size)
3441 {
3442 n = MZ_MIN(n, filename_buf_size - 1);
3443 memcpy(pFilename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n);
3444 pFilename[n] = '\0';
3445 }
3446 return n + 1;
3447 }
3448
3449 static MZ_FORCEINLINE mz_bool mz_zip_reader_string_equal(const char *pA, const char *pB, mz_uint len, mz_uint flags)
3450 {
3451 mz_uint i;
3452 if (flags & MZ_ZIP_FLAG_CASE_SENSITIVE)
3453 return 0 == memcmp(pA, pB, len);
3454 for (i = 0; i < len; ++i)
3455 if (MZ_TOLOWER(pA[i]) != MZ_TOLOWER(pB[i]))
3456 return MZ_FALSE;
3457 return MZ_TRUE;
3458 }
3459
3460 static MZ_FORCEINLINE int mz_zip_reader_filename_compare(const mz_zip_array *pCentral_dir_array, const mz_zip_array *pCentral_dir_offsets, mz_uint l_index, const char *pR, mz_uint r_len)
3461 {
3462 const mz_uint8 *pL = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, l_index)), *pE;
3463 mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS);
3464 mz_uint8 l = 0, r = 0;
3465 pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
3466 pE = pL + MZ_MIN(l_len, r_len);
3467 while (pL < pE)
3468 {
3469 if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR)))
3470 break;
3471 pL++; pR++;
3472 }
3473 return (pL == pE) ? (int)(l_len - r_len) : (l - r);
3474 }
3475
3476 static int mz_zip_reader_locate_file_binary_search(mz_zip_archive *pZip, const char *pFilename)
3477 {
3478 mz_zip_internal_state *pState = pZip->m_pState;
3479 const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets;
3480 const mz_zip_array *pCentral_dir = &pState->m_central_dir;
3481 mz_uint32 *pIndices = &MZ_ZIP_ARRAY_ELEMENT(&pState->m_sorted_central_dir_offsets, mz_uint32, 0);
3482 const int size = pZip->m_total_files;
3483 const mz_uint filename_len = (mz_uint)strlen(pFilename);
3484 int l = 0, h = size - 1;
3485 while (l <= h)
3486 {
3487 int m = (l + h) >> 1, file_index = pIndices[m], comp = mz_zip_reader_filename_compare(pCentral_dir, pCentral_dir_offsets, file_index, pFilename, filename_len);
3488 if (!comp)
3489 return file_index;
3490 else if (comp < 0)
3491 l = m + 1;
3492 else
3493 h = m - 1;
3494 }
3495 return -1;
3496 }
3497
3498 int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags)
3499 {
3500 mz_uint file_index; size_t name_len, comment_len;
3501 if ((!pZip) || (!pZip->m_pState) || (!pName) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
3502 return -1;
3503 if (((flags & (MZ_ZIP_FLAG_IGNORE_PATH | MZ_ZIP_FLAG_CASE_SENSITIVE)) == 0) && (!pComment) && (pZip->m_pState->m_sorted_central_dir_offsets.m_size))
3504 return mz_zip_reader_locate_file_binary_search(pZip, pName);
3505 name_len = strlen(pName); if (name_len > 0xFFFF) return -1;
3506 comment_len = pComment ? strlen(pComment) : 0; if (comment_len > 0xFFFF) return -1;
3507 for (file_index = 0; file_index < pZip->m_total_files; file_index++)
3508 {
3509 const mz_uint8 *pHeader = &MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index));
3510 mz_uint filename_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_FILENAME_LEN_OFS);
3511 const char *pFilename = (const char *)pHeader + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
3512 if (filename_len < name_len)
3513 continue;
3514 if (comment_len)
3515 {
3516 mz_uint file_extra_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_EXTRA_LEN_OFS), file_comment_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_COMMENT_LEN_OFS);
3517 const char *pFile_comment = pFilename + filename_len + file_extra_len;
3518 if ((file_comment_len != comment_len) || (!mz_zip_reader_string_equal(pComment, pFile_comment, file_comment_len, flags)))
3519 continue;
3520 }
3521 if ((flags & MZ_ZIP_FLAG_IGNORE_PATH) && (filename_len))
3522 {
3523 int ofs = filename_len - 1;
3524 do
3525 {
3526 if ((pFilename[ofs] == '/') || (pFilename[ofs] == '\\') || (pFilename[ofs] == ':'))
3527 break;
3528 } while (--ofs >= 0);
3529 ofs++;
3530 pFilename += ofs; filename_len -= ofs;
3531 }
3532 if ((filename_len == name_len) && (mz_zip_reader_string_equal(pName, pFilename, filename_len, flags)))
3533 return file_index;
3534 }
3535 return -1;
3536 }
3537
3538 mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size)
3539 {
3540 int status = TINFL_STATUS_DONE;
3541 mz_uint64 needed_size, cur_file_ofs, comp_remaining, out_buf_ofs = 0, read_buf_size, read_buf_ofs = 0, read_buf_avail;
3542 mz_zip_archive_file_stat file_stat;
3543 void *pRead_buf;
3544 mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)]; mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
3545 tinfl_decompressor inflator;
3546
3547 if ((buf_size) && (!pBuf))
3548 return MZ_FALSE;
3549
3550 if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
3551 return MZ_FALSE;
3552
3553 // Empty file, or a directory (but not always a directory - I've seen odd zips with directories that have compressed data which inflates to 0 bytes)
3554 if (!file_stat.m_comp_size)
3555 return MZ_TRUE;
3556
3557 // Entry is a subdirectory (I've seen old zips with dir entries which have compressed deflate data which inflates to 0 bytes, but these entries claim to uncompress to 512 bytes in the headers).
3558 // I'm torn how to handle this case - should it fail instead?
3559 if (mz_zip_reader_is_file_a_directory(pZip, file_index))
3560 return MZ_TRUE;
3561
3562 // Encryption and patch files are not supported.
3563 if (file_stat.m_bit_flag & (1 | 32))
3564 return MZ_FALSE;
3565
3566 // This function only supports stored and deflate.
3567 if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED))
3568 return MZ_FALSE;
3569
3570 // Ensure supplied output buffer is large enough.
3571 needed_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? file_stat.m_comp_size : file_stat.m_uncomp_size;
3572 if (buf_size < needed_size)
3573 return MZ_FALSE;
3574
3575 // Read and parse the local directory entry.
3576 cur_file_ofs = file_stat.m_local_header_ofs;
3577 if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
3578 return MZ_FALSE;
3579 if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
3580 return MZ_FALSE;
3581
3582 cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
3583 if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size)
3584 return MZ_FALSE;
3585
3586 if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method))
3587 {
3588 // The file is stored or the caller has requested the compressed data.
3589 if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, (size_t)needed_size) != needed_size)
3590 return MZ_FALSE;
3591 return ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) != 0) || (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, (size_t)file_stat.m_uncomp_size) == file_stat.m_crc32);
3592 }
3593
3594 // Decompress the file either directly from memory or from a file input buffer.
3595 tinfl_init(&inflator);
3596
3597 if (pZip->m_pState->m_pMem)
3598 {
3599 // Read directly from the archive in memory.
3600 pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs;
3601 read_buf_size = read_buf_avail = file_stat.m_comp_size;
3602 comp_remaining = 0;
3603 }
3604 else if (pUser_read_buf)
3605 {
3606 // Use a user provided read buffer.
3607 if (!user_read_buf_size)
3608 return MZ_FALSE;
3609 pRead_buf = (mz_uint8 *)pUser_read_buf;
3610 read_buf_size = user_read_buf_size;
3611 read_buf_avail = 0;
3612 comp_remaining = file_stat.m_comp_size;
3613 }
3614 else
3615 {
3616 // Temporarily allocate a read buffer.
3617 read_buf_size = MZ_MIN(file_stat.m_comp_size, MZ_ZIP_MAX_IO_BUF_SIZE);
3618 #ifdef _MSC_VER
3619 if (((0, sizeof(size_t) == sizeof(mz_uint32))) && (read_buf_size > 0x7FFFFFFF))
3620 #else
3621 if (((sizeof(size_t) == sizeof(mz_uint32))) && (read_buf_size > 0x7FFFFFFF))
3622 #endif
3623 return MZ_FALSE;
3624 if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)read_buf_size)))
3625 return MZ_FALSE;
3626 read_buf_avail = 0;
3627 comp_remaining = file_stat.m_comp_size;
3628 }
3629
3630 do
3631 {
3632 size_t in_buf_size, out_buf_size = (size_t)(file_stat.m_uncomp_size - out_buf_ofs);
3633 if ((!read_buf_avail) && (!pZip->m_pState->m_pMem))
3634 {
3635 read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
3636 if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)
3637 {
3638 status = TINFL_STATUS_FAILED;
3639 break;
3640 }
3641 cur_file_ofs += read_buf_avail;
3642 comp_remaining -= read_buf_avail;
3643 read_buf_ofs = 0;
3644 }
3645 in_buf_size = (size_t)read_buf_avail;
3646 status = tinfl_decompress(&inflator, (mz_uint8 *)pRead_buf + read_buf_ofs, &in_buf_size, (mz_uint8 *)pBuf, (mz_uint8 *)pBuf + out_buf_ofs, &out_buf_size, TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF | (comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0));
3647 read_buf_avail -= in_buf_size;
3648 read_buf_ofs += in_buf_size;
3649 out_buf_ofs += out_buf_size;
3650 } while (status == TINFL_STATUS_NEEDS_MORE_INPUT);
3651
3652 if (status == TINFL_STATUS_DONE)
3653 {
3654 // Make sure the entire file was decompressed, and check its CRC.
3655 if ((out_buf_ofs != file_stat.m_uncomp_size) || (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, (size_t)file_stat.m_uncomp_size) != file_stat.m_crc32))
3656 status = TINFL_STATUS_FAILED;
3657 }
3658
3659 if ((!pZip->m_pState->m_pMem) && (!pUser_read_buf))
3660 pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
3661
3662 return status == TINFL_STATUS_DONE;
3663 }
3664
3665 mz_bool mz_zip_reader_extract_file_to_mem_no_alloc(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size)
3666 {
3667 int file_index = mz_zip_reader_locate_file(pZip, pFilename, NULL, flags);
3668 if (file_index < 0)
3669 return MZ_FALSE;
3670 return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size, flags, pUser_read_buf, user_read_buf_size);
3671 }
3672
3673 mz_bool mz_zip_reader_extract_to_mem(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags)
3674 {
3675 return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size, flags, NULL, 0);
3676 }
3677
3678 mz_bool mz_zip_reader_extract_file_to_mem(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags)
3679 {
3680 return mz_zip_reader_extract_file_to_mem_no_alloc(pZip, pFilename, pBuf, buf_size, flags, NULL, 0);
3681 }
3682
3683 void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index, size_t *pSize, mz_uint flags)
3684 {
3685 mz_uint64 comp_size, uncomp_size, alloc_size;
3686 const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index);
3687 void *pBuf;
3688
3689 if (pSize)
3690 *pSize = 0;
3691 if (!p)
3692 return NULL;
3693
3694 comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
3695 uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
3696
3697 alloc_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? comp_size : uncomp_size;
3698 #ifdef _MSC_VER
3699 if (((0, sizeof(size_t) == sizeof(mz_uint32))) && (alloc_size > 0x7FFFFFFF))
3700 #else
3701 if (((sizeof(size_t) == sizeof(mz_uint32))) && (alloc_size > 0x7FFFFFFF))
3702 #endif
3703 return NULL;
3704 if (NULL == (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)alloc_size)))
3705 return NULL;
3706
3707 if (!mz_zip_reader_extract_to_mem(pZip, file_index, pBuf, (size_t)alloc_size, flags))
3708 {
3709 pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
3710 return NULL;
3711 }
3712
3713 if (pSize) *pSize = (size_t)alloc_size;
3714 return pBuf;
3715 }
3716
3717 void *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip, const char *pFilename, size_t *pSize, mz_uint flags)
3718 {
3719 int file_index = mz_zip_reader_locate_file(pZip, pFilename, NULL, flags);
3720 if (file_index < 0)
3721 {
3722 if (pSize) *pSize = 0;
3723 return MZ_FALSE;
3724 }
3725 return mz_zip_reader_extract_to_heap(pZip, file_index, pSize, flags);
3726 }
3727
3728 mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip, mz_uint file_index, mz_file_write_func pCallback, void *pOpaque, mz_uint flags)
3729 {
3730 int status = TINFL_STATUS_DONE; mz_uint file_crc32 = MZ_CRC32_INIT;
3731 mz_uint64 read_buf_size, read_buf_ofs = 0, read_buf_avail, comp_remaining, out_buf_ofs = 0, cur_file_ofs;
3732 mz_zip_archive_file_stat file_stat;
3733 void *pRead_buf = NULL; void *pWrite_buf = NULL;
3734 mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)]; mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
3735
3736 if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
3737 return MZ_FALSE;
3738
3739 // Empty file, or a directory (but not always a directory - I've seen odd zips with directories that have compressed data which inflates to 0 bytes)
3740 if (!file_stat.m_comp_size)
3741 return MZ_TRUE;
3742
3743 // Entry is a subdirectory (I've seen old zips with dir entries which have compressed deflate data which inflates to 0 bytes, but these entries claim to uncompress to 512 bytes in the headers).
3744 // I'm torn how to handle this case - should it fail instead?
3745 if (mz_zip_reader_is_file_a_directory(pZip, file_index))
3746 return MZ_TRUE;
3747
3748 // Encryption and patch files are not supported.
3749 if (file_stat.m_bit_flag & (1 | 32))
3750 return MZ_FALSE;
3751
3752 // This function only supports stored and deflate.
3753 if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED))
3754 return MZ_FALSE;
3755
3756 // Read and parse the local directory entry.
3757 cur_file_ofs = file_stat.m_local_header_ofs;
3758 if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
3759 return MZ_FALSE;
3760 if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
3761 return MZ_FALSE;
3762
3763 cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
3764 if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size)
3765 return MZ_FALSE;
3766
3767 // Decompress the file either directly from memory or from a file input buffer.
3768 if (pZip->m_pState->m_pMem)
3769 {
3770 pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs;
3771 read_buf_size = read_buf_avail = file_stat.m_comp_size;
3772 comp_remaining = 0;
3773 }
3774 else
3775 {
3776 read_buf_size = MZ_MIN(file_stat.m_comp_size, MZ_ZIP_MAX_IO_BUF_SIZE);
3777 if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)read_buf_size)))
3778 return MZ_FALSE;
3779 read_buf_avail = 0;
3780 comp_remaining = file_stat.m_comp_size;
3781 }
3782
3783 if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method))
3784 {
3785 // The file is stored or the caller has requested the compressed data.
3786 if (pZip->m_pState->m_pMem)
3787 {
3788 #ifdef _MSC_VER
3789 if (((0, sizeof(size_t) == sizeof(mz_uint32))) && (file_stat.m_comp_size > 0xFFFFFFFF))
3790 #else
3791 if (((sizeof(size_t) == sizeof(mz_uint32))) && (file_stat.m_comp_size > 0xFFFFFFFF))
3792 #endif
3793 return MZ_FALSE;
3794 if (pCallback(pOpaque, out_buf_ofs, pRead_buf, (size_t)file_stat.m_comp_size) != file_stat.m_comp_size)
3795 status = TINFL_STATUS_FAILED;
3796 else if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
3797 file_crc32 = (mz_uint32)mz_crc32(file_crc32, (const mz_uint8 *)pRead_buf, (size_t)file_stat.m_comp_size);
3798 cur_file_ofs += file_stat.m_comp_size;
3799 out_buf_ofs += file_stat.m_comp_size;
3800 comp_remaining = 0;
3801 }
3802 else
3803 {
3804 while (comp_remaining)
3805 {
3806 read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
3807 if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)
3808 {
3809 status = TINFL_STATUS_FAILED;
3810 break;
3811 }
3812
3813 if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
3814 file_crc32 = (mz_uint32)mz_crc32(file_crc32, (const mz_uint8 *)pRead_buf, (size_t)read_buf_avail);
3815
3816 if (pCallback(pOpaque, out_buf_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)
3817 {
3818 status = TINFL_STATUS_FAILED;
3819 break;
3820 }
3821 cur_file_ofs += read_buf_avail;
3822 out_buf_ofs += read_buf_avail;
3823 comp_remaining -= read_buf_avail;
3824 }
3825 }
3826 }
3827 else
3828 {
3829 tinfl_decompressor inflator;
3830 tinfl_init(&inflator);
3831
3832 if (NULL == (pWrite_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, TINFL_LZ_DICT_SIZE)))
3833 status = TINFL_STATUS_FAILED;
3834 else
3835 {
3836 do
3837 {
3838 mz_uint8 *pWrite_buf_cur = (mz_uint8 *)pWrite_buf + (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));
3839 size_t in_buf_size, out_buf_size = TINFL_LZ_DICT_SIZE - (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));
3840 if ((!read_buf_avail) && (!pZip->m_pState->m_pMem))
3841 {
3842 read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
3843 if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)
3844 {
3845 status = TINFL_STATUS_FAILED;
3846 break;
3847 }
3848 cur_file_ofs += read_buf_avail;
3849 comp_remaining -= read_buf_avail;
3850 read_buf_ofs = 0;
3851 }
3852
3853 in_buf_size = (size_t)read_buf_avail;
3854 status = tinfl_decompress(&inflator, (const mz_uint8 *)pRead_buf + read_buf_ofs, &in_buf_size, (mz_uint8 *)pWrite_buf, pWrite_buf_cur, &out_buf_size, comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0);
3855 read_buf_avail -= in_buf_size;
3856 read_buf_ofs += in_buf_size;
3857
3858 if (out_buf_size)
3859 {
3860 if (pCallback(pOpaque, out_buf_ofs, pWrite_buf_cur, out_buf_size) != out_buf_size)
3861 {
3862 status = TINFL_STATUS_FAILED;
3863 break;
3864 }
3865 file_crc32 = (mz_uint32)mz_crc32(file_crc32, pWrite_buf_cur, out_buf_size);
3866 if ((out_buf_ofs += out_buf_size) > file_stat.m_uncomp_size)
3867 {
3868 status = TINFL_STATUS_FAILED;
3869 break;
3870 }
3871 }
3872 } while ((status == TINFL_STATUS_NEEDS_MORE_INPUT) || (status == TINFL_STATUS_HAS_MORE_OUTPUT));
3873 }
3874 }
3875
3876 if ((status == TINFL_STATUS_DONE) && (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)))
3877 {
3878 // Make sure the entire file was decompressed, and check its CRC.
3879 if ((out_buf_ofs != file_stat.m_uncomp_size) || (file_crc32 != file_stat.m_crc32))
3880 status = TINFL_STATUS_FAILED;
3881 }
3882
3883 if (!pZip->m_pState->m_pMem)
3884 pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
3885 if (pWrite_buf)
3886 pZip->m_pFree(pZip->m_pAlloc_opaque, pWrite_buf);
3887
3888 return status == TINFL_STATUS_DONE;
3889 }
3890
3891 mz_bool mz_zip_reader_extract_file_to_callback(mz_zip_archive *pZip, const char *pFilename, mz_file_write_func pCallback, void *pOpaque, mz_uint flags)
3892 {
3893 int file_index = mz_zip_reader_locate_file(pZip, pFilename, NULL, flags);
3894 if (file_index < 0)
3895 return MZ_FALSE;
3896 return mz_zip_reader_extract_to_callback(pZip, file_index, pCallback, pOpaque, flags);
3897 }
3898
3899 #ifndef MINIZ_NO_STDIO
3900 static size_t mz_zip_file_write_callback(void *pOpaque, mz_uint64 ofs, const void *pBuf, size_t n)
3901 {
3902 (void)ofs; return MZ_FWRITE(pBuf, 1, n, (MZ_FILE*)pOpaque);
3903 }
3904
3905 mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index, const char *pDst_filename, mz_uint flags)
3906 {
3907 mz_bool status;
3908 mz_zip_archive_file_stat file_stat;
3909 MZ_FILE *pFile;
3910 if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
3911 return MZ_FALSE;
3912 pFile = MZ_FOPEN(pDst_filename, "wb");
3913 if (!pFile)
3914 return MZ_FALSE;
3915 status = mz_zip_reader_extract_to_callback(pZip, file_index, mz_zip_file_write_callback, pFile, flags);
3916 if (MZ_FCLOSE(pFile) == EOF)
3917 return MZ_FALSE;
3918 #ifndef MINIZ_NO_TIME
3919 if (status)
3920 mz_zip_set_file_times(pDst_filename, file_stat.m_time, file_stat.m_time);
3921 #endif
3922 return status;
3923 }
3924 #endif // #ifndef MINIZ_NO_STDIO
3925
3926 mz_bool mz_zip_reader_end(mz_zip_archive *pZip)
3927 {
3928 if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
3929 return MZ_FALSE;
3930
3931 if (pZip->m_pState)
3932 {
3933 mz_zip_internal_state *pState = pZip->m_pState; pZip->m_pState = NULL;
3934 mz_zip_array_clear(pZip, &pState->m_central_dir);
3935 mz_zip_array_clear(pZip, &pState->m_central_dir_offsets);
3936 mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets);
3937
3938 #ifndef MINIZ_NO_STDIO
3939 if (pState->m_pFile)
3940 {
3941 MZ_FCLOSE(pState->m_pFile);
3942 pState->m_pFile = NULL;
3943 }
3944 #endif // #ifndef MINIZ_NO_STDIO
3945
3946 pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
3947 }
3948 pZip->m_zip_mode = MZ_ZIP_MODE_INVALID;
3949
3950 return MZ_TRUE;
3951 }
3952
3953 #ifndef MINIZ_NO_STDIO
3954 mz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive *pZip, const char *pArchive_filename, const char *pDst_filename, mz_uint flags)
3955 {
3956 int file_index = mz_zip_reader_locate_file(pZip, pArchive_filename, NULL, flags);
3957 if (file_index < 0)
3958 return MZ_FALSE;
3959 return mz_zip_reader_extract_to_file(pZip, file_index, pDst_filename, flags);
3960 }
3961 #endif
3962
3963 // ------------------- .ZIP archive writing
3964
3965 #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
3966
3967 static void mz_write_le16(mz_uint8 *p, mz_uint16 v) { p[0] = (mz_uint8)v; p[1] = (mz_uint8)(v >> 8); }
3968 static void mz_write_le32(mz_uint8 *p, mz_uint32 v) { p[0] = (mz_uint8)v; p[1] = (mz_uint8)(v >> 8); p[2] = (mz_uint8)(v >> 16); p[3] = (mz_uint8)(v >> 24); }
3969 #define MZ_WRITE_LE16(p, v) mz_write_le16((mz_uint8 *)(p), (mz_uint16)(v))
3970 #define MZ_WRITE_LE32(p, v) mz_write_le32((mz_uint8 *)(p), (mz_uint32)(v))
3971
3972 mz_bool mz_zip_writer_init(mz_zip_archive *pZip, mz_uint64 existing_size)
3973 {
3974 if ((!pZip) || (pZip->m_pState) || (!pZip->m_pWrite) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID))
3975 return MZ_FALSE;
3976
3977 if (pZip->m_file_offset_alignment)
3978 {
3979 // Ensure user specified file offset alignment is a power of 2.
3980 if (pZip->m_file_offset_alignment & (pZip->m_file_offset_alignment - 1))
3981 return MZ_FALSE;
3982 }
3983
3984 if (!pZip->m_pAlloc) pZip->m_pAlloc = def_alloc_func;
3985 if (!pZip->m_pFree) pZip->m_pFree = def_free_func;
3986 if (!pZip->m_pRealloc) pZip->m_pRealloc = def_realloc_func;
3987
3988 pZip->m_zip_mode = MZ_ZIP_MODE_WRITING;
3989 pZip->m_archive_size = existing_size;
3990 pZip->m_central_directory_file_ofs = 0;
3991 pZip->m_total_files = 0;
3992
3993 if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state))))
3994 return MZ_FALSE;
3995 memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state));
3996 MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir, sizeof(mz_uint8));
3997 MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets, sizeof(mz_uint32));
3998 MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets, sizeof(mz_uint32));
3999 return MZ_TRUE;
4000 }
4001
4002 static size_t mz_zip_heap_write_func(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n)
4003 {
4004 mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
4005 mz_zip_internal_state *pState = pZip->m_pState;
4006 mz_uint64 new_size = MZ_MAX(file_ofs + n, pState->m_mem_size);
4007 #ifdef _MSC_VER
4008 if ((!n) || ((0, sizeof(size_t) == sizeof(mz_uint32)) && (new_size > 0x7FFFFFFF)))
4009 #else
4010 if ((!n) || ((sizeof(size_t) == sizeof(mz_uint32)) && (new_size > 0x7FFFFFFF)))
4011 #endif
4012 return 0;
4013 if (new_size > pState->m_mem_capacity)
4014 {
4015 void *pNew_block;
4016 size_t new_capacity = MZ_MAX(64, pState->m_mem_capacity); while (new_capacity < new_size) new_capacity *= 2;
4017 if (NULL == (pNew_block = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pState->m_pMem, 1, new_capacity)))
4018 return 0;
4019 pState->m_pMem = pNew_block; pState->m_mem_capacity = new_capacity;
4020 }
4021 memcpy((mz_uint8 *)pState->m_pMem + file_ofs, pBuf, n);
4022 pState->m_mem_size = (size_t)new_size;
4023 return n;
4024 }
4025
4026 mz_bool mz_zip_writer_init_heap(mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size)
4027 {
4028 pZip->m_pWrite = mz_zip_heap_write_func;
4029 pZip->m_pIO_opaque = pZip;
4030 if (!mz_zip_writer_init(pZip, size_to_reserve_at_beginning))
4031 return MZ_FALSE;
4032 if (0 != (initial_allocation_size = MZ_MAX(initial_allocation_size, size_to_reserve_at_beginning)))
4033 {
4034 if (NULL == (pZip->m_pState->m_pMem = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, initial_allocation_size)))
4035 {
4036 mz_zip_writer_end(pZip);
4037 return MZ_FALSE;
4038 }
4039 pZip->m_pState->m_mem_capacity = initial_allocation_size;
4040 }
4041 return MZ_TRUE;
4042 }
4043
4044 #ifndef MINIZ_NO_STDIO
4045 static size_t mz_zip_file_write_func(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n)
4046 {
4047 mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
4048 mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile);
4049 if (((mz_int64)file_ofs < 0) || (((cur_ofs != (mz_int64)file_ofs)) && (MZ_FSEEK64(pZip->m_pState->m_pFile, (mz_int64)file_ofs, SEEK_SET))))
4050 return 0;
4051 return MZ_FWRITE(pBuf, 1, n, pZip->m_pState->m_pFile);
4052 }
4053
4054 mz_bool mz_zip_writer_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint64 size_to_reserve_at_beginning)
4055 {
4056 MZ_FILE *pFile;
4057 pZip->m_pWrite = mz_zip_file_write_func;
4058 pZip->m_pIO_opaque = pZip;
4059 if (!mz_zip_writer_init(pZip, size_to_reserve_at_beginning))
4060 return MZ_FALSE;
4061 if (NULL == (pFile = MZ_FOPEN(pFilename, "wb")))
4062 {
4063 mz_zip_writer_end(pZip);
4064 return MZ_FALSE;
4065 }
4066 pZip->m_pState->m_pFile = pFile;
4067 if (size_to_reserve_at_beginning)
4068 {
4069 mz_uint64 cur_ofs = 0; char buf[4096]; MZ_CLEAR_OBJ(buf);
4070 do
4071 {
4072 size_t n = (size_t)MZ_MIN(sizeof(buf), size_to_reserve_at_beginning);
4073 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_ofs, buf, n) != n)
4074 {
4075 mz_zip_writer_end(pZip);
4076 return MZ_FALSE;
4077 }
4078 cur_ofs += n; size_to_reserve_at_beginning -= n;
4079 } while (size_to_reserve_at_beginning);
4080 }
4081 return MZ_TRUE;
4082 }
4083 #endif // #ifndef MINIZ_NO_STDIO
4084
4085 mz_bool mz_zip_writer_init_from_reader(mz_zip_archive *pZip, const char *pFilename)
4086 {
4087 mz_zip_internal_state *pState;
4088 if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
4089 return MZ_FALSE;
4090 // No sense in trying to write to an archive that's already at the support max size
4091 if ((pZip->m_total_files == 0xFFFF) || ((pZip->m_archive_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_ZIP_LOCAL_DIR_HEADER_SIZE) > 0xFFFFFFFF))
4092 return MZ_FALSE;
4093
4094 pState = pZip->m_pState;
4095
4096 if (pState->m_pFile)
4097 {
4098 #ifdef MINIZ_NO_STDIO
4099 pFilename; return MZ_FALSE;
4100 #else
4101 // Archive is being read from stdio - try to reopen as writable.
4102 if (pZip->m_pIO_opaque != pZip)
4103 return MZ_FALSE;
4104 if (!pFilename)
4105 return MZ_FALSE;
4106 pZip->m_pWrite = mz_zip_file_write_func;
4107 if (NULL == (pState->m_pFile = MZ_FREOPEN(pFilename, "r+b", pState->m_pFile)))
4108 {
4109 // The mz_zip_archive is now in a bogus state because pState->m_pFile is NULL, so just close it.
4110 mz_zip_reader_end(pZip);
4111 return MZ_FALSE;
4112 }
4113 #endif // #ifdef MINIZ_NO_STDIO
4114 }
4115 else if (pState->m_pMem)
4116 {
4117 // Archive lives in a memory block. Assume it's from the heap that we can resize using the realloc callback.
4118 if (pZip->m_pIO_opaque != pZip)
4119 return MZ_FALSE;
4120 pState->m_mem_capacity = pState->m_mem_size;
4121 pZip->m_pWrite = mz_zip_heap_write_func;
4122 }
4123 // Archive is being read via a user provided read function - make sure the user has specified a write function too.
4124 else if (!pZip->m_pWrite)
4125 return MZ_FALSE;
4126
4127 // Start writing new files at the archive's current central directory location.
4128 pZip->m_archive_size = pZip->m_central_directory_file_ofs;
4129 pZip->m_zip_mode = MZ_ZIP_MODE_WRITING;
4130 pZip->m_central_directory_file_ofs = 0;
4131
4132 return MZ_TRUE;
4133 }
4134
4135 mz_bool mz_zip_writer_add_mem(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, mz_uint level_and_flags)
4136 {
4137 return mz_zip_writer_add_mem_ex(pZip, pArchive_name, pBuf, buf_size, NULL, 0, level_and_flags, 0, 0);
4138 }
4139
4140 typedef struct
4141 {
4142 mz_zip_archive *m_pZip;
4143 mz_uint64 m_cur_archive_file_ofs;
4144 mz_uint64 m_comp_size;
4145 } mz_zip_writer_add_state;
4146
4147 static mz_bool mz_zip_writer_add_put_buf_callback(const void* pBuf, int len, void *pUser)
4148 {
4149 mz_zip_writer_add_state *pState = (mz_zip_writer_add_state *)pUser;
4150 if ((int)pState->m_pZip->m_pWrite(pState->m_pZip->m_pIO_opaque, pState->m_cur_archive_file_ofs, pBuf, len) != len)
4151 return MZ_FALSE;
4152 pState->m_cur_archive_file_ofs += len;
4153 pState->m_comp_size += len;
4154 return MZ_TRUE;
4155 }
4156
4157 static mz_bool mz_zip_writer_create_local_dir_header(mz_zip_archive *pZip, mz_uint8 *pDst, mz_uint16 filename_size, mz_uint16 extra_size, mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date)
4158 {
4159 (void)pZip;
4160 memset(pDst, 0, MZ_ZIP_LOCAL_DIR_HEADER_SIZE);
4161 MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_SIG_OFS, MZ_ZIP_LOCAL_DIR_HEADER_SIG);
4162 MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_VERSION_NEEDED_OFS, method ? 20 : 0);
4163 MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_BIT_FLAG_OFS, bit_flags);
4164 MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_METHOD_OFS, method);
4165 MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_TIME_OFS, dos_time);
4166 MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_DATE_OFS, dos_date);
4167 MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_CRC32_OFS, uncomp_crc32);
4168 MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS, comp_size);
4169 MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS, uncomp_size);
4170 MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILENAME_LEN_OFS, filename_size);
4171 MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_EXTRA_LEN_OFS, extra_size);
4172 return MZ_TRUE;
4173 }
4174
4175 static mz_bool mz_zip_writer_create_central_dir_header(mz_zip_archive *pZip, mz_uint8 *pDst, mz_uint16 filename_size, mz_uint16 extra_size, mz_uint16 comment_size, mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date, mz_uint64 local_header_ofs, mz_uint32 ext_attributes)
4176 {
4177 (void)pZip;
4178 memset(pDst, 0, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE);
4179 MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_SIG_OFS, MZ_ZIP_CENTRAL_DIR_HEADER_SIG);
4180 MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_VERSION_NEEDED_OFS, method ? 20 : 0);
4181 MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_BIT_FLAG_OFS, bit_flags);
4182 MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_METHOD_OFS, method);
4183 MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_TIME_OFS, dos_time);
4184 MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_DATE_OFS, dos_date);
4185 MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_CRC32_OFS, uncomp_crc32);
4186 MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS, comp_size);
4187 MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS, uncomp_size);
4188 MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILENAME_LEN_OFS, filename_size);
4189 MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_EXTRA_LEN_OFS, extra_size);
4190 MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_COMMENT_LEN_OFS, comment_size);
4191 MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS, ext_attributes);
4192 MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_LOCAL_HEADER_OFS, local_header_ofs);
4193 return MZ_TRUE;
4194 }
4195
4196 static mz_bool mz_zip_writer_add_to_central_dir(mz_zip_archive *pZip, const char *pFilename, mz_uint16 filename_size, const void *pExtra, mz_uint16 extra_size, const void *pComment, mz_uint16 comment_size, mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date, mz_uint64 local_header_ofs, mz_uint32 ext_attributes)
4197 {
4198 mz_zip_internal_state *pState = pZip->m_pState;
4199 mz_uint32 central_dir_ofs = (mz_uint32)pState->m_central_dir.m_size;
4200 size_t orig_central_dir_size = pState->m_central_dir.m_size;
4201 mz_uint8 central_dir_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE];
4202
4203 // No zip64 support yet
4204 if ((local_header_ofs > 0xFFFFFFFF) || (((mz_uint64)pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size + extra_size + comment_size) > 0xFFFFFFFF))
4205 return MZ_FALSE;
4206
4207 if (!mz_zip_writer_create_central_dir_header(pZip, central_dir_header, filename_size, extra_size, comment_size, uncomp_size, comp_size, uncomp_crc32, method, bit_flags, dos_time, dos_date, local_header_ofs, ext_attributes))
4208 return MZ_FALSE;
4209
4210 if ((!mz_zip_array_push_back(pZip, &pState->m_central_dir, central_dir_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)) ||
4211 (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pFilename, filename_size)) ||
4212 (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pExtra, extra_size)) ||
4213 (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pComment, comment_size)) ||
4214 (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, &central_dir_ofs, 1)))
4215 {
4216 // Try to push the central directory array back into its original state.
4217 mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
4218 return MZ_FALSE;
4219 }
4220
4221 return MZ_TRUE;
4222 }
4223
4224 static mz_bool mz_zip_writer_validate_archive_name(const char *pArchive_name)
4225 {
4226 // Basic ZIP archive filename validity checks: Valid filenames cannot start with a forward slash, cannot contain a drive letter, and cannot use DOS-style backward slashes.
4227 if (*pArchive_name == '/')
4228 return MZ_FALSE;
4229 while (*pArchive_name)
4230 {
4231 if ((*pArchive_name == '\\') || (*pArchive_name == ':'))
4232 return MZ_FALSE;
4233 pArchive_name++;
4234 }
4235 return MZ_TRUE;
4236 }
4237
4238 static mz_uint mz_zip_writer_compute_padding_needed_for_file_alignment(mz_zip_archive *pZip)
4239 {
4240 mz_uint32 n;
4241 if (!pZip->m_file_offset_alignment)
4242 return 0;
4243 n = (mz_uint32)(pZip->m_archive_size & (pZip->m_file_offset_alignment - 1));
4244 return (pZip->m_file_offset_alignment - n) & (pZip->m_file_offset_alignment - 1);
4245 }
4246
4247 static mz_bool mz_zip_writer_write_zeros(mz_zip_archive *pZip, mz_uint64 cur_file_ofs, mz_uint32 n)
4248 {
4249 char buf[4096];
4250 memset(buf, 0, MZ_MIN(sizeof(buf), n));
4251 while (n)
4252 {
4253 mz_uint32 s = MZ_MIN(sizeof(buf), n);
4254 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_file_ofs, buf, s) != s)
4255 return MZ_FALSE;
4256 cur_file_ofs += s; n -= s;
4257 }
4258 return MZ_TRUE;
4259 }
4260
4261 mz_bool mz_zip_writer_add_mem_ex(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, mz_uint64 uncomp_size, mz_uint32 uncomp_crc32)
4262 {
4263 mz_uint16 method = 0, dos_time = 0, dos_date = 0;
4264 mz_uint level, ext_attributes = 0, num_alignment_padding_bytes;
4265 mz_uint64 local_dir_header_ofs = pZip->m_archive_size, cur_archive_file_ofs = pZip->m_archive_size, comp_size = 0;
4266 size_t archive_name_size;
4267 mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE];
4268 tdefl_compressor *pComp = NULL;
4269 mz_bool store_data_uncompressed;
4270 mz_zip_internal_state *pState;
4271
4272 if ((int)level_and_flags < 0)
4273 level_and_flags = MZ_DEFAULT_LEVEL;
4274 level = level_and_flags & 0xF;
4275 store_data_uncompressed = ((!level) || (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA));
4276
4277 if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || ((buf_size) && (!pBuf)) || (!pArchive_name) || ((comment_size) && (!pComment)) || (pZip->m_total_files == 0xFFFF) || (level > MZ_UBER_COMPRESSION))
4278 return MZ_FALSE;
4279
4280 pState = pZip->m_pState;
4281
4282 if ((!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (uncomp_size))
4283 return MZ_FALSE;
4284 // No zip64 support yet
4285 if ((buf_size > 0xFFFFFFFF) || (uncomp_size > 0xFFFFFFFF))
4286 return MZ_FALSE;
4287 if (!mz_zip_writer_validate_archive_name(pArchive_name))
4288 return MZ_FALSE;
4289
4290 #ifndef MINIZ_NO_TIME
4291 {
4292 time_t cur_time; time(&cur_time);
4293 mz_zip_time_to_dos_time(cur_time, &dos_time, &dos_date);
4294 }
4295 #endif // #ifndef MINIZ_NO_TIME
4296
4297 archive_name_size = strlen(pArchive_name);
4298 if (archive_name_size > 0xFFFF)
4299 return MZ_FALSE;
4300
4301 num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
4302
4303 // no zip64 support yet
4304 if ((pZip->m_total_files == 0xFFFF) || ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + comment_size + archive_name_size) > 0xFFFFFFFF))
4305 return MZ_FALSE;
4306
4307 if ((archive_name_size) && (pArchive_name[archive_name_size - 1] == '/'))
4308 {
4309 // Set DOS Subdirectory attribute bit.
4310 ext_attributes |= 0x10;
4311 // Subdirectories cannot contain data.
4312 if ((buf_size) || (uncomp_size))
4313 return MZ_FALSE;
4314 }
4315
4316 // Try to do any allocations before writing to the archive, so if an allocation fails the file remains unmodified. (A good idea if we're doing an in-place modification.)
4317 if ((!mz_zip_array_ensure_room(pZip, &pState->m_central_dir, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + comment_size)) || (!mz_zip_array_ensure_room(pZip, &pState->m_central_dir_offsets, 1)))
4318 return MZ_FALSE;
4319
4320 if ((!store_data_uncompressed) && (buf_size))
4321 {
4322 if (NULL == (pComp = (tdefl_compressor *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor))))
4323 return MZ_FALSE;
4324 }
4325
4326 if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs, num_alignment_padding_bytes + sizeof(local_dir_header)))
4327 {
4328 pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
4329 return MZ_FALSE;
4330 }
4331 local_dir_header_ofs += num_alignment_padding_bytes;
4332 if (pZip->m_file_offset_alignment) { MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0); }
4333 cur_archive_file_ofs += num_alignment_padding_bytes + sizeof(local_dir_header);
4334
4335 MZ_CLEAR_OBJ(local_dir_header);
4336 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size)
4337 {
4338 pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
4339 return MZ_FALSE;
4340 }
4341 cur_archive_file_ofs += archive_name_size;
4342
4343 if (!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
4344 {
4345 uncomp_crc32 = (mz_uint32)mz_crc32(MZ_CRC32_INIT, (const mz_uint8*)pBuf, buf_size);
4346 uncomp_size = buf_size;
4347 if (uncomp_size <= 3)
4348 {
4349 level = 0;
4350 store_data_uncompressed = MZ_TRUE;
4351 }
4352 }
4353
4354 if (store_data_uncompressed)
4355 {
4356 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pBuf, buf_size) != buf_size)
4357 {
4358 pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
4359 return MZ_FALSE;
4360 }
4361
4362 cur_archive_file_ofs += buf_size;
4363 comp_size = buf_size;
4364
4365 if (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)
4366 method = MZ_DEFLATED;
4367 }
4368 else if (buf_size)
4369 {
4370 mz_zip_writer_add_state state;
4371
4372 state.m_pZip = pZip;
4373 state.m_cur_archive_file_ofs = cur_archive_file_ofs;
4374 state.m_comp_size = 0;
4375
4376 if ((tdefl_init(pComp, mz_zip_writer_add_put_buf_callback, &state, tdefl_create_comp_flags_from_zip_params(level, -15, MZ_DEFAULT_STRATEGY)) != TDEFL_STATUS_OKAY) ||
4377 (tdefl_compress_buffer(pComp, pBuf, buf_size, TDEFL_FINISH) != TDEFL_STATUS_DONE))
4378 {
4379 pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
4380 return MZ_FALSE;
4381 }
4382
4383 comp_size = state.m_comp_size;
4384 cur_archive_file_ofs = state.m_cur_archive_file_ofs;
4385
4386 method = MZ_DEFLATED;
4387 }
4388
4389 pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
4390 pComp = NULL;
4391
4392 // no zip64 support yet
4393 if ((comp_size > 0xFFFFFFFF) || (cur_archive_file_ofs > 0xFFFFFFFF))
4394 return MZ_FALSE;
4395
4396 if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, 0, uncomp_size, comp_size, uncomp_crc32, method, 0, dos_time, dos_date))
4397 return MZ_FALSE;
4398
4399 if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header))
4400 return MZ_FALSE;
4401
4402 if (!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, NULL, 0, pComment, comment_size, uncomp_size, comp_size, uncomp_crc32, method, 0, dos_time, dos_date, local_dir_header_ofs, ext_attributes))
4403 return MZ_FALSE;
4404
4405 pZip->m_total_files++;
4406 pZip->m_archive_size = cur_archive_file_ofs;
4407
4408 return MZ_TRUE;
4409 }
4410
4411 #ifndef MINIZ_NO_STDIO
4412 mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name, const char *pSrc_filename, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags)
4413 {
4414 mz_uint uncomp_crc32 = MZ_CRC32_INIT, level, num_alignment_padding_bytes;
4415 mz_uint16 method = 0, dos_time = 0, dos_date = 0, ext_attributes = 0;
4416 mz_uint64 local_dir_header_ofs = pZip->m_archive_size, cur_archive_file_ofs = pZip->m_archive_size, uncomp_size = 0, comp_size = 0;
4417 size_t archive_name_size;
4418 mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE];
4419 MZ_FILE *pSrc_file = NULL;
4420
4421 if ((int)level_and_flags < 0)
4422 level_and_flags = MZ_DEFAULT_LEVEL;
4423 level = level_and_flags & 0xF;
4424
4425 if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || (!pArchive_name) || ((comment_size) && (!pComment)) || (level > MZ_UBER_COMPRESSION))
4426 return MZ_FALSE;
4427 if (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)
4428 return MZ_FALSE;
4429 if (!mz_zip_writer_validate_archive_name(pArchive_name))
4430 return MZ_FALSE;
4431
4432 archive_name_size = strlen(pArchive_name);
4433 if (archive_name_size > 0xFFFF)
4434 return MZ_FALSE;
4435
4436 num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
4437
4438 // no zip64 support yet
4439 if ((pZip->m_total_files == 0xFFFF) || ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + comment_size + archive_name_size) > 0xFFFFFFFF))
4440 return MZ_FALSE;
4441
4442 if (!mz_zip_get_file_modified_time(pSrc_filename, &dos_time, &dos_date))
4443 return MZ_FALSE;
4444
4445 pSrc_file = MZ_FOPEN(pSrc_filename, "rb");
4446 if (!pSrc_file)
4447 return MZ_FALSE;
4448 MZ_FSEEK64(pSrc_file, 0, SEEK_END);
4449 uncomp_size = MZ_FTELL64(pSrc_file);
4450 MZ_FSEEK64(pSrc_file, 0, SEEK_SET);
4451
4452 if (uncomp_size > 0xFFFFFFFF)
4453 {
4454 // No zip64 support yet
4455 MZ_FCLOSE(pSrc_file);
4456 return MZ_FALSE;
4457 }
4458 if (uncomp_size <= 3)
4459 level = 0;
4460
4461 if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs, num_alignment_padding_bytes + sizeof(local_dir_header)))
4462 {
4463 MZ_FCLOSE(pSrc_file);
4464 return MZ_FALSE;
4465 }
4466 local_dir_header_ofs += num_alignment_padding_bytes;
4467 if (pZip->m_file_offset_alignment) { MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0); }
4468 cur_archive_file_ofs += num_alignment_padding_bytes + sizeof(local_dir_header);
4469
4470 MZ_CLEAR_OBJ(local_dir_header);
4471 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size)
4472 {
4473 MZ_FCLOSE(pSrc_file);
4474 return MZ_FALSE;
4475 }
4476 cur_archive_file_ofs += archive_name_size;
4477
4478 if (uncomp_size)
4479 {
4480 mz_uint64 uncomp_remaining = uncomp_size;
4481 void *pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, MZ_ZIP_MAX_IO_BUF_SIZE);
4482 if (!pRead_buf)
4483 {
4484 MZ_FCLOSE(pSrc_file);
4485 return MZ_FALSE;
4486 }
4487
4488 if (!level)
4489 {
4490 while (uncomp_remaining)
4491 {
4492 mz_uint n = (mz_uint)MZ_MIN(MZ_ZIP_MAX_IO_BUF_SIZE, uncomp_remaining);
4493 if ((MZ_FREAD(pRead_buf, 1, n, pSrc_file) != n) || (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pRead_buf, n) != n))
4494 {
4495 pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
4496 MZ_FCLOSE(pSrc_file);
4497 return MZ_FALSE;
4498 }
4499 uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, n);
4500 uncomp_remaining -= n;
4501 cur_archive_file_ofs += n;
4502 }
4503 comp_size = uncomp_size;
4504 }
4505 else
4506 {
4507 mz_bool result = MZ_FALSE;
4508 mz_zip_writer_add_state state;
4509 tdefl_compressor *pComp = (tdefl_compressor *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor));
4510 if (!pComp)
4511 {
4512 pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
4513 MZ_FCLOSE(pSrc_file);
4514 return MZ_FALSE;
4515 }
4516
4517 state.m_pZip = pZip;
4518 state.m_cur_archive_file_ofs = cur_archive_file_ofs;
4519 state.m_comp_size = 0;
4520
4521 if (tdefl_init(pComp, mz_zip_writer_add_put_buf_callback, &state, tdefl_create_comp_flags_from_zip_params(level, -15, MZ_DEFAULT_STRATEGY)) != TDEFL_STATUS_OKAY)
4522 {
4523 pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
4524 pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
4525 MZ_FCLOSE(pSrc_file);
4526 return MZ_FALSE;
4527 }
4528
4529 for ( ; ; )
4530 {
4531 size_t in_buf_size = (mz_uint32)MZ_MIN(uncomp_remaining, MZ_ZIP_MAX_IO_BUF_SIZE);
4532 tdefl_status status;
4533
4534 if (MZ_FREAD(pRead_buf, 1, in_buf_size, pSrc_file) != in_buf_size)
4535 break;
4536
4537 uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, in_buf_size);
4538 uncomp_remaining -= in_buf_size;
4539
4540 status = tdefl_compress_buffer(pComp, pRead_buf, in_buf_size, uncomp_remaining ? TDEFL_NO_FLUSH : TDEFL_FINISH);
4541 if (status == TDEFL_STATUS_DONE)
4542 {
4543 result = MZ_TRUE;
4544 break;
4545 }
4546 else if (status != TDEFL_STATUS_OKAY)
4547 break;
4548 }
4549
4550 pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
4551
4552 if (!result)
4553 {
4554 pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
4555 MZ_FCLOSE(pSrc_file);
4556 return MZ_FALSE;
4557 }
4558
4559 comp_size = state.m_comp_size;
4560 cur_archive_file_ofs = state.m_cur_archive_file_ofs;
4561
4562 method = MZ_DEFLATED;
4563 }
4564
4565 pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
4566 }
4567
4568 MZ_FCLOSE(pSrc_file); pSrc_file = NULL;
4569
4570 // no zip64 support yet
4571 if ((comp_size > 0xFFFFFFFF) || (cur_archive_file_ofs > 0xFFFFFFFF))
4572 return MZ_FALSE;
4573
4574 if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, 0, uncomp_size, comp_size, uncomp_crc32, method, 0, dos_time, dos_date))
4575 return MZ_FALSE;
4576
4577 if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header))
4578 return MZ_FALSE;
4579
4580 if (!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, NULL, 0, pComment, comment_size, uncomp_size, comp_size, uncomp_crc32, method, 0, dos_time, dos_date, local_dir_header_ofs, ext_attributes))
4581 return MZ_FALSE;
4582
4583 pZip->m_total_files++;
4584 pZip->m_archive_size = cur_archive_file_ofs;
4585
4586 return MZ_TRUE;
4587 }
4588 #endif // #ifndef MINIZ_NO_STDIO
4589
4590 mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive *pSource_zip, mz_uint file_index)
4591 {
4592 mz_uint n, bit_flags, num_alignment_padding_bytes;
4593 mz_uint64 comp_bytes_remaining, local_dir_header_ofs;
4594 mz_uint64 cur_src_file_ofs, cur_dst_file_ofs;
4595 mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)]; mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
4596 mz_uint8 central_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE];
4597 size_t orig_central_dir_size;
4598 mz_zip_internal_state *pState;
4599 void *pBuf; const mz_uint8 *pSrc_central_header;
4600
4601 if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING))
4602 return MZ_FALSE;
4603 if (NULL == (pSrc_central_header = mz_zip_reader_get_cdh(pSource_zip, file_index)))
4604 return MZ_FALSE;
4605 pState = pZip->m_pState;
4606
4607 num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
4608
4609 // no zip64 support yet
4610 if ((pZip->m_total_files == 0xFFFF) || ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) > 0xFFFFFFFF))
4611 return MZ_FALSE;
4612
4613 cur_src_file_ofs = MZ_READ_LE32(pSrc_central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS);
4614 cur_dst_file_ofs = pZip->m_archive_size;
4615
4616 if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
4617 return MZ_FALSE;
4618 if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
4619 return MZ_FALSE;
4620 cur_src_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE;
4621
4622 if (!mz_zip_writer_write_zeros(pZip, cur_dst_file_ofs, num_alignment_padding_bytes))
4623 return MZ_FALSE;
4624 cur_dst_file_ofs += num_alignment_padding_bytes;
4625 local_dir_header_ofs = cur_dst_file_ofs;
4626 if (pZip->m_file_offset_alignment) { MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0); }
4627
4628 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
4629 return MZ_FALSE;
4630 cur_dst_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE;
4631
4632 n = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
4633 comp_bytes_remaining = n + MZ_READ_LE32(pSrc_central_header + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
4634
4635 if (NULL == (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)MZ_MAX(sizeof(mz_uint32) * 4, MZ_MIN(MZ_ZIP_MAX_IO_BUF_SIZE, comp_bytes_remaining)))))
4636 return MZ_FALSE;
4637
4638 while (comp_bytes_remaining)
4639 {
4640 n = (mz_uint)MZ_MIN(MZ_ZIP_MAX_IO_BUF_SIZE, comp_bytes_remaining);
4641 if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, n) != n)
4642 {
4643 pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
4644 return MZ_FALSE;
4645 }
4646 cur_src_file_ofs += n;
4647
4648 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n)
4649 {
4650 pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
4651 return MZ_FALSE;
4652 }
4653 cur_dst_file_ofs += n;
4654
4655 comp_bytes_remaining -= n;
4656 }
4657
4658 bit_flags = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_BIT_FLAG_OFS);
4659 if (bit_flags & 8)
4660 {
4661 // Copy data descriptor
4662 if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, sizeof(mz_uint32) * 4) != sizeof(mz_uint32) * 4)
4663 {
4664 pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
4665 return MZ_FALSE;
4666 }
4667
4668 n = sizeof(mz_uint32) * ((MZ_READ_LE32(pBuf) == 0x08074b50) ? 4 : 3);
4669 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n)
4670 {
4671 pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
4672 return MZ_FALSE;
4673 }
4674
4675 cur_src_file_ofs += n;
4676 cur_dst_file_ofs += n;
4677 }
4678 pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
4679
4680 // no zip64 support yet
4681 if (cur_dst_file_ofs > 0xFFFFFFFF)
4682 return MZ_FALSE;
4683
4684 orig_central_dir_size = pState->m_central_dir.m_size;
4685
4686 memcpy(central_header, pSrc_central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE);
4687 MZ_WRITE_LE32(central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS, local_dir_header_ofs);
4688 if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE))
4689 return MZ_FALSE;
4690
4691 n = MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_EXTRA_LEN_OFS) + MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_COMMENT_LEN_OFS);
4692 if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n))
4693 {
4694 mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
4695 return MZ_FALSE;
4696 }
4697
4698 if (pState->m_central_dir.m_size > 0xFFFFFFFF)
4699 return MZ_FALSE;
4700 n = (mz_uint32)orig_central_dir_size;
4701 if (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, &n, 1))
4702 {
4703 mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
4704 return MZ_FALSE;
4705 }
4706
4707 pZip->m_total_files++;
4708 pZip->m_archive_size = cur_dst_file_ofs;
4709
4710 return MZ_TRUE;
4711 }
4712
4713 mz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip)
4714 {
4715 mz_zip_internal_state *pState;
4716 mz_uint64 central_dir_ofs, central_dir_size;
4717 mz_uint8 hdr[MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE];
4718
4719 if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING))
4720 return MZ_FALSE;
4721
4722 pState = pZip->m_pState;
4723
4724 // no zip64 support yet
4725 if ((pZip->m_total_files > 0xFFFF) || ((pZip->m_archive_size + pState->m_central_dir.m_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) > 0xFFFFFFFF))
4726 return MZ_FALSE;
4727
4728 central_dir_ofs = 0;
4729 central_dir_size = 0;
4730 if (pZip->m_total_files)
4731 {
4732 // Write central directory
4733 central_dir_ofs = pZip->m_archive_size;
4734 central_dir_size = pState->m_central_dir.m_size;
4735 pZip->m_central_directory_file_ofs = central_dir_ofs;
4736 if (pZip->m_pWrite(pZip->m_pIO_opaque, central_dir_ofs, pState->m_central_dir.m_p, (size_t)central_dir_size) != central_dir_size)
4737 return MZ_FALSE;
4738 pZip->m_archive_size += central_dir_size;
4739 }
4740
4741 // Write end of central directory record
4742 MZ_CLEAR_OBJ(hdr);
4743 MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_SIG_OFS, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG);
4744 MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS, pZip->m_total_files);
4745 MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS, pZip->m_total_files);
4746 MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_SIZE_OFS, central_dir_size);
4747 MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_OFS_OFS, central_dir_ofs);
4748
4749 if (pZip->m_pWrite(pZip->m_pIO_opaque, pZip->m_archive_size, hdr, sizeof(hdr)) != sizeof(hdr))
4750 return MZ_FALSE;
4751 #ifndef MINIZ_NO_STDIO
4752 if ((pState->m_pFile) && (MZ_FFLUSH(pState->m_pFile) == EOF))
4753 return MZ_FALSE;
4754 #endif // #ifndef MINIZ_NO_STDIO
4755
4756 pZip->m_archive_size += sizeof(hdr);
4757
4758 pZip->m_zip_mode = MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED;
4759 return MZ_TRUE;
4760 }
4761
4762 mz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive *pZip, void **pBuf, size_t *pSize)
4763 {
4764 if ((!pZip) || (!pZip->m_pState) || (!pBuf) || (!pSize))
4765 return MZ_FALSE;
4766 if (pZip->m_pWrite != mz_zip_heap_write_func)
4767 return MZ_FALSE;
4768 if (!mz_zip_writer_finalize_archive(pZip))
4769 return MZ_FALSE;
4770
4771 *pBuf = pZip->m_pState->m_pMem;
4772 *pSize = pZip->m_pState->m_mem_size;
4773 pZip->m_pState->m_pMem = NULL;
4774 pZip->m_pState->m_mem_size = pZip->m_pState->m_mem_capacity = 0;
4775 return MZ_TRUE;
4776 }
4777
4778 mz_bool mz_zip_writer_end(mz_zip_archive *pZip)
4779 {
4780 mz_zip_internal_state *pState;
4781 mz_bool status = MZ_TRUE;
4782 if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || ((pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) && (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED)))
4783 return MZ_FALSE;
4784
4785 pState = pZip->m_pState;
4786 pZip->m_pState = NULL;
4787 mz_zip_array_clear(pZip, &pState->m_central_dir);
4788 mz_zip_array_clear(pZip, &pState->m_central_dir_offsets);
4789 mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets);
4790
4791 #ifndef MINIZ_NO_STDIO
4792 if (pState->m_pFile)
4793 {
4794 MZ_FCLOSE(pState->m_pFile);
4795 pState->m_pFile = NULL;
4796 }
4797 #endif // #ifndef MINIZ_NO_STDIO
4798
4799 if ((pZip->m_pWrite == mz_zip_heap_write_func) && (pState->m_pMem))
4800 {
4801 pZip->m_pFree(pZip->m_pAlloc_opaque, pState->m_pMem);
4802 pState->m_pMem = NULL;
4803 }
4804
4805 pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
4806 pZip->m_zip_mode = MZ_ZIP_MODE_INVALID;
4807 return status;
4808 }
4809
4810 #ifndef MINIZ_NO_STDIO
4811 mz_bool mz_zip_add_mem_to_archive_file_in_place(const char *pZip_filename, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags)
4812 {
4813 mz_bool status, created_new_archive = MZ_FALSE;
4814 mz_zip_archive zip_archive;
4815 struct MZ_FILE_STAT_STRUCT file_stat;
4816 MZ_CLEAR_OBJ(zip_archive);
4817 if ((int)level_and_flags < 0)
4818 level_and_flags = MZ_DEFAULT_LEVEL;
4819 if ((!pZip_filename) || (!pArchive_name) || ((buf_size) && (!pBuf)) || ((comment_size) && (!pComment)) || ((level_and_flags & 0xF) > MZ_UBER_COMPRESSION))
4820 return MZ_FALSE;
4821 if (!mz_zip_writer_validate_archive_name(pArchive_name))
4822 return MZ_FALSE;
4823 if (MZ_FILE_STAT(pZip_filename, &file_stat) != 0)
4824 {
4825 // Create a new archive.
4826 if (!mz_zip_writer_init_file(&zip_archive, pZip_filename, 0))
4827 return MZ_FALSE;
4828 created_new_archive = MZ_TRUE;
4829 }
4830 else
4831 {
4832 // Append to an existing archive.
4833 if (!mz_zip_reader_init_file(&zip_archive, pZip_filename, level_and_flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY))
4834 return MZ_FALSE;
4835 if (!mz_zip_writer_init_from_reader(&zip_archive, pZip_filename))
4836 {
4837 mz_zip_reader_end(&zip_archive);
4838 return MZ_FALSE;
4839 }
4840 }
4841 status = mz_zip_writer_add_mem_ex(&zip_archive, pArchive_name, pBuf, buf_size, pComment, comment_size, level_and_flags, 0, 0);
4842 // Always finalize, even if adding failed for some reason, so we have a valid central directory. (This may not always succeed, but we can try.)
4843 if (!mz_zip_writer_finalize_archive(&zip_archive))
4844 status = MZ_FALSE;
4845 if (!mz_zip_writer_end(&zip_archive))
4846 status = MZ_FALSE;
4847 if ((!status) && (created_new_archive))
4848 {
4849 // It's a new archive and something went wrong, so just delete it.
4850 int ignoredStatus = MZ_DELETE_FILE(pZip_filename);
4851 (void)ignoredStatus;
4852 }
4853 return status;
4854 }
4855
4856 void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const char *pArchive_name, size_t *pSize, mz_uint flags)
4857 {
4858 int file_index;
4859 mz_zip_archive zip_archive;
4860 void *p = NULL;
4861
4862 if (pSize)
4863 *pSize = 0;
4864
4865 if ((!pZip_filename) || (!pArchive_name))
4866 return NULL;
4867
4868 MZ_CLEAR_OBJ(zip_archive);
4869 if (!mz_zip_reader_init_file(&zip_archive, pZip_filename, flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY))
4870 return NULL;
4871
4872 if ((file_index = mz_zip_reader_locate_file(&zip_archive, pArchive_name, NULL, flags)) >= 0)
4873 p = mz_zip_reader_extract_to_heap(&zip_archive, file_index, pSize, flags);
4874
4875 mz_zip_reader_end(&zip_archive);
4876 return p;
4877 }
4878
4879 #endif // #ifndef MINIZ_NO_STDIO
4880
4881 #endif // #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
4882
4883 #endif // #ifndef MINIZ_NO_ARCHIVE_APIS
4884
4885 #ifdef __cplusplus
4886 }
4887 #endif
4888
4889 #endif // MINIZ_HEADER_FILE_ONLY
4890
4891 /*
4892 This is free and unencumbered software released into the public domain.
4893
4894 Anyone is free to copy, modify, publish, use, compile, sell, or
4895 distribute this software, either in source code form or as a compiled
4896 binary, for any purpose, commercial or non-commercial, and by any
4897 means.
4898
4899 In jurisdictions that recognize copyright laws, the author or authors
4900 of this software dedicate any and all copyright interest in the
4901 software to the public domain. We make this dedication for the benefit
4902 of the public at large and to the detriment of our heirs and
4903 successors. We intend this dedication to be an overt act of
4904 relinquishment in perpetuity of all present and future rights to this
4905 software under copyright law.
4906
4907 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
4908 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
4909 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
4910 IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
4911 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
4912 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
4913 OTHER DEALINGS IN THE SOFTWARE.
4914
4915 For more information, please refer to <http://unlicense.org/>
4916 */
--- a/src/miniz.c
+++ b/src/miniz.c
@@ -1,4916 +0,0 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
D src/pikchr.c
-77
--- a/src/pikchr.c
+++ b/src/pikchr.c
@@ -1,77 +0,0 @@
1
-v<0.0 ? -v : v; generated by Lemon from input grammar
2
-** sourcedo good and not e il.
3
-** May you find forgiveness for yourself and forgive others.
4
-** May you share freely, never taking more than you give.
5
-**
6
-*************************************************************************
7
-** Driver template for the LEMON parser generator.
8
-**
9
-** The "lemon" program processes an LALR(1) input grammar file, then uses
10
-** this template to construct a parser. The "lemon" program inserts text
11
-** at each "%%" line. Also, any "P-a-r-s-e" identifier prefix (without the
12
-** interstitial "-" characters) contained in this template is changed into
13
-** the value of the %name directive from the grammar. Otherwise, the content
14
-** of this template is copied straight through into the generate /* This file is automatically genenation of all %include directives from the
15
-** input grammar file:
16
-*/
17
-/************ Begin %include sections from the grammar ************************/
18
-#line 1 "VERSION052f07296e76ab2312caf2a4bf6237e574b3e533c7a36ee8f34db833baa3efb4E "20250319161943"
19
-VERSION "[052f07296e]E "202503191619
20
-6E "20250319161943"
21
-NUMERIC_DATE 20250305tically generated by Lemon 20250305tically generated by Lemon from /* This file 0 */ 59, 60, 64, 63, 62, 61, 445, 445, 376, 445,
22
- /* 540 */ 445, 42, 445, 394, 473, 391, 59, 60, 445, 436,
23
- /* 550 */ 437, 438, 439, 49, 376, 445, 74, 42, 148, 445,
24
- /* 560 */ 88, 445, 445, 445, 490, 113, 120, 161, 119, 445,
25
- /* 570 */ 120, 161, 119, 132, 130, 394, 143, 475, 59, 60,
26
- /* 580 */ 445, 473, 64, 63, 62, 61, 376, 106, 149, 42,
27
- /* 590 */ 445, 445, 152, 445, 375, 391, 117, 393, 155, 154,
28
- /* 600 */ 153, 394, 144, 52, 59, 60, 445, 445, 445, 106,
29
- /* 610 */ 445, 445, 376, 445, 445, 42, 375, 445, 117, 393,
30
- /* 620 */ 155, 154, 153, 445, 445, 106, 64, 63, 62, 61,
31
- /* 630 */ 445, 445, 375, 445, 117, 393, 155, 154, 153, 394,
32
- /* 640 */ 445, 445, 59, 60, 88, 445, 445, 53, 445, 445,
33
- /* 650 */ 376, 445, 445, 42, 120, 161, 119, 106, 445, 445,
34
- /* 660 */ 445, 110, 110, 445, 375, 445, 117, 393, 155, 154,
35
- /* 670 */ 153, 394, 445, 445, 59, 60, 152, 107, 445, 445,
36
- /* 680 */ 445, 445, 102, 106, 445, 42, 445, 120, 161, 119,
37
- /* 690 */ 375, 451, 117, 393, 155, 154, 153, 394, 445, 445,
38
- /* 700 */ 59, 60, 64, 63, 62, 61, 445, 445, 376, 152,
39
- /* 710 */ 445, 40, 445, 394, 445, 396, 59, 60, 445, 445,
40
- /* 720 */ 445, 106, 445, 445, 376, 88, 445, 41, 375, 445,
41
- /* 730 */ 117, 393, 155, 154, 153, 120, 161, 119, 74, 445,
42
- /* 740 */ 0.5*(f.x+t.x);
43
- m.y = 0.5);
44
-);
45
-0 "pikchr.c"
46
-/* This file is automatically generated by Lemon from input grammar
47
-** source file "pikchr.y".
48
-*/
49
-/*
50
-** 2000-05-29
51
-**
52
-** The author disclaims copyright to this source code. In place of
53
-** a legal notice, here is a blessing:
54
-**
55
-** May you do good and not evil.
56
-** May you find forgiveness for yourself and forgive others.
57
-** May you share freely, never taking more than you give.
58
-**
59
-*************************************************************************
60
-** Driver template for the LEMON parser generator.
61
-**
62
-** The "lemon" program processes an LALR(1) input grammar file, then uses
63
-** this template to construct a parser. The "lemon" program inserts text
64
-** at each "%%" line. Also, any "P-a-r-s-e" identifier prefix (without the
65
-** interstitial "-" characters) contained in this template is changed into
66
-** the value of the %name directive from the grammar. Otherwise, the content
67
-** of this template is copied straight through into the generate parser
68
-** source file.
69
-**
70
-** The following is the concatenation of all %include directives from the
71
-** input grammar file:
72
-*/
73
-/************ Begin %include sections from the grammar ************************/
74
-#line 1 "VERSION052f07296e76ab2312caf2a4bf6237e574b3e533c7a36ee8f34db833baa3efb4E "20250319161943"
75
-VERSION "[052f07296e]E "20250319161943"
76
-DATE "2025-03-05 10:54:1605105416E "20250319161943"
77
-NUMERIC_DATE 20250305tically generated by Lemon from /* This file 0 */ 59, 60, 64, 63, 62, 61, 4erated by Lemo
--- a/src/pikchr.c
+++ b/src/pikchr.c
@@ -1,77 +0,0 @@
1 v<0.0 ? -v : v; generated by Lemon from input grammar
2 ** sourcedo good and not e il.
3 ** May you find forgiveness for yourself and forgive others.
4 ** May you share freely, never taking more than you give.
5 **
6 *************************************************************************
7 ** Driver template for the LEMON parser generator.
8 **
9 ** The "lemon" program processes an LALR(1) input grammar file, then uses
10 ** this template to construct a parser. The "lemon" program inserts text
11 ** at each "%%" line. Also, any "P-a-r-s-e" identifier prefix (without the
12 ** interstitial "-" characters) contained in this template is changed into
13 ** the value of the %name directive from the grammar. Otherwise, the content
14 ** of this template is copied straight through into the generate /* This file is automatically genenation of all %include directives from the
15 ** input grammar file:
16 */
17 /************ Begin %include sections from the grammar ************************/
18 #line 1 "VERSION052f07296e76ab2312caf2a4bf6237e574b3e533c7a36ee8f34db833baa3efb4E "20250319161943"
19 VERSION "[052f07296e]E "202503191619
20 6E "20250319161943"
21 NUMERIC_DATE 20250305tically generated by Lemon 20250305tically generated by Lemon from /* This file 0 */ 59, 60, 64, 63, 62, 61, 445, 445, 376, 445,
22 /* 540 */ 445, 42, 445, 394, 473, 391, 59, 60, 445, 436,
23 /* 550 */ 437, 438, 439, 49, 376, 445, 74, 42, 148, 445,
24 /* 560 */ 88, 445, 445, 445, 490, 113, 120, 161, 119, 445,
25 /* 570 */ 120, 161, 119, 132, 130, 394, 143, 475, 59, 60,
26 /* 580 */ 445, 473, 64, 63, 62, 61, 376, 106, 149, 42,
27 /* 590 */ 445, 445, 152, 445, 375, 391, 117, 393, 155, 154,
28 /* 600 */ 153, 394, 144, 52, 59, 60, 445, 445, 445, 106,
29 /* 610 */ 445, 445, 376, 445, 445, 42, 375, 445, 117, 393,
30 /* 620 */ 155, 154, 153, 445, 445, 106, 64, 63, 62, 61,
31 /* 630 */ 445, 445, 375, 445, 117, 393, 155, 154, 153, 394,
32 /* 640 */ 445, 445, 59, 60, 88, 445, 445, 53, 445, 445,
33 /* 650 */ 376, 445, 445, 42, 120, 161, 119, 106, 445, 445,
34 /* 660 */ 445, 110, 110, 445, 375, 445, 117, 393, 155, 154,
35 /* 670 */ 153, 394, 445, 445, 59, 60, 152, 107, 445, 445,
36 /* 680 */ 445, 445, 102, 106, 445, 42, 445, 120, 161, 119,
37 /* 690 */ 375, 451, 117, 393, 155, 154, 153, 394, 445, 445,
38 /* 700 */ 59, 60, 64, 63, 62, 61, 445, 445, 376, 152,
39 /* 710 */ 445, 40, 445, 394, 445, 396, 59, 60, 445, 445,
40 /* 720 */ 445, 106, 445, 445, 376, 88, 445, 41, 375, 445,
41 /* 730 */ 117, 393, 155, 154, 153, 120, 161, 119, 74, 445,
42 /* 740 */ 0.5*(f.x+t.x);
43 m.y = 0.5);
44 );
45 0 "pikchr.c"
46 /* This file is automatically generated by Lemon from input grammar
47 ** source file "pikchr.y".
48 */
49 /*
50 ** 2000-05-29
51 **
52 ** The author disclaims copyright to this source code. In place of
53 ** a legal notice, here is a blessing:
54 **
55 ** May you do good and not evil.
56 ** May you find forgiveness for yourself and forgive others.
57 ** May you share freely, never taking more than you give.
58 **
59 *************************************************************************
60 ** Driver template for the LEMON parser generator.
61 **
62 ** The "lemon" program processes an LALR(1) input grammar file, then uses
63 ** this template to construct a parser. The "lemon" program inserts text
64 ** at each "%%" line. Also, any "P-a-r-s-e" identifier prefix (without the
65 ** interstitial "-" characters) contained in this template is changed into
66 ** the value of the %name directive from the grammar. Otherwise, the content
67 ** of this template is copied straight through into the generate parser
68 ** source file.
69 **
70 ** The following is the concatenation of all %include directives from the
71 ** input grammar file:
72 */
73 /************ Begin %include sections from the grammar ************************/
74 #line 1 "VERSION052f07296e76ab2312caf2a4bf6237e574b3e533c7a36ee8f34db833baa3efb4E "20250319161943"
75 VERSION "[052f07296e]E "20250319161943"
76 DATE "2025-03-05 10:54:1605105416E "20250319161943"
77 NUMERIC_DATE 20250305tically generated by Lemon from /* This file 0 */ 59, 60, 64, 63, 62, 61, 4erated by Lemo
--- a/src/pikchr.c
+++ b/src/pikchr.c
@@ -1,77 +0,0 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
D src/shell.c
-4
--- a/src/shell.c
+++ b/src/shell.c
@@ -1,4 +0,0 @@
1
-echo the sql statement if echo onentile()"/
2
-staticpIwithin this sch;uinthhashch;uinthg->out, "%s\n",t/ay nci +i/ay nci += nr;uinthr"Inf input to /*
3
-** Out-ofashch;uinthg->out, "%s\n",t/ay nci +i/ay nci += nr;uinthr"Inf input to onentile()"/
4
-staticpI
--- a/src/shell.c
+++ b/src/shell.c
@@ -1,4 +0,0 @@
1 echo the sql statement if echo onentile()"/
2 staticpIwithin this sch;uinthhashch;uinthg->out, "%s\n",t/ay nci +i/ay nci += nr;uinthr"Inf input to /*
3 ** Out-ofashch;uinthg->out, "%s\n",t/ay nci +i/ay nci += nr;uinthr"Inf input to onentile()"/
4 staticpI
--- a/src/shell.c
+++ b/src/shell.c
@@ -1,4 +0,0 @@
 
 
 
 
+65 -35
--- tools/makemake.tcl
+++ tools/makemake.tcl
@@ -35,10 +35,13 @@
3535
# $srcDir is used to set the target source dir in several places. Not
3636
# all code-generation bits use $srcDir and instead hard-code, so
3737
# replacing it only here (should it ever changes) is not sufficient.
3838
#
3939
set srcDir ../src
40
+# Directory $srcDirExt houses single-file source code solutions which
41
+# are imported directly into the fossil source tree.
42
+set srcDirExt ../extsrc
4043
4144
# Basenames of all source files that get preprocessed using
4245
# "translate" and "makeheaders". To add new C-language source files to the
4346
# project, simply add the basename to this list and rerun this script.
4447
#
@@ -137,11 +140,10 @@
137140
moderate
138141
name
139142
patch
140143
path
141144
piechart
142
- pikchr
143145
pikchrshow
144146
pivot
145147
popen
146148
pqueue
147149
printf
@@ -194,10 +196,18 @@
194196
xfer
195197
xfersetup
196198
zip
197199
http_ssl
198200
}
201
+
202
+# Source files which live under $srcDirExt, but only those for which
203
+# we need to run makeheaders. External sources which have their own
204
+# header files must not be in this list.
205
+set src_ext {
206
+ miniz
207
+ pikchr
208
+}
199209
200210
# Additional resource files that get built into the executable.
201211
# These paths are all resolved from the src/ directory, so must
202212
# be relative to that.
203213
set extra_files {
@@ -458,14 +468,14 @@
458468
SQLITE3_SRC.0 = $(SRCDIR.extsrc)/sqlite3.c
459469
SQLITE3_SRC.1 = $(SRCDIR.extsrc)/sqlite3-see.c
460470
# SQLITE3_SRC.2 is set by top-level configure/makefile process.
461471
SQLITE3_SRC. = $(SRCDIR.extsrc)/sqlite3.c
462472
SQLITE3_SRC = $(SQLITE3_SRC.$(SQLITE3_ORIGIN))
463
-SQLITE3_SHELL_SRC.0 = $(SRCDIR)/shell.c
464
-SQLITE3_SHELL_SRC.1 = $(SRCDIR)/shell-see.c
473
+SQLITE3_SHELL_SRC.0 = $(SRCDIR.extsrc)/shell.c
474
+SQLITE3_SHELL_SRC.1 = $(SRCDIR.extsrc)/shell-see.c
465475
# SQLITE3_SHELL_SRC.2 comes from the configure process
466
-SQLITE3_SHELL_SRC. = $(SRCDIR)/shell.c
476
+SQLITE3_SHELL_SRC. = $(SRCDIR.extsrc)/shell.c
467477
SQLITE3_SHELL_SRC = $(SQLITE3_SHELL_SRC.$(SQLITE3_ORIGIN))
468478
SEE_FLAGS.0 =
469479
SEE_FLAGS.1 = -DSQLITE_HAS_CODEC -DSQLITE_SHELL_DBKEY_PROC=fossil_key
470480
SEE_FLAGS. =
471481
SEE_FLAGS = $(SEE_FLAGS.$(USE_SEE))
@@ -474,10 +484,11 @@
474484
writeln [string map [list <<<NEXT_LINE>>> \\] {
475485
EXTRAOBJ = <<<NEXT_LINE>>>
476486
$(SQLITE3_OBJ.$(SQLITE3_ORIGIN)) <<<NEXT_LINE>>>
477487
$(MINIZ_OBJ.$(FOSSIL_ENABLE_MINIZ)) <<<NEXT_LINE>>>
478488
$(LINENOISE_OBJ.$(USE_LINENOISE)) <<<NEXT_LINE>>>
489
+ $(OBJDIR)/pikchr.o <<<NEXT_LINE>>>
479490
$(OBJDIR)/shell.o <<<NEXT_LINE>>>
480491
$(OBJDIR)/th.o <<<NEXT_LINE>>>
481492
$(OBJDIR)/th_lang.o <<<NEXT_LINE>>>
482493
$(OBJDIR)/th_tcl.o <<<NEXT_LINE>>>
483494
$(OBJDIR)/cson_amalgamation.o
@@ -501,14 +512,18 @@
501512
502513
set mhargs {}
503514
foreach s [lsort $src] {
504515
append mhargs "\$(OBJDIR)/${s}_.c:\$(OBJDIR)/$s.h <<<NEXT_LINE>>>"
505516
set extra_h($s) { }
517
+}
518
+foreach s [lsort $src_ext] {
519
+ append mhargs "\$(SRCDIR.extsrc)/${s}.c:\$(OBJDIR)/$s.h <<<NEXT_LINE>>>"
520
+ set extra_h($s) { }
506521
}
507522
append mhargs "\$(SRCDIR.extsrc)/sqlite3.h <<<NEXT_LINE>>>"
508523
append mhargs "\$(SRCDIR)/th.h <<<NEXT_LINE>>>"
509
-#append mhargs "\$(SRCDIR)/cson_amalgamation.h <<<NEXT_LINE>>>"
524
+#append mhargs "\$(SRCDIR.extsrc)/cson_amalgamation.h <<<NEXT_LINE>>>"
510525
append mhargs "\$(OBJDIR)/VERSION.h "
511526
set mhargs [string map [list <<<NEXT_LINE>>> \\\n\t] $mhargs]
512527
writeln "\$(OBJDIR)/page_index.h: \$(TRANS_SRC) \$(OBJDIR)/mkindex"
513528
writeln "\t\$(OBJDIR)/mkindex \$(TRANS_SRC) >\$@\n"
514529
@@ -538,12 +553,12 @@
538553
writeln "\t\t-c \$(SQLITE3_SRC) -o \$@"
539554
540555
writeln "\$(OBJDIR)/shell.o:\t\$(SQLITE3_SHELL_SRC) \$(SRCDIR.extsrc)/sqlite3.h"
541556
writeln "\t\$(XTCC) \$(SHELL_OPTIONS) \$(SHELL_CFLAGS) \$(SEE_FLAGS) \$(LINENOISE_DEF.\$(USE_LINENOISE)) -c \$(SQLITE3_SHELL_SRC) -o \$@\n"
542557
543
-writeln "\$(OBJDIR)/linenoise.o:\t\$(SRCDIR)/linenoise.c \$(SRCDIR)/linenoise.h"
544
-writeln "\t\$(XTCC) -c \$(SRCDIR)/linenoise.c -o \$@\n"
558
+writeln "\$(OBJDIR)/linenoise.o:\t\$(SRCDIR.extsrc)/linenoise.c \$(SRCDIR.extsrc)/linenoise.h"
559
+writeln "\t\$(XTCC) -c \$(SRCDIR.extsrc)/linenoise.c -o \$@\n"
545560
546561
writeln "\$(OBJDIR)/th.o:\t\$(SRCDIR)/th.c"
547562
writeln "\t\$(XTCC) -c \$(SRCDIR)/th.c -o \$@\n"
548563
549564
writeln "\$(OBJDIR)/th_lang.o:\t\$(SRCDIR)/th_lang.c"
@@ -551,15 +566,18 @@
551566
552567
writeln "\$(OBJDIR)/th_tcl.o:\t\$(SRCDIR)/th_tcl.c"
553568
writeln "\t\$(XTCC) -c \$(SRCDIR)/th_tcl.c -o \$@\n"
554569
555570
writeln {
556
-$(OBJDIR)/miniz.o: $(SRCDIR)/miniz.c
557
- $(XTCC) $(MINIZ_OPTIONS) -c $(SRCDIR)/miniz.c -o $@
571
+$(OBJDIR)/miniz.o: $(SRCDIR.extsrc)/miniz.c
572
+ $(XTCC) $(MINIZ_OPTIONS) -c $(SRCDIR.extsrc)/miniz.c -o $@
558573
559
-$(OBJDIR)/cson_amalgamation.o: $(SRCDIR)/cson_amalgamation.c
560
- $(XTCC) -c $(SRCDIR)/cson_amalgamation.c -o $@
574
+$(OBJDIR)/pikchr.o: $(SRCDIR.extsrc)/pikchr.c
575
+ $(XTCC) -c $(SRCDIR.extsrc)/pikchr.c -o $@
576
+
577
+$(OBJDIR)/cson_amalgamation.o: $(SRCDIR.extsrc)/cson_amalgamation.c
578
+ $(XTCC) -c $(SRCDIR.extsrc)/cson_amalgamation.c -o $@
561579
562580
#
563581
# The list of all the targets that do not correspond to real files. This stops
564582
# 'make' from getting confused when someone makes an error in a rule.
565583
#
@@ -1068,16 +1086,16 @@
10681086
writeln {
10691087
all: $(OBJDIR) $(APPNAME)
10701088
10711089
$(OBJDIR)/fossil.o: $(SRCDIR)/../win/fossil.rc $(OBJDIR)/VERSION.h
10721090
ifdef USE_WINDOWS
1073
- $(CAT) $(subst /,\,$(SRCDIR)\miniz.c) | $(GREP) "define MZ_VERSION" > $(subst /,\,$(OBJDIR)\minizver.h)
1091
+ $(CAT) $(subst /,\,$(SRCDIR.extsrc)\miniz.c) | $(GREP) "define MZ_VERSION" > $(subst /,\,$(OBJDIR)\minizver.h)
10741092
$(CP) $(subst /,\,$(SRCDIR)\..\win\fossil.rc) $(subst /,\,$(OBJDIR))
10751093
$(CP) $(subst /,\,$(SRCDIR)\..\win\fossil.ico) $(subst /,\,$(OBJDIR))
10761094
$(CP) $(subst /,\,$(SRCDIR)\..\win\fossil.exe.manifest) $(subst /,\,$(OBJDIR))
10771095
else
1078
- $(CAT) $(SRCDIR)/miniz.c | $(GREP) "define MZ_VERSION" > $(OBJDIR)/minizver.h
1096
+ $(CAT) $(SRCDIR.extsrc)/miniz.c | $(GREP) "define MZ_VERSION" > $(OBJDIR)/minizver.h
10791097
$(CP) $(SRCDIR)/../win/fossil.rc $(OBJDIR)
10801098
$(CP) $(SRCDIR)/../win/fossil.ico $(OBJDIR)
10811099
$(CP) $(SRCDIR)/../win/fossil.exe.manifest $(OBJDIR)
10821100
endif
10831101
$(RCC) $(OBJDIR)/fossil.rc -o $(OBJDIR)/fossil.o
@@ -1155,14 +1173,14 @@
11551173
SQLITE3_SRC.0 = $(SRCDIR.extsrc)/sqlite3.c
11561174
SQLITE3_SRC.1 = $(SRCDIR.extsrc)/sqlite3-see.c
11571175
# SQLITE3_SRC.2 is set by top-level configure/makefile process.
11581176
SQLITE3_SRC. = $(SRCDIR.extsrc)/sqlite3.c
11591177
SQLITE3_SRC = $(SRCDIR)/$(SQLITE3_SRC.$(SQLITE3_ORIGIN))
1160
-SQLITE3_SHELL_SRC.0 = $(SRCDIR)/shell.c
1161
-SQLITE3_SHELL_SRC.1 = $(SRCDIR)/shell-see.c
1178
+SQLITE3_SHELL_SRC.0 = $(SRCDIR.extsrc)/shell.c
1179
+SQLITE3_SHELL_SRC.1 = $(SRCDIR.extsrc)/shell-see.c
11621180
# SQLITE3_SHELL_SRC.2 comes from the configure process
1163
-SQLITE3_SHELL_SRC. = $(SRCDIR)/shell.c
1181
+SQLITE3_SHELL_SRC. = $(SRCDIR.extsrc)/shell.c
11641182
SQLITE3_SHELL_SRC = $(SQLITE3_SHELL_SRC.$(SQLITE3_ORIGIN))
11651183
SEE_FLAGS.0 =
11661184
SEE_FLAGS.1 = -DSQLITE_HAS_CODEC -DSQLITE_SHELL_DBKEY_PROC=fossil_key
11671185
SEE_FLAGS. =
11681186
SEE_FLAGS = $(SEE_FLAGS.$(USE_SEE))
@@ -1248,10 +1266,14 @@
12481266
set mhargs {}
12491267
foreach s [lsort $src] {
12501268
if {[string length $mhargs] > 0} {append mhargs " \\\n\t\t"}
12511269
append mhargs "\$(OBJDIR)/${s}_.c:\$(OBJDIR)/$s.h"
12521270
set extra_h($s) { }
1271
+}
1272
+foreach s [lsort $src_ext] {
1273
+ append mhargs "\$(SRCDIR.extsrc)/${s}.c:\$(OBJDIR)/$s.h <<<NEXT_LINE>>>"
1274
+ set extra_h($s) { }
12531275
}
12541276
append mhargs " \\\n\t\t\$(SRCDIR.extsrc)/sqlite3.h"
12551277
append mhargs " \\\n\t\t\$(SRCDIR)/th.h"
12561278
append mhargs " \\\n\t\t\$(OBJDIR)/VERSION.h"
12571279
writeln "\$(OBJDIR)/page_index.h: \$(TRANS_SRC) \$(MKINDEX)"
@@ -1298,12 +1320,12 @@
12981320
12991321
writeln "\$(OBJDIR)/sqlite3.o:\t\$(SQLITE3_SRC) \$(SRCDIR)/../win/Makefile.mingw"
13001322
writeln "\t\$(XTCC) \$(SQLITE_OPTIONS) \$(SQLITE_CFLAGS) \$(SEE_FLAGS) \\"
13011323
writeln "\t\t-c \$(SQLITE3_SRC) -o \$@\n"
13021324
1303
-writeln "\$(OBJDIR)/cson_amalgamation.o:\t\$(SRCDIR)/cson_amalgamation.c"
1304
-writeln "\t\$(XTCC) -c \$(SRCDIR)/cson_amalgamation.c -o \$@\n"
1325
+writeln "\$(OBJDIR)/cson_amalgamation.o:\t\$(SRCDIR.extsrc)/cson_amalgamation.c"
1326
+writeln "\t\$(XTCC) -c \$(SRCDIR.extsrc)/cson_amalgamation.c -o \$@\n"
13051327
writeln "\$(OBJDIR)/json.o \$(OBJDIR)/json_artifact.o \$(OBJDIR)/json_branch.o \$(OBJDIR)/json_config.o \$(OBJDIR)/json_diff.o \$(OBJDIR)/json_dir.o \$(OBJDIR)/jsos_finfo.o \$(OBJDIR)/json_login.o \$(OBJDIR)/json_query.o \$(OBJDIR)/json_report.o \$(OBJDIR)/json_status.o \$(OBJDIR)/json_tag.o \$(OBJDIR)/json_timeline.o \$(OBJDIR)/json_user.o \$(OBJDIR)/json_wiki.o : \$(SRCDIR)/json_detail.h\n"
13061328
13071329
writeln "\$(OBJDIR)/shell.o:\t\$(SQLITE3_SHELL_SRC) \$(SRCDIR.extsrc)/sqlite3.h \$(SRCDIR)/../win/Makefile.mingw"
13081330
writeln "\t\$(XTCC) \$(SHELL_OPTIONS) \$(SHELL_CFLAGS) \$(SEE_FLAGS) -c \$(SQLITE3_SHELL_SRC) -o \$@\n"
13091331
@@ -1314,12 +1336,15 @@
13141336
writeln "\t\$(XTCC) -c \$(SRCDIR)/th_lang.c -o \$@\n"
13151337
13161338
writeln "\$(OBJDIR)/th_tcl.o:\t\$(SRCDIR)/th_tcl.c"
13171339
writeln "\t\$(XTCC) -c \$(SRCDIR)/th_tcl.c -o \$@\n"
13181340
1319
-writeln "\$(OBJDIR)/miniz.o:\t\$(SRCDIR)/miniz.c"
1320
-writeln "\t\$(XTCC) \$(MINIZ_OPTIONS) -c \$(SRCDIR)/miniz.c -o \$@\n"
1341
+writeln "\$(OBJDIR)/miniz.o:\t\$(SRCDIR.extsrc)/miniz.c"
1342
+writeln "\t\$(XTCC) \$(MINIZ_OPTIONS) -c \$(SRCDIR.extsrc)/miniz.c -o \$@\n"
1343
+
1344
+writeln "\$(OBJDIR)/pikchr.o:\t\$(SRCDIR.extsrc)/pikchr.c"
1345
+writeln "\t\$(XTCC) -c \$(SRCDIR.extsrc)/pikchr.c -o \$@\n"
13211346
13221347
close $output_file
13231348
#
13241349
# End of the win/Makefile.mingw output
13251350
##############################################################################
@@ -1417,23 +1442,23 @@
14171442
$(BCC) -o$@ $**
14181443
14191444
codecheck1$E: $(SRCDIR.tools)\codecheck1.c
14201445
$(BCC) -o$@ $**
14211446
1422
-$(OBJDIR)\shell$O : $(SRCDIR)\shell.c
1447
+$(OBJDIR)\shell$O : $(SRCDIR.extsrc)\shell.c
14231448
$(TCC) -o$@ -c $(SHELL_OPTIONS) $(SQLITE_OPTIONS) $(SHELL_CFLAGS) $**
14241449
1425
-$(OBJDIR)\sqlite3$O : $(SRCDIR)\sqlite3.c
1450
+$(OBJDIR)\sqlite3$O : $(SRCDIR.extsrc)\sqlite3.c
14261451
$(TCC) -o$@ -c $(SQLITE_OPTIONS) $(SQLITE_CFLAGS) $**
14271452
14281453
$(OBJDIR)\th$O : $(SRCDIR)\th.c
14291454
$(TCC) -o$@ -c $**
14301455
14311456
$(OBJDIR)\th_lang$O : $(SRCDIR)\th_lang.c
14321457
$(TCC) -o$@ -c $**
14331458
1434
-$(OBJDIR)\cson_amalgamation.h : $(SRCDIR)\cson_amalgamation.h
1459
+$(OBJDIR)\cson_amalgamation.h : $(SRCDIR.extsrc)\cson_amalgamation.h
14351460
cp $@ $@
14361461
14371462
VERSION.h : mkversion$E $B\manifest.uuid $B\manifest $B\VERSION
14381463
+$** > $@
14391464
@@ -1476,11 +1501,11 @@
14761501
14771502
writeln -nonewline "headers: makeheaders\$E page_index.h builtin_data.h VERSION.h\n\t +makeheaders\$E "
14781503
foreach s [lsort $src] {
14791504
writeln -nonewline "${s}_.c:$s.h "
14801505
}
1481
-writeln "\$(SRCDIR.extsrc)\\sqlite3.h \$(SRCDIR)\\th.h VERSION.h \$(SRCDIR)\\cson_amalgamation.h"
1506
+writeln "\$(SRCDIR.extsrc)\\sqlite3.h \$(SRCDIR)\\th.h VERSION.h \$(SRCDIR.extsrc)\\cson_amalgamation.h"
14821507
writeln "\t@copy /Y nul: headers"
14831508
14841509
close $output_file
14851510
#
14861511
# End of the win/Makefile.dmc output
@@ -1503,10 +1528,11 @@
15031528
# file, edit "makemake.tcl" then run "tclsh makemake.tcl"
15041529
# to regenerate this file.
15051530
#
15061531
B = ..
15071532
SRCDIR = $(B)\src
1533
+SRCDIRX = $(B)\extsrc
15081534
T = .
15091535
OBJDIR = $(T)
15101536
OX = $(OBJDIR)
15111537
O = .obj
15121538
E = .exe
@@ -1827,11 +1853,11 @@
18271853
}
18281854
set s [regsub -all / $s \\]
18291855
writeln -nonewline "\"\$(SRCDIR)\\${s}\""; incr i
18301856
}
18311857
writeln "\n"
1832
-set AdditionalObj [list shell sqlite3 th th_lang th_tcl cson_amalgamation]
1858
+set AdditionalObj [list shell sqlite3 th th_lang th_tcl cson_amalgamation pikchr]
18331859
writeln -nonewline "OBJ = "
18341860
set i 0
18351861
foreach s [lsort [concat $src $AdditionalObj]] {
18361862
if {$i > 0} {
18371863
writeln " \\"
@@ -1952,11 +1978,11 @@
19521978
SEE_FLAGS = /DSQLITE_HAS_CODEC=1 /DSQLITE_SHELL_DBKEY_PROC=fossil_key
19531979
SQLITE3_SHELL_SRC = $(SRCDIR)\shell-see.c
19541980
SQLITE3_SRC = $(SRCDIR.extsrc)\sqlite3-see.c
19551981
!else
19561982
SEE_FLAGS =
1957
-SQLITE3_SHELL_SRC = $(SRCDIR)\shell.c
1983
+SQLITE3_SHELL_SRC = $(SRCDIR.extsrc)\shell.c
19581984
SQLITE3_SRC = $(SRCDIR.extsrc)\sqlite3.c
19591985
!endif
19601986
19611987
"$(OX)\shell$O" : "$(SQLITE3_SHELL_SRC)" "$(B)\win\Makefile.msc"
19621988
$(TCC) /Fo$@ /Fd$(@D)\ $(SHELL_OPTIONS) $(SQLITE_OPTIONS) $(SHELL_CFLAGS) $(SEE_FLAGS) -c "$(SQLITE3_SHELL_SRC)"
@@ -1971,20 +1997,23 @@
19711997
$(TCC) /Fo$@ /Fd$(@D)\ -c $**
19721998
19731999
"$(OX)\th_tcl$O" : "$(SRCDIR)\th_tcl.c"
19742000
$(TCC) /Fo$@ /Fd$(@D)\ -c $**
19752001
1976
-"$(OX)\miniz$O" : "$(SRCDIR)\miniz.c"
2002
+"$(OX)\miniz$O" : "$(SRCDIR.extsrc)\miniz.c"
19772003
$(TCC) /Fo$@ /Fd$(@D)\ -c $(MINIZ_OPTIONS) $**
2004
+
2005
+"$(OX)\pikchr$O" : "$(SRCDIR.extsrc)" "$(B)\win\Makefile.msc"
2006
+ $(TCC) /Fo$@ /Fd$(@D)\ -c $**
19782007
19792008
"$(OX)\VERSION.h" : "$(OBJDIR)\mkversion$E" "$(B)\manifest.uuid" "$(B)\manifest" "$(B)\VERSION" "$(B)\phony.h"
19802009
"$(OBJDIR)\mkversion$E" "$(B)\manifest.uuid" "$(B)\manifest" "$(B)\VERSION" > $@
19812010
19822011
"$(B)\phony.h" :
19832012
rem Force rebuild of VERSION.h whenever nmake is run
19842013
1985
-"$(OX)\cson_amalgamation$O" : "$(SRCDIR)\cson_amalgamation.c"
2014
+"$(OX)\cson_amalgamation$O" : "$(SRCDIR.extsrc)\cson_amalgamation.c"
19862015
$(TCC) /Fo$@ /Fd$(@D)\ -c $**
19872016
19882017
"$(OX)\page_index.h": "$(OBJDIR)\mkindex$E" $(SRC)
19892018
$** > $@
19902019
@@ -2070,11 +2099,11 @@
20702099
writeln -nonewline "\"\$(OX)\\${s}_.c\":\"\$(OX)\\$s.h\""; incr i
20712100
}
20722101
writeln " \\\n\t\t\t\"\$(SRCDIR.extsrc)\\sqlite3.h\" \\"
20732102
writeln "\t\t\t\"\$(SRCDIR)\\th.h\" \\"
20742103
writeln "\t\t\t\"\$(OX)\\VERSION.h\" \\"
2075
-writeln "\t\t\t\"\$(SRCDIR)\\cson_amalgamation.h\""
2104
+writeln "\t\t\t\"\$(SRCDIR.extsrc)\\cson_amalgamation.h\""
20762105
writeln "\t@copy /Y nul: $@"
20772106
20782107
20792108
close $output_file
20802109
#
@@ -2145,10 +2174,11 @@
21452174
endif
21462175
21472176
# define the project directories
21482177
B=..
21492178
SRCDIR=$(B)/src/
2179
+SRCDIRX=$(B)/extsrc/
21502180
WINDIR=$(B)/win/
21512181
ZLIBSRCDIR=../../zlib/
21522182
21532183
# define linker command and options
21542184
LINK=$(PellesCDir)/bin/polink.exe
@@ -2158,11 +2188,11 @@
21582188
# the fossil binary. Some special definitions follow for
21592189
# special files follow
21602190
CC=$(PellesCDir)\bin\pocc.exe
21612191
DEFINES=-D_pgmptr=g.argv[0]
21622192
CCFLAGS=-T$(TARGETMACHINE_CC)-coff -Ot -W2 -Gd -Go -Ze -MT $(DEFINES)
2163
-INCLUDE=/I $(PellesCDir)\Include\Win /I $(PellesCDir)\Include /I $(ZLIBSRCDIR) /I $(SRCDIR)
2193
+INCLUDE=/I $(PellesCDir)\Include\Win /I $(PellesCDir)\Include /I $(ZLIBSRCDIR) /I $(SRCDIR) /I $(SRCDIRX)
21642194
21652195
# define commands for building the windows resource files
21662196
RESOURCE=fossil.res
21672197
RC=$(PellesCDir)\bin\porc.exe
21682198
RCFLAGS=$(INCLUDE) -D__POCC__=1 -D_M_X$(TARGETVERSION)
@@ -2169,21 +2199,21 @@
21692199
21702200
# define the special utilities files, needed to generate
21712201
# the automatically generated source files
21722202
UTILS=translate.exe mkindex.exe makeheaders.exe mkbuiltin.exe
21732203
UTILS_OBJ=$(UTILS:.exe=.obj)
2174
-UTILS_SRC=$(foreach uf,$(UTILS),$(SRCDIR)$(uf:.exe=.c))
2204
+UTILS_SRC=$(foreach uf,$(UTILS),$(SRCDIRX)$(uf:.exe=.c))
21752205
21762206
# define the SQLite files, which need special flags on compile
21772207
SQLITESRC=sqlite3.c
2178
-ORIGSQLITESRC=$(foreach sf,$(SQLITESRC),$(SRCDIR)$(sf))
2208
+ORIGSQLITESRC=$(foreach sf,$(SQLITESRC),$(SRCDIRX)$(sf))
21792209
SQLITEOBJ=$(foreach sf,$(SQLITESRC),$(sf:.c=.obj))
21802210
SQLITEDEFINES=<<<SQLITE_OPTIONS>>>
21812211
21822212
# define the SQLite shell files, which need special flags on compile
21832213
SQLITESHELLSRC=shell.c
2184
-ORIGSQLITESHELLSRC=$(foreach sf,$(SQLITESHELLSRC),$(SRCDIR)$(sf))
2214
+ORIGSQLITESHELLSRC=$(foreach sf,$(SQLITESHELLSRC),$(SRCDIRX)$(sf))
21852215
SQLITESHELLOBJ=$(foreach sf,$(SQLITESHELLSRC),$(sf:.c=.obj))
21862216
SQLITESHELLDEFINES=<<<SHELL_OPTIONS>>>
21872217
21882218
# define the th scripting files, which need special flags on compile
21892219
THSRC=th.c th_lang.c
@@ -2249,14 +2279,14 @@
22492279
# compile C sources with relevant options
22502280
22512281
$(TRANSLATEDOBJ): %_.obj: %_.c %.h
22522282
$(CC) $(CCFLAGS) $(INCLUDE) "$<" -Fo"$@"
22532283
2254
-$(SQLITEOBJ): %.obj: $(SRCDIR)%.c $(SRCDIR)%.h
2284
+$(SQLITEOBJ): %.obj: $(SRCDIRX)%.c $(SRCDIRX)%.h
22552285
$(CC) $(CCFLAGS) $(SQLITEDEFINES) $(INCLUDE) "$<" -Fo"$@"
22562286
2257
-$(SQLITESHELLOBJ): %.obj: $(SRCDIR)%.c
2287
+$(SQLITESHELLOBJ): %.obj: $(SRCDIRX)%.c
22582288
$(CC) $(CCFLAGS) $(SQLITESHELLDEFINES) $(INCLUDE) "$<" -Fo"$@"
22592289
22602290
$(THOBJ): %.obj: $(SRCDIR)%.c $(SRCDIR)th.h
22612291
$(CC) $(CCFLAGS) $(INCLUDE) "$<" -Fo"$@"
22622292
22632293
--- tools/makemake.tcl
+++ tools/makemake.tcl
@@ -35,10 +35,13 @@
35 # $srcDir is used to set the target source dir in several places. Not
36 # all code-generation bits use $srcDir and instead hard-code, so
37 # replacing it only here (should it ever changes) is not sufficient.
38 #
39 set srcDir ../src
 
 
 
40
41 # Basenames of all source files that get preprocessed using
42 # "translate" and "makeheaders". To add new C-language source files to the
43 # project, simply add the basename to this list and rerun this script.
44 #
@@ -137,11 +140,10 @@
137 moderate
138 name
139 patch
140 path
141 piechart
142 pikchr
143 pikchrshow
144 pivot
145 popen
146 pqueue
147 printf
@@ -194,10 +196,18 @@
194 xfer
195 xfersetup
196 zip
197 http_ssl
198 }
 
 
 
 
 
 
 
 
199
200 # Additional resource files that get built into the executable.
201 # These paths are all resolved from the src/ directory, so must
202 # be relative to that.
203 set extra_files {
@@ -458,14 +468,14 @@
458 SQLITE3_SRC.0 = $(SRCDIR.extsrc)/sqlite3.c
459 SQLITE3_SRC.1 = $(SRCDIR.extsrc)/sqlite3-see.c
460 # SQLITE3_SRC.2 is set by top-level configure/makefile process.
461 SQLITE3_SRC. = $(SRCDIR.extsrc)/sqlite3.c
462 SQLITE3_SRC = $(SQLITE3_SRC.$(SQLITE3_ORIGIN))
463 SQLITE3_SHELL_SRC.0 = $(SRCDIR)/shell.c
464 SQLITE3_SHELL_SRC.1 = $(SRCDIR)/shell-see.c
465 # SQLITE3_SHELL_SRC.2 comes from the configure process
466 SQLITE3_SHELL_SRC. = $(SRCDIR)/shell.c
467 SQLITE3_SHELL_SRC = $(SQLITE3_SHELL_SRC.$(SQLITE3_ORIGIN))
468 SEE_FLAGS.0 =
469 SEE_FLAGS.1 = -DSQLITE_HAS_CODEC -DSQLITE_SHELL_DBKEY_PROC=fossil_key
470 SEE_FLAGS. =
471 SEE_FLAGS = $(SEE_FLAGS.$(USE_SEE))
@@ -474,10 +484,11 @@
474 writeln [string map [list <<<NEXT_LINE>>> \\] {
475 EXTRAOBJ = <<<NEXT_LINE>>>
476 $(SQLITE3_OBJ.$(SQLITE3_ORIGIN)) <<<NEXT_LINE>>>
477 $(MINIZ_OBJ.$(FOSSIL_ENABLE_MINIZ)) <<<NEXT_LINE>>>
478 $(LINENOISE_OBJ.$(USE_LINENOISE)) <<<NEXT_LINE>>>
 
479 $(OBJDIR)/shell.o <<<NEXT_LINE>>>
480 $(OBJDIR)/th.o <<<NEXT_LINE>>>
481 $(OBJDIR)/th_lang.o <<<NEXT_LINE>>>
482 $(OBJDIR)/th_tcl.o <<<NEXT_LINE>>>
483 $(OBJDIR)/cson_amalgamation.o
@@ -501,14 +512,18 @@
501
502 set mhargs {}
503 foreach s [lsort $src] {
504 append mhargs "\$(OBJDIR)/${s}_.c:\$(OBJDIR)/$s.h <<<NEXT_LINE>>>"
505 set extra_h($s) { }
 
 
 
 
506 }
507 append mhargs "\$(SRCDIR.extsrc)/sqlite3.h <<<NEXT_LINE>>>"
508 append mhargs "\$(SRCDIR)/th.h <<<NEXT_LINE>>>"
509 #append mhargs "\$(SRCDIR)/cson_amalgamation.h <<<NEXT_LINE>>>"
510 append mhargs "\$(OBJDIR)/VERSION.h "
511 set mhargs [string map [list <<<NEXT_LINE>>> \\\n\t] $mhargs]
512 writeln "\$(OBJDIR)/page_index.h: \$(TRANS_SRC) \$(OBJDIR)/mkindex"
513 writeln "\t\$(OBJDIR)/mkindex \$(TRANS_SRC) >\$@\n"
514
@@ -538,12 +553,12 @@
538 writeln "\t\t-c \$(SQLITE3_SRC) -o \$@"
539
540 writeln "\$(OBJDIR)/shell.o:\t\$(SQLITE3_SHELL_SRC) \$(SRCDIR.extsrc)/sqlite3.h"
541 writeln "\t\$(XTCC) \$(SHELL_OPTIONS) \$(SHELL_CFLAGS) \$(SEE_FLAGS) \$(LINENOISE_DEF.\$(USE_LINENOISE)) -c \$(SQLITE3_SHELL_SRC) -o \$@\n"
542
543 writeln "\$(OBJDIR)/linenoise.o:\t\$(SRCDIR)/linenoise.c \$(SRCDIR)/linenoise.h"
544 writeln "\t\$(XTCC) -c \$(SRCDIR)/linenoise.c -o \$@\n"
545
546 writeln "\$(OBJDIR)/th.o:\t\$(SRCDIR)/th.c"
547 writeln "\t\$(XTCC) -c \$(SRCDIR)/th.c -o \$@\n"
548
549 writeln "\$(OBJDIR)/th_lang.o:\t\$(SRCDIR)/th_lang.c"
@@ -551,15 +566,18 @@
551
552 writeln "\$(OBJDIR)/th_tcl.o:\t\$(SRCDIR)/th_tcl.c"
553 writeln "\t\$(XTCC) -c \$(SRCDIR)/th_tcl.c -o \$@\n"
554
555 writeln {
556 $(OBJDIR)/miniz.o: $(SRCDIR)/miniz.c
557 $(XTCC) $(MINIZ_OPTIONS) -c $(SRCDIR)/miniz.c -o $@
558
559 $(OBJDIR)/cson_amalgamation.o: $(SRCDIR)/cson_amalgamation.c
560 $(XTCC) -c $(SRCDIR)/cson_amalgamation.c -o $@
 
 
 
561
562 #
563 # The list of all the targets that do not correspond to real files. This stops
564 # 'make' from getting confused when someone makes an error in a rule.
565 #
@@ -1068,16 +1086,16 @@
1068 writeln {
1069 all: $(OBJDIR) $(APPNAME)
1070
1071 $(OBJDIR)/fossil.o: $(SRCDIR)/../win/fossil.rc $(OBJDIR)/VERSION.h
1072 ifdef USE_WINDOWS
1073 $(CAT) $(subst /,\,$(SRCDIR)\miniz.c) | $(GREP) "define MZ_VERSION" > $(subst /,\,$(OBJDIR)\minizver.h)
1074 $(CP) $(subst /,\,$(SRCDIR)\..\win\fossil.rc) $(subst /,\,$(OBJDIR))
1075 $(CP) $(subst /,\,$(SRCDIR)\..\win\fossil.ico) $(subst /,\,$(OBJDIR))
1076 $(CP) $(subst /,\,$(SRCDIR)\..\win\fossil.exe.manifest) $(subst /,\,$(OBJDIR))
1077 else
1078 $(CAT) $(SRCDIR)/miniz.c | $(GREP) "define MZ_VERSION" > $(OBJDIR)/minizver.h
1079 $(CP) $(SRCDIR)/../win/fossil.rc $(OBJDIR)
1080 $(CP) $(SRCDIR)/../win/fossil.ico $(OBJDIR)
1081 $(CP) $(SRCDIR)/../win/fossil.exe.manifest $(OBJDIR)
1082 endif
1083 $(RCC) $(OBJDIR)/fossil.rc -o $(OBJDIR)/fossil.o
@@ -1155,14 +1173,14 @@
1155 SQLITE3_SRC.0 = $(SRCDIR.extsrc)/sqlite3.c
1156 SQLITE3_SRC.1 = $(SRCDIR.extsrc)/sqlite3-see.c
1157 # SQLITE3_SRC.2 is set by top-level configure/makefile process.
1158 SQLITE3_SRC. = $(SRCDIR.extsrc)/sqlite3.c
1159 SQLITE3_SRC = $(SRCDIR)/$(SQLITE3_SRC.$(SQLITE3_ORIGIN))
1160 SQLITE3_SHELL_SRC.0 = $(SRCDIR)/shell.c
1161 SQLITE3_SHELL_SRC.1 = $(SRCDIR)/shell-see.c
1162 # SQLITE3_SHELL_SRC.2 comes from the configure process
1163 SQLITE3_SHELL_SRC. = $(SRCDIR)/shell.c
1164 SQLITE3_SHELL_SRC = $(SQLITE3_SHELL_SRC.$(SQLITE3_ORIGIN))
1165 SEE_FLAGS.0 =
1166 SEE_FLAGS.1 = -DSQLITE_HAS_CODEC -DSQLITE_SHELL_DBKEY_PROC=fossil_key
1167 SEE_FLAGS. =
1168 SEE_FLAGS = $(SEE_FLAGS.$(USE_SEE))
@@ -1248,10 +1266,14 @@
1248 set mhargs {}
1249 foreach s [lsort $src] {
1250 if {[string length $mhargs] > 0} {append mhargs " \\\n\t\t"}
1251 append mhargs "\$(OBJDIR)/${s}_.c:\$(OBJDIR)/$s.h"
1252 set extra_h($s) { }
 
 
 
 
1253 }
1254 append mhargs " \\\n\t\t\$(SRCDIR.extsrc)/sqlite3.h"
1255 append mhargs " \\\n\t\t\$(SRCDIR)/th.h"
1256 append mhargs " \\\n\t\t\$(OBJDIR)/VERSION.h"
1257 writeln "\$(OBJDIR)/page_index.h: \$(TRANS_SRC) \$(MKINDEX)"
@@ -1298,12 +1320,12 @@
1298
1299 writeln "\$(OBJDIR)/sqlite3.o:\t\$(SQLITE3_SRC) \$(SRCDIR)/../win/Makefile.mingw"
1300 writeln "\t\$(XTCC) \$(SQLITE_OPTIONS) \$(SQLITE_CFLAGS) \$(SEE_FLAGS) \\"
1301 writeln "\t\t-c \$(SQLITE3_SRC) -o \$@\n"
1302
1303 writeln "\$(OBJDIR)/cson_amalgamation.o:\t\$(SRCDIR)/cson_amalgamation.c"
1304 writeln "\t\$(XTCC) -c \$(SRCDIR)/cson_amalgamation.c -o \$@\n"
1305 writeln "\$(OBJDIR)/json.o \$(OBJDIR)/json_artifact.o \$(OBJDIR)/json_branch.o \$(OBJDIR)/json_config.o \$(OBJDIR)/json_diff.o \$(OBJDIR)/json_dir.o \$(OBJDIR)/jsos_finfo.o \$(OBJDIR)/json_login.o \$(OBJDIR)/json_query.o \$(OBJDIR)/json_report.o \$(OBJDIR)/json_status.o \$(OBJDIR)/json_tag.o \$(OBJDIR)/json_timeline.o \$(OBJDIR)/json_user.o \$(OBJDIR)/json_wiki.o : \$(SRCDIR)/json_detail.h\n"
1306
1307 writeln "\$(OBJDIR)/shell.o:\t\$(SQLITE3_SHELL_SRC) \$(SRCDIR.extsrc)/sqlite3.h \$(SRCDIR)/../win/Makefile.mingw"
1308 writeln "\t\$(XTCC) \$(SHELL_OPTIONS) \$(SHELL_CFLAGS) \$(SEE_FLAGS) -c \$(SQLITE3_SHELL_SRC) -o \$@\n"
1309
@@ -1314,12 +1336,15 @@
1314 writeln "\t\$(XTCC) -c \$(SRCDIR)/th_lang.c -o \$@\n"
1315
1316 writeln "\$(OBJDIR)/th_tcl.o:\t\$(SRCDIR)/th_tcl.c"
1317 writeln "\t\$(XTCC) -c \$(SRCDIR)/th_tcl.c -o \$@\n"
1318
1319 writeln "\$(OBJDIR)/miniz.o:\t\$(SRCDIR)/miniz.c"
1320 writeln "\t\$(XTCC) \$(MINIZ_OPTIONS) -c \$(SRCDIR)/miniz.c -o \$@\n"
 
 
 
1321
1322 close $output_file
1323 #
1324 # End of the win/Makefile.mingw output
1325 ##############################################################################
@@ -1417,23 +1442,23 @@
1417 $(BCC) -o$@ $**
1418
1419 codecheck1$E: $(SRCDIR.tools)\codecheck1.c
1420 $(BCC) -o$@ $**
1421
1422 $(OBJDIR)\shell$O : $(SRCDIR)\shell.c
1423 $(TCC) -o$@ -c $(SHELL_OPTIONS) $(SQLITE_OPTIONS) $(SHELL_CFLAGS) $**
1424
1425 $(OBJDIR)\sqlite3$O : $(SRCDIR)\sqlite3.c
1426 $(TCC) -o$@ -c $(SQLITE_OPTIONS) $(SQLITE_CFLAGS) $**
1427
1428 $(OBJDIR)\th$O : $(SRCDIR)\th.c
1429 $(TCC) -o$@ -c $**
1430
1431 $(OBJDIR)\th_lang$O : $(SRCDIR)\th_lang.c
1432 $(TCC) -o$@ -c $**
1433
1434 $(OBJDIR)\cson_amalgamation.h : $(SRCDIR)\cson_amalgamation.h
1435 cp $@ $@
1436
1437 VERSION.h : mkversion$E $B\manifest.uuid $B\manifest $B\VERSION
1438 +$** > $@
1439
@@ -1476,11 +1501,11 @@
1476
1477 writeln -nonewline "headers: makeheaders\$E page_index.h builtin_data.h VERSION.h\n\t +makeheaders\$E "
1478 foreach s [lsort $src] {
1479 writeln -nonewline "${s}_.c:$s.h "
1480 }
1481 writeln "\$(SRCDIR.extsrc)\\sqlite3.h \$(SRCDIR)\\th.h VERSION.h \$(SRCDIR)\\cson_amalgamation.h"
1482 writeln "\t@copy /Y nul: headers"
1483
1484 close $output_file
1485 #
1486 # End of the win/Makefile.dmc output
@@ -1503,10 +1528,11 @@
1503 # file, edit "makemake.tcl" then run "tclsh makemake.tcl"
1504 # to regenerate this file.
1505 #
1506 B = ..
1507 SRCDIR = $(B)\src
 
1508 T = .
1509 OBJDIR = $(T)
1510 OX = $(OBJDIR)
1511 O = .obj
1512 E = .exe
@@ -1827,11 +1853,11 @@
1827 }
1828 set s [regsub -all / $s \\]
1829 writeln -nonewline "\"\$(SRCDIR)\\${s}\""; incr i
1830 }
1831 writeln "\n"
1832 set AdditionalObj [list shell sqlite3 th th_lang th_tcl cson_amalgamation]
1833 writeln -nonewline "OBJ = "
1834 set i 0
1835 foreach s [lsort [concat $src $AdditionalObj]] {
1836 if {$i > 0} {
1837 writeln " \\"
@@ -1952,11 +1978,11 @@
1952 SEE_FLAGS = /DSQLITE_HAS_CODEC=1 /DSQLITE_SHELL_DBKEY_PROC=fossil_key
1953 SQLITE3_SHELL_SRC = $(SRCDIR)\shell-see.c
1954 SQLITE3_SRC = $(SRCDIR.extsrc)\sqlite3-see.c
1955 !else
1956 SEE_FLAGS =
1957 SQLITE3_SHELL_SRC = $(SRCDIR)\shell.c
1958 SQLITE3_SRC = $(SRCDIR.extsrc)\sqlite3.c
1959 !endif
1960
1961 "$(OX)\shell$O" : "$(SQLITE3_SHELL_SRC)" "$(B)\win\Makefile.msc"
1962 $(TCC) /Fo$@ /Fd$(@D)\ $(SHELL_OPTIONS) $(SQLITE_OPTIONS) $(SHELL_CFLAGS) $(SEE_FLAGS) -c "$(SQLITE3_SHELL_SRC)"
@@ -1971,20 +1997,23 @@
1971 $(TCC) /Fo$@ /Fd$(@D)\ -c $**
1972
1973 "$(OX)\th_tcl$O" : "$(SRCDIR)\th_tcl.c"
1974 $(TCC) /Fo$@ /Fd$(@D)\ -c $**
1975
1976 "$(OX)\miniz$O" : "$(SRCDIR)\miniz.c"
1977 $(TCC) /Fo$@ /Fd$(@D)\ -c $(MINIZ_OPTIONS) $**
 
 
 
1978
1979 "$(OX)\VERSION.h" : "$(OBJDIR)\mkversion$E" "$(B)\manifest.uuid" "$(B)\manifest" "$(B)\VERSION" "$(B)\phony.h"
1980 "$(OBJDIR)\mkversion$E" "$(B)\manifest.uuid" "$(B)\manifest" "$(B)\VERSION" > $@
1981
1982 "$(B)\phony.h" :
1983 rem Force rebuild of VERSION.h whenever nmake is run
1984
1985 "$(OX)\cson_amalgamation$O" : "$(SRCDIR)\cson_amalgamation.c"
1986 $(TCC) /Fo$@ /Fd$(@D)\ -c $**
1987
1988 "$(OX)\page_index.h": "$(OBJDIR)\mkindex$E" $(SRC)
1989 $** > $@
1990
@@ -2070,11 +2099,11 @@
2070 writeln -nonewline "\"\$(OX)\\${s}_.c\":\"\$(OX)\\$s.h\""; incr i
2071 }
2072 writeln " \\\n\t\t\t\"\$(SRCDIR.extsrc)\\sqlite3.h\" \\"
2073 writeln "\t\t\t\"\$(SRCDIR)\\th.h\" \\"
2074 writeln "\t\t\t\"\$(OX)\\VERSION.h\" \\"
2075 writeln "\t\t\t\"\$(SRCDIR)\\cson_amalgamation.h\""
2076 writeln "\t@copy /Y nul: $@"
2077
2078
2079 close $output_file
2080 #
@@ -2145,10 +2174,11 @@
2145 endif
2146
2147 # define the project directories
2148 B=..
2149 SRCDIR=$(B)/src/
 
2150 WINDIR=$(B)/win/
2151 ZLIBSRCDIR=../../zlib/
2152
2153 # define linker command and options
2154 LINK=$(PellesCDir)/bin/polink.exe
@@ -2158,11 +2188,11 @@
2158 # the fossil binary. Some special definitions follow for
2159 # special files follow
2160 CC=$(PellesCDir)\bin\pocc.exe
2161 DEFINES=-D_pgmptr=g.argv[0]
2162 CCFLAGS=-T$(TARGETMACHINE_CC)-coff -Ot -W2 -Gd -Go -Ze -MT $(DEFINES)
2163 INCLUDE=/I $(PellesCDir)\Include\Win /I $(PellesCDir)\Include /I $(ZLIBSRCDIR) /I $(SRCDIR)
2164
2165 # define commands for building the windows resource files
2166 RESOURCE=fossil.res
2167 RC=$(PellesCDir)\bin\porc.exe
2168 RCFLAGS=$(INCLUDE) -D__POCC__=1 -D_M_X$(TARGETVERSION)
@@ -2169,21 +2199,21 @@
2169
2170 # define the special utilities files, needed to generate
2171 # the automatically generated source files
2172 UTILS=translate.exe mkindex.exe makeheaders.exe mkbuiltin.exe
2173 UTILS_OBJ=$(UTILS:.exe=.obj)
2174 UTILS_SRC=$(foreach uf,$(UTILS),$(SRCDIR)$(uf:.exe=.c))
2175
2176 # define the SQLite files, which need special flags on compile
2177 SQLITESRC=sqlite3.c
2178 ORIGSQLITESRC=$(foreach sf,$(SQLITESRC),$(SRCDIR)$(sf))
2179 SQLITEOBJ=$(foreach sf,$(SQLITESRC),$(sf:.c=.obj))
2180 SQLITEDEFINES=<<<SQLITE_OPTIONS>>>
2181
2182 # define the SQLite shell files, which need special flags on compile
2183 SQLITESHELLSRC=shell.c
2184 ORIGSQLITESHELLSRC=$(foreach sf,$(SQLITESHELLSRC),$(SRCDIR)$(sf))
2185 SQLITESHELLOBJ=$(foreach sf,$(SQLITESHELLSRC),$(sf:.c=.obj))
2186 SQLITESHELLDEFINES=<<<SHELL_OPTIONS>>>
2187
2188 # define the th scripting files, which need special flags on compile
2189 THSRC=th.c th_lang.c
@@ -2249,14 +2279,14 @@
2249 # compile C sources with relevant options
2250
2251 $(TRANSLATEDOBJ): %_.obj: %_.c %.h
2252 $(CC) $(CCFLAGS) $(INCLUDE) "$<" -Fo"$@"
2253
2254 $(SQLITEOBJ): %.obj: $(SRCDIR)%.c $(SRCDIR)%.h
2255 $(CC) $(CCFLAGS) $(SQLITEDEFINES) $(INCLUDE) "$<" -Fo"$@"
2256
2257 $(SQLITESHELLOBJ): %.obj: $(SRCDIR)%.c
2258 $(CC) $(CCFLAGS) $(SQLITESHELLDEFINES) $(INCLUDE) "$<" -Fo"$@"
2259
2260 $(THOBJ): %.obj: $(SRCDIR)%.c $(SRCDIR)th.h
2261 $(CC) $(CCFLAGS) $(INCLUDE) "$<" -Fo"$@"
2262
2263
--- tools/makemake.tcl
+++ tools/makemake.tcl
@@ -35,10 +35,13 @@
35 # $srcDir is used to set the target source dir in several places. Not
36 # all code-generation bits use $srcDir and instead hard-code, so
37 # replacing it only here (should it ever changes) is not sufficient.
38 #
39 set srcDir ../src
40 # Directory $srcDirExt houses single-file source code solutions which
41 # are imported directly into the fossil source tree.
42 set srcDirExt ../extsrc
43
44 # Basenames of all source files that get preprocessed using
45 # "translate" and "makeheaders". To add new C-language source files to the
46 # project, simply add the basename to this list and rerun this script.
47 #
@@ -137,11 +140,10 @@
140 moderate
141 name
142 patch
143 path
144 piechart
 
145 pikchrshow
146 pivot
147 popen
148 pqueue
149 printf
@@ -194,10 +196,18 @@
196 xfer
197 xfersetup
198 zip
199 http_ssl
200 }
201
202 # Source files which live under $srcDirExt, but only those for which
203 # we need to run makeheaders. External sources which have their own
204 # header files must not be in this list.
205 set src_ext {
206 miniz
207 pikchr
208 }
209
210 # Additional resource files that get built into the executable.
211 # These paths are all resolved from the src/ directory, so must
212 # be relative to that.
213 set extra_files {
@@ -458,14 +468,14 @@
468 SQLITE3_SRC.0 = $(SRCDIR.extsrc)/sqlite3.c
469 SQLITE3_SRC.1 = $(SRCDIR.extsrc)/sqlite3-see.c
470 # SQLITE3_SRC.2 is set by top-level configure/makefile process.
471 SQLITE3_SRC. = $(SRCDIR.extsrc)/sqlite3.c
472 SQLITE3_SRC = $(SQLITE3_SRC.$(SQLITE3_ORIGIN))
473 SQLITE3_SHELL_SRC.0 = $(SRCDIR.extsrc)/shell.c
474 SQLITE3_SHELL_SRC.1 = $(SRCDIR.extsrc)/shell-see.c
475 # SQLITE3_SHELL_SRC.2 comes from the configure process
476 SQLITE3_SHELL_SRC. = $(SRCDIR.extsrc)/shell.c
477 SQLITE3_SHELL_SRC = $(SQLITE3_SHELL_SRC.$(SQLITE3_ORIGIN))
478 SEE_FLAGS.0 =
479 SEE_FLAGS.1 = -DSQLITE_HAS_CODEC -DSQLITE_SHELL_DBKEY_PROC=fossil_key
480 SEE_FLAGS. =
481 SEE_FLAGS = $(SEE_FLAGS.$(USE_SEE))
@@ -474,10 +484,11 @@
484 writeln [string map [list <<<NEXT_LINE>>> \\] {
485 EXTRAOBJ = <<<NEXT_LINE>>>
486 $(SQLITE3_OBJ.$(SQLITE3_ORIGIN)) <<<NEXT_LINE>>>
487 $(MINIZ_OBJ.$(FOSSIL_ENABLE_MINIZ)) <<<NEXT_LINE>>>
488 $(LINENOISE_OBJ.$(USE_LINENOISE)) <<<NEXT_LINE>>>
489 $(OBJDIR)/pikchr.o <<<NEXT_LINE>>>
490 $(OBJDIR)/shell.o <<<NEXT_LINE>>>
491 $(OBJDIR)/th.o <<<NEXT_LINE>>>
492 $(OBJDIR)/th_lang.o <<<NEXT_LINE>>>
493 $(OBJDIR)/th_tcl.o <<<NEXT_LINE>>>
494 $(OBJDIR)/cson_amalgamation.o
@@ -501,14 +512,18 @@
512
513 set mhargs {}
514 foreach s [lsort $src] {
515 append mhargs "\$(OBJDIR)/${s}_.c:\$(OBJDIR)/$s.h <<<NEXT_LINE>>>"
516 set extra_h($s) { }
517 }
518 foreach s [lsort $src_ext] {
519 append mhargs "\$(SRCDIR.extsrc)/${s}.c:\$(OBJDIR)/$s.h <<<NEXT_LINE>>>"
520 set extra_h($s) { }
521 }
522 append mhargs "\$(SRCDIR.extsrc)/sqlite3.h <<<NEXT_LINE>>>"
523 append mhargs "\$(SRCDIR)/th.h <<<NEXT_LINE>>>"
524 #append mhargs "\$(SRCDIR.extsrc)/cson_amalgamation.h <<<NEXT_LINE>>>"
525 append mhargs "\$(OBJDIR)/VERSION.h "
526 set mhargs [string map [list <<<NEXT_LINE>>> \\\n\t] $mhargs]
527 writeln "\$(OBJDIR)/page_index.h: \$(TRANS_SRC) \$(OBJDIR)/mkindex"
528 writeln "\t\$(OBJDIR)/mkindex \$(TRANS_SRC) >\$@\n"
529
@@ -538,12 +553,12 @@
553 writeln "\t\t-c \$(SQLITE3_SRC) -o \$@"
554
555 writeln "\$(OBJDIR)/shell.o:\t\$(SQLITE3_SHELL_SRC) \$(SRCDIR.extsrc)/sqlite3.h"
556 writeln "\t\$(XTCC) \$(SHELL_OPTIONS) \$(SHELL_CFLAGS) \$(SEE_FLAGS) \$(LINENOISE_DEF.\$(USE_LINENOISE)) -c \$(SQLITE3_SHELL_SRC) -o \$@\n"
557
558 writeln "\$(OBJDIR)/linenoise.o:\t\$(SRCDIR.extsrc)/linenoise.c \$(SRCDIR.extsrc)/linenoise.h"
559 writeln "\t\$(XTCC) -c \$(SRCDIR.extsrc)/linenoise.c -o \$@\n"
560
561 writeln "\$(OBJDIR)/th.o:\t\$(SRCDIR)/th.c"
562 writeln "\t\$(XTCC) -c \$(SRCDIR)/th.c -o \$@\n"
563
564 writeln "\$(OBJDIR)/th_lang.o:\t\$(SRCDIR)/th_lang.c"
@@ -551,15 +566,18 @@
566
567 writeln "\$(OBJDIR)/th_tcl.o:\t\$(SRCDIR)/th_tcl.c"
568 writeln "\t\$(XTCC) -c \$(SRCDIR)/th_tcl.c -o \$@\n"
569
570 writeln {
571 $(OBJDIR)/miniz.o: $(SRCDIR.extsrc)/miniz.c
572 $(XTCC) $(MINIZ_OPTIONS) -c $(SRCDIR.extsrc)/miniz.c -o $@
573
574 $(OBJDIR)/pikchr.o: $(SRCDIR.extsrc)/pikchr.c
575 $(XTCC) -c $(SRCDIR.extsrc)/pikchr.c -o $@
576
577 $(OBJDIR)/cson_amalgamation.o: $(SRCDIR.extsrc)/cson_amalgamation.c
578 $(XTCC) -c $(SRCDIR.extsrc)/cson_amalgamation.c -o $@
579
580 #
581 # The list of all the targets that do not correspond to real files. This stops
582 # 'make' from getting confused when someone makes an error in a rule.
583 #
@@ -1068,16 +1086,16 @@
1086 writeln {
1087 all: $(OBJDIR) $(APPNAME)
1088
1089 $(OBJDIR)/fossil.o: $(SRCDIR)/../win/fossil.rc $(OBJDIR)/VERSION.h
1090 ifdef USE_WINDOWS
1091 $(CAT) $(subst /,\,$(SRCDIR.extsrc)\miniz.c) | $(GREP) "define MZ_VERSION" > $(subst /,\,$(OBJDIR)\minizver.h)
1092 $(CP) $(subst /,\,$(SRCDIR)\..\win\fossil.rc) $(subst /,\,$(OBJDIR))
1093 $(CP) $(subst /,\,$(SRCDIR)\..\win\fossil.ico) $(subst /,\,$(OBJDIR))
1094 $(CP) $(subst /,\,$(SRCDIR)\..\win\fossil.exe.manifest) $(subst /,\,$(OBJDIR))
1095 else
1096 $(CAT) $(SRCDIR.extsrc)/miniz.c | $(GREP) "define MZ_VERSION" > $(OBJDIR)/minizver.h
1097 $(CP) $(SRCDIR)/../win/fossil.rc $(OBJDIR)
1098 $(CP) $(SRCDIR)/../win/fossil.ico $(OBJDIR)
1099 $(CP) $(SRCDIR)/../win/fossil.exe.manifest $(OBJDIR)
1100 endif
1101 $(RCC) $(OBJDIR)/fossil.rc -o $(OBJDIR)/fossil.o
@@ -1155,14 +1173,14 @@
1173 SQLITE3_SRC.0 = $(SRCDIR.extsrc)/sqlite3.c
1174 SQLITE3_SRC.1 = $(SRCDIR.extsrc)/sqlite3-see.c
1175 # SQLITE3_SRC.2 is set by top-level configure/makefile process.
1176 SQLITE3_SRC. = $(SRCDIR.extsrc)/sqlite3.c
1177 SQLITE3_SRC = $(SRCDIR)/$(SQLITE3_SRC.$(SQLITE3_ORIGIN))
1178 SQLITE3_SHELL_SRC.0 = $(SRCDIR.extsrc)/shell.c
1179 SQLITE3_SHELL_SRC.1 = $(SRCDIR.extsrc)/shell-see.c
1180 # SQLITE3_SHELL_SRC.2 comes from the configure process
1181 SQLITE3_SHELL_SRC. = $(SRCDIR.extsrc)/shell.c
1182 SQLITE3_SHELL_SRC = $(SQLITE3_SHELL_SRC.$(SQLITE3_ORIGIN))
1183 SEE_FLAGS.0 =
1184 SEE_FLAGS.1 = -DSQLITE_HAS_CODEC -DSQLITE_SHELL_DBKEY_PROC=fossil_key
1185 SEE_FLAGS. =
1186 SEE_FLAGS = $(SEE_FLAGS.$(USE_SEE))
@@ -1248,10 +1266,14 @@
1266 set mhargs {}
1267 foreach s [lsort $src] {
1268 if {[string length $mhargs] > 0} {append mhargs " \\\n\t\t"}
1269 append mhargs "\$(OBJDIR)/${s}_.c:\$(OBJDIR)/$s.h"
1270 set extra_h($s) { }
1271 }
1272 foreach s [lsort $src_ext] {
1273 append mhargs "\$(SRCDIR.extsrc)/${s}.c:\$(OBJDIR)/$s.h <<<NEXT_LINE>>>"
1274 set extra_h($s) { }
1275 }
1276 append mhargs " \\\n\t\t\$(SRCDIR.extsrc)/sqlite3.h"
1277 append mhargs " \\\n\t\t\$(SRCDIR)/th.h"
1278 append mhargs " \\\n\t\t\$(OBJDIR)/VERSION.h"
1279 writeln "\$(OBJDIR)/page_index.h: \$(TRANS_SRC) \$(MKINDEX)"
@@ -1298,12 +1320,12 @@
1320
1321 writeln "\$(OBJDIR)/sqlite3.o:\t\$(SQLITE3_SRC) \$(SRCDIR)/../win/Makefile.mingw"
1322 writeln "\t\$(XTCC) \$(SQLITE_OPTIONS) \$(SQLITE_CFLAGS) \$(SEE_FLAGS) \\"
1323 writeln "\t\t-c \$(SQLITE3_SRC) -o \$@\n"
1324
1325 writeln "\$(OBJDIR)/cson_amalgamation.o:\t\$(SRCDIR.extsrc)/cson_amalgamation.c"
1326 writeln "\t\$(XTCC) -c \$(SRCDIR.extsrc)/cson_amalgamation.c -o \$@\n"
1327 writeln "\$(OBJDIR)/json.o \$(OBJDIR)/json_artifact.o \$(OBJDIR)/json_branch.o \$(OBJDIR)/json_config.o \$(OBJDIR)/json_diff.o \$(OBJDIR)/json_dir.o \$(OBJDIR)/jsos_finfo.o \$(OBJDIR)/json_login.o \$(OBJDIR)/json_query.o \$(OBJDIR)/json_report.o \$(OBJDIR)/json_status.o \$(OBJDIR)/json_tag.o \$(OBJDIR)/json_timeline.o \$(OBJDIR)/json_user.o \$(OBJDIR)/json_wiki.o : \$(SRCDIR)/json_detail.h\n"
1328
1329 writeln "\$(OBJDIR)/shell.o:\t\$(SQLITE3_SHELL_SRC) \$(SRCDIR.extsrc)/sqlite3.h \$(SRCDIR)/../win/Makefile.mingw"
1330 writeln "\t\$(XTCC) \$(SHELL_OPTIONS) \$(SHELL_CFLAGS) \$(SEE_FLAGS) -c \$(SQLITE3_SHELL_SRC) -o \$@\n"
1331
@@ -1314,12 +1336,15 @@
1336 writeln "\t\$(XTCC) -c \$(SRCDIR)/th_lang.c -o \$@\n"
1337
1338 writeln "\$(OBJDIR)/th_tcl.o:\t\$(SRCDIR)/th_tcl.c"
1339 writeln "\t\$(XTCC) -c \$(SRCDIR)/th_tcl.c -o \$@\n"
1340
1341 writeln "\$(OBJDIR)/miniz.o:\t\$(SRCDIR.extsrc)/miniz.c"
1342 writeln "\t\$(XTCC) \$(MINIZ_OPTIONS) -c \$(SRCDIR.extsrc)/miniz.c -o \$@\n"
1343
1344 writeln "\$(OBJDIR)/pikchr.o:\t\$(SRCDIR.extsrc)/pikchr.c"
1345 writeln "\t\$(XTCC) -c \$(SRCDIR.extsrc)/pikchr.c -o \$@\n"
1346
1347 close $output_file
1348 #
1349 # End of the win/Makefile.mingw output
1350 ##############################################################################
@@ -1417,23 +1442,23 @@
1442 $(BCC) -o$@ $**
1443
1444 codecheck1$E: $(SRCDIR.tools)\codecheck1.c
1445 $(BCC) -o$@ $**
1446
1447 $(OBJDIR)\shell$O : $(SRCDIR.extsrc)\shell.c
1448 $(TCC) -o$@ -c $(SHELL_OPTIONS) $(SQLITE_OPTIONS) $(SHELL_CFLAGS) $**
1449
1450 $(OBJDIR)\sqlite3$O : $(SRCDIR.extsrc)\sqlite3.c
1451 $(TCC) -o$@ -c $(SQLITE_OPTIONS) $(SQLITE_CFLAGS) $**
1452
1453 $(OBJDIR)\th$O : $(SRCDIR)\th.c
1454 $(TCC) -o$@ -c $**
1455
1456 $(OBJDIR)\th_lang$O : $(SRCDIR)\th_lang.c
1457 $(TCC) -o$@ -c $**
1458
1459 $(OBJDIR)\cson_amalgamation.h : $(SRCDIR.extsrc)\cson_amalgamation.h
1460 cp $@ $@
1461
1462 VERSION.h : mkversion$E $B\manifest.uuid $B\manifest $B\VERSION
1463 +$** > $@
1464
@@ -1476,11 +1501,11 @@
1501
1502 writeln -nonewline "headers: makeheaders\$E page_index.h builtin_data.h VERSION.h\n\t +makeheaders\$E "
1503 foreach s [lsort $src] {
1504 writeln -nonewline "${s}_.c:$s.h "
1505 }
1506 writeln "\$(SRCDIR.extsrc)\\sqlite3.h \$(SRCDIR)\\th.h VERSION.h \$(SRCDIR.extsrc)\\cson_amalgamation.h"
1507 writeln "\t@copy /Y nul: headers"
1508
1509 close $output_file
1510 #
1511 # End of the win/Makefile.dmc output
@@ -1503,10 +1528,11 @@
1528 # file, edit "makemake.tcl" then run "tclsh makemake.tcl"
1529 # to regenerate this file.
1530 #
1531 B = ..
1532 SRCDIR = $(B)\src
1533 SRCDIRX = $(B)\extsrc
1534 T = .
1535 OBJDIR = $(T)
1536 OX = $(OBJDIR)
1537 O = .obj
1538 E = .exe
@@ -1827,11 +1853,11 @@
1853 }
1854 set s [regsub -all / $s \\]
1855 writeln -nonewline "\"\$(SRCDIR)\\${s}\""; incr i
1856 }
1857 writeln "\n"
1858 set AdditionalObj [list shell sqlite3 th th_lang th_tcl cson_amalgamation pikchr]
1859 writeln -nonewline "OBJ = "
1860 set i 0
1861 foreach s [lsort [concat $src $AdditionalObj]] {
1862 if {$i > 0} {
1863 writeln " \\"
@@ -1952,11 +1978,11 @@
1978 SEE_FLAGS = /DSQLITE_HAS_CODEC=1 /DSQLITE_SHELL_DBKEY_PROC=fossil_key
1979 SQLITE3_SHELL_SRC = $(SRCDIR)\shell-see.c
1980 SQLITE3_SRC = $(SRCDIR.extsrc)\sqlite3-see.c
1981 !else
1982 SEE_FLAGS =
1983 SQLITE3_SHELL_SRC = $(SRCDIR.extsrc)\shell.c
1984 SQLITE3_SRC = $(SRCDIR.extsrc)\sqlite3.c
1985 !endif
1986
1987 "$(OX)\shell$O" : "$(SQLITE3_SHELL_SRC)" "$(B)\win\Makefile.msc"
1988 $(TCC) /Fo$@ /Fd$(@D)\ $(SHELL_OPTIONS) $(SQLITE_OPTIONS) $(SHELL_CFLAGS) $(SEE_FLAGS) -c "$(SQLITE3_SHELL_SRC)"
@@ -1971,20 +1997,23 @@
1997 $(TCC) /Fo$@ /Fd$(@D)\ -c $**
1998
1999 "$(OX)\th_tcl$O" : "$(SRCDIR)\th_tcl.c"
2000 $(TCC) /Fo$@ /Fd$(@D)\ -c $**
2001
2002 "$(OX)\miniz$O" : "$(SRCDIR.extsrc)\miniz.c"
2003 $(TCC) /Fo$@ /Fd$(@D)\ -c $(MINIZ_OPTIONS) $**
2004
2005 "$(OX)\pikchr$O" : "$(SRCDIR.extsrc)" "$(B)\win\Makefile.msc"
2006 $(TCC) /Fo$@ /Fd$(@D)\ -c $**
2007
2008 "$(OX)\VERSION.h" : "$(OBJDIR)\mkversion$E" "$(B)\manifest.uuid" "$(B)\manifest" "$(B)\VERSION" "$(B)\phony.h"
2009 "$(OBJDIR)\mkversion$E" "$(B)\manifest.uuid" "$(B)\manifest" "$(B)\VERSION" > $@
2010
2011 "$(B)\phony.h" :
2012 rem Force rebuild of VERSION.h whenever nmake is run
2013
2014 "$(OX)\cson_amalgamation$O" : "$(SRCDIR.extsrc)\cson_amalgamation.c"
2015 $(TCC) /Fo$@ /Fd$(@D)\ -c $**
2016
2017 "$(OX)\page_index.h": "$(OBJDIR)\mkindex$E" $(SRC)
2018 $** > $@
2019
@@ -2070,11 +2099,11 @@
2099 writeln -nonewline "\"\$(OX)\\${s}_.c\":\"\$(OX)\\$s.h\""; incr i
2100 }
2101 writeln " \\\n\t\t\t\"\$(SRCDIR.extsrc)\\sqlite3.h\" \\"
2102 writeln "\t\t\t\"\$(SRCDIR)\\th.h\" \\"
2103 writeln "\t\t\t\"\$(OX)\\VERSION.h\" \\"
2104 writeln "\t\t\t\"\$(SRCDIR.extsrc)\\cson_amalgamation.h\""
2105 writeln "\t@copy /Y nul: $@"
2106
2107
2108 close $output_file
2109 #
@@ -2145,10 +2174,11 @@
2174 endif
2175
2176 # define the project directories
2177 B=..
2178 SRCDIR=$(B)/src/
2179 SRCDIRX=$(B)/extsrc/
2180 WINDIR=$(B)/win/
2181 ZLIBSRCDIR=../../zlib/
2182
2183 # define linker command and options
2184 LINK=$(PellesCDir)/bin/polink.exe
@@ -2158,11 +2188,11 @@
2188 # the fossil binary. Some special definitions follow for
2189 # special files follow
2190 CC=$(PellesCDir)\bin\pocc.exe
2191 DEFINES=-D_pgmptr=g.argv[0]
2192 CCFLAGS=-T$(TARGETMACHINE_CC)-coff -Ot -W2 -Gd -Go -Ze -MT $(DEFINES)
2193 INCLUDE=/I $(PellesCDir)\Include\Win /I $(PellesCDir)\Include /I $(ZLIBSRCDIR) /I $(SRCDIR) /I $(SRCDIRX)
2194
2195 # define commands for building the windows resource files
2196 RESOURCE=fossil.res
2197 RC=$(PellesCDir)\bin\porc.exe
2198 RCFLAGS=$(INCLUDE) -D__POCC__=1 -D_M_X$(TARGETVERSION)
@@ -2169,21 +2199,21 @@
2199
2200 # define the special utilities files, needed to generate
2201 # the automatically generated source files
2202 UTILS=translate.exe mkindex.exe makeheaders.exe mkbuiltin.exe
2203 UTILS_OBJ=$(UTILS:.exe=.obj)
2204 UTILS_SRC=$(foreach uf,$(UTILS),$(SRCDIRX)$(uf:.exe=.c))
2205
2206 # define the SQLite files, which need special flags on compile
2207 SQLITESRC=sqlite3.c
2208 ORIGSQLITESRC=$(foreach sf,$(SQLITESRC),$(SRCDIRX)$(sf))
2209 SQLITEOBJ=$(foreach sf,$(SQLITESRC),$(sf:.c=.obj))
2210 SQLITEDEFINES=<<<SQLITE_OPTIONS>>>
2211
2212 # define the SQLite shell files, which need special flags on compile
2213 SQLITESHELLSRC=shell.c
2214 ORIGSQLITESHELLSRC=$(foreach sf,$(SQLITESHELLSRC),$(SRCDIRX)$(sf))
2215 SQLITESHELLOBJ=$(foreach sf,$(SQLITESHELLSRC),$(sf:.c=.obj))
2216 SQLITESHELLDEFINES=<<<SHELL_OPTIONS>>>
2217
2218 # define the th scripting files, which need special flags on compile
2219 THSRC=th.c th_lang.c
@@ -2249,14 +2279,14 @@
2279 # compile C sources with relevant options
2280
2281 $(TRANSLATEDOBJ): %_.obj: %_.c %.h
2282 $(CC) $(CCFLAGS) $(INCLUDE) "$<" -Fo"$@"
2283
2284 $(SQLITEOBJ): %.obj: $(SRCDIRX)%.c $(SRCDIRX)%.h
2285 $(CC) $(CCFLAGS) $(SQLITEDEFINES) $(INCLUDE) "$<" -Fo"$@"
2286
2287 $(SQLITESHELLOBJ): %.obj: $(SRCDIRX)%.c
2288 $(CC) $(CCFLAGS) $(SQLITESHELLDEFINES) $(INCLUDE) "$<" -Fo"$@"
2289
2290 $(THOBJ): %.obj: $(SRCDIR)%.c $(SRCDIR)th.h
2291 $(CC) $(CCFLAGS) $(INCLUDE) "$<" -Fo"$@"
2292
2293
--- win/Makefile.PellesCGMake
+++ win/Makefile.PellesCGMake
@@ -53,10 +53,11 @@
5353
endif
5454
5555
# define the project directories
5656
B=..
5757
SRCDIR=$(B)/src/
58
+SRCDIRX=$(B)/extsrc/
5859
WINDIR=$(B)/win/
5960
ZLIBSRCDIR=../../zlib/
6061
6162
# define linker command and options
6263
LINK=$(PellesCDir)/bin/polink.exe
@@ -66,11 +67,11 @@
6667
# the fossil binary. Some special definitions follow for
6768
# special files follow
6869
CC=$(PellesCDir)\bin\pocc.exe
6970
DEFINES=-D_pgmptr=g.argv[0]
7071
CCFLAGS=-T$(TARGETMACHINE_CC)-coff -Ot -W2 -Gd -Go -Ze -MT $(DEFINES)
71
-INCLUDE=/I $(PellesCDir)\Include\Win /I $(PellesCDir)\Include /I $(ZLIBSRCDIR) /I $(SRCDIR)
72
+INCLUDE=/I $(PellesCDir)\Include\Win /I $(PellesCDir)\Include /I $(ZLIBSRCDIR) /I $(SRCDIR) /I $(SRCDIRX)
7273
7374
# define commands for building the windows resource files
7475
RESOURCE=fossil.res
7576
RC=$(PellesCDir)\bin\porc.exe
7677
RCFLAGS=$(INCLUDE) -D__POCC__=1 -D_M_X$(TARGETVERSION)
@@ -77,21 +78,21 @@
7778
7879
# define the special utilities files, needed to generate
7980
# the automatically generated source files
8081
UTILS=translate.exe mkindex.exe makeheaders.exe mkbuiltin.exe
8182
UTILS_OBJ=$(UTILS:.exe=.obj)
82
-UTILS_SRC=$(foreach uf,$(UTILS),$(SRCDIR)$(uf:.exe=.c))
83
+UTILS_SRC=$(foreach uf,$(UTILS),$(SRCDIRX)$(uf:.exe=.c))
8384
8485
# define the SQLite files, which need special flags on compile
8586
SQLITESRC=sqlite3.c
86
-ORIGSQLITESRC=$(foreach sf,$(SQLITESRC),$(SRCDIR)$(sf))
87
+ORIGSQLITESRC=$(foreach sf,$(SQLITESRC),$(SRCDIRX)$(sf))
8788
SQLITEOBJ=$(foreach sf,$(SQLITESRC),$(sf:.c=.obj))
8889
SQLITEDEFINES=-DNDEBUG=1 -DSQLITE_DQS=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_USE_ALLOCA -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_INTROSPECTION_PRAGMAS -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_TRUSTED_SCHEMA=0 -DSQLITE_WIN32_NO_ANSI
8990
9091
# define the SQLite shell files, which need special flags on compile
9192
SQLITESHELLSRC=shell.c
92
-ORIGSQLITESHELLSRC=$(foreach sf,$(SQLITESHELLSRC),$(SRCDIR)$(sf))
93
+ORIGSQLITESHELLSRC=$(foreach sf,$(SQLITESHELLSRC),$(SRCDIRX)$(sf))
9394
SQLITESHELLOBJ=$(foreach sf,$(SQLITESHELLSRC),$(sf:.c=.obj))
9495
SQLITESHELLDEFINES=-DNDEBUG=1 -DSQLITE_DQS=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_USE_ALLOCA -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_INTROSPECTION_PRAGMAS -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_TRUSTED_SCHEMA=0 -Dmain=sqlite3_shell -DSQLITE_SHELL_IS_UTF8=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=sqlcmd_get_dbname -DSQLITE_SHELL_INIT_PROC=sqlcmd_init_proc -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen
9596
9697
# define the th scripting files, which need special flags on compile
9798
THSRC=th.c th_lang.c
@@ -157,14 +158,14 @@
157158
# compile C sources with relevant options
158159
159160
$(TRANSLATEDOBJ): %_.obj: %_.c %.h
160161
$(CC) $(CCFLAGS) $(INCLUDE) "$<" -Fo"$@"
161162
162
-$(SQLITEOBJ): %.obj: $(SRCDIR)%.c $(SRCDIR)%.h
163
+$(SQLITEOBJ): %.obj: $(SRCDIRX)%.c $(SRCDIRX)%.h
163164
$(CC) $(CCFLAGS) $(SQLITEDEFINES) $(INCLUDE) "$<" -Fo"$@"
164165
165
-$(SQLITESHELLOBJ): %.obj: $(SRCDIR)%.c
166
+$(SQLITESHELLOBJ): %.obj: $(SRCDIRX)%.c
166167
$(CC) $(CCFLAGS) $(SQLITESHELLDEFINES) $(INCLUDE) "$<" -Fo"$@"
167168
168169
$(THOBJ): %.obj: $(SRCDIR)%.c $(SRCDIR)th.h
169170
$(CC) $(CCFLAGS) $(INCLUDE) "$<" -Fo"$@"
170171
171172
--- win/Makefile.PellesCGMake
+++ win/Makefile.PellesCGMake
@@ -53,10 +53,11 @@
53 endif
54
55 # define the project directories
56 B=..
57 SRCDIR=$(B)/src/
 
58 WINDIR=$(B)/win/
59 ZLIBSRCDIR=../../zlib/
60
61 # define linker command and options
62 LINK=$(PellesCDir)/bin/polink.exe
@@ -66,11 +67,11 @@
66 # the fossil binary. Some special definitions follow for
67 # special files follow
68 CC=$(PellesCDir)\bin\pocc.exe
69 DEFINES=-D_pgmptr=g.argv[0]
70 CCFLAGS=-T$(TARGETMACHINE_CC)-coff -Ot -W2 -Gd -Go -Ze -MT $(DEFINES)
71 INCLUDE=/I $(PellesCDir)\Include\Win /I $(PellesCDir)\Include /I $(ZLIBSRCDIR) /I $(SRCDIR)
72
73 # define commands for building the windows resource files
74 RESOURCE=fossil.res
75 RC=$(PellesCDir)\bin\porc.exe
76 RCFLAGS=$(INCLUDE) -D__POCC__=1 -D_M_X$(TARGETVERSION)
@@ -77,21 +78,21 @@
77
78 # define the special utilities files, needed to generate
79 # the automatically generated source files
80 UTILS=translate.exe mkindex.exe makeheaders.exe mkbuiltin.exe
81 UTILS_OBJ=$(UTILS:.exe=.obj)
82 UTILS_SRC=$(foreach uf,$(UTILS),$(SRCDIR)$(uf:.exe=.c))
83
84 # define the SQLite files, which need special flags on compile
85 SQLITESRC=sqlite3.c
86 ORIGSQLITESRC=$(foreach sf,$(SQLITESRC),$(SRCDIR)$(sf))
87 SQLITEOBJ=$(foreach sf,$(SQLITESRC),$(sf:.c=.obj))
88 SQLITEDEFINES=-DNDEBUG=1 -DSQLITE_DQS=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_USE_ALLOCA -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_INTROSPECTION_PRAGMAS -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_TRUSTED_SCHEMA=0 -DSQLITE_WIN32_NO_ANSI
89
90 # define the SQLite shell files, which need special flags on compile
91 SQLITESHELLSRC=shell.c
92 ORIGSQLITESHELLSRC=$(foreach sf,$(SQLITESHELLSRC),$(SRCDIR)$(sf))
93 SQLITESHELLOBJ=$(foreach sf,$(SQLITESHELLSRC),$(sf:.c=.obj))
94 SQLITESHELLDEFINES=-DNDEBUG=1 -DSQLITE_DQS=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_USE_ALLOCA -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_INTROSPECTION_PRAGMAS -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_TRUSTED_SCHEMA=0 -Dmain=sqlite3_shell -DSQLITE_SHELL_IS_UTF8=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=sqlcmd_get_dbname -DSQLITE_SHELL_INIT_PROC=sqlcmd_init_proc -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen
95
96 # define the th scripting files, which need special flags on compile
97 THSRC=th.c th_lang.c
@@ -157,14 +158,14 @@
157 # compile C sources with relevant options
158
159 $(TRANSLATEDOBJ): %_.obj: %_.c %.h
160 $(CC) $(CCFLAGS) $(INCLUDE) "$<" -Fo"$@"
161
162 $(SQLITEOBJ): %.obj: $(SRCDIR)%.c $(SRCDIR)%.h
163 $(CC) $(CCFLAGS) $(SQLITEDEFINES) $(INCLUDE) "$<" -Fo"$@"
164
165 $(SQLITESHELLOBJ): %.obj: $(SRCDIR)%.c
166 $(CC) $(CCFLAGS) $(SQLITESHELLDEFINES) $(INCLUDE) "$<" -Fo"$@"
167
168 $(THOBJ): %.obj: $(SRCDIR)%.c $(SRCDIR)th.h
169 $(CC) $(CCFLAGS) $(INCLUDE) "$<" -Fo"$@"
170
171
--- win/Makefile.PellesCGMake
+++ win/Makefile.PellesCGMake
@@ -53,10 +53,11 @@
53 endif
54
55 # define the project directories
56 B=..
57 SRCDIR=$(B)/src/
58 SRCDIRX=$(B)/extsrc/
59 WINDIR=$(B)/win/
60 ZLIBSRCDIR=../../zlib/
61
62 # define linker command and options
63 LINK=$(PellesCDir)/bin/polink.exe
@@ -66,11 +67,11 @@
67 # the fossil binary. Some special definitions follow for
68 # special files follow
69 CC=$(PellesCDir)\bin\pocc.exe
70 DEFINES=-D_pgmptr=g.argv[0]
71 CCFLAGS=-T$(TARGETMACHINE_CC)-coff -Ot -W2 -Gd -Go -Ze -MT $(DEFINES)
72 INCLUDE=/I $(PellesCDir)\Include\Win /I $(PellesCDir)\Include /I $(ZLIBSRCDIR) /I $(SRCDIR) /I $(SRCDIRX)
73
74 # define commands for building the windows resource files
75 RESOURCE=fossil.res
76 RC=$(PellesCDir)\bin\porc.exe
77 RCFLAGS=$(INCLUDE) -D__POCC__=1 -D_M_X$(TARGETVERSION)
@@ -77,21 +78,21 @@
78
79 # define the special utilities files, needed to generate
80 # the automatically generated source files
81 UTILS=translate.exe mkindex.exe makeheaders.exe mkbuiltin.exe
82 UTILS_OBJ=$(UTILS:.exe=.obj)
83 UTILS_SRC=$(foreach uf,$(UTILS),$(SRCDIRX)$(uf:.exe=.c))
84
85 # define the SQLite files, which need special flags on compile
86 SQLITESRC=sqlite3.c
87 ORIGSQLITESRC=$(foreach sf,$(SQLITESRC),$(SRCDIRX)$(sf))
88 SQLITEOBJ=$(foreach sf,$(SQLITESRC),$(sf:.c=.obj))
89 SQLITEDEFINES=-DNDEBUG=1 -DSQLITE_DQS=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_USE_ALLOCA -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_INTROSPECTION_PRAGMAS -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_TRUSTED_SCHEMA=0 -DSQLITE_WIN32_NO_ANSI
90
91 # define the SQLite shell files, which need special flags on compile
92 SQLITESHELLSRC=shell.c
93 ORIGSQLITESHELLSRC=$(foreach sf,$(SQLITESHELLSRC),$(SRCDIRX)$(sf))
94 SQLITESHELLOBJ=$(foreach sf,$(SQLITESHELLSRC),$(sf:.c=.obj))
95 SQLITESHELLDEFINES=-DNDEBUG=1 -DSQLITE_DQS=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_USE_ALLOCA -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_INTROSPECTION_PRAGMAS -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_TRUSTED_SCHEMA=0 -Dmain=sqlite3_shell -DSQLITE_SHELL_IS_UTF8=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=sqlcmd_get_dbname -DSQLITE_SHELL_INIT_PROC=sqlcmd_init_proc -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen
96
97 # define the th scripting files, which need special flags on compile
98 THSRC=th.c th_lang.c
@@ -157,14 +158,14 @@
158 # compile C sources with relevant options
159
160 $(TRANSLATEDOBJ): %_.obj: %_.c %.h
161 $(CC) $(CCFLAGS) $(INCLUDE) "$<" -Fo"$@"
162
163 $(SQLITEOBJ): %.obj: $(SRCDIRX)%.c $(SRCDIRX)%.h
164 $(CC) $(CCFLAGS) $(SQLITEDEFINES) $(INCLUDE) "$<" -Fo"$@"
165
166 $(SQLITESHELLOBJ): %.obj: $(SRCDIRX)%.c
167 $(CC) $(CCFLAGS) $(SQLITESHELLDEFINES) $(INCLUDE) "$<" -Fo"$@"
168
169 $(THOBJ): %.obj: $(SRCDIR)%.c $(SRCDIR)th.h
170 $(CC) $(CCFLAGS) $(INCLUDE) "$<" -Fo"$@"
171
172
+7 -13
--- win/Makefile.dmc
+++ win/Makefile.dmc
@@ -28,13 +28,13 @@
2828
2929
SQLITE_OPTIONS = -DNDEBUG=1 -DSQLITE_DQS=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_USE_ALLOCA -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_INTROSPECTION_PRAGMAS -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_TRUSTED_SCHEMA=0
3030
3131
SHELL_OPTIONS = -DNDEBUG=1 -DSQLITE_DQS=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_USE_ALLOCA -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_INTROSPECTION_PRAGMAS -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_TRUSTED_SCHEMA=0 -Dmain=sqlite3_shell -DSQLITE_SHELL_IS_UTF8=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=sqlcmd_get_dbname -DSQLITE_SHELL_INIT_PROC=sqlcmd_init_proc -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen
3232
33
-SRC = add_.c ajax_.c alerts_.c allrepo_.c attach_.c backlink_.c backoffice_.c bag_.c bisect_.c blob_.c branch_.c browse_.c builtin_.c bundle_.c cache_.c capabilities_.c captcha_.c cgi_.c chat_.c checkin_.c checkout_.c clearsign_.c clone_.c color_.c comformat_.c configure_.c content_.c cookies_.c db_.c delta_.c deltacmd_.c deltafunc_.c descendants_.c diff_.c diffcmd_.c dispatch_.c doc_.c encode_.c etag_.c event_.c export_.c extcgi_.c file_.c fileedit_.c finfo_.c foci_.c forum_.c fshell_.c fusefs_.c fuzz_.c glob_.c graph_.c gzip_.c hname_.c hook_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c interwiki_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_status_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c loadctrl_.c login_.c lookslike_.c main_.c manifest_.c markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c patch_.c path_.c piechart_.c pikchr_.c pikchrshow_.c pivot_.c popen_.c pqueue_.c printf_.c publish_.c purge_.c rebuild_.c regexp_.c repolist_.c report_.c rss_.c schema_.c search_.c security_audit_.c setup_.c setupuser_.c sha1_.c sha1hard_.c sha3_.c shun_.c sitemap_.c skins_.c smtp_.c sqlcmd_.c stash_.c stat_.c statrep_.c style_.c sync_.c tag_.c tar_.c terminal_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c unversioned_.c update_.c url_.c user_.c utf8_.c util_.c verify_.c vfile_.c wiki_.c wikiformat_.c winfile_.c winhttp_.c xfer_.c xfersetup_.c zip_.c
33
+SRC = add_.c ajax_.c alerts_.c allrepo_.c attach_.c backlink_.c backoffice_.c bag_.c bisect_.c blob_.c branch_.c browse_.c builtin_.c bundle_.c cache_.c capabilities_.c captcha_.c cgi_.c chat_.c checkin_.c checkout_.c clearsign_.c clone_.c color_.c comformat_.c configure_.c content_.c cookies_.c db_.c delta_.c deltacmd_.c deltafunc_.c descendants_.c diff_.c diffcmd_.c dispatch_.c doc_.c encode_.c etag_.c event_.c export_.c extcgi_.c file_.c fileedit_.c finfo_.c foci_.c forum_.c fshell_.c fusefs_.c fuzz_.c glob_.c graph_.c gzip_.c hname_.c hook_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c interwiki_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_status_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c loadctrl_.c login_.c lookslike_.c main_.c manifest_.c markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c patch_.c path_.c piechart_.c pikchrshow_.c pivot_.c popen_.c pqueue_.c printf_.c publish_.c purge_.c rebuild_.c regexp_.c repolist_.c report_.c rss_.c schema_.c search_.c security_audit_.c setup_.c setupuser_.c sha1_.c sha1hard_.c sha3_.c shun_.c sitemap_.c skins_.c smtp_.c sqlcmd_.c stash_.c stat_.c statrep_.c style_.c sync_.c tag_.c tar_.c terminal_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c unversioned_.c update_.c url_.c user_.c utf8_.c util_.c verify_.c vfile_.c wiki_.c wikiformat_.c winfile_.c winhttp_.c xfer_.c xfersetup_.c zip_.c
3434
35
-OBJ = $(OBJDIR)\add$O $(OBJDIR)\ajax$O $(OBJDIR)\alerts$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\backlink$O $(OBJDIR)\backoffice$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\builtin$O $(OBJDIR)\bundle$O $(OBJDIR)\cache$O $(OBJDIR)\capabilities$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\chat$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\color$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\cookies$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\deltafunc$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\dispatch$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\etag$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\extcgi$O $(OBJDIR)\file$O $(OBJDIR)\fileedit$O $(OBJDIR)\finfo$O $(OBJDIR)\foci$O $(OBJDIR)\forum$O $(OBJDIR)\fshell$O $(OBJDIR)\fusefs$O $(OBJDIR)\fuzz$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\hname$O $(OBJDIR)\hook$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\interwiki$O $(OBJDIR)\json$O $(OBJDIR)\json_artifact$O $(OBJDIR)\json_branch$O $(OBJDIR)\json_config$O $(OBJDIR)\json_diff$O $(OBJDIR)\json_dir$O $(OBJDIR)\json_finfo$O $(OBJDIR)\json_login$O $(OBJDIR)\json_query$O $(OBJDIR)\json_report$O $(OBJDIR)\json_status$O $(OBJDIR)\json_tag$O $(OBJDIR)\json_timeline$O $(OBJDIR)\json_user$O $(OBJDIR)\json_wiki$O $(OBJDIR)\leaf$O $(OBJDIR)\loadctrl$O $(OBJDIR)\login$O $(OBJDIR)\lookslike$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\markdown$O $(OBJDIR)\markdown_html$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\moderate$O $(OBJDIR)\name$O $(OBJDIR)\patch$O $(OBJDIR)\path$O $(OBJDIR)\piechart$O $(OBJDIR)\pikchr$O $(OBJDIR)\pikchrshow$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\publish$O $(OBJDIR)\purge$O $(OBJDIR)\rebuild$O $(OBJDIR)\regexp$O $(OBJDIR)\repolist$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\security_audit$O $(OBJDIR)\setup$O $(OBJDIR)\setupuser$O $(OBJDIR)\sha1$O $(OBJDIR)\sha1hard$O $(OBJDIR)\sha3$O $(OBJDIR)\shun$O $(OBJDIR)\sitemap$O $(OBJDIR)\skins$O $(OBJDIR)\smtp$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\statrep$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\terminal$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\unicode$O $(OBJDIR)\unversioned$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\utf8$O $(OBJDIR)\util$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winfile$O $(OBJDIR)\winhttp$O $(OBJDIR)\xfer$O $(OBJDIR)\xfersetup$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O
35
+OBJ = $(OBJDIR)\add$O $(OBJDIR)\ajax$O $(OBJDIR)\alerts$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\backlink$O $(OBJDIR)\backoffice$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\builtin$O $(OBJDIR)\bundle$O $(OBJDIR)\cache$O $(OBJDIR)\capabilities$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\chat$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\color$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\cookies$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\deltafunc$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\dispatch$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\etag$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\extcgi$O $(OBJDIR)\file$O $(OBJDIR)\fileedit$O $(OBJDIR)\finfo$O $(OBJDIR)\foci$O $(OBJDIR)\forum$O $(OBJDIR)\fshell$O $(OBJDIR)\fusefs$O $(OBJDIR)\fuzz$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\hname$O $(OBJDIR)\hook$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\interwiki$O $(OBJDIR)\json$O $(OBJDIR)\json_artifact$O $(OBJDIR)\json_branch$O $(OBJDIR)\json_config$O $(OBJDIR)\json_diff$O $(OBJDIR)\json_dir$O $(OBJDIR)\json_finfo$O $(OBJDIR)\json_login$O $(OBJDIR)\json_query$O $(OBJDIR)\json_report$O $(OBJDIR)\json_status$O $(OBJDIR)\json_tag$O $(OBJDIR)\json_timeline$O $(OBJDIR)\json_user$O $(OBJDIR)\json_wiki$O $(OBJDIR)\leaf$O $(OBJDIR)\loadctrl$O $(OBJDIR)\login$O $(OBJDIR)\lookslike$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\markdown$O $(OBJDIR)\markdown_html$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\moderate$O $(OBJDIR)\name$O $(OBJDIR)\patch$O $(OBJDIR)\path$O $(OBJDIR)\piechart$O $(OBJDIR)\pikchrshow$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\publish$O $(OBJDIR)\purge$O $(OBJDIR)\rebuild$O $(OBJDIR)\regexp$O $(OBJDIR)\repolist$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\security_audit$O $(OBJDIR)\setup$O $(OBJDIR)\setupuser$O $(OBJDIR)\sha1$O $(OBJDIR)\sha1hard$O $(OBJDIR)\sha3$O $(OBJDIR)\shun$O $(OBJDIR)\sitemap$O $(OBJDIR)\skins$O $(OBJDIR)\smtp$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\statrep$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\terminal$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\unicode$O $(OBJDIR)\unversioned$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\utf8$O $(OBJDIR)\util$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winfile$O $(OBJDIR)\winhttp$O $(OBJDIR)\xfer$O $(OBJDIR)\xfersetup$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O
3636
3737
3838
RC=$(DMDIR)\bin\rcc
3939
RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__
4040
@@ -49,11 +49,11 @@
4949
5050
$(OBJDIR)\fossil.res: $B\win\fossil.rc
5151
$(RC) $(RCFLAGS) -o$@ $**
5252
5353
$(OBJDIR)\link: $B\win\Makefile.dmc $(OBJDIR)\fossil.res
54
- +echo add ajax alerts allrepo attach backlink backoffice bag bisect blob branch browse builtin bundle cache capabilities captcha cgi chat checkin checkout clearsign clone color comformat configure content cookies db delta deltacmd deltafunc descendants diff diffcmd dispatch doc encode etag event export extcgi file fileedit finfo foci forum fshell fusefs fuzz glob graph gzip hname hook http http_socket http_ssl http_transport import info interwiki json json_artifact json_branch json_config json_diff json_dir json_finfo json_login json_query json_report json_status json_tag json_timeline json_user json_wiki leaf loadctrl login lookslike main manifest markdown markdown_html md5 merge merge3 moderate name patch path piechart pikchr pikchrshow pivot popen pqueue printf publish purge rebuild regexp repolist report rss schema search security_audit setup setupuser sha1 sha1hard sha3 shun sitemap skins smtp sqlcmd stash stat statrep style sync tag tar terminal th_main timeline tkt tktsetup undo unicode unversioned update url user utf8 util verify vfile wiki wikiformat winfile winhttp xfer xfersetup zip shell sqlite3 th th_lang > $@
54
+ +echo add ajax alerts allrepo attach backlink backoffice bag bisect blob branch browse builtin bundle cache capabilities captcha cgi chat checkin checkout clearsign clone color comformat configure content cookies db delta deltacmd deltafunc descendants diff diffcmd dispatch doc encode etag event export extcgi file fileedit finfo foci forum fshell fusefs fuzz glob graph gzip hname hook http http_socket http_ssl http_transport import info interwiki json json_artifact json_branch json_config json_diff json_dir json_finfo json_login json_query json_report json_status json_tag json_timeline json_user json_wiki leaf loadctrl login lookslike main manifest markdown markdown_html md5 merge merge3 moderate name patch path piechart pikchrshow pivot popen pqueue printf publish purge rebuild regexp repolist report rss schema search security_audit setup setupuser sha1 sha1hard sha3 shun sitemap skins smtp sqlcmd stash stat statrep style sync tag tar terminal th_main timeline tkt tktsetup undo unicode unversioned update url user utf8 util verify vfile wiki wikiformat winfile winhttp xfer xfersetup zip shell sqlite3 th th_lang > $@
5555
+echo fossil >> $@
5656
+echo fossil >> $@
5757
+echo $(LIBS) >> $@
5858
+echo. >> $@
5959
+echo fossil >> $@
@@ -74,23 +74,23 @@
7474
$(BCC) -o$@ $**
7575
7676
codecheck1$E: $(SRCDIR.tools)\codecheck1.c
7777
$(BCC) -o$@ $**
7878
79
-$(OBJDIR)\shell$O : $(SRCDIR)\shell.c
79
+$(OBJDIR)\shell$O : $(SRCDIR.extsrc)\shell.c
8080
$(TCC) -o$@ -c $(SHELL_OPTIONS) $(SQLITE_OPTIONS) $(SHELL_CFLAGS) $**
8181
82
-$(OBJDIR)\sqlite3$O : $(SRCDIR)\sqlite3.c
82
+$(OBJDIR)\sqlite3$O : $(SRCDIR.extsrc)\sqlite3.c
8383
$(TCC) -o$@ -c $(SQLITE_OPTIONS) $(SQLITE_CFLAGS) $**
8484
8585
$(OBJDIR)\th$O : $(SRCDIR)\th.c
8686
$(TCC) -o$@ -c $**
8787
8888
$(OBJDIR)\th_lang$O : $(SRCDIR)\th_lang.c
8989
$(TCC) -o$@ -c $**
9090
91
-$(OBJDIR)\cson_amalgamation.h : $(SRCDIR)\cson_amalgamation.h
91
+$(OBJDIR)\cson_amalgamation.h : $(SRCDIR.extsrc)\cson_amalgamation.h
9292
cp $@ $@
9393
9494
VERSION.h : mkversion$E $B\manifest.uuid $B\manifest $B\VERSION
9595
+$** > $@
9696
@@ -680,16 +680,10 @@
680680
$(TCC) -o$@ -c piechart_.c
681681
682682
piechart_.c : $(SRCDIR)\piechart.c
683683
+translate$E $** > $@
684684
685
-$(OBJDIR)\pikchr$O : pikchr_.c pikchr.h
686
- $(TCC) -o$@ -c pikchr_.c
687
-
688
-pikchr_.c : $(SRCDIR)\pikchr.c
689
- +translate$E $** > $@
690
-
691685
$(OBJDIR)\pikchrshow$O : pikchrshow_.c pikchrshow.h
692686
$(TCC) -o$@ -c pikchrshow_.c
693687
694688
pikchrshow_.c : $(SRCDIR)\pikchrshow.c
695689
+translate$E $** > $@
@@ -1011,7 +1005,7 @@
10111005
10121006
zip_.c : $(SRCDIR)\zip.c
10131007
+translate$E $** > $@
10141008
10151009
headers: makeheaders$E page_index.h builtin_data.h VERSION.h
1016
- +makeheaders$E add_.c:add.h ajax_.c:ajax.h alerts_.c:alerts.h allrepo_.c:allrepo.h attach_.c:attach.h backlink_.c:backlink.h backoffice_.c:backoffice.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h builtin_.c:builtin.h bundle_.c:bundle.h cache_.c:cache.h capabilities_.c:capabilities.h captcha_.c:captcha.h cgi_.c:cgi.h chat_.c:chat.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h color_.c:color.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h cookies_.c:cookies.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h deltafunc_.c:deltafunc.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h dispatch_.c:dispatch.h doc_.c:doc.h encode_.c:encode.h etag_.c:etag.h event_.c:event.h export_.c:export.h extcgi_.c:extcgi.h file_.c:file.h fileedit_.c:fileedit.h finfo_.c:finfo.h foci_.c:foci.h forum_.c:forum.h fshell_.c:fshell.h fusefs_.c:fusefs.h fuzz_.c:fuzz.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h hname_.c:hname.h hook_.c:hook.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h interwiki_.c:interwiki.h json_.c:json.h json_artifact_.c:json_artifact.h json_branch_.c:json_branch.h json_config_.c:json_config.h json_diff_.c:json_diff.h json_dir_.c:json_dir.h json_finfo_.c:json_finfo.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_status_.c:json_status.h json_tag_.c:json_tag.h json_timeline_.c:json_timeline.h json_user_.c:json_user.h json_wiki_.c:json_wiki.h leaf_.c:leaf.h loadctrl_.c:loadctrl.h login_.c:login.h lookslike_.c:lookslike.h main_.c:main.h manifest_.c:manifest.h markdown_.c:markdown.h markdown_html_.c:markdown_html.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h moderate_.c:moderate.h name_.c:name.h patch_.c:patch.h path_.c:path.h piechart_.c:piechart.h pikchr_.c:pikchr.h pikchrshow_.c:pikchrshow.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h publish_.c:publish.h purge_.c:purge.h rebuild_.c:rebuild.h regexp_.c:regexp.h repolist_.c:repolist.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h security_audit_.c:security_audit.h setup_.c:setup.h setupuser_.c:setupuser.h sha1_.c:sha1.h sha1hard_.c:sha1hard.h sha3_.c:sha3.h shun_.c:shun.h sitemap_.c:sitemap.h skins_.c:skins.h smtp_.c:smtp.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h statrep_.c:statrep.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h terminal_.c:terminal.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h unicode_.c:unicode.h unversioned_.c:unversioned.h update_.c:update.h url_.c:url.h user_.c:user.h utf8_.c:utf8.h util_.c:util.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winfile_.c:winfile.h winhttp_.c:winhttp.h xfer_.c:xfer.h xfersetup_.c:xfersetup.h zip_.c:zip.h $(SRCDIR.extsrc)\sqlite3.h $(SRCDIR)\th.h VERSION.h $(SRCDIR)\cson_amalgamation.h
1010
+ +makeheaders$E add_.c:add.h ajax_.c:ajax.h alerts_.c:alerts.h allrepo_.c:allrepo.h attach_.c:attach.h backlink_.c:backlink.h backoffice_.c:backoffice.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h builtin_.c:builtin.h bundle_.c:bundle.h cache_.c:cache.h capabilities_.c:capabilities.h captcha_.c:captcha.h cgi_.c:cgi.h chat_.c:chat.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h color_.c:color.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h cookies_.c:cookies.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h deltafunc_.c:deltafunc.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h dispatch_.c:dispatch.h doc_.c:doc.h encode_.c:encode.h etag_.c:etag.h event_.c:event.h export_.c:export.h extcgi_.c:extcgi.h file_.c:file.h fileedit_.c:fileedit.h finfo_.c:finfo.h foci_.c:foci.h forum_.c:forum.h fshell_.c:fshell.h fusefs_.c:fusefs.h fuzz_.c:fuzz.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h hname_.c:hname.h hook_.c:hook.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h interwiki_.c:interwiki.h json_.c:json.h json_artifact_.c:json_artifact.h json_branch_.c:json_branch.h json_config_.c:json_config.h json_diff_.c:json_diff.h json_dir_.c:json_dir.h json_finfo_.c:json_finfo.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_status_.c:json_status.h json_tag_.c:json_tag.h json_timeline_.c:json_timeline.h json_user_.c:json_user.h json_wiki_.c:json_wiki.h leaf_.c:leaf.h loadctrl_.c:loadctrl.h login_.c:login.h lookslike_.c:lookslike.h main_.c:main.h manifest_.c:manifest.h markdown_.c:markdown.h markdown_html_.c:markdown_html.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h moderate_.c:moderate.h name_.c:name.h patch_.c:patch.h path_.c:path.h piechart_.c:piechart.h pikchrshow_.c:pikchrshow.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h publish_.c:publish.h purge_.c:purge.h rebuild_.c:rebuild.h regexp_.c:regexp.h repolist_.c:repolist.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h security_audit_.c:security_audit.h setup_.c:setup.h setupuser_.c:setupuser.h sha1_.c:sha1.h sha1hard_.c:sha1hard.h sha3_.c:sha3.h shun_.c:shun.h sitemap_.c:sitemap.h skins_.c:skins.h smtp_.c:smtp.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h statrep_.c:statrep.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h terminal_.c:terminal.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h unicode_.c:unicode.h unversioned_.c:unversioned.h update_.c:update.h url_.c:url.h user_.c:user.h utf8_.c:utf8.h util_.c:util.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winfile_.c:winfile.h winhttp_.c:winhttp.h xfer_.c:xfer.h xfersetup_.c:xfersetup.h zip_.c:zip.h $(SRCDIR.extsrc)\sqlite3.h $(SRCDIR)\th.h VERSION.h $(SRCDIR.extsrc)\cson_amalgamation.h
10171011
@copy /Y nul: headers
10181012
--- win/Makefile.dmc
+++ win/Makefile.dmc
@@ -28,13 +28,13 @@
28
29 SQLITE_OPTIONS = -DNDEBUG=1 -DSQLITE_DQS=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_USE_ALLOCA -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_INTROSPECTION_PRAGMAS -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_TRUSTED_SCHEMA=0
30
31 SHELL_OPTIONS = -DNDEBUG=1 -DSQLITE_DQS=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_USE_ALLOCA -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_INTROSPECTION_PRAGMAS -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_TRUSTED_SCHEMA=0 -Dmain=sqlite3_shell -DSQLITE_SHELL_IS_UTF8=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=sqlcmd_get_dbname -DSQLITE_SHELL_INIT_PROC=sqlcmd_init_proc -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen
32
33 SRC = add_.c ajax_.c alerts_.c allrepo_.c attach_.c backlink_.c backoffice_.c bag_.c bisect_.c blob_.c branch_.c browse_.c builtin_.c bundle_.c cache_.c capabilities_.c captcha_.c cgi_.c chat_.c checkin_.c checkout_.c clearsign_.c clone_.c color_.c comformat_.c configure_.c content_.c cookies_.c db_.c delta_.c deltacmd_.c deltafunc_.c descendants_.c diff_.c diffcmd_.c dispatch_.c doc_.c encode_.c etag_.c event_.c export_.c extcgi_.c file_.c fileedit_.c finfo_.c foci_.c forum_.c fshell_.c fusefs_.c fuzz_.c glob_.c graph_.c gzip_.c hname_.c hook_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c interwiki_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_status_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c loadctrl_.c login_.c lookslike_.c main_.c manifest_.c markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c patch_.c path_.c piechart_.c pikchr_.c pikchrshow_.c pivot_.c popen_.c pqueue_.c printf_.c publish_.c purge_.c rebuild_.c regexp_.c repolist_.c report_.c rss_.c schema_.c search_.c security_audit_.c setup_.c setupuser_.c sha1_.c sha1hard_.c sha3_.c shun_.c sitemap_.c skins_.c smtp_.c sqlcmd_.c stash_.c stat_.c statrep_.c style_.c sync_.c tag_.c tar_.c terminal_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c unversioned_.c update_.c url_.c user_.c utf8_.c util_.c verify_.c vfile_.c wiki_.c wikiformat_.c winfile_.c winhttp_.c xfer_.c xfersetup_.c zip_.c
34
35 OBJ = $(OBJDIR)\add$O $(OBJDIR)\ajax$O $(OBJDIR)\alerts$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\backlink$O $(OBJDIR)\backoffice$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\builtin$O $(OBJDIR)\bundle$O $(OBJDIR)\cache$O $(OBJDIR)\capabilities$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\chat$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\color$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\cookies$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\deltafunc$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\dispatch$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\etag$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\extcgi$O $(OBJDIR)\file$O $(OBJDIR)\fileedit$O $(OBJDIR)\finfo$O $(OBJDIR)\foci$O $(OBJDIR)\forum$O $(OBJDIR)\fshell$O $(OBJDIR)\fusefs$O $(OBJDIR)\fuzz$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\hname$O $(OBJDIR)\hook$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\interwiki$O $(OBJDIR)\json$O $(OBJDIR)\json_artifact$O $(OBJDIR)\json_branch$O $(OBJDIR)\json_config$O $(OBJDIR)\json_diff$O $(OBJDIR)\json_dir$O $(OBJDIR)\json_finfo$O $(OBJDIR)\json_login$O $(OBJDIR)\json_query$O $(OBJDIR)\json_report$O $(OBJDIR)\json_status$O $(OBJDIR)\json_tag$O $(OBJDIR)\json_timeline$O $(OBJDIR)\json_user$O $(OBJDIR)\json_wiki$O $(OBJDIR)\leaf$O $(OBJDIR)\loadctrl$O $(OBJDIR)\login$O $(OBJDIR)\lookslike$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\markdown$O $(OBJDIR)\markdown_html$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\moderate$O $(OBJDIR)\name$O $(OBJDIR)\patch$O $(OBJDIR)\path$O $(OBJDIR)\piechart$O $(OBJDIR)\pikchr$O $(OBJDIR)\pikchrshow$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\publish$O $(OBJDIR)\purge$O $(OBJDIR)\rebuild$O $(OBJDIR)\regexp$O $(OBJDIR)\repolist$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\security_audit$O $(OBJDIR)\setup$O $(OBJDIR)\setupuser$O $(OBJDIR)\sha1$O $(OBJDIR)\sha1hard$O $(OBJDIR)\sha3$O $(OBJDIR)\shun$O $(OBJDIR)\sitemap$O $(OBJDIR)\skins$O $(OBJDIR)\smtp$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\statrep$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\terminal$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\unicode$O $(OBJDIR)\unversioned$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\utf8$O $(OBJDIR)\util$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winfile$O $(OBJDIR)\winhttp$O $(OBJDIR)\xfer$O $(OBJDIR)\xfersetup$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O
36
37
38 RC=$(DMDIR)\bin\rcc
39 RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__
40
@@ -49,11 +49,11 @@
49
50 $(OBJDIR)\fossil.res: $B\win\fossil.rc
51 $(RC) $(RCFLAGS) -o$@ $**
52
53 $(OBJDIR)\link: $B\win\Makefile.dmc $(OBJDIR)\fossil.res
54 +echo add ajax alerts allrepo attach backlink backoffice bag bisect blob branch browse builtin bundle cache capabilities captcha cgi chat checkin checkout clearsign clone color comformat configure content cookies db delta deltacmd deltafunc descendants diff diffcmd dispatch doc encode etag event export extcgi file fileedit finfo foci forum fshell fusefs fuzz glob graph gzip hname hook http http_socket http_ssl http_transport import info interwiki json json_artifact json_branch json_config json_diff json_dir json_finfo json_login json_query json_report json_status json_tag json_timeline json_user json_wiki leaf loadctrl login lookslike main manifest markdown markdown_html md5 merge merge3 moderate name patch path piechart pikchr pikchrshow pivot popen pqueue printf publish purge rebuild regexp repolist report rss schema search security_audit setup setupuser sha1 sha1hard sha3 shun sitemap skins smtp sqlcmd stash stat statrep style sync tag tar terminal th_main timeline tkt tktsetup undo unicode unversioned update url user utf8 util verify vfile wiki wikiformat winfile winhttp xfer xfersetup zip shell sqlite3 th th_lang > $@
55 +echo fossil >> $@
56 +echo fossil >> $@
57 +echo $(LIBS) >> $@
58 +echo. >> $@
59 +echo fossil >> $@
@@ -74,23 +74,23 @@
74 $(BCC) -o$@ $**
75
76 codecheck1$E: $(SRCDIR.tools)\codecheck1.c
77 $(BCC) -o$@ $**
78
79 $(OBJDIR)\shell$O : $(SRCDIR)\shell.c
80 $(TCC) -o$@ -c $(SHELL_OPTIONS) $(SQLITE_OPTIONS) $(SHELL_CFLAGS) $**
81
82 $(OBJDIR)\sqlite3$O : $(SRCDIR)\sqlite3.c
83 $(TCC) -o$@ -c $(SQLITE_OPTIONS) $(SQLITE_CFLAGS) $**
84
85 $(OBJDIR)\th$O : $(SRCDIR)\th.c
86 $(TCC) -o$@ -c $**
87
88 $(OBJDIR)\th_lang$O : $(SRCDIR)\th_lang.c
89 $(TCC) -o$@ -c $**
90
91 $(OBJDIR)\cson_amalgamation.h : $(SRCDIR)\cson_amalgamation.h
92 cp $@ $@
93
94 VERSION.h : mkversion$E $B\manifest.uuid $B\manifest $B\VERSION
95 +$** > $@
96
@@ -680,16 +680,10 @@
680 $(TCC) -o$@ -c piechart_.c
681
682 piechart_.c : $(SRCDIR)\piechart.c
683 +translate$E $** > $@
684
685 $(OBJDIR)\pikchr$O : pikchr_.c pikchr.h
686 $(TCC) -o$@ -c pikchr_.c
687
688 pikchr_.c : $(SRCDIR)\pikchr.c
689 +translate$E $** > $@
690
691 $(OBJDIR)\pikchrshow$O : pikchrshow_.c pikchrshow.h
692 $(TCC) -o$@ -c pikchrshow_.c
693
694 pikchrshow_.c : $(SRCDIR)\pikchrshow.c
695 +translate$E $** > $@
@@ -1011,7 +1005,7 @@
1011
1012 zip_.c : $(SRCDIR)\zip.c
1013 +translate$E $** > $@
1014
1015 headers: makeheaders$E page_index.h builtin_data.h VERSION.h
1016 +makeheaders$E add_.c:add.h ajax_.c:ajax.h alerts_.c:alerts.h allrepo_.c:allrepo.h attach_.c:attach.h backlink_.c:backlink.h backoffice_.c:backoffice.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h builtin_.c:builtin.h bundle_.c:bundle.h cache_.c:cache.h capabilities_.c:capabilities.h captcha_.c:captcha.h cgi_.c:cgi.h chat_.c:chat.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h color_.c:color.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h cookies_.c:cookies.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h deltafunc_.c:deltafunc.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h dispatch_.c:dispatch.h doc_.c:doc.h encode_.c:encode.h etag_.c:etag.h event_.c:event.h export_.c:export.h extcgi_.c:extcgi.h file_.c:file.h fileedit_.c:fileedit.h finfo_.c:finfo.h foci_.c:foci.h forum_.c:forum.h fshell_.c:fshell.h fusefs_.c:fusefs.h fuzz_.c:fuzz.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h hname_.c:hname.h hook_.c:hook.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h interwiki_.c:interwiki.h json_.c:json.h json_artifact_.c:json_artifact.h json_branch_.c:json_branch.h json_config_.c:json_config.h json_diff_.c:json_diff.h json_dir_.c:json_dir.h json_finfo_.c:json_finfo.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_status_.c:json_status.h json_tag_.c:json_tag.h json_timeline_.c:json_timeline.h json_user_.c:json_user.h json_wiki_.c:json_wiki.h leaf_.c:leaf.h loadctrl_.c:loadctrl.h login_.c:login.h lookslike_.c:lookslike.h main_.c:main.h manifest_.c:manifest.h markdown_.c:markdown.h markdown_html_.c:markdown_html.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h moderate_.c:moderate.h name_.c:name.h patch_.c:patch.h path_.c:path.h piechart_.c:piechart.h pikchr_.c:pikchr.h pikchrshow_.c:pikchrshow.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h publish_.c:publish.h purge_.c:purge.h rebuild_.c:rebuild.h regexp_.c:regexp.h repolist_.c:repolist.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h security_audit_.c:security_audit.h setup_.c:setup.h setupuser_.c:setupuser.h sha1_.c:sha1.h sha1hard_.c:sha1hard.h sha3_.c:sha3.h shun_.c:shun.h sitemap_.c:sitemap.h skins_.c:skins.h smtp_.c:smtp.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h statrep_.c:statrep.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h terminal_.c:terminal.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h unicode_.c:unicode.h unversioned_.c:unversioned.h update_.c:update.h url_.c:url.h user_.c:user.h utf8_.c:utf8.h util_.c:util.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winfile_.c:winfile.h winhttp_.c:winhttp.h xfer_.c:xfer.h xfersetup_.c:xfersetup.h zip_.c:zip.h $(SRCDIR.extsrc)\sqlite3.h $(SRCDIR)\th.h VERSION.h $(SRCDIR)\cson_amalgamation.h
1017 @copy /Y nul: headers
1018
--- win/Makefile.dmc
+++ win/Makefile.dmc
@@ -28,13 +28,13 @@
28
29 SQLITE_OPTIONS = -DNDEBUG=1 -DSQLITE_DQS=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_USE_ALLOCA -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_INTROSPECTION_PRAGMAS -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_TRUSTED_SCHEMA=0
30
31 SHELL_OPTIONS = -DNDEBUG=1 -DSQLITE_DQS=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_USE_ALLOCA -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_INTROSPECTION_PRAGMAS -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_TRUSTED_SCHEMA=0 -Dmain=sqlite3_shell -DSQLITE_SHELL_IS_UTF8=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=sqlcmd_get_dbname -DSQLITE_SHELL_INIT_PROC=sqlcmd_init_proc -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen
32
33 SRC = add_.c ajax_.c alerts_.c allrepo_.c attach_.c backlink_.c backoffice_.c bag_.c bisect_.c blob_.c branch_.c browse_.c builtin_.c bundle_.c cache_.c capabilities_.c captcha_.c cgi_.c chat_.c checkin_.c checkout_.c clearsign_.c clone_.c color_.c comformat_.c configure_.c content_.c cookies_.c db_.c delta_.c deltacmd_.c deltafunc_.c descendants_.c diff_.c diffcmd_.c dispatch_.c doc_.c encode_.c etag_.c event_.c export_.c extcgi_.c file_.c fileedit_.c finfo_.c foci_.c forum_.c fshell_.c fusefs_.c fuzz_.c glob_.c graph_.c gzip_.c hname_.c hook_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c interwiki_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_status_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c loadctrl_.c login_.c lookslike_.c main_.c manifest_.c markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c patch_.c path_.c piechart_.c pikchrshow_.c pivot_.c popen_.c pqueue_.c printf_.c publish_.c purge_.c rebuild_.c regexp_.c repolist_.c report_.c rss_.c schema_.c search_.c security_audit_.c setup_.c setupuser_.c sha1_.c sha1hard_.c sha3_.c shun_.c sitemap_.c skins_.c smtp_.c sqlcmd_.c stash_.c stat_.c statrep_.c style_.c sync_.c tag_.c tar_.c terminal_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c unversioned_.c update_.c url_.c user_.c utf8_.c util_.c verify_.c vfile_.c wiki_.c wikiformat_.c winfile_.c winhttp_.c xfer_.c xfersetup_.c zip_.c
34
35 OBJ = $(OBJDIR)\add$O $(OBJDIR)\ajax$O $(OBJDIR)\alerts$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\backlink$O $(OBJDIR)\backoffice$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\builtin$O $(OBJDIR)\bundle$O $(OBJDIR)\cache$O $(OBJDIR)\capabilities$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\chat$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\color$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\cookies$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\deltafunc$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\dispatch$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\etag$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\extcgi$O $(OBJDIR)\file$O $(OBJDIR)\fileedit$O $(OBJDIR)\finfo$O $(OBJDIR)\foci$O $(OBJDIR)\forum$O $(OBJDIR)\fshell$O $(OBJDIR)\fusefs$O $(OBJDIR)\fuzz$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\hname$O $(OBJDIR)\hook$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\interwiki$O $(OBJDIR)\json$O $(OBJDIR)\json_artifact$O $(OBJDIR)\json_branch$O $(OBJDIR)\json_config$O $(OBJDIR)\json_diff$O $(OBJDIR)\json_dir$O $(OBJDIR)\json_finfo$O $(OBJDIR)\json_login$O $(OBJDIR)\json_query$O $(OBJDIR)\json_report$O $(OBJDIR)\json_status$O $(OBJDIR)\json_tag$O $(OBJDIR)\json_timeline$O $(OBJDIR)\json_user$O $(OBJDIR)\json_wiki$O $(OBJDIR)\leaf$O $(OBJDIR)\loadctrl$O $(OBJDIR)\login$O $(OBJDIR)\lookslike$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\markdown$O $(OBJDIR)\markdown_html$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\moderate$O $(OBJDIR)\name$O $(OBJDIR)\patch$O $(OBJDIR)\path$O $(OBJDIR)\piechart$O $(OBJDIR)\pikchrshow$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\publish$O $(OBJDIR)\purge$O $(OBJDIR)\rebuild$O $(OBJDIR)\regexp$O $(OBJDIR)\repolist$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\security_audit$O $(OBJDIR)\setup$O $(OBJDIR)\setupuser$O $(OBJDIR)\sha1$O $(OBJDIR)\sha1hard$O $(OBJDIR)\sha3$O $(OBJDIR)\shun$O $(OBJDIR)\sitemap$O $(OBJDIR)\skins$O $(OBJDIR)\smtp$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\statrep$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\terminal$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\unicode$O $(OBJDIR)\unversioned$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\utf8$O $(OBJDIR)\util$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winfile$O $(OBJDIR)\winhttp$O $(OBJDIR)\xfer$O $(OBJDIR)\xfersetup$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O
36
37
38 RC=$(DMDIR)\bin\rcc
39 RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__
40
@@ -49,11 +49,11 @@
49
50 $(OBJDIR)\fossil.res: $B\win\fossil.rc
51 $(RC) $(RCFLAGS) -o$@ $**
52
53 $(OBJDIR)\link: $B\win\Makefile.dmc $(OBJDIR)\fossil.res
54 +echo add ajax alerts allrepo attach backlink backoffice bag bisect blob branch browse builtin bundle cache capabilities captcha cgi chat checkin checkout clearsign clone color comformat configure content cookies db delta deltacmd deltafunc descendants diff diffcmd dispatch doc encode etag event export extcgi file fileedit finfo foci forum fshell fusefs fuzz glob graph gzip hname hook http http_socket http_ssl http_transport import info interwiki json json_artifact json_branch json_config json_diff json_dir json_finfo json_login json_query json_report json_status json_tag json_timeline json_user json_wiki leaf loadctrl login lookslike main manifest markdown markdown_html md5 merge merge3 moderate name patch path piechart pikchrshow pivot popen pqueue printf publish purge rebuild regexp repolist report rss schema search security_audit setup setupuser sha1 sha1hard sha3 shun sitemap skins smtp sqlcmd stash stat statrep style sync tag tar terminal th_main timeline tkt tktsetup undo unicode unversioned update url user utf8 util verify vfile wiki wikiformat winfile winhttp xfer xfersetup zip shell sqlite3 th th_lang > $@
55 +echo fossil >> $@
56 +echo fossil >> $@
57 +echo $(LIBS) >> $@
58 +echo. >> $@
59 +echo fossil >> $@
@@ -74,23 +74,23 @@
74 $(BCC) -o$@ $**
75
76 codecheck1$E: $(SRCDIR.tools)\codecheck1.c
77 $(BCC) -o$@ $**
78
79 $(OBJDIR)\shell$O : $(SRCDIR.extsrc)\shell.c
80 $(TCC) -o$@ -c $(SHELL_OPTIONS) $(SQLITE_OPTIONS) $(SHELL_CFLAGS) $**
81
82 $(OBJDIR)\sqlite3$O : $(SRCDIR.extsrc)\sqlite3.c
83 $(TCC) -o$@ -c $(SQLITE_OPTIONS) $(SQLITE_CFLAGS) $**
84
85 $(OBJDIR)\th$O : $(SRCDIR)\th.c
86 $(TCC) -o$@ -c $**
87
88 $(OBJDIR)\th_lang$O : $(SRCDIR)\th_lang.c
89 $(TCC) -o$@ -c $**
90
91 $(OBJDIR)\cson_amalgamation.h : $(SRCDIR.extsrc)\cson_amalgamation.h
92 cp $@ $@
93
94 VERSION.h : mkversion$E $B\manifest.uuid $B\manifest $B\VERSION
95 +$** > $@
96
@@ -680,16 +680,10 @@
680 $(TCC) -o$@ -c piechart_.c
681
682 piechart_.c : $(SRCDIR)\piechart.c
683 +translate$E $** > $@
684
 
 
 
 
 
 
685 $(OBJDIR)\pikchrshow$O : pikchrshow_.c pikchrshow.h
686 $(TCC) -o$@ -c pikchrshow_.c
687
688 pikchrshow_.c : $(SRCDIR)\pikchrshow.c
689 +translate$E $** > $@
@@ -1011,7 +1005,7 @@
1005
1006 zip_.c : $(SRCDIR)\zip.c
1007 +translate$E $** > $@
1008
1009 headers: makeheaders$E page_index.h builtin_data.h VERSION.h
1010 +makeheaders$E add_.c:add.h ajax_.c:ajax.h alerts_.c:alerts.h allrepo_.c:allrepo.h attach_.c:attach.h backlink_.c:backlink.h backoffice_.c:backoffice.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h builtin_.c:builtin.h bundle_.c:bundle.h cache_.c:cache.h capabilities_.c:capabilities.h captcha_.c:captcha.h cgi_.c:cgi.h chat_.c:chat.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h color_.c:color.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h cookies_.c:cookies.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h deltafunc_.c:deltafunc.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h dispatch_.c:dispatch.h doc_.c:doc.h encode_.c:encode.h etag_.c:etag.h event_.c:event.h export_.c:export.h extcgi_.c:extcgi.h file_.c:file.h fileedit_.c:fileedit.h finfo_.c:finfo.h foci_.c:foci.h forum_.c:forum.h fshell_.c:fshell.h fusefs_.c:fusefs.h fuzz_.c:fuzz.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h hname_.c:hname.h hook_.c:hook.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h interwiki_.c:interwiki.h json_.c:json.h json_artifact_.c:json_artifact.h json_branch_.c:json_branch.h json_config_.c:json_config.h json_diff_.c:json_diff.h json_dir_.c:json_dir.h json_finfo_.c:json_finfo.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_status_.c:json_status.h json_tag_.c:json_tag.h json_timeline_.c:json_timeline.h json_user_.c:json_user.h json_wiki_.c:json_wiki.h leaf_.c:leaf.h loadctrl_.c:loadctrl.h login_.c:login.h lookslike_.c:lookslike.h main_.c:main.h manifest_.c:manifest.h markdown_.c:markdown.h markdown_html_.c:markdown_html.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h moderate_.c:moderate.h name_.c:name.h patch_.c:patch.h path_.c:path.h piechart_.c:piechart.h pikchrshow_.c:pikchrshow.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h publish_.c:publish.h purge_.c:purge.h rebuild_.c:rebuild.h regexp_.c:regexp.h repolist_.c:repolist.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h security_audit_.c:security_audit.h setup_.c:setup.h setupuser_.c:setupuser.h sha1_.c:sha1.h sha1hard_.c:sha1hard.h sha3_.c:sha3.h shun_.c:shun.h sitemap_.c:sitemap.h skins_.c:skins.h smtp_.c:smtp.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h statrep_.c:statrep.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h terminal_.c:terminal.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h unicode_.c:unicode.h unversioned_.c:unversioned.h update_.c:update.h url_.c:url.h user_.c:user.h utf8_.c:utf8.h util_.c:util.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winfile_.c:winfile.h winhttp_.c:winhttp.h xfer_.c:xfer.h xfersetup_.c:xfersetup.h zip_.c:zip.h $(SRCDIR.extsrc)\sqlite3.h $(SRCDIR)\th.h VERSION.h $(SRCDIR.extsrc)\cson_amalgamation.h
1011 @copy /Y nul: headers
1012
+13 -22
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -516,11 +516,10 @@
516516
$(SRCDIR)/moderate.c \
517517
$(SRCDIR)/name.c \
518518
$(SRCDIR)/patch.c \
519519
$(SRCDIR)/path.c \
520520
$(SRCDIR)/piechart.c \
521
- $(SRCDIR)/pikchr.c \
522521
$(SRCDIR)/pikchrshow.c \
523522
$(SRCDIR)/pivot.c \
524523
$(SRCDIR)/popen.c \
525524
$(SRCDIR)/pqueue.c \
526525
$(SRCDIR)/printf.c \
@@ -775,11 +774,10 @@
775774
$(OBJDIR)/moderate_.c \
776775
$(OBJDIR)/name_.c \
777776
$(OBJDIR)/patch_.c \
778777
$(OBJDIR)/path_.c \
779778
$(OBJDIR)/piechart_.c \
780
- $(OBJDIR)/pikchr_.c \
781779
$(OBJDIR)/pikchrshow_.c \
782780
$(OBJDIR)/pivot_.c \
783781
$(OBJDIR)/popen_.c \
784782
$(OBJDIR)/pqueue_.c \
785783
$(OBJDIR)/printf_.c \
@@ -925,11 +923,10 @@
925923
$(OBJDIR)/moderate.o \
926924
$(OBJDIR)/name.o \
927925
$(OBJDIR)/patch.o \
928926
$(OBJDIR)/path.o \
929927
$(OBJDIR)/piechart.o \
930
- $(OBJDIR)/pikchr.o \
931928
$(OBJDIR)/pikchrshow.o \
932929
$(OBJDIR)/pivot.o \
933930
$(OBJDIR)/popen.o \
934931
$(OBJDIR)/pqueue.o \
935932
$(OBJDIR)/printf.o \
@@ -1025,16 +1022,16 @@
10251022
10261023
all: $(OBJDIR) $(APPNAME)
10271024
10281025
$(OBJDIR)/fossil.o: $(SRCDIR)/../win/fossil.rc $(OBJDIR)/VERSION.h
10291026
ifdef USE_WINDOWS
1030
- $(CAT) $(subst /,\,$(SRCDIR)\miniz.c) | $(GREP) "define MZ_VERSION" > $(subst /,\,$(OBJDIR)\minizver.h)
1027
+ $(CAT) $(subst /,\,$(SRCDIR.extsrc)\miniz.c) | $(GREP) "define MZ_VERSION" > $(subst /,\,$(OBJDIR)\minizver.h)
10311028
$(CP) $(subst /,\,$(SRCDIR)\..\win\fossil.rc) $(subst /,\,$(OBJDIR))
10321029
$(CP) $(subst /,\,$(SRCDIR)\..\win\fossil.ico) $(subst /,\,$(OBJDIR))
10331030
$(CP) $(subst /,\,$(SRCDIR)\..\win\fossil.exe.manifest) $(subst /,\,$(OBJDIR))
10341031
else
1035
- $(CAT) $(SRCDIR)/miniz.c | $(GREP) "define MZ_VERSION" > $(OBJDIR)/minizver.h
1032
+ $(CAT) $(SRCDIR.extsrc)/miniz.c | $(GREP) "define MZ_VERSION" > $(OBJDIR)/minizver.h
10361033
$(CP) $(SRCDIR)/../win/fossil.rc $(OBJDIR)
10371034
$(CP) $(SRCDIR)/../win/fossil.ico $(OBJDIR)
10381035
$(CP) $(SRCDIR)/../win/fossil.exe.manifest $(OBJDIR)
10391036
endif
10401037
$(RCC) $(OBJDIR)/fossil.rc -o $(OBJDIR)/fossil.o
@@ -1112,14 +1109,14 @@
11121109
SQLITE3_SRC.0 = $(SRCDIR.extsrc)/sqlite3.c
11131110
SQLITE3_SRC.1 = $(SRCDIR.extsrc)/sqlite3-see.c
11141111
# SQLITE3_SRC.2 is set by top-level configure/makefile process.
11151112
SQLITE3_SRC. = $(SRCDIR.extsrc)/sqlite3.c
11161113
SQLITE3_SRC = $(SRCDIR)/$(SQLITE3_SRC.$(SQLITE3_ORIGIN))
1117
-SQLITE3_SHELL_SRC.0 = $(SRCDIR)/shell.c
1118
-SQLITE3_SHELL_SRC.1 = $(SRCDIR)/shell-see.c
1114
+SQLITE3_SHELL_SRC.0 = $(SRCDIR.extsrc)/shell.c
1115
+SQLITE3_SHELL_SRC.1 = $(SRCDIR.extsrc)/shell-see.c
11191116
# SQLITE3_SHELL_SRC.2 comes from the configure process
1120
-SQLITE3_SHELL_SRC. = $(SRCDIR)/shell.c
1117
+SQLITE3_SHELL_SRC. = $(SRCDIR.extsrc)/shell.c
11211118
SQLITE3_SHELL_SRC = $(SQLITE3_SHELL_SRC.$(SQLITE3_ORIGIN))
11221119
SEE_FLAGS.0 =
11231120
SEE_FLAGS.1 = -DSQLITE_HAS_CODEC -DSQLITE_SHELL_DBKEY_PROC=fossil_key
11241121
SEE_FLAGS. =
11251122
SEE_FLAGS = $(SEE_FLAGS.$(USE_SEE))
@@ -1297,11 +1294,10 @@
12971294
$(OBJDIR)/moderate_.c:$(OBJDIR)/moderate.h \
12981295
$(OBJDIR)/name_.c:$(OBJDIR)/name.h \
12991296
$(OBJDIR)/patch_.c:$(OBJDIR)/patch.h \
13001297
$(OBJDIR)/path_.c:$(OBJDIR)/path.h \
13011298
$(OBJDIR)/piechart_.c:$(OBJDIR)/piechart.h \
1302
- $(OBJDIR)/pikchr_.c:$(OBJDIR)/pikchr.h \
13031299
$(OBJDIR)/pikchrshow_.c:$(OBJDIR)/pikchrshow.h \
13041300
$(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \
13051301
$(OBJDIR)/popen_.c:$(OBJDIR)/popen.h \
13061302
$(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h \
13071303
$(OBJDIR)/printf_.c:$(OBJDIR)/printf.h \
@@ -1351,11 +1347,11 @@
13511347
$(OBJDIR)/wikiformat_.c:$(OBJDIR)/wikiformat.h \
13521348
$(OBJDIR)/winfile_.c:$(OBJDIR)/winfile.h \
13531349
$(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h \
13541350
$(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h \
13551351
$(OBJDIR)/xfersetup_.c:$(OBJDIR)/xfersetup.h \
1356
- $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h \
1352
+ $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h$(SRCDIR.extsrc)/miniz.c:$(OBJDIR)/miniz.h <<<NEXT_LINE>>>$(SRCDIR.extsrc)/pikchr.c:$(OBJDIR)/pikchr.h <<<NEXT_LINE>>> \
13571353
$(SRCDIR.extsrc)/sqlite3.h \
13581354
$(SRCDIR)/th.h \
13591355
$(OBJDIR)/VERSION.h
13601356
echo Done >$(OBJDIR)/headers
13611357
@@ -2105,18 +2101,10 @@
21052101
$(OBJDIR)/piechart.o: $(OBJDIR)/piechart_.c $(OBJDIR)/piechart.h $(SRCDIR)/config.h
21062102
$(XTCC) -o $(OBJDIR)/piechart.o -c $(OBJDIR)/piechart_.c
21072103
21082104
$(OBJDIR)/piechart.h: $(OBJDIR)/headers
21092105
2110
-$(OBJDIR)/pikchr_.c: $(SRCDIR)/pikchr.c $(TRANSLATE)
2111
- $(TRANSLATE) $(SRCDIR)/pikchr.c >$@
2112
-
2113
-$(OBJDIR)/pikchr.o: $(OBJDIR)/pikchr_.c $(OBJDIR)/pikchr.h $(SRCDIR)/config.h
2114
- $(XTCC) -o $(OBJDIR)/pikchr.o -c $(OBJDIR)/pikchr_.c
2115
-
2116
-$(OBJDIR)/pikchr.h: $(OBJDIR)/headers
2117
-
21182106
$(OBJDIR)/pikchrshow_.c: $(SRCDIR)/pikchrshow.c $(TRANSLATE)
21192107
$(TRANSLATE) $(SRCDIR)/pikchrshow.c >$@
21202108
21212109
$(OBJDIR)/pikchrshow.o: $(OBJDIR)/pikchrshow_.c $(OBJDIR)/pikchrshow.h $(SRCDIR)/config.h
21222110
$(XTCC) -o $(OBJDIR)/pikchrshow.o -c $(OBJDIR)/pikchrshow_.c
@@ -2621,12 +2609,12 @@
26212609
26222610
$(OBJDIR)/sqlite3.o: $(SQLITE3_SRC) $(SRCDIR)/../win/Makefile.mingw
26232611
$(XTCC) $(SQLITE_OPTIONS) $(SQLITE_CFLAGS) $(SEE_FLAGS) \
26242612
-c $(SQLITE3_SRC) -o $@
26252613
2626
-$(OBJDIR)/cson_amalgamation.o: $(SRCDIR)/cson_amalgamation.c
2627
- $(XTCC) -c $(SRCDIR)/cson_amalgamation.c -o $@
2614
+$(OBJDIR)/cson_amalgamation.o: $(SRCDIR.extsrc)/cson_amalgamation.c
2615
+ $(XTCC) -c $(SRCDIR.extsrc)/cson_amalgamation.c -o $@
26282616
26292617
$(OBJDIR)/json.o $(OBJDIR)/json_artifact.o $(OBJDIR)/json_branch.o $(OBJDIR)/json_config.o $(OBJDIR)/json_diff.o $(OBJDIR)/json_dir.o $(OBJDIR)/jsos_finfo.o $(OBJDIR)/json_login.o $(OBJDIR)/json_query.o $(OBJDIR)/json_report.o $(OBJDIR)/json_status.o $(OBJDIR)/json_tag.o $(OBJDIR)/json_timeline.o $(OBJDIR)/json_user.o $(OBJDIR)/json_wiki.o : $(SRCDIR)/json_detail.h
26302618
26312619
$(OBJDIR)/shell.o: $(SQLITE3_SHELL_SRC) $(SRCDIR.extsrc)/sqlite3.h $(SRCDIR)/../win/Makefile.mingw
26322620
$(XTCC) $(SHELL_OPTIONS) $(SHELL_CFLAGS) $(SEE_FLAGS) -c $(SQLITE3_SHELL_SRC) -o $@
@@ -2638,8 +2626,11 @@
26382626
$(XTCC) -c $(SRCDIR)/th_lang.c -o $@
26392627
26402628
$(OBJDIR)/th_tcl.o: $(SRCDIR)/th_tcl.c
26412629
$(XTCC) -c $(SRCDIR)/th_tcl.c -o $@
26422630
2643
-$(OBJDIR)/miniz.o: $(SRCDIR)/miniz.c
2644
- $(XTCC) $(MINIZ_OPTIONS) -c $(SRCDIR)/miniz.c -o $@
2631
+$(OBJDIR)/miniz.o: $(SRCDIR.extsrc)/miniz.c
2632
+ $(XTCC) $(MINIZ_OPTIONS) -c $(SRCDIR.extsrc)/miniz.c -o $@
2633
+
2634
+$(OBJDIR)/pikchr.o: $(SRCDIR.extsrc)/pikchr.c
2635
+ $(XTCC) -c $(SRCDIR.extsrc)/pikchr.c -o $@
26452636
26462637
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -516,11 +516,10 @@
516 $(SRCDIR)/moderate.c \
517 $(SRCDIR)/name.c \
518 $(SRCDIR)/patch.c \
519 $(SRCDIR)/path.c \
520 $(SRCDIR)/piechart.c \
521 $(SRCDIR)/pikchr.c \
522 $(SRCDIR)/pikchrshow.c \
523 $(SRCDIR)/pivot.c \
524 $(SRCDIR)/popen.c \
525 $(SRCDIR)/pqueue.c \
526 $(SRCDIR)/printf.c \
@@ -775,11 +774,10 @@
775 $(OBJDIR)/moderate_.c \
776 $(OBJDIR)/name_.c \
777 $(OBJDIR)/patch_.c \
778 $(OBJDIR)/path_.c \
779 $(OBJDIR)/piechart_.c \
780 $(OBJDIR)/pikchr_.c \
781 $(OBJDIR)/pikchrshow_.c \
782 $(OBJDIR)/pivot_.c \
783 $(OBJDIR)/popen_.c \
784 $(OBJDIR)/pqueue_.c \
785 $(OBJDIR)/printf_.c \
@@ -925,11 +923,10 @@
925 $(OBJDIR)/moderate.o \
926 $(OBJDIR)/name.o \
927 $(OBJDIR)/patch.o \
928 $(OBJDIR)/path.o \
929 $(OBJDIR)/piechart.o \
930 $(OBJDIR)/pikchr.o \
931 $(OBJDIR)/pikchrshow.o \
932 $(OBJDIR)/pivot.o \
933 $(OBJDIR)/popen.o \
934 $(OBJDIR)/pqueue.o \
935 $(OBJDIR)/printf.o \
@@ -1025,16 +1022,16 @@
1025
1026 all: $(OBJDIR) $(APPNAME)
1027
1028 $(OBJDIR)/fossil.o: $(SRCDIR)/../win/fossil.rc $(OBJDIR)/VERSION.h
1029 ifdef USE_WINDOWS
1030 $(CAT) $(subst /,\,$(SRCDIR)\miniz.c) | $(GREP) "define MZ_VERSION" > $(subst /,\,$(OBJDIR)\minizver.h)
1031 $(CP) $(subst /,\,$(SRCDIR)\..\win\fossil.rc) $(subst /,\,$(OBJDIR))
1032 $(CP) $(subst /,\,$(SRCDIR)\..\win\fossil.ico) $(subst /,\,$(OBJDIR))
1033 $(CP) $(subst /,\,$(SRCDIR)\..\win\fossil.exe.manifest) $(subst /,\,$(OBJDIR))
1034 else
1035 $(CAT) $(SRCDIR)/miniz.c | $(GREP) "define MZ_VERSION" > $(OBJDIR)/minizver.h
1036 $(CP) $(SRCDIR)/../win/fossil.rc $(OBJDIR)
1037 $(CP) $(SRCDIR)/../win/fossil.ico $(OBJDIR)
1038 $(CP) $(SRCDIR)/../win/fossil.exe.manifest $(OBJDIR)
1039 endif
1040 $(RCC) $(OBJDIR)/fossil.rc -o $(OBJDIR)/fossil.o
@@ -1112,14 +1109,14 @@
1112 SQLITE3_SRC.0 = $(SRCDIR.extsrc)/sqlite3.c
1113 SQLITE3_SRC.1 = $(SRCDIR.extsrc)/sqlite3-see.c
1114 # SQLITE3_SRC.2 is set by top-level configure/makefile process.
1115 SQLITE3_SRC. = $(SRCDIR.extsrc)/sqlite3.c
1116 SQLITE3_SRC = $(SRCDIR)/$(SQLITE3_SRC.$(SQLITE3_ORIGIN))
1117 SQLITE3_SHELL_SRC.0 = $(SRCDIR)/shell.c
1118 SQLITE3_SHELL_SRC.1 = $(SRCDIR)/shell-see.c
1119 # SQLITE3_SHELL_SRC.2 comes from the configure process
1120 SQLITE3_SHELL_SRC. = $(SRCDIR)/shell.c
1121 SQLITE3_SHELL_SRC = $(SQLITE3_SHELL_SRC.$(SQLITE3_ORIGIN))
1122 SEE_FLAGS.0 =
1123 SEE_FLAGS.1 = -DSQLITE_HAS_CODEC -DSQLITE_SHELL_DBKEY_PROC=fossil_key
1124 SEE_FLAGS. =
1125 SEE_FLAGS = $(SEE_FLAGS.$(USE_SEE))
@@ -1297,11 +1294,10 @@
1297 $(OBJDIR)/moderate_.c:$(OBJDIR)/moderate.h \
1298 $(OBJDIR)/name_.c:$(OBJDIR)/name.h \
1299 $(OBJDIR)/patch_.c:$(OBJDIR)/patch.h \
1300 $(OBJDIR)/path_.c:$(OBJDIR)/path.h \
1301 $(OBJDIR)/piechart_.c:$(OBJDIR)/piechart.h \
1302 $(OBJDIR)/pikchr_.c:$(OBJDIR)/pikchr.h \
1303 $(OBJDIR)/pikchrshow_.c:$(OBJDIR)/pikchrshow.h \
1304 $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \
1305 $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h \
1306 $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h \
1307 $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h \
@@ -1351,11 +1347,11 @@
1351 $(OBJDIR)/wikiformat_.c:$(OBJDIR)/wikiformat.h \
1352 $(OBJDIR)/winfile_.c:$(OBJDIR)/winfile.h \
1353 $(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h \
1354 $(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h \
1355 $(OBJDIR)/xfersetup_.c:$(OBJDIR)/xfersetup.h \
1356 $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h \
1357 $(SRCDIR.extsrc)/sqlite3.h \
1358 $(SRCDIR)/th.h \
1359 $(OBJDIR)/VERSION.h
1360 echo Done >$(OBJDIR)/headers
1361
@@ -2105,18 +2101,10 @@
2105 $(OBJDIR)/piechart.o: $(OBJDIR)/piechart_.c $(OBJDIR)/piechart.h $(SRCDIR)/config.h
2106 $(XTCC) -o $(OBJDIR)/piechart.o -c $(OBJDIR)/piechart_.c
2107
2108 $(OBJDIR)/piechart.h: $(OBJDIR)/headers
2109
2110 $(OBJDIR)/pikchr_.c: $(SRCDIR)/pikchr.c $(TRANSLATE)
2111 $(TRANSLATE) $(SRCDIR)/pikchr.c >$@
2112
2113 $(OBJDIR)/pikchr.o: $(OBJDIR)/pikchr_.c $(OBJDIR)/pikchr.h $(SRCDIR)/config.h
2114 $(XTCC) -o $(OBJDIR)/pikchr.o -c $(OBJDIR)/pikchr_.c
2115
2116 $(OBJDIR)/pikchr.h: $(OBJDIR)/headers
2117
2118 $(OBJDIR)/pikchrshow_.c: $(SRCDIR)/pikchrshow.c $(TRANSLATE)
2119 $(TRANSLATE) $(SRCDIR)/pikchrshow.c >$@
2120
2121 $(OBJDIR)/pikchrshow.o: $(OBJDIR)/pikchrshow_.c $(OBJDIR)/pikchrshow.h $(SRCDIR)/config.h
2122 $(XTCC) -o $(OBJDIR)/pikchrshow.o -c $(OBJDIR)/pikchrshow_.c
@@ -2621,12 +2609,12 @@
2621
2622 $(OBJDIR)/sqlite3.o: $(SQLITE3_SRC) $(SRCDIR)/../win/Makefile.mingw
2623 $(XTCC) $(SQLITE_OPTIONS) $(SQLITE_CFLAGS) $(SEE_FLAGS) \
2624 -c $(SQLITE3_SRC) -o $@
2625
2626 $(OBJDIR)/cson_amalgamation.o: $(SRCDIR)/cson_amalgamation.c
2627 $(XTCC) -c $(SRCDIR)/cson_amalgamation.c -o $@
2628
2629 $(OBJDIR)/json.o $(OBJDIR)/json_artifact.o $(OBJDIR)/json_branch.o $(OBJDIR)/json_config.o $(OBJDIR)/json_diff.o $(OBJDIR)/json_dir.o $(OBJDIR)/jsos_finfo.o $(OBJDIR)/json_login.o $(OBJDIR)/json_query.o $(OBJDIR)/json_report.o $(OBJDIR)/json_status.o $(OBJDIR)/json_tag.o $(OBJDIR)/json_timeline.o $(OBJDIR)/json_user.o $(OBJDIR)/json_wiki.o : $(SRCDIR)/json_detail.h
2630
2631 $(OBJDIR)/shell.o: $(SQLITE3_SHELL_SRC) $(SRCDIR.extsrc)/sqlite3.h $(SRCDIR)/../win/Makefile.mingw
2632 $(XTCC) $(SHELL_OPTIONS) $(SHELL_CFLAGS) $(SEE_FLAGS) -c $(SQLITE3_SHELL_SRC) -o $@
@@ -2638,8 +2626,11 @@
2638 $(XTCC) -c $(SRCDIR)/th_lang.c -o $@
2639
2640 $(OBJDIR)/th_tcl.o: $(SRCDIR)/th_tcl.c
2641 $(XTCC) -c $(SRCDIR)/th_tcl.c -o $@
2642
2643 $(OBJDIR)/miniz.o: $(SRCDIR)/miniz.c
2644 $(XTCC) $(MINIZ_OPTIONS) -c $(SRCDIR)/miniz.c -o $@
 
 
 
2645
2646
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -516,11 +516,10 @@
516 $(SRCDIR)/moderate.c \
517 $(SRCDIR)/name.c \
518 $(SRCDIR)/patch.c \
519 $(SRCDIR)/path.c \
520 $(SRCDIR)/piechart.c \
 
521 $(SRCDIR)/pikchrshow.c \
522 $(SRCDIR)/pivot.c \
523 $(SRCDIR)/popen.c \
524 $(SRCDIR)/pqueue.c \
525 $(SRCDIR)/printf.c \
@@ -775,11 +774,10 @@
774 $(OBJDIR)/moderate_.c \
775 $(OBJDIR)/name_.c \
776 $(OBJDIR)/patch_.c \
777 $(OBJDIR)/path_.c \
778 $(OBJDIR)/piechart_.c \
 
779 $(OBJDIR)/pikchrshow_.c \
780 $(OBJDIR)/pivot_.c \
781 $(OBJDIR)/popen_.c \
782 $(OBJDIR)/pqueue_.c \
783 $(OBJDIR)/printf_.c \
@@ -925,11 +923,10 @@
923 $(OBJDIR)/moderate.o \
924 $(OBJDIR)/name.o \
925 $(OBJDIR)/patch.o \
926 $(OBJDIR)/path.o \
927 $(OBJDIR)/piechart.o \
 
928 $(OBJDIR)/pikchrshow.o \
929 $(OBJDIR)/pivot.o \
930 $(OBJDIR)/popen.o \
931 $(OBJDIR)/pqueue.o \
932 $(OBJDIR)/printf.o \
@@ -1025,16 +1022,16 @@
1022
1023 all: $(OBJDIR) $(APPNAME)
1024
1025 $(OBJDIR)/fossil.o: $(SRCDIR)/../win/fossil.rc $(OBJDIR)/VERSION.h
1026 ifdef USE_WINDOWS
1027 $(CAT) $(subst /,\,$(SRCDIR.extsrc)\miniz.c) | $(GREP) "define MZ_VERSION" > $(subst /,\,$(OBJDIR)\minizver.h)
1028 $(CP) $(subst /,\,$(SRCDIR)\..\win\fossil.rc) $(subst /,\,$(OBJDIR))
1029 $(CP) $(subst /,\,$(SRCDIR)\..\win\fossil.ico) $(subst /,\,$(OBJDIR))
1030 $(CP) $(subst /,\,$(SRCDIR)\..\win\fossil.exe.manifest) $(subst /,\,$(OBJDIR))
1031 else
1032 $(CAT) $(SRCDIR.extsrc)/miniz.c | $(GREP) "define MZ_VERSION" > $(OBJDIR)/minizver.h
1033 $(CP) $(SRCDIR)/../win/fossil.rc $(OBJDIR)
1034 $(CP) $(SRCDIR)/../win/fossil.ico $(OBJDIR)
1035 $(CP) $(SRCDIR)/../win/fossil.exe.manifest $(OBJDIR)
1036 endif
1037 $(RCC) $(OBJDIR)/fossil.rc -o $(OBJDIR)/fossil.o
@@ -1112,14 +1109,14 @@
1109 SQLITE3_SRC.0 = $(SRCDIR.extsrc)/sqlite3.c
1110 SQLITE3_SRC.1 = $(SRCDIR.extsrc)/sqlite3-see.c
1111 # SQLITE3_SRC.2 is set by top-level configure/makefile process.
1112 SQLITE3_SRC. = $(SRCDIR.extsrc)/sqlite3.c
1113 SQLITE3_SRC = $(SRCDIR)/$(SQLITE3_SRC.$(SQLITE3_ORIGIN))
1114 SQLITE3_SHELL_SRC.0 = $(SRCDIR.extsrc)/shell.c
1115 SQLITE3_SHELL_SRC.1 = $(SRCDIR.extsrc)/shell-see.c
1116 # SQLITE3_SHELL_SRC.2 comes from the configure process
1117 SQLITE3_SHELL_SRC. = $(SRCDIR.extsrc)/shell.c
1118 SQLITE3_SHELL_SRC = $(SQLITE3_SHELL_SRC.$(SQLITE3_ORIGIN))
1119 SEE_FLAGS.0 =
1120 SEE_FLAGS.1 = -DSQLITE_HAS_CODEC -DSQLITE_SHELL_DBKEY_PROC=fossil_key
1121 SEE_FLAGS. =
1122 SEE_FLAGS = $(SEE_FLAGS.$(USE_SEE))
@@ -1297,11 +1294,10 @@
1294 $(OBJDIR)/moderate_.c:$(OBJDIR)/moderate.h \
1295 $(OBJDIR)/name_.c:$(OBJDIR)/name.h \
1296 $(OBJDIR)/patch_.c:$(OBJDIR)/patch.h \
1297 $(OBJDIR)/path_.c:$(OBJDIR)/path.h \
1298 $(OBJDIR)/piechart_.c:$(OBJDIR)/piechart.h \
 
1299 $(OBJDIR)/pikchrshow_.c:$(OBJDIR)/pikchrshow.h \
1300 $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \
1301 $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h \
1302 $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h \
1303 $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h \
@@ -1351,11 +1347,11 @@
1347 $(OBJDIR)/wikiformat_.c:$(OBJDIR)/wikiformat.h \
1348 $(OBJDIR)/winfile_.c:$(OBJDIR)/winfile.h \
1349 $(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h \
1350 $(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h \
1351 $(OBJDIR)/xfersetup_.c:$(OBJDIR)/xfersetup.h \
1352 $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h$(SRCDIR.extsrc)/miniz.c:$(OBJDIR)/miniz.h <<<NEXT_LINE>>>$(SRCDIR.extsrc)/pikchr.c:$(OBJDIR)/pikchr.h <<<NEXT_LINE>>> \
1353 $(SRCDIR.extsrc)/sqlite3.h \
1354 $(SRCDIR)/th.h \
1355 $(OBJDIR)/VERSION.h
1356 echo Done >$(OBJDIR)/headers
1357
@@ -2105,18 +2101,10 @@
2101 $(OBJDIR)/piechart.o: $(OBJDIR)/piechart_.c $(OBJDIR)/piechart.h $(SRCDIR)/config.h
2102 $(XTCC) -o $(OBJDIR)/piechart.o -c $(OBJDIR)/piechart_.c
2103
2104 $(OBJDIR)/piechart.h: $(OBJDIR)/headers
2105
 
 
 
 
 
 
 
 
2106 $(OBJDIR)/pikchrshow_.c: $(SRCDIR)/pikchrshow.c $(TRANSLATE)
2107 $(TRANSLATE) $(SRCDIR)/pikchrshow.c >$@
2108
2109 $(OBJDIR)/pikchrshow.o: $(OBJDIR)/pikchrshow_.c $(OBJDIR)/pikchrshow.h $(SRCDIR)/config.h
2110 $(XTCC) -o $(OBJDIR)/pikchrshow.o -c $(OBJDIR)/pikchrshow_.c
@@ -2621,12 +2609,12 @@
2609
2610 $(OBJDIR)/sqlite3.o: $(SQLITE3_SRC) $(SRCDIR)/../win/Makefile.mingw
2611 $(XTCC) $(SQLITE_OPTIONS) $(SQLITE_CFLAGS) $(SEE_FLAGS) \
2612 -c $(SQLITE3_SRC) -o $@
2613
2614 $(OBJDIR)/cson_amalgamation.o: $(SRCDIR.extsrc)/cson_amalgamation.c
2615 $(XTCC) -c $(SRCDIR.extsrc)/cson_amalgamation.c -o $@
2616
2617 $(OBJDIR)/json.o $(OBJDIR)/json_artifact.o $(OBJDIR)/json_branch.o $(OBJDIR)/json_config.o $(OBJDIR)/json_diff.o $(OBJDIR)/json_dir.o $(OBJDIR)/jsos_finfo.o $(OBJDIR)/json_login.o $(OBJDIR)/json_query.o $(OBJDIR)/json_report.o $(OBJDIR)/json_status.o $(OBJDIR)/json_tag.o $(OBJDIR)/json_timeline.o $(OBJDIR)/json_user.o $(OBJDIR)/json_wiki.o : $(SRCDIR)/json_detail.h
2618
2619 $(OBJDIR)/shell.o: $(SQLITE3_SHELL_SRC) $(SRCDIR.extsrc)/sqlite3.h $(SRCDIR)/../win/Makefile.mingw
2620 $(XTCC) $(SHELL_OPTIONS) $(SHELL_CFLAGS) $(SEE_FLAGS) -c $(SQLITE3_SHELL_SRC) -o $@
@@ -2638,8 +2626,11 @@
2626 $(XTCC) -c $(SRCDIR)/th_lang.c -o $@
2627
2628 $(OBJDIR)/th_tcl.o: $(SRCDIR)/th_tcl.c
2629 $(XTCC) -c $(SRCDIR)/th_tcl.c -o $@
2630
2631 $(OBJDIR)/miniz.o: $(SRCDIR.extsrc)/miniz.c
2632 $(XTCC) $(MINIZ_OPTIONS) -c $(SRCDIR.extsrc)/miniz.c -o $@
2633
2634 $(OBJDIR)/pikchr.o: $(SRCDIR.extsrc)/pikchr.c
2635 $(XTCC) -c $(SRCDIR.extsrc)/pikchr.c -o $@
2636
2637
+8 -12
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -8,10 +8,11 @@
88
# file, edit "makemake.tcl" then run "tclsh makemake.tcl"
99
# to regenerate this file.
1010
#
1111
B = ..
1212
SRCDIR = $(B)\src
13
+SRCDIRX = $(B)\extsrc
1314
T = .
1415
OBJDIR = $(T)
1516
OX = $(OBJDIR)
1617
O = .obj
1718
E = .exe
@@ -459,11 +460,10 @@
459460
"$(OX)\moderate_.c" \
460461
"$(OX)\name_.c" \
461462
"$(OX)\patch_.c" \
462463
"$(OX)\path_.c" \
463464
"$(OX)\piechart_.c" \
464
- "$(OX)\pikchr_.c" \
465465
"$(OX)\pikchrshow_.c" \
466466
"$(OX)\pivot_.c" \
467467
"$(OX)\popen_.c" \
468468
"$(OX)\pqueue_.c" \
469469
"$(OX)\printf_.c" \
@@ -1037,11 +1037,11 @@
10371037
SEE_FLAGS = /DSQLITE_HAS_CODEC=1 /DSQLITE_SHELL_DBKEY_PROC=fossil_key
10381038
SQLITE3_SHELL_SRC = $(SRCDIR)\shell-see.c
10391039
SQLITE3_SRC = $(SRCDIR.extsrc)\sqlite3-see.c
10401040
!else
10411041
SEE_FLAGS =
1042
-SQLITE3_SHELL_SRC = $(SRCDIR)\shell.c
1042
+SQLITE3_SHELL_SRC = $(SRCDIR.extsrc)\shell.c
10431043
SQLITE3_SRC = $(SRCDIR.extsrc)\sqlite3.c
10441044
!endif
10451045
10461046
"$(OX)\shell$O" : "$(SQLITE3_SHELL_SRC)" "$(B)\win\Makefile.msc"
10471047
$(TCC) /Fo$@ /Fd$(@D)\ $(SHELL_OPTIONS) $(SQLITE_OPTIONS) $(SHELL_CFLAGS) $(SEE_FLAGS) -c "$(SQLITE3_SHELL_SRC)"
@@ -1056,20 +1056,23 @@
10561056
$(TCC) /Fo$@ /Fd$(@D)\ -c $**
10571057
10581058
"$(OX)\th_tcl$O" : "$(SRCDIR)\th_tcl.c"
10591059
$(TCC) /Fo$@ /Fd$(@D)\ -c $**
10601060
1061
-"$(OX)\miniz$O" : "$(SRCDIR)\miniz.c"
1061
+"$(OX)\miniz$O" : "$(SRCDIR.extsrc)\miniz.c"
10621062
$(TCC) /Fo$@ /Fd$(@D)\ -c $(MINIZ_OPTIONS) $**
1063
+
1064
+"$(OX)\pikchr$O" : "$(SRCDIR.extsrc)" "$(B)\win\Makefile.msc"
1065
+ $(TCC) /Fo$@ /Fd$(@D)\ -c $**
10631066
10641067
"$(OX)\VERSION.h" : "$(OBJDIR)\mkversion$E" "$(B)\manifest.uuid" "$(B)\manifest" "$(B)\VERSION" "$(B)\phony.h"
10651068
"$(OBJDIR)\mkversion$E" "$(B)\manifest.uuid" "$(B)\manifest" "$(B)\VERSION" > $@
10661069
10671070
"$(B)\phony.h" :
10681071
rem Force rebuild of VERSION.h whenever nmake is run
10691072
1070
-"$(OX)\cson_amalgamation$O" : "$(SRCDIR)\cson_amalgamation.c"
1073
+"$(OX)\cson_amalgamation$O" : "$(SRCDIR.extsrc)\cson_amalgamation.c"
10711074
$(TCC) /Fo$@ /Fd$(@D)\ -c $**
10721075
10731076
"$(OX)\page_index.h": "$(OBJDIR)\mkindex$E" $(SRC)
10741077
$** > $@
10751078
@@ -1790,16 +1793,10 @@
17901793
$(TCC) /Fo$@ /Fd$(@D)\ -c "$(OX)\piechart_.c"
17911794
17921795
"$(OX)\piechart_.c" : "$(SRCDIR)\piechart.c"
17931796
"$(OBJDIR)\translate$E" $** > $@
17941797
1795
-"$(OX)\pikchr$O" : "$(OX)\pikchr_.c" "$(OX)\pikchr.h"
1796
- $(TCC) /Fo$@ /Fd$(@D)\ -c "$(OX)\pikchr_.c"
1797
-
1798
-"$(OX)\pikchr_.c" : "$(SRCDIR)\pikchr.c"
1799
- "$(OBJDIR)\translate$E" $** > $@
1800
-
18011798
"$(OX)\pikchrshow$O" : "$(OX)\pikchrshow_.c" "$(OX)\pikchrshow.h"
18021799
$(TCC) /Fo$@ /Fd$(@D)\ -c "$(OX)\pikchrshow_.c"
18031800
18041801
"$(OX)\pikchrshow_.c" : "$(SRCDIR)\pikchrshow.c"
18051802
"$(OBJDIR)\translate$E" $** > $@
@@ -2217,11 +2214,10 @@
22172214
"$(OX)\moderate_.c":"$(OX)\moderate.h" \
22182215
"$(OX)\name_.c":"$(OX)\name.h" \
22192216
"$(OX)\patch_.c":"$(OX)\patch.h" \
22202217
"$(OX)\path_.c":"$(OX)\path.h" \
22212218
"$(OX)\piechart_.c":"$(OX)\piechart.h" \
2222
- "$(OX)\pikchr_.c":"$(OX)\pikchr.h" \
22232219
"$(OX)\pikchrshow_.c":"$(OX)\pikchrshow.h" \
22242220
"$(OX)\pivot_.c":"$(OX)\pivot.h" \
22252221
"$(OX)\popen_.c":"$(OX)\popen.h" \
22262222
"$(OX)\pqueue_.c":"$(OX)\pqueue.h" \
22272223
"$(OX)\printf_.c":"$(OX)\printf.h" \
@@ -2275,7 +2271,7 @@
22752271
"$(OX)\xfersetup_.c":"$(OX)\xfersetup.h" \
22762272
"$(OX)\zip_.c":"$(OX)\zip.h" \
22772273
"$(SRCDIR.extsrc)\sqlite3.h" \
22782274
"$(SRCDIR)\th.h" \
22792275
"$(OX)\VERSION.h" \
2280
- "$(SRCDIR)\cson_amalgamation.h"
2276
+ "$(SRCDIR.extsrc)\cson_amalgamation.h"
22812277
@copy /Y nul: $@
22822278
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -8,10 +8,11 @@
8 # file, edit "makemake.tcl" then run "tclsh makemake.tcl"
9 # to regenerate this file.
10 #
11 B = ..
12 SRCDIR = $(B)\src
 
13 T = .
14 OBJDIR = $(T)
15 OX = $(OBJDIR)
16 O = .obj
17 E = .exe
@@ -459,11 +460,10 @@
459 "$(OX)\moderate_.c" \
460 "$(OX)\name_.c" \
461 "$(OX)\patch_.c" \
462 "$(OX)\path_.c" \
463 "$(OX)\piechart_.c" \
464 "$(OX)\pikchr_.c" \
465 "$(OX)\pikchrshow_.c" \
466 "$(OX)\pivot_.c" \
467 "$(OX)\popen_.c" \
468 "$(OX)\pqueue_.c" \
469 "$(OX)\printf_.c" \
@@ -1037,11 +1037,11 @@
1037 SEE_FLAGS = /DSQLITE_HAS_CODEC=1 /DSQLITE_SHELL_DBKEY_PROC=fossil_key
1038 SQLITE3_SHELL_SRC = $(SRCDIR)\shell-see.c
1039 SQLITE3_SRC = $(SRCDIR.extsrc)\sqlite3-see.c
1040 !else
1041 SEE_FLAGS =
1042 SQLITE3_SHELL_SRC = $(SRCDIR)\shell.c
1043 SQLITE3_SRC = $(SRCDIR.extsrc)\sqlite3.c
1044 !endif
1045
1046 "$(OX)\shell$O" : "$(SQLITE3_SHELL_SRC)" "$(B)\win\Makefile.msc"
1047 $(TCC) /Fo$@ /Fd$(@D)\ $(SHELL_OPTIONS) $(SQLITE_OPTIONS) $(SHELL_CFLAGS) $(SEE_FLAGS) -c "$(SQLITE3_SHELL_SRC)"
@@ -1056,20 +1056,23 @@
1056 $(TCC) /Fo$@ /Fd$(@D)\ -c $**
1057
1058 "$(OX)\th_tcl$O" : "$(SRCDIR)\th_tcl.c"
1059 $(TCC) /Fo$@ /Fd$(@D)\ -c $**
1060
1061 "$(OX)\miniz$O" : "$(SRCDIR)\miniz.c"
1062 $(TCC) /Fo$@ /Fd$(@D)\ -c $(MINIZ_OPTIONS) $**
 
 
 
1063
1064 "$(OX)\VERSION.h" : "$(OBJDIR)\mkversion$E" "$(B)\manifest.uuid" "$(B)\manifest" "$(B)\VERSION" "$(B)\phony.h"
1065 "$(OBJDIR)\mkversion$E" "$(B)\manifest.uuid" "$(B)\manifest" "$(B)\VERSION" > $@
1066
1067 "$(B)\phony.h" :
1068 rem Force rebuild of VERSION.h whenever nmake is run
1069
1070 "$(OX)\cson_amalgamation$O" : "$(SRCDIR)\cson_amalgamation.c"
1071 $(TCC) /Fo$@ /Fd$(@D)\ -c $**
1072
1073 "$(OX)\page_index.h": "$(OBJDIR)\mkindex$E" $(SRC)
1074 $** > $@
1075
@@ -1790,16 +1793,10 @@
1790 $(TCC) /Fo$@ /Fd$(@D)\ -c "$(OX)\piechart_.c"
1791
1792 "$(OX)\piechart_.c" : "$(SRCDIR)\piechart.c"
1793 "$(OBJDIR)\translate$E" $** > $@
1794
1795 "$(OX)\pikchr$O" : "$(OX)\pikchr_.c" "$(OX)\pikchr.h"
1796 $(TCC) /Fo$@ /Fd$(@D)\ -c "$(OX)\pikchr_.c"
1797
1798 "$(OX)\pikchr_.c" : "$(SRCDIR)\pikchr.c"
1799 "$(OBJDIR)\translate$E" $** > $@
1800
1801 "$(OX)\pikchrshow$O" : "$(OX)\pikchrshow_.c" "$(OX)\pikchrshow.h"
1802 $(TCC) /Fo$@ /Fd$(@D)\ -c "$(OX)\pikchrshow_.c"
1803
1804 "$(OX)\pikchrshow_.c" : "$(SRCDIR)\pikchrshow.c"
1805 "$(OBJDIR)\translate$E" $** > $@
@@ -2217,11 +2214,10 @@
2217 "$(OX)\moderate_.c":"$(OX)\moderate.h" \
2218 "$(OX)\name_.c":"$(OX)\name.h" \
2219 "$(OX)\patch_.c":"$(OX)\patch.h" \
2220 "$(OX)\path_.c":"$(OX)\path.h" \
2221 "$(OX)\piechart_.c":"$(OX)\piechart.h" \
2222 "$(OX)\pikchr_.c":"$(OX)\pikchr.h" \
2223 "$(OX)\pikchrshow_.c":"$(OX)\pikchrshow.h" \
2224 "$(OX)\pivot_.c":"$(OX)\pivot.h" \
2225 "$(OX)\popen_.c":"$(OX)\popen.h" \
2226 "$(OX)\pqueue_.c":"$(OX)\pqueue.h" \
2227 "$(OX)\printf_.c":"$(OX)\printf.h" \
@@ -2275,7 +2271,7 @@
2275 "$(OX)\xfersetup_.c":"$(OX)\xfersetup.h" \
2276 "$(OX)\zip_.c":"$(OX)\zip.h" \
2277 "$(SRCDIR.extsrc)\sqlite3.h" \
2278 "$(SRCDIR)\th.h" \
2279 "$(OX)\VERSION.h" \
2280 "$(SRCDIR)\cson_amalgamation.h"
2281 @copy /Y nul: $@
2282
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -8,10 +8,11 @@
8 # file, edit "makemake.tcl" then run "tclsh makemake.tcl"
9 # to regenerate this file.
10 #
11 B = ..
12 SRCDIR = $(B)\src
13 SRCDIRX = $(B)\extsrc
14 T = .
15 OBJDIR = $(T)
16 OX = $(OBJDIR)
17 O = .obj
18 E = .exe
@@ -459,11 +460,10 @@
460 "$(OX)\moderate_.c" \
461 "$(OX)\name_.c" \
462 "$(OX)\patch_.c" \
463 "$(OX)\path_.c" \
464 "$(OX)\piechart_.c" \
 
465 "$(OX)\pikchrshow_.c" \
466 "$(OX)\pivot_.c" \
467 "$(OX)\popen_.c" \
468 "$(OX)\pqueue_.c" \
469 "$(OX)\printf_.c" \
@@ -1037,11 +1037,11 @@
1037 SEE_FLAGS = /DSQLITE_HAS_CODEC=1 /DSQLITE_SHELL_DBKEY_PROC=fossil_key
1038 SQLITE3_SHELL_SRC = $(SRCDIR)\shell-see.c
1039 SQLITE3_SRC = $(SRCDIR.extsrc)\sqlite3-see.c
1040 !else
1041 SEE_FLAGS =
1042 SQLITE3_SHELL_SRC = $(SRCDIR.extsrc)\shell.c
1043 SQLITE3_SRC = $(SRCDIR.extsrc)\sqlite3.c
1044 !endif
1045
1046 "$(OX)\shell$O" : "$(SQLITE3_SHELL_SRC)" "$(B)\win\Makefile.msc"
1047 $(TCC) /Fo$@ /Fd$(@D)\ $(SHELL_OPTIONS) $(SQLITE_OPTIONS) $(SHELL_CFLAGS) $(SEE_FLAGS) -c "$(SQLITE3_SHELL_SRC)"
@@ -1056,20 +1056,23 @@
1056 $(TCC) /Fo$@ /Fd$(@D)\ -c $**
1057
1058 "$(OX)\th_tcl$O" : "$(SRCDIR)\th_tcl.c"
1059 $(TCC) /Fo$@ /Fd$(@D)\ -c $**
1060
1061 "$(OX)\miniz$O" : "$(SRCDIR.extsrc)\miniz.c"
1062 $(TCC) /Fo$@ /Fd$(@D)\ -c $(MINIZ_OPTIONS) $**
1063
1064 "$(OX)\pikchr$O" : "$(SRCDIR.extsrc)" "$(B)\win\Makefile.msc"
1065 $(TCC) /Fo$@ /Fd$(@D)\ -c $**
1066
1067 "$(OX)\VERSION.h" : "$(OBJDIR)\mkversion$E" "$(B)\manifest.uuid" "$(B)\manifest" "$(B)\VERSION" "$(B)\phony.h"
1068 "$(OBJDIR)\mkversion$E" "$(B)\manifest.uuid" "$(B)\manifest" "$(B)\VERSION" > $@
1069
1070 "$(B)\phony.h" :
1071 rem Force rebuild of VERSION.h whenever nmake is run
1072
1073 "$(OX)\cson_amalgamation$O" : "$(SRCDIR.extsrc)\cson_amalgamation.c"
1074 $(TCC) /Fo$@ /Fd$(@D)\ -c $**
1075
1076 "$(OX)\page_index.h": "$(OBJDIR)\mkindex$E" $(SRC)
1077 $** > $@
1078
@@ -1790,16 +1793,10 @@
1793 $(TCC) /Fo$@ /Fd$(@D)\ -c "$(OX)\piechart_.c"
1794
1795 "$(OX)\piechart_.c" : "$(SRCDIR)\piechart.c"
1796 "$(OBJDIR)\translate$E" $** > $@
1797
 
 
 
 
 
 
1798 "$(OX)\pikchrshow$O" : "$(OX)\pikchrshow_.c" "$(OX)\pikchrshow.h"
1799 $(TCC) /Fo$@ /Fd$(@D)\ -c "$(OX)\pikchrshow_.c"
1800
1801 "$(OX)\pikchrshow_.c" : "$(SRCDIR)\pikchrshow.c"
1802 "$(OBJDIR)\translate$E" $** > $@
@@ -2217,11 +2214,10 @@
2214 "$(OX)\moderate_.c":"$(OX)\moderate.h" \
2215 "$(OX)\name_.c":"$(OX)\name.h" \
2216 "$(OX)\patch_.c":"$(OX)\patch.h" \
2217 "$(OX)\path_.c":"$(OX)\path.h" \
2218 "$(OX)\piechart_.c":"$(OX)\piechart.h" \
 
2219 "$(OX)\pikchrshow_.c":"$(OX)\pikchrshow.h" \
2220 "$(OX)\pivot_.c":"$(OX)\pivot.h" \
2221 "$(OX)\popen_.c":"$(OX)\popen.h" \
2222 "$(OX)\pqueue_.c":"$(OX)\pqueue.h" \
2223 "$(OX)\printf_.c":"$(OX)\printf.h" \
@@ -2275,7 +2271,7 @@
2271 "$(OX)\xfersetup_.c":"$(OX)\xfersetup.h" \
2272 "$(OX)\zip_.c":"$(OX)\zip.h" \
2273 "$(SRCDIR.extsrc)\sqlite3.h" \
2274 "$(SRCDIR)\th.h" \
2275 "$(OX)\VERSION.h" \
2276 "$(SRCDIR.extsrc)\cson_amalgamation.h"
2277 @copy /Y nul: $@
2278

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button