/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 | | |