Coverage Report

Created: 2025-06-13 06:12

/src/resiprocate/rutil/Data.cxx
Line
Count
Source (jump to first uncovered line)
1
#include <algorithm>
2
#include "rutil/ResipAssert.h"
3
#include <ctype.h>
4
#include <fstream>
5
#include <math.h>
6
#include <limits>
7
#include <limits.h>
8
#include <stdexcept>
9
10
#if defined(HAVE_CONFIG_H)
11
#include "config.h"
12
#endif
13
14
#include "rutil/Data.hxx"
15
#include "rutil/DataException.hxx"
16
#include "rutil/ParseBuffer.hxx"
17
#include "rutil/vmd5.hxx"
18
#include "rutil/Coders.hxx"
19
#include "rutil/WinLeakCheck.hxx"
20
21
#ifdef WIN32
22
#include "Winsock2.h"
23
#endif
24
25
using namespace resip;
26
using namespace std;
27
28
const Data Data::Empty("", 0);
29
const Data::size_type Data::npos = UINT_MAX;
30
31
Data::PreallocateType::PreallocateType(int)
32
4
{}
33
34
const Data::PreallocateType Data::Preallocate(0);
35
36
const bool DataHelper::isCharHex[256] =
37
{
38
// 0       1       2       3       4       5       6       7       8       9       a   b   c   d   e   f
39
   false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  //0
40
   false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  //1
41
   false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  //2
42
   true,   true,   true,   true,   true,   true,   true,   true,   true,   true,  false,  false,  false,  false,  false,  false,  //3
43
   false,   true,   true,   true,   true,   true,   true,  false,  false,  false,  false,  false,  false,  false,  false,  false,  //4
44
   false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  //5
45
   false,   true,   true,   true,   true,   true,   true,  false,  false,  false,  false,  false,  false,  false,  false,  false,  //6
46
   false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  //8
47
   false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  //9
48
   false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  //a
49
   false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  //b
50
   false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  //c
51
   false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  //d
52
   false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  //e
53
   false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false,  false   //f
54
};
55
56
//must be lowercase for MD5
57
static const char hexmap[] = "0123456789abcdef";
58
59
static const signed char inversehexmap[] = {
60
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,     // 0 - 
61
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
62
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
63
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
64
    -1, -1, -1, -1, -1, -1, -1, -1,             //   - 47
65
66
          0, 1, 2, 3, 4, 5, 6, 7, 8, 9,         // 48 ...
67
68
                                     -1, -1,    // 58 -
69
    -1, -1, -1, -1, -1,                         //  -64
70
71
          10, 11, 12, 13, 14, 15,               // 65 ...
72
73
        -1, -1, -1, -1, -1, -1, -1, -1, -1,     // 71 ...
74
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
75
    -1, -1, -1, -1, -1, -1, -1,                 //   - 96
76
77
          10, 11, 12, 13, 14, 15                // 97 ...
78
};
79
80
int 
81
hexpair2int(char high, char low)
82
0
{
83
0
   int val;
84
    
85
0
   switch(high)
86
0
   {
87
0
      case '0':
88
0
         val = 0x00;
89
0
         break;
90
0
      case '1':
91
0
         val = 0x10;
92
0
         break;
93
0
      case '2':
94
0
         val = 0x20;
95
0
         break;
96
0
      case '3':
97
0
         val =  0x30;
98
0
         break;
99
0
      case '4':
100
0
         val =  0x40;
101
0
         break;
102
0
      case '5':
103
0
         val =  0x50;
104
0
         break;
105
0
      case '6':
106
0
         val =  0x60;
107
0
         break;
108
0
      case '7':
109
0
         val =  0x70;
110
0
         break;
111
0
      case '8':
112
0
         val =  0x80;
113
0
         break;
114
0
      case '9':
115
0
         val =  0x90;
116
0
         break;
117
0
      case 'A':
118
0
      case 'a':
119
0
         val =  0xA0;
120
0
         break;
121
0
      case 'B':
122
0
      case 'b':
123
0
         val =  0xB0;
124
0
         break;
125
0
      case 'C':
126
0
      case 'c':
127
0
         val =  0xC0;
128
0
         break;
129
0
      case 'D':
130
0
      case 'd':
131
0
         val =  0xD0;
132
0
         break;
133
0
      case 'E':
134
0
      case 'e':
135
0
         val =  0xE0;
136
0
         break;
137
0
      case 'F':
138
0
      case 'f':
139
0
         val =  0xF0;
140
0
         break;
141
0
      default:
142
0
         return '?';
143
0
         break;
144
0
   }
145
146
0
   switch(low)
147
0
   {
148
0
      case '0':
149
0
         if (!val)
150
0
         {
151
0
            return '?';
152
0
         }
153
0
         break;
154
0
      case '1':
155
0
         val += 0x01;
156
0
         break;
157
0
      case '2':
158
0
         val += 0x02;
159
0
         break;
160
0
      case '3':
161
0
         val +=  0x03;
162
0
         break;
163
0
      case '4':
164
0
         val +=  0x04;
165
0
         break;
166
0
      case '5':
167
0
         val +=  0x05;
168
0
         break;
169
0
      case '6':
170
0
         val +=  0x06;
171
0
         break;
172
0
      case '7':
173
0
         val +=  0x07;
174
0
         break;
175
0
      case '8':
176
0
         val +=  0x08;
177
0
         break;
178
0
      case '9':
179
0
         val +=  0x09;
180
0
         break;
181
0
      case 'A':
182
0
      case 'a':
183
0
         val +=  0x0A;
184
0
         break;
185
0
      case 'B':
186
0
      case 'b':
187
0
         val +=  0x0B;
188
0
         break;
189
0
      case 'C':
190
0
      case 'c':
191
0
         val +=  0x0C;
192
0
         break;
193
0
      case 'D':
194
0
      case 'd':
195
0
         val +=  0x0D;
196
0
         break;
197
0
      case 'E':
198
0
      case 'e':
199
0
         val +=  0x0E;
200
0
         break;
201
0
      case 'F':
202
0
      case 'f':
203
0
         val +=  0x0F;
204
0
         break;
205
0
      default:
206
0
         return '?';
207
0
         break;
208
0
   }
209
0
   return val;
210
0
}
211
212
bool
213
Data::init(DataLocalSize<RESIP_DATA_LOCAL_SIZE> arg)
214
226
{
215
226
   return true;
216
226
}
217
218
Data::Data(size_type capacity,
219
           const Data::PreallocateType&) 
220
213k
   : mBuf(capacity > LocalAlloc 
221
213k
          ? new char[capacity + 1]
222
213k
          : mPreBuffer),
223
213k
     mSize(0),
224
213k
     mCapacity(capacity > LocalAlloc
225
213k
               ? capacity
226
213k
               : LocalAlloc),
227
213k
     mShareEnum(capacity > LocalAlloc ? Take : Borrow)
228
213k
{
229
213k
   resip_assert( capacity >= 0 );
230
213k
   mBuf[mSize] = 0;
231
213k
}
232
233
#ifdef DEPRECATED_PREALLOC
234
// pre-allocate capacity
235
Data::Data(size_type capacity, bool) 
236
   : mBuf(capacity > LocalAlloc 
237
          ? new char[capacity + 1]
238
          : mPreBuffer),
239
     mSize(0),
240
     mCapacity(capacity > LocalAlloc
241
               ? capacity
242
               : LocalAlloc),
243
     mShareEnum(capacity > LocalAlloc ? Take : Borrow)
244
{
245
   resip_assert( capacity >= 0 );
246
   mBuf[mSize] = 0;
247
}
248
#endif
249
250
Data::Data(const char* str, size_type length) 
251
4.48M
{
252
4.48M
   initFromString(str, length);
253
4.48M
}
254
255
Data::Data(const unsigned char* str, size_type length) 
256
0
{
257
0
   initFromString((const char*)str, length);
258
0
}
259
260
// share memory KNOWN to be in a surrounding scope
261
// wears off on, c_str, operator=, operator+=, non-const
262
// operator[], append, reserve
263
Data::Data(const char* str, size_type length, bool) 
264
0
   : mBuf(const_cast<char*>(str)),
265
0
     mSize(length),
266
0
     mCapacity(mSize),
267
0
     mShareEnum(Share)
268
0
{
269
0
   resip_assert(str);
270
0
}
271
272
void
273
Data::initFromString(const char* str, size_type len)
274
7.67M
{
275
7.67M
   mSize = len;
276
7.67M
   if(len > 0)
277
7.40M
   {
278
7.40M
      resip_assert(str);
279
7.40M
   }
280
7.67M
   size_t bytes = len + 1;
281
7.67M
   if(bytes <= len)
282
0
   {
283
      // integer overflow
284
0
      throw std::bad_alloc();
285
0
   }
286
7.67M
   if(bytes > LocalAlloc)
287
377k
   {
288
377k
      mBuf = new char[bytes];
289
377k
      mCapacity = mSize;
290
377k
      mShareEnum = Take;
291
377k
   }
292
7.29M
   else
293
7.29M
   {
294
7.29M
      mBuf = mPreBuffer;
295
7.29M
      mCapacity = LocalAlloc;
296
7.29M
      mShareEnum = Borrow;
297
7.29M
   }
298
7.67M
   if(str)
299
7.67M
   {
300
7.67M
      memcpy(mBuf, str, len);
301
7.67M
   }
302
7.67M
   mBuf[mSize] = 0;
303
7.67M
}
304
305
Data::Data(ShareEnum se, const char* buffer, size_type length)
306
6.46k
   : mBuf(const_cast<char*>(buffer)),
307
6.46k
     mSize(length),
308
6.46k
     mCapacity(mSize),
309
6.46k
     mShareEnum(se)
310
6.46k
{
311
6.46k
   resip_assert(buffer);
312
6.46k
}
313
314
Data::Data(ShareEnum se, const char* buffer, size_type length, size_type capacity)
315
0
   : mBuf(const_cast<char*>(buffer)),
316
0
     mSize(length),
317
0
     mCapacity(capacity),
318
0
     mShareEnum(se)
319
0
{
320
0
   resip_assert(buffer);
321
0
}
322
323
Data::Data(ShareEnum se, const char* buffer)
324
32.5k
   : mBuf(const_cast<char*>(buffer)),
325
32.5k
     mSize((Data::size_type)strlen(buffer)),
326
32.5k
     mCapacity(mSize),
327
32.5k
     mShareEnum(se)
328
32.5k
{
329
32.5k
   resip_assert(buffer);
330
32.5k
}
331
332
Data::Data(ShareEnum se, const Data& staticData)
333
6.84k
   : mBuf(staticData.mBuf),
334
6.84k
     mSize(staticData.mSize),
335
6.84k
     mCapacity(mSize),
336
6.84k
     mShareEnum(Share)
337
6.84k
{
338
   // !dlb! maybe:
339
   // if you are trying to use Take, but make sure that you unset the mShareEnum on
340
   // the staticData
341
6.84k
   resip_assert(se == Share); // makes no sense to call this with 'Take'.
342
6.84k
}
343
//=============================================================================
344
345
Data::Data(const char* str)
346
215k
{
347
215k
   initFromString(str, str ? (Data::size_type)strlen(str) : 0);
348
215k
}
349
350
Data::Data(const string& str)
351
0
{
352
0
   initFromString(str.c_str(), (Data::size_type)str.size());
353
0
}
354
355
#if RESIP_HAVE_STRING_VIEW
356
/**
357
  Creates a data with the contents of the string_view.
358
*/
359
 Data::Data(const std::string_view sv)
