00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "data.h"
00023 #include <fstream>
00024 #include <sstream>
00025 #include <iomanip>
00026 #include <string>
00027 #include <stdexcept>
00028 #include <string.h>
00029 #include <stdlib.h>
00030
00031
00032 #include "debug.h"
00033
00034
00035 using namespace std;
00036
00037
00038 namespace Barry {
00039
00040 inline bool IsHexData(const std::string &s)
00041 {
00042 const char *str = s.c_str();
00043 for( int i = 0; i < 4 && *str; str++, i++ )
00044 if( *str != ' ' )
00045 return false;
00046
00047 for( int i = 0; i < 8 && *str; str++, i++ ) {
00048 const char *hexchars = "0123456789abcdef";
00049 if( strchr(hexchars, *str) == NULL )
00050 return false;
00051 }
00052
00053 if( *str != ':' )
00054 return false;
00055
00056 return true;
00057 }
00058
00059
00060
00061
00062
00063
00064 bool Data::bPrintAscii = true;
00065
00066 Data::Data()
00067 : m_data(new unsigned char[0x4000]),
00068 m_bufsize(0x4000),
00069 m_datasize(0),
00070 m_endpoint(-1),
00071 m_externalData(0),
00072 m_external(false)
00073 {
00074 memset(m_data, 0, m_bufsize);
00075 }
00076
00077 Data::Data(int endpoint, size_t startsize)
00078 : m_data(new unsigned char[startsize]),
00079 m_bufsize(startsize),
00080 m_datasize(0),
00081 m_endpoint(endpoint),
00082 m_externalData(0),
00083 m_external(false)
00084 {
00085 memset(m_data, 0, m_bufsize);
00086 }
00087
00088 Data::Data(const void *ValidData, size_t size)
00089 : m_data(0),
00090 m_bufsize(0),
00091 m_datasize(size),
00092 m_endpoint(-1),
00093 m_externalData((const unsigned char*)ValidData),
00094 m_external(true)
00095 {
00096 }
00097
00098 Data::Data(const Data &other)
00099 : m_data(other.m_bufsize ? new unsigned char[other.m_bufsize] : 0),
00100 m_bufsize(other.m_bufsize),
00101 m_datasize(other.m_datasize),
00102 m_endpoint(other.m_endpoint),
00103 m_externalData(other.m_externalData),
00104 m_external(other.m_external)
00105 {
00106
00107 if( !m_external )
00108 memcpy(m_data, other.m_data, other.m_bufsize);
00109 }
00110
00111 Data::~Data()
00112 {
00113 delete [] m_data;
00114 }
00115
00116 void Data::MakeSpace(size_t desiredsize)
00117 {
00118 if( m_bufsize < desiredsize ) {
00119 desiredsize += 1024;
00120 unsigned char *newbuf = new unsigned char[desiredsize];
00121 memcpy(newbuf, m_data, m_bufsize);
00122 memset(newbuf + m_bufsize, 0, desiredsize - m_bufsize);
00123 delete [] m_data;
00124 m_data = newbuf;
00125 m_bufsize = desiredsize;
00126 }
00127 }
00128
00129
00130 void Data::CopyOnWrite(size_t desiredsize)
00131 {
00132 if( m_external ) {
00133
00134 MakeSpace(std::max(desiredsize, m_datasize));
00135
00136
00137 memcpy(m_data, m_externalData, m_datasize);
00138
00139
00140 m_external = false;
00141 }
00142 }
00143
00144 void Data::InputHexLine(istream &is)
00145 {
00146 unsigned int values[16];
00147 size_t index = 0;
00148
00149 size_t address;
00150 is >> setbase(16) >> address;
00151 if( !is )
00152 return;
00153
00154 is.ignore();
00155
00156 while( is && index < 16 ) {
00157 is >> setbase(16) >> values[index];
00158 if( is )
00159 index++;
00160 }
00161
00162 dout("InputHexLine: read " << index << " bytes");
00163
00164 CopyOnWrite(address + index);
00165 MakeSpace(address + index);
00166 m_datasize = std::max(address + index, m_datasize);
00167 while( index-- )
00168 m_data[address + index] = (unsigned char) values[index];
00169 return;
00170 }
00171
00172 void Data::DumpHexLine(ostream &os, size_t index, size_t size) const
00173 {
00174 ios::fmtflags oldflags = os.setf(ios::right);
00175
00176
00177 os << " ";
00178 os << setbase(16) << setfill('0') << setw(8)
00179 << index << ": ";
00180
00181
00182 for( size_t i = 0; i < size; i++ ) {
00183 if( (index+i) < GetSize() ) {
00184 os << setbase(16) << setfill('0')
00185 << setw(2) << setprecision(2)
00186 << (unsigned int) GetData()[index + i] << ' ';
00187 }
00188 else {
00189 os << " ";
00190 }
00191 }
00192
00193
00194 if( bPrintAscii ) {
00195 locale loc = os.getloc();
00196 os << ' ';
00197 for( size_t i = 0; i < size && (index+i) < GetSize(); i++ ) {
00198 ostream::traits_type::char_type c = GetData()[index + i];
00199 os << setbase(10) << (char) (isprint(c, loc) ? c : '.');
00200 }
00201 }
00202
00203 os << "\n";
00204 os.flags(oldflags);
00205 }
00206
00207 void Data::DumpHex(ostream &os) const
00208 {
00209 for( size_t address = 0; address < GetSize(); address += 16 ) {
00210 DumpHexLine(os, address, 16);
00211 }
00212 }
00213
00214 unsigned char * Data::GetBuffer(size_t requiredsize)
00215 {
00216 CopyOnWrite(requiredsize);
00217 if( requiredsize > 0 )
00218 MakeSpace(requiredsize);
00219 return m_data;
00220 }
00221
00222 void Data::ReleaseBuffer(int datasize)
00223 {
00224 assert( datasize >= 0 || datasize == -1 );
00225 assert( datasize == -1 || (unsigned int)datasize <= m_bufsize );
00226 assert( !m_external );
00227
00228 if( m_external )
00229 return;
00230 if( datasize >= 0 && (unsigned int)datasize > m_bufsize ) {
00231 dout("ReleaseBuffer called with datasize("
00232 << std::dec << datasize << ") > m_bufsize("
00233 << m_bufsize << ")");
00234 return;
00235 }
00236
00237 if( datasize >= 0 ) {
00238 m_datasize = datasize;
00239 }
00240 else {
00241
00242 m_datasize = m_bufsize - 1;
00243 while( m_datasize && m_data[m_datasize] == 0 )
00244 --m_datasize;
00245 }
00246 }
00247
00248
00249 void Data::AppendHexString(const char *str)
00250 {
00251 CopyOnWrite(m_datasize + 512);
00252
00253 std::istringstream iss(str);
00254 unsigned int byte;
00255 while( iss >> hex >> byte ) {
00256 MakeSpace(m_datasize + 1);
00257 m_data[m_datasize] = (unsigned char) byte;
00258 m_datasize++;
00259 }
00260 }
00261
00262
00263 void Data::Zap()
00264 {
00265 if( !m_external )
00266 memset(m_data, 0, m_bufsize);
00267 m_datasize = 0;
00268 }
00269
00270 Data & Data::operator=(const Data &other)
00271 {
00272 if( this == &other )
00273 return *this;
00274
00275
00276 MakeSpace(other.m_bufsize);
00277 memcpy(m_data, other.m_data, other.m_bufsize);
00278
00279
00280 m_datasize = other.m_datasize;
00281 m_endpoint = other.m_endpoint;
00282 m_externalData = other.m_externalData;
00283 m_external = other.m_external;
00284 return *this;
00285 }
00286
00287 istream& operator>> (istream &is, Data &data)
00288 {
00289 data.InputHexLine(is);
00290 return is;
00291 }
00292
00293 ostream& operator<< (ostream &os, const Data &data)
00294 {
00295 data.DumpHex(os);
00296 return os;
00297 }
00298
00299
00300
00301
00302
00303 Diff::Diff(const Data &old, const Data &new_)
00304 : m_old(old), m_new(new_)
00305 {
00306 }
00307
00308 void Diff::Compare(ostream &os, size_t index, size_t size) const
00309 {
00310 size_t min = std::min(m_old.GetSize(), m_new.GetSize());
00311
00312
00313 os << "> ";
00314 os << setbase(16) << setfill('0') << setw(8)
00315 << index << ": ";
00316
00317
00318 for( size_t i = 0; i < size; i++ ) {
00319 size_t address = index + i;
00320
00321
00322 if( address < min ) {
00323 if( m_old.GetData()[address] != m_new.GetData()[address] ) {
00324
00325 os << setbase(16) << setfill('0')
00326 << setw(2) << setprecision(2)
00327 << (unsigned int) m_new.GetData()[address] << ' ';
00328 }
00329 else {
00330
00331 os << " ";
00332 }
00333 }
00334 else {
00335
00336 if( address < m_new.GetSize() ) {
00337
00338 os << setbase(16) << setfill('0')
00339 << setw(2) << setprecision(2)
00340 << (unsigned int) m_new.GetData()[address]
00341 << ' ';
00342 }
00343 else if( address < m_old.GetSize() ) {
00344
00345 os << "XX ";
00346 }
00347 else {
00348
00349 os << " ";
00350 }
00351 }
00352 }
00353
00354
00355 if( Data::PrintAscii() ) {
00356 os << ' ';
00357 for( size_t i = 0; i < size && (index+i) < m_new.GetSize(); i++ ) {
00358 int c = m_new.GetData()[index + i];
00359 os << setbase(10) << (char) (isprint(c) ? c : '.');
00360 }
00361 }
00362
00363 os << "\n";
00364 }
00365
00366 void Diff::Dump(std::ostream &os) const
00367 {
00368 if( m_old.GetSize() != m_new.GetSize() )
00369 os << "sizes differ: "
00370 << m_old.GetSize() << " != " << m_new.GetSize() << endl;
00371
00372 size_t max = std::max(m_old.GetSize(), m_new.GetSize());
00373 for( size_t i = 0; i < max; i += 16 ) {
00374 m_old.DumpHexLine(os, i, 16);
00375 Compare(os, i, 16);
00376 }
00377 }
00378
00379 ostream& operator<< (ostream &os, const Diff &diff)
00380 {
00381 diff.Dump(os);
00382 return os;
00383 }
00384
00385
00386
00387
00388
00389 static bool IsEndpointStart(const std::string &line, int &endpoint)
00390 {
00391 if( strncmp(line.c_str(), "sep: ", 5) == 0 ||
00392 strncmp(line.c_str(), "rep: ", 5) == 0 )
00393 {
00394 endpoint = atoi(line.c_str() + 5);
00395 return true;
00396 }
00397 return false;
00398 }
00399
00400 bool LoadDataArray(const string &filename, std::vector<Data> &array)
00401 {
00402 ifstream in(filename.c_str());
00403 return ReadDataArray(in, array);
00404 }
00405
00406 bool ReadDataArray(std::istream &is, std::vector<Data> &array)
00407 {
00408 if( !is )
00409 return false;
00410
00411 bool bInEndpoint = false;
00412 unsigned int nCurrent = 0;
00413 size_t nLargestSize = 0x100;
00414 while( is ) {
00415 string line;
00416 getline(is, line);
00417 int endpoint;
00418 if( bInEndpoint ) {
00419 if( IsHexData(line) ) {
00420 istringstream sline(line);
00421 sline >> array[nCurrent];
00422 continue;
00423 }
00424 else {
00425 nLargestSize = std::max(nLargestSize,
00426 array[nCurrent].GetBufSize());
00427 bInEndpoint = false;
00428 }
00429 }
00430
00431
00432 if( IsEndpointStart(line, endpoint) ) {
00433 bInEndpoint = true;
00434 Data chunk(endpoint, nLargestSize);
00435 array.push_back(chunk);
00436 nCurrent = array.size() - 1;
00437 }
00438 }
00439 return true;
00440 }
00441
00442 }
00443
00444
00445 #ifdef __TEST_MODE__
00446
00447 #include <iostream>
00448 #include <iomanip>
00449 #include "data.h"
00450
00451 using namespace std;
00452
00453 int main()
00454 {
00455 typedef std::vector<Data> DataVec;
00456 DataVec array;
00457 if( !LoadDataArray("data/parsed.log", array) ) {
00458 cout << "Can't load file" << endl;
00459 return 1;
00460 }
00461
00462 DataVec::iterator i = array.begin();
00463 Data::PrintAscii(false);
00464 for( ; i != array.end(); i++ ) {
00465 cout << "Endpoint: " << i->GetEndpoint() << endl;
00466 cout << *i;
00467 cout << "\n\n";
00468 }
00469
00470
00471 Data one, two;
00472 one.GetBuffer()[0] = 0x01;
00473 one.ReleaseBuffer(1);
00474 two.GetBuffer()[0] = 0x02;
00475 two.ReleaseBuffer(2);
00476
00477 cout << Diff(one, two) << endl;
00478 cout << Diff(two, one) << endl;
00479
00480 two.GetBuffer();
00481 two.ReleaseBuffer(32);
00482 cout << Diff(one, two) << endl;
00483 }
00484
00485 #endif
00486