~ubuntu-branches/ubuntu/saucy/resiprocate/saucy-proposed

« back to all changes in this revision

Viewing changes to rutil/Data.hxx

  • Committer: Package Import Robot
  • Author(s): Daniel Pocock
  • Date: 2012-05-17 19:29:59 UTC
  • Revision ID: package-import@ubuntu.com-20120517192959-vv00m77isztdy64q
Tags: upstream-1.8.2
ImportĀ upstreamĀ versionĀ 1.8.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 <cassert>
 
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
      explicit DataLocalSize(size_t) {}
 
42
};
 
43
 
 
44
// .bwc. Pack class Data; has to come before doxygen block though.
 
45
#pragma pack(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 size_type;
 
92
 
 
93
      inline Data()
 
94
         : mBuf(mPreBuffer),
 
95
           mSize(0),
 
96
           mCapacity(LocalAlloc),
 
97
           mShareEnum(Borrow)
 
98
      {
 
99
         mBuf[mSize] = 0;
 
100
      }
 
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 disambuguate 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 disambuguate 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(int 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(unsigned long 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(unsigned int value);
 
207
 
 
208
      /**
 
209
        Converts the passed in value into ascii-decimal
 
210
        representation, and then creates a "Data" containing
 
211
        that value. (E.g. "Data(75)" will create a Data
 
212
        with length=2, and contents of 0x37 0x35).
 
213
      */
 
214
      explicit Data(UInt64 value);
 
215
 
 
216
#ifndef RESIP_FIXED_POINT
 
217
      enum DoubleDigitPrecision 
 
218
      {
 
219
         ZeroDigitPrecision = 0, OneDigitPrecision, 
 
220
         TwoDigitPrecision, ThreeDigitPrecision, 
 
221
         FourDigitPrecision, FiveDigitPrecision,
 
222
         SixDigitPrecision, SevenDigitPrecision,
 
223
         EightDigitPrecision, NineDigitPrecision,
 
224
         TenDigitPrecision, MaxDigitPrecision
 
225
      };
 
226
      /**
 
227
        Converts the passed in value into ascii-decimal
 
228
        representation, and then creates a "Data" containing
 
229
        that value. (E.g. "Data(75.4,2)" will create a Data
 
230
        with length=4, and contents of 0x37 0x35 0x2E 0x34).
 
231
 
 
232
        @param precision  Number of digits after the decimal point.
 
233
                          Trailing zeros will be removed.
 
234
      */
 
235
      explicit Data(double value, 
 
236
                    Data::DoubleDigitPrecision precision = FourDigitPrecision);
 
237
#endif
 
238
 
 
239
      /**
 
240
        Creates a buffer containing "true" or "false", depending
 
241
        on the value of "value".
 
242
      */
 
243
      explicit Data(bool value);
 
244
 
 
245
      /**
 
246
        Creates a buffer containing a single character. Is this silly?
 
247
        Maybe. Perhaps it can be removed.
 
248
      */
 
249
      explicit Data(char c);
 
250
 
 
251
      /**
 
252
        The various memory management behaviors.
 
253
      */
 
254
      enum ShareEnum 
 
255
      {
 
256
        /** The Data instance is borrowing the memory from the passed
 
257
            in buffer. It will modify its contents as necessary,
 
258
            but will not deallocate it.
 
259
        */
 
260
        Borrow=0,
 
261
 
 
262
        /** The Data instance will use the buffer in a read-only mode.
 
263
            If any attempt is made to modify the contents of
 
264
            the Data, it will copy the buffer and modify it.
 
265
        */
 
266
        Share=1,
 
267
 
 
268
        /** The Data instance takes complete ownership of the
 
269
            buffer. The buffer must have been allocate using
 
270
            "new char[]" so that it can be freed with "delete char[]".
 
271
        */
 
272
        Take=2
 
273
      };
 
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);
 
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
      {
 
310
         if (mShareEnum == Take)
 
311
         {
 
312
            delete[] mBuf;
 
313
         }
 
314
      }
 
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
      {
 
335
         return setBuf(se, str, (size_type)strlen(str));
 
336
      };
 
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
        but avoid the intermediate allocation and free. Also,
 
351
        will never decrease capacity. Safe to call even if {buf}
 
352
        is part of {this}.
 
353
 
 
354
        @note The result is always NULL terminated. Unfortunately,
 
355
        this requires a buffer allocation even if capacity exactly
 
356
        equals length.
 
357
      **/
 
358
      Data& copy(const char *buf, size_type length);
 
359
 
 
360
      /**
 
361
        Set size to be exactly {length}, extending buffer if needed.
 
362
        Also, reallocate buffer if needed so that it is writable.
 
363
        Buffer contents is NOT initialized, and existing contents
 
364
        may or may not be preserved.
 
365
 
 
366
        @note Purpose of this function is to provide a working buffer
 
367
        of fixed size that the application fills in after this call.
 
368
 
 
369
        @note If you want just the buffer without changing the size,
 
370
        use data() and cast-away the const-ness.
 
371
 
 
372
        @note The result may or may not be NULL terminated. The buffer
 
373
        is NULL terminated only when safe to do so without extra reallocation.
 
374
      **/
 
375
      char* getBuf(size_type length);
 
376
 
 
377
      /**
 
378
        Converts from arbitrary other type to Data. Requires the other
 
379
        type to have an operator<<.
 
380
      */
 
381
      template<class T>
 
382
      static Data from(const T& x)
 
383
      {
 
384
         Data d;
 
385
         {
 
386
            DataStream s(d);
 
387
            s << x;
 
388
         }
 
389
         return d;
 
390
      }
 
391
 
 
392
      friend bool operator==(const Data& lhs, const Data& rhs);
 
393
      friend bool operator==(const Data& lhs, const char* rhs);
 
394
 
 
395
      friend bool operator<(const Data& lhs, const Data& rhs);
 
396
      friend bool operator<(const Data& lhs, const char* rhs);
 
397
      friend bool operator<(const char* lhs, const Data& rhs);
 
398
 
 
399
      Data& operator=(const Data& data)
 
400
      {
 
401
         if (&data==this)
 
402
             return *this;
 
403
         return copy(data.mBuf,data.mSize);
 
404
      }
 
405
 
 
406
#ifdef RESIP_HAS_RVALUE_REFS
 
407
      Data& operator=(Data &&data);
 
408
#endif
 
409
 
 
410
      /**
 
411
        Assigns a null-terminated string to the buffer.
 
412
 
 
413
        @warning Passing a non-null-terminated string to this
 
414
                 method would be a Really Bad Thing.
 
415
        The strlen() inlined to take advantages of cases where
 
416
        the compiler knows the length statically.
 
417
      */
 
418
      Data& operator=(const char* str)
 
419
      {
 
420
         return copy(str, (size_type)strlen(str));
 
421
      }
 
422
 
 
423
      /**
 
424
        Concatenates two Data objects.
 
425
      */
 
426
      Data operator+(const Data& rhs) const;
 
427
 
 
428
      /**
 
429
        Concatenates a null-terminated string after the Data object.
 
430
 
 
431
        @warning Passing a non-null-terminated string to this
 
432
                 method would be a Really Bad Thing.
 
433
      */
 
434
      Data operator+(const char* str) const;
 
435
 
 
436
      /**
 
437
        Concatenates a single byte after Data object.
 
438
      */
 
439
      Data operator+(char c) const;
 
440
 
 
441
      /**
 
442
        Appends a data object to this one.
 
443
      */
 
444
      inline Data& operator+=(const Data& rhs)
 
445
      {
 
446
         return append(rhs.data(), rhs.size());
 
447
      }
 
448
 
 
449
      /**
 
450
        Appends a null-terminated string to the end of the Data
 
451
        object.
 
452
 
 
453
        @warning Passing a non-null-terminated string to this
 
454
                 method would be a Really Bad Thing.
 
455
      */
 
456
      inline Data& operator+=(const char* str)
 
457
      {
 
458
         assert(str);
 
459
         return append(str, (size_type)strlen(str));
 
460
      }
 
461
 
 
462
 
 
463
      /**
 
464
        Appends a single byte to the Data object.
 
465
      */
 
466
      inline Data& operator+=(char c)
 
467
      {
 
468
         return append(&c, 1);
 
469
      }
 
470
 
 
471
 
 
472
      /**
 
473
        Performs an in-place exclusive-or of this buffer
 
474
        buffer with the specified buffer. If the specifed
 
475
        buffer is longer than this buffer, then this buffer
 
476
        will first be expanded and zero-padded.
 
477
      */
 
478
      Data& operator^=(const Data& rhs);
 
479
 
 
480
      /**
 
481
        Returns the character at the specified position. Ensures that ownership of
 
482
        the buffer is taken, since the character could be modified by the caller.
 
483
      */
 
484
      inline char& operator[](size_type p)
 
485
      {
 
486
         assert(p < mSize);
 
487
         own();
 
488
         return mBuf[p];
 
489
      }
 
490
 
 
491
      /**
 
492
        Returns the character at the specified position.
 
493
      */
 
494
      inline char operator[](size_type p) const
 
495
      {
 
496
         assert(p < mSize);
 
497
         return mBuf[p];
 
498
      }
 
499
 
 
500
      /**
 
501
        Returns the character at the specified position.
 
502
      */
 
503
      char& at(size_type p);
 
504
 
 
505
      /**
 
506
        Guarantees that the underlying buffer used by the Data
 
507
        is at least the number of bytes specified. May cause
 
508
        reallocation of the buffer.
 
509
      */
 
510
      void reserve(size_type capacity);
 
511
 
 
512
      /**
 
513
        Appends the specified number of bytes to the end of
 
514
        this Data.
 
515
      */
 
516
      Data& append(const char* str, size_type len);
 
517
 
 
518
      /**
 
519
        Shortens the size of this Data. Does not
 
520
        impact the size of the allocated buffer.
 
521
        This owns() the buffer (undoes Share) so as to write
 
522
        terminating NULL. See truncate2() as alternative.
 
523
 
 
524
        @deprecated dlb says that no one uses this and
 
525
                    it should be removed.
 
526
 
 
527
        @todo Remove this at some point.
 
528
      */
 
529
      size_type truncate(size_type len);
 
530
 
 
531
      /**
 
532
        Shortens the size of this Data so length is at most of {len}.
 
533
        (If already shorter, doesn't increase length).
 
534
        Does not affect buffer allocation, and doesn't impact writing
 
535
        terminating NULL. Thus is safe to use with Share'd or external
 
536
        Take'n buffers.
 
537
      **/
 
538
      Data& truncate2(size_type len);
 
539
 
 
540
      /**
 
541
        Checks whether the Data is empty.
 
542
      */
 
543
      bool empty() const { return mSize == 0; }
 
544
 
 
545
      /**
 
546
        Returns the number of bytes in this Data.
 
547
 
 
548
        @note This does NOT indicate the capacity of the
 
549
              underlying buffer.
 
550
      */
 
551
      size_type size() const { return mSize; }
 
552
 
 
553
      /**
 
554
        Returns a pointer to the contents of this Data. This
 
555
        is the preferred mechanism for accessing the bytes inside
 
556
        the Data.
 
557
 
 
558
        @note The value returned is NOT necessarily null-terminated.
 
559
      */
 
560
      inline const char* data() const
 
561
      {
 
562
         return mBuf;
 
563
      }
 
564
 
 
565
      /**
 
566
        Returns a null-terminated string representing 
 
567
 
 
568
        @note    Depending on the memory management scheme being used,
 
569
                 this method often copies the contents of the Data;
 
570
                 consequently, this method is rather expensive and should
 
571
                 be avoided when possible.
 
572
 
 
573
        @warning Calling this method is a pretty bad idea if the
 
574
                 contents of Data are binary (i.e. may contain
 
575
                 a null in the middle of the Data).
 
576
      */
 
577
      const char* c_str() const;
 
578
 
 
579
      /**
 
580
        Returns a pointer to the beginning of the buffer used by the Data.
 
581
      */
 
582
      inline const char* begin() const
 
583
      {
 
584
         return mBuf;
 
585
      }
 
586
 
 
587
      /**
 
588
        Returns a pointer to the end of the buffer used by the Data.
 
589
      */
 
590
      inline const char* end() const
 
591
      {
 
592
         return mBuf + mSize;
 
593
      }
 
594
 
 
595
      typedef enum
 
596
      {
 
597
         BINARY,
 
598
         BASE64,
 
599
         HEX
 
600
      } EncodingType;
 
601
 
 
602
      /**
 
603
        Computes the MD5 hash of the current data.
 
604
        @param type The encoding of the return (default is HEX)
 
605
        @return The MD5 hash, in the encoding specified by type.
 
606
      */      
 
607
      Data md5(EncodingType type=HEX) const;
 
608
 
 
609
      /**
 
610
        Converts this Data to lowercase.
 
611
 
 
612
        @note This is silly unless the contents are ASCII.
 
613
      */      
 
614
      Data& lowercase();
 
615
 
 
616
      /**
 
617
        Converts this Data to uppercase.
 
618
 
 
619
        @note This is silly unless the contents are ASCII.
 
620
      */      
 
621
      Data& uppercase();
 
622
 
 
623
      /**
 
624
        Converts this Data to lowercase, assuming this Data only consists of 
 
625
        scheme characters.
 
626
 
 
627
        @note Assuming scheme contents allows the use of a bitmask instead of
 
628
         tolower(), which is faster. Why, you ask? A bitmask is sufficient to 
 
629
         perform a lowercase operation on alphabetical data, since 'a' and 'A' 
 
630
         only differ on bit 6; it is set for 'a', but not for 'A'. Digits always 
 
631
         have bit 6 set, so setting it is a no-op. The last three characters in 
 
632
         the scheme character set are '+', '-', and '.'; all of these have bit 6 
 
633
         set as well. Note that there is no corresponding efficient uppercase 
 
634
         function; clearing bit 6 on either a digit or the the three remaining 
 
635
         characters (+=.) will change them.
 
636
      */
 
637
      Data& schemeLowercase();
 
638
 
 
639
      /**
 
640
        Returns a hexadecimal representation of the contents of
 
641
        this Data.
 
642
      */
 
643
      Data hex() const;
 
644
 
 
645
      /**
 
646
        Returns a representation of the contents of the data
 
647
        with any non-printable characters escaped.
 
648
 
 
649
        @warning This is extremely slow, and should not be called
 
650
                 except for debugging purposes.
 
651
      */
 
652
      Data escaped() const;
 
653
 
 
654
      /**
 
655
        Performs RFC 3261 escaping of SIP URIs.
 
656
 
 
657
        @note This method is relatively inefficient
 
658
 
 
659
        @deprecated Use escapeToStream instead
 
660
 
 
661
        @todo This method should be removed
 
662
 
 
663
        @see escapeToStream
 
664
      */
 
665
      Data charEncoded() const;
 
666
 
 
667
      /**
 
668
        Performs RFC 3261 un-escaping of SIP URIs.
 
669
 
 
670
        @note This method is relatively inefficient
 
671
 
 
672
        @bug This method can assert if a "%00" comes
 
673
             in off the wire. That's really bad form.
 
674
 
 
675
        @deprecated Use something more in the spirit of escapeToStream instead
 
676
 
 
677
        @todo This method should be removed
 
678
 
 
679
        @see escapeToStream
 
680
      */
 
681
      Data charUnencoded() const;
 
682
 
 
683
      /**
 
684
        Performs in-place HTTP URL escaping of a Data.
 
685
      */
 
686
      Data urlEncoded() const;
 
687
 
 
688
      /**
 
689
        Performs in-place HTTP URL un-escaping of a Data.
 
690
      */
 
691
      Data urlDecoded() const;
 
692
 
 
693
      /**
 
694
        Escapes a Data to a stream according to HTTP URL encoding rules.
 
695
      */
 
696
      EncodeStream& urlEncode(EncodeStream& s) const;
 
697
 
 
698
      /**
 
699
        Un-escapes a Data to a stream according to HTTP URL encoding rules.
 
700
      */
 
701
      EncodeStream& urlDecode(EncodeStream& s) const;
 
702
 
 
703
      /**
 
704
        Performs in-place XML Character Data escaping of a Data.
 
705
      */
 
706
      Data xmlCharDataEncode() const;
 
707
 
 
708
      /**
 
709
        Performs in-place XML Character Data un-escaping of a Data.
 
710
      */
 
711
      Data xmlCharDataDecode() const;
 
712
 
 
713
      /**
 
714
        Escapes a Data to a stream according to XML Character Data encoding rules.
 
715
      */
 
716
      EncodeStream& xmlCharDataEncode(EncodeStream& s) const;
 
717
 
 
718
      /**
 
719
        Un-escapes a Data to a stream according to XML Character Data encoding rules.
 
720
      */
 
721
      EncodeStream& xmlCharDataDecode(EncodeStream& s) const;
 
722
 
 
723
      /**
 
724
        Shortens the size of this Data. If the contents are truncated,
 
725
        this method appends two dot ('.') characters to the end.
 
726
        Presumably, this is used for output purposes.
 
727
      */
 
728
      Data trunc(size_type trunc) const;
 
729
 
 
730
      /**
 
731
        Clears the contents of this Data. This call does not modify
 
732
        the capacity of the Data. It does not write terminating NULL,
 
733
        and thus is safe to use with external buffers.
 
734
      */
 
735
      Data& clear() { return truncate2(0); };
 
736
 
 
737
      /**
 
738
        Takes the contents of the Data and converts them to an 
 
739
        integer. Will strip leading whitespace. This method stops
 
740
        upon encountering the first non-decimal digit (with exceptions
 
741
        made for leading negative signs).
 
742
      */ 
 
743
      int convertInt() const;
 
744
      unsigned long convertUnsignedLong() const;
 
745
 
 
746
      /**
 
747
        Takes the contents of the Data and converts them to a 
 
748
        size_t. Will strip leading whitespace. This method stops
 
749
        upon encountering the first non-decimal digit.
 
750
      */ 
 
751
      size_t convertSize() const;
 
752
 
 
753
#ifndef RESIP_FIXED_POINT
 
754
      /**
 
755
        Takes the contents of the Data and converts them to a 
 
756
        double precision floating point value. Will strip leading
 
757
        whitespace. This method stops upon encountering the first
 
758
        non-decimal digit (with exceptions made for decimal points
 
759
        and leading negative signs).
 
760
      */ 
 
761
      double convertDouble() const;
 
762
#endif
 
763
 
 
764
      /**
 
765
        Takes the contents of the Data and converts them to an
 
766
        unsigned 64-bit integer. Will strip leading whitespace.
 
767
        This method stops upon encountering the first non-decimal digit.
 
768
      */ 
 
769
      UInt64 convertUInt64() const;
 
770
 
 
771
      /**
 
772
        Returns true if this Data starts with the bytes indicated by
 
773
        the passed-in Data. For example, if this Data is "abc", then
 
774
        prefix(Data("ab")) would be true; however, prefix(Data("abcd"))
 
775
        would be false.
 
776
      */
 
777
      bool prefix(const Data& pre) const;
 
778
 
 
779
      /**
 
780
        Returns true if this Data ends with the bytes indicated by
 
781
        the passed-in Data. For example, if this Data is "abc", then
 
782
        postfix(Data("bc")) would be true; however, postfix(Data("ab"))
 
783
        would be false.
 
784
      */
 
785
      bool postfix(const Data& post) const;
 
786
 
 
787
      /**
 
788
        Copies a portion of this Data into a new Data.
 
789
 
 
790
        @param first Index of the first byte to copy
 
791
        @param count Number of bytes to copy
 
792
      */
 
793
      Data substr(size_type first, size_type count = Data::npos) const;
 
794
 
 
795
      /**
 
796
        Finds a specified sequence of bytes in this Data.
 
797
 
 
798
        @param match The bytes to be found
 
799
 
 
800
        @param start Offset into this Data to start the search
 
801
 
 
802
        @returns An index to the start of the found bytes.
 
803
      */
 
804
      size_type find(const Data& match, size_type start = 0) const;
 
805
 
 
806
      /** 
 
807
          Replaces up to max occurrences of the bytes match with
 
808
          target. Returns the number of matches.
 
809
      */
 
810
      int replace(const Data& match, const Data& target, int max=INT_MAX);
 
811
      
 
812
      /**
 
813
        Constant that represents a zero-length data.
 
814
      */
 
815
      static const Data Empty;
 
816
 
 
817
      /**
 
818
         Represents an impossible position; returned to indicate failure to find.
 
819
      */
 
820
      static const size_type npos;
 
821
 
 
822
      /**
 
823
        Initializes Data class.
 
824
 
 
825
        @note This method is a link time constraint. Don't remove it.
 
826
      */
 
827
      static bool init(DataLocalSize<RESIP_DATA_LOCAL_SIZE> arg);
 
828
 
 
829
      /**
 
830
        Performs RFC 3548 Base 64 decoding of the contents of this data.
 
831
 
 
832
        @returns A new buffer containing the unencoded representation
 
833
      */
 
834
      Data base64decode() const;
 
835
 
 
836
      /**
 
837
        Performs RFC 3548 Base 64 encoding of the contents of this data.
 
838
 
 
839
        @returns A new buffer containing the base64 representation
 
840
      */
 
841
      Data base64encode(bool useUrlSafe=false) const;
 
842
 
 
843
      /**
 
844
        Creates a 32-bit hash based on the contents of the indicated
 
845
        buffer.
 
846
 
 
847
        @param c Pointer to the buffer to hash
 
848
        @param size Number of bytes to be hashed
 
849
      */
 
850
      static size_t rawHash(const unsigned char* c, size_t size);
 
851
 
 
852
      /**
 
853
        Creates a 32-bit hash based on the contents of this Data.
 
854
      */
 
855
      size_t hash() const;
 
856
 
 
857
      /**
 
858
        Creates a 32-bit hash based on the contents of the indicated
 
859
        buffer, after normalizing any alphabetic characters to lowercase.
 
860
 
 
861
        @param c Pointer to the buffer to hash
 
862
        @param size Number of bytes to be hashed
 
863
      */
 
864
      static size_t rawCaseInsensitiveHash(const unsigned char* c, size_t size);
 
865
 
 
866
      /**
 
867
        A faster version of rawCaseInsensitiveHash that has the same collision 
 
868
        properties if this Data is made up of RFC 3261 token characters.
 
869
 
 
870
        @param c Pointer to the buffer to hash
 
871
        @param size Number of bytes to be hashed
 
872
        @note This is not guaranteed to return the same value as 
 
873
            rawCaseInsensitiveHash.
 
874
      */
 
875
      static size_t rawCaseInsensitiveTokenHash(const unsigned char* c, size_t size);
 
876
 
 
877
      /**
 
878
        Creates a 32-bit hash based on the contents of this Data, after
 
879
        normalizing any alphabetic characters to lowercase.
 
880
      */
 
881
      size_t caseInsensitivehash() const;
 
882
 
 
883
      /**
 
884
        A faster version of caseInsensitiveHash that has the same collision 
 
885
        properties if this Data is made up of RFC 3261 token characters.
 
886
        @note This is not guaranteed to return the same value as 
 
887
            rawCaseInsensitiveHash.
 
888
      */
 
889
      size_t caseInsensitiveTokenHash() const;
 
890
 
 
891
      inline bool caseInsensitiveTokenCompare(const Data& rhs) const
 
892
      {
 
893
         if(mSize==rhs.mSize)
 
894
         {
 
895
            return sizeEqualCaseInsensitiveTokenCompare(rhs);
 
896
         }
 
897
         return false;
 
898
      }
 
899
 
 
900
      bool sizeEqualCaseInsensitiveTokenCompare(const Data& rhs) const;
 
901
 
 
902
      /**
 
903
         Creates a bitset reflecting the contents of this data (as a set)
 
904
         ie. "15eo" would have the bits 49, 53, 101, and 111 set to true, and
 
905
         all others set to false
 
906
      */
 
907
      static std::bitset<256> toBitset(const resip::Data& chars);
 
908
 
 
909
      /**
 
910
        Performs escaping of this Data according to the indicated
 
911
        Predicate.
 
912
 
 
913
        @param str          A stream to which the escaped representation
 
914
                            should be added.
 
915
 
 
916
        @param shouldEscape A functor which takes a single character
 
917
                            as a parameter, and returns true if the
 
918
                            character should be escaped, false if
 
919
                            it should not.
 
920
 
 
921
        @deprecated dlb -- pass a 256 array of bits rather than a function.
 
922
      */      
 
923
      template<class Predicate> EncodeStream& 
 
924
          escapeToStream(EncodeStream& str, 
 
925
                         Predicate shouldEscape) const;
 
926
 
 
927
      /**
 
928
        Performs escaping of this Data according to a bitset.
 
929
 
 
930
        @param str          A stream to which the escaped representation
 
931
                            should be added.
 
932
 
 
933
        @param shouldEscape A bitset representing which chars should be escaped.
 
934
      */      
 
935
      std::ostream& escapeToStream(std::ostream& str, 
 
936
                                   const std::bitset<256>& shouldEscape) const;
 
937
 
 
938
   private:
 
939
      /**
 
940
        @deprecated use Data(ShareEnum ...)
 
941
      */
 
942
      Data(const char* buffer, size_type length, bool);
 
943
 
 
944
      /**
 
945
        Copies the contents of this data to a new buffer if the
 
946
        Data does not own the current buffer.
 
947
      */
 
948
      void own() const;
 
949
 
 
950
      /**
 
951
        @note Always allocates a new buffer
 
952
      */
 
953
      void resize(size_type newSize, bool copy);
 
954
 
 
955
      static bool isHex(unsigned char c);      
 
956
 
 
957
      /** Trade off between in-object and heap allocation
 
958
          Larger LocalAlloc makes for larger objects that have Data members but
 
959
          bulk allocation/deallocation of Data  members. */
 
960
      enum {LocalAlloc = RESIP_DATA_LOCAL_SIZE };
 
961
 
 
962
      char* mBuf;
 
963
      size_type mSize;
 
964
      size_type mCapacity;
 
965
      char mPreBuffer[LocalAlloc];
 
966
      // Null terminator for mPreBuffer when mSize==LocalAlloc lands here; this
 
967
      // is ok, because Borrow==0.
 
968
      // Note: we could use a char here, and expand mPreBuffer by 3 bytes, but 
 
969
      // this imposes a performance penalty since it requires operating on a 
 
970
      // memory location smaller than a word (requires masking and such).
 
971
      size_type mShareEnum;
 
972
 
 
973
      friend std::ostream& operator<<(std::ostream& strm, const Data& d);
 
974
#ifndef RESIP_USE_STL_STREAMS
 
975
      friend EncodeStream& operator<<(EncodeStream& strm, const Data& d);
 
976
#endif
 
977
      friend class ParseBuffer;
 
978
      friend class DataBuffer;
 
979
      friend class DataStream;
 
980
      friend class oDataStream;
 
981
      friend class ::TestData;
 
982
      friend class MD5Buffer;
 
983
};
 
984
// reset alignment to default
 
985
#pragma pack()
 
986
 
 
987
 
 
988
class DataHelper {
 
989
   public:
 
990
      static const bool isCharHex[256];
 
991
};
 
992
 
 
993
static bool invokeDataInit = Data::init(DataLocalSize<RESIP_DATA_LOCAL_SIZE>(0));
 
994
 
 
995
inline bool Data::isHex(unsigned char c)
 
996
{
 
997
   return DataHelper::isCharHex[c];
 
998
}
 
999
 
 
1000
inline bool isEqualNoCase(const Data& left, const Data& right)
 
1001
{
 
1002
   return ( (left.size() == right.size()) &&
 
1003
            (strncasecmp(left.data(), right.data(), left.size()) == 0) );
 
1004
}
 
1005
 
 
1006
inline bool isTokenEqualNoCase(const Data& left, const Data& right)
 
1007
{
 
1008
   return left.caseInsensitiveTokenCompare(right);
 
1009
}
 
1010
 
 
1011
inline bool isLessThanNoCase(const Data& left, const Data& right)
 
1012
{
 
1013
   size_t minsize = resipMin( left.size(), right.size() );
 
1014
   int res = strncasecmp(left.data(), right.data(), minsize);
 
1015
 
 
1016
   if (res < 0)
 
1017
   {
 
1018
      return true;
 
1019
   }
 
1020
   else if (res > 0)
 
1021
   {
 
1022
      return false;
 
1023
   }
 
1024
   else
 
1025
   {
 
1026
      return left.size() < right.size();
 
1027
   }
 
1028
}
 
1029
 
 
1030
template<class Predicate> EncodeStream& 
 
1031
Data::escapeToStream(EncodeStream& str, Predicate shouldEscape) const
 
1032
{
 
1033
   static char hex[] = "0123456789ABCDEF";
 
1034
 
 
1035
   if (empty())
 
1036
   {
 
1037
      return str;
 
1038
   }
 
1039
   
 
1040
   const unsigned char* p = (unsigned char*)mBuf;
 
1041
   const unsigned char* e = (unsigned char*)mBuf + mSize;
 
1042
 
 
1043
   while (p < e)
 
1044
   {
 
1045
      // ?abr? Why is this special cased? Removing this code
 
1046
      // does not change the behavior of this method.
 
1047
      if (*p == '%' 
 
1048
          && e - p > 2 
 
1049
          && isHex(*(p+1)) 
 
1050
          && isHex(*(p+2)))
 
1051
      {
 
1052
         str.write((char*)p, 3);
 
1053
         p+=3;
 
1054
      }
 
1055
      else if (shouldEscape[*p])
 
1056
      {
 
1057
         int hi = (*p & 0xF0)>>4;
 
1058
         int low = (*p & 0x0F);
 
1059
 
 
1060
         str << '%' << hex[hi] << hex[low];
 
1061
         p++;
 
1062
      }
 
1063
      else
 
1064
      {
 
1065
         str.put(*p++);
 
1066
      }
 
1067
   }
 
1068
   return str;
 
1069
}
 
1070
 
 
1071
inline bool operator!=(const Data& lhs, const Data& rhs) { return !(lhs == rhs); }
 
1072
inline bool operator>(const Data& lhs, const Data& rhs) { return rhs < lhs; }
 
1073
inline bool operator<=(const Data& lhs, const Data& rhs) { return !(rhs < lhs); }
 
1074
inline bool operator>=(const Data& lhs, const Data& rhs) { return !(lhs < rhs); }
 
1075
inline bool operator!=(const Data& lhs, const char* rhs) { return !(lhs == rhs); }
 
1076
inline bool operator>(const Data& lhs, const char* rhs) { return rhs < lhs; }
 
1077
inline bool operator<=(const Data& lhs, const char* rhs) { return !(rhs < lhs); }
 
1078
inline bool operator>=(const Data& lhs, const char* rhs) { return !(lhs < rhs); }
 
1079
inline bool operator==(const char* lhs, const Data& rhs) { return rhs == lhs; }
 
1080
inline bool operator!=(const char* lhs, const Data& rhs) { return !(rhs == lhs); }
 
1081
inline bool operator>(const char* lhs, const Data& rhs) { return rhs < lhs; }
 
1082
inline bool operator<=(const char* lhs, const Data& rhs) { return !(rhs < lhs); }
 
1083
inline bool operator>=(const char* lhs, const Data& rhs) { return !(lhs < rhs); }
 
1084
#ifndef  RESIP_USE_STL_STREAMS
 
1085
EncodeStream& operator<<(EncodeStream& strm, const Data& d);
 
1086
#endif
 
1087
inline std::ostream& operator<<(std::ostream& strm, const Data& d)
 
1088
{
 
1089
   return strm.write(d.mBuf, d.mSize);
 
1090
}
 
1091
 
 
1092
 
 
1093
inline Data
 
1094
operator+(const char* c, const Data& d)
 
1095
{
 
1096
   return Data(c) + d;
 
1097
}
 
1098
 
 
1099
}
 
1100
 
 
1101
HashValue(resip::Data);
 
1102
 
 
1103
#endif
 
1104
 
 
1105
/* ====================================================================
 
1106
 * The Vovida Software License, Version 1.0 
 
1107
 * 
 
1108
 * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
 
1109
 * 
 
1110
 * Redistribution and use in source and binary forms, with or without
 
1111
 * modification, are permitted provided that the following conditions
 
1112
 * are met:
 
1113
 * 
 
1114
 * 1. Redistributions of source code must retain the above copyright
 
1115
 *    notice, this list of conditions and the following disclaimer.
 
1116
 * 
 
1117
 * 2. Redistributions in binary form must reproduce the above copyright
 
1118
 *    notice, this list of conditions and the following disclaimer in
 
1119
 *    the documentation and/or other materials provided with the
 
1120
 *    distribution.
 
1121
 * 
 
1122
 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
 
1123
 *    and "Vovida Open Communication Application Library (VOCAL)" must
 
1124
 *    not be used to endorse or promote products derived from this
 
1125
 *    software without prior written permission. For written
 
1126
 *    permission, please contact vocal@vovida.org.
 
1127
 *
 
1128
 * 4. Products derived from this software may not be called "VOCAL", nor
 
1129
 *    may "VOCAL" appear in their name, without prior written
 
1130
 *    permission of Vovida Networks, Inc.
 
1131
 * 
 
1132
 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
 
1133
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 
1134
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
 
1135
 * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
 
1136
 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
 
1137
 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
 
1138
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 
1139
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 
1140
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 
1141
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
1142
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
 
1143
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
 
1144
 * DAMAGE.
 
1145
 * 
 
1146
 * ====================================================================
 
1147
 * 
 
1148
 * This software consists of voluntary contributions made by Vovida
 
1149
 * Networks, Inc. and many individuals on behalf of Vovida Networks,
 
1150
 * Inc.  For more information on Vovida Networks, Inc., please see
 
1151
 * <http://www.vovida.org/>.
 
1152
 *
 
1153
 * vi: set shiftwidth=3 expandtab:
 
1154
 */