360
0
{
361
0
   initFromString(sv.data(), (Data::size_type)sv.size());
362
0
}
363
#endif
364
365
Data::Data(const Data& data) 
366
2.97M
{
367
2.97M
   initFromString(data.mBuf, data.mSize);
368
2.97M
}
369
370
#ifdef RESIP_HAS_RVALUE_REFS
371
Data::Data(Data &&data)
372
   : mBuf(mPreBuffer),mSize(0),mCapacity(LocalAlloc),mShareEnum(Borrow)
373
{
374
   *this = std::move(data);
375
}
376
#endif
377
378
// -2147483646
379
static const int Int32MaxSize = 11;
380
381
// 18446744073709551615
382
static const int UInt64MaxSize = 20;
383
384
Data::Data(int32_t val)
385
7.33k
   : mBuf(Int32MaxSize > LocalAlloc 
386
7.33k
          ? new char[Int32MaxSize + 1]
387
7.33k
          : mPreBuffer),
388
7.33k
     mSize(0),
389
7.33k
     mCapacity(Int32MaxSize > LocalAlloc
390
7.33k
               ? Int32MaxSize
391
7.33k
               : LocalAlloc),
392
7.33k
     mShareEnum(Int32MaxSize > LocalAlloc ? Take : Borrow)
393
7.33k
{
394
7.33k
   if (val == 0)
395
214
   {
396
214
      mBuf[0] = '0';
397
214
      mBuf[1] = 0;
398
214
      mSize = 1;
399
214
      return;
400
214
   }
401
402
7.12k
   bool neg = false;
403
   
404
7.12k
   int32_t value = val;
405
7.12k
   if (value < 0)
406
870
   {
407
870
      value = -value;
408
870
      neg = true;
409
870
   }
410
411
7.12k
   int c = 0;
412
7.12k
   int32_t v = value;
413
12.7k
   while (v /= 10)
414
5.66k
   {
415
5.66k
      ++c;
416
5.66k
   }
417
418
7.12k
   if (neg)
419
870
   {
420
870
      ++c;
421
870
   }
422
423
7.12k
   mSize = c+1;
424
7.12k
   mBuf[c+1] = 0;
425
   
426
7.12k
   v = value;
427
19.9k
   while (v)
428
12.7k
   {
429
12.7k
      mBuf[c--] = '0' + v%10;
430
12.7k
      v /= 10;
431
12.7k
   }
432
433
7.12k
   if (neg)
434
870
   {
435
870
      mBuf[0] = '-';
436
870
   }
437
7.12k
}
438
439
#ifndef RESIP_FIXED_POINT
440
static const int DoubleMaxSize = UInt64MaxSize + Data::MaxDigitPrecision;
441
Data::Data(double value, 
442
           Data::DoubleDigitPrecision precision)
443
0
   : mBuf(DoubleMaxSize + precision > LocalAlloc 
444
0
          ? new char[DoubleMaxSize + precision + 1]
445
0
          : mPreBuffer),
446
0
     mSize(0),
447
0
     mCapacity(DoubleMaxSize + precision > LocalAlloc
448
0
               ? DoubleMaxSize + precision
449
0
               : LocalAlloc),
450
0
     mShareEnum(DoubleMaxSize + precision > LocalAlloc ? Take : Borrow)
451
0
{
452
0
   resip_assert(precision >= 0);
453
0
   resip_assert(precision < MaxDigitPrecision);
454
455
0
   double v = value;
456
0
   bool neg = (value < 0.0);
457
   
458
0
   if (neg)
459
0
   {
460
0
      v = -v;
461
0
   }
462
463
0
   Data m((uint64_t)v);
464
465
   // remainder
466
0
   v = v - floor(v);
467
468
0
   int p = precision;
469
0
   while (p--)
470
0
   {
471
0
      v *= 10;
472
0
   }
473
474
0
   int dec = (int)floor(v+0.5);
475
0
   Data d(precision, Data::Preallocate);
476
477
0
   if (dec == 0)
478
0
   {
479
0
      d = "0";
480
0
   }
481
0
   else
482
0
   {
483
0
      d.mBuf[precision] = 0;
484
0
      p = precision;
485
      // neglect trailing zeros
486
0
      bool significant = false;
487
0
      while (p--)
488
0
      {
489
0
         if (dec % 10 || significant)
490
0
         {
491
0
            significant = true;
492
0
            ++d.mSize;
493
0
            d.mBuf[p] = '0' + (dec % 10);
494
0
         }
495
0
         else
496
0
         {
497
0
            d.mBuf[p] = 0;
498
0
         }
499
         
500
0
         dec /= 10;
501
0
      }
502
0
   }
503
504
0
   if (neg)
505
0
   {
506
0
      mBuf[0] = '-';
507
0
      memcpy(mBuf+1, m.mBuf, m.size());
508
0
      mBuf[1+m.size()] = '.';
509
0
      memcpy(mBuf+1+m.size()+1, d.mBuf, d.size()+1);
510
0
      mSize = m.size() + d.size() + 2;
511
0
   }
512
0
   else
513
0
   {
514
0
      if (mCapacity < m.size() + d.size() + 1)
515
0
      {
516
0
         resize(m.size() + d.size() + 1, false);
517
0
      }
518
0
      memcpy(mBuf, m.mBuf, m.size());
519
0
      mBuf[m.size()] = '.';
520
0
      memcpy(mBuf+m.size()+1, d.mBuf, d.size()+1);
521
0
      mSize = m.size() + d.size() + 1;
522
0
   }
523
524
0
   resip_assert(mBuf[mSize] == 0);
525
0
}
526
#endif
527
528
Data::Data(uint32_t value)
529
0
   : mBuf(Int32MaxSize > LocalAlloc 
530
0
          ? new char[Int32MaxSize + 1]
531
0
          : mPreBuffer),
532
0
     mSize(0),
533
0
     mCapacity(Int32MaxSize > LocalAlloc
534
0
               ? Int32MaxSize
535
0
               : LocalAlloc),
536
0
     mShareEnum(Int32MaxSize > LocalAlloc ? Take : Borrow)
537
0
{
538
0
   if (value == 0)
539
0
   {
540
0
      mBuf[0] = '0';
541
0
      mBuf[1] = 0;
542
0
      mSize = 1;
543
0
      return;
544
0
   }
545
546
0
   int c = 0;
547
0
   uint32_t v = value;
548
0
   while (v /= 10)
549
0
   {
550
0
      ++c;
551
0
   }
552
553
0
   mSize = c+1;
554
0
   mBuf[c+1] = 0;
555
   
556
0
   v = value;
557
0
   while (v)
558
0
   {
559
0
      unsigned int digit = v%10;
560
0
      unsigned char d = (char)digit;
561
0
      mBuf[c--] = '0' + d;
562
0
      v /= 10;
563
0
   }
564
0
}
565
566
Data::Data(uint64_t value)
567
0
   : mBuf(UInt64MaxSize > LocalAlloc 
568
0
          ? new char[UInt64MaxSize + 1]
569
0
          : mPreBuffer),
570
0
     mSize(0),
571
0
     mCapacity(UInt64MaxSize > LocalAlloc
572
0
               ? UInt64MaxSize
573
0
               : LocalAlloc),
574
0
     mShareEnum(UInt64MaxSize > LocalAlloc ? Take : Borrow)
575
0
{
576
0
   if (value == 0)
577
0
   {
578
0
      mBuf[0] = '0';
579
0
      mBuf[1] = 0;
580
0
      mSize = 1;
581
0
      return;
582
0
   }
583
584
0
   int c = 0;
585
0
   uint64_t v = value;
586
0
   while (v /= 10)
587
0
   {
588
0
      ++c;
589
0
   }
590
591
0
   mSize = c+1;
592
0
   mBuf[c+1] = 0;
593
   
594
0
   v = value;
595
0
   while (v)
596
0
   {
597
0
      uint64_t digit = v%10;
598
0
      unsigned char d = (char)digit;
599
0
      mBuf[c--] = '0' + d;
600
0
      v /= 10;
601
0
   }
602
0
}
603
604
static const int CharMaxSize = 1;
605
Data::Data(char c)
606
0
   : mBuf(CharMaxSize > LocalAlloc 
607
0
          ? new char[CharMaxSize + 1]
608
0
          : mPreBuffer),
609
0
     mSize(1),
610
0
     mCapacity(CharMaxSize > LocalAlloc
611
0
               ? CharMaxSize
612
0
               : LocalAlloc),
613
0
     mShareEnum(CharMaxSize > LocalAlloc ? Take : Borrow)
614
0
{
615
0
   mBuf[0] = c;
616
0
   mBuf[1] = 0;
617
0
}
618
619
Data::Data(bool value)
620
0
   : mBuf(value ? const_cast<char*>("true") : const_cast<char*>("false")),
621
0
     mSize(value ? 4 : 5), 
622
0
     mCapacity(value ? 4 : 5),
623
0
     mShareEnum(Borrow)
