TNB Library
TnbSlideCompressor.h
[詳解]
1#pragma once
13#include "TnbVector.h"
15
16
17
18//TNB Library
19namespace TNB
20{
21
22
23
48{
49 #define TNB_SLD_HEAD "SLD"
50 #define TNB_SLD_NON TNB_SLD_HEAD "0"
51 #define TNB_SLD_LV1 TNB_SLD_HEAD "1"
53 enum
54 {
55 DIC_SIZE = 4096,
56 MAXMATCH = 18,
57 THRESHOLD = 3,
58 NIL = 0,
59 DIC_BIT = 12,
60 };
61
63 struct TBuf
64 {
66 enum
67 {
68 DIC_SIZE = 4096,
69 MAXMATCH = 18,
70 MAX_HASH_VAL= (3 * DIC_SIZE + (DIC_SIZE / 512 + 1) * UCHAR_MAX)
71 };
72 BYTE text[DIC_SIZE * 2 + MAXMATCH];
73 int level[DIC_SIZE + UCHAR_MAX + 1];
74 int childcount[DIC_SIZE + UCHAR_MAX + 1];
75 int position[DIC_SIZE + UCHAR_MAX + 1];
76 int parent[DIC_SIZE * 2];
77 int prev[DIC_SIZE * 2];
78 int next[MAX_HASH_VAL + 1];
79 };
80
81 TBuf* m_ptBuf;
82 int m_iMatchLen;
83 int m_iMatchPos;
84 int m_iPos;
85 int m_iAvail;
86
87 ICollectionT<BYTE> * m_pDstDat;
88 const IConstCollectionT<BYTE>* m_pSrcDat;
89 int m_iSrcPos;
90 int m_iSrcSize;
91
93 int m_Hash(int p, int c)
94 {
95 return ((p) + ((c) << (DIC_BIT - 9)) + DIC_SIZE * 2);
96 }
97
99 void insert_node(void)
100 {
101 TBuf& B = *m_ptBuf;
102 int r, t, q, j;
103 BYTE c, *t1, *t2;
104 //
105 if ( m_iMatchLen >= 4 )
106 {
107 m_iMatchLen--;
108 r = (m_iMatchPos + 1) | DIC_SIZE;
109 while ( (q = B.parent[r]) == NIL )
110 {
111 r = B.next[r];
112 }
113 while ( B.level[q] >= m_iMatchLen )
114 {
115 r = q;
116 q = B.parent[q];
117 }
118 t = q;
119 while ( t < DIC_SIZE )
120 {
121 B.position[t] = m_iPos;
122 t = B.parent[t];
123 }
124 }
125 else
126 {
127 q = B.text[m_iPos] + DIC_SIZE;
128 c = B.text[m_iPos + 1];
129 r = searchchild(q, c);
130 if ( r == NIL )
131 {
132 makechild(q, c, m_iPos);
133 m_iMatchLen = 1;
134 return;
135 }
136 m_iMatchLen = 2;
137 }
138 while ( true )
139 {
140 if ( r >= DIC_SIZE )
141 {
142 j = MAXMATCH;
143 m_iMatchPos = r;
144 }
145 else
146 {
147 j = B.level[r];
148 m_iMatchPos = B.position[r];
149 }
150 if ( m_iMatchPos >= m_iPos )
151 {
152 m_iMatchPos -= DIC_SIZE;
153 }
154 t1 = &B.text[m_iPos + m_iMatchLen];
155 t2 = &B.text[m_iMatchPos + m_iMatchLen];
156 while ( m_iMatchLen < j )
157 {
158 if ( *t1 != *t2 )
159 {
160 split(r);
161 return;
162 }
163 m_iMatchLen++;
164 t1++;
165 t2++;
166 }
167 if ( m_iMatchLen == MAXMATCH )
168 {
169 break;
170 }
171 B.position[r] = m_iPos;
172 q = r;
173 r = searchchild(q, *t1);
174 if ( r == NIL )
175 {
176 makechild(q, *t1, m_iPos);
177 return;
178 }
179 m_iMatchLen++;
180 }
181 t = B.prev[r]; B.prev[m_iPos] = t; B.next[t] = m_iPos;
182 t = B.next[r]; B.next[m_iPos] = t; B.prev[t] = m_iPos;
183 B.parent[m_iPos] = q; B.parent[r] = NIL;
184 B.next[r] = m_iPos;
185 }
186
188 void delete_node(void)
189 {
190 TBuf& B = *m_ptBuf;
191 int r, t, s, u;
192 if ( B.parent[m_iPos] == NIL )
193 {
194 return;
195 }
196 r = B.prev[m_iPos];
197 s = B.next[m_iPos];
198 B.next[r] = s;
199 B.prev[s] = r;
200 r = B.parent[m_iPos];
201 B.parent[m_iPos] = NIL;
202 if ( r >= DIC_SIZE || --B.childcount[r] > 1 )
203 {
204 return;
205 }
206 t = B.position[r];
207 if ( t >= m_iPos )
208 {
209 t -= DIC_SIZE;
210 }
211 s = searchchild(r, B.text[t + B.level[r]]);
212 t = B.prev[s]; u = B.next[s];
213 B.next[t] = u; B.prev[u] = t;
214 t = B.prev[r]; B.next[t] = s; B.prev[s] = t;
215 t = B.next[r]; B.prev[t] = s; B.next[s] = t;
216 B.parent[s] = B.parent[r];
217 B.parent[r] = NIL;
218 B.next[r] = m_iAvail;
219 m_iAvail = r;
220 }
221
223 int searchchild(int q, BYTE c)
224 {
225 TBuf& B = *m_ptBuf;
226 int r;
227 r = B.next[m_Hash(q, c)];
228 B.parent[NIL] = q; /* sentinel */
229 while ( B.parent[r] != q )
230 {
231 r = B.next[r];
232 }
233 return r;
234 }
235
237 void makechild(int q, BYTE c, int r)
238 {
239 TBuf& B = *m_ptBuf;
240 int h, t;
241 h = m_Hash(q, c);
242 t = B.next[h]; B.next[h] = r; B.next[r] = t;
243 B.prev[t] = r; B.prev[r] = h;
244 B.parent[r] = q;
245 B.childcount[q]++;
246 }
247
249 void split(int old)
250 {
251 TBuf& B = *m_ptBuf;
252 int sNew, t;
253 sNew = m_iAvail; m_iAvail = B.next[sNew]; B.childcount[sNew] = 0;
254 t = B.prev[old]; B.prev[sNew] = t; B.next[t] = sNew;
255 t = B.next[old]; B.next[sNew] = t; B.prev[t] = sNew;
256 B.parent[sNew] = B.parent[old];
257 B.level[sNew] = m_iMatchLen;
258 B.position[sNew] = m_iPos;
259 makechild(sNew, B.text[m_iMatchPos + m_iMatchLen], old);
260 makechild(sNew, B.text[m_iPos + m_iMatchLen], m_iPos);
261 }
262
264 bool m_Copy(size_t iLen)
265 {
266 return m_pDstDat->Append(CConstOffsetAdapterT<BYTE>(m_pSrcDat, m_iSrcPos, iLen)) == iLen;
267 }
268
270 int m_Read(LPVOID lpBuf, int iLen)
271 {
272 if ( iLen + m_iSrcPos > m_iSrcSize )
273 {
274 iLen = m_iSrcSize - m_iSrcPos;
275 }
276 BYTE* B = static_cast<BYTE*>(lpBuf);
277 loop ( i, iLen )
278 {
279 *B++ = m_pSrcDat->At(m_iSrcPos++);
280 }
281 return iLen;
282 }
283
285 bool m_Write(LPCVOID lpBuf, size_t iLen)
286 {
287 return m_pDstDat->AddElements(iLen, static_cast<const BYTE*>(lpBuf)) == iLen;
288 }
289
294 bool m_EncodePlain(void)
295 {
296 bool r = true;
297 r &= m_pDstDat->RemoveAll();
298 m_iSrcPos = 0;
299 r &= m_Write(TNB_SLD_NON, 4);
300 r &= m_Write(&m_iSrcSize, 4);
301 r &= m_Write(&m_iSrcSize, 4);
302 r &= m_Copy(m_iSrcSize);
303 return r;
304 }
305
315 bool m_Encode(ICollectionT<BYTE>& _out, const IConstCollectionT<BYTE>& in, bool boIsPlain = false)
316 {
317 bool r = true;
318 TBuf& B = *m_ptBuf;
319 m_pDstDat = &_out;
320 m_pSrcDat = &in;
321 m_iSrcPos = 0;
322 m_iSrcSize = ToInt(m_pSrcDat->GetSize());
323 r &= m_pDstDat->RemoveAll();
324 //
325 if ( m_iSrcSize == 0 || boIsPlain )
326 {
327 // サイズが 0 のは圧縮意味無し
328 return m_EncodePlain();
329 }
330 //--- クラスワーク初期化
331 m_iPos = 0;
332 m_iMatchPos = 0;
333 m_iAvail = 1;
334 m_iPos = DIC_SIZE + MAXMATCH;
335 m_iMatchLen = 0;
336 for ( int i = DIC_SIZE; i <= DIC_SIZE + UCHAR_MAX; i++ )
337 {
338 B.level[i] = 1;
339 }
340 for ( int i = DIC_SIZE; i < DIC_SIZE * 2; i++ )
341 {
342 B.parent[i] = NIL;
343 }
344 for ( int i = 1; i < DIC_SIZE - 1; i++ )
345 {
346 B.next[i] = i + 1;
347 }
348 B.next[DIC_SIZE - 1] = NIL;
349 for ( int i = DIC_SIZE * 2; i <= TBuf::MAX_HASH_VAL; i++ )
350 {
351 B.next[i] = NIL;
352 }
353 //--- ローカルワーク初期化
354 BYTE code[17];
355 BYTE mask = 1;
356 code[0] = 0;
357 int codeptr = 1;
358 int comp_size = 0;
359 //-- ヘッダ書き出し
360 r &= m_Write(TNB_SLD_LV1, 4);
361 r &= m_Write(&m_iSrcSize, 4);
362 r &= m_Write(&m_iSrcSize, 4);
363 //-- 解析
364 int remainder = m_Read(&B.text[m_iPos], DIC_SIZE);
365 insert_node();
366 while ( remainder > 0 )
367 {
368 int lastmatchlen = m_iMatchLen;
369 int lastmatchpos = m_iMatchPos;
370 remainder--;
371 if ( ++m_iPos == DIC_SIZE * 2 )
372 {
373 MemCopy(&B.text[0], &B.text[DIC_SIZE], DIC_SIZE + MAXMATCH);
374 m_Read(&B.text[DIC_SIZE + MAXMATCH], DIC_SIZE);
375 remainder += DIC_SIZE;
376 m_iPos = DIC_SIZE;
377 }
378 delete_node();
379 insert_node();
380 if ( m_iMatchLen > remainder )
381 {
382 m_iMatchLen = remainder;
383 }
384 if ( m_iMatchLen > lastmatchlen || lastmatchlen < THRESHOLD )
385 {
386 code[codeptr++] = B.text[m_iPos - 1];
387 code[0] |= mask;
388 }
389 else
390 {
391 code[codeptr++] = static_cast<BYTE>(m_iPos - 1 - lastmatchpos);
392 code[codeptr++] = static_cast<BYTE>((((m_iPos - 1 - lastmatchpos) >> 4) & 0xf0) | (lastmatchlen - THRESHOLD));
393 remainder = remainder - lastmatchlen + 1;
394 while ( --lastmatchlen > 0 )
395 {
396 if ( ++m_iPos == DIC_SIZE * 2 )
397 {
398 MemCopy(&B.text[0], &B.text[DIC_SIZE], DIC_SIZE + MAXMATCH);
399 m_Read(&B.text[DIC_SIZE + MAXMATCH], DIC_SIZE);
400 remainder += DIC_SIZE;
401 m_iPos = DIC_SIZE;
402 }
403 delete_node();
404 insert_node();
405 }
406 if ( m_iMatchLen > remainder )
407 {
408 m_iMatchLen = remainder;
409 }
410 }
411 if ( (mask <<= 1) == 0 )
412 {
413 if ( comp_size + codeptr + 8 > m_iSrcSize )
414 {
415 // 元よりでかくなってしまう
416 return m_EncodePlain();
417 }
418 r &= m_Write(&code[0], codeptr);
419 comp_size += codeptr;
420 code[0] = 0;
421 codeptr = mask = 1;
422 }
423 }
424 if ( codeptr > 1 )
425 {
426 r &= m_Write(&code[0], codeptr);
427 comp_size += codeptr;
428 }
429 if ( comp_size + 8 > m_iSrcSize )
430 {
431 // 元よりでかくなってしまう
432 return m_EncodePlain();
433 }
434 ASSERTLIB( ToInt(m_pDstDat->GetSize()) == comp_size + 12 );
435 return r;
436 }
437
445 bool m_Decode(ICollectionT<BYTE>& _out, const IConstCollectionT<BYTE>& in)
446 {
447 bool r = true;
448 TBuf& B = *m_ptBuf;
449 m_pDstDat = &_out;
450 m_pSrcDat = &in;
451 m_iSrcPos = 0;
452 m_iSrcSize = ToInt(m_pSrcDat->GetSize());
453 r &= m_pDstDat->RemoveAll();
454 //
455 int fl; //展開後のサイズ
456 //--- Headチェック
457 {
458 BYTE hd[4] = {0};
459 LONG lLen1 = 0;
460 LONG lLen2 = 1;
461 m_Read(hd, 4);
462 if ( memcmp(hd, TNB_SLD_HEAD, 3) != 0 )
463 {
464 return false;
465 }
466 m_Read(&lLen1, 4);
467 m_Read(&lLen2, 4);
468 //
469 if ( lLen1 != lLen2 )
470 {
471 return false;
472 }
473 fl = lLen1; //ファイルの長さ
474 //
475 if ( memcmp(hd, TNB_SLD_NON, 4) == 0 )
476 {
477 //非圧縮
478 if ( m_Copy(fl) && ToInt(m_pDstDat->GetSize()) == fl )
479 {
480 return true;
481 }
482 return false;
483 }
484 }
485 //--- クラスワーク初期化
486 for ( int i = 0; i < DIC_SIZE - MAXMATCH; i++ )
487 {
488 B.text[i] = 0;
489 }
490 //--- ローカルワーク初期化
491 int count = 0;
492 int posi = 0;
493 BYTE flags = 0;
494 //--- 展開
495 while ( true )
496 {
497 if ( count >= fl )
498 {
499 break;
500 }
501 if ( m_Read(&flags, 1) != 1 )
502 {
503 break;
504 }
505 int g = 8;
506 do
507 {
508 if ( (flags & 1) != 0 )
509 {
510 BYTE fd;
511 if ( m_Read(&fd, 1) != 1 )
512 {
513 break;
514 }
515 B.text[posi++] = fd;
516 if ( posi == DIC_SIZE || count + posi >= fl )
517 {
518 r &= m_Write(B.text, posi);
519 count += posi;
520 posi = 0;
521 }
522 }
523 else
524 {
525 BYTE fd[2];
526 if ( m_Read(&fd, 2) != 2 )
527 {
528 break;
529 }
530 int d1=fd[0];
531 int d2=fd[1];
532 d1 |= ((d2 & 0xf0) << 4);
533 d2 = (d2 & 0x0f) + 2;
534 d1 = posi - d1;
535 for ( int k = 0; k <= d2; k++ )
536 {
537 B.text[posi++] = B.text[(d1 + k) & (DIC_SIZE - 1)];
538 if ( posi == DIC_SIZE || count + posi >= fl )
539 {
540 r &= m_Write(B.text, posi);
541 count += posi;
542 posi = 0;
543 }
544 }
545 }
546 flags >>= 1;
547 //
548 if ( count >= fl )
549 {
550 break;
551 }
552 } while ( --g != 0 );
553 }
554 if ( count < fl )
555 {
556 return false;
557 }
558 if ( posi > 0 )
559 {
560 r &= m_Write(B.text, posi);
561 count += posi;
562 }
563 return r;
564 }
565
566public:
567
570 {
571 m_ptBuf = new TBuf;
572 }
573
576 {
577 if ( m_ptBuf != NULL )
578 {
579 delete m_ptBuf;
580 m_ptBuf = NULL;
581 }
582 }
583
594 bool Encode(ICollectionT<BYTE>& _out, const IConstCollectionT<BYTE>& in, bool boIsPlain = false)
595 {
596 return m_Encode(_out, in, boIsPlain);
597 }
598
607 CByteVector Encode(const IConstCollectionT<BYTE>& in, bool boIsPlain = false)
608 {
609 CByteVector vb;
610 vb.SetIncrementSize(in.GetSize() / 2 + 1);
611 if ( ! Encode(vb, in, boIsPlain) )
612 {
613 vb.Invalid();
614 }
615 return vb;
616 }
617
627 {
628 return m_Decode(_out, in);
629 }
630
638 {
639 CByteVector vb;
640 int l = GetSizeAfterDecoding(in);
641 if ( l < 0 )
642 {
643 vb.Invalid();
644 }
645 else
646 {
647 vb.SetIncrementSize(l);
648 if ( ! Decode(vb, in) )
649 {
650 vb.Invalid();
651 }
652 }
653 return vb;
654 }
655
664 {
665 m_pSrcDat = &in;
666 m_iSrcPos = 0;
667 m_iSrcSize = ToInt(m_pSrcDat->GetSize());
668 //
669 BYTE hd[4] = {0};
670 LONG lLen1 = 0;
671 LONG lLen2 = 1;
672 m_Read(hd, 4);
673 if ( memcmp(hd, TNB_SLD_HEAD, 3) != 0 )
674 {
675 return -1;
676 }
677 m_Read(&lLen1, 4);
678 m_Read(&lLen2, 4);
679 if ( lLen1 != lLen2 )
680 {
681 return -1;
682 }
683 return lLen1;
684 }
685
686private:
687 friend class CSlideCompressorTest;
688 #undef TNB_SLD_HEAD
689 #undef TNB_SLD_NON
690 #undef TNB_SLD_LV1
691};
692
693
694
695};//TNB
情報群管理アダプタ関係のヘッダ
#define loop(VAR, CNT)
loop構文.
Definition: TnbDef.h:343
#define TNB_SLD_LV1
圧縮1データヘッダ
#define TNB_SLD_NON
非圧縮データヘッダ
#define TNB_SLD_HEAD
ヘッダベース
配列型情報管理関係のヘッダ
圧縮展開処理クラス
bool Decode(ICollectionT< BYTE > &_out, const IConstCollectionT< BYTE > &in)
[処理] 展開
CByteVector Encode(const IConstCollectionT< BYTE > &in, bool boIsPlain=false)
[処理] 圧縮
CSlideCompressor(void)
コンストラクタ
CByteVector Decode(const IConstCollectionT< BYTE > &in)
[処理] 展開
~CSlideCompressor(void)
デストラクタ
int GetSizeAfterDecoding(const IConstCollectionT< BYTE > &in)
[取得] 展開サイズ
bool Encode(ICollectionT< BYTE > &_out, const IConstCollectionT< BYTE > &in, bool boIsPlain=false)
[処理] 圧縮
void SetIncrementSize(size_t size)
[設定] 余白サイズ
Definition: TnbVector.h:340
void Invalid(void)
[操作] 無効状態にする
Definition: TnbVector.h:604
int ToInt(LPCSTR lpsz, int iBase=10)
[変換] INT変換(ASCII/SJIS用).
Definition: TnbStrLib.h:367
TNB Library
Definition: TnbDoxyTitle.txt:2
void MemCopy(T *_pDst, const void *pSrc, size_t len)
[複製] メモリコピー
Definition: TnbDef.h:376
virtual bool RemoveAll(void)
[削除] 全要素削除 .
virtual size_t AddElements(size_t size, const TYP *P=NULL)
[追加] 複数要素追加.
virtual size_t Append(const IConstCollectionT< TYP > &c)
[追加] 追加.
virtual const TYP & At(INDEX index) const =0
[取得] 要素の参照取得.
virtual size_t GetSize(void) const =0
[取得] 要素数取得.