Coverage Report

Created: 2024-07-23 06:39

/src/resiprocate/rutil/Data.hxx
Line
Count
Source (jump to first uncovered line)
1
#ifndef RESIP_Data_hxx
2
#define RESIP_Data_hxx
3
4
#ifdef HAVE_CONFIG_H
5
#include "config.h"
6
#endif
7
8
#include <iostream>
9
#include <string>
10
#include <bitset>
11
#include "rutil/ResipAssert.h"
12
13
#include "rutil/compat.hxx"
14
#include "rutil/DataStream.hxx"
15
#include "rutil/HeapInstanceCounter.hxx"
16
#include "rutil/HashMap.hxx"
17
18
#ifndef RESIP_DATA_LOCAL_SIZE
19
#define RESIP_DATA_LOCAL_SIZE 16
20
#endif
21
22
class TestData;
23
namespace resip
24
{
25
26
/**
27
   @internal
28
   This template is here to help diagnose API/ABI mismatches. Say you build
29
   librutil. A single Data::init(DataLocalSize<RESIP_DATA_LOCAL_SIZE>)
30
   function is implemented in Data.cxx, with the default
31
   value. (Data::init(DataLocalSize<16>) ends up being defined,
32
   Data::init(DataLocalSize<15>) does not) If, later, another build using
33
   that librutil tries to tweak the local alloc size to 24, it will end
34
   up attempting to call Data::init(DataLocalSize<24>); this will result
35
   in a link-time error, that while opaque, is less opaque than the stack
36
   corruption that would result otherwise.
37
**/
38
template <int S>
39
struct DataLocalSize
40
{
41
196
      explicit DataLocalSize(size_t) noexcept {}
42
};
43
44
// .bwc. Pack class Data; has to come before doxygen block though.
45
#pragma pack(push, 4)
46
47
/**
48
  @brief An alternative to std::string, encapsulates an arbitrary buffer of 
49
  bytes.
50
51
  It has a variety of memory management styles that can be
52
  established at contruction time and changed later via setBuf().
53
54
  Three modes of allocation are currently available:
55
56
    @li 'Borrow' - The Data instance is borrowing the memory from the passed
57
                   in buffer. It will modify its contents as necessary,
58
                   but will not deallocate it.
59
            
60
    @li 'Share'  - The Data instance will use the buffer in a read-only mode.
61
                   If any attempt is made to modify the contents of
62
                   the Data, it will copy the buffer and modify it.
63
           
64
    @li 'Take'   - The Data instance takes complete ownership of the
65
                   buffer. The buffer is deallocated using delete[].
66
67
   Additionally, Data has a small locally-allocated buffer (member buffer) that
68
   it will use to hold small amounts of data. By default, this buffer can 
69
   contain 16 bytes, meaning that Data will not use the heap unless it
70
   needs more than 16 bytes of space. The tradeoff here, of course, is that
71
   instances of Data will be larger than instances of std::string. Generally
72
   speaking, if you expect to need more than 16 bytes of room, and you cannot
73
   make good use of the flexible memory management offered by Data, you may want
74
   to use a std::string instead.
75
76
  @see RESIP_HeapCount
77
78
  @todo It might be worthwhile examining the heap usage of this
79
        class in the context of using realloc everywhere appropriate.
80
        (realloc is defined in ANSI C, SVID, and the OpenGroup "Single
81
        Unix Specification").
82
83
   @ingroup text_proc
84
*/
85
86
class Data 
87
{
88
   public:
89
      RESIP_HeapCount(Data);
90
91
      typedef uint32_t size_type;
92
93
      inline Data()
94
         : mBuf(mPreBuffer),
95
           mSize(0),
96
           mCapacity(LocalAlloc),
97
           mShareEnum(Borrow)
98
19.4M
      {
99
19.4M
         mBuf[mSize] = 0;
100
19.4M
      }
101
102
      /**
103
      @internal
104
      */
105
      class PreallocateType
106
      {
107
         friend class Data;
108
         explicit PreallocateType(int);
109
      };
110
      /**
111
      @brief used only to disambiguate constructors
112
      */
113
      static const PreallocateType Preallocate;
114
115
      /**
116
        Creates a data with a specified initial capacity.
117
118
        @param capacity  The initial capacity of the buffer
119
120
        @param foo       This parameter is ignored; it is merely
121
                         used to disambiguate this constructor
122
                         from the constructor that takes a single
123
                         int. Always pass Data::Preallocate.
124
      */
125
      Data(size_type capacity, const PreallocateType&);
126
127
//#define DEPRECATED_PREALLOC
128
#ifdef DEPRECATED_PREALLOC
129
      /**
130
        Creates a data with a specified initial capacity.
131
132
        @deprecated      This constructor shouldn't really exist;
133
                         it would be far better to add a value
134
                         to "ShareEnum" (e.g. "Allocate") which
135
                         indicates that the Data should allocated
136
                         its own buffer.
137
138
        @param capacity  The initial capacity of the buffer
139
140
        @param foo       This parameter is ignored; it is merely
141
                         used to disambiguate this constructor
142
                         from the constructor that takes a single
143
                         int. Yes, it's ugly -- that's why it's
144
                         deprecated.
145
146
        @todo Remove this constructor
147
      */
148
      Data(size_type capacity, bool foo);
149
#endif      
150
151
      /**
152
        Creates a data with a copy of the contents of the
153
        null-terminated string.
154
155
        @warning Passing a non-null-terminated string to this
156
                 method would be a Really Bad Thing.
157
      */
158
      Data(const char* str);
159
160
      /**
161
        Creates a data with the contents of the buffer.
162
163
        @param length Number of bytes in the buffer
164
      */
165
      Data(const char* buffer, size_type length);
166
167
      /**
168
        Creates a data with the contents of the buffer.
169
170
        @param length Number of bytes in the buffer
171
      */
172
      Data(const unsigned char* buffer, size_type length);
173
174
      Data(const Data& data);
175
176
#ifdef RESIP_HAS_RVALUE_REFS
177
      Data(Data &&data);
178
#endif
179
      /**
180
        Creates a data with the contents of the string.
181
      */
182
      explicit Data(const std::string& str);
183
184
      /**
185
        Converts the passed in value into ascii-decimal
186
        representation, and then creates a "Data" containing
187
        that value. (E.g. "Data(75)" will create a Data
188
        with length=2, and contents of 0x37 0x35).
189
      */
190
      explicit Data(int32_t value);
191
192
      /**
193
        Converts the passed in value into ascii-decimal
194
        representation, and then creates a "Data" containing
195
        that value. (E.g. "Data(75)" will create a Data
196
        with length=2, and contents of 0x37 0x35).
197
      */
198
      explicit Data(uint32_t value);
199
200
      /**
201
        Converts the passed in value into ascii-decimal
202
        representation, and then creates a "Data" containing
203
        that value. (E.g. "Data(75)" will create a Data
204
        with length=2, and contents of 0x37 0x35).
205
      */
206
      explicit Data(uint64_t value);
207
208
#ifndef RESIP_FIXED_POINT
209
      enum DoubleDigitPrecision 
210
      {
211
         ZeroDigitPrecision = 0, OneDigitPrecision, 
212
         TwoDigitPrecision, ThreeDigitPrecision, 
213
         FourDigitPrecision, FiveDigitPrecision,
214
         SixDigitPrecision, SevenDigitPrecision,
215
         EightDigitPrecision, NineDigitPrecision,
216
         TenDigitPrecision, MaxDigitPrecision
217
      };
218
      /**
219
        Converts the passed in value into ascii-decimal
220
        representation, and then creates a "Data" containing
221
        that value. (E.g. "Data(75.4,2)" will create a Data
222
        with length=4, and contents of 0x37 0x35 0x2E 0x34).
223
224
        @param precision  Number of digits after the decimal point.
225
                          Trailing zeros will be removed.
226
      */
227
      explicit Data(double value, 
228
                    Data::DoubleDigitPrecision precision = FourDigitPrecision);
229
#endif
230
231
      /**
232
        Creates a buffer containing "true" or "false", depending
233
        on the value of "value".
234
      */
235
      explicit Data(bool value);
236
237
      /**
238
        Creates a buffer containing a single character. Is this silly?
239
        Maybe. Perhaps it can be removed.
240
      */
241
      explicit Data(char c);
242
243
      /**
244
        The various memory management behaviors.
245
      */
246
      enum ShareEnum 
247
      {
248
        /** The Data instance is borrowing the memory from the passed
249
            in buffer. It will modify its contents as necessary,
250
            but will not deallocate it.
251
        */
252
        Borrow=0,
253
254
        /** The Data instance will use the buffer in a read-only mode.
255
            If any attempt is made to modify the contents of
256
            the Data, it will copy the buffer and modify it.
257
        */
258
        Share=1,
259
260
        /** The Data instance takes complete ownership of the
261
            buffer. The buffer must have been allocate using
262
            "new char[]" so that it can be freed with "delete char[]".
263
        */
264
        Take=2
265
      };
266
267
      /**
268
        Creates a Data from the passed-in buffer.
269
270
        @see ShareEnum
271
      */
272
273
      Data(ShareEnum, const char* buffer, size_type length);
274
275
      /**
276
        Creates a Data from the passed-in buffer.
277
278
        @see ShareEnum
279
      */
280
281
      Data(ShareEnum, const char* buffer, size_type length, size_type capacity);
282
283
      /**
284
        Takes a null-terminated string and creates a buffer.
285
286
        @see ShareEnum
287
288
        @warning Passing a non-null-terminated string to this
289
                 method would be a Really Bad Thing.
290
      */
291
      Data(ShareEnum, const char* buffer);
292
293
      /**
294
        Lazily creates a Data from the passed-in Data. 
295
296
        @see ShareEnum
297
298
        @warning Calling this with "Take" or "Borrow" is invalid and will
299
                 cause an assertion or crash.
300
301
        @todo This implementation has some confusing and conflicting
302
              comments. (e.g. is Borrow actually okay? Can there be some
303
              way to use it with Take as long as you play with mShareEnum
304
              correctly?)
305
      */
306
      Data(ShareEnum, const Data& staticData); // Cannot call with 'Take'
307
308
      inline ~Data()
309
51.8M
      {
310
51.8M
         if (mShareEnum == Take)
311
626k
         {
312
626k
            delete[] mBuf;
313
626k
         }
314
51.8M
      }
315
316
      /**
317
        Set the Data to hold {buf} using share type {se}, which may be any
318
        of Share (read-only, no-free), Borrow (read-write, no-free)
319
        or Take (read-write, yes-free). Both the capacity
320
        and current length are set to {length}; you can call truncate2()
321
        afterwords to shorten.  The provided buffer (and its current
322
        contents) will be used going forward; any currently owned buffer
323
        will be released.
324
        NOTE: The {buf} param is declared const to support Share type; for
325
        Borrow and Take the buffer may be written (e.g., treated non-const).
326
      **/
327
      Data& setBuf(ShareEnum se, const char *buf, size_type length);
328
329
      /**
330
        Convience function to call setBuf() with a NULL-terminated string.
331
        This is in-lined for case where compiler knows strlen statically.
332
      **/
333
      Data& setBuf(ShareEnum se, const char *str)
334
0
      {
335
0
         return setBuf(se, str, (size_type)strlen(str));
336
0
      };
337
338
339
      /**
340
        Take the data from {other}. Any current buffer is released.
341
        {this} will have the same storage mode as {other} and steal
342
        its buffer. All storage modes of {other} (Share,Borrow,Take)
343
        are legal. When done, {other} will be empty (it will ref its
344
        internal buffer).
345
      **/
346
      Data& takeBuf(Data& other);
347
348
      /**
349
        Functional equivalent of: *this = Data(buf, length)
350
        and Data& copy(const char *buf, size_type length)
351
        but avoids an actual copy of the data if {other} is Shared
352
        or Borrowed.  Will have the same storage mode as {other}.
353
      **/
354
      Data& duplicate(const Data& other);
355
356
      /**
357
        Functional equivalent of: *this = Data(buf, length)
358
        but avoids the intermediate allocation and free. Also,
359
        will never decrease capacity. Safe to call even if {buf}
360
        is part of {this}.
361
362
        @note The result is always NULL terminated. Unfortunately,
363
        this requires a buffer allocation even if capacity exactly
364
        equals length.
365
      **/
366
      Data& copy(const char *buf, size_type length);
367
368
      /**
369
        Set size to be exactly {length}, extending buffer if needed.
370
        Also, reallocate buffer if needed so that it is writable.
371
        Buffer contents is NOT initialized, and existing contents
372
        may or may not be preserved.
373
374
        @note Purpose of this function is to provide a working buffer
375
        of fixed size that the application fills in after this call.
376
377
        @note If you want just the buffer without changing the size,
378
        use data() and cast-away the const-ness.
379
380
        @note The result may or may not be NULL terminated. The buffer
381
        is NULL terminated only when safe to do so without extra reallocation.
382
      **/
383
      char* getBuf(size_type length);
384
385
      /**
386
        Converts from arbitrary other type to Data. Requires the other
387
        type to have an operator<<.
388
      */
389
      template<class T>
390
      static Data from(const T& x)
391
0
      {
392
0
         Data d;
393
0
         {
394
0
            DataStream s(d);
395
0
            s << x;
396
0
         }
397
0
         return d;
398
0
      }
Unexecuted instantiation: resip::Data resip::Data::from<resip::Contents>(resip::Contents const&)
Unexecuted instantiation: resip::Data resip::Data::from<resip::Uri>(resip::Uri const&)
399
400
      friend bool operator==(const Data& lhs, const Data& rhs);
401
      friend bool operator==(const Data& lhs, const char* rhs);
402
403
      friend bool operator<(const Data& lhs, const Data& rhs);
404
      friend bool operator<(const Data& lhs, const char* rhs);
405
      friend bool operator<(const char* lhs, const Data& rhs);
406
407
      Data& operator=(const Data& data)
408
151k
      {
409
151k
         if (&data==this)
410
0
             return *this;
411
151k
         return copy(data.mBuf,data.mSize);
412
151k
      }
413
414
#ifdef RESIP_HAS_RVALUE_REFS
415
      Data& operator=(Data &&data);
416
#endif
417
418
      /**
419
        Assigns a null-terminated string to the buffer.
420
421
        @warning Passing a non-null-terminated string to this
422
                 method would be a Really Bad Thing.
423
        The strlen() inlined to take advantages of cases where
424
        the compiler knows the length statically.
425
      */
426
      Data& operator=(const char* str)
427
426
      {
428
426
         return copy(str, (size_type)strlen(str));
429
426
      }
430
431
      /**
432
        Concatenates two Data objects.
433
      */
434
      Data operator+(const Data& rhs) const;
435
436
      /**
437
        Concatenates a null-terminated string after the Data object.
438
439
        @warning Passing a non-null-terminated string to this
440
                 method would be a Really Bad Thing.
441
      */
442
      Data operator+(const char* str) const;
443
444
      /**
445
        Concatenates a single byte after Data object.
446
      */
447
      Data operator+(char c) const;
448
449
      /**
450
        Appends a data object to this one.
451
      */
452
      inline Data& operator+=(const Data& rhs)
453
102k
      {
454
102k
         return append(rhs.data(), rhs.size());
455
102k
      }
456
457
      /**
458
        Appends a null-terminated string to the end of the Data
459
        object.
460
461
        @warning Passing a non-null-terminated string to this
462
                 method would be a Really Bad Thing.
463
      */
464
      inline Data& operator+=(const char* str)
465
205k
      {
466
205k
         resip_assert(str);
467
205k
         return append(str, (size_type)strlen(str));
468
205k
      }
469
470
471
      /**
472
        Appends a single byte to the Data object.
473
      */
474
      inline Data& operator+=(char c)
475
1.35G
      {
476
1.35G
         return append(&c, 1);
477
1.35G
      }
478
479
480
      /**
481
        Performs an in-place exclusive-or of this buffer
482
        buffer with the specified buffer. If the specifed
483
        buffer is longer than this buffer, then this buffer
484
        will first be expanded and zero-padded.
485
      */
486
      Data& operator^=(const Data& rhs);
487
488
      /**
489
        Returns the character at the specified position. Ensures that ownership of
490
        the buffer is taken, since the character could be modified by the caller.
491
      */
492
      inline char& operator[](size_type p)
493
9.70M
      {
494
9.70M
         resip_assert(p < mSize);
495
9.70M
         own();
496
9.70M
         return mBuf[p];
497
9.70M
      }
498
499
      /**
500
        Returns the character at the specified position.
501
      */
502
      inline char operator[](size_type p) const
503
5.96M
      {
504
5.96M
         resip_assert(p < mSize);
505
5.96M
         return mBuf[p];
506
5.96M
      }
507
508
      /**
509
        Returns the character at the specified position.
510
      */
511
      char& at(size_type p);
512
513
      /**
514
        Guarantees that the underlying buffer used by the Data
515
        is at least the number of bytes specified. May cause
516
        reallocation of the buffer.
517
      */
518
      void reserve(size_type capacity);
519
520
      /**
521
        Appends the specified number of bytes to the end of
522
        this Data.
523
      */
524
      Data& append(const char* str, size_type len);
525
526
      /**
527
        Shortens the size of this Data. Does not
528
        impact the size of the allocated buffer.
529
        This owns() the buffer (undoes Share) so as to write
530
        terminating NULL. See truncate2() as alternative.
531
532
        @deprecated dlb says that no one uses this and
533
                    it should be removed.
534
535
        @todo Remove this at some point.
536
      */
537
      size_type truncate(size_type len);
538
539
      /**
540
        Shortens the size of this Data so length is at most of {len}.
541
        (If already shorter, doesn't increase length).
542
        Does not affect buffer allocation, and doesn't impact writing
543
        terminating NULL. Thus is safe to use with Share'd or external
544
        Take'n buffers.
545
      **/
546
      Data& truncate2(size_type len);
547
548
      /**
549
        Checks whether the Data is empty.
550
      */
551
769k
      bool empty() const noexcept { return mSize == 0; }
552
553
      /**
554
        Returns the number of bytes in this Data.
555
556
        @note This does NOT indicate the capacity of the
557
              underlying buffer.
558
      */
559
42.3M
      size_type size() const noexcept { return mSize; }
560
561
      /**
562
        Returns a pointer to the contents of this Data. This
563
        is the preferred mechanism for accessing the bytes inside
564
        the Data.
565
566
        @note The value returned is NOT necessarily null-terminated.
567
      */
568
      const char* data() const noexcept
569
9.77M
      {
570
9.77M
         return mBuf;
571
9.77M
      }
572
573
      /**
574
        Returns a null-terminated string representing 
575
576
        @note    Depending on the memory management scheme being used,
577
                 this method often copies the contents of the Data;
578
                 consequently, this method is rather expensive and should
579
                 be avoided when possible.
580
581
        @warning Calling this method is a pretty bad idea if the
582
                 contents of Data are binary (i.e. may contain
583
                 a null in the middle of the Data).
584
      */
585
      const char* c_str() const;
586
587
      /**
588
        Returns a pointer to the beginning of the buffer used by the Data.
589
      */
590
      const char* begin() const noexcept
591
0
      {
592
0
         return mBuf;
593
0
      }
594
595
      /**
596
        Returns a pointer to the end of the buffer used by the Data.
597
      */
598
      const char* end() const noexcept
599
0
      {
600
0
         return mBuf + mSize;
601
0
      }
602
603
      typedef enum
604
      {
605
         BINARY,
606
         BASE64,
607
         HEX
608
      } EncodingType;
609
610
      /**
611
        Computes the MD5 hash of the current data.
612
        @param type The encoding of the return (default is HEX)
613
        @return The MD5 hash, in the encoding specified by type.
614
      */      
615
      Data md5(EncodingType type=HEX) const;
616
617
      /**
618
        Converts this Data to lowercase.
619
620
        @note This is silly unless the contents are ASCII.
621
      */      
622
      Data& lowercase();
623
624
      /**
625
        Converts this Data to uppercase.
626
627
        @note This is silly unless the contents are ASCII.
628
      */      
629
      Data& uppercase();
630
631
      /**
632
        Converts this Data to lowercase, assuming this Data only consists of 
633
        scheme characters.
634
635
        @note Assuming scheme contents allows the use of a bitmask instead of
636
         tolower(), which is faster. Why, you ask? A bitmask is sufficient to 
637
         perform a lowercase operation on alphabetical data, since 'a' and 'A' 
638
         only differ on bit 6; it is set for 'a', but not for 'A'. Digits always 
639
         have bit 6 set, so setting it is a no-op. The last three characters in 
640
         the scheme character set are '+', '-', and '.'; all of these have bit 6 
641
         set as well. Note that there is no corresponding efficient uppercase 
642
         function; clearing bit 6 on either a digit or the the three remaining 
643
         characters (+=.) will change them.
644
      */
645
      Data& schemeLowercase();
646
647
      /**
648
        Returns a hexadecimal representation of the contents of
649
        this Data.
650
      */
651
      Data hex() const;
652
653
      /**
654
        Returns the binary form of the hexadecimal string in this Data
655
      */
656
      Data fromHex() const;
657
658
      /**
659
        Returns a representation of the contents of the data
660
        with any non-printable characters escaped.
661
662
        @warning This is extremely slow, and should not be called
663
                 except for debugging purposes.
664
      */
665
      Data escaped() const;
666
667
      /**
668
        Performs RFC 3261 escaping of SIP URIs.
669
670
        @note This method is relatively inefficient
671
672
        @deprecated Use escapeToStream instead
673
674
        @todo This method should be removed
675
676
        @see escapeToStream
677
      */
678
      Data charEncoded() const;
679
680
      /**
681
        Performs RFC 3261 un-escaping of SIP URIs.
682
683
        @note This method is relatively inefficient
684
685
        @bug This method can assert if a "%00" comes
686
             in off the wire. That's really bad form.
687
688
        @deprecated Use something more in the spirit of escapeToStream instead
689
690
        @todo This method should be removed
691
692
        @see escapeToStream
693
      */
694
      Data charUnencoded() const;
695
696
      /**
697
        Performs in-place HTTP URL escaping of a Data.
698
      */
699
      Data urlEncoded() const;
700
701
      /**
702
        Performs in-place HTTP URL un-escaping of a Data.
703
      */
704
      Data urlDecoded() const;
705
706
      /**
707
        Escapes a Data to a stream according to HTTP URL encoding rules.
708
      */
709
      EncodeStream& urlEncode(EncodeStream& s) const;
710
711
      /**
712
        Un-escapes a Data to a stream according to HTTP URL encoding rules.
713
      */
714
      EncodeStream& urlDecode(EncodeStream& s) const;
715
716
      /**
717
        Performs in-place XML Character Data escaping of a Data.
718
      */
719
      Data xmlCharDataEncode() const;
720
721
      /**
722
        Performs in-place XML Character Data un-escaping of a Data.
723
      */
724
      Data xmlCharDataDecode() const;
725
726
      /**
727
        Escapes a Data to a stream according to XML Character Data encoding rules.
728
      */
729
      EncodeStream& xmlCharDataEncode(EncodeStream& s) const;
730
731
      /**
732
        Un-escapes a Data to a stream according to XML Character Data encoding rules.
733
      */
734
      EncodeStream& xmlCharDataDecode(EncodeStream& s) const;
735
736
      /**
737
        Shortens the size of this Data. If the contents are truncated,
738
        this method appends two dot ('.') characters to the end.
739
        Presumably, this is used for output purposes.
740
      */
741
      Data trunc(size_type trunc) const;
742
743
      /**
744
        Clears the contents of this Data. This call does not modify
745
        the capacity of the Data. It does not write terminating NULL,
746
        and thus is safe to use with external buffers.
747
      */
748
824
      Data& clear() { return truncate2(0); };
749
750
      /**
751
        Takes the contents of the Data and converts them to an 
752
        integer. Will strip leading whitespace. This method stops
753
        upon encountering the first non-decimal digit (with exceptions
754
        made for leading negative signs).
755
      */ 
756
      int convertInt() const;
757
      unsigned long convertUnsignedLong() const;
758
759
      /**
760
        Takes the contents of the Data and converts them to a 
761
        size_t. Will strip leading whitespace. This method stops
762
        upon encountering the first non-decimal digit.
763
      */ 
764
      size_t convertSize() const;
765
766
#ifndef RESIP_FIXED_POINT
767
      /**
768
        Takes the contents of the Data and converts them to a 
769
        double precision floating point value. Will strip leading
770
        whitespace. This method stops upon encountering the first
771
        non-decimal digit (with exceptions made for decimal points
772
        and leading negative signs).
773
      */ 
774
      double convertDouble() const;
775
#endif
776
777
      /**
778
        Takes the contents of the Data and converts them to an
779
        unsigned 64-bit integer. Will strip leading whitespace.
780
        This method stops upon encountering the first non-decimal digit.
781
      */ 
782
      uint64_t convertUInt64() const;
783
784
      /**
785
        Returns true if this Data starts with the bytes indicated by
786
        the passed-in Data. For example, if this Data is "abc", then
787
        prefix(Data("ab")) would be true; however, prefix(Data("abcd"))
788
        would be false.
789
      */
790
      bool prefix(const Data& pre) const;
791
792
      /**
793
        Returns true if this Data ends with the bytes indicated by
794
        the passed-in Data. For example, if this Data is "abc", then
795
        postfix(Data("bc")) would be true; however, postfix(Data("ab"))
796
        would be false.
797
      */
798
      bool postfix(const Data& post) const;
799
800
      /**
801
        Copies a portion of this Data into a new Data.
802
 
803
        @param first Index of the first byte to copy
804
        @param count Number of bytes to copy
805
      */
806
      Data substr(size_type first, size_type count = Data::npos) const;
807
808
      /**
809
        Finds a specified sequence of bytes in this Data.
810
811
        @param match The bytes to be found
812
813
        @param start Offset into this Data to start the search
814
815
        @returns An index to the start of the found bytes.
816
      */
817
      size_type find(const Data& match, size_type start = 0) const;
818
819
      /** 
820
          Replaces up to max occurrences of the bytes match with
821
          target. Returns the number of matches.
822
      */
823
      int replace(const Data& match, const Data& target, int max=INT_MAX);
824
      
825
      /**
826
        Constant that represents a zero-length data.
827
      */
828
      static const Data Empty;
829
830
      /**
831
         Represents an impossible position; returned to indicate failure to find.
832
      */
833
      static const size_type npos;
834
835
      /**
836
        Initializes Data class.
837
838
        @note This method is a link time constraint. Don't remove it.
839
      */
840
      static bool init(DataLocalSize<RESIP_DATA_LOCAL_SIZE> arg);
841
842
      /**
843
        Performs RFC 3548 Base 64 decoding of the contents of this data.
844
845
        @returns A new buffer containing the unencoded representation
846
      */
847
      Data base64decode() const;
848
849
      /**
850
        Performs RFC 3548 Base 64 encoding of the contents of this data.
851
852
        @returns A new buffer containing the base64 representation
853
      */
854
      Data base64encode(bool useUrlSafe=false) const;
855
856
      /**
857
        Creates a 32-bit hash based on the contents of the indicated
858
        buffer.
859
860
        @param c Pointer to the buffer to hash
861
        @param size Number of bytes to be hashed
862
      */
863
      static size_t rawHash(const unsigned char* c, size_t size);
864
865
      /**
866
        Creates a 32-bit hash based on the contents of this Data.
867
      */
868
      size_t hash() const;
869
870
      /**
871
        Creates a 32-bit hash based on the contents of the indicated
872
        buffer, after normalizing any alphabetic characters to lowercase.
873
874
        @param c Pointer to the buffer to hash
875
        @param size Number of bytes to be hashed
876
      */
877
      static size_t rawCaseInsensitiveHash(const unsigned char* c, size_t size);
878
879
      /**
880
        A faster version of rawCaseInsensitiveHash that has the same collision 
881
        properties if this Data is made up of RFC 3261 token characters.
882
883
        @param c Pointer to the buffer to hash
884
        @param size Number of bytes to be hashed
885
        @note This is not guaranteed to return the same value as 
886
            rawCaseInsensitiveHash.
887
      */
888
      static size_t rawCaseInsensitiveTokenHash(const unsigned char* c, size_t size);
889
890
      /**
891
        Creates a 32-bit hash based on the contents of this Data, after
892
        normalizing any alphabetic characters to lowercase.
893
      */
894
      size_t caseInsensitivehash() const;
895
896
      /**
897
        A faster version of caseInsensitiveHash that has the same collision 
898
        properties if this Data is made up of RFC 3261 token characters.
899
        @note This is not guaranteed to return the same value as 
900
            rawCaseInsensitiveHash.
901
      */
902
      size_t caseInsensitiveTokenHash() const;
903
904
      inline bool caseInsensitiveTokenCompare(const Data& rhs) const
905
0
      {
906
0
         if(mSize==rhs.mSize)
907
0
         {
908
0
            return sizeEqualCaseInsensitiveTokenCompare(rhs);
909
0
         }
910
0
         return false;
911
0
      }
912
913
      bool sizeEqualCaseInsensitiveTokenCompare(const Data& rhs) const;
914
915
      /**
916
         Creates a bitset reflecting the contents of this data (as a set)
917
         ie. "15eo" would have the bits 49, 53, 101, and 111 set to true, and
918
         all others set to false
919
      */
920
      static std::bitset<256> toBitset(const resip::Data& chars);
921
922
      /**
923
        Performs escaping of this Data according to the indicated
924
        Predicate.
925
926
        @param str          A stream to which the escaped representation
927
                            should be added.
928
929
        @param shouldEscape A functor which takes a single character
930
                            as a parameter, and returns true if the
931
                            character should be escaped, false if
932
                            it should not.
933
934
        @deprecated dlb -- pass a 256 array of bits rather than a function.
935
      */      
936
      template<class Predicate> EncodeStream& 
937
          escapeToStream(EncodeStream& str, 
938
                         Predicate shouldEscape) const;
939
940
      /**
941
        Performs escaping of this Data according to a bitset.
942
943
        @param str          A stream to which the escaped representation
944
                            should be added.
945
946
        @param shouldEscape A bitset representing which chars should be escaped.
947
      */      
948
      std::ostream& escapeToStream(std::ostream& str, 
949
                                   const std::bitset<256>& shouldEscape) const;
950
951
      static Data fromFile(const Data& filename);
952
953
   private:
954
      /**
955
        @deprecated use Data(ShareEnum ...)
956
      */
957
      Data(const char* buffer, size_type length, bool);
958
959
      /**
960
        Used by string constructors
961
      */
962
      inline void initFromString(const char* str, size_type len);
963
964
      /**
965
        Copies the contents of this data to a new buffer if the
966
        Data does not own the current buffer.
967
      */
968
      void own() const;
969
970
      /**
971
        @note Always allocates a new buffer
972
      */
973
      void resize(size_type newSize, bool copy);
974
975
      static bool isHex(unsigned char c);      
976
977
      /** Trade off between in-object and heap allocation
978
          Larger LocalAlloc makes for larger objects that have Data members but
979
          bulk allocation/deallocation of Data  members. */
980
      enum {LocalAlloc = RESIP_DATA_LOCAL_SIZE };
981
982
      char* mBuf;
983
      size_type mSize;
984
      size_type mCapacity;
985
      char mPreBuffer[LocalAlloc];
986
      // Null terminator for mPreBuffer when mSize==LocalAlloc lands here; this
987
      // is ok, because Borrow==0.
988
      // Note: we could use a char here, and expand mPreBuffer by 3 bytes, but 
989
      // this imposes a performance penalty since it requires operating on a 
990
      // memory location smaller than a word (requires masking and such).
991
      size_type mShareEnum;
992
993
      friend std::ostream& operator<<(std::ostream& strm, const Data& d);
994
#ifndef RESIP_USE_STL_STREAMS
995
      friend EncodeStream& operator<<(EncodeStream& strm, const Data& d);
996
#endif
997
      friend class ParseBuffer;
998
      friend class DataBuffer;
999
      friend class DataStream;
1000
      friend class oDataStream;
1001
      friend class ::TestData;
1002
      friend class MD5Buffer;
1003
};
1004
// reset alignment to previous value
1005
#pragma pack(pop)
1006
1007
1008
class DataHelper {
1009
   public:
1010
      static const bool isCharHex[256];
1011
};
1012
1013
static bool invokeDataInit = Data::init(DataLocalSize<RESIP_DATA_LOCAL_SIZE>(0));
1014
1015
inline bool Data::isHex(unsigned char c)
1016
0
{
1017
   // Shut up the warning about invokeDataInit defined, but not used
1018
0
   if(0){(void) invokeDataInit;}
1019
1020
0
   return DataHelper::isCharHex[c];
1021
0
}
1022
1023
inline bool isEqualNoCase(const Data& left, const Data& right)
1024
1.49M
{
1025
1.49M
   return ( (left.size() == right.size()) &&
1026
1.49M
            (strncasecmp(left.data(), right.data(), left.size()) == 0) );
1027
1.49M
}
1028
1029
inline bool isTokenEqualNoCase(const Data& left, const Data& right)
1030
0
{
1031
0
   return left.caseInsensitiveTokenCompare(right);
1032
0
}
1033
1034
inline bool isLessThanNoCase(const Data& left, const Data& right)
1035
0
{
1036
0
   size_t minsize = resipMin( left.size(), right.size() );
1037
0
   int res = strncasecmp(left.data(), right.data(), minsize);
1038
1039
0
   if (res < 0)
1040
0
   {
1041
0
      return true;
1042
0
   }
1043
0
   else if (res > 0)
1044
0
   {
1045
0
      return false;
1046
0
   }
1047
0
   else
1048
0
   {
1049
0
      return left.size() < right.size();
1050
0
   }
1051
0
}
1052
1053
template<class Predicate> EncodeStream& 
1054
Data::escapeToStream(EncodeStream& str, Predicate shouldEscape) const
1055
{
1056
   constexpr char hex[] = "0123456789ABCDEF";
1057
1058
   if (empty())
1059
   {
1060
      return str;
1061
   }
1062
   
1063
   const unsigned char* p = (unsigned char*)mBuf;
1064
   const unsigned char* e = (unsigned char*)mBuf + mSize;
1065
1066
   while (p < e)
1067
   {
1068
      // ?abr? Why is this special cased? Removing this code
1069
      // does not change the behavior of this method.
1070
      if (*p == '%' 
1071
          && e - p > 2 
1072
          && isHex(*(p+1)) 
1073
          && isHex(*(p+2)))
1074
      {
1075
         str.write((char*)p, 3);
1076
         p+=3;
1077
      }
1078
      else if (shouldEscape[*p])
1079
      {
1080
         int hi = (*p & 0xF0)>>4;
1081
         int low = (*p & 0x0F);
1082
1083
         str << '%' << hex[hi] << hex[low];
1084
         p++;
1085
      }
1086
      else
1087
      {
1088
         str.put(*p++);
1089
      }
1090
   }
1091
   return str;
1092
}
1093
1094
83.9k
inline bool operator!=(const Data& lhs, const Data& rhs) { return !(lhs == rhs); }
1095
0
inline bool operator>(const Data& lhs, const Data& rhs) { return rhs < lhs; }
1096
0
inline bool operator<=(const Data& lhs, const Data& rhs) { return !(rhs < lhs); }
1097
0
inline bool operator>=(const Data& lhs, const Data& rhs) { return !(lhs < rhs); }
1098
0
inline bool operator!=(const Data& lhs, const char* rhs) { return !(lhs == rhs); }
1099
0
inline bool operator>(const Data& lhs, const char* rhs) { return rhs < lhs; }
1100
0
inline bool operator<=(const Data& lhs, const char* rhs) { return !(rhs < lhs); }
1101
0
inline bool operator>=(const Data& lhs, const char* rhs) { return !(lhs < rhs); }
1102
0
inline bool operator==(const char* lhs, const Data& rhs) { return rhs == lhs; }
1103
0
inline bool operator!=(const char* lhs, const Data& rhs) { return !(rhs == lhs); }
1104
0
inline bool operator>(const char* lhs, const Data& rhs) { return rhs < lhs; }
1105
0
inline bool operator<=(const char* lhs, const Data& rhs) { return !(rhs < lhs); }
1106
0
inline bool operator>=(const char* lhs, const Data& rhs) { return !(lhs < rhs); }
1107
#ifndef  RESIP_USE_STL_STREAMS
1108
EncodeStream& operator<<(EncodeStream& strm, const Data& d);
1109
#endif
1110
inline std::ostream& operator<<(std::ostream& strm, const Data& d)
1111
996k
{
1112
996k
   return strm.write(d.mBuf, d.mSize);
1113
996k
}
1114
1115
1116
inline Data
1117
operator+(const char* c, const Data& d)
1118
0
{
1119
0
   return Data(c) + d;
1120
0
}
1121
1122
bool operator==(const Data& lhs, const Data& rhs);
1123
bool operator==(const Data& lhs, const char* rhs);
1124
1125
bool operator<(const Data& lhs, const Data& rhs);
1126
bool operator<(const Data& lhs, const char* rhs);
1127
bool operator<(const char* lhs, const Data& rhs);
1128
1129
}
1130
1131
HashValue(resip::Data);
1132
1133
#endif
1134
1135
/* ====================================================================
1136
 * The Vovida Software License, Version 1.0 
1137
 * 
1138
 * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
1139
 * 
1140
 * Redistribution and use in source and binary forms, with or without
1141
 * modification, are permitted provided that the following conditions
1142
 * are met:
1143
 * 
1144
 * 1. Redistributions of source code must retain the above copyright
1145
 *    notice, this list of conditions and the following disclaimer.
1146
 * 
1147
 * 2. Redistributions in binary form must reproduce the above copyright
1148
 *    notice, this list of conditions and the following disclaimer in
1149
 *    the documentation and/or other materials provided with the
1150
 *    distribution.
1151
 * 
1152
 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
1153
 *    and "Vovida Open Communication Application Library (VOCAL)" must
1154
 *    not be used to endorse or promote products derived from this
1155
 *    software without prior written permission. For written
1156
 *    permission, please contact vocal@vovida.org.
1157
 *
1158
 * 4. Products derived from this software may not be called "VOCAL", nor
1159
 *    may "VOCAL" appear in their name, without prior written
1160
 *    permission of Vovida Networks, Inc.
1161
 * 
1162
 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
1163
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1164
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
1165
 * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
1166
 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
1167
 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
1168
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
1169
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
1170
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
1171
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1172
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
1173
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
1174
 * DAMAGE.
1175
 * 
1176
 * ====================================================================
1177
 * 
1178
 * This software consists of voluntary contributions made by Vovida
1179
 * Networks, Inc. and many individuals on behalf of Vovida Networks,
1180
 * Inc.  For more information on Vovida Networks, Inc., please see
1181
 * <http://www.vovida.org/>.
1182
 *
1183
 * vi: set shiftwidth=3 expandtab:
1184
 */