624
0
{}
625
626
Data&
627
Data::setBuf(ShareEnum se, const char* buffer, size_type length)
628
0
{
629
0
   resip_assert(buffer);
630
0
   if (mShareEnum == Take)
631
0
   {
632
0
      delete[] mBuf;
633
0
   }
634
0
   mBuf = const_cast<char*>(buffer);
635
0
   mCapacity = mSize = length;
636
0
   mShareEnum = se;
637
0
   return *this;
638
0
}
639
640
Data&
641
Data::takeBuf(Data& other)
642
0
{
643
0
   if ( &other == this )
644
0
      return *this;
645
646
0
   if (mShareEnum == Data::Take)
647
0
      delete[] mBuf;
648
649
0
   if ( other.mBuf == other.mPreBuffer )
650
0
   {
651
      // plus one picks up the terminating safety NULL
652
0
      memcpy( mPreBuffer, other.mPreBuffer, other.mSize+1);
653
0
      mBuf = mPreBuffer;
654
0
   }
655
0
   else
656
0
   {
657
0
      mBuf = other.mBuf;
658
0
      other.mBuf = other.mPreBuffer;
659
0
   }
660
0
   mSize = other.mSize;
661
0
   mCapacity = other.mCapacity;
662
0
   mShareEnum = other.mShareEnum;
663
664
   // reset {other} to same state as the default Data() constructor
665
   // note that other.mBuf is set above
666
0
   other.mSize = 0;
667
0
   other.mCapacity = LocalAlloc;
668
0
   other.mShareEnum = Data::Borrow;
669
0
   other.mPreBuffer[0] = 0;
670
671
0
   return *this;
672
0
}
673
674
Data& 
675
Data::duplicate(const Data& other)
676
0
{
677
0
   if (&other == this)
678
0
      return *this;
679
680
0
   if (mShareEnum == Data::Take)
681
0
      delete[] mBuf;
682
683
0
   if (other.mBuf == other.mPreBuffer)
684
0
   {
685
      // plus one picks up the terminating safety NULL
686
0
      memcpy(mPreBuffer, other.mPreBuffer, other.mSize + 1);
687
0
      mBuf = mPreBuffer;
688
0
   }
689
0
   else
690
0
   {
691
0
      mBuf = other.mBuf;
692
0
   }
693
0
   mSize = other.mSize;
694
0
   mCapacity = other.mCapacity;
695
0
   mShareEnum = other.mShareEnum;
696
697
0
   return *this;
698
0
}
699
700
Data&
701
Data::copy(const char *buf, size_type length)
702
69.9k
{
703
69.9k
   if (mShareEnum == Data::Share || mCapacity < length+1)
704
15.3k
   {
705
      // will alloc length+1, so the term NULL below is safe
706
15.3k
      resize(length, false);
707
15.3k
   }
708
   // {buf} might be part of ourselves already, in which case {length}
709
   // is smaller than our capacity, so resize above won't happen, so
710
   // just memmove (not memcpy) and everything good
711
69.9k
   mSize = length;
712
69.9k
   if (mSize>0)
713
46.0k
   {
714
46.0k
      memmove(mBuf, buf, mSize);
715
46.0k
   }
716
   // DONT do term NULL until after copy, because may be shifting contents
717
   // down and don't want to put NULL in middle of it
718
69.9k
   mBuf[mSize] = 0;
719
69.9k
   return *this;
720
69.9k
}
721
722
char*
723
Data::getBuf(size_type length)
724
0
{
725
0
   if (mShareEnum == Data::Share || mCapacity < length)
726
0
   {
727
      // will alloc length+1, so the term NULL below is safe
728
0
      resize(length, false);
729
0
      mBuf[length] = 0;
730
0
   }
731
0
   else if ( mCapacity != length )
732
0
   {
733
0
      mBuf[length] = 0;
734
0
   }
735
   // even if we don't NULL-term it, it may have NULL term from before.
736
   // But if external buffer (taken or borrow'd) then don't know if it
737
   // has a NULL or not.
738
0
   mSize = length;
739
0
   return mBuf;
740
0
}
741
742
bool 
743
resip::operator==(const Data& lhs, const Data& rhs)
744
109k
{
745
109k
   if (lhs.mSize != rhs.mSize)
746
83.7k
   {
747
83.7k
      return false;
748
83.7k
   }
749
25.9k
   return memcmp(lhs.mBuf, rhs.mBuf, lhs.mSize) == 0;
750
109k
}
751
752
bool 
753
resip::operator==(const Data& lhs, const char* rhs)
754
26.9k
{
755
26.9k
   resip_assert(rhs); // .dlb. not consistent with constructor
756
26.9k
   if (strncmp(lhs.mBuf, rhs, lhs.mSize) != 0)
757
5.72k
   {
758
5.72k
      return false;
759
5.72k
   }
760
21.2k
   return strlen(rhs) == lhs.mSize;
761
26.9k
}
762
763
bool
764
resip::operator==(const Data& lhs, const std::string& rhs) noexcept
765
0
{
766
0
   return lhs.size() == rhs.size() && std::memcmp(lhs.data(), rhs.c_str(), rhs.size()) == 0;
767
0
}
768
769
#if RESIP_HAVE_STRING_VIEW
770
bool
771
resip::operator==(const Data& lhs, const std::string_view rhs) noexcept
772
0
{
773
0
   return lhs.size() == rhs.size() && std::memcmp(lhs.data(), rhs.data(), rhs.size()) == 0;
774
0
}
775
#endif
776
777
bool
778
resip::operator<(const Data& lhs, const Data& rhs)
779
12
{
780
12
   int res = memcmp(lhs.mBuf, rhs.mBuf, resipMin(lhs.mSize, rhs.mSize));
781
782
12
   if (res < 0)
783
8
   {
784
8
      return true;
785
8
   }
786
4
   else if (res > 0)
787
4
   {
788
4
      return false;
789
4
   }
790
0
   else
791
0
   {
792
0
      return (lhs.mSize < rhs.mSize);
793
0
   }
794
12
}
795
796
bool
797
resip::operator<(const Data& lhs, const char* rhs)
798
0
{
799
0
   resip_assert(rhs);
800
0
   Data::size_type l = (Data::size_type)strlen(rhs);
801
0
   int res = memcmp(lhs.mBuf, rhs, resipMin(lhs.mSize, l));
802
803
0
   if (res < 0)
804
0
   {
805
0
      return true;
806
0
   }
807
0
   else if (res > 0)
808
0
   {
809
0
      return false;
810
0
   }
811
0
   else
812
0
   {
813
0
      return (lhs.mSize < l);
814
0
   }
815
0
}
816
817
bool
818
resip::operator<(const char* lhs, const Data& rhs)
819
0
{
820
0
   resip_assert(lhs);
821
0
   Data::size_type l = (Data::size_type)strlen(lhs);
822
0
   int res = memcmp(lhs, rhs.mBuf, resipMin(l, rhs.mSize));
823
824
0
   if (res < 0)
825
0
   {
826
0
      return true;
827
0
   }
828
0
   else if (res > 0)
829
0
   {
830
0
      return false;
831
0
   }
832
0
   else
833
0
   {
834
0
      return (l < rhs.mSize);
835
0
   }
836
0
}
837
838
bool
839
resip::operator<(const Data& lhs, const std::string& rhs) noexcept
840
0
{
841
0
   const Data::size_type l = rhs.size();
842
0
   if (lhs.mSize != l)
843
0
   {
844
0
      return lhs.mSize < l;
845
0
   }
846
0
   return memcmp(lhs.mBuf, rhs.c_str(), lhs.mSize) < 0;
847
0
}
848
849
bool
850
resip::operator<(const std::string& lhs, const Data& rhs) noexcept
851
0
{
852
0
   const Data::size_type lhsSize = lhs.size();
853
0
   if (lhsSize != rhs.mSize)
854
0
   {
855
0
      return lhsSize < rhs.mSize;
856
0
   }
857
0
   return memcmp(lhs.c_str(), rhs.mBuf, lhsSize) < 0;
858
0
}
859
860
#if RESIP_HAVE_STRING_VIEW
861
bool
862
resip::operator<(const Data& lhs, const std::string_view rhs) noexcept
863
0
{
864
0
   const Data::size_type rhsSize = rhs.size();
865
0
   if (lhs.mSize != rhsSize)
866
0
   {
867
0
      return lhs.mSize < rhsSize;
868
0
   }
869
0
   return memcmp(lhs.mBuf, rhs.data(), lhs.mSize) < 0;
870
0
}
871
872
bool
873
resip::operator<(const std::string_view lhs, const Data& rhs) noexcept
874
0
{
875
0
   const Data::size_type lhsSize = lhs.size();
876
0
   if (lhsSize != rhs.mSize)
877
0
   {
878
0
      return lhsSize < rhs.mSize;
879
0
   }
880
0
   return memcmp(lhs.data(), rhs.mBuf, lhsSize) < 0;
881
0
}
882
#endif
883
884
885
#if 0
886
// Moved to inline header as special case of copy()
887
Data& 
888
Data::operator=(const Data& data)
889
{
890
   resip_assert(mBuf);
891
   
892
   if (&data != this)
893
   {
894
      if (mShareEnum == Share)
895
      {
896
         resize(data.mSize, false);
897
      }
898
      else
899
      {
900
         if (data.mSize > mCapacity)
901
         {
902
            resize(data.mSize, false);
903
         }
904
      }
905
      
906
      mSize = data.mSize;
907
      // could overlap!
908
      if (mSize > 0)
909
      {
910
         memmove(mBuf, data.mBuf, mSize);
911
      }
912
      mBuf[mSize] = 0;
913
   }
914
   return *this;
915
}
916
#endif
917
918
#ifdef RESIP_HAS_RVALUE_REFS
919
Data& Data::operator=(Data &&data)
920
{
921
   if (&data != this)
922
   {
923
      if (data.mPreBuffer != data.mBuf)
924
      {
925
         //data is not using the local buffer, take ownership of data.
926
         mBuf = data.mBuf;
927
         mCapacity = data.mCapacity;
928
         mShareEnum = data.mShareEnum;
929
         mSize = data.mSize;
930
         data.mShareEnum = Borrow; //don't delete the transferred buffer in data's destructor.
931
      }
932
      else
933
      {
934
         *this = data; //lvalue assignment operator will be called for named rvalue.
935
      }
936
   }
937
   
938
   return *this;
939
}
940
#endif
941
942
Data::size_type
943
Data::truncate(size_type len)
944
0
{
945
0
   if (len < mSize)
946
0
   {
947
0
      (*this)[len] = 0;
948
0
      mSize = len;
949
0
   }
950
951
0
   return mSize;
952
0
}
953
954
Data&
955
Data::truncate2(size_type len)
956
751
{
957
751
   if (len < mSize)
958
377
   {
959
      // NOTE: Do not write terminating NULL, to avoid un-doing Share
960
377
      mSize = len;
961
377
   }
962
751
   return *this;
963
751
}
964
965
Data 
966
Data::operator+(const Data& data) const
967
36.5k
{
968
36.5k
   Data tmp(mSize + (int)data.mSize, Data::Preallocate);
969
36.5k
   tmp.mSize = mSize + data.mSize;
970
36.5k
   tmp.mCapacity = tmp.mSize;
971
36.5k
   memcpy(tmp.mBuf, mBuf, mSize);
972
36.5k
   memcpy(tmp.mBuf + mSize, data.mBuf, data.mSize);
973
36.5k
   tmp.mBuf[tmp.mSize] = 0;
974
975
36.5k
   return tmp;
976
36.5k
}
977
978
Data&
979
Data::operator^=(const Data& rhs)
980
0
{
981
0
   if (mCapacity < rhs.mSize)
982
0
   {
983
0
      resize(rhs.mSize, true);
984
0
   }
985
0
   if (mSize < rhs.mSize)
986
0
   {
987
0
      memset(mBuf+mSize, 0, mCapacity - mSize);
988
0
   }
989
990
0
   char* c1 = mBuf;
991
0
   char* c2 = rhs.mBuf;
992
0
   char* end = c2 + rhs.mSize;
993
0
   while (c2 != end)
994
0
   {
995
0
      *c1++ ^= *c2++;
996
0
   }
997
0
   mSize = resipMax(mSize, rhs.mSize);
998
   
999
0
   return *this;
1000
0
}
1001
1002
char& 
1003
Data::at(size_type p)
1004
0
{
1005
0
   if (p >= mCapacity)
1006
0
   {
1007
0
      resize(p+1, true);
1008
0
   }
1009
0
   else
1010
0
   {
1011
0
      own();
1012
0
      if (p > mSize)
1013
0
      {
1014
0
         mSize = p + 1;
1015
0
         mBuf[mSize] = 0;
1016
0
      }
1017
0
   }
1018
0
   return mBuf[p];
1019
0
}
1020
1021
#if 0
1022
// Moved to inline header as special case of copy()
1023
Data& 
1024
Data::operator=(const char* str)
1025
{
1026
   resip_assert(str);
1027
   size_type l = strlen(str);
1028
1029
   if (mShareEnum == Share)
1030
   {
1031
      resize(l, false);
1032
   }
1033
   else
1034
   {
1035
      if (l > mCapacity)
1036
      {
1037
         resize(l, false);
1038
      }
1039
   }
1040
      
1041
   mSize = l;
1042
   // could conceivably overlap
1043
   memmove(mBuf, str, mSize+1);
1044
1045
   return *this;
1046
}
1047
#endif
1048
1049
Data 
1050
Data::operator+(const char* str) const
1051
0
{
1052
0
   resip_assert(str);
1053
0
   Data::size_type l = (Data::size_type)strlen(str);
1054
0
   Data tmp(mSize + l, Data::Preallocate);
1055
0
   tmp.mSize = mSize + l;
1056
0
   tmp.mCapacity = tmp.mSize;
1057
0
   memcpy(tmp.mBuf, mBuf, mSize);
1058
0
   memcpy(tmp.mBuf + mSize, str, l+1);
1059
1060
0
   return tmp;
1061
0
}
1062
1063
void
1064
Data::reserve(size_type len)
1065
0
{
1066
0
   if (len > mCapacity)
1067
0
   {
1068
0
      resize(len, true);
1069
0
   }
1070
0
}
1071
1072
Data&
1073
Data::append(const char* str, size_type len)
1074
1.45G
{
1075
1.45G
   resip_assert(str);
1076
1.45G
   if (mCapacity <= mSize + len)  // append null terminates, thus the equality
1077
45.4k
   {
1078
      // .dlb. pad for future growth?
1079
45.4k
      resize(((mSize + len +16)*3)/2, true);
1080
45.4k
   }
1081
1.45G
   else
1082
1.45G
   {
1083
1.45G
      if (mShareEnum == Share)
1084
0
      {
1085
0
         resize(mSize + len, true);
1086
0
      }
1087
1.45G
   }
1088
1089
   // could conceivably overlap
1090
1.45G
   memmove(mBuf + mSize, str, len);
1091
1.45G
   mSize += len;
1092
1.45G
   mBuf[mSize] = 0;
1093
1094
1.45G
   return *this;
1095
1.45G
}
1096
1097
1098
Data
1099
Data::operator+(char c) const
1100
0
{
1101
0
   Data tmp(mSize + 1, Data::Preallocate);
1102
0
   tmp.mSize = mSize + 1;
1103
0
   tmp.mCapacity = tmp.mSize;
1104
0
   memcpy(tmp.mBuf, mBuf, mSize);
1105
0
   tmp.mBuf[mSize] = c;
1106
0
   tmp.mBuf[mSize+1] = 0;
1107
1108
0
   return tmp;
1109
0
}
1110
1111
const char* 
1112
Data::c_str() const
1113
164
{
1114
164
   if (mShareEnum == Data::Share || mSize == mCapacity)
1115
152
   {
1116
152
      const_cast<Data*>(this)->resize(mSize+1,true);
1117
152
   }
1118
   // mostly is zero terminated, but not by DataStream
1119
164
   mBuf[mSize] = 0;
1120
164
   return mBuf;
1121
164
}
1122
1123
std::string 
1124
Data::toString() const
1125
0
{
1126
0
   return std::string(c_str(), size());
1127
0
}
1128
1129
#if RESIP_HAVE_STRING_VIEW
1130
std::string_view 
1131
Data::toStringView() const
1132
0
{
1133
0
   return std::string_view(c_str(), size());
1134
0
}
1135
#endif
1136
1137
void
1138
Data::own() const
1139
8.38M
{
1140
8.38M
   if (mShareEnum == Share)
1141
7.97k
   {
1142
7.97k
      const_cast<Data*>(this)->resize(mSize, true);
1143
7.97k
   }
1144
8.38M
}
1145
1146
// generate additional capacity
1147
void
1148
Data::resize(size_type newCapacity, 
1149
             bool copy)
