~ubuntu-branches/ubuntu/wily/qgis/wily

« back to all changes in this revision

Viewing changes to src/core/spatialindex/tools/Tools.cc

  • Committer: Bazaar Package Importer
  • Author(s): Johan Van de Wauw
  • Date: 2010-07-11 20:23:24 UTC
  • mfrom: (3.1.4 squeeze)
  • Revision ID: james.westby@ubuntu.com-20100711202324-5ktghxa7hracohmr
Tags: 1.4.0+12730-3ubuntu1
* Merge from Debian unstable (LP: #540941).
* Fix compilation issues with QT 4.7
* Add build-depends on libqt4-webkit-dev 

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Tools Library
 
2
//
 
3
// Copyright (C) 2004  Navel Ltd.
 
4
//
 
5
// This library is free software; you can redistribute it and/or
 
6
// modify it under the terms of the GNU Lesser General Public
 
7
// License as published by the Free Software Foundation; either
 
8
// version 2.1 of the License, or (at your option) any later version.
 
9
//
 
10
// This library is distributed in the hope that it will be useful,
 
11
// but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
13
// Lesser General Public License for more details.
 
14
//
 
15
// You should have received a copy of the GNU Lesser General Public
 
16
// License along with this library; if not, write to the Free Software
 
17
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
18
//
 
19
//  Email:
 
20
//    mhadji@gmail.com
 
21
 
 
22
#include <cstring>
 
23
#include <limits>
 
24
#include <cfloat>
 
25
#include <Tools.h>
 
26
#include "ExternalSort.h"
 
27
//#include "SHA1.h"
 
28
 
 
29
Tools::IndexOutOfBoundsException::IndexOutOfBoundsException( int i )
 
30
{
 
31
  std::ostringstream s;
 
32
  s << "Invalid index " << i;
 
33
  m_error = s.str();
 
34
}
 
35
 
 
36
std::string Tools::IndexOutOfBoundsException::what()
 
37
{
 
38
  return "IndexOutOfBoundsException: " + m_error;
 
39
}
 
40
 
 
41
Tools::IllegalArgumentException::IllegalArgumentException( std::string s ) : m_error( s )
 
42
{
 
43
}
 
44
 
 
45
std::string Tools::IllegalArgumentException::what()
 
46
{
 
47
  return "IllegalArgumentException: " + m_error;
 
48
}
 
49
 
 
50
Tools::IllegalStateException::IllegalStateException( std::string s ) : m_error( s )
 
51
{
 
52
}
 
53
 
 
54
std::string Tools::IllegalStateException::what()
 
55
{
 
56
  return "IllegalStateException: " + m_error + "\n"; //Please contact " + PACKAGE_BUGREPORT;
 
57
}
 
58
 
 
59
Tools::EndOfStreamException::EndOfStreamException( std::string s ) : m_error( s )
 
60
{
 
61
}
 
62
 
 
63
std::string Tools::EndOfStreamException::what()
 
64
{
 
65
  return "EndOfStreamException: " + m_error;
 
66
}
 
67
 
 
68
Tools::ResourceLockedException::ResourceLockedException( std::string s ) : m_error( s )
 
69
{
 
70
}
 
71
 
 
72
std::string Tools::ResourceLockedException::what()
 
73
{
 
74
  return "ResourceLockedException: " + m_error;
 
75
}
 
76
 
 
77
Tools::InvalidPageException::InvalidPageException( long id )
 
78
{
 
79
  std::ostringstream s;
 
80
  s << "Unknown page id " << id;
 
81
  m_error = s.str();
 
82
}
 
83
 
 
84
std::string Tools::InvalidPageException::what()
 
85
{
 
86
  return "InvalidPageException: " + m_error;
 
87
}
 
88
 
 
89
Tools::NotSupportedException::NotSupportedException( std::string s ) : m_error( s )
 
90
{
 
91
}
 
92
 
 
93
std::string Tools::NotSupportedException::what()
 
94
{
 
95
  return "NotSupportedException: " + m_error;
 
96
}
 
97
 
 
98
Tools::ParseErrorException::ParseErrorException( std::string s ) : m_error( s )
 
99
{
 
100
}
 
101
 
 
102
std::string Tools::ParseErrorException::what()
 
103
{
 
104
  return "ParseErrorException: " + m_error;
 
105
}
 
106
 
 
107
Tools::Variant::Variant() : m_varType( VT_EMPTY )
 
108
{
 
109
}
 
110
 
 
111
Tools::PropertySet::PropertySet( const byte* data )
 
112
{
 
113
  loadFromByteArray( data );
 
114
}
 
115
 
 
116
void Tools::PropertySet::loadFromByteArray( const byte* ptr )
 
117
{
 
118
  m_propertySet.clear();
 
119
 
 
120
  unsigned long numberOfProperties;
 
121
  memcpy( &numberOfProperties, ptr, sizeof( unsigned long ) );
 
122
  ptr += sizeof( unsigned long );
 
123
 
 
124
  Variant v;
 
125
 
 
126
  for ( unsigned long cIndex = 0; cIndex < numberOfProperties; cIndex++ )
 
127
  {
 
128
    std::string s( reinterpret_cast<const char*>( ptr ) );
 
129
    ptr += s.size() + 1;
 
130
    memcpy( &( v.m_varType ), ptr, sizeof( VariantType ) );
 
131
    ptr += sizeof( VariantType );
 
132
 
 
133
    switch ( v.m_varType )
 
134
    {
 
135
      case VT_LONG:
 
136
        long l;
 
137
        memcpy( &l, ptr, sizeof( long ) );
 
138
        ptr += sizeof( long );
 
139
        v.m_val.lVal = l;
 
140
        break;
 
141
      case VT_LONGLONG:
 
142
        long long ll;
 
143
        memcpy( &ll, ptr, sizeof( long long ) );
 
144
        ptr += sizeof( long long );
 
145
        v.m_val.llVal = ll;
 
146
        break;
 
147
      case VT_BYTE:
 
148
        byte b;
 
149
        memcpy( &b, ptr, sizeof( byte ) );
 
150
        ptr += sizeof( byte );
 
151
        v.m_val.bVal = b;
 
152
        break;
 
153
      case VT_SHORT:
 
154
        short s;
 
155
        memcpy( &s, ptr, sizeof( short ) );
 
156
        ptr += sizeof( short );
 
157
        v.m_val.iVal = s;
 
158
        break;
 
159
      case VT_FLOAT:
 
160
        float f;
 
161
        memcpy( &f, ptr, sizeof( float ) );
 
162
        ptr += sizeof( float );
 
163
        v.m_val.fltVal = f;
 
164
        break;
 
165
      case VT_DOUBLE:
 
166
        double d;
 
167
        memcpy( &d, ptr, sizeof( double ) );
 
168
        ptr += sizeof( double );
 
169
        v.m_val.dblVal = d;
 
170
        break;
 
171
      case VT_CHAR:
 
172
        char c;
 
173
        memcpy( &c, ptr, sizeof( char ) );
 
174
        ptr += sizeof( char );
 
175
        v.m_val.cVal = c;
 
176
        break;
 
177
      case VT_USHORT:
 
178
        unsigned short us;
 
179
        memcpy( &us, ptr, sizeof( unsigned short ) );
 
180
        ptr += sizeof( unsigned short );
 
181
        v.m_val.uiVal = us;
 
182
        break;
 
183
      case VT_ULONG:
 
184
        unsigned long ul;
 
185
        memcpy( &ul, ptr, sizeof( unsigned long ) );
 
186
        ptr += sizeof( unsigned long );
 
187
        v.m_val.ulVal = ul;
 
188
        break;
 
189
      case VT_ULONGLONG:
 
190
        unsigned long long ull;
 
191
        memcpy( &ull, ptr, sizeof( unsigned long long ) );
 
192
        ptr += sizeof( unsigned long long );
 
193
        v.m_val.ullVal = ull;
 
194
        break;
 
195
      case VT_INT:
 
196
        int i;
 
197
        memcpy( &i, ptr, sizeof( int ) );
 
198
        ptr += sizeof( int );
 
199
        v.m_val.intVal = i;
 
200
        break;
 
201
      case VT_UINT:
 
202
        unsigned int ui;
 
203
        memcpy( &ui, ptr, sizeof( unsigned int ) );
 
204
        ptr += sizeof( unsigned int );
 
205
        v.m_val.uintVal = ui;
 
206
        break;
 
207
      case VT_BOOL:
 
208
        byte bl;
 
209
        memcpy( &bl, ptr, sizeof( byte ) );
 
210
        ptr += sizeof( byte );
 
211
        v.m_val.blVal = bl != 0;
 
212
        break;
 
213
      default:
 
214
        throw IllegalStateException(
 
215
          "Tools::PropertySet::PropertySet: Deserialization problem."
 
216
        );
 
217
    }
 
218
 
 
219
    m_propertySet.insert( std::pair<std::string, Variant>( s, v ) );
 
220
  }
 
221
}
 
222
 
 
223
unsigned long Tools::PropertySet::getByteArraySize()
 
224
{
 
225
  unsigned long size = sizeof( unsigned long );
 
226
  std::map<std::string, Variant>::iterator it;
 
227
 
 
228
  for ( it = m_propertySet.begin(); it != m_propertySet.end(); it++ )
 
229
  {
 
230
    switch (( *it ).second.m_varType )
 
231
    {
 
232
      case VT_LONG:
 
233
        size += sizeof( long );
 
234
        break;
 
235
      case VT_LONGLONG:
 
236
        size += sizeof( long long );
 
237
        break;
 
238
      case VT_BYTE:
 
239
        size += sizeof( byte );
 
240
        break;
 
241
      case VT_SHORT:
 
242
        size += sizeof( short );
 
243
        break;
 
244
      case VT_FLOAT:
 
245
        size += sizeof( float );
 
246
        break;
 
247
      case VT_DOUBLE:
 
248
        size += sizeof( double );
 
249
        break;
 
250
      case VT_CHAR:
 
251
        size += sizeof( char );
 
252
        break;
 
253
      case VT_USHORT:
 
254
        size += sizeof( unsigned short );
 
255
        break;
 
256
      case VT_ULONG:
 
257
        size += sizeof( unsigned long );
 
258
        break;
 
259
      case VT_ULONGLONG:
 
260
        size += sizeof( unsigned long long );
 
261
        break;
 
262
      case VT_INT:
 
263
        size += sizeof( int );
 
264
        break;
 
265
      case VT_UINT:
 
266
        size += sizeof( unsigned int );
 
267
        break;
 
268
      case VT_BOOL:
 
269
        size += sizeof( byte );
 
270
        break;
 
271
      default:
 
272
        throw NotSupportedException(
 
273
          "Tools::PropertySet::getSize: Unknown type."
 
274
        );
 
275
    }
 
276
    size += ( *it ).first.size() + 1 + sizeof( VariantType );
 
277
  }
 
278
 
 
279
  return size;
 
280
}
 
281
 
 
282
void Tools::PropertySet::storeToByteArray( byte** data, unsigned long& length )
 
283
{
 
284
  length = getByteArraySize();
 
285
  *data = new byte[length];
 
286
  byte* ptr = *data;
 
287
 
 
288
  unsigned long numberOfProperties = m_propertySet.size();
 
289
  memcpy( ptr, &numberOfProperties, sizeof( unsigned long ) );
 
290
  ptr += sizeof( unsigned long );
 
291
 
 
292
  std::map<std::string, Variant>::iterator it;
 
293
 
 
294
  for ( it = m_propertySet.begin(); it != m_propertySet.end(); it++ )
 
295
  {
 
296
    unsigned long strSize = ( *it ).first.size();
 
297
    memcpy( ptr, ( *it ).first.c_str(), strSize );
 
298
    ptr += strSize;
 
299
    *ptr = 0;
 
300
    ptr++;
 
301
 
 
302
    memcpy( ptr, &(( *it ).second.m_varType ), sizeof( VariantType ) );
 
303
    ptr += sizeof( VariantType );
 
304
 
 
305
    switch (( *it ).second.m_varType )
 
306
    {
 
307
      case VT_LONG:
 
308
        memcpy( ptr, &(( *it ).second.m_val.lVal ), sizeof( long ) );
 
309
        ptr += sizeof( long );
 
310
        break;
 
311
      case VT_LONGLONG:
 
312
        memcpy( ptr, &(( *it ).second.m_val.llVal ), sizeof( long long ) );
 
313
        ptr += sizeof( long long );
 
314
        break;
 
315
      case VT_BYTE:
 
316
        memcpy( ptr, &(( *it ).second.m_val.bVal ), sizeof( byte ) );
 
317
        ptr += sizeof( byte );
 
318
        break;
 
319
      case VT_SHORT:
 
320
        memcpy( ptr, &(( *it ).second.m_val.iVal ), sizeof( short ) );
 
321
        ptr += sizeof( short );
 
322
        break;
 
323
      case VT_FLOAT:
 
324
        memcpy( ptr, &(( *it ).second.m_val.fltVal ), sizeof( float ) );
 
325
        ptr += sizeof( float );
 
326
        break;
 
327
      case VT_DOUBLE:
 
328
        memcpy( ptr, &(( *it ).second.m_val.dblVal ), sizeof( double ) );
 
329
        ptr += sizeof( double );
 
330
        break;
 
331
      case VT_CHAR:
 
332
        memcpy( ptr, &(( *it ).second.m_val.cVal ), sizeof( char ) );
 
333
        ptr += sizeof( char );
 
334
        break;
 
335
      case VT_USHORT:
 
336
        memcpy( ptr, &(( *it ).second.m_val.uiVal ), sizeof( unsigned short ) );
 
337
        ptr += sizeof( unsigned short );
 
338
        break;
 
339
      case VT_ULONG:
 
340
        memcpy( ptr, &(( *it ).second.m_val.ulVal ), sizeof( unsigned long ) );
 
341
        ptr += sizeof( unsigned long );
 
342
        break;
 
343
      case VT_ULONGLONG:
 
344
        memcpy( ptr, &(( *it ).second.m_val.ullVal ), sizeof( unsigned long long ) );
 
345
        ptr += sizeof( unsigned long long );
 
346
        break;
 
347
      case VT_INT:
 
348
        memcpy( ptr, &(( *it ).second.m_val.intVal ), sizeof( int ) );
 
349
        ptr += sizeof( int );
 
350
        break;
 
351
      case VT_UINT:
 
352
        memcpy( ptr, &(( *it ).second.m_val.uintVal ), sizeof( unsigned int ) );
 
353
        ptr += sizeof( unsigned int );
 
354
        break;
 
355
      case VT_BOOL:
 
356
        byte bl;
 
357
        bl = ( *it ).second.m_val.blVal;
 
358
        memcpy( ptr, &bl, sizeof( byte ) );
 
359
        ptr += sizeof( byte );
 
360
        break;
 
361
      default:
 
362
        throw NotSupportedException(
 
363
          "Tools::PropertySet::getData: Cannot serialize a variant of this type."
 
364
        );
 
365
    }
 
366
  }
 
367
 
 
368
  assert( ptr == ( *data ) + length );
 
369
}
 
370
 
 
371
Tools::Variant Tools::PropertySet::getProperty( std::string property )
 
372
{
 
373
  std::map<std::string, Variant>::iterator it = m_propertySet.find( property );
 
374
  if ( it != m_propertySet.end() ) return ( *it ).second;
 
375
  else return Variant();
 
376
}
 
377
 
 
378
void Tools::PropertySet::setProperty( std::string property, Variant& v )
 
379
{
 
380
  m_propertySet.insert( std::pair<std::string, Variant>( property, v ) );
 
381
}
 
382
 
 
383
void Tools::PropertySet::removeProperty( std::string property )
 
384
{
 
385
  std::map<std::string, Variant>::iterator it = m_propertySet.find( property );
 
386
  if ( it != m_propertySet.end() ) m_propertySet.erase( it );
 
387
}
 
388
 
 
389
Tools::IObjectStream* Tools::externalSort( IObjectStream& source, unsigned long bufferSize )
 
390
{
 
391
  return new ExternalSort( source, bufferSize );
 
392
 
 
393
}
 
394
 
 
395
Tools::IObjectStream* Tools::externalSort( IObjectStream& source, IObjectComparator& comp, unsigned long bufferSize )
 
396
{
 
397
  return new ExternalSort( source, comp, bufferSize );
 
398
}
 
399
 
 
400
Tools::Interval::Interval() : m_type( IT_RIGHTOPEN ), m_low( 0.0 ), m_high( 0.0 )
 
401
{
 
402
}
 
403
 
 
404
Tools::Interval::Interval( IntervalType t, double l, double h ) : m_type( t ), m_low( l ), m_high( h )
 
405
{
 
406
  assert( l < h );
 
407
}
 
408
 
 
409
Tools::Interval::Interval( double l, double h ) : m_type( IT_RIGHTOPEN ), m_low( l ), m_high( h )
 
410
{
 
411
  assert( l < h );
 
412
}
 
413
 
 
414
Tools::Interval::Interval( const Interval& iv )
 
415
{
 
416
  m_low = iv.m_low;
 
417
  m_high = iv.m_high;
 
418
  m_type = iv.m_type;
 
419
}
 
420
 
 
421
Tools::IInterval& Tools::Interval::operator=( const IInterval & iv )
 
422
{
 
423
  if ( this != &iv )
 
424
  {
 
425
    m_low = iv.getLowerBound();
 
426
    m_high = iv.getUpperBound();
 
427
    m_type = iv.getIntervalType();
 
428
  }
 
429
 
 
430
  return *this;
 
431
}
 
432
 
 
433
Tools::Interval& Tools::Interval::operator=( const Interval & iv )
 
434
{
 
435
  *this = *( static_cast<const IInterval*>( &iv ) );
 
436
  return *this;
 
437
}
 
438
 
 
439
bool Tools::Interval::operator==( const Interval& iv ) const
 
440
{
 
441
  if (
 
442
    m_type == iv.m_type &&
 
443
    m_low >= iv.m_low - std::numeric_limits<double>::epsilon() &&
 
444
    m_low <= iv.m_low + std::numeric_limits<double>::epsilon() &&
 
445
    m_high >= iv.m_high - std::numeric_limits<double>::epsilon() &&
 
446
    m_high <= iv.m_high + std::numeric_limits<double>::epsilon() )
 
447
    return true;
 
448
 
 
449
  return false;
 
450
}
 
451
 
 
452
bool Tools::Interval::operator!=( const Interval& iv ) const
 
453
{
 
454
  return !( *this == iv );
 
455
}
 
456
 
 
457
double Tools::Interval::getLowerBound() const
 
458
{
 
459
  return m_low;
 
460
}
 
461
 
 
462
double Tools::Interval::getUpperBound() const
 
463
{
 
464
  return m_high;
 
465
}
 
466
 
 
467
void Tools::Interval::setBounds( double l, double h )
 
468
{
 
469
  assert( l <= h );
 
470
 
 
471
  m_low = l;
 
472
  m_high = h;
 
473
}
 
474
 
 
475
bool Tools::Interval::intersectsInterval( const IInterval& i ) const
 
476
{
 
477
  return intersectsInterval( i.getIntervalType(), i.getLowerBound(), i.getUpperBound() );
 
478
}
 
479
 
 
480
bool Tools::Interval::intersectsInterval( IntervalType type, const double low, const double high ) const
 
481
{
 
482
  if ( m_high < m_low )
 
483
    throw IllegalStateException(
 
484
      "Tools::Interval::intersectsInterval: high boundary is smaller than low boundary."
 
485
    );
 
486
 
 
487
  if ( m_low > high || m_high < low ) return false;
 
488
  if (( m_low > low && m_low < high ) || ( m_high > low && m_high < high ) ) return true;
 
489
 
 
490
  switch ( m_type )
 
491
  {
 
492
    case IT_CLOSED:
 
493
      if ( m_low == high )
 
494
      {
 
495
        if ( type == IT_CLOSED || type == IT_LEFTOPEN ) return true;
 
496
        else return false;
 
497
      }
 
498
      else if ( m_high == low )
 
499
      {
 
500
        if ( type == IT_CLOSED || type == IT_RIGHTOPEN ) return true;
 
501
        else return false;
 
502
      }
 
503
      break;
 
504
    case IT_OPEN:
 
505
      if ( m_low == high || m_high == low ) return false;
 
506
      break;
 
507
    case IT_RIGHTOPEN:
 
508
      if ( m_low == high )
 
509
      {
 
510
        if ( type == IT_CLOSED || type == IT_LEFTOPEN ) return true;
 
511
        else return false;
 
512
      }
 
513
      else if ( m_high == low )
 
514
      {
 
515
        return false;
 
516
      }
 
517
      break;
 
518
    case IT_LEFTOPEN:
 
519
      if ( m_low == high )
 
520
      {
 
521
        return false;
 
522
      }
 
523
      else if ( m_high == low )
 
524
      {
 
525
        if ( type == IT_CLOSED || type == IT_RIGHTOPEN ) return true;
 
526
        else return false;
 
527
      }
 
528
      break;
 
529
  }
 
530
 
 
531
  return true;
 
532
}
 
533
 
 
534
bool Tools::Interval::containsInterval( const IInterval& i ) const
 
535
{
 
536
  if ( m_high < m_low )
 
537
    throw IllegalStateException(
 
538
      "Tools::Interval::containsInterval: high boundary is smaller than low boundary."
 
539
    );
 
540
 
 
541
  double low = i.getLowerBound();
 
542
  double high = i.getUpperBound();
 
543
  IntervalType type = i.getIntervalType();
 
544
 
 
545
  if ( m_low < low && m_high > high ) return true;
 
546
  if ( m_low > low || m_high < high ) return false;
 
547
 
 
548
  switch ( m_type )
 
549
  {
 
550
    case IT_CLOSED:
 
551
      break;
 
552
    case IT_OPEN:
 
553
      if (( m_low == low && m_high == high && type != IT_OPEN ) ||
 
554
          ( m_low == low && ( type == IT_CLOSED || type == IT_RIGHTOPEN ) ) ||
 
555
          ( m_high == high && ( type == IT_CLOSED || type == IT_LEFTOPEN ) ) )
 
556
        return false;
 
557
      break;
 
558
    case IT_RIGHTOPEN:
 
559
      if ( m_high == high && ( type == IT_CLOSED || type == IT_LEFTOPEN ) )
 
560
        return false;
 
561
      break;
 
562
    case IT_LEFTOPEN:
 
563
      if ( m_low == low && ( type == IT_CLOSED || type == IT_RIGHTOPEN ) )
 
564
        return false;
 
565
      break;
 
566
  }
 
567
 
 
568
  return true;
 
569
}
 
570
 
 
571
Tools::IntervalType Tools::Interval::getIntervalType() const
 
572
{
 
573
  return m_type;
 
574
}
 
575
 
 
576
 
 
577
void Tools::uncompressRLE(
 
578
  unsigned long blockSize,
 
579
  byte* in, unsigned long lin,
 
580
  byte** out, unsigned long& lout )
 
581
{
 
582
  if ( lin == 0 ) { *out = 0; lout = 0; return; }
 
583
 
 
584
  byte *data = 0, *pdata = 0, *pin;
 
585
  byte* cv = new byte[blockSize];
 
586
  byte* pv = new byte[blockSize];
 
587
  byte rl;
 
588
  unsigned long bufferLength = 2 * lin;
 
589
 
 
590
  pin = in;
 
591
  std::memcpy( cv, pin, blockSize );
 
592
  pv[0] = ~cv[0]; // force next character to be different.
 
593
  assert( pv[0] != cv[0] );
 
594
  data = new byte[bufferLength];
 
595
  pdata = data;
 
596
 
 
597
  while ( pin < in + lin )
 
598
  {
 
599
    std::memcpy( cv, pin, blockSize );
 
600
    pin += blockSize;
 
601
 
 
602
    assert( pin <= in + lin );
 
603
 
 
604
    if (
 
605
      bufferLength - static_cast<unsigned long>( pdata - data ) <=
 
606
      blockSize
 
607
    )
 
608
    {
 
609
      byte* tmp;
 
610
      try
 
611
      {
 
612
        tmp = new byte[2 * bufferLength];
 
613
      }
 
614
      catch ( ... )
 
615
      {
 
616
        delete[] data;
 
617
        delete[] cv;
 
618
        delete[] pv;
 
619
        throw;
 
620
      }
 
621
 
 
622
      std::memcpy( tmp, data, bufferLength );
 
623
      pdata = tmp + ( pdata - data );
 
624
      byte* tmp2 = data;
 
625
      data = tmp;
 
626
      delete[] tmp2;
 
627
      bufferLength *= 2;
 
628
    }
 
629
 
 
630
    std::memcpy( pdata, cv, blockSize );
 
631
    pdata += blockSize;
 
632
 
 
633
    if ( memcmp( cv, pv, blockSize ) == 0 && pin < in + lin )
 
634
    {
 
635
      std::memcpy( &rl, pin, sizeof( byte ) );
 
636
      pin += sizeof( byte );
 
637
      assert( pin <= in + lin );
 
638
      if (
 
639
        bufferLength - static_cast<unsigned long>( pdata - data ) <=
 
640
        rl * blockSize
 
641
      )
 
642
      {
 
643
        unsigned long l = std::max( bufferLength, rl * blockSize );
 
644
 
 
645
        byte* tmp;
 
646
        try
 
647
        {
 
648
          tmp = new byte[2 * l];
 
649
        }
 
650
        catch ( ... )
 
651
        {
 
652
          delete[] data;
 
653
          delete[] cv;
 
654
          delete[] pv;
 
655
          throw;
 
656
        }
 
657
 
 
658
        std::memcpy( tmp, data, bufferLength );
 
659
        pdata = tmp + ( pdata - data );
 
660
        byte* tmp2 = data;
 
661
        data = tmp;
 
662
        delete[] tmp2;
 
663
        bufferLength = 2 * l;
 
664
      }
 
665
 
 
666
      while ( rl > 0 )
 
667
      {
 
668
        std::memcpy( pdata, cv, blockSize );
 
669
        pdata += blockSize;
 
670
        rl--;
 
671
      }
 
672
      std::memcpy( cv, pin, blockSize );
 
673
      pv[0] = ~cv[0];
 
674
      assert( pv[0] != cv[0] );
 
675
    }
 
676
    else std::memcpy( pv, cv, blockSize );
 
677
  }
 
678
 
 
679
  lout = pdata - data;
 
680
 
 
681
  try
 
682
  {
 
683
    *out = new byte[lout];
 
684
  }
 
685
  catch ( ... )
 
686
  {
 
687
    delete[] data;
 
688
    delete[] cv;
 
689
    delete[] pv;
 
690
    throw;
 
691
  }
 
692
 
 
693
  std::memcpy( *out, data, lout );
 
694
  delete[] data;
 
695
  delete[] cv;
 
696
  delete[] pv;
 
697
}
 
698
 
 
699
#if HAVE_GETTIMEOFDAY
 
700
Tools::ResourceUsage::ResourceUsage()
 
701
{
 
702
  reset();
 
703
}
 
704
 
 
705
void Tools::ResourceUsage::start()
 
706
{
 
707
  struct timezone dummy;
 
708
 
 
709
  if ( getrusage( RUSAGE_SELF, &m_tmpRU ) != 0 )
 
710
    throw IllegalStateException(
 
711
      "Tools::ResourceUsage::start: getrusage failed."
 
712
    );
 
713
 
 
714
  if ( gettimeofday( &m_tmpTV, &dummy ) != 0 )
 
715
    throw IllegalStateException(
 
716
      "Tools::ResourceUsage::start: gettimeofday failed."
 
717
    );
 
718
 
 
719
  // maximum resident set size
 
720
  m_peakMemory = std::max( m_peakMemory, m_tmpRU.ru_maxrss );
 
721
 
 
722
  // total memory
 
723
  m_totalMemory = std::max( m_totalMemory, m_tmpRU.ru_ixrss + m_tmpRU.ru_idrss + m_tmpRU.ru_isrss + m_tmpRU.ru_maxrss );
 
724
}
 
725
 
 
726
void Tools::ResourceUsage::stop()
 
727
{
 
728
  struct timezone dummy;
 
729
  struct timeval dif;
 
730
  struct rusage ru;
 
731
  struct timeval tv;
 
732
 
 
733
  if ( getrusage( RUSAGE_SELF, &ru ) != 0 )
 
734
    throw IllegalStateException(
 
735
      "Tools::ResourceUsage::stop: getrusage failed."
 
736
    );
 
737
 
 
738
  if ( gettimeofday( &tv, &dummy ) != 0 )
 
739
    throw IllegalStateException(
 
740
      "Tools::ResourceUsage::stop: gettimeofday failed."
 
741
    );
 
742
 
 
743
  // total_time
 
744
  subtractTimeval( dif, tv, m_tmpTV );
 
745
  addTimeval( m_totalTime, dif );
 
746
 
 
747
  // system_time
 
748
  subtractTimeval( dif, ru.ru_stime, m_tmpRU.ru_stime );
 
749
  addTimeval( m_systemTime, dif );
 
750
 
 
751
  // user_time
 
752
  subtractTimeval( dif, ru.ru_utime, m_tmpRU.ru_utime );
 
753
  addTimeval( m_userTime, dif );
 
754
 
 
755
  // readIO, writeIOs
 
756
  m_readIO += ru.ru_inblock - m_tmpRU.ru_inblock;
 
757
  m_writeIO += ru.ru_oublock - m_tmpRU.ru_oublock;
 
758
 
 
759
  // maximum resident set size
 
760
  m_peakMemory = std::max( m_peakMemory, ru.ru_maxrss );
 
761
 
 
762
  // total memory
 
763
  m_totalMemory = std::max( m_totalMemory, ru.ru_ixrss + ru.ru_idrss + ru.ru_isrss + ru.ru_maxrss );
 
764
 
 
765
  // page faults
 
766
  m_pageFaults += ru.ru_majflt - m_tmpRU.ru_majflt;
 
767
}
 
768
 
 
769
void Tools::ResourceUsage::reset()
 
770
{
 
771
  m_pageFaults = 0;
 
772
  m_readIO = 0;
 
773
  m_writeIO = 0;
 
774
  m_peakMemory = 0;
 
775
  m_totalMemory = 0;
 
776
  m_totalTime.tv_sec = 0;
 
777
  m_totalTime.tv_usec = 0;
 
778
  m_userTime.tv_sec = 0;
 
779
  m_userTime.tv_usec = 0;
 
780
  m_systemTime.tv_sec = 0;
 
781
  m_systemTime.tv_usec = 0;
 
782
}
 
783
 
 
784
double Tools::ResourceUsage::combineTime( const struct timeval& t )
 
785
{
 
786
  return
 
787
    static_cast<double>( t.tv_sec ) +
 
788
    static_cast<double>( t.tv_usec ) / 1000000.0;
 
789
}
 
790
 
 
791
void Tools::ResourceUsage::addTimeval( struct timeval& result, const struct timeval& a )
 
792
{
 
793
  result.tv_sec += a.tv_sec;
 
794
  result.tv_usec += a.tv_usec;
 
795
 
 
796
  if ( result.tv_usec > 1000000 )
 
797
  {
 
798
    long div = result.tv_usec / 1000000;
 
799
    result.tv_sec += div;
 
800
    result.tv_usec -= div * 1000000;
 
801
  }
 
802
}
 
803
 
 
804
void Tools::ResourceUsage::subtractTimeval( struct timeval& result, const struct timeval& a, const struct timeval& b )
 
805
{
 
806
  result.tv_sec = a.tv_sec - b.tv_sec;
 
807
  result.tv_usec = a.tv_usec - b.tv_usec;
 
808
 
 
809
  if ( result.tv_usec < 0 )
 
810
  {
 
811
    result.tv_sec -= 1;
 
812
    result.tv_usec += 1000000;
 
813
  }
 
814
}
 
815
 
 
816
double Tools::ResourceUsage::getTotalTime()
 
817
{
 
818
  return combineTime( m_totalTime );
 
819
}
 
820
 
 
821
double Tools::ResourceUsage::getUserTime()
 
822
{
 
823
  return combineTime( m_userTime );
 
824
}
 
825
 
 
826
double Tools::ResourceUsage::getSystemTime()
 
827
{
 
828
  return combineTime( m_systemTime );
 
829
}
 
830
 
 
831
long Tools::ResourceUsage::getPageFaults()
 
832
{
 
833
  return m_pageFaults;
 
834
}
 
835
 
 
836
long Tools::ResourceUsage::getReadIO()
 
837
{
 
838
  return m_readIO;
 
839
}
 
840
 
 
841
long Tools::ResourceUsage::getWriteIO()
 
842
{
 
843
  return m_writeIO;
 
844
}
 
845
 
 
846
long Tools::ResourceUsage::getPeakResidentMemoryUsage()
 
847
{
 
848
  return m_peakMemory;
 
849
}
 
850
 
 
851
long Tools::ResourceUsage::getTotalMemoryUsage()
 
852
{
 
853
  return m_totalMemory;
 
854
}
 
855
#endif
 
856
 
 
857
#if BUILD_CPU_I686
 
858
Tools::CycleCounter::CycleCounter() : m_totalCycles( 0 ), m_bRunning( false )
 
859
{
 
860
}
 
861
 
 
862
double Tools::CycleCounter::getCPUMHz()
 
863
{
 
864
  unsigned long long v1 = rdtsc();
 
865
  sleep( 10 );
 
866
  unsigned long long v2 = rdtsc();
 
867
  return (( v2 - v1 ) / 1e7 );
 
868
}
 
869
 
 
870
double Tools::CycleCounter::getCyclesPerSecond()
 
871
{
 
872
  unsigned long long v1 = rdtsc();
 
873
  sleep( 10 );
 
874
  unsigned long long v2 = rdtsc();
 
875
  return (( v2 - v1 ) / 10 );
 
876
}
 
877
 
 
878
inline unsigned long long Tools::CycleCounter::rdtsc()
 
879
{
 
880
  unsigned long long ret;
 
881
__asm__ __volatile__( "rdtsc": "=A"( ret ): );
 
882
  return ret;
 
883
}
 
884
 
 
885
void Tools::CycleCounter::start()
 
886
{
 
887
  if ( ! m_bRunning )
 
888
  {
 
889
    m_tmpCycles = rdtsc();
 
890
    m_bRunning = true;
 
891
  }
 
892
}
 
893
 
 
894
void Tools::CycleCounter::stop()
 
895
{
 
896
  if ( m_bRunning )
 
897
  {
 
898
    unsigned long long t = rdtsc();
 
899
    m_totalCycles += t - m_tmpCycles;
 
900
    m_bRunning = false;
 
901
  }
 
902
}
 
903
 
 
904
void Tools::CycleCounter::reset()
 
905
{
 
906
  m_totalCycles = 0;
 
907
  m_bRunning = false;
 
908
}
 
909
 
 
910
double Tools::CycleCounter::getTotalCycles()
 
911
{
 
912
  return m_totalCycles;
 
913
}
 
914
#endif
 
915
 
 
916
#if HAVE_PTHREAD_H
 
917
Tools::SharedLock::SharedLock( pthread_rwlock_t* pLock )
 
918
    : m_pLock( pLock )
 
919
{
 
920
  pthread_rwlock_rdlock( m_pLock );
 
921
}
 
922
 
 
923
Tools::SharedLock::~SharedLock()
 
924
{
 
925
  pthread_rwlock_unlock( m_pLock );
 
926
}
 
927
 
 
928
Tools::ExclusiveLock::ExclusiveLock( pthread_rwlock_t* pLock )
 
929
    : m_pLock( pLock )
 
930
{
 
931
  pthread_rwlock_wrlock( m_pLock );
 
932
}
 
933
 
 
934
Tools::ExclusiveLock::~ExclusiveLock()
 
935
{
 
936
  pthread_rwlock_unlock( m_pLock );
 
937
}
 
938
#endif
 
939
 
 
940
Tools::StringTokenizer::StringTokenizer( const std::string& str, const std::string& delimiters )
 
941
    : m_index( 0 )
 
942
{
 
943
  // Skip delimiters at beginning.
 
944
  std::string::size_type lastPos = str.find_first_not_of( delimiters, 0 );
 
945
  // Find first "non-delimiter".
 
946
  std::string::size_type pos = str.find_first_of( delimiters, lastPos );
 
947
 
 
948
  while ( std::string::npos != pos || std::string::npos != lastPos )
 
949
  {
 
950
    // Found a token, add it to the vector.
 
951
    m_token.push_back( str.substr( lastPos, pos - lastPos ) );
 
952
    // Skip delimiters.  Note the "not_of"
 
953
    lastPos = str.find_first_not_of( delimiters, pos );
 
954
    // Find next "non-delimiter"
 
955
    pos = str.find_first_of( delimiters, lastPos );
 
956
  }
 
957
}
 
958
 
 
959
std::string Tools::StringTokenizer::getNextToken()
 
960
{
 
961
  return m_token.at( m_index++ );
 
962
}
 
963
 
 
964
bool Tools::StringTokenizer::hasMoreTokens()
 
965
{
 
966
  return ( m_index < m_token.size() );
 
967
}
 
968
 
 
969
void Tools::StringTokenizer::reset()
 
970
{
 
971
  m_index = 0;
 
972
}
 
973
 
 
974
std::string Tools::trimLeft( const std::string& source, const std::string& t )
 
975
{
 
976
  std::string str = source;
 
977
  return str.erase( 0, source.find_first_not_of( t ) );
 
978
}
 
979
 
 
980
std::string Tools::trimRight( const std::string& source, const std::string& t )
 
981
{
 
982
  std::string str = source;
 
983
  return str.erase( str.find_last_not_of( t ) + 1 );
 
984
}
 
985
 
 
986
std::string Tools::trim( const std::string& source, const std::string& t )
 
987
{
 
988
  std::string str = source;
 
989
  return trimLeft( trimRight( str, t ), t );
 
990
}
 
991
 
 
992
char Tools::toLower( char c )
 
993
{
 
994
#ifdef _MSC_VER
 
995
  // MSVC doesn't seem to have std::tolower(char)
 
996
  std::locale loc;
 
997
  return std::tolower( c, loc );
 
998
#else
 
999
  return std::tolower( c );
 
1000
#endif//_MSC_VER
 
1001
}
 
1002
 
 
1003
char Tools::toUpper( char c )
 
1004
{
 
1005
#ifdef _MSC_VER
 
1006
  // MSVC doesn't seem to have std::toupper(char)
 
1007
  std::locale loc;
 
1008
  return std::toupper( c, loc );
 
1009
#else
 
1010
  return std::toupper( c );
 
1011
#endif//_MSC_VER
 
1012
}
 
1013
 
 
1014
std::string Tools::toUpperCase( const std::string& s )
 
1015
{
 
1016
  std::string t = s;
 
1017
  transform( t.begin(), t.end(), t.begin(), Tools::toUpper );
 
1018
  return t;
 
1019
}
 
1020
 
 
1021
std::string Tools::toLowerCase( const std::string& s )
 
1022
{
 
1023
  std::string t = s;
 
1024
  transform( t.begin(), t.end(), t.begin(), Tools::toLower );
 
1025
  return t;
 
1026
}
 
1027
 
 
1028
unsigned long long choose( unsigned long a, unsigned long k )
 
1029
{
 
1030
  unsigned long long cnm = 1, n = a, m = k;
 
1031
  unsigned long long i, f;
 
1032
 
 
1033
  if ( m * 2 > n ) m = n - m;
 
1034
  for ( i = 1 ; i <= m; n--, i++ )
 
1035
  {
 
1036
    if (( f = n ) % i == 0 ) f /= i;
 
1037
    else cnm /= i;
 
1038
    cnm *= f;
 
1039
  }
 
1040
  return cnm;
 
1041
}
 
1042
 
 
1043
Tools::Architecture Tools::System::getArchitecture()
 
1044
{
 
1045
  union {double f; unsigned long i[2];} convert;
 
1046
  convert.f = 1.0;
 
1047
 
 
1048
  // Note: Old versions of the Gnu g++ compiler may make an error here,
 
1049
  // compile with the option  -fenum-int-equiv  to fix the problem
 
1050
  if ( convert.i[1] == 0x3FF00000 ) return ARCH_LITTLEENDIAN;
 
1051
  else if ( convert.i[0] == 0x3FF00000 ) return ARCH_BIGENDIAN;
 
1052
  else return ARCH_NONIEEE;
 
1053
}
 
1054
 
 
1055
std::ostream& Tools::operator<<( std::ostream& os, const Tools::PropertySet& p )
 
1056
{
 
1057
  std::map<std::string, Variant>::const_iterator it;
 
1058
 
 
1059
  for ( it = p.m_propertySet.begin(); it != p.m_propertySet.end(); it++ )
 
1060
  {
 
1061
    if ( it != p.m_propertySet.begin() ) os << ", ";
 
1062
 
 
1063
    switch (( *it ).second.m_varType )
 
1064
    {
 
1065
      case VT_LONG:
 
1066
        os << ( *it ).first << ": " << ( *it ).second.m_val.lVal;
 
1067
        break;
 
1068
      case VT_LONGLONG:
 
1069
        os << ( *it ).first << ": " << ( *it ).second.m_val.llVal;
 
1070
        break;
 
1071
      case VT_BYTE:
 
1072
        os << ( *it ).first << ": " << ( *it ).second.m_val.bVal;
 
1073
        break;
 
1074
      case VT_SHORT:
 
1075
        os << ( *it ).first << ": " << ( *it ).second.m_val.iVal;
 
1076
        break;
 
1077
      case VT_FLOAT:
 
1078
        os << ( *it ).first << ": " << ( *it ).second.m_val.fltVal;
 
1079
        break;
 
1080
      case VT_DOUBLE:
 
1081
        os << ( *it ).first << ": " << ( *it ).second.m_val.dblVal;
 
1082
        break;
 
1083
      case VT_CHAR:
 
1084
        os << ( *it ).first << ": " << ( *it ).second.m_val.cVal;
 
1085
        break;
 
1086
      case VT_USHORT:
 
1087
        os << ( *it ).first << ": " << ( *it ).second.m_val.uiVal;
 
1088
        break;
 
1089
      case VT_ULONG:
 
1090
        os << ( *it ).first << ": " << ( *it ).second.m_val.ulVal;
 
1091
        break;
 
1092
      case VT_ULONGLONG:
 
1093
        os << ( *it ).first << ": " << ( *it ).second.m_val.ullVal;
 
1094
        break;
 
1095
      case VT_INT:
 
1096
        os << ( *it ).first << ": " << ( *it ).second.m_val.intVal;
 
1097
        break;
 
1098
      case VT_UINT:
 
1099
        os << ( *it ).first << ": " << ( *it ).second.m_val.uintVal;
 
1100
        break;
 
1101
      case VT_BOOL:
 
1102
        os << ( *it ).first << ": " << ( *it ).second.m_val.blVal;
 
1103
        break;
 
1104
      case VT_PCHAR:
 
1105
        os << ( *it ).first << ": " << ( *it ).second.m_val.pcVal;
 
1106
        break;
 
1107
      case VT_PVOID:
 
1108
        os << ( *it ).first << ": ?";
 
1109
        break;
 
1110
      case VT_EMPTY:
 
1111
        os << ( *it ).first << ": empty";
 
1112
        break;
 
1113
      default:
 
1114
        os << ( *it ).first << ": unknown";
 
1115
    }
 
1116
  }
 
1117
 
 
1118
  return os;
 
1119
}
 
1120
 
 
1121
std::ostream& Tools::operator<<( std::ostream& os, const Tools::Interval& iv )
 
1122
{
 
1123
  os << iv.m_type << " " << iv.m_low << " " << iv.m_high;
 
1124
  return os;
 
1125
}
 
1126
 
 
1127
std::ostream& Tools::operator<<( std::ostream& os, const Tools::UniversalHash& h )
 
1128
{
 
1129
  os << h.m_k;
 
1130
 
 
1131
  for ( unsigned long i = 0; i < h.m_k; i++ )
 
1132
    os << " " << h.m_a[i];
 
1133
 
 
1134
  return os;
 
1135
}
 
1136