3 /// Classes to help manage pre-determined data files.
7 Copyright (C) 2005-2007, Net Direct Inc. (http://www.netdirect.ca/)
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18 See the GNU General Public License in the COPYING file at the
19 root directory of this project for more details.
29 //#define __DEBUG_MODE__
38 inline bool IsHexData(const std::string
&s
)
40 const char *str
= s
.c_str();
41 for( int i
= 0; i
< 4 && *str
; str
++, i
++ )
45 for( int i
= 0; i
< 8 && *str
; str
++, i
++ )
46 if( !isdigit(*str
) && !(*str
>= 'a' && *str
<= 'f') )
57 ///////////////////////////////////////////////////////////////////////////////
60 bool Data::bPrintAscii
= true;
63 : m_data(new unsigned char[0x4000]),
70 memset(m_data
, 0, m_bufsize
);
73 Data::Data(int endpoint
, size_t startsize
)
74 : m_data(new unsigned char[startsize
]),
81 memset(m_data
, 0, m_bufsize
);
84 Data::Data(const void *ValidData
, size_t size
)
89 m_externalData((const unsigned char*)ValidData
),
94 Data::Data(const Data
&other
)
95 : m_data(other
.m_bufsize
? new unsigned char[other
.m_bufsize
] : 0),
96 m_bufsize(other
.m_bufsize
),
97 m_datasize(other
.m_datasize
),
98 m_endpoint(other
.m_endpoint
),
99 m_externalData(other
.m_externalData
),
100 m_external(other
.m_external
)
102 // copy over the raw data
104 memcpy(m_data
, other
.m_data
, other
.m_bufsize
);
112 void Data::MakeSpace(size_t desiredsize
)
114 if( m_bufsize
< desiredsize
) {
115 desiredsize
+= 1024; // get a proper chunk
116 unsigned char *newbuf
= new unsigned char[desiredsize
];
117 memcpy(newbuf
, m_data
, m_bufsize
);
118 memset(newbuf
+ m_bufsize
, 0, desiredsize
- m_bufsize
);
121 m_bufsize
= desiredsize
;
125 // perform the copy on write operation if needed
126 void Data::CopyOnWrite(size_t desiredsize
)
130 MakeSpace(std::max(desiredsize
, m_datasize
));
133 memcpy(m_data
, m_externalData
, m_datasize
);
135 // not external anymore
140 void Data::InputHexLine(istream
&is
)
142 unsigned int values
[16];
146 is
>> setbase(16) >> address
;
148 return; // nothing to do
150 is
.ignore(); // eat the ':'
152 while( is
&& index
< 16 ) {
153 is
>> setbase(16) >> values
[index
];
158 dout("InputHexLine: read " << index
<< " bytes");
160 CopyOnWrite(address
+ index
);
161 MakeSpace(address
+ index
); // make space for the new
162 m_datasize
= std::max(address
+ index
, m_datasize
);
164 m_data
[address
+ index
] = (unsigned char) values
[index
];
168 void Data::DumpHexLine(ostream
&os
, size_t index
, size_t size
) const
170 ios::fmtflags oldflags
= os
.setf(ios::right
);
174 os
<< setbase(16) << setfill('0') << setw(8)
178 for( size_t i
= 0; i
< size
; i
++ ) {
179 if( (index
+i
) < GetSize() ) {
180 os
<< setbase(16) << setfill('0')
181 << setw(2) << setprecision(2)
182 << (unsigned int) GetData()[index
+ i
] << ' ';
192 for( size_t i
= 0; i
< size
&& (index
+i
) < GetSize(); i
++ ) {
193 int c
= GetData()[index
+ i
];
194 os
<< setbase(10) << (char) (isprint(c
) ? c
: '.');
202 void Data::DumpHex(ostream
&os
) const
204 for( size_t address
= 0; address
< GetSize(); address
+= 16 ) {
205 DumpHexLine(os
, address
, 16);
209 unsigned char * Data::GetBuffer(size_t requiredsize
)
211 CopyOnWrite(requiredsize
);
212 if( requiredsize
> 0 )
213 MakeSpace(requiredsize
);
217 void Data::ReleaseBuffer(int datasize
)
219 assert( datasize
>= 0 || datasize
== -1 );
220 assert( datasize
== -1 || (unsigned int)datasize
<= m_bufsize
);
221 assert( !m_external
);
225 if( datasize
>= 0 && (unsigned int)datasize
> m_bufsize
) {
226 dout("ReleaseBuffer called with datasize("
227 << std::dec
<< datasize
<< ") > m_bufsize("
228 << m_bufsize
<< ")");
232 if( datasize
>= 0 ) {
233 m_datasize
= datasize
;
236 // search for last non-zero value in buffer
237 m_datasize
= m_bufsize
- 1;
238 while( m_datasize
&& m_data
[m_datasize
] == 0 )
243 /// Append bytes of data based on str
244 void Data::AppendHexString(const char *str
)
246 CopyOnWrite(m_datasize
+ 512);
248 std::istringstream
iss(str
);
250 while( iss
>> hex
>> byte
) {
251 MakeSpace(m_datasize
+ 1);
252 m_data
[m_datasize
] = (unsigned char) byte
;
257 /// set buffer to 0 and remove all data
261 memset(m_data
, 0, m_bufsize
);
265 Data
& Data::operator=(const Data
&other
)
270 // don't remove our current buffer, only grow it if needed
271 MakeSpace(other
.m_bufsize
);
272 memcpy(m_data
, other
.m_data
, other
.m_bufsize
);
274 // then copy over the data state
275 m_datasize
= other
.m_datasize
;
276 m_endpoint
= other
.m_endpoint
;
277 m_externalData
= other
.m_externalData
;
278 m_external
= other
.m_external
;
282 istream
& operator>> (istream
&is
, Data
&data
)
284 data
.InputHexLine(is
);
288 ostream
& operator<< (ostream
&os
, const Data
&data
)
295 ///////////////////////////////////////////////////////////////////////////////
298 Diff::Diff(const Data
&old
, const Data
&new_
)
299 : m_old(old
), m_new(new_
)
303 void Diff::Compare(ostream
&os
, size_t index
, size_t size
) const
305 size_t min
= std::min(m_old
.GetSize(), m_new
.GetSize());
309 os
<< setbase(16) << setfill('0') << setw(8)
313 for( size_t i
= 0; i
< size
; i
++ ) {
314 size_t address
= index
+ i
;
316 // if data is available, print the diff
317 if( address
< min
) {
318 if( m_old
.GetData()[address
] != m_new
.GetData()[address
] ) {
320 os
<< setbase(16) << setfill('0')
321 << setw(2) << setprecision(2)
322 << (unsigned int) m_new
.GetData()[address
] << ' ';
325 // same, just print spaces
330 // one of the buffers is shorter...
331 if( address
< m_new
.GetSize() ) {
332 // new still has data, print it
333 os
<< setbase(16) << setfill('0')
334 << setw(2) << setprecision(2)
335 << (unsigned int) m_new
.GetData()[address
]
338 else if( address
< m_old
.GetSize() ) {
339 // new is out of data and old still has some
343 // no more data, just print spaces
349 // printable data, just dump new
350 if( Data::PrintAscii() ) {
352 for( size_t i
= 0; i
< size
&& (index
+i
) < m_new
.GetSize(); i
++ ) {
353 int c
= m_new
.GetData()[index
+ i
];
354 os
<< setbase(10) << (char) (isprint(c
) ? c
: '.');
361 void Diff::Dump(std::ostream
&os
) const
363 if( m_old
.GetSize() != m_new
.GetSize() )
364 os
<< "sizes differ: "
365 << m_old
.GetSize() << " != " << m_new
.GetSize() << endl
;
367 size_t max
= std::max(m_old
.GetSize(), m_new
.GetSize());
368 for( size_t i
= 0; i
< max
; i
+= 16 ) {
369 m_old
.DumpHexLine(os
, i
, 16);
374 ostream
& operator<< (ostream
&os
, const Diff
&diff
)
381 ///////////////////////////////////////////////////////////////////////////////
384 static bool IsEndpointStart(const std::string
&line
, int &endpoint
)
386 if( strncmp(line
.c_str(), "sep: ", 5) == 0 ||
387 strncmp(line
.c_str(), "rep: ", 5) == 0 )
389 endpoint
= atoi(line
.c_str() + 5);
395 bool LoadDataArray(const string
&filename
, std::vector
<Data
> &array
)
397 ifstream
in(filename
.c_str());
401 bool bInEndpoint
= false;
402 unsigned int nCurrent
= 0;
403 size_t nLargestSize
= 0x100;
409 if( IsHexData(line
) ) {
410 istringstream
sline(line
);
411 sline
>> array
[nCurrent
];
415 nLargestSize
= std::max(nLargestSize
,
416 array
[nCurrent
].GetBufSize());
421 // check if this line starts a new endpoint
422 if( IsEndpointStart(line
, endpoint
) ) {
424 Data
chunk(endpoint
, nLargestSize
);
425 array
.push_back(chunk
);
426 nCurrent
= array
.size() - 1;
445 typedef std::vector
<Data
> DataVec
;
447 if( !LoadDataArray("data/parsed.log", array
) ) {
448 cout
<< "Can't load file" << endl
;
452 DataVec::iterator i
= array
.begin();
453 Data::PrintAscii(false);
454 for( ; i
!= array
.end(); i
++ ) {
455 cout
<< "Endpoint: " << i
->GetEndpoint() << endl
;
462 one
.GetBuffer()[0] = 0x01;
463 one
.ReleaseBuffer(1);
464 two
.GetBuffer()[0] = 0x02;
465 two
.ReleaseBuffer(2);
467 cout
<< Diff(one
, two
) << endl
;
468 cout
<< Diff(two
, one
) << endl
;
471 two
.ReleaseBuffer(32);
472 cout
<< Diff(one
, two
) << endl
;