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 void Data::MemCpy(size_t &offset, const void *src, size_t size)
00288 {
00289 unsigned char *pd = GetBuffer(offset + size) + offset;
00290 memcpy(pd, src, size);
00291 offset += size;
00292 }
00293
00294 void Data::Append(const void *buf, size_t size)
00295 {
00296
00297 MemCpy(m_datasize, buf, size);
00298 }
00299
00300 istream& operator>> (istream &is, Data &data)
00301 {
00302 data.InputHexLine(is);
00303 return is;
00304 }
00305
00306 ostream& operator<< (ostream &os, const Data &data)
00307 {
00308 data.DumpHex(os);
00309 return os;
00310 }
00311
00312
00313
00314
00315
00316 Diff::Diff(const Data &old, const Data &new_)
00317 : m_old(old), m_new(new_)
00318 {
00319 }
00320
00321 void Diff::Compare(ostream &os, size_t index, size_t size) const
00322 {
00323 size_t min = std::min(m_old.GetSize(), m_new.GetSize());
00324
00325
00326 os << "> ";
00327 os << setbase(16) << setfill('0') << setw(8)
00328 << index << ": ";
00329
00330
00331 for( size_t i = 0; i < size; i++ ) {
00332 size_t address = index + i;
00333
00334
00335 if( address < min ) {
00336 if( m_old.GetData()[address] != m_new.GetData()[address] ) {
00337
00338 os << setbase(16) << setfill('0')
00339 << setw(2) << setprecision(2)
00340 << (unsigned int) m_new.GetData()[address] << ' ';
00341 }
00342 else {
00343
00344 os << " ";
00345 }
00346 }
00347 else {
00348
00349 if( address < m_new.GetSize() ) {
00350
00351 os << setbase(16) << setfill('0')
00352 << setw(2) << setprecision(2)
00353 << (unsigned int) m_new.GetData()[address]
00354 << ' ';
00355 }
00356 else if( address < m_old.GetSize() ) {
00357
00358 os << "XX ";
00359 }
00360 else {
00361
00362 os << " ";
00363 }
00364 }
00365 }
00366
00367
00368 if( Data::PrintAscii() ) {
00369 os << ' ';
00370 for( size_t i = 0; i < size && (index+i) < m_new.GetSize(); i++ ) {
00371 int c = m_new.GetData()[index + i];
00372 os << setbase(10) << (char) (isprint(c) ? c : '.');
00373 }
00374 }
00375
00376 os << "\n";
00377 }
00378
00379 void Diff::Dump(std::ostream &os) const
00380 {
00381 if( m_old.GetSize() != m_new.GetSize() )
00382 os << "sizes differ: "
00383 << m_old.GetSize() << " != " << m_new.GetSize() << endl;
00384
00385 size_t max = std::max(m_old.GetSize(), m_new.GetSize());
00386 for( size_t i = 0; i < max; i += 16 ) {
00387 m_old.DumpHexLine(os, i, 16);
00388 Compare(os, i, 16);
00389 }
00390 }
00391
00392 ostream& operator<< (ostream &os, const Diff &diff)
00393 {
00394 diff.Dump(os);
00395 return os;
00396 }
00397
00398
00399
00400
00401
00402
00403 DBData::DBData()
00404 : m_version(REC_VERSION_1)
00405 , m_localData(new Data)
00406 , m_data(*m_localData)
00407 {
00408 }
00409
00410
00411
00412 DBData::DBData(const void *ValidData, size_t size)
00413 : m_version(REC_VERSION_1)
00414 , m_localData(new Data)
00415 , m_data(*m_localData)
00416 {
00417 }
00418
00419 DBData::DBData(RecordFormatVersion ver,
00420 const std::string &dbName,
00421 uint8_t recType,
00422 uint32_t uniqueId,
00423 size_t offset,
00424 const void *ValidData,
00425 size_t size)
00426 : m_version(ver)
00427 , m_dbName(dbName)
00428 , m_recType(recType)
00429 , m_uniqueId(uniqueId)
00430 , m_offset(offset)
00431 , m_localData(new Data(ValidData, size))
00432 , m_data(*m_localData)
00433 {
00434 }
00435
00436
00437
00438 DBData::DBData(Data &externalData, bool copy)
00439 : m_version(REC_VERSION_1)
00440 , m_localData(copy ? new Data(externalData) : 0)
00441 , m_data(copy ? *m_localData : externalData)
00442 {
00443 }
00444
00445 DBData::DBData(RecordFormatVersion ver,
00446 const std::string &dbName,
00447 uint8_t recType,
00448 uint32_t uniqueId,
00449 size_t offset,
00450 Data &externalData,
00451 bool copy)
00452 : m_version(ver)
00453 , m_dbName(dbName)
00454 , m_recType(recType)
00455 , m_uniqueId(uniqueId)
00456 , m_offset(offset)
00457 , m_localData(copy ? new Data(externalData) : 0)
00458 , m_data(copy ? *m_localData : externalData)
00459 {
00460 }
00461
00462 DBData::~DBData()
00463 {
00464 delete m_localData;
00465 }
00466
00467 Data& DBData::UseData()
00468 {
00469
00470 m_data.GetBuffer();
00471 return m_data;
00472 }
00473
00474
00475
00476
00477
00478
00479 DBData& DBData::operator=(const DBData &other)
00480 {
00481 if( this == &other )
00482 return *this;
00483
00484
00485 m_data = other.m_data;
00486
00487
00488 CopyMeta(other);
00489
00490 return *this;
00491 }
00492
00493
00494
00495
00496 static bool IsEndpointStart(const std::string &line, int &endpoint)
00497 {
00498 if( strncmp(line.c_str(), "sep: ", 5) == 0 ||
00499 strncmp(line.c_str(), "rep: ", 5) == 0 )
00500 {
00501 endpoint = atoi(line.c_str() + 5);
00502 return true;
00503 }
00504 return false;
00505 }
00506
00507 bool LoadDataArray(const string &filename, std::vector<Data> &array)
00508 {
00509 ifstream in(filename.c_str());
00510 return ReadDataArray(in, array);
00511 }
00512
00513 bool ReadDataArray(std::istream &is, std::vector<Data> &array)
00514 {
00515 if( !is )
00516 return false;
00517
00518 bool bInEndpoint = false;
00519 unsigned int nCurrent = 0;
00520 size_t nLargestSize = 0x100;
00521 while( is ) {
00522 string line;
00523 getline(is, line);
00524 int endpoint;
00525 if( bInEndpoint ) {
00526 if( IsHexData(line) ) {
00527 istringstream sline(line);
00528 sline >> array[nCurrent];
00529 continue;
00530 }
00531 else {
00532 nLargestSize = std::max(nLargestSize,
00533 array[nCurrent].GetBufSize());
00534 bInEndpoint = false;
00535 }
00536 }
00537
00538
00539 if( IsEndpointStart(line, endpoint) ) {
00540 bInEndpoint = true;
00541 Data chunk(endpoint, nLargestSize);
00542 array.push_back(chunk);
00543 nCurrent = array.size() - 1;
00544 }
00545 }
00546 return true;
00547 }
00548
00549 }
00550
00551
00552 #ifdef __TEST_MODE__
00553
00554 #include <iostream>
00555 #include <iomanip>
00556 #include "data.h"
00557
00558 using namespace std;
00559
00560 int main()
00561 {
00562 typedef std::vector<Data> DataVec;
00563 DataVec array;
00564 if( !LoadDataArray("data/parsed.log", array) ) {
00565 cout << "Can't load file" << endl;
00566 return 1;
00567 }
00568
00569 DataVec::iterator i = array.begin();
00570 Data::PrintAscii(false);
00571 for( ; i != array.end(); i++ ) {
00572 cout << "Endpoint: " << i->GetEndpoint() << endl;
00573 cout << *i;
00574 cout << "\n\n";
00575 }
00576
00577
00578 Data one, two;
00579 one.GetBuffer()[0] = 0x01;
00580 one.ReleaseBuffer(1);
00581 two.GetBuffer()[0] = 0x02;
00582 two.ReleaseBuffer(2);
00583
00584 cout << Diff(one, two) << endl;
00585 cout << Diff(two, one) << endl;
00586
00587 two.GetBuffer();
00588 two.ReleaseBuffer(32);
00589 cout << Diff(one, two) << endl;
00590 }
00591
00592 #endif
00593