Upstream tarball 9861
[amule.git] / src / RLE.cpp
blob65672b4ca12c4e4738f107db210a5eca5932f99a
1 //
2 // This file is part of the aMule Project.
3 //
4 // Copyright (c) 2003-2008 aMule Team ( admin@amule.org / http://www.amule.org )
5 //
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
8 // respective authors.
9 //
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.
19 //
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
25 #include "RLE.h"
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 void RLE_Data::setup(int len, bool use_diff, unsigned char * content)
40 m_len = len;
41 m_use_diff = use_diff;
43 if (m_len) {
44 m_buff = new unsigned char[m_len];
45 if (content) {
46 memcpy(m_buff, content, m_len);
47 } else {
48 memset(m_buff, 0, m_len);
51 // in worst case 2-byte sequence encoded as 3. So, data can grow at 1/3
52 m_enc_buff = new unsigned char[m_len*4/3 + 1];
53 } else {
54 m_buff = m_enc_buff = 0;
58 RLE_Data &RLE_Data::operator=(const RLE_Data &obj)
60 if (this == &obj)
61 return *this;
63 delete [] m_buff;
64 delete [] m_enc_buff;
65 setup(obj.m_len, obj.m_use_diff, obj.m_buff);
67 return *this;
70 RLE_Data::~RLE_Data()
72 delete [] m_buff;
73 delete [] m_enc_buff;
76 void RLE_Data::Realloc(int size)
78 if ( size == m_len ) {
79 return;
82 unsigned char *buff = new unsigned char[size];
83 if ( size > m_len ) {
84 memset(buff + m_len, 0, size - m_len);
85 memcpy(buff, m_buff, m_len);
86 } else {
87 memcpy(buff, m_buff, size);
89 delete [] m_buff;
90 m_buff = buff;
92 buff = new unsigned char[size*4/3 + 1];
93 if ( size > m_len ) {
94 memset(buff + m_len*4/3 + 1, 0, (size - m_len)*4/3);
95 memcpy(buff, m_enc_buff, m_len*4/3 + 1);
96 } else {
97 memcpy(buff, m_enc_buff, size*4/3 + 1);
99 delete [] m_enc_buff;
100 m_enc_buff = buff;
102 m_len = size;
105 const unsigned char *RLE_Data::Decode(const unsigned char *buff, int len)
108 // Open RLE
111 int i = 0, j = 0;
112 while ( j != m_len ) {
114 if ( i < (len -1) ) {
115 if (buff[i+1] == buff[i]) {
116 // this is sequence
117 memset(m_enc_buff + j, buff[i], buff[i + 2]);
118 j += buff[i + 2];
119 i += 3;
120 } else {
121 // this is single byte
122 m_enc_buff[j++] = buff[i++];
124 } else {
125 // only 1 byte left in encoded data - it can't be sequence
126 m_enc_buff[j++] = buff[i++];
127 // if there's no more data, but buffer end is not reached,
128 // it must be error in some point
129 if ( j != m_len ) {
130 printf("RLE_Data: decoding error. %d bytes decoded to %d instead of %d\n", len, j, m_len);
132 break;
136 // Recreate data from diff
138 if ( m_use_diff ) {
139 for (int k = 0; k < m_len; k++) {
140 m_buff[k] ^= m_enc_buff[k];
144 return m_buff;
147 void PartFileEncoderData::Decode(unsigned char *gapdata, int gaplen, unsigned char *partdata, int partlen)
149 m_part_status.Decode(partdata, partlen);
151 // in a first dword - real size
152 uint32 gapsize = ENDIAN_NTOHL( RawPeekUInt32( gapdata ) );
153 gapdata += sizeof(uint32);
154 m_gap_status.Realloc(gapsize*2*sizeof(uint64));
156 m_gap_status.Decode(gapdata, gaplen - sizeof(uint32));
159 unsigned char RLE_Data_BV::m_buff[256];
161 RLE_Data_BV::RLE_Data_BV(int len) : m_last_buff(len)
165 int RLE_Data_BV::Encode(std::vector<bool> &data)
167 unsigned char *curr = m_buff;
168 std::vector<bool>::const_iterator i = data.begin();
169 std::vector<bool>::const_iterator j = m_last_buff.begin();
170 while( i != data.end() ) {
171 unsigned char count = 0;
172 while ( (i != data.end()) && ( (*i ^ *j) == false) ) {
173 count++;
174 i++;
175 j++;
177 *curr++ = count;
179 m_last_buff = data;
180 return 0;
183 // File_checked_for_headers