Coverage Report

Created: 2026-05-24 06:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/resiprocate/rutil/Data.cxx
Line
Count
Source
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 = std::string::npos;
30
31
Data::PreallocateType::PreallocateType(int)
32
2
{}
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
202
{
215
202
   return true;
216
202
}
217
218
Data::Data(size_type capacity,
219
           const Data::PreallocateType&) 
220
429k
   : mBuf(capacity > LocalAlloc 
221
429k
          ? new char[capacity + 1]
222
429k
          : mPreBuffer),
223
429k
     mSize(0),
224
429k
     mCapacity(capacity > LocalAlloc
225
429k
               ? capacity
226
429k
               : LocalAlloc),
227
429k
     mShareEnum(capacity > LocalAlloc ? Take : Borrow)
228
429k
{
229
429k
   resip_assert( capacity >= 0 );
230
429k
   mBuf[mSize] = 0;
231
429k
}
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
3.34M
{
252
3.34M
   initFromString(str, length);
253
3.34M
}
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.10M
{
275
7.10M
   mSize = len;
276
7.10M
   if(len > 0)
277
6.85M
   {
278
6.85M
      resip_assert(str);
279
6.85M
   }
280
7.10M
   size_t bytes = len + 1;
281
7.10M
   if(bytes <= len)
282
0
   {
283
      // integer overflow
284
0
      throw std::bad_alloc();
285
0
   }
286
7.10M
   if(bytes > LocalAlloc)
287
458k
   {
288
458k
      mBuf = new char[bytes];
289
458k
      mCapacity = mSize;
290
458k
      mShareEnum = Take;
291
458k
   }
292
6.65M
   else
293
6.65M
   {
294
6.65M
      mBuf = mPreBuffer;
295
6.65M
      mCapacity = LocalAlloc;
296
6.65M
      mShareEnum = Borrow;
297
6.65M
   }
298
7.10M
   if(str)
299
7.10M
   {
300
7.10M
      memcpy(mBuf, str, len);
301
7.10M
   }
302
7.10M
   mBuf[mSize] = 0;
303
7.10M
}
304
305
Data::Data(ShareEnum se, const char* buffer, size_type length)
306
6.23k
   : mBuf(const_cast<char*>(buffer)),
307
6.23k
     mSize(length),
308
6.23k
     mCapacity(mSize),
309
6.23k
     mShareEnum(se)
310
6.23k
{
311
6.23k
   resip_assert(buffer);
312
6.23k
}
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.3k
   : mBuf(const_cast<char*>(buffer)),
325
32.3k
     mSize((Data::size_type)strlen(buffer)),
326
32.3k
     mCapacity(mSize),
327
32.3k
     mShareEnum(se)
328
32.3k
{
329
32.3k
   resip_assert(buffer);
330
32.3k
}
331
332
Data::Data(ShareEnum se, const Data& staticData)
333
6.81k
   : mBuf(staticData.mBuf),
334
6.81k
     mSize(staticData.mSize),
335
6.81k
     mCapacity(mSize),
336
6.81k
     mShareEnum(Share)
337
6.81k
{
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.81k
   resip_assert(se == Share); // makes no sense to call this with 'Take'.
342
6.81k
}
343
//=============================================================================
344
345
Data::Data(const char* str)
346
431k
{
347
431k
   initFromString(str, str ? (Data::size_type)strlen(str) : 0);
348
431k
}
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
3.33M
{
367
3.33M
   initFromString(data.mBuf, data.mSize);
368
3.33M
}
369
370
#ifdef RESIP_HAS_RVALUE_REFS
371
Data::Data(Data &&data) noexcept
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.16k
   : mBuf(Int32MaxSize > LocalAlloc 
386
7.16k
          ? new char[Int32MaxSize + 1]
387
7.16k
          : mPreBuffer),
388
7.16k
     mSize(0),
389
7.16k
     mCapacity(Int32MaxSize > LocalAlloc
390
7.16k
               ? Int32MaxSize
391
7.16k
               : LocalAlloc),
392
7.16k
     mShareEnum(Int32MaxSize > LocalAlloc ? Take : Borrow)
393
7.16k
{
394
7.16k
   if (val == 0)
395
210
   {
396
210
      mBuf[0] = '0';
397
210
      mBuf[1] = 0;
398
210
      mSize = 1;
399
210
      return;
400
210
   }
401
402
6.95k
   bool neg = false;
403
   
404
6.95k
   int32_t value = val;
405
6.95k
   if (value < 0)
406
1.10k
   {
407
1.10k
      value = -value;
408
1.10k
      neg = true;
409
1.10k
   }
410
411
6.95k
   int c = 0;
412
6.95k
   int32_t v = value;
413
13.5k
   while (v /= 10)
414
6.61k
   {
415
6.61k
      ++c;
416
6.61k
   }
417
418
6.95k
   if (neg)
419
1.10k
   {
420
1.10k
      ++c;
421
1.10k
   }
422
423
6.95k
   mSize = c+1;
424
6.95k
   mBuf[c+1] = 0;
425
   
426
6.95k
   v = value;
427
20.5k
   while (v)
428
13.5k
   {
429
13.5k
      mBuf[c--] = '0' + v%10;
430
13.5k
      v /= 10;
431
13.5k
   }
432
433
6.95k
   if (neg)
434
1.10k
   {
435
1.10k
      mBuf[0] = '-';
436
1.10k
   }
437
6.95k
}
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) noexcept
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
286k
{
703
286k
   if (mShareEnum == Data::Share || mCapacity < length+1)
704
70.4k
   {
705
      // will alloc length+1, so the term NULL below is safe
706
70.4k
      resize(length, false);
707
70.4k
   }
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
286k
   mSize = length;
712
286k
   if (mSize>0)
713
262k
   {
714
262k
      memmove(mBuf, buf, mSize);
715
262k
   }
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
286k
   mBuf[mSize] = 0;
719
286k
   return *this;
720
286k
}
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
106k
{
745
106k
   if (lhs.mSize != rhs.mSize)
746
83.4k
   {
747
83.4k
      return false;
748
83.4k
   }
749
22.8k
   return memcmp(lhs.mBuf, rhs.mBuf, lhs.mSize) == 0;
750
106k
}
751
752
bool 
753
resip::operator==(const Data& lhs, const char* rhs)
754
28.7k
{
755
28.7k
   resip_assert(rhs); // .dlb. not consistent with constructor
756
28.7k
   if (strncmp(lhs.mBuf, rhs, lhs.mSize) != 0)
757
6.22k
   {
758
6.22k
      return false;
759
6.22k
   }
760
22.5k
   return strlen(rhs) == lhs.mSize;
761
28.7k
}
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) noexcept
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
785
{
957
785
   if (len < mSize)
958
402
   {
959
      // NOTE: Do not write terminating NULL, to avoid un-doing Share
960
402
      mSize = len;
961
402
   }
962
785
   return *this;
963
785
}
964
965
Data 
966
Data::operator+(const Data& data) const
967
253k
{
968
253k
   Data tmp(mSize + (int)data.mSize, Data::Preallocate);
969
253k
   tmp.mSize = mSize + data.mSize;
970
253k
   tmp.mCapacity = tmp.mSize;
971
253k
   memcpy(tmp.mBuf, mBuf, mSize);
972
253k
   memcpy(tmp.mBuf + mSize, data.mBuf, data.mSize);
973
253k
   tmp.mBuf[tmp.mSize] = 0;
974
975
253k
   return tmp;
976
253k
}
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.51G
{
1075
1.51G
   resip_assert(str);
1076
1.51G
   if (mCapacity <= mSize + len)  // append null terminates, thus the equality
1077
45.1k
   {
1078
      // .dlb. pad for future growth?
1079
45.1k
      resize(((mSize + len +16)*3)/2, true);
1080
45.1k
   }
1081
1.51G
   else
1082
1.51G
   {
1083
1.51G
      if (mShareEnum == Share)
1084
0
      {
1085
0
         resize(mSize + len, true);
1086
0
      }
1087
1.51G
   }
1088
1089
   // could conceivably overlap
1090
1.51G
   memmove(mBuf + mSize, str, len);
1091
1.51G
   mSize += len;
1092
1.51G
   mBuf[mSize] = 0;
1093
1094
1.51G
   return *this;
1095
1.51G
}
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
218
{
1114
218
   if (mShareEnum == Data::Share || mSize == mCapacity)
1115
160
   {
1116
160
      const_cast<Data*>(this)->resize(mSize+1,true);
1117
160
   }
1118
   // mostly is zero terminated, but not by DataStream
1119
218
   mBuf[mSize] = 0;
1120
218
   return mBuf;
1121
218
}
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
19.4M
{
1140
19.4M
   if (mShareEnum == Share)
1141
7.95k
   {
1142
7.95k
      const_cast<Data*>(this)->resize(mSize, true);
1143
7.95k
   }
1144
19.4M
}
1145
1146
// generate additional capacity
1147
void
1148
Data::resize(size_type newCapacity, 
1149
             bool copy)
1150
543k
{
1151
543k
   resip_assert(newCapacity >= mCapacity || mShareEnum == Data::Share);
1152
1153
543k
   char *oldBuf = mBuf;
1154
543k
   bool needToDelete=(mShareEnum==Take);
1155
1156
543k
   size_t newBytes = newCapacity + 1;
1157
543k
   if(newBytes <= newCapacity)
1158
0
   {
1159
      // integer overflow
1160
0
      throw std::range_error("newCapacity too big");
1161
0
   }
1162
1163
543k
   if(newCapacity > LocalAlloc)
1164
526k
   {
1165
526k
      mBuf = new char[newBytes];
1166
526k
      mShareEnum = Take;
1167
526k
   }
1168
17.7k
   else
1169
17.7k
   {
1170
17.7k
      mBuf = mPreBuffer;
1171
17.7k
      mShareEnum = Borrow;
1172
17.7k
   }
1173
1174
543k
   if (copy)
1175
473k
   {
1176
473k
      memcpy(mBuf, oldBuf, mSize);
1177
473k
      mBuf[mSize] = 0;
1178
473k
   }
1179
1180
543k
   if (needToDelete)
1181
433k
   {
1182
433k
      delete[] oldBuf;
1183
433k
   }
1184
1185
543k
   mCapacity = newCapacity;
1186
543k
}
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(static_cast< unsigned char >(*p++)));
1317
0
            const char* low = strchr(hexmap, tolower(static_cast< unsigned char >(*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
2
{
1400
   // query part of HTTP URL can be a pchar, slash, or question
1401
   // pchar is unreserved, subdelims, colon, at-sign
1402
1403
514
   for (int i = 0; i < 256; ++i)
1404
512
   {
1405
512
      unsigned char c(i);
1406
512
      urlNonEncodedChars[c] = (isalpha(c) ||  // unreserved
1407
408
                               isdigit(c) ||  // unreserved
1408
388
                               c == '-' ||  // these first 4 are unreserved
1409
386
                               c == '_' ||
1410
384
                               c == '.' ||
1411
382
                               c == '~' ||
1412
380
                               c == '!' ||  // these are subdelims (allowed in pchars)
1413
378
                               c == '$' ||
1414
//                               c == '&' ||  // while these are allowed subdelims, this is an error
1415
//                               c == '+' ||  // I believe this is an error as well.
1416
376
                               c == '\'' ||
1417
374
                               c == '(' ||
1418
372
                               c == ')' ||
1419
370
                               c == '*' ||
1420
368
                               c == ',' ||
1421
366
                               c == ';' ||
1422
364
                               c == '=' ||
1423
362
                               c == ':' ||   // next two explicitly allowed in pchar
1424
360
                               c == '@' ||   
1425
358
                               c == '/' ||   // next two explicitly allowed in query in addition to pchar
1426
356
                               c == '?');    
1427
512
   }
1428
1429
2
   return false;
1430
2
}
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.23k
{
1594
6.23k
   Data ret( 2*mSize, Data::Preallocate);
1595
1596
6.23k
   const char* p = mBuf;
1597
6.23k
   char* r = ret.mBuf;
1598
56.1k
   for (size_type i=0; i < mSize; ++i)
1599
49.9k
   {
1600
49.9k
      unsigned char temp = *p++;
1601
1602
49.9k
      int hi = (temp & 0xf0)>>4;
1603
49.9k
      int low = (temp & 0xf);
1604
1605
49.9k
      *r++ = hexmap[hi];
1606
49.9k
      *r++ = hexmap[low];
1607
49.9k
   }
1608
6.23k
   *r = 0;
1609
6.23k
   ret.mSize = 2*mSize;
1610
6.23k
   return ret;
1611
6.23k
}
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(static_cast< unsigned char >(*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(static_cast< unsigned char >(*p));
1670
0
      ++p;
1671
0
   }
1672
0
   return *this;
1673
0
}
1674
1675
Data& 
1676
Data::schemeLowercase()
1677
7.62k
{
1678
7.62k
   own();
1679
7.62k
   char* p = mBuf;
1680
18.3M
   for (size_type i=0; i < mSize; ++i)
1681
18.3M
   {
1682
18.3M
      *p |= ' ';
1683
18.3M
      ++p;
1684
18.3M
   }
1685
7.62k
   return *this;
1686
7.62k
}
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(static_cast< unsigned char >(*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(static_cast< unsigned char >(*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(static_cast< unsigned char >(*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(static_cast< unsigned char >(*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(static_cast< unsigned char >(*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(static_cast< unsigned char >(*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(static_cast< unsigned char >(*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(static_cast< unsigned char >(*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(static_cast< unsigned char >(*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(static_cast< unsigned char >(*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(static_cast< unsigned char >(*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
bool
1914
Data::prefixNoCase(const Data& pre) const noexcept
1915
0
{
1916
0
   if (pre.size() > size())
1917
0
   {
1918
0
      return false;
1919
0
   }
1920
1921
0
   return strncasecmp(data(), pre.data(), pre.size()) == 0;
1922
0
}
1923
1924
bool
1925
Data::postfix(const Data& post) const noexcept
1926
0
{
1927
0
   if (post.size() > size())
1928
0
   {
1929
0
      return false;
1930
0
   }
1931
1932
0
   return memcmp(data() + (size()-post.size()), post.data(), post.size()) == 0;
1933
0
}
1934
1935
bool
1936
Data::postfixNoCase(const Data& post) const noexcept
1937
0
{
1938
0
   if (post.size() > size())
1939
0
   {
1940
0
      return false;
1941
0
   }
1942
1943
0
   return strncasecmp(data() + (size() - post.size()), post.data(), post.size()) == 0;
1944
0
}
1945
1946
Data 
1947
Data::substr(size_type first, size_type count) const
1948
0
{
1949
0
   resip_assert(first <= mSize);
1950
0
   if ( count == Data::npos)
1951
0
   {
1952
0
      return Data(mBuf+first, mSize-first);
1953
0
   }
1954
0
   else
1955
0
   {
1956
0
      resip_assert(first + count <= mSize);
1957
0
      return Data(mBuf+first, count);
1958
0
   }
1959
0
}
1960
1961
Data::size_type
1962
Data::find(const Data& match, 
1963
           size_type start) const
1964
132
{
1965
132
   if (start < mSize)
1966
130
   {
1967
130
      ParseBuffer pb(mBuf + start, mSize - start);
1968
130
      pb.skipToChars(match);
1969
130
      if (!pb.eof())
1970
116
      {
1971
116
         return (Data::size_type)(pb.position() - pb.start() + start);
1972
116
      }
1973
130
   }
1974
1975
16
   return Data::npos;
1976
132
}
1977
1978
int
1979
Data::replace(const Data& match, 
1980
              const Data& replaceWith,
1981
              int max)
1982
0
{
1983
0
   resip_assert(!match.empty());
1984
1985
0
   int count = 0;
1986
1987
0
   const int incr = int(replaceWith.size() - match.size());
1988
0
   for (size_type offset = find(match, 0); 
1989
0
        count < max && offset != Data::npos; 
1990
0
        offset = find(match, offset+replaceWith.size()))
1991
0
   {
1992
0
      if (mSize + incr >= mCapacity)
1993
0
      {
1994
0
         resize((mCapacity + incr) * 3 / 2, true);
1995
0
      }
1996
0
      else
1997
0
      {
1998
0
         own();
1999
0
      }
2000
2001
      // move the memory forward (or backward)
2002
0
      memmove(mBuf + offset + replaceWith.size(), mBuf + offset + match.size(), mSize - offset - match.size());
2003
0
      memcpy(mBuf + offset, replaceWith.data(), replaceWith.size());
2004
0
      mSize += incr;
2005
2006
0
      ++count;
2007
0
   }
2008
2009
0
   return count;
2010
0
}
2011
2012
#ifndef  RESIP_USE_STL_STREAMS
2013
EncodeStream& 
2014
resip::operator<<(EncodeStream& strm, const Data& d)
2015
{
2016
   return strm.write(d.mBuf, d.mSize);
2017
}
2018
#endif
2019
2020
// random permutation of 0..255
2021
static const unsigned char randomPermutation[256] = 
2022
{
2023
   44, 9, 46, 184, 21, 30, 92, 231, 79, 7, 166, 237, 173, 72, 91, 123, 
2024
   212, 183, 16, 99, 85, 45, 190, 130, 118, 107, 169, 119, 100, 179, 251, 177,
2025
   23, 125, 12, 101, 121, 246, 61, 38, 156, 114, 159, 57, 181, 145, 198, 182,
2026
   58, 215, 174, 225, 82, 178, 150, 161, 63, 103, 32, 203, 68, 151, 139, 55, 
2027
   143, 2, 36, 110, 209, 154, 204, 89, 62, 17, 187, 226, 31, 105, 195, 208,
2028
   49, 56, 238, 172, 37, 3, 234, 206, 134, 233, 19, 148, 64, 4, 10, 224,
2029
   144, 88, 93, 191, 20, 131, 138, 199, 243, 244, 39, 50, 214, 87, 6, 84,
2030
   185, 112, 171, 75, 192, 193, 239, 69, 106, 43, 194, 1, 78, 67, 116, 200,
2031
   83, 70, 213, 25, 59, 137, 52, 13, 153, 42, 232, 0, 133, 210, 76, 33,
2032
   255, 236, 124, 104, 65, 201, 53, 155, 140, 254, 54, 196, 120, 146, 216, 29,
2033
   28, 86, 245, 90, 98, 26, 81, 115, 180, 66, 102, 136, 167, 51, 109, 132,
2034
   77, 175, 14, 202, 222, 48, 223, 188, 40, 242, 157, 5, 128, 229, 71, 127,
2035
   164, 207, 247, 8, 80, 149, 94, 160, 47, 117, 135, 176, 129, 142, 189, 97,
2036
   11, 250, 221, 218, 96, 220, 35, 197, 152, 126, 219, 74, 170, 252, 163, 41,
2037
   95, 27, 34, 22, 205, 230, 241, 186, 168, 228, 253, 249, 113, 108, 111, 211,
2038
   235, 217, 165, 122, 15, 141, 158, 147, 240, 24, 162, 18, 60, 73, 227, 248
2039
};
2040
2041
size_t
2042
Data::rawHash(const unsigned char* c, size_t size)
2043
31.6k
{
2044
   // 4 byte Pearson's hash
2045
   // essentially random hashing
2046
2047
31.6k
   union 
2048
31.6k
   {
2049
31.6k
         size_t st;
2050
31.6k
         unsigned char bytes[4];
2051
31.6k
   };
2052
31.6k
   st = 0; // suppresses warnings about unused st
2053
31.6k
   bytes[0] = randomPermutation[0];
2054
31.6k
   bytes[1] = randomPermutation[1];
2055
31.6k
   bytes[2] = randomPermutation[2];
2056
31.6k
   bytes[3] = randomPermutation[3];
2057
2058
31.6k
   const unsigned char* end = c + size;
2059
2.04M
   for ( ; c != end; ++c)
2060
2.00M
   {
2061
2.00M
      bytes[0] = randomPermutation[*c ^ bytes[0]];
2062
2.00M
      bytes[1] = randomPermutation[*c ^ bytes[1]];
2063
2.00M
      bytes[2] = randomPermutation[*c ^ bytes[2]];
2064
2.00M
      bytes[3] = randomPermutation[*c ^ bytes[3]];
2065
2.00M
   }
2066
2067
   // convert from network to host byte order
2068
31.6k
   return ntohl((u_long)st);
2069
31.6k
}
2070
2071
// use only for ascii characters!
2072
size_t 
2073
Data::rawCaseInsensitiveHash(const unsigned char* c, size_t size)
2074
0
{
2075
2076
0
   union 
2077
0
   {
2078
0
         size_t st;
2079
0
         unsigned char bytes[4];
2080
0
   };
2081
0
   st = 0; // suppresses warnings about unused st
2082
0
   bytes[0] = randomPermutation[0];
2083
0
   bytes[1] = randomPermutation[1];
2084
0
   bytes[2] = randomPermutation[2];
2085
0
   bytes[3] = randomPermutation[3];
2086
2087
0
   const unsigned char* end = c + size;
2088
0
   for ( ; c != end; ++c)
2089
0
   {
2090
0
      unsigned char cc = tolower(*c);
2091
0
      bytes[0] = randomPermutation[cc ^ bytes[0]];
2092
0
      bytes[1] = randomPermutation[cc ^ bytes[1]];
2093
0
      bytes[2] = randomPermutation[cc ^ bytes[2]];
2094
0
      bytes[3] = randomPermutation[cc ^ bytes[3]];
2095
0
   }
2096
2097
   // convert from network to host byte order
2098
0
   return ntohl((u_long)st);
2099
0
}
2100
2101
#if defined(RESIP_BIG_ENDIAN) || (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
2102
2103
#if !defined (get16bits)
2104
#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[0])) << 8)\
2105
                       +(uint32_t)(((const uint8_t *)(d))[1]) )
2106
#endif
2107
2108
#if !defined (get32bits)
2109
#define get32bits(d) ((get16bits(d) << 16) + get16bits(d+2))
2110
#endif
2111
2112
#else  // little endian:
2113
2114
#undef get16bits
2115
#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \
2116
  || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__)
2117
#define get16bits(d) (*((const uint16_t *) (d)))
2118
#endif
2119
2120
#if !defined (get16bits)
2121
638
#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8)\
2122
638
                       +(uint32_t)(((const uint8_t *)(d))[0]) )
2123
#endif
2124
2125
#undef get32bits
2126
#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \
2127
  || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__)
2128
#define get32bits(d) (*((const uint32_t *) (d)))
2129
#endif
2130
2131
#if !defined (get32bits)
2132
272
#define get32bits(d) ((get16bits(d+2) << 16) + get16bits(d))
2133
#endif
2134
#endif
2135
2136
// This is intended to be a faster case-insensitive hash function that works
2137
// well when the buffer is a RFC 3261 token.
2138
// Having non-token characters will not prevent the hash from working, but it 
2139
// will increase the number of cases where a single char difference will result 
2140
// in a hash collision. The pairs of _printable_ characters that this hash will 
2141
// not distinguish between are @`, [{, \|, ]} and ^~
2142
// (Note that, for RFC 3261 tokens, this will not be a problem since @, [, {, \, 
2143
// |, ], } and ^ are not allowed in a token.)
2144
size_t
2145
Data::rawCaseInsensitiveTokenHash(const unsigned char* data, size_t len)
2146
140
{
2147
   // .bwc. Hsieh hash, with some bitmasking to get the case-insensitive 
2148
   // property (this is what all the "0x2020 |" business is about.)
2149
140
   uint32_t hash = (uint32_t)len, tmp;
2150
140
   int rem;
2151
2152
140
    if (len <= 0 || data == NULL) return 0;
2153
2154
140
    rem = len & 3;
2155
140
    len >>= 2;
2156
2157
140
    union 
2158
140
    {
2159
140
          uint32_t masked;
2160
140
          uint16_t ui16[2];
2161
140
    };
2162
2163
    /* Main loop */
2164
412
    for (;len > 0; len--) 
2165
272
    {
2166
        // mask out bit 6 for case-insensitivity
2167
272
        masked = (0x20202020 | get32bits(data));
2168
272
        hash  += ui16[0];
2169
272
        tmp    = ((uint32_t)ui16[1] << 11) ^ hash;
2170
272
        hash   = (hash << 16) ^ tmp;
2171
272
        data  += 2*sizeof (uint16_t);
2172
272
        hash  += hash >> 11;
2173
272
    }
2174
2175
    /* Handle end cases */
2176
140
    switch (rem) 
2177
140
    {
2178
78
        case 3: hash += (0x2020 | get16bits (data));
2179
78
                hash ^= hash << 16;
2180
78
                hash ^= (0x20 | data[sizeof (uint16_t)]) << 18;
2181
78
                hash += hash >> 11;
2182
78
                break;
2183
16
        case 2: hash += (0x2020 | get16bits (data));
2184
16
                hash ^= hash << 11;
2185
16
                hash += hash >> 17;
2186
16
                break;
2187
28
        case 1: hash += (0x20 | *data);
2188
28
                hash ^= hash << 10;
2189
28
                hash += hash >> 1;
2190
140
    }
2191
2192
    /* Force "avalanching" of final 127 bits */
2193
140
    hash ^= hash << 3;
2194
140
    hash += hash >> 5;
2195
140
    hash ^= hash << 4;
2196
140
    hash += hash >> 17;
2197
140
    hash ^= hash << 25;
2198
140
    hash += hash >> 6;
2199
2200
140
    return hash;
2201
2202
//   union 
2203
//   {
2204
//         size_t st;
2205
//         unsigned char bytes[4];
2206
//   };
2207
//   st = 0; // suppresses warnings about unused st
2208
//   bytes[0] = randomPermutation[0];
2209
//   bytes[1] = randomPermutation[1];
2210
//   bytes[2] = randomPermutation[2];
2211
//   bytes[3] = randomPermutation[3];
2212
//
2213
//   const unsigned char* end = c + size;
2214
//   for ( ; c != end; ++c)
2215
//   {
2216
//       union
2217
//       {
2218
//         uint32_t temp;
2219
//         uint8_t cccc[4];
2220
//       };
2221
//       // .bwc. Mask out bit 6, use a multiplication op to write the 
2222
//       // resulting byte to each of the 4 bytes in temp, and xor the whole 
2223
//       // thing with bytes/st.
2224
//      temp = ( (*c | ' ') * 16843009UL) ^ st;
2225
//      bytes[0] = randomPermutation[cccc[0]];
2226
//      bytes[1] = randomPermutation[cccc[1]];
2227
//      bytes[2] = randomPermutation[cccc[2]];
2228
//      bytes[3] = randomPermutation[cccc[3]];
2229
//   }
2230
//
2231
//   // convert from network to host byte order
2232
//   return ntohl((u_long)st);
2233
140
}
2234
2235
Data
2236
bits(size_t v)
2237
0
{
2238
0
   Data ret;
2239
0
   for (unsigned int i = 0; i < 8*sizeof(size_t); ++i)
2240
0
   {
2241
0
      ret += ('0' + v%2);
2242
0
      v /= 2;
2243
0
   }
2244
2245
0
   return ret;
2246
0
}
2247
2248
size_t
2249
Data::hash() const
2250
31.6k
{
2251
31.6k
   return rawHash((const unsigned char*)(this->data()), this->size());
2252
31.6k
}
2253
2254
size_t
2255
Data::caseInsensitivehash() const
2256
0
{
2257
0
   return rawCaseInsensitiveHash((const unsigned char*)(this->data()), this->size());
2258
0
}
2259
2260
size_t
2261
Data::caseInsensitiveTokenHash() const
2262
140
{
2263
140
   return rawCaseInsensitiveTokenHash((const unsigned char*)(this->data()), this->size());
2264
140
}
2265
2266
0
#define compUnalignedRemainder(d1, d2, size) \
2267
0
switch(size) \
2268
0
{\
2269
0
   case 3:                                         \
2270
0
      if( (*d1 ^ *d2) & 0xDF)                      \
2271
0
      {                                            \
2272
0
         return false;                             \
2273
0
      }                                            \
2274
0
      d1++;                                        \
2275
0
      d2++;                                        \
2276
0
      /* fallthrough */                            \
2277
0
   case 2:                                         \
2278
0
      if((get16bits(d1) ^ get16bits(d2)) & 0xDFDF) \
2279
0
      {                                            \
2280
0
         return false;                             \
2281
0
      }                                            \
2282
0
      d1+=2;                                       \
2283
0
      d2+=2;                                       \
2284
0
      break;                                       \
2285
0
   case 1:                                         \
2286
0
      if( (*d1 ^ *d2) & 0xDF)                      \
2287
0
      {                                            \
2288
0
         return false;                             \
2289
0
      }                                            \
2290
0
      d1++;                                        \
2291
0
      d2++;                                        \
2292
0
      /* fallthrough */                            \
2293
0
   default:                                        \
2294
0
      ;                                            \
2295
0
}\
2296
2297
bool 
2298
Data::sizeEqualCaseInsensitiveTokenCompare(const Data& rhs) const
2299
0
{
2300
0
   resip_assert(mSize==rhs.mSize);
2301
0
   const char* d1(mBuf);
2302
0
   const char* d2(rhs.mBuf);
2303
2304
0
   if(mSize < 4)
2305
0
   {
2306
      // No point in trying 32-bit ops.
2307
0
      compUnalignedRemainder(d1, d2, mSize);
2308
0
      return true;
2309
0
   }
2310
2311
0
   int unalignedPrefix(4-((ptrdiff_t)d1 & 3));
2312
2313
0
   compUnalignedRemainder(d1, d2, unalignedPrefix);
2314
2315
   // We are now on a 32-bit boundary with d1.
2316
0
   uint32_t* wd1((uint32_t*)(d1));
2317
0
   size_t wordLen=(mSize-unalignedPrefix)>>2;
2318
0
   int rem=(mSize-unalignedPrefix)&3;
2319
2320
0
   if((ptrdiff_t)(d2)%4==0)
2321
0
   {
2322
      // d2 is aligned too. Happy day!
2323
0
      uint32_t* wd2((uint32_t*)(d2));
2324
0
      for (;wordLen > 0; wordLen--)
2325
0
      {
2326
         // bitwise xor is zero iff equal, but we only really care about bits 
2327
         // other than bit 6, so we mask out bit 6 after the xor.
2328
0
         if( (*wd1 ^ *wd2) & 0xDFDFDFDF)
2329
0
         {
2330
0
            return false;
2331
0
         }
2332
0
         wd1++;
2333
0
         wd2++;
2334
0
      }
2335
0
      d2=(const char*)wd2;
2336
0
   }
2337
0
   else
2338
0
   {
2339
0
      for (;wordLen > 0; wordLen--)
2340
0
      {
2341
         // bitwise xor is zero iff equal, but we only really care about bits 
2342
         // other than bit 6, so we mask out bit 6 after the xor.
2343
0
         uint32_t test=get32bits(d2);
2344
0
         if( (*wd1 ^ test) & 0xDFDFDFDF)
2345
0
         {
2346
0
            return false;
2347
0
         }
2348
0
         wd1++;
2349
0
         d2+=4;
2350
0
      }
2351
0
   }
2352
0
   d1=(const char*)wd1;
2353
2354
0
   compUnalignedRemainder(d1, d2, rem);
2355
0
   return true;
2356
0
}
2357
2358
std::bitset<256>
2359
Data::toBitset(const resip::Data& chars)
2360
19
{
2361
19
   std::bitset<256> result;
2362
19
   result.reset();
2363
464
   for (unsigned int i=0; i!=chars.mSize;++i)
2364
445
   {
2365
445
      result.set(*(unsigned char*)(chars.mBuf+i));
2366
445
   }
2367
19
   return result;
2368
19
}
2369
2370
std::ostream& 
2371
Data::escapeToStream(std::ostream& str, 
2372
                     const std::bitset<256>& shouldEscape) const
2373
0
{
2374
0
   static char hex[] = "0123456789ABCDEF";
2375
2376
0
   if (empty())
2377
0
   {
2378
0
      return str;
2379
0
   }
2380
   
2381
0
   const unsigned char* anchor = (unsigned char*)mBuf;
2382
0
   const unsigned char* p = (unsigned char*)mBuf;
2383
0
   const unsigned char* e = (unsigned char*)mBuf + mSize;
2384
2385
0
   while (p < e)
2386
0
   {
2387
      // ?abr? Why is this special cased? Removing this code
2388
      // does not change the behavior of this method.
2389
0
      if (*p == '%' 
2390
0
          && e - p > 2 
2391
0
          && isHex(*(p+1)) 
2392
0
          && isHex(*(p+2)))
2393
0
      {
2394
0
         p+=3;
2395
0
      }
2396
0
      else if (shouldEscape[*p])
2397
0
      {
2398
0
         if(p > anchor)
2399
0
         {
2400
0
            str.write((char*)anchor, p-anchor);
2401
0
         }
2402
0
         int hi = (*p & 0xF0)>>4;
2403
0
         int low = (*p & 0x0F);
2404
      
2405
0
         str << '%' << hex[hi] << hex[low];
2406
0
         anchor=++p;
2407
0
      }
2408
0
      else
2409
0
      {
2410
0
         ++p;
2411
0
      }
2412
0
   }
2413
0
   if(p > anchor)
2414
0
   {
2415
0
      str.write((char*)anchor, p-anchor);
2416
0
   }
2417
0
   return str;
2418
0
}
2419
2420
Data
2421
Data::fromFile(const Data& filename)
2422
0
{
2423
0
   ifstream is;
2424
0
   is.open(filename.c_str(), ios::binary );
2425
0
   if ( !is.is_open() )
2426
0
   {
2427
0
      throw DataException("Could not read file " + filename, __FILE__,__LINE__);
2428
0
   }
2429
2430
0
   resip_assert(is.is_open());
2431
2432
0
   int length = 0;
2433
2434
   // get length of file:
2435
0
#if !defined(__MSL_CPP__) || (__MSL_CPP_ >= 0x00012000)
2436
0
   is.seekg (0, ios::end);
2437
0
   length = (int)is.tellg();
2438
0
   is.seekg (0, ios::beg);
2439
#else
2440
   // this is a work around for a bug in CodeWarrior 9's implementation of seekg.
2441
   // http://groups.google.ca/group/comp.sys.mac.programmer.codewarrior/browse_frm/thread/a4279eb75f3bd55a
2442
   FILE * tmpFile = fopen(filename.c_str(), "r+b");
2443
   resip_assert(tmpFile != NULL);
2444
   fseek(tmpFile, 0, SEEK_END);
2445
   length = ftell(tmpFile);
2446
   fseek(tmpFile, 0, SEEK_SET);
2447
#endif // __MWERKS__
2448
2449
   // tellg/tell will return -1 if the stream is bad
2450
0
   if (length == -1)
2451
0
   {
2452
0
      throw DataException("Could not seek into file ",
2453
0
                                    __FILE__,__LINE__);
2454
0
   }
2455
2456
   // !jf! +1 is a workaround for a bug in Data::c_str() that adds the 0 without
2457
   // resizing.
2458
0
   char* buffer = new char [length+1];
2459
2460
   // read data as a block:
2461
0
   is.read (buffer,length);
2462
2463
0
   Data target(Data::Take, buffer, length);
2464
2465
0
   is.close();
2466
2467
0
   return target;
2468
0
}
2469
2470
HashValueImp(resip::Data, data.hash());
2471
2472
static signed char base64Lookup[128] = 
2473
{
2474
   -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 
2475
   -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 
2476
   -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 
2477
   -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 
2478
   -1,-1,-1,62,-1,62,-2,63,52,53, 
2479
   54,55,56,57,58,59,60,61,-1,-1, 
2480
   -1,-2,-1,-1,-1,0, 1, 2, 3, 4,
2481
   5, 6, 7, 8, 9, 10,11,12,13,14, 
2482
   15,16,17,18,19,20,21,22,23,24, 
2483
   25,-1,-1,-1,-1,63,-1,26,27,28, 
2484
   29,30,31,32,33,34,35,36,37,38, 
2485
   39,40,41,42,43,44,45,46,47,48, 
2486
   49,50,51,-1,-1,-1,-1,-1            
2487
};
2488
Data 
2489
Data::base64decode() const
2490
0
{
2491
   // see RFC 3548 
2492
   // this will decode normal and URL safe alphabet 
2493
#if 0
2494
   return Base64Coder::decode( *this );
2495
#else
2496
0
   int wc=0;
2497
0
   int val=0;
2498
0
   Data bin;
2499
0
   bin.reserve( size()*3/4 );
2500
   
2501
0
   for( unsigned int i=0; i<size(); i++ )
2502
0
   {
2503
0
      unsigned int x = mBuf[i] & 0x7F;
2504
0
      char c1,c2,c3;
2505
      
2506
0
      int v =  base64Lookup[x];
2507
2508
0
      if ( v >= 0 )
2509
0
      {
2510
0
         val = val << 6;
2511
0
         val |= v;
2512
0
         wc++;
2513
         
2514
0
         if ( wc == 4 )
2515
0
         {
2516
0
            c3 = char( val & 0xFF ); val = val >> 8;
2517
0
            c2 = char( val & 0xFF ); val = val >> 8;
2518
0
            c1 = char( val & 0xFF ); val = val >> 8;
2519
2520
0
            bin += c1;
2521
0
            bin += c2;
2522
0
            bin += c3;
2523
            
2524
0
            wc=0;
2525
0
            val=0;
2526
0
         }
2527
0
      }
2528
0
      if ( base64Lookup[x] == -2 )
2529
0
      {
2530
0
         if (wc==2) val = val<<12;
2531
0
         if (wc==3) val = val<<6;
2532
         
2533
0
         c3 = char( val & 0xFF ); val = val >> 8;
2534
0
         c2 = char( val & 0xFF ); val = val >> 8;
2535
0
         c1 = char( val & 0xFF ); val = val >> 8;
2536
         
2537
0
         unsigned int xNext = mBuf[i] & 0x7F;
2538
0
         if ( (i+1<size() ) && ( base64Lookup[xNext] == -2 ))
2539
0
         {
2540
0
            bin += c1;
2541
0
            i++;
2542
0
         }
2543
0
         else
2544
0
         {
2545
0
            bin += c1;
2546
0
            bin += c2;
2547
0
         }
2548
2549
0
         break;
2550
0
      }
2551
0
   }
2552
2553
0
   return bin;
2554
0
#endif
2555
0
}
2556
2557
2558
// see RFC 3548 
2559
static unsigned char codeCharUnsafe[] = 
2560
   "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
2561
static unsigned char codeCharSafe[] = 
2562
   "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.";
2563
Data 
2564
Data::base64encode(bool useSafeSet) const
2565
0
{
2566
0
   unsigned char* codeChar = useSafeSet ? codeCharSafe : codeCharUnsafe;
2567
   
2568
0
   int srcLength = (int)this->size();
2569
0
   unsigned int dstLimitLength = 4 * (srcLength / 3 + (srcLength%3==0 ? 0 : 1));
2570
0
   unsigned char * dstData = new unsigned char[dstLimitLength + 1];
2571
0
   unsigned int dstIndex = 0;
2572
   
2573
0
   const char * p = static_cast<const char *>( this->data() );
2574
   
2575
0
   for(int index=0;index<srcLength;index+=3)
2576
0
   {
2577
0
      unsigned char codeBits = (p[index] & 0xfc)>>2;
2578
      
2579
0
      resip_assert(codeBits < 64);
2580
0
      dstData[dstIndex++] = codeChar[codeBits]; // c0 output
2581
0
      resip_assert(dstIndex <= dstLimitLength);
2582
      
2583
      // do second codeBits
2584
0
      codeBits = ((p[index]&0x3)<<4);
2585
0
      if (index+1 < srcLength)
2586
0
      {
2587
0
         codeBits |= ((p[index+1]&0xf0)>>4);
2588
0
      }
2589
0
      resip_assert(codeBits < 64);
2590
0
      dstData[dstIndex++] = codeChar[codeBits]; // c1 output
2591
0
      resip_assert(dstIndex <= dstLimitLength);
2592
      
2593
0
      if (index+1 >= srcLength) 
2594
0
      {
2595
0
         dstData[dstIndex++] = codeChar[64];
2596
0
         resip_assert(dstIndex <= dstLimitLength);
2597
0
         dstData[dstIndex++] = codeChar[64];
2598
0
         resip_assert(dstIndex <= dstLimitLength);
2599
0
         break; // encoded d0 only
2600
0
      }
2601
      
2602
      // do third codeBits
2603
0
      codeBits = ((p[index+1]&0xf)<<2);
2604
0
      if (index+2 < srcLength)
2605
0
      {
2606
0
         codeBits |= ((p[index+2]&0xc0)>>6);
2607
0
      }
2608
0
      resip_assert(codeBits < 64);
2609
0
      dstData[dstIndex++] = codeChar[codeBits]; // c2 output
2610
0
      resip_assert(dstIndex <= dstLimitLength);
2611
      
2612
0
      if (index+2 >= srcLength) 
2613
0
      {
2614
0
         dstData[dstIndex++] = codeChar[64];   
2615
0
         resip_assert(dstIndex <= dstLimitLength);
2616
0
         break; // encoded d0 d1 only
2617
0
      }
2618
      
2619
      // do fourth codeBits
2620
0
      codeBits = ((p[index+2]&0x3f));
2621
0
      resip_assert(codeBits < 64);
2622
0
      dstData[dstIndex++] = codeChar[codeBits]; // c3 output
2623
0
      resip_assert(dstIndex <= dstLimitLength);
2624
      // outputed all d0,d1, and d2
2625
0
   }
2626
2627
0
   dstData[dstIndex] = 0;
2628
0
   return Data(Data::Take, reinterpret_cast<char*>(dstData),
2629
0
               dstIndex);
2630
0
}
2631
2632
2633
/* ====================================================================
2634
 * The Vovida Software License, Version 1.0 
2635
 * 
2636
 * Copyright (c) 2026 SIP Spectrum, Inc. https://www.sipspectrum.com
2637
 * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
2638
 * 
2639
 * Redistribution and use in source and binary forms, with or without
2640
 * modification, are permitted provided that the following conditions
2641
 * are met:
2642
 * 
2643
 * 1. Redistributions of source code must retain the above copyright
2644
 *    notice, this list of conditions and the following disclaimer.
2645
 * 
2646
 * 2. Redistributions in binary form must reproduce the above copyright
2647
 *    notice, this list of conditions and the following disclaimer in
2648
 *    the documentation and/or other materials provided with the
2649
2650
 *    distribution.
2651
 * 
2652
 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
2653
 *    and "Vovida Open Communication Application Library (VOCAL)" must
2654
 *    not be used to endorse or promote products derived from this
2655
 *    software without prior written permission. For written
2656
 *    permission, please contact vocal@vovida.org.
2657
 *
2658
 * 4. Products derived from this software may not be called "VOCAL", nor
2659
 *    may "VOCAL" appear in their name, without prior written
2660
 *    permission of Vovida Networks, Inc.
2661
 * 
2662
 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
2663
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2664
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
2665
 * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
2666
 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
2667
 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
2668
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
2669
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
2670
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
2671
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2672
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
2673
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
2674
 * DAMAGE.
2675
 * 
2676
 * ====================================================================
2677
 * 
2678
 * This software consists of voluntary contributions made by Vovida
2679
 * Networks, Inc. and many individuals on behalf of Vovida Networks,
2680
 * Inc.  For more information on Vovida Networks, Inc., please see
2681
 * <http://www.vovida.org/>.
2682
 *
2683
 * vi: set shiftwidth=3 expandtab:
2684
 */