1150
490k
{
1151
490k
   resip_assert(newCapacity >= mCapacity || mShareEnum == Data::Share);
1152
1153
490k
   char *oldBuf = mBuf;
1154
490k
   bool needToDelete=(mShareEnum==Take);
1155
1156
490k
   size_t newBytes = newCapacity + 1;
1157
490k
   if(newBytes <= newCapacity)
1158
0
   {
1159
      // integer overflow
1160
0
      throw std::range_error("newCapacity too big");
1161
0
   }
1162
1163
490k
   if(newCapacity > LocalAlloc)
1164
473k
   {
1165
473k
      mBuf = new char[newBytes];
1166
473k
      mShareEnum = Take;
1167
473k
   }
1168
16.8k
   else
1169
16.8k
   {
1170
16.8k
      mBuf = mPreBuffer;
1171
16.8k
      mShareEnum = Borrow;
1172
16.8k
   }
1173
1174
490k
   if (copy)
1175
475k
   {
1176
475k
      memcpy(mBuf, oldBuf, mSize);
1177
475k
      mBuf[mSize] = 0;
1178
475k
   }
1179
1180
490k
   if (needToDelete)
1181
379k
   {
1182
379k
      delete[] oldBuf;
1183
379k
   }
1184
1185
490k
   mCapacity = newCapacity;
1186
490k
}
1187
1188
Data
1189
Data::md5(EncodingType type) const
1190
0
{
1191
0
   MD5Context context;
1192
0
   MD5Init(&context);
1193
0
   MD5Update(&context, reinterpret_cast < unsigned const char* > (mBuf), (unsigned int)mSize);
1194
1195
0
   unsigned char digestBuf[16];
1196
0
   MD5Final(digestBuf, &context);
1197
0
   Data digest(digestBuf,16);
1198
1199
0
   switch(type)
1200
0
   {
1201
0
      case BINARY:
1202
0
         return digest;
1203
0
      case BASE64:
1204
0
         return digest.base64encode(true);
1205
0
      case HEX:
1206
0
      default:
1207
0
         return digest.hex();
1208
0
   }
1209
0
   resip_assert(0);
1210
0
   return digest.hex();
1211
0
}
1212
1213
Data 
1214
Data::escaped() const
1215
0
{ 
1216
0
   Data ret((int)((size()*11)/10), Data::Preallocate);
1217
1218
0
   const char* p = data();
1219
0
   for (size_type i=0; i < size(); ++i)
1220
0
   {
1221
0
      unsigned char c = *p++;
1222
1223
0
      if ( c == 0x0d )
1224
0
      {
1225
0
         if ( i+1 < size() )
1226
0
         {
1227
0
            if ( *p == 0x0a )
1228
0
            {
1229
               // found a CRLF sequence
1230
0
               ret += c;
1231
0
               c = *p++; i++;
1232
0
               ret += c;
1233
0
               continue;
1234
0
            }
1235
0
         }
1236
0
      }
1237
      
1238
0
      if ( !isprint(c) )
1239
0
      {
1240
0
         ret +='%';
1241
         
1242
0
         int hi = (c & 0xF0)>>4;
1243
0
         int low = (c & 0x0F);
1244
      
1245
0
         ret += hexmap[hi];
1246
0
         ret += hexmap[low];
1247
0
      }
1248
0
      else
1249
0
      {
1250
0
         ret += c;
1251
0
      }
1252
0
   }
1253
1254
0
   return ret;
1255
0
}
1256
1257
Data 
1258
Data::charEncoded() const
1259
0
{ 
1260
0
   Data ret((int)((size()*11)/10), Data::Preallocate);
1261
1262
0
   const char* p = data();
1263
0
   for (size_type i=0; i < size(); ++i)
1264
0
   {
1265
0
      unsigned char c = *p++;
1266
1267
0
      if ( c == 0x0d )
1268
0
      {
1269
0
         if ( i+1 < size() )
1270
0
         {
1271
0
            if ( *p == 0x0a )
1272
0
            {
1273
               // found a CRLF sequence
1274
0
               ret += c;
1275
0
               c = *p++; i++;
1276
0
               ret += c;
1277
0
               continue;
1278
0
            }
1279
0
         }
1280
0
      }
1281
      
1282
0
      if ( !isprint(c) ||
1283
           // rfc 3261 reserved + mark + space + tab
1284
0
           strchr(" \";/?:@&=+%$,\t-_.!~*'()", c))
1285
0
      {
1286
0
         ret +='%';
1287
         
1288
0
         int hi = (c & 0xF0)>>4;
1289
0
         int low = (c & 0x0F);
1290
      
1291
0
         ret += hexmap[hi];
1292
0
         ret += hexmap[low];
1293
0
      }
1294
0
      else
1295
0
      {
1296
0
         ret += c;
1297
0
      }
1298
0
   }
1299
1300
0
   return ret;
1301
0
}
1302
1303
Data
1304
Data::charUnencoded() const
1305
0
{
1306
0
   Data ret(size(), Data::Preallocate);
1307
1308
0
   const char* p = data();
1309
0
   for (size_type i = 0; i < size(); ++i)
1310
0
   {
1311
0
      unsigned char c = *p++;
1312
0
      if (c == '%')
1313
0
      {
1314
0
         if ( i+2 < size())
1315
0
         {
1316
0
            const char* high = strchr(hexmap, tolower(*p++));
1317
0
            const char* low = strchr(hexmap, tolower(*p++));
1318
1319
            // !rwm! changed from high==0 || low==0
1320
0
            if (high == 0 && low == 0)
1321
0
            {
1322
0
               resip_assert(0);
1323
               // ugh
1324
0
               return ret;
1325
0
            }
1326
            
1327
0
            int highInt = int(high - hexmap);
1328
0
            int lowInt = int(low - hexmap);
1329
0
            ret += char(highInt<<4 | lowInt);
1330
0
            i += 2;
1331
0
         }
1332
0
         else
1333
0
         {
1334
0
            break;
1335
0
         }
1336
0
      }
1337
0
      else
1338
0
      {
1339
0
         ret += c;
1340
0
      }
1341
0
   }
1342
0
   return ret;
1343
0
}
1344
1345
Data
1346
Data::urlEncoded() const
1347
0
{
1348
0
   Data buffer;
1349
0
   DataStream strm(buffer);
1350
0
   urlEncode(strm);
1351
0
   strm.flush();
1352
0
   return buffer;
1353
0
}
1354
1355
Data
1356
Data::urlDecoded() const
1357
0
{
1358
0
   Data buffer;
1359
0
   DataStream strm(buffer);
1360
0
   urlDecode(strm);
1361
0
   strm.flush();
1362
0
   return buffer;
1363
0
}
1364
1365
EncodeStream&
1366
Data::urlDecode(EncodeStream& s) const
1367
0
{
1368
0
   unsigned int i = 0;
1369
0
   for (const char* p = data(); p != data()+size(); ++p, ++i)
1370
0
   {
1371
0
      unsigned char c = *p;
1372
0
      if (c == '%')
1373
0
      {
1374
0
         if (i+2 < size())
1375
0
         {
1376
0
            s << (char) hexpair2int( *(p+1), *(p+2));
1377
0
            p += 2;
1378
0
         }
1379
0
         else
1380
0
         {
1381
0
            break;
1382
0
         }
1383
0
      }
1384
0
      else if (c == '+')
1385
0
      {
1386
0
         s << ' ';
1387
0
      }
1388
0
      else
1389
0
      {
1390
0
         s << c;
1391
0
      }
1392
0
   }
1393
0
   return s;
1394
0
}
1395
1396
bool urlNonEncodedChars[256] = {false};
1397
bool 
1398
urlNonEncodedCharsInitFn()
1399
4
{
1400
   // query part of HTTP URL can be a pchar, slash, or question
1401
   // pchar is unreserved, subdelims, colon, at-sign
1402
1403
1.02k
   for (int i = 0; i < 256; ++i)
1404
1.02k
   {
1405
1.02k
      unsigned char c(i);
1406
1.02k
      urlNonEncodedChars[c] = (isalpha(c) ||  // unreserved
1407
1.02k
                               isdigit(c) ||  // unreserved
1408
1.02k
                               c == '-' ||  // these first 4 are unreserved
1409
1.02k
                               c == '_' ||
1410
1.02k
                               c == '.' ||
1411
1.02k
                               c == '~' ||
1412
1.02k
                               c == '!' ||  // these are subdelims (allowed in pchars)
1413
1.02k
                               c == '$' ||
1414
//                               c == '&' ||  // while these are allowed subdelims, this is an error
1415
//                               c == '+' ||  // I believe this is an error as well.
1416
1.02k
                               c == '\'' ||
1417
1.02k
                               c == '(' ||
1418
1.02k
                               c == ')' ||
1419
1.02k
                               c == '*' ||
1420
1.02k
                               c == ',' ||
1421
1.02k
                               c == ';' ||
1422
1.02k
                               c == '=' ||
1423
1.02k
                               c == ':' ||   // next two explicitly allowed in pchar
1424
1.02k
                               c == '@' ||   
1425
1.02k
                               c == '/' ||   // next two explicitly allowed in query in addition to pchar
1426
1.02k
                               c == '?');    
1427
1.02k
   }
1428
1429
4
   return false;
1430
4
}
1431
1432
static bool dummy = urlNonEncodedCharsInitFn();
1433
1434
// e.g. http://www.blooberry.com/indexdot/html/topics/urlencoding.htm
1435
EncodeStream&
1436
Data::urlEncode(EncodeStream& s) const
1437
0
{
1438
0
   for (const char* p = data(); p != data() + size(); ++p)
1439
0
   {
1440
0
      unsigned char c = *p;
1441
1442
      // pchar, slash, questionmark
1443
      // pchar = unreserved, sub-delims, colon, at-sign
1444
      // unreserved = alphanum, hyphen, underscore, period, tilde
1445
      // subdelims = bang (!), dollar, ampersand (oops!), plus, single-quote, lparen, rparen, asterisk, comma, semicolon, equal
1446
      //if (isalpha(c) || isdigit(c) || strchr("-_.~!$+'()*,;=:@/?", c)) //
1447
      // strchr is inefficient and wrong
1448
0
      if (urlNonEncodedChars[c])
1449
0
      {
1450
0
         s << c;
1451
0
      }
1452
0
      else
1453
0
      {
1454
0
         if (c == 0x20)
1455
0
         {
1456
0
            s << '+';
1457
0
         }
1458
0
         else
1459
0
         {
1460
0
            s << '%' << (hexmap[(c & 0xF0)>>4]) << (hexmap[(c & 0x0F)]);
1461
0
         }
1462
0
      }
1463
0
   }
1464
1465
0
   return s;
1466
0
}
1467
1468
Data
1469
Data::xmlCharDataEncode() const
1470
0
{
1471
0
   Data buffer;
1472
0
   DataStream strm(buffer);
1473
0
   xmlCharDataEncode(strm);
1474
0
   strm.flush();
1475
0
   return buffer;
1476
0
}
1477
1478
Data
1479
Data::xmlCharDataDecode() const
1480
0
{
1481
0
   Data buffer;
1482
0
   DataStream strm(buffer);
1483
0
   xmlCharDataDecode(strm);
1484
0
   strm.flush();
1485
0
   return buffer;
1486
0
}
1487
1488
// http://www.w3.org/TR/REC-xml/#syntax
1489
EncodeStream&
1490
Data::xmlCharDataEncode(EncodeStream& s) const
1491
0
{
1492
0
   for (const char* p = data(); p != data() + size(); ++p)
1493
0
   {
1494
0
      unsigned char c = *p;
1495
1496
0
      switch(c)
1497
0
      {
1498
0
      case '&':
1499
0
         s << "&amp;";
1500
0
         break;
1501
0
      case '<':
1502
0
         s << "&lt;";
1503
0
         break;
1504
0
      case '>':
1505
0
         s << "&gt;";
1506
0
         break;
1507
0
      case '\'':
1508
0
         s << "&apos;";
1509
0
         break;
1510
0
      case '\"':
1511
0
         s << "&quot;";
1512
0
         break;
1513
0
      default:
1514
0
         s << c;
1515
0
      }
1516
0
   }
1517
1518
0
   return s;
1519
0
}
1520
1521
EncodeStream&
1522
Data::xmlCharDataDecode(EncodeStream& s) const
1523
0
{
1524
0
   unsigned int i = 0;
1525
0
   for (const char* p = data(); p != data()+size(); ++p, ++i)
1526
0
   {
1527
0
      unsigned char c = *p;
1528
0
      if (c == '&')
1529
0
      {
1530
         // look for amp;
1531
0
         if(i+4 < size() && 
1532
0
            *(p+1) == 'a' && *(p+2) == 'm' && *(p+3) == 'p' && *(p+4) == ';')
1533
0
         {
1534
0
            s << '&';
1535
0
            p += 4;
1536
0
         }
1537
         // look for lt;
1538
0
         else if(i+3 < size() && 
1539
0
            *(p+1) == 'l' && *(p+2) == 't' && *(p+3) == ';')
1540
0
         {
1541
0
            s << '<';
1542
0
            p += 3;
1543
0
         }
1544
         // look for gt;
1545
0
         else if(i+3 < size() &&
1546
0
            *(p+1) == 'g' && *(p+2) == 't' && *(p+3) == ';')
1547
0
         {
1548
0
            s << '>';
1549
0
            p += 3;
1550
0
         }
1551
         // look for apos;
1552
0
         else if(i+5 < size() && 
1553
0
            *(p+1) == 'a' && *(p+2) == 'p' && *(p+3) == 'o' && *(p+4) == 's' && *(p+5) == ';')
1554
0
         {
1555
0
            s << '\'';
1556
0
            p += 5;
1557
0
         }
1558
         // look for quot;
1559
0
         else if(i+5 < size() && 
1560
0
            *(p+1) == 'q' && *(p+2) == 'u' && *(p+3) == 'o' && *(p+4) == 't' && *(p+5) == ';')
1561
0
         {
1562
0
            s << '\"';
1563
0
            p += 5;
1564
0
         }
1565
0
         else // if no conversion found - just leave characters in data
1566
0
         {
1567
0
            s << c;
1568
0
         }
1569
0
      }
1570
0
      else
1571
0
      {
1572
0
         s << c;
1573
0
      }
1574
0
   }
1575
0
   return s;
1576
0
}
1577
1578
Data
1579
Data::trunc(size_type s) const
1580
0
{
1581
0
   if (size() <= s)
1582
0
   {
1583
0
      return *this;
1584
0
   }
1585
0
   else
1586
0
   {
1587
0
      return Data(data(), s) + "..";
1588
0
   }
1589
0
}
1590
1591
Data
1592
Data::hex() const
1593
6.29k
{
1594
6.29k
   Data ret( 2*mSize, Data::Preallocate);
1595
1596
6.29k
   const char* p = mBuf;
1597
6.29k
   char* r = ret.mBuf;
1598
56.6k
   for (size_type i=0; i < mSize; ++i)
1599
50.3k
   {
1600
50.3k
      unsigned char temp = *p++;
1601
1602
50.3k
      int hi = (temp & 0xf0)>>4;
1603
50.3k
      int low = (temp & 0xf);
1604
1605
50.3k
      *r++ = hexmap[hi];
1606
50.3k
      *r++ = hexmap[low];
1607
50.3k
   }
1608
6.29k
   *r = 0;
1609
6.29k
   ret.mSize = 2*mSize;
1610
6.29k
   return ret;
1611
6.29k
}
1612
1613
Data
1614
Data::fromHex() const
1615
0
{
1616
0
   bool oddSize = mSize & 1;
1617
0
   size_type resultSize = (mSize + (mSize & 1)) / 2;
1618
0
   Data ret(resultSize, Data::Preallocate);
1619
1620
0
   const unsigned char* p = (unsigned char*)mBuf;
1621
0
   char* r = ret.mBuf;
1622
0
   size_type i = 0;
1623
0
   if(oddSize)
1624
0
   {
1625
0
      if(!isHex(*p))
1626
0
      {
1627
0
         throw DataException("Encountered non-hex digit",
1628
0
                                    __FILE__,__LINE__);
1629
0
      }
1630
0
      *r++ = inversehexmap[*p++];
1631
0
      i++;
1632
0
   }
1633
0
   for ( ; i < mSize; i+=2)
1634
0
   {
1635
0
      const unsigned char high = *p++;
1636
0
      const unsigned char low = *p++;
1637
0
      if(!isHex(high) || !isHex(low))
1638
0
      {
1639
0
         throw DataException("Encountered non-hex digit",
1640
0
                                    __FILE__,__LINE__);
1641
0
      }
1642
1643
0
      *r++ = (inversehexmap[high] << 4) + inversehexmap[low];
1644
0
   }
1645
0
   ret.mSize = resultSize;
1646
0
   return ret;
1647
0
}
1648
1649
Data&
1650
Data::lowercase()
1651
0
{
1652
0
   own();
1653
0
   char* p = mBuf;
1654
0
   for (size_type i=0; i < mSize; ++i)
1655
0
   {
1656
0
      *p = tolower(*p);
1657
0
      ++p;
1658
0
   }
1659
0
   return *this;
1660
0
}
1661
1662
Data&
1663
Data::uppercase()
1664
0
{
1665
0
   own();
1666
0
   char* p = mBuf;
1667
0
   for (size_type i=0; i < mSize; ++i)
1668
0
   {
1669
0
      *p = toupper(*p);
1670
0
      ++p;
1671
0
   }
1672
0
   return *this;
1673
0
}
1674
1675
Data& 
1676
Data::schemeLowercase()
1677
7.67k
{
1678
7.67k
   own();
1679
7.67k
   char* p = mBuf;
1680
18.9M
   for (size_type i=0; i < mSize; ++i)
1681
18.9M
   {
1682
18.9M
      *p |= ' ';
1683
18.9M
      ++p;
1684
18.9M
   }
1685
7.67k
   return *this;
1686
7.67k
}
1687
1688
#if 0
1689
// in-lined into header as special case of truncate2()
1690
Data&
1691
Data::clear()
1692
{
1693
   mSize = 0;
1694
   return *this;
1695
}
1696
#endif
1697
1698
int 
1699
Data::convertInt() const
1700
0
{
1701
0
   int val = 0;
1702
0
   char* p = mBuf;
1703
0
   const char* const end = mBuf + mSize;
1704
0
   int s = 1;
1705
1706
0
   for (; p != end; ++p)
1707
0
   {
1708
0
      if (!isspace(*p))
1709
0
      {
1710
0
         goto sign_char;
1711
0
      }
1712
0
   }
1713
0
   return val;
1714
0
sign_char:
1715
1716
0
   if (*p == '-')
1717
0
   {
1718
0
      s = -1;
1719
0
      ++p;
1720
0
   }
1721
0
   else if (*p == '+')
1722
0
   {
1723
0
      ++p;
1724
0
   }
1725
1726
0
   for(; p != end; ++p)
1727
0
   {
1728
0
      if (!isdigit(*p))
1729
0
      {
1730
0
         break;
1731
0
      }
1732
0
      val *= 10;
1733
0
      val += (*p) - '0';
1734
0
   }
1735
0
   return s*val;
1736
0
}
1737
1738
unsigned long
1739
Data::convertUnsignedLong() const
1740
0
{
1741
0
   unsigned long val = 0;
1742
0
   char* p = mBuf;
1743
0
   const char* const end = mBuf + mSize;
1744
1745
0
   for (; p != end; ++p)
1746
0
   {
1747
0
      if (!isspace(*p))
1748
0
      {
1749
0
         goto sign_char;
1750
0
      }
1751
0
   }
1752
0
   return val;
1753
0
sign_char:
1754
1755
0
   if (*p == '+')
1756
0
   {
1757
0
      ++p;
1758
0
   }
1759
1760
0
   for(; p != end; ++p)
1761
0
   {
1762
0
      if (!isdigit(*p))
1763
0
      {
1764
0
         break;
1765
0
      }
1766
0
      val *= 10;
1767
0
      val += (*p) - '0';
1768
0
   }
1769
0
   return val;
1770
0
}
1771
1772
uint64_t
1773
Data::convertUInt64() const
1774
0
{
1775
0
   uint64_t val = 0;
1776
0
   char* p = mBuf;
1777
0
   const char* const end = mBuf + mSize;
1778
1779
0
   for (; p != end; ++p)
1780
0
   {
1781
0
      if (!isspace(*p))
1782
0
      {
1783
0
         goto sign_char;
1784
0
      }
1785
0
   }
1786
0
   return val;
1787
0
sign_char:
1788
1789
0
   if (*p == '+')
1790
0
   {
1791
0
      ++p;
1792
0
   }
1793
1794
0
   for(; p != end; ++p)
1795
0
   {
1796
0
      if (!isdigit(*p))
1797
0
      {
1798
0
         break;
1799
0
      }
1800
0
      val *= 10;
1801
0
      val += (*p) - '0';
1802
0
   }
1803
0
   return val;
1804
0
}
1805
1806
size_t
1807
Data::convertSize() const
1808
0
{
1809
0
   size_t val = 0;
1810
0
   char* p = mBuf;
1811
0
   const char* const end = mBuf + mSize;
1812
1813
0
   for (; p != end; ++p)
1814
0
   {
1815
0
      if (!isspace(*p))
1816
0
      {
1817
0
         goto sign_char;
1818
0
      }
1819
0
   }
1820
0
   return val;
1821
0
sign_char:
1822
1823
0
   if (*p == '+')
1824
0
   {
1825
0
      ++p;
1826
0
   }
1827
1828
0
   for(; p != end; ++p)
1829
0
   {
1830
0
      if (!isdigit(*p))
1831
0
      {
1832
0
         break;
1833
0
      }
1834
0
      val *= 10;
1835
0
      val += (*p) - '0';
1836
0
   }
1837
0
   return val;
1838
0
}
1839
1840
#ifndef RESIP_FIXED_POINT
1841
double 
1842
Data::convertDouble() const
1843
0
{
1844
0
   long val = 0;
1845
0
   char* p = mBuf;
1846
0
   const char* const end = p + mSize;
1847
0
   int s = 1;
1848
1849
0
   for (; p != end; ++p)
1850
0
   {
1851
0
      if (!isspace(*p))
1852
0
      {
1853
0
         goto sign_char;
1854
0
      }
1855
0
   }
1856
0
   return val;
1857
0
sign_char:
1858
1859
0
   if (*p == '-')
1860
0
   {
1861
0
      s = -1;
1862
0
      ++p;
1863
0
   }
1864
0
   else if (*p == '+')
1865
0
   {
1866
0
      ++p;
1867
0
   }
1868
1869
0
   for(; p != end; ++p)
1870
0
   {
1871
0
      if (*p == '.')
1872
0
      {
1873
0
         goto decimals;
1874
0
      }
1875
0
      if (!isdigit(*p))
1876
0
      {
1877
0
         return s*val;
1878
0
      }
1879
0
      val *= 10;
1880
0
      val += (*p) - '0';
1881
0
   }
1882
0
   return s*val;
1883
1884
0
decimals:
1885
0
   ++p;
1886
0
   long d = 0;
1887
0
   double div = 1.0;
1888
0
   for(; p != end; ++p)
1889
0
   {
1890
0
      if (!isdigit(*p)) 
1891
0
      {
1892
0
         break;
1893
0
      }
1894
0
      d *= 10;
1895
0
      d += *p - '0';
1896
0
      div *= 10;
1897
0
   }
1898
0
   return s*(val + d/div);
1899
0
}
1900
#endif
1901
1902
bool
1903
Data::prefix(const Data& pre) const noexcept
1904
0
{
1905
0
   if (pre.size() > size())
1906
0
   {
1907
0
      return false;
1908
0
   }
1909
1910
0
   return memcmp(data(), pre.data(), pre.size()) == 0;
1911
0
}
1912
1913
1914
bool
1915
Data::postfix(const Data& post) const noexcept
1916
0
{
1917
0
   if (post.size() > size())
1918
0
   {
1919
0
      return false;
1920
0
   }
1921
1922
0
   return memcmp(data() + (size()-post.size()), post.data(), post.size()) == 0;
1923
0
}
1924
1925
Data 
1926
Data::substr(size_type first, size_type count) const
1927
0
{
1928
0
   resip_assert(first <= mSize);
1929
0
   if ( count == Data::npos)
1930
0
   {
1931
0
      return Data(mBuf+first, mSize-first);
1932
0
   }
1933
0
   else
1934
0
   {
1935
0
      resip_assert(first + count <= mSize);
1936
0
      return Data(mBuf+first, count);
1937
0
   }
1938
0
}
1939
1940
Data::size_type
1941
Data::find(const Data& match, 
1942
           size_type start) const
1943
117
{
1944
117
   if (start < mSize)
1945
115
   {
1946
115
      ParseBuffer pb(mBuf + start, mSize - start);
1947
115
      pb.skipToChars(match);
1948
115
      if (!pb.eof())
1949
103
      {
1950
103
         return (Data::size_type)(pb.position() - pb.start() + start);
1951
103
      }
1952
115
   }
1953
1954
14
   return Data::npos;
1955
117
}
1956
1957
int
1958
Data::replace(const Data& match, 
1959
              const Data& replaceWith,
1960
              int max)
1961
0
{
1962
0
   resip_assert(!match.empty());
1963
1964
0
   int count = 0;
1965
1966
0
   const int incr = int(replaceWith.size() - match.size());
1967
0
   for (size_type offset = find(match, 0); 
1968
0
        count < max && offset != Data::npos; 
1969
0
        offset = find(match, offset+replaceWith.size()))
1970
0
   {
1971
0
      if (mSize + incr >= mCapacity)
1972
0
      {
1973
0
         resize((mCapacity + incr) * 3 / 2, true);
1974
0
      }
1975
0
      else
1976
0
      {
1977
0
         own();
1978
0
      }
1979
1980
      // move the memory forward (or backward)
1981
0
      memmove(mBuf + offset + replaceWith.size(), mBuf + offset + match.size(), mSize - offset - match.size());
1982
0
      memcpy(mBuf + offset, replaceWith.data(), replaceWith.size());
1983
0
      mSize += incr;
1984
1985
0
      ++count;
1986
0
   }
1987
1988
0
   return count;
1989
0
}
1990
1991
#ifndef  RESIP_USE_STL_STREAMS
1992
EncodeStream& 
1993
resip::operator<<(EncodeStream& strm, const Data& d)
1994
{
1995
   return strm.write(d.mBuf, d.mSize);
1996
}
1997
#endif
1998
1999
// random permutation of 0..255
2000
static const unsigned char randomPermutation[256] = 
2001
{
2002
   44, 9, 46, 184, 21, 30, 92, 231, 79, 7, 166, 237, 173, 72, 91, 123, 
2003
   212, 183, 16, 99, 85, 45, 190, 130, 118, 107, 169, 119, 100, 179, 251, 177,
2004
   23, 125, 12, 101, 121, 246, 61, 38, 156, 114, 159, 57, 181, 145, 198, 182,
2005
   58, 215, 174, 225, 82, 178, 150, 161, 63, 103, 32, 203, 68, 151, 139, 55, 
2006
   143, 2, 36, 110, 209, 154, 204, 89, 62, 17, 187, 226, 31, 105, 195, 208,
2007
   49, 56, 238, 172, 37, 3, 234, 206, 134, 233, 19, 148, 64, 4, 10, 224,
2008
   144, 88, 93, 191, 20, 131, 138, 199, 243, 244, 39, 50, 214, 87, 6, 84,
2009
   185, 112, 171, 75, 192, 193, 239, 69, 106, 43, 194, 1, 78, 67, 116, 200,
2010
   83, 70, 213, 25, 59, 137, 52, 13, 153, 42, 232, 0, 133, 210, 76, 33,
2011
   255, 236, 124, 104, 65, 201, 53, 155, 140, 254, 54, 196, 120, 146, 216, 29,
2012
   28, 86, 245, 90, 98, 26, 81, 115, 180, 66, 102, 136, 167, 51, 109, 132,
2013
   77, 175, 14, 202, 222, 48, 223, 188, 40, 242, 157, 5, 128, 229, 71, 127,
2014
   164, 207, 247, 8, 80, 149, 94, 160, 47, 117, 135, 176, 129, 142, 189, 97,
2015
   11, 250, 221, 218, 96, 220, 35, 197, 152, 126, 219, 74, 170, 252, 163, 41,
2016
   95, 27, 34, 22, 205, 230, 241, 186, 168, 228, 253, 249, 113, 108, 111, 211,
2017
   235, 217, 165, 122, 15, 141, 158, 147, 240, 24, 162, 18, 60, 73, 227, 248
2018
};
2019
2020
size_t
2021
Data::rawHash(const unsigned char* c, size_t size)
2022
34.4k
{
2023
   // 4 byte Pearson's hash
2024
   // essentially random hashing
2025
2026
34.4k
   union 
2027
34.4k
   {
2028
34.4k
         size_t st;
2029
34.4k
         unsigned char bytes[4];
2030
34.4k
   };
2031
34.4k
   st = 0; // suppresses warnings about unused st
2032
34.4k
   bytes[0] = randomPermutation[0];
2033
34.4k
   bytes[1] = randomPermutation[1];
2034
34.4k
   bytes[2] = randomPermutation[2];
2035
34.4k
   bytes[3] = randomPermutation[3];
2036
2037
34.4k
   const unsigned char* end = c + size;
2038
2.28M
   for ( ; c != end; ++c)
2039
2.24M
   {
2040
2.24M
      bytes[0] = randomPermutation[*c ^ bytes[0]];
2041
2.24M
      bytes[1] = randomPermutation[*c ^ bytes[1]];
2042
2.24M
      bytes[2] = randomPermutation[*c ^ bytes[2]];
2043
2.24M
      bytes[3] = randomPermutation[*c ^ bytes[3]];
2044
2.24M
   }
2045
2046
   // convert from network to host byte order
2047
34.4k
   return ntohl((u_long)st);
2048
34.4k
}
2049
2050
// use only for ascii characters!
2051
size_t 
2052
Data::rawCaseInsensitiveHash(const unsigned char* c, size_t size)
2053
0
{
2054
2055
0
   union 
2056
0
   {
2057
0
         size_t st;
2058
0
         unsigned char bytes[4];
2059
0
   };
2060
0
   st = 0; // suppresses warnings about unused st
2061
0
   bytes[0] = randomPermutation[0];
2062
0
   bytes[1] = randomPermutation[1];
2063
0
   bytes[2] = randomPermutation[2];
2064
0
   bytes[3] = randomPermutation[3];
2065
2066
0
   const unsigned char* end = c + size;
2067
0
   for ( ; c != end; ++c)
2068
0
   {
2069
0
      unsigned char cc = tolower(*c);
2070
0
      bytes[0] = randomPermutation[cc ^ bytes[0]];
2071
0
      bytes[1] = randomPermutation[cc ^ bytes[1]];
2072
0
      bytes[2] = randomPermutation[cc ^ bytes[2]];
2073
0
      bytes[3] = randomPermutation[cc ^ bytes[3]];
2074
0
   }
2075
2076
   // convert from network to host byte order
2077
0
   return ntohl((u_long)st);
2078
0
}
2079
2080
#if defined(RESIP_BIG_ENDIAN) || (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
2081
2082
#if !defined (get16bits)
2083
#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[0])) << 8)\
2084
                       +(uint32_t)(((const uint8_t *)(d))[1]) )
2085
#endif
2086
2087
#if !defined (get32bits)
2088
#define get32bits(d) ((get16bits(d) << 16) + get16bits(d+2))
2089
#endif
2090
2091
#else  // little endian:
2092
2093
#undef get16bits
2094
#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \
2095
  || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__)
2096
#define get16bits(d) (*((const uint16_t *) (d)))
2097
#endif
2098
2099
#if !defined (get16bits)
2100
666
#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8)\
2101
666
                       +(uint32_t)(((const uint8_t *)(d))[0]) )
2102
#endif
2103
2104
#undef get32bits
2105
#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \
2106
  || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__)
2107
#define get32bits(d) (*((const uint32_t *) (d)))
2108
#endif
2109
2110
#if !defined (get32bits)
2111
284
#define get32bits(d) ((get16bits(d+2) << 16) + get16bits(d))
2112
#endif
2113
#endif
2114
2115
// This is intended to be a faster case-insensitive hash function that works
2116
// well when the buffer is a RFC 3261 token.
2117
// Having non-token characters will not prevent the hash from working, but it 
2118
// will increase the number of cases where a single char difference will result 
2119
// in a hash collision. The pairs of _printable_ characters that this hash will 
2120
// not distinguish between are @`, [{, \|, ]} and ^~
2121
// (Note that, for RFC 3261 tokens, this will not be a problem since @, [, {, \, 
2122
// |, ], } and ^ are not allowed in a token.)
2123
size_t
2124
Data::rawCaseInsensitiveTokenHash(const unsigned char* data, size_t len)
2125
148
{
2126
   // .bwc. Hsieh hash, with some bitmasking to get the case-insensitive 
2127
   // property (this is what all the "0x2020 |" business is about.)
2128
148
   uint32_t hash = (uint32_t)len, tmp;
2129
148
   int rem;
2130
2131
148
    if (len <= 0 || data == NULL) return 0;
2132
2133
148
    rem = len & 3;
2134
148
    len >>= 2;
2135
2136
148
    union 
2137
148
    {
2138
148
          uint32_t masked;
2139
148
          uint16_t ui16[2];
2140
148
    };
2141
2142
    /* Main loop */
2143
432
    for (;len > 0; len--) 
2144
284
    {
2145
        // mask out bit 6 for case-insensitivity
2146
284
        masked = (0x20202020 | get32bits(data));
2147
284
        hash  += ui16[0];
2148
284
        tmp    = ((uint32_t)ui16[1] << 11) ^ hash;
2149
284
        hash   = (hash << 16) ^ tmp;
2150
284
        data  += 2*sizeof (uint16_t);
2151
284
        hash  += hash >> 11;
2152
284
    }
2153
2154
    /* Handle end cases */
2155
148
    switch (rem) 
2156
148
    {
2157
82
        case 3: hash += (0x2020 | get16bits (data));
2158
82
                hash ^= hash << 16;
2159
82
                hash ^= (0x20 | data[sizeof (uint16_t)]) << 18;
2160
82
                hash += hash >> 11;
2161
82
                break;
2162
16
        case 2: hash += (0x2020 | get16bits (data));
2163
16
                hash ^= hash << 11;
2164
16
                hash += hash >> 17;
2165
16
                break;
2166
28
        case 1: hash += (0x20 | *data);
2167
28
                hash ^= hash << 10;
2168
28
                hash += hash >> 1;
2169
148
    }
2170
2171
    /* Force "avalanching" of final 127 bits */
2172
148
    hash ^= hash << 3;
2173
148
    hash += hash >> 5;
2174
148
    hash ^= hash << 4;
2175
148
    hash += hash >> 17;
2176
148
    hash ^= hash << 25;
2177
148
    hash += hash >> 6;
2178
2179
148
    return hash;
2180
2181
//   union 
2182
//   {
2183
//         size_t st;
2184
//         unsigned char bytes[4];
2185
//   };
2186
//   st = 0; // suppresses warnings about unused st
2187
//   bytes[0] = randomPermutation[0];
2188
//   bytes[1] = randomPermutation[1];
2189
//   bytes[2] = randomPermutation[2];
2190
//   bytes[3] = randomPermutation[3];
2191
//
2192
//   const unsigned char* end = c + size;
2193
//   for ( ; c != end; ++c)
2194
//   {
2195
//       union
2196
//       {
2197
//         uint32_t temp;
2198
//         uint8_t cccc[4];
2199
//       };
2200
//       // .bwc. Mask out bit 6, use a multiplication op to write the 
2201
//       // resulting byte to each of the 4 bytes in temp, and xor the whole 
2202
//       // thing with bytes/st.
2203
//      temp = ( (*c | ' ') * 16843009UL) ^ st;
2204
//      bytes[0] = randomPermutation[cccc[0]];
2205
//      bytes[1] = randomPermutation[cccc[1]];
2206
//      bytes[2] = randomPermutation[cccc[2]];
2207
//      bytes[3] = randomPermutation[cccc[3]];
2208
//   }
2209
//
2210
//   // convert from network to host byte order
2211
//   return ntohl((u_long)st);
2212
148
}
2213
2214
Data
2215
bits(size_t v)
2216
0
{
2217
0
   Data ret;
2218
0
   for (unsigned int i = 0; i < 8*sizeof(size_t); ++i)
2219
0
   {
2220
0
      ret += ('0' + v%2);
2221
0
      v /= 2;
2222
0
   }
2223
2224
0
   return ret;
2225
0
}
2226
2227
size_t
2228
Data::hash() const
2229
34.4k
{
2230
34.4k
   return rawHash((const unsigned char*)(this->data()), this->size());
2231
34.4k
}
2232
2233
size_t
2234
Data::caseInsensitivehash() const
2235
0
{
2236
0
   return rawCaseInsensitiveHash((const unsigned char*)(this->data()), this->size());
2237
0
}
2238
2239
size_t
2240
Data::caseInsensitiveTokenHash() const
2241
148
{
2242
148
   return rawCaseInsensitiveTokenHash((const unsigned char*)(this->data()), this->size());
2243
148
}
2244
2245
0
#define compUnalignedRemainder(d1, d2, size) \
2246
0
switch(size) \
2247
0
{\
2248
0
   case 3:                                         \
2249
0
      if( (*d1 ^ *d2) & 0xDF)                      \
2250
0
      {                                            \
2251
0
         return false;                             \
2252
0
      }                                            \
2253
0
      d1++;                                        \
2254
0
      d2++;                                        \
2255
0
      /* fallthrough */                            \
2256
0
   case 2:                                         \
2257
0
      if((get16bits(d1) ^ get16bits(d2)) & 0xDFDF) \
2258
0
      {                                            \
2259
0
         return false;                             \
2260
0
      }                                            \
2261
0
      d1+=2;                                       \
2262
0
      d2+=2;                                       \
2263
0
      break;                                       \
2264
0
   case 1:                                         \
2265
0
      if( (*d1 ^ *d2) & 0xDF)                      \
2266
0
      {                                            \
2267
0
         return false;                             \
2268
0
      }                                            \
2269
0
      d1++;                                        \
2270
0
      d2++;                                        \
2271
0
      /* fallthrough */                            \
2272
0
   default:                                        \
2273
0
      ;                                            \
2274
0
}\
2275
2276
bool 
2277
Data::sizeEqualCaseInsensitiveTokenCompare(const Data& rhs) const
2278
0
{
2279
0
   resip_assert(mSize==rhs.mSize);
2280
0
   const char* d1(mBuf);
2281
0
   const char* d2(rhs.mBuf);
2282
2283
0
   if(mSize < 4)
2284
0
   {
2285
      // No point in trying 32-bit ops.
2286
0
      compUnalignedRemainder(d1, d2, mSize);
2287
0
      return true;
2288
0
   }
2289
2290
0
   int unalignedPrefix(4-((ptrdiff_t)d1 & 3));
2291
2292
0
   compUnalignedRemainder(d1, d2, unalignedPrefix);
2293
2294
   // We are now on a 32-bit boundary with d1.
2295
0
   uint32_t* wd1((uint32_t*)(d1));
2296
0
   size_t wordLen=(mSize-unalignedPrefix)>>2;
2297
0
   int rem=(mSize-unalignedPrefix)&3;
2298
2299
0
   if((ptrdiff_t)(d2)%4==0)
2300
0
   {
2301
      // d2 is aligned too. Happy day!
2302
0
      uint32_t* wd2((uint32_t*)(d2));
2303
0
      for (;wordLen > 0; wordLen--)
2304
0
      {
2305
         // bitwise xor is zero iff equal, but we only really care about bits 
2306
         // other than bit 6, so we mask out bit 6 after the xor.
2307
0
         if( (*wd1 ^ *wd2) & 0xDFDFDFDF)
2308
0
         {
2309
0
            return false;
2310
0
         }
2311
0
         wd1++;
2312
0
         wd2++;
2313
0
      }
2314
0
      d2=(const char*)wd2;
2315
0
   }
2316
0
   else
2317
0
   {
2318
0
      for (;wordLen > 0; wordLen--)
2319
0
      {
2320
         // bitwise xor is zero iff equal, but we only really care about bits 
2321
         // other than bit 6, so we mask out bit 6 after the xor.
2322
0
         uint32_t test=get32bits(d2);
2323
0
         if( (*wd1 ^ test) & 0xDFDFDFDF)
2324
0
         {
2325
0
            return false;
2326
0
         }
2327
0
         wd1++;
2328
0
         d2+=4;
2329
0
      }
2330
0
   }
2331
0
   d1=(const char*)wd1;
2332
2333
0
   compUnalignedRemainder(d1, d2, rem);
2334
0
   return true;
2335
0
}
2336
2337
std::bitset<256>
2338
Data::toBitset(const resip::Data& chars)
2339
19
{
2340
19
   std::bitset<256> result;
2341
19
   result.reset();
2342
464
   for (unsigned int i=0; i!=chars.mSize;++i)
2343
445
   {
2344
445
      result.set(*(unsigned char*)(chars.mBuf+i));
2345
445
   }
2346
19
   return result;
2347
19
}
2348
2349
std::ostream& 
2350
Data::escapeToStream(std::ostream& str, 
2351
                     const std::bitset<256>& shouldEscape) const
2352
0
{
2353
0
   static char hex[] = "0123456789ABCDEF";
2354
2355
0
   if (empty())
2356
0
   {
2357
0
      return str;
2358
0
   }
2359
   
2360
0
   const unsigned char* anchor = (unsigned char*)mBuf;
2361
0
   const unsigned char* p = (unsigned char*)mBuf;
2362
0
   const unsigned char* e = (unsigned char*)mBuf + mSize;
2363
2364
0
   while (p < e)
2365
0
   {
2366
      // ?abr? Why is this special cased? Removing this code
2367
      // does not change the behavior of this method.
2368
0
      if (*p == '%' 
2369
0
          && e - p > 2 
2370
0
          && isHex(*(p+1)) 
2371
0
          && isHex(*(p+2)))
2372
0
      {
2373
0
         p+=3;
2374
0
      }
2375
0
      else if (shouldEscape[*p])
2376
0
      {
2377
0
         if(p > anchor)
2378
0
         {
2379
0
            str.write((char*)anchor, p-anchor);
2380
0
         }
2381
0
         int hi = (*p & 0xF0)>>4;
2382
0
         int low = (*p & 0x0F);
2383
      
2384
0
         str << '%' << hex[hi] << hex[low];
2385
0
         anchor=++p;
2386
0
      }
2387
0
      else
2388
0
      {
2389
0
         ++p;
2390
0
      }
2391
0
   }
2392
0
   if(p > anchor)
2393
0
   {
2394
0
      str.write((char*)anchor, p-anchor);
2395
0
   }
2396
0
   return str;
2397
0
}
2398
2399
Data
2400
Data::fromFile(const Data& filename)
2401
0
{
2402
0
   ifstream is;
2403
0
   is.open(filename.c_str(), ios::binary );
2404
0
   if ( !is.is_open() )
2405
0
   {
2406
0
      throw DataException("Could not read file ",
2407
0
                                    __FILE__,__LINE__);
2408
0
   }
2409
2410
0
   resip_assert(is.is_open());
2411
2412
0
   int length = 0;
2413
2414
   // get length of file:
2415
0
#if !defined(__MSL_CPP__) || (__MSL_CPP_ >= 0x00012000)
2416
0
   is.seekg (0, ios::end);
2417
0
   length = (int)is.tellg();
2418
0
   is.seekg (0, ios::beg);
2419
#else
2420
   // this is a work around for a bug in CodeWarrior 9's implementation of seekg.
2421
   // http://groups.google.ca/group/comp.sys.mac.programmer.codewarrior/browse_frm/thread/a4279eb75f3bd55a
2422
   FILE * tmpFile = fopen(filename.c_str(), "r+b");
2423
   resip_assert(tmpFile != NULL);
2424
   fseek(tmpFile, 0, SEEK_END);
2425
   length = ftell(tmpFile);
2426
   fseek(tmpFile, 0, SEEK_SET);
2427
#endif // __MWERKS__
2428
2429
   // tellg/tell will return -1 if the stream is bad
2430
0
   if (length == -1)
2431
0
   {
2432
0
      throw DataException("Could not seek into file ",
2433
0
                                    __FILE__,__LINE__);
2434
0
   }
2435
2436
   // !jf! +1 is a workaround for a bug in Data::c_str() that adds the 0 without
2437
   // resizing.
2438
0
   char* buffer = new char [length+1];
2439
2440
   // read data as a block:
2441
0
   is.read (buffer,length);
2442
2443
0
   Data target(Data::Take, buffer, length);
2444
2445
0
   is.close();
2446
2447
0
   return target;
2448
0
}
2449
2450
HashValueImp(resip::Data, data.hash());
2451
2452
static signed char base64Lookup[128] = 
2453
{
2454
   -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 
2455
   -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 
2456
   -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 
2457
   -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 
2458
   -1,-1,-1,62,-1,62,-2,63,52,53, 
2459
   54,55,56,57,58,59,60,61,-1,-1, 
2460
   -1,-2,-1,-1,-1,0, 1, 2, 3, 4,
2461
   5, 6, 7, 8, 9, 10,11,12,13,14, 
2462
   15,16,17,18,19,20,21,22,23,24, 
2463
   25,-1,-1,-1,-1,63,-1,26,27,28, 
2464
   29,30,31,32,33,34,35,36,37,38, 
2465
   39,40,41,42,43,44,45,46,47,48, 
2466
   49,50,51,-1,-1,-1,-1,-1            
2467
};
2468
Data 
2469
Data::base64decode() const
2470
0
{
2471
   // see RFC 3548 
2472
   // this will decode normal and URL safe alphabet 
2473
#if 0
2474
   return Base64Coder::decode( *this );
2475
#else
2476
0
   int wc=0;
2477
0
   int val=0;
2478
0
   Data bin;
2479
0
   bin.reserve( size()*3/4 );
2480
   
2481
0
   for( unsigned int i=0; i<size(); i++ )
2482
0
   {
2483
0
      unsigned int x = mBuf[i] & 0x7F;
2484
0
      char c1,c2,c3;
2485
      
2486
0
      int v =  base64Lookup[x];
2487
2488
0
      if ( v >= 0 )
2489
0
      {
2490
0
         val = val << 6;
2491
0
         val |= v;
2492
0
         wc++;
2493
         
2494
0
         if ( wc == 4 )
2495
0
         {
2496
0
            c3 = char( val & 0xFF ); val = val >> 8;
2497
0
            c2 = char( val & 0xFF ); val = val >> 8;
2498
0
            c1 = char( val & 0xFF ); val = val >> 8;
2499
2500
0
            bin += c1;
2501
0
            bin += c2;
2502
0
            bin += c3;
2503
            
2504
0
            wc=0;
2505
0
            val=0;
2506
0
         }
2507
0
      }
2508
0
      if ( base64Lookup[x] == -2 )
2509
0
      {
2510
0
         if (wc==2) val = val<<12;
2511
0
         if (wc==3) val = val<<6;
2512
         
2513
0
         c3 = char( val & 0xFF ); val = val >> 8;
2514
0
         c2 = char( val & 0xFF ); val = val >> 8;
2515
0
         c1 = char( val & 0xFF ); val = val >> 8;
2516
         
2517
0
         unsigned int xNext = mBuf[i] & 0x7F;
2518
0
         if ( (i+1<size() ) && ( base64Lookup[xNext] == -2 ))
2519
0
         {
2520
0
            bin += c1;
2521
0
            i++;
2522
0
         }
2523
0
         else
2524
0
         {
2525
0
            bin += c1;
2526
0
            bin += c2;
2527
0
         }
2528
2529
0
         break;
2530
0
      }
2531
0
   }
2532
2533
0
   return bin;
2534
0
#endif
2535
0
}
2536
2537
2538
// see RFC 3548 
2539
static unsigned char codeCharUnsafe[] = 
2540
   "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
2541
static unsigned char codeCharSafe[] = 
2542
   "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.";
2543
Data 
2544
Data::base64encode(bool useSafeSet) const
2545
0
{
2546
0
   unsigned char* codeChar = useSafeSet ? codeCharSafe : codeCharUnsafe;
2547
   
2548
0
   int srcLength = (int)this->size();
2549
0
   unsigned int dstLimitLength = 4 * (srcLength / 3 + (srcLength%3==0 ? 0 : 1));
2550
0
   unsigned char * dstData = new unsigned char[dstLimitLength + 1];
2551
0
   unsigned int dstIndex = 0;
2552
   
2553
0
   const char * p = static_cast<const char *>( this->data() );
2554
   
2555
0
   for(int index=0;index<srcLength;index+=3)
2556
0
   {
2557
0
      unsigned char codeBits = (p[index] & 0xfc)>>2;
2558
      
2559
0
      resip_assert(codeBits < 64);
2560
0
      dstData[dstIndex++] = codeChar[codeBits]; // c0 output
2561
0
      resip_assert(dstIndex <= dstLimitLength);
2562
      
2563
      // do second codeBits
2564
0
      codeBits = ((p[index]&0x3)<<4);
2565
0
      if (index+1 < srcLength)
2566
0
      {
2567
0
         codeBits |= ((p[index+1]&0xf0)>>4);
2568
0
      }
2569
0
      resip_assert(codeBits < 64);
2570
0
      dstData[dstIndex++] = codeChar[codeBits]; // c1 output
2571
0
      resip_assert(dstIndex <= dstLimitLength);
2572
      
2573
0
      if (index+1 >= srcLength) 
2574
0
      {
2575
0
         dstData[dstIndex++] = codeChar[64];
2576
0
         resip_assert(dstIndex <= dstLimitLength);
2577
0
         dstData[dstIndex++] = codeChar[64];
2578
0
         resip_assert(dstIndex <= dstLimitLength);
2579
0
         break; // encoded d0 only
2580
0
      }
2581
      
2582
      // do third codeBits
2583
0
      codeBits = ((p[index+1]&0xf)<<2);
2584
0
      if (index+2 < srcLength)
2585
0
      {
2586
0
         codeBits |= ((p[index+2]&0xc0)>>6);
2587
0
      }
2588
0
      resip_assert(codeBits < 64);
2589
0
      dstData[dstIndex++] = codeChar[codeBits]; // c2 output
2590
0
      resip_assert(dstIndex <= dstLimitLength);
2591
      
2592
0
      if (index+2 >= srcLength) 
2593
0
      {
2594
0
         dstData[dstIndex++] = codeChar[64];   
2595
0
         resip_assert(dstIndex <= dstLimitLength);
2596
0
         break; // encoded d0 d1 only
2597
0
      }
2598
      
2599
      // do fourth codeBits
2600
0
      codeBits = ((p[index+2]&0x3f));
2601
0
      resip_assert(codeBits < 64);
2602
0
      dstData[dstIndex++] = codeChar[codeBits]; // c3 output
2603
0
      resip_assert(dstIndex <= dstLimitLength);
2604
      // outputed all d0,d1, and d2
2605
0
   }
2606
2607
0
   dstData[dstIndex] = 0;
2608
0
   return Data(Data::Take, reinterpret_cast<char*>(dstData),
2609
0
               dstIndex);
2610
0
}
2611
2612
2613
/* ====================================================================
2614
 * The Vovida Software License, Version 1.0 
2615
 * 
2616
 * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
2617
 * 
2618
 * Redistribution and use in source and binary forms, with or without
2619
 * modification, are permitted provided that the following conditions
2620
 * are met:
2621
 * 
2622
 * 1. Redistributions of source code must retain the above copyright
2623
 *    notice, this list of conditions and the following disclaimer.
2624
 * 
2625
 * 2. Redistributions in binary form must reproduce the above copyright
2626
 *    notice, this list of conditions and the following disclaimer in
2627
 *    the documentation and/or other materials provided with the
2628
2629
 *    distribution.
2630
 * 
2631
 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
2632
 *    and "Vovida Open Communication Application Library (VOCAL)" must
2633
 *    not be used to endorse or promote products derived from this
2634
 *    software without prior written permission. For written
2635
 *    permission, please contact vocal@vovida.org.
2636
 *
2637
 * 4. Products derived from this software may not be called "VOCAL", nor
2638
 *    may "VOCAL" appear in their name, without prior written
2639
 *    permission of Vovida Networks, Inc.
2640
 * 
2641
 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
2642
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2643
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
2644
 * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
2645
 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
2646
 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
2647
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
2648
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
2649
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
2650
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2651
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
2652
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
2653
 * DAMAGE.
2654
 * 
2655
 * ====================================================================
2656
 * 
2657
 * This software consists of voluntary contributions made by Vovida
2658
 * Networks, Inc. and many individuals on behalf of Vovida Networks,
2659
 * Inc.  For more information on Vovida Networks, Inc., please see
2660
 * <http://www.vovida.org/>.
2661
 *
2662
 * vi: set shiftwidth=3 expandtab:
2663
 */