2 // This file is part of the aMule Project.
4 // Copyright (c) 2003-2008 aMule Team ( admin@amule.org / http://www.amule.org )
6 // Any parts of this program derived from the xMule, lMule or eMule project,
7 // or contributed by third-party developers are copyrighted by their
10 // This program is free software; you can redistribute it and/or modify
11 // it under the terms of the GNU General Public License as published by
12 // the Free Software Foundation; either version 2 of the License, or
13 // (at your option) any later version.
15 // This program is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU General Public License for more details.
20 // You should have received a copy of the GNU General Public License
21 // along with this program; if not, write to the Free Software
22 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 #include "ArchSpecific.h"
30 * RLE encoder implementation. This is RLE implementation for very specific
31 * purpose: encode DIFFERENCE between subsequent states of status bar.
33 * This difference is calculated by xor-ing with previous data
35 * We can't use implementation with "control char" since this encoder
36 * will process binary data - not ascii (or unicode) strings
38 RLE_Data::RLE_Data(int len
, bool use_diff
)
41 m_use_diff
= use_diff
;
43 m_buff
= new unsigned char[m_len
];
44 memset(m_buff
, 0, m_len
);
46 // in worst case 2-byte sequence encoded as 3. So, data can grow at 1/3
47 m_enc_buff
= new unsigned char[m_len
*4/3 + 1];
58 RLE_Data::RLE_Data(const RLE_Data
&obj
)
61 m_use_diff
= obj
.m_use_diff
;
63 m_buff
= new unsigned char[m_len
];
64 memcpy(m_buff
, obj
.m_buff
, m_len
);
66 m_enc_buff
= new unsigned char[m_len
*4/3 + 1];
69 RLE_Data
&RLE_Data::operator=(const RLE_Data
&obj
)
73 m_use_diff
= obj
.m_use_diff
;
75 m_buff
= new unsigned char[m_len
];
76 memcpy(m_buff
, obj
.m_buff
, m_len
);
78 m_enc_buff
= new unsigned char[m_len
*4/3 + 1];
93 void RLE_Data::Realloc(int size
)
95 if ( size
== m_len
) {
99 unsigned char *buff
= new unsigned char[size
];
100 if ( size
> m_len
) {
101 memset(buff
+ m_len
, 0, size
- m_len
);
102 memcpy(buff
, m_buff
, m_len
);
104 memcpy(buff
, m_buff
, size
);
109 buff
= new unsigned char[size
*4/3 + 1];
110 if ( size
> m_len
) {
111 memset(buff
+ m_len
*4/3 + 1, 0, (size
- m_len
)*4/3);
112 memcpy(buff
, m_enc_buff
, m_len
*4/3 + 1);
114 memcpy(buff
, m_enc_buff
, size
*4/3 + 1);
116 delete [] m_enc_buff
;
122 const unsigned char *RLE_Data::Decode(const unsigned char *buff
, int len
)
129 while ( j
!= m_len
) {
131 if ( i
< (len
-1) ) {
132 if (buff
[i
+1] == buff
[i
]) {
134 memset(m_enc_buff
+ j
, buff
[i
], buff
[i
+ 2]);
138 // this is single byte
139 m_enc_buff
[j
++] = buff
[i
++];
142 // only 1 byte left in encoded data - it can't be sequence
143 m_enc_buff
[j
++] = buff
[i
++];
144 // if there's no more data, but buffer end is not reached,
145 // it must be error in some point
147 printf("RLE_Data: decoding error. %d bytes decoded to %d instead of %d\n", len
, j
, m_len
);
153 // Recreate data from diff
156 for (int k
= 0; k
< m_len
; k
++) {
157 m_buff
[k
] ^= m_enc_buff
[k
];
164 void PartFileEncoderData::Decode(unsigned char *gapdata
, int gaplen
, unsigned char *partdata
, int partlen
)
166 m_part_status
.Decode(partdata
, partlen
);
168 // in a first dword - real size
169 uint32 gapsize
= ENDIAN_NTOHL( RawPeekUInt32( gapdata
) );
170 gapdata
+= sizeof(uint32
);
171 m_gap_status
.Realloc(gapsize
*2*sizeof(uint64
));
173 m_gap_status
.Decode(gapdata
, gaplen
- sizeof(uint32
));
176 unsigned char RLE_Data_BV::m_buff
[256];
178 RLE_Data_BV::RLE_Data_BV(int len
) : m_last_buff(len
)
182 int RLE_Data_BV::Encode(std::vector
<bool> &data
)
184 unsigned char *curr
= m_buff
;
185 std::vector
<bool>::const_iterator i
= data
.begin();
186 std::vector
<bool>::const_iterator j
= m_last_buff
.begin();
187 while( i
!= data
.end() ) {
188 unsigned char count
= 0;
189 while ( (i
!= data
.end()) && ( (*i
^ *j
) == false) ) {
200 // File_checked_for_headers