-
Notifications
You must be signed in to change notification settings - Fork 19
Expand file tree
/
Copy pathCompressionLibrary.cpp
More file actions
612 lines (531 loc) · 24 KB
/
Copy pathCompressionLibrary.cpp
File metadata and controls
612 lines (531 loc) · 24 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
#include "Compression.h"
#include "MultiThreading.h"
#include "LZMA/Windows/Synchronization.cpp"
// Ðàñïàêîâàòü äàííûå çàäàííûì ìåòîäîì ñæàòèÿ è âîçâðàòèòü âðåìÿ ðàáîòû â ñåêóíäàõ
int timed_decompress (COMPRESSION_METHOD *compressor, CALLBACK_FUNC *callback, void *auxdata)
{
//SET_JMP_POINT( FREEARC_ERRCODE_GENERAL);
double time0 = GetThreadCPUTime();
int result = compressor->decompress (callback, auxdata);
double time1 = GetThreadCPUTime(), t;
if (time0>=0 && time1>=0 && compressor->addtime>=0)
t = compressor->addtime + time1 - time0;
else
t = -1;
callback ("time", &t, 0, auxdata);
return result;
}
// Ðàñïàêîâàòü äàííûå çàäàííûì ìåòîäîì ñæàòèÿ
int Decompress (char *method, CALLBACK_FUNC *callback, void *auxdata)
{
COMPRESSION_METHOD *compressor = ParseCompressionMethod (method);
if (compressor){
int result = timed_decompress (compressor, callback, auxdata);
delete compressor;
return result;}
else
return FREEARC_ERRCODE_INVALID_COMPRESSOR;
}
// Ïðî÷èòàòü èç âõîäíîãî ïîòîêà îáîçíà÷åíèå ìåòîäà ñæàòèÿ è ðàñïàêîâàòü äàííûå ýòèì ìåòîäîì
int DecompressWithHeader (CALLBACK_FUNC *callback, void *auxdata)
{
char method [MAX_METHOD_STRLEN];
for (int i=0; i<MAX_METHOD_STRLEN; i++)
{
// Ïîñèìâîëüíî ÷èòàåì âõîäíûå äàííûå, ïîêà íå ïðî÷ò¸ì ñèìâîë êîíöà ñòðîêè
callback ("read", &method[i], 1, auxdata);
if (method[i]=='\0')
return Decompress (method, callback, auxdata);
}
return FREEARC_ERRCODE_INVALID_COMPRESSOR; // Ñþäà ìû ïîïàäàåì, åñëè â ïåðâûõ MAX_METHOD_STRLEN ñèìâîëàõ âõîäíûõ äàííûõ íå íàøëîñü ñèìâîëà '\0'
}
// Callback-ôóíêöèÿ ÷òåíèÿ/çàïèñè äëÿ (ðàñ)ïàêîâêè â ïàìÿòè
void *readPtr; // òåêóùàÿ ïîçèöèÿ ÷èòàåìûõ äàííûõ
int readLeft; // ñêîëüêî áàéò åù¸ îñòàëîñü âî âõîäíîì áóôåðå
void *writePtr; // òåêóùàÿ ïîçèöèÿ çàïèñûâàåìûõ äàííûõ
int writeLeft; // ñêîëüêî áàéò åù¸ îñòàëîñü â âûõîäíîì áóôåðå
int ReadWriteMem (const char *what, void *buf, int size, void *callback)
{
if (strequ(what,"read")) {
int read_bytes = readLeft<size ? readLeft : size;
memcpy (buf, readPtr, read_bytes);
readPtr = (uint8*)readPtr+read_bytes;
readLeft -= read_bytes;
return read_bytes;
} else if (strequ(what,"write")) {
if (size>writeLeft) return FREEARC_ERRCODE_OUTBLOCK_TOO_SMALL;
memcpy (writePtr, buf, size);
writePtr = (uint8*)writePtr+size;
writeLeft -= size;
return size;
} else {
return FREEARC_ERRCODE_NOT_IMPLEMENTED;
}
}
// Ðàñïàêîâàòü äàííûå â ïàìÿòè, çàïèñàâ â âûõîäíîé áóôåð íå áîëåå outputSize áàéò.
// Âîçâðàùàåò êîä îøèáêè èëè êîëè÷åñòâî áàéò, çàïèñàííûõ â âûõîäíîé áóôåð
int DecompressMem (char *method, void *input, int inputSize, void *output, int outputSize)
{
readPtr=input, readLeft=inputSize, writePtr=output, writeLeft=outputSize;
int result = Decompress (method, ReadWriteMem, 0);
return result<0 ? result : outputSize-writeLeft;
}
// Ðàñïàêîâàòü äàííûå â ïàìÿòè, çàïèñàâ â âûõîäíîé áóôåð íå áîëåå outputSize áàéò.
// Âîçâðàùàåò êîä îøèáêè èëè êîëè÷åñòâî áàéò, çàïèñàííûõ â âûõîäíîé áóôåð
int DecompressMemWithHeader (void *input, int inputSize, void *output, int outputSize)
{
readPtr=input, readLeft=inputSize, writePtr=output, writeLeft=outputSize;
int result = DecompressWithHeader (ReadWriteMem, 0);
return result<0 ? result : outputSize-writeLeft;
}
#ifndef FREEARC_DECOMPRESS_ONLY
// Óïàêîâàòü äàííûå çàäàííûì ìåòîäîì ñæàòèÿ è âîçâðàòèòü âðåìÿ ðàáîòû â ñåêóíäàõ
int timed_compress (COMPRESSION_METHOD *compressor, CALLBACK_FUNC *callback, void *auxdata)
{
//SET_JMP_POINT( FREEARC_ERRCODE_GENERAL);
double time0 = GetThreadCPUTime();
int result = compressor->compress (callback, auxdata);
double time1 = GetThreadCPUTime(), t;
if (time0>=0 && time1>=0 && compressor->addtime>=0)
t = compressor->addtime + time1 - time0;
else
t = -1;
callback ("time", &t, 0, auxdata);
return result;
}
// Óïàêîâàòü äàííûå çàäàííûì ìåòîäîì ñæàòèÿ
int Compress (char *method, CALLBACK_FUNC *callback, void *auxdata)
{
COMPRESSION_METHOD *compressor = ParseCompressionMethod (method);
if (compressor){
int result = timed_compress (compressor, callback, auxdata);
delete compressor;
return result;}
else
return FREEARC_ERRCODE_INVALID_COMPRESSOR;
}
// Çàïèñàòü â âûõîäíîé ïîòîê îáîçíà÷åíèå ìåòîäà ñæàòèÿ è óïàêîâàòü äàííûå ýòèì ìåòîäîì
int CompressWithHeader (char *method, CALLBACK_FUNC *callback, void *auxdata)
{
COMPRESSION_METHOD *compressor = ParseCompressionMethod (method);
if (compressor){
char canonical_method [MAX_METHOD_STRLEN];
compressor->ShowCompressionMethod (canonical_method);
int result = callback ("write", canonical_method, strlen(canonical_method)+1, auxdata);
if (result>=0) result = timed_compress (compressor, callback, auxdata);
delete compressor;
return result;}
else
return FREEARC_ERRCODE_INVALID_COMPRESSOR;
}
// Óïàêîâàòü äàííûå â ïàìÿòè, çàïèñàâ â âûõîäíîé áóôåð íå áîëåå outputSize áàéò.
// Âîçâðàùàåò êîä îøèáêè èëè êîëè÷åñòâî áàéò, çàïèñàííûõ â âûõîäíîé áóôåð
int CompressMem (char *method, void *input, int inputSize, void *output, int outputSize)
{
readPtr=input, readLeft=inputSize, writePtr=output, writeLeft=outputSize;
int result = Compress (method, ReadWriteMem, 0);
return result<0 ? result : outputSize-writeLeft;
}
// Óïàêîâàòü äàííûå â ïàìÿòè, çàïèñàâ â âûõîäíîé áóôåð íå áîëåå outputSize áàéò.
// Âîçâðàùàåò êîä îøèáêè èëè êîëè÷åñòâî áàéò, çàïèñàííûõ â âûõîäíîé áóôåð
int CompressMemWithHeader (char *method, void *input, int inputSize, void *output, int outputSize)
{
readPtr=input, readLeft=inputSize, writePtr=output, writeLeft=outputSize;
int result = CompressWithHeader (method, ReadWriteMem, 0);
return result<0 ? result : outputSize-writeLeft;
}
// Âûâåñòè â canonical_method êàíîíè÷åñêîå ïðåäñòàâëåíèå ìåòîäà ñæàòèÿ in_method
int CanonizeCompressionMethod (char *method, char *canonical_method)
{
COMPRESSION_METHOD *compressor = ParseCompressionMethod (method);
if (compressor){
compressor->ShowCompressionMethod (canonical_method);
delete compressor;
return FREEARC_OK;}
else
return FREEARC_ERRCODE_INVALID_COMPRESSOR;
}
#define Generate_Getter(GETTER) \
MemSize GETTER (char *method) \
{ \
COMPRESSION_METHOD *compressor = ParseCompressionMethod (method); \
if (compressor){ \
MemSize bytes = compressor->GETTER(); \
delete compressor; \
return bytes;} \
else \
return (MemSize)FREEARC_ERRCODE_INVALID_COMPRESSOR; \
} \
#define Generate_Setter(SETTER) \
int SETTER (char *in_method, MemSize bytes, char *out_method) \
{ \
COMPRESSION_METHOD *compressor = ParseCompressionMethod (in_method); \
if (compressor){ \
compressor->SETTER (bytes); \
compressor->ShowCompressionMethod (out_method); \
delete compressor; \
return FREEARC_OK;} \
else \
return FREEARC_ERRCODE_INVALID_COMPRESSOR; \
} \
// Èíôîðìàöèÿ î ïàìÿòè, íåîáõîäèìîé äëÿ óïàêîâêè/ðàñïàêîâêè, ðàçìåðå ñëîâàðÿ è ðàçìåðå áëîêà.
Generate_Getter(GetCompressionMem)
Generate_Getter(GetDictionary)
Generate_Getter(GetBlockSize)
// Âîçâðàòèòü â out_method íîâûé ìåòîä ñæàòèÿ, íàñòðîåííûé íà èñïîëüçîâàíèå
// ñîîòâåòñòâóþùåãî êîëè÷åñòâà ïàìÿòè ïðè óïàêîâêå/ðàñïàêîâêå èëè ñëîâàðÿ/ðàçìåðà áëîêà
Generate_Setter(SetCompressionMem)
Generate_Setter(SetDecompressionMem)
Generate_Setter(SetDictionary)
Generate_Setter(SetBlockSize)
// Âîçâðàòèòü â out_method íîâûé ìåòîä ñæàòèÿ, óìåíüøèâ, åñëè íåîáõîäèìî,
// èñïîëüçóåìóþ àëãîðèòìîì ïàìÿòü / åãî ñëîâàðü / ðàçìåð áëîêà
Generate_Setter(LimitCompressionMem)
Generate_Setter(LimitDecompressionMem)
Generate_Setter(LimitDictionary)
Generate_Setter(LimitBlockSize)
#endif // !defined (FREEARC_DECOMPRESS_ONLY)
// Èíôîðìàöèÿ î ïàìÿòè, íåîáõîäèìîé äëÿ ðàñïàêîâêè
MemSize GetDecompressionMem (char *method)
{
COMPRESSION_METHOD *compressor = ParseCompressionMethod (method);
if (compressor){
MemSize bytes = compressor->GetDecompressionMem();
delete compressor;
return bytes;}
else
return (MemSize)FREEARC_ERRCODE_INVALID_COMPRESSOR;
}
// Óíèâåðñàëüíûé ìåòîä. Ïàðàìåòðû:
// what: "compress", "decompress", "setCompressionMem", "limitDictionary"...
// data: äàííûå äëÿ îïåðàöèè â ôîðìàòå, çàâèñÿùåì îò êîíêðåòíîé âûïîëíÿåìîé îïåðàöèè
// param&result: ïðîñòîé ÷èñëîâîé ïàðàìåòð, ÷òî äîñòàòî÷íî äëÿ ìíîãèõ èíôîðìàöèîííûõ îïåðàöèé
// Íåèñïîëüçóåìûå ïàðàìåòðû óñòàíàâëèâàþòñÿ â NULL/0. result<0 - êîä îøèáêè
int COMPRESSION_METHOD::doit (char *what, int param, void *data, CALLBACK_FUNC *callback)
{
if (strequ (what, "encryption?")) return 0; // Ýòî àëãîðèòì øèôðîâàíèÿ?
else if (strequ (what, "GetCompressionMem")) return 0; // Îáú¸ì ïàìÿòè, íåîáõîäèìûé äëÿ óïàêîâêè
else if (strequ (what, "GetDecompressionMem")) return 0; // Îáú¸ì ïàìÿòè, íåîáõîäèìûé äëÿ ðàñïàêîâêè
else return FREEARC_ERRCODE_NOT_IMPLEMENTED;
}
// ****************************************************************************************************************************
// Ðàñïàêîâêà äàííûõ, ñæàòûõ öåïî÷êîé ìåòîäîâ *
// ****************************************************************************************************************************
// Ëîêàëüíûå äàííûå îäíîãî ìåòîäà
struct Params
{
CThread thread; // OS thread executing this (de)compression algorithm
int thread_num; // Number of method in chain (0..N-1)
int threads_total; // Total amount of methods in chain (N)
CMETHOD method; // String denoting (de)compression method with its parameters
CALLBACK_FUNC* callback; // Original callback (function that reads data in first method and write data in last one)
void* auxdata; // Original callback parameter
BYTE* buf; // Buffer that points to data sent from i'th thread to i+1'th
int size; // Amount of data in the buf
CManualResetEvent* done; // Set when (de)compression is finished or error was found
int* retcode; // Overall multi_decompress return code
CCriticalSection* retcode_cs; // Ensure single-threaded access to retcode
CSemaphore read;
CSemaphore write;
// Abort multi_decompress and set its exit code
void SetExitCode (int code)
{
CCriticalSectionLock lock(*retcode_cs);
if (*retcode == 0) *retcode = code; // Save into retcode first error code signalled (subsequent error codes may be sequels of the first one)
done->Set();
}
};
static DWORD WINAPI multi_decompress_thread (void *paramPtr);
static int multi_decompress_callback (const char *what, void *buf, int size, void *paramPtr);
// Ðàñïàêîâàòü äàííûå, ñæàòûå öåïî÷êîé ìåòîäîâ
int MultiDecompress (char *_method, CALLBACK_FUNC *callback, void *auxdata)
{
char *method = strdup_msg(_method);
// Ðàçîáü¸ì êîìïðåññîð íà îòäåëüíûå àëãîðèòìû è çàïóñòèì äëÿ êàæäîãî èç íèõ îòäåëüíûé òðåä
CMETHOD cm[MAX_METHODS_IN_COMPRESSOR];
Params param[MAX_METHODS_IN_COMPRESSOR];
int N = split (method, COMPRESSION_METHODS_DELIMITER, cm, MAX_METHODS_IN_COMPRESSOR);
CManualResetEvent done; // Set when (de)compression is finished or error was found
int retcode = 0; // multi_decompress return code
CCriticalSection retcode_cs; // Ensure single-threaded access to retcode
// Create semaphores for inter-thread communication
for (int i=0; i<N; i++)
{
param[i].read .Create(0,1);
param[i].write.Create(0,1);
}
// Start N threads
for (int i=0; i<N; i++)
{
param[i].thread_num = i;
param[i].threads_total = N;
param[i].method = cm[N-1-i]; // ïðè ðàñïàêîâêå ïóñêàåì êèíî çàäîì íàïåð¸ä :D
param[i].callback = callback;
param[i].auxdata = auxdata;
param[i].done = &done;
param[i].retcode = &retcode;
param[i].retcode_cs = &retcode_cs;
param[i].thread.Create (multi_decompress_thread, ¶m[i]);
}
done.Lock(); // wait for error or finish of last thread
// Wait until all threads will be finished and return errcode or 0 at success
for (int i=0; i<N; i++)
param[i].thread.Wait();
//printf("\nreleased %d ", i);
FreeAndNil(method);
return retcode;
}
// Îäèí òðåä ðàñïàêîâêè â multi_decompress
static DWORD WINAPI multi_decompress_thread (void *paramPtr)
{
Params *param = (Params*) paramPtr;
// Íå çàïóñêàòü ýòîò thread, ïîêà íå íà÷àëñÿ âûâîä èç ïðåäûäóùåãî (äëÿ ýêîíîìèè ïàìÿòè)
if (param->thread_num > 0)
param->read.Lock(), // îæèäàåì ðàçðåøåíèÿ íà ÷òåíèå (ïîÿâëåíèÿ äàííûõ â áóôåðå)
param->read.Release(); // âîçâðàùàåì ðàçðåøåíèå íà ÷òåíèå
//printf("\nstarted %d ", param->thread_num);
int ret = Decompress (param->method, multi_decompress_callback, param);
// Abort multi_decompress if decompress() returned error code
if (ret<0)
param->SetExitCode (ret);
// Tell the previous thread that no more data required
if (param->thread_num > 0)
param[-1].size = -1,
param[-1].write.Release();
// Tell the next thread that no more data will be supplied to it
if (param->thread_num < param->threads_total-1)
param->size = -1,
param[+1].read.Release();
// If the last thread finished then no more data will be output, so we can finish multi_decompress
if (param->thread_num == param->threads_total-1)
param->SetExitCode(0);
//printf("\nfinished %d ", param->thread_num);
return 0;
}
// Callback-ôóíêöèÿ ÷òåíèÿ/çàïèñè äëÿ multi_decompress_thread
static int multi_decompress_callback (const char *what, void *_buf, int size, void *paramPtr)
{
Params *param = (Params*) paramPtr;
BYTE *buf = (BYTE*)_buf;
//printf("\n%s %d........ ", what, param->thread_num);
// Çàïèñü äàííûõ â ñëåäóþùèé òðåä
if (strequ(what,"write") && param->thread_num < param->threads_total-1)
{
param->buf = buf;
param->size = size;
param[+1].read.Release(); // äà¸ì ðàçðåøåíèå íà ÷òåíèå (â áóôåðå ïîÿâèëèñü äàííûå)
param->write.Lock(); // îæèäàåì ðàçðåøåíèÿ íà âûõîä (ïîñëå òîãî, êàê âñå äàííûå áóäóò ïðî÷èòàíû)
//printf("\n%s %d -> %d ", what, param->thread_num, param->size<0? -1 : size);
return param->size<0? FREEARC_ERRCODE_NO_MORE_DATA_REQUIRED : size;
}
// ×òåíèå äàííûõ èç ïðåäûäóùåãî òðåäà
else if (strequ(what,"read") && param->thread_num > 0)
{
int prev=0;
loop:
//if (size==0) return prev;
param->read.Lock(); // îæèäàåì ðàçðåøåíèÿ íà ÷òåíèå (ïîÿâëåíèÿ äàííûõ â áóôåðå)
if (param[-1].size < 0) // äàííûõ áîëüøå íå áóäåò - ïðåäûäóùèé òðåä çàâåðø¸í
{
param->read.Release(); // âîçâðàùàåì ðàçðåøåíèå íà ÷òåíèå
//printf("\n%s %d -> %d ", what, param->thread_num, prev);
return prev;
}
else if (size <= param[-1].size)
{
memcpy (buf, param[-1].buf, size);
param[-1].buf += size;
param[-1].size -= size;
param->read.Release(); // âîçâðàùàåì ðàçðåøåíèå íà ÷òåíèå
//printf("\n%s %d -> %d ", what, param->thread_num, prev+size);
return prev+size;
}
else // param[-1].size < size
{
memcpy (buf, param[-1].buf, param[-1].size);
buf += param[-1].size;
size -= param[-1].size;
prev += param[-1].size;
param[-1].write.Release(); // äà¸ì ðàçðåøåíèå íà âûõîä èç çàïèñè (áóôåð ïóñò)
goto loop;
}
}
// ×òåíèå â ïåðâîì òðåäå, çàïèñü â ïîñëåäíåì,
// à òàêæå âñå íåèçâåñòíûå íàóêå çàïðîñû ïåðåäàþòñÿ íà âûïîëíåíèå â îðèãèíàëüíûé callback
else
{
int n = param->callback (what, buf, size, param->auxdata);
//printf("\n%s %d -> %d ", what, param->thread_num, n);
return n;
}
}
// ****************************************************************************************************************************
// ÓÒÈËÈÒÛ *
// ****************************************************************************************************************************
// Ðàçáèòü COMPRESSOR íà îòäåëüíûå àëãîðèòìû ñæàòèÿ/øèôðîâàíèÿ
//void splitCompressor (COMPRESSOR c, ARRAY<CMETHOD> &cm)
// Çàïðîñèòü ñåðâèñ what ìåòîäà ñæàòèÿ method
int CompressionService (char *method, char *what, int param, void *data, CALLBACK_FUNC *callback)
{
COMPRESSION_METHOD *compressor = ParseCompressionMethod (method);
if (compressor){
int result = compressor->doit (what, param, data, callback);
delete compressor;
return result;}
else
return FREEARC_ERRCODE_INVALID_COMPRESSOR;
}
// Ïðîâåðèòü, ÷òî äàííûé êîìïðåññîð âêëþ÷àåò àëãîðèòì øèôðîâàíèÿ
int compressorIsEncrypted (COMPRESSOR c)
{
// Ðàçîáü¸ì êîìïðåññîð íà îòäåëüíûå àëãîðèòìû è ïîèùåì ñðåäè íèõ àëãîðèòì øèôðîâàíèÿ
CMETHOD arr[MAX_METHODS_IN_COMPRESSOR];
split (c, COMPRESSION_METHODS_DELIMITER, arr, MAX_METHODS_IN_COMPRESSOR);
for (CMETHOD *cm=arr; *cm; cm++)
if (CompressionService (*cm, "encryption?") == 1) return TRUE;
return FALSE;
}
// Âû÷èñëèòü, ñêîëüêî ïàìÿòè íóæíî äëÿ ðàñïàêîâêè äàííûõ, ñæàòûõ ýòèì êîìïðåññîðîì
MemSize compressorGetDecompressionMem (COMPRESSOR c)
{
// Ðàçîáü¸ì êîìïðåññîð íà îòäåëüíûå àëãîðèòìû è ïðîñóììèðóåì èõ òðåáîâàíèÿ ê ïàìÿòè
CMETHOD arr[MAX_METHODS_IN_COMPRESSOR];
split (c, COMPRESSION_METHODS_DELIMITER, arr, MAX_METHODS_IN_COMPRESSOR);
MemSize sum=0;
for (CMETHOD *cm=arr; *cm; cm++)
sum += CompressionService (*cm, "GetDecompressionMem");
return sum;
}
// Get/set number of threads used for (de)compression. 0 means "autodetect"
static int CompressionThreads = 1;
int __cdecl GetCompressionThreads (void) {return CompressionThreads;}
void __cdecl SetCompressionThreads (int threads)
{
CompressionThreads = threads==0? 1 : threads;
#ifndef FREEARC_DLL
static FARPROC f = LoadFromDLL ("SetCompressionThreads");
if (f) ((void (__cdecl *)(int)) f) (threads);
#endif
}
// Load accelerated function from facompress.dll
FARPROC LoadFromDLL (char *funcname)
{
#ifdef FREEARC_WIN // Non-Windows platforms aren't yet supported
static bool loaded = FALSE;
static HMODULE dll = NULL;
if (!loaded)
{
loaded = TRUE;
// Get program's executable filename
wchar_t path[MY_FILENAME_MAX];
GetModuleFileNameW (NULL, path, MY_FILENAME_MAX);
// Replace basename part with "facompress.dll"
wchar_t *basename = _tcsrchr (path,L'\\')+1;
_tcscpy (basename, L"facompress.dll");
// Load facompress.dll from the same directory as executable
dll = LoadLibraryW(path);
}
return GetProcAddress (dll, funcname);
#else
return NULL;
#endif
}
// This function cleans up the Compression Library
void compressionLib_cleanup (void)
{
removeTemporaryFiles();
}
// ****************************************************************************************************************************
// ÏÎÄÄÅÐÆÊÀ ÒÀÁËÈÖÛ ÇÀÐÅÃÈÑÒÐÈÐÎÂÀÍÍÛÕ ÐÀÇÁÎÐÙÈÊΠÌÅÒÎÄÎÂ ÑÆÀÒÈß È ÏÎÈÑÊ Â ÝÒÎÉ ÒÀÁËÈÖÅ ÐÅÀËÈÇÀÖÈÈ ×ÈÑÒÎ ÊÎÍÊÐÅÒÍÎÃÎ ÌÅÒÎÄÀ *
// ****************************************************************************************************************************
template <class PARSER>
struct Parser
{
PARSER parser;
void* data;
};
int cmCount = 0; // Êîë-âî çàðåãèñòðèðîâàííûõ ìåòîäîâ ñæàòèÿ
Parser<CM_PARSER> cmTable[MAX_COMPRESSION_METHODS]; // Òàáëèöà, â êîòîðóþ çàïèñûâàþòñÿ âñå çàðåãèñòðèðîâàííûå ïàðñåðû ìåòîäîâ ñæàòèÿ
// Äîáàâèòü íîâûé ìåòîä â ñïèñîê ïîääåðæèâàåìûõ ìåòîäîâ ñæàòèÿ
int AddCompressionMethod (CM_PARSER parser)
{
CHECK (cmCount < elements(cmTable), (s,"INTERNAL ERROR: Overflow of compression methods table"));
cmTable[cmCount++].parser = parser;
return 0;
}
int cmExternalCount = 0; // Êîë-âî çàðåãèñòðèðîâàííûõ âíåøíèõ ìåòîäîâ ñæàòèÿ
Parser<CM_PARSER2> cmExternalTable[MAX_COMPRESSION_METHODS]; // Òàáëèöà, â êîòîðóþ çàïèñûâàþòñÿ âñå çàðåãèñòðèðîâàííûå ïàðñåðû âíåøíèõ ìåòîäîâ ñæàòèÿ
// Î÷èñòèòü òàáëèöó âíåøíèõ óïàêîâùèêîâ
void ClearExternalCompressorsTable (void)
{
static int builtins = -1; if (builtins<0) builtins=cmExternalCount;
cmExternalCount = builtins; // Îñòàâèì òîëüêî âñòðîåííûå îïèñàíèÿ âíåøíèõ óïàêîâùèêîâ
}
// Äîáàâèòü ïàðñåð ìåòîäà ñ äîïîëíèòåëüíûì ïàðàìåòðîì, êîòîðûé äîëæåí áûòü ïåðåäàí ýòîìó ïàðñåðó
int AddExternalCompressionMethod (CM_PARSER2 parser, void *data)
{
CHECK (cmExternalCount < elements(cmExternalTable), (s,"INTERNAL ERROR: Overflow of external compression methods table"));
cmExternalTable[cmExternalCount].parser = parser;
cmExternalTable[cmExternalCount].data = data;
cmExternalCount++;
return 0;
}
// Ñêîíñòðóèðîâàòü îáúåêò êëàññà COMPRESSION_METHOD, ðåàëèçóþùèé ìåòîä, çàäàííûé â âèäå ñòðîêè `method`
COMPRESSION_METHOD *ParseCompressionMethod (char* method)
{
// Ïðåâðàòèì ñòðîêó ìåòîäà ñæàòèÿ â ìàññèâ ñòðîê `parameters`, õðàíÿùèé åãî íàçâàíèå è ïàðàìåòðû
char* parameters [MAX_PARAMETERS];
char local_method [MAX_METHOD_STRLEN];
strncopy (local_method, method, sizeof (local_method));
split (local_method, COMPRESSION_METHOD_PARAMETERS_DELIMITER, parameters, MAX_PARAMETERS);
// Ïåðåáåð¸ì âñå çàðåãèñòðèðîâàííûå ïàðñåðû ìåòîäîâ ñæàòèÿ è íàéä¸ì òîò, êîòîðûé ñìîæåò îïîçíàòü `parameters`
iterate_var (i, cmExternalCount) {
COMPRESSION_METHOD *m = (*cmExternalTable[i].parser) (parameters, cmExternalTable[i].data);
if (m) return m;
}
iterate_var (i, cmCount) {
COMPRESSION_METHOD *m = (*cmTable[i].parser) (parameters);
if (m) return m;
}
return NULL; // Ïîëó÷åííûé ìåòîä ñæàòèÿ íå îïîçíàí íè îäíèì èç ïàðñåðîâ
}
// ***********************************************************************************************************************
// Ðåàëèçàöèÿ êëàññà STORING *
// ***********************************************************************************************************************
// Ôóíêöèÿ "(ðàñ)ïàêîâêè", êîïèðóþùàÿ äàííûå îäèí â îäèí
int copy_data (CALLBACK_FUNC *callback, void *auxdata)
{
char buf[BUFFER_SIZE]; int len;
while ((len = callback ("read", buf, BUFFER_SIZE, auxdata)) > 0) {
if ((len = callback ("write", buf, len, auxdata)) < 0) break;
}
return len;
}
// Ôóíêöèÿ ðàñïàêîâêè
int STORING_METHOD::decompress (CALLBACK_FUNC *callback, void *auxdata)
{
return copy_data (callback, auxdata);
}
#ifndef FREEARC_DECOMPRESS_ONLY
// Ôóíêöèÿ óïàêîâêè
int STORING_METHOD::compress (CALLBACK_FUNC *callback, void *auxdata)
{
return copy_data (callback, auxdata);
}
// Çàïèñàòü â buf[MAX_METHOD_STRLEN] ñòðîêó, îïèñûâàþùóþ ìåòîä ñæàòèÿ (ôóíêöèÿ, îáðàòíàÿ ê parse_STORING)
void STORING_METHOD::ShowCompressionMethod (char *buf)
{
sprintf (buf, "storing");
}
#endif // !defined (FREEARC_DECOMPRESS_ONLY)
// Êîíñòðóèðóåò îáúåêò òèïà STORING_METHOD èëè âîçâðàùàåò NULL, åñëè ýòî äðóãîé ìåòîä ñæàòèÿ
COMPRESSION_METHOD* parse_STORING (char** parameters)
{
if (strcmp (parameters[0], "storing") == 0
&& parameters[1]==NULL )
// Åñëè íàçâàíèå ìåòîäà - "storing" è ïàðàìåòðîâ ó íåãî íåò, òî ýòî íàø ìåòîä
return new STORING_METHOD;
else
return NULL; // Ýòî íå ìåòîä storing
}
static int STORING_x = AddCompressionMethod (parse_STORING); // Çàðåãèñòðèðóåì ïàðñåð ìåòîäà STORING_METHOD