Coverage Report

Created: 2024-07-23 06:39

/src/resiprocate/rutil/Inserter.hxx
Line
Count
Source (jump to first uncovered line)
1
#if !defined(RESIP_INSERTER_HXX)
2
#define RESIP_INSERTER_HXX 
3
4
#include <iostream>
5
#include <utility>
6
#include <map>
7
#include <set>
8
#include <list>
9
#include <unordered_map>
10
#include <unordered_set>
11
#include <vector>
12
#include <deque>
13
#include "rutil/ResipAssert.h"
14
15
#include "rutil/compat.hxx"
16
#include "rutil/resipfaststreams.hxx"
17
18
/* 
19
Example of use Inserter
20
21
int
22
main(int argc, char** argv)
23
{
24
   std::vector<std::string> v;
25
   
26
   v.push_back("foo");
27
   v.push_back("bar");
28
   v.push_back("baz");
29
30
   std::cerr << Inserter(v) << std::endl;
31
   std::cerr << Inserter("nnn") << std::endl; // though you wouldn't bother
32
}
33
34
Example of use InserterP
35
InserterP - allows processing of collections with pointers to items
36
37
int
38
main(int argc, char** argv)
39
{
40
   std::vector<std::string*> v;
41
   
42
   v.push_back(new std::string("foo"));
43
   v.push_back(new std::string("bar"));
44
   v.push_back(new std::string("baz"));
45
46
   std::cerr << InserterP(v) << std::endl;
47
}
48
*/
49
50
namespace resip
51
{
52
53
static const char* leftanglebracket("<");
54
static const char* rightanglebracket(">");
55
static const char* leftsqbracket("[");
56
static const char* rightsqbracket("]");
57
static const char* sparrowsp(" -> ");
58
static const char* commaspace(", ");
59
60
/// Completely generic insert function
61
#ifdef REASONABLE_TEMPLATES
62
template <class T>
63
EncodeStream&
64
insert(EncodeStream& s, const T& t)
65
0
{
66
   // use native <<
67
0
   s << t;
68
0
   return s;
69
0
}
70
#endif
71
72
// specific collections, sigh
73
template <class T>
74
EncodeStream&
75
insert(EncodeStream& s, const std::vector <T>& c)
76
{
77
   s << leftsqbracket;
78
   for (typename std::vector <T>::const_iterator i = c.begin();
79
        i != c.end(); i++) 
80
   {
81
      if (i != c.begin()) 
82
      {
83
         s << commaspace;
84
      }
85
      // recurse
86
      insert(s, *i);
87
   }
88
   s << rightsqbracket;
89
   return s;
90
}
91
92
template <class T>
93
EncodeStream&
94
insert(EncodeStream& s, const std::deque<T>& c)
95
{
96
   s << leftsqbracket;
97
   for (typename std::deque <T>::const_iterator i = c.begin();
98
        i != c.end(); i++) 
99
   {
100
      if (i != c.begin()) 
101
      {
102
         s << commaspace;
103
      }
104
      // recurse
105
      insert(s, *i);
106
   }
107
   s << rightsqbracket;
108
   return s;
109
}
110
111
template <class T>
112
EncodeStream&
113
insert(EncodeStream& s, const std::list <T>& c)
114
0
{
115
0
   s << leftsqbracket;
116
0
   for (typename std::list <T>::const_iterator i = c.begin();
117
0
        i != c.end(); i++) 
118
0
   {
119
0
      if (i != c.begin()) 
120
0
      {
121
0
         s << commaspace;
122
0
      }
123
      // recurse
124
0
      insert(s, *i);
125
0
   }
126
0
   s << rightsqbracket;
127
0
   return s;
128
0
}
129
130
#if !defined(__INTEL_COMPILER)
131
template <class K, class C>
132
EncodeStream&
133
insert(EncodeStream& s, const std::set <K, C>& c)
134
{
135
   s << leftsqbracket;
136
   for (typename std::set <K, C>::const_iterator i = c.begin();
137
        i != c.end(); i++) 
138
   {
139
      if (i != c.begin()) 
140
      {
141
         s << commaspace;
142
      }
143
      insert(s, *i);
144
   }
145
   s << rightsqbracket;
146
   return s;
147
}
148
#endif
149
150
#if !defined(__INTEL_COMPILER)
151
template <class K, class C>
152
EncodeStream&
153
insert(EncodeStream& s, const std::multiset <K, C>& c)
154
{
155
   s << leftsqbracket;
156
   for (typename std::multiset <K, C>::const_iterator i = c.begin();
157
        i != c.end(); i++) 
158
   {
159
      if (i != c.begin()) 
160
      {
161
         s << commaspace;
162
      }
163
      insert(s, *i);
164
   }
165
   s << rightsqbracket;
166
   return s;
167
}
168
#endif
169
170
template <class K, class V, class H>
171
EncodeStream&
172
insert(EncodeStream& s, const std::unordered_map<K,V,H>& c)
173
0
{
174
0
   s << leftsqbracket;
175
0
   for (auto i = c.begin(); i != c.end(); i++) 
176
0
   {
177
0
      if (i != c.begin()) 
178
0
      {
179
0
         s << commaspace;
180
0
      }
181
0
      insert(s, i->first);
182
0
      s << sparrowsp;
183
0
      insert(s, i->second);      
184
0
   }
185
0
   s << rightsqbracket;
186
0
   return s;
187
0
}
188
189
template <class V, class H>
190
EncodeStream&
191
insert(EncodeStream& s, const std::unordered_set<V,H>& c)
192
{
193
   s << leftsqbracket;
194
   for (auto i = c.begin(); i != c.end(); i++) 
195
   {
196
      if (i != c.begin()) 
197
      {
198
         s << commaspace;
199
      }
200
      insert(s, *i);
201
   }
202
   s << rightsqbracket;
203
   return s;
204
}
205
206
// map
207
template <class K, class V, class H>
208
EncodeStream&
209
insert(EncodeStream& s, const std::map <K, V, H>& c)
210
{
211
   s << leftsqbracket;
212
   for (typename std::map<K,V, H>::const_iterator i = c.begin();
213
        i != c.end(); i++) 
214
   {
215
      if (i != c.begin()) 
216
      {
217
         s << commaspace;
218
      }
219
      insert(s, i->first);
220
      s << sparrowsp;
221
      insert(s, i->second);  
222
   }
223
   s << rightsqbracket;
224
   return s;
225
}
226
227
// special case for basic_string container
228
template <class T>
229
EncodeStream&
230
insert(EncodeStream& s, const std::basic_string<T>& str)
231
{
232
   // use native <<
233
   s << str;
234
   return s;
235
}
236
237
// special case for pair
238
template <class T, class U>
239
EncodeStream&
240
insert(EncodeStream& s, const std::pair<T, U>& p)
241
{
242
   // use native <<
243
   s << leftanglebracket << p.first << commaspace << p.second << rightanglebracket;
244
   return s;
245
}
246
247
/**
248
   @brief Allows a (possibly recursive) container of anything with operator<< to 
249
   be dumped to a stream.
250
251
   
252
   This is particularly useful within a Log call.
253
   e.g.
254
   @code
255
   void logNameAddrs(vector<resip::NameAddr>& contacts)
256
   {
257
      DebugLog(<< "Contacts: " << Inserter(contacts));
258
   }
259
   @endcode
260
261
   @see Inserter()
262
 */
263
template <class T>
264
class InserterClass
265
{
266
   public:
267
      InserterClass(const T& t)
268
         : _t(t)
269
0
      {}
Unexecuted instantiation: resip::InserterClass<std::__1::unordered_map<resip::Data, resip::Data, std::__1::hash<resip::Data>, std::__1::equal_to<resip::Data>, std::__1::allocator<std::__1::pair<resip::Data const, resip::Data> > > >::InserterClass(std::__1::unordered_map<resip::Data, resip::Data, std::__1::hash<resip::Data>, std::__1::equal_to<resip::Data>, std::__1::allocator<std::__1::pair<resip::Data const, resip::Data> > > const&)
Unexecuted instantiation: resip::InserterClass<std::__1::list<resip::Data, std::__1::allocator<resip::Data> > >::InserterClass(std::__1::list<resip::Data, std::__1::allocator<resip::Data> > const&)
270
      
271
      const T& _t;
272
};
273
274
/// Function to allow an Inserter to be used directly with a stream
275
template <class T>
276
EncodeStream&
277
operator<<(EncodeStream& s, const InserterClass<T>& inserter)
278
0
{
279
#if defined(WIN32) && defined(_MSC_VER) && (_MSC_VER < 1310)
280
  resip_assert(0); // CJ - really need to fix this
281
  return s;
282
#else
283
0
   return insert(s, inserter._t);
284
0
#endif
285
0
}
Unexecuted instantiation: std::__1::basic_ostream<char, std::__1::char_traits<char> >& resip::operator<< <std::__1::unordered_map<resip::Data, resip::Data, std::__1::hash<resip::Data>, std::__1::equal_to<resip::Data>, std::__1::allocator<std::__1::pair<resip::Data const, resip::Data> > > >(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, resip::InserterClass<std::__1::unordered_map<resip::Data, resip::Data, std::__1::hash<resip::Data>, std::__1::equal_to<resip::Data>, std::__1::allocator<std::__1::pair<resip::Data const, resip::Data> > > > const&)
Unexecuted instantiation: std::__1::basic_ostream<char, std::__1::char_traits<char> >& resip::operator<< <std::__1::list<resip::Data, std::__1::allocator<resip::Data> > >(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, resip::InserterClass<std::__1::list<resip::Data, std::__1::allocator<resip::Data> > > const&)
286
287
/// Templatized function to construct an instance of InserterClass for a
288
/// container to be inserted. The function induces the template type, saving the
289
/// user from thinking about it.
290
template <class T>
291
InserterClass<T>
292
Inserter(const T& t)
293
0
{
294
0
   return InserterClass<T>(t);
295
0
}
Unexecuted instantiation: resip::InserterClass<std::__1::unordered_map<resip::Data, resip::Data, std::__1::hash<resip::Data>, std::__1::equal_to<resip::Data>, std::__1::allocator<std::__1::pair<resip::Data const, resip::Data> > > > resip::Inserter<std::__1::unordered_map<resip::Data, resip::Data, std::__1::hash<resip::Data>, std::__1::equal_to<resip::Data>, std::__1::allocator<std::__1::pair<resip::Data const, resip::Data> > > >(std::__1::unordered_map<resip::Data, resip::Data, std::__1::hash<resip::Data>, std::__1::equal_to<resip::Data>, std::__1::allocator<std::__1::pair<resip::Data const, resip::Data> > > const&)
Unexecuted instantiation: resip::InserterClass<std::__1::list<resip::Data, std::__1::allocator<resip::Data> > > resip::Inserter<std::__1::list<resip::Data, std::__1::allocator<resip::Data> > >(std::__1::list<resip::Data, std::__1::allocator<resip::Data> > const&)
296
297
298
299
///
300
///  The following functions are more or less the same as the above, but add P to the naming
301
///  and treat data items as pointers
302
///
303
304
305
306
/// Completely generic insert function
307
#ifdef REASONABLE_TEMPLATES
308
template <class T>
309
EncodeStream&
310
insertP(EncodeStream& s, const T& t)
311
{
312
   // use native <<
313
   s << *t;
314
   return s;
315
}
316
#endif
317
318
// specific collections, sigh
319
template <class T>
320
EncodeStream&
321
insertP(EncodeStream& s, const std::vector <T>& c)
322
{
323
   s << leftsqbracket;
324
   for (typename std::vector <T>::const_iterator i = c.begin();
325
        i != c.end(); i++) 
326
   {
327
      if (i != c.begin()) 
328
      {
329
         s << commaspace;
330
      }
331
      // recurse
332
      insert(s, *(*i));
333
   }
334
   s << rightsqbracket;
335
   return s;
336
}
337
338
template <class T>
339
EncodeStream&
340
insertP(EncodeStream& s, const std::deque<T>& c)
341
{
342
   s << leftsqbracket;
343
   for (typename std::deque <T>::const_iterator i = c.begin();
344
        i != c.end(); i++) 
345
   {
346
      if (i != c.begin()) 
347
      {
348
         s << commaspace;
349
      }
350
      // recurse
351
      insert(s, *(*i));
352
   }
353
   s << rightsqbracket;
354
   return s;
355
}
356
357
template <class T>
358
EncodeStream&
359
insertP(EncodeStream& s, const std::list <T>& c)
360
{
361
   s << leftsqbracket;
362
   for (typename std::list <T>::const_iterator i = c.begin();
363
        i != c.end(); i++) 
364
   {
365
      if (i != c.begin()) 
366
      {
367
         s << commaspace;
368
      }
369
      // recurse
370
      insert(s, *(*i));
371
   }
372
   s << rightsqbracket;
373
   return s;
374
}
375
376
#if !defined(__INTEL_COMPILER)
377
template <class K, class C>
378
EncodeStream&
379
insertP(EncodeStream& s, const std::set <K, C>& c)
380
{
381
   s << leftsqbracket;
382
   for (typename std::set <K, C>::const_iterator i = c.begin();
383
        i != c.end(); i++) 
384
   {
385
      if (i != c.begin()) 
386
      {
387
         s << commaspace;
388
      }
389
      insert(s, *(*i));
390
   }
391
   s << rightsqbracket;
392
   return s;
393
}
394
#endif
395
396
#if !defined(__INTEL_COMPILER)
397
template <class K, class C>
398
EncodeStream&
399
insertP(EncodeStream& s, const std::multiset <K, C>& c)
400
{
401
   s << leftsqbracket;
402
   for (typename std::multiset <K, C>::const_iterator i = c.begin();
403
        i != c.end(); i++) 
404
   {
405
      if (i != c.begin()) 
406
      {
407
         s << commaspace;
408
      }
409
      insert(s, *(*i));
410
   }
411
   s << rightsqbracket;
412
   return s;
413
}
414
#endif
415
416
template <class K, class V, class H>
417
EncodeStream&
418
insertP(EncodeStream& s, const std::unordered_map<K,V,H>& c)
419
{
420
   s << leftsqbracket;
421
   for (auto i = c.begin(); i != c.end(); i++) 
422
   {
423
      if (i != c.begin()) 
424
      {
425
         s << commaspace;
426
      }
427
      insert(s, i->first);
428
      s << sparrowsp;
429
      insert(s, *i->second);      
430
   }
431
   s << rightsqbracket;
432
   return s;
433
}
434
435
template <class V, class H>
436
EncodeStream&
437
insertP(EncodeStream& s, const std::unordered_set<V,H>& c)
438
{
439
   s << leftsqbracket;
440
   for (auto i = c.begin(); i != c.end(); i++) 
441
   {
442
      if (i != c.begin()) 
443
      {
444
         s << commaspace;
445
      }
446
      insert(s, *(*i));
447
   }
448
   s << rightsqbracket;
449
   return s;
450
}
451
452
// map
453
template <class K, class V, class H>
454
EncodeStream&
455
insertP(EncodeStream& s, const std::map <K, V, H>& c)
456
{
457
   s << leftsqbracket;
458
   for (typename std::map<K,V, H>::const_iterator i = c.begin();
459
        i != c.end(); i++) 
460
   {
461
      if (i != c.begin()) 
462
      {
463
         s << commaspace;
464
      }
465
      insert(s, i->first);
466
      s << sparrowsp;
467
      insert(s, *i->second);  
468
   }
469
   s << rightsqbracket;
470
   return s;
471
}
472
473
// special case for basic_string container
474
template <class T>
475
EncodeStream&
476
insertP(EncodeStream& s, const std::basic_string<T>& str)
477
{
478
   // use native <<
479
   s << str;
480
   return s;
481
}
482
483
// special case for pair
484
template <class T, class U>
485
EncodeStream&
486
insertP(EncodeStream& s, const std::pair<T, U>& p)
487
{
488
   // use native <<
489
   s << leftanglebracket << *p.first << commaspace << *p.second << rightanglebracket;
490
   return s;
491
}
492
493
/**
494
   @brief Allows a (possibly recursive) container of anything with operator<< to 
495
   be dumped to a stream.
496
497
   
498
   This is particularly useful within a Log call.
499
   e.g.
500
   @code
501
   void logNameAddrs(vector<resip::NameAddr>& contacts)
502
   {
503
      DebugLog(<< "Contacts: " << Inserter(contacts));
504
   }
505
   @endcode
506
507
   @see Inserter()
508
 */
509
template <class T>
510
class InserterPClass
511
{
512
   public:
513
      InserterPClass(const T& t)
514
         : _t(t)
515
      {}
516
      
517
      const T& _t;
518
};
519
520
/// Function to allow an Inserter to be used directly with a stream
521
template <class T>
522
EncodeStream&
523
operator<<(EncodeStream& s, const InserterPClass<T>& inserter)
524
{
525
#if defined(WIN32) && defined(_MSC_VER) && (_MSC_VER < 1310)
526
  resip_assert(0); // CJ - really need to fix this
527
  return s;
528
#else
529
   return insertP(s, inserter._t);
530
#endif
531
}
532
533
/// Templatized function to construct an instance of InserterClass for a
534
/// container to be inserted. The function induces the template type, saving the
535
/// user from thinking about it.
536
template <class T>
537
InserterPClass<T>
538
InserterP(const T& t)
539
{
540
   return InserterPClass<T>(t);
541
}
542
 
543
} // resip
544
545
#endif
546
547
/* ====================================================================
548
 * The Vovida Software License, Version 1.0 
549
 * 
550
 * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
551
 * 
552
 * Redistribution and use in source and binary forms, with or without
553
 * modification, are permitted provided that the following conditions
554
 * are met:
555
 * 
556
 * 1. Redistributions of source code must retain the above copyright
557
 *    notice, this list of conditions and the following disclaimer.
558
 * 
559
 * 2. Redistributions in binary form must reproduce the above copyright
560
 *    notice, this list of conditions and the following disclaimer in
561
 *    the documentation and/or other materials provided with the
562
 *    distribution.
563
 * 
564
 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
565
 *    and "Vovida Open Communication Application Library (VOCAL)" must
566
 *    not be used to endorse or promote products derived from this
567
 *    software without prior written permission. For written
568
 *    permission, please contact vocal@vovida.org.
569
 *
570
 * 4. Products derived from this software may not be called "VOCAL", nor
571
 *    may "VOCAL" appear in their name, without prior written
572
 *    permission of Vovida Networks, Inc.
573
 * 
574
 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
575
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
576
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
577
 * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
578
 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
579
 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
580
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
581
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
582
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
583
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
584
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
585
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
586
 * DAMAGE.
587
 * 
588
 * ====================================================================
589
 * 
590
 * This software consists of voluntary contributions made by Vovida
591
 * Networks, Inc. and many individuals on behalf of Vovida Networks,
592
 * Inc.  For more information on Vovida Networks, Inc., please see
593
 * <http://www.vovida.org/>.
594
 *
595
 */