Coverage Report

Created: 2026-06-07 06:36

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/resiprocate/rutil/resipfaststreams.hxx
Line
Count
Source
1
#if !defined(RESIP_RESIPFASTSTREAMS_HXX)
2
#define RESIP_RESIPFASTSTREAMS_HXX
3
/*! \file resipfaststreams.hxx
4
    \brief Replaces STL streams for general encoding purposes.
5
6
    #define RESIP_USE_STL_STREAMS will use the STL for stream encoding (std::ostream).  Undefining RESIP_USE_STL_STREAMS will
7
      cause resip to use the alternative stream handling defined in this file for encoding objects.
8
*/
9
#define RESIP_USE_STL_STREAMS
10
11
#ifdef HAVE_CONFIG_H
12
#include "config.h"
13
#endif
14
15
#include <cinttypes>
16
17
#include <iostream> //for std::endl, std::cerr, etc.
18
#include <stdio.h> //for snprintf
19
20
#include "rutil/ResipAssert.h"
21
#include "rutil/compat.hxx"
22
23
#include <memory>
24
25
namespace resip
26
{
27
28
class ResipStreamBuf
29
{
30
   public:
31
      ResipStreamBuf(void)
32
0
      {}
33
      virtual ~ ResipStreamBuf(void)
34
0
      {}
35
      virtual size_t writebuf(const char *s, size_t count) = 0;
36
      virtual size_t readbuf(char *buf, size_t count) = 0;
37
      virtual size_t putbuf(char ch) = 0;
38
      virtual void flushbuf(void)=0;
39
      virtual uint64_t tellpbuf(void)=0;
40
};
41
42
class ResipBasicIOStream
43
{
44
   public:
45
      ResipBasicIOStream(void):good_(false),eof_(true)
46
0
      {}
47
      ~ResipBasicIOStream(void)
48
0
      {}
49
50
      bool good(void) const
51
0
      {
52
0
         return good_;
53
0
      }
54
      bool eof(void) const
55
0
      {
56
0
         return eof_;
57
0
      }
58
      void clear(void) const
59
0
      {}
60
61
   protected:
62
      bool good_;
63
      bool eof_;
64
};
65
66
/** std::ostream replacement.
67
*/
68
class ResipFastOStream : public ResipBasicIOStream
69
{
70
   public:
71
      ResipFastOStream(ResipStreamBuf *buf):buf_(buf)
72
0
      {
73
0
         good_ = true;
74
0
      }
75
      virtual ~ResipFastOStream(void)
76
0
      {}
77
78
      virtual uint64_t tellp(void)
79
0
      {
80
0
         if (rdbuf())
81
0
         {
82
0
            return rdbuf()->tellpbuf();
83
0
         }
84
0
         return 0;
85
0
      }
86
87
      ResipStreamBuf * rdbuf(void) const
88
0
      {
89
0
         return buf_;
90
0
      }
91
92
      void rdbuf(ResipStreamBuf *buf)
93
0
      {
94
0
         buf_ = buf;
95
0
      }
96
97
      ResipFastOStream & flush(void)
98
0
      {
99
0
         if (rdbuf())
100
0
         {
101
0
            rdbuf()->flushbuf();
102
0
         }
103
0
         return *this;
104
0
      }
105
106
      ResipFastOStream &write(const char *s, size_t count)
107
0
      {
108
0
         if (rdbuf())
109
0
         {
110
0
            rdbuf()->writebuf(s,count);
111
0
         }
112
0
         return *this;
113
0
      }
114
115
      ResipFastOStream &put(char ch)
116
0
      {
117
0
         if (rdbuf())
118
0
         {
119
0
            rdbuf()->putbuf(ch);
120
0
         }
121
0
         return *this;
122
0
      }
123
124
      ResipFastOStream& operator<<(bool b)
125
0
      {
126
0
         //int i = (b == true) ? (1):(0);
127
0
         *this<<(static_cast<int32_t>(b));
128
0
         return *this;
129
0
      }
130
131
      ResipFastOStream& operator<<(int16_t i)
132
0
      {
133
0
         *this<<(static_cast<int32_t>(i));
134
0
         return *this;
135
0
      }
136
137
      ResipFastOStream& operator<<(uint16_t ui)
138
0
      {
139
0
         *this<<(static_cast<uint32_t>(ui));
140
0
         return *this;
141
0
      }
142
143
      ResipFastOStream& operator<<(int32_t l)
144
0
      {
145
0
         if (!buf_)
146
0
         {
147
0
            return *this;
148
0
         }
149
0
         char buf[33];
150
0
         snprintf(buf,33,"%" PRId32,l);
151
0
         size_t count = strlen(buf);
152
0
         if (buf_->writebuf(buf,count) < count)
153
0
         {
154
0
            good_ = false;
155
0
         }
156
0
157
0
         return *this;
158
0
      }
159
160
      ResipFastOStream& operator<<(uint32_t ul)
161
0
      {
162
0
         if (!buf_)
163
0
         {
164
0
            return *this;
165
0
         }
166
0
         char buf[33];
167
0
         snprintf(buf,33,"%" PRIu32,ul);
168
0
         size_t count = strlen(buf);
169
0
         if (buf_->writebuf(buf,count) < count)
170
0
         {
171
0
            good_ = false;
172
0
         }
173
0
174
0
         return *this;
175
0
      }
176
177
      ResipFastOStream& operator<<(int64_t i64)
178
0
      {
179
0
         if (!buf_)
180
0
         {
181
0
            return *this;
182
0
         }
183
0
184
0
         char buf[66];
185
0
         snprintf(buf,66,"%" PRId64,i64);
186
0
187
0
         size_t count = strlen(buf);
188
0
         if (buf_->writebuf(buf,count) < count)
189
0
         {
190
0
            good_ = false;
191
0
         }
192
0
193
0
         return *this;
194
0
      }
195
196
      ResipFastOStream& operator<<(uint64_t ui64)
197
0
      {
198
0
         if (!buf_)
199
0
         {
200
0
            return *this;
201
0
         }
202
0
203
0
         char buf[66];
204
0
         snprintf(buf,66,"%" PRIu64,ui64);
205
0
206
0
         size_t count = strlen(buf);
207
0
         if (buf_->writebuf(buf,count) < count)
208
0
         {
209
0
            good_ = false;
210
0
         }
211
0
212
0
         return *this;
213
0
      }
214
215
      ResipFastOStream& operator<<(float f)
216
0
      {
217
0
         *this<< (static_cast<double>(f));
218
0
219
0
         return *this;
220
0
      }
221
222
      ResipFastOStream& operator<<(double d)
223
0
      {
224
0
         if (!buf_)
225
0
         {
226
0
            return *this;
227
0
         }
228
0
229
0
         char buf[_CVTBUFSIZE];
230
0
         GCVT(d,6,buf,_CVTBUFSIZE);//6 significant digits is the default for %f
231
0
         size_t count = strlen(buf);
232
0
#ifndef WIN32 
233
0
         //not using the non-standard microsoft conversion functions
234
0
         //remove any trailing zeros.  Note that resipfastreams does not support STL stream width or precision
235
0
         //modifiers
236
0
         size_t idx=0;
237
0
         for (; count > 1; count--)
238
0
         {
239
0
            idx = count-1;
240
0
            if (buf[idx] != '0' && buf[idx] != '.')
241
0
            {
242
0
               break;
243
0
            }
244
0
         }
245
0
#endif
246
0
         if (buf_->writebuf(buf,count) < count)
247
0
         {
248
0
            good_ = false;
249
0
         }
250
0
251
0
         return *this;
252
0
      }
253
254
      ResipFastOStream& operator<<(const void *vp)
255
0
      {
256
0
         if (!buf_)
257
0
         {
258
0
            return *this;
259
0
         }
260
0
261
0
         char buf[32];
262
0
         SNPRINTF_1(buf,32,_TRUNCATE,"%p",vp);
263
0
         size_t count = strlen(buf);
264
0
         if (buf_->writebuf(buf,count) < count)
265
0
         {
266
0
            good_ = false;
267
0
         }
268
0
269
0
         return *this;
270
0
      }
271
#ifdef WIN32
272
      ResipFastOStream& operator<<(std::ostream& (__cdecl *_Pfn)(std::ostream&))
273
#else
274
      ResipFastOStream& operator<<(std::ostream& (*_Pfn)(std::ostream &))
275
#endif
276
0
      {
277
0
         if (!buf_)
278
0
         {
279
0
            return *this;
280
0
         }
281
0
282
0
         if (_Pfn == static_cast<std::ostream& (*)(std::ostream&)>(std::endl))
283
0
         {
284
0
            if (buf_->writebuf("\n",1) < 1)
285
0
            {
286
0
               good_ = false;
287
0
            }
288
0
         }
289
0
         else
290
0
         {
291
0
            resip_assert(0);
292
0
         }
293
0
         return *this;
294
0
      }
295
296
   private:
297
      ResipStreamBuf *buf_;
298
};
299
300
301
inline resip::ResipFastOStream& operator<<(resip::ResipFastOStream& ostr, const char *str)
302
0
{
303
0
   ostr.write(str,strlen(str));
304
0
305
0
   return ostr;
306
0
}
307
308
inline resip::ResipFastOStream& operator<<(resip::ResipFastOStream& ostr, char ch)
309
0
{
310
0
   ostr.put(ch);
311
0
312
0
   return ostr;
313
0
}
314
315
inline resip::ResipFastOStream& operator<<(resip::ResipFastOStream& ostr, unsigned char ch)
316
0
{
317
0
   ostr.put((char)ch);
318
0
319
0
   return ostr;
320
0
}
321
322
inline resip::ResipFastOStream& operator<<(resip::ResipFastOStream& ostr, const unsigned char *str)
323
0
{
324
0
   ostr.write((const char *)str,strlen((const char *)str));
325
0
326
0
   return ostr;
327
0
}
328
329
inline resip::ResipFastOStream& operator<<(resip::ResipFastOStream& ostr, signed char ch)
330
0
{
331
0
   ostr.put((char)ch);
332
0
333
0
   return ostr;
334
0
}
335
336
inline resip::ResipFastOStream& operator<<(resip::ResipFastOStream& ostr, const signed char *str)
337
0
{
338
0
   ostr.write((const char *)str,strlen((const char *)str));
339
0
340
0
   return ostr;
341
0
}
342
343
inline resip::ResipFastOStream & operator<<(resip::ResipFastOStream &ostr, const std::string &str)
344
0
{
345
0
   ostr.write(str.c_str(),str.size());
346
0
347
0
   return ostr;
348
0
}
349
350
template <typename T>
351
ResipFastOStream& operator<<(ResipFastOStream& os, const std::shared_ptr<T>& ptr)
352
{
353
   os << ptr.get();
354
   return os;
355
}
356
357
/** std::istream replacement
358
*/
359
class ResipFastIStream : public ResipBasicIOStream
360
{
361
   public:
362
      ResipFastIStream(ResipStreamBuf *buf):buf_(buf)
363
0
      {}
364
      virtual ~ResipFastIStream(void)
365
0
      {}
366
367
      ResipStreamBuf * rdbuf(void) const
368
0
      {
369
0
         return buf_;
370
0
      }
371
372
      ResipFastIStream &read(char *s, size_t count)
373
0
      {
374
0
         if (rdbuf())
375
0
         {
376
0
            rdbuf()->readbuf(s,count);
377
0
         }
378
0
         return *this;
379
0
      }
380
381
   private:
382
      ResipStreamBuf *buf_;
383
};
384
385
/** Used to replace std::cerr, std::cout, etc.
386
*/
387
class ResipStdBuf : public ResipStreamBuf
388
{
389
   public:
390
      typedef enum BufType
391
      {
392
         null,
393
         stdCerr,
394
         stdCout
395
      } BufType;
396
397
      ResipStdBuf(BufType type)
398
            :type_(type)
399
0
      {}
400
401
      ~ResipStdBuf(void)
402
0
      {}
403
404
      virtual size_t writebuf(const char *s, size_t count)
405
0
      {
406
0
         switch (type_)
407
0
         {
408
0
            case stdCerr:
409
0
            {
410
0
               std::cerr << s;
411
0
               break;
412
0
            }
413
0
            case stdCout:
414
0
            {
415
0
               std::cout << s;
416
0
               break;
417
0
            }
418
0
            default:
419
0
               break;
420
0
         }
421
0
         return count;
422
0
      }
423
      virtual size_t readbuf(char *buf, size_t count)
424
0
      {
425
0
         return 0;
426
0
      }
427
      virtual size_t putbuf(char ch)
428
0
      {
429
0
         return writebuf(&ch,1);
430
0
      }
431
      virtual void flushbuf(void)
432
0
      {}
433
      virtual uint64_t tellpbuf(void)
434
0
      {
435
0
         return 0;
436
0
      }
437
438
   private:
439
      BufType type_;
440
};
441
442
/** A direct replacement for std::cout, std::cerr, etc.
443
*/
444
class ResipStdCOStream: public ResipFastOStream
445
{
446
   public:
447
      ResipStdCOStream(ResipStdBuf::BufType type)
448
            :ResipFastOStream(0),buf_(type)
449
0
      {
450
0
         rdbuf(&buf_);
451
0
      }
452
453
      ~ResipStdCOStream(void)
454
0
      {}
455
456
   private:
457
      ResipStdBuf buf_;
458
};
459
460
#ifdef  RESIP_USE_STL_STREAMS
461
704
#define EncodeStream std::ostream
462
0
#define DecodeStream std::istream
463
0
#define resipCerr std::cerr
464
#define resipCout std::cout
465
#else
466
#define EncodeStream resip::ResipFastOStream
467
#define DecodeStream resip::ResipFastIStream
468
extern ResipStdCOStream resipFastCerr;
469
extern ResipStdCOStream resipFastCout;
470
#define resipCerr resip::resipFastCerr
471
#define resipCout resip::resipFastCout
472
#endif
473
extern ResipStdCOStream resipFastNull;
474
475
} //namespace resip
476
477
#endif //RESIP_RESIPFASTSTREAMS_HXX
478
479
/* ====================================================================
480
 * The Vovida Software License, Version 1.0
481
 *
482
 * Copyright (c) 2005.   All rights reserved.
483
 *
484
 * Redistribution and use in source and binary forms, with or without
485
 * modification, are permitted provided that the following conditions
486
 * are met:
487
 *
488
 * 1. Redistributions of source code must retain the above copyright
489
 *    notice, this list of conditions and the following disclaimer.
490
 *
491
 * 2. Redistributions in binary form must reproduce the above copyright
492
 *    notice, this list of conditions and the following disclaimer in
493
 *    the documentation and/or other materials provided with the
494
 *    distribution.
495
 *
496
 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
497
 *    and "Vovida Open Communication Application Library (VOCAL)" must
498
 *    not be used to endorse or promote products derived from this
499
 *    software without prior written permission. For written
500
 *    permission, please contact vocal@vovida.org.
501
 *
502
 * 4. Products derived from this software may not be called "VOCAL", nor
503
 *    may "VOCAL" appear in their name, without prior written
504
 *    permission of Vovida Networks, Inc.
505
 *
506
 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
507
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
508
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
509
 * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
510
 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
511
 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
512
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
513
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
514
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
515
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
516
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
517
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
518
 * DAMAGE.
519
 *
520
 * ====================================================================
521
 *
522
 * This software consists of voluntary contributions made by Vovida
523
 * Networks, Inc. and many individuals on behalf of Vovida Networks,
524
 * Inc.  For more information on Vovida Networks, Inc., please see
525
 * <http://www.vovida.org/>.
526
 *
527
 */
528
529
530
531