reSIProcate
SIP stack, Dialog Usage Manager and related libraries
Loading...
Searching...
No Matches
AbstractDb.cxx
Go to the documentation of this file.
1#include "rutil/ResipAssert.h"
2
3#include "rutil/Data.hxx"
7#include "rutil/Logger.hxx"
8
9
10#include "repro/UserStore.hxx"
11#include "repro/AbstractDb.hxx"
12
13
14using namespace resip;
15using namespace repro;
16using namespace std;
17
18#define RESIPROCATE_SUBSYSTEM Subsystem::REPRO
19
20#define REPRO_DB_VERSION_USERS 3
21
22static void
24{
25 short len = (short)data.size();
26 s.write( (char*)(&len) , sizeof( len ) );
27 s.write( data.data(), len );
28}
29
30
31static void
33{
34 data.clear();
35
36 if(s.eof()) return;
37
38 short len;
39 s.read((char*)(&len), sizeof(len));
40 if(s.eof()) return;
41
42 // [TODO] This is probably OK for now, but we can do better than this.
43 if (len > 8192)
44 {
45 ErrLog( << "Tried to decode a database record that was much larger (>8k) than expected. Returning an empty Data instead." );
46 return;
47 }
48
49 s.read(data.getBuf(len), len);
50}
51
52
56
57
61
62
63Data
65{
66 return dbNextKey(table,true/*first*/);
67}
68
69
70bool
72 const Data& key,
73 Data& data,
74 bool forUpdate)
75{
76 return dbNextRecord(table, key, data, forUpdate, true/*first*/);
77}
78
79
80// Callback used by BerkeleyDb for secondary table support. Returns key to use in
81// secondary database table
82// secondaryKey should point to persistent data (ie. typically something from data itself)
83int
85 const Key& key,
86 const Data& data,
87 void** secondaryKey,
88 unsigned int* secondaryKeyLen)
89{
90 if(table == SiloTable)
91 {
92 // Secondary Key for Silo table is DestUri
93 Data nonConstData(Data::Share, data.data(), data.size());
94 iDataStream s(nonConstData);
95
96 short version;
97 resip_assert(sizeof(version) == 2);
98 s.read((char*)(&version), sizeof(version));
99 resip_assert(version == 1);
100 if (version == 1)
101 {
102 // DestUri is first element after version
103 short len;
104 s.read( (char*)(&len), sizeof(len));
105 *secondaryKeyLen = (unsigned int)len;
106 *secondaryKey = (void*)(nonConstData.data() + (sizeof(version)+sizeof(len)));
107 return 0;
108 }
109 }
110 return -1;
111}
112
113
114void
116{
117 oDataStream s(data);
118
119 short version = REPRO_DB_VERSION_USERS;
120 resip_assert( sizeof( version) == 2 );
121 s.write( (char*)(&version) , sizeof(version) );
122
123 encodeString( s, rec.user );
124 encodeString( s, rec.domain);
125 encodeString( s, rec.realm);
126 encodeString( s, rec.passwordHash);
128 encodeString( s, rec.name);
129 encodeString( s, rec.email);
131 s.flush();
132}
133
134bool
136{
137 resip_assert( !key.empty() );
138
139 Data data;
140 encodeUser(rec, data);
141
142 return dbWriteRecord(UserTable,key,data);
143}
144
145
146void
151
152
155{
157 Data data;
158 bool stat = dbReadRecord( UserTable, key, data );
159 if ( !stat )
160 {
161 return rec;
162 }
163 if ( data.empty() )
164 {
165 return rec;
166 }
167
168 iDataStream s(data);
169
170 short version;
171 resip_assert( sizeof(version) == 2 );
172 s.read( (char*)(&version), sizeof(version) );
173
174 if ( version == REPRO_DB_VERSION_USERS )
175 {
176 decodeString(s, rec.user);
177 decodeString(s, rec.domain);
178 decodeString(s, rec.realm);
181 decodeString(s, rec.name);
182 decodeString(s, rec.email);
184 }
185 else if ( version == 2 )
186 {
187 // We can read from the older version DB, but the entry
188 // will be written back in the new format with
189 // passwordHashAlt blank
190 decodeString(s, rec.user);
191 decodeString(s, rec.domain);
192 decodeString(s, rec.realm);
194 decodeString(s, rec.name);
195 decodeString(s, rec.email);
198 }
199 else
200 {
201 // unknown version
202 ErrLog( <<"Data in user database with unknown version " << version );
203 ErrLog( <<"record size is " << data.size() );
204 }
205
206 return rec;
207}
208
209
210Data
212{
214
215 return rec.passwordHash;
216}
217
218
224
225
231
232
233bool
235{
236 resip_assert( !key.empty() );
237
238 Data data;
239 {
240 oDataStream s(data);
241
242 short version=1;
243 resip_assert( sizeof( version) == 2 );
244 s.write( (char*)(&version) , sizeof(version) );
245
246 encodeString( s, rec.peerName );
248
249 s.flush();
250 }
251
252 return dbWriteRecord(TlsPeerIdentityTable,key,data);
253}
254
255
256void
261
262
265{
267 Data data;
268 bool stat = dbReadRecord( TlsPeerIdentityTable, key, data );
269 if ( !stat )
270 {
271 return rec;
272 }
273 if ( data.empty() )
274 {
275 return rec;
276 }
277
278 iDataStream s(data);
279
280 short version;
281 resip_assert( sizeof(version) == 2 );
282 s.read( (char*)(&version), sizeof(version) );
283
284 if ( version == 1 )
285 {
286 decodeString(s, rec.peerName);
288 }
289 else
290 {
291 // unknown version
292 ErrLog( <<"Data in TlsPeerIdentity database with unknown version " << version );
293 ErrLog( <<"record size is " << data.size() );
294 }
295
296 return rec;
297}
298
299
300bool
301AbstractDb::isAuthorized(const std::set<resip::Data>& peerNames, const std::set<resip::Data>& identities) const
302{
303 // FIXME
304 resip_assert("TlsPeerIdentity not implemented for this database backend");
305 return false;
306}
307
308
314
315
321
322
323void
325{
326 oDataStream s(data);
327
328 short version=1;
329 resip_assert( sizeof( version) == 2 );
330 s.write( (char*)(&version) , sizeof(version) );
331
332 encodeString( s, rec.mMethod );
333 encodeString( s, rec.mEvent );
336 s.write( (char*)(&rec.mOrder) , sizeof( rec.mOrder ) );
337 resip_assert( sizeof( rec.mOrder) == 2 );
338
340
341 s.flush();
342}
343
344
345bool
347 const AbstractDb::RouteRecord& rec )
348{
349 resip_assert( !key.empty() );
350
351 Data data;
352 encodeRoute(rec, data);
353
354 return dbWriteRecord( RouteTable, key, data );
355}
356
357
358void
363
364
367{
369 Data data;
370 bool stat = dbReadRecord( RouteTable, key, data );
371 if ( !stat )
372 {
373 return rec;
374 }
375 if ( data.empty() )
376 {
377 return rec;
378 }
379
380 iDataStream s(data);
381
382 short version;
383 resip_assert( sizeof(version) == 2 );
384 s.read( (char*)(&version), sizeof(version) );
385
386 if ( version == 1 )
387 {
388 decodeString(s, rec.mMethod);
389 decodeString(s, rec.mEvent);
392 s.read( (char*)(&rec.mOrder), sizeof(rec.mOrder) );
393 resip_assert( sizeof( rec.mOrder) == 2 );
394 }
395 else
396 {
397 // unknown version
398 ErrLog( <<"Data in route database with unknown version " << version );
399 ErrLog( <<"record size is " << data.size() );
400 }
401
402 return rec;
403}
404
405
408{
410
412 while ( !key.empty() )
413 {
415
416 ret.push_back(rec);
417
418 key = nextRouteKey();
419 }
420
421 return ret;
422}
423
424
430
431
437
438
439bool
441 const AbstractDb::AclRecord& rec )
442{
443 resip_assert( !key.empty() );
444
445 Data data;
446 {
447 oDataStream s(data);
448
449 short version=1;
450 resip_assert( sizeof( version) == 2 );
451 s.write( (char*)(&version) , sizeof(version) );
452
453 encodeString( s, rec.mTlsPeerName );
454 encodeString( s, rec.mAddress );
455 s.write( (char*)(&rec.mMask) , sizeof( rec.mMask ) );
456 s.write( (char*)(&rec.mPort) , sizeof( rec.mPort ) );
457 s.write( (char*)(&rec.mFamily) , sizeof( rec.mFamily ) );
458 s.write( (char*)(&rec.mTransport) , sizeof( rec.mTransport ) );
459
460 s.flush();
461 }
462
463 return dbWriteRecord( AclTable, key, data );
464}
465
466
467void
469{
470 dbEraseRecord (AclTable, key);
471}
472
473
476{
478 Data data;
479 bool stat = dbReadRecord( AclTable, key, data );
480 if ( !stat )
481 {
482 return rec;
483 }
484 if ( data.empty() )
485 {
486 return rec;
487 }
488
489 iDataStream s(data);
490
491 short version;
492 resip_assert( sizeof(version) == 2 );
493 s.read( (char*)(&version), sizeof(version) );
494
495 if ( version == 1 )
496 {
498 decodeString(s, rec.mAddress);
499 s.read( (char*)(&rec.mMask), sizeof(rec.mMask) );
500 s.read( (char*)(&rec.mPort), sizeof(rec.mPort) );
501 s.read( (char*)(&rec.mFamily), sizeof(rec.mFamily) );
502 s.read( (char*)(&rec.mTransport), sizeof(rec.mTransport) );
503 }
504 else
505 {
506 // unknown version
507 ErrLog( <<"Data in ACL database with unknown version " << version );
508 ErrLog( <<"record size is " << data.size() );
509 }
510
511 return rec;
512}
513
514
517{
519
521 while ( !key.empty() )
522 {
523 AbstractDb::AclRecord rec = getAcl(key);
524
525 ret.push_back(rec);
526
527 key = nextAclKey();
528 }
529
530 return ret;
531}
532
533
539
540
546
547
548bool
550 const AbstractDb::ConfigRecord& rec )
551{
552 resip_assert( !key.empty() );
553
554 Data data;
555 {
556 oDataStream s(data);
557
558 short version=1;
559 resip_assert( sizeof( version) == 2 );
560 s.write( (char*)(&version) , sizeof(version) );
561
562 encodeString( s, rec.mDomain );
563 s.write( (char*)(&rec.mTlsPort) , sizeof( rec.mTlsPort ) );
564 resip_assert( sizeof(rec.mTlsPort) == 2 );
565
566 s.flush();
567 }
568
569 return dbWriteRecord( ConfigTable, key, data );
570}
571
572
573void
578
579
582{
584 Data data;
585 bool stat = dbReadRecord( ConfigTable, key, data );
586 if ( !stat )
587 {
588 return rec;
589 }
590 if ( data.empty() )
591 {
592 return rec;
593 }
594
595 iDataStream s(data);
596
597 short version;
598 resip_assert( sizeof(version) == 2 );
599 s.read( (char*)(&version), sizeof(version) );
600
601 if ( version == 1 )
602 {
603 decodeString(s, rec.mDomain);
604
605 s.read( (char*)(&rec.mTlsPort), sizeof(rec.mTlsPort) );
606 resip_assert( sizeof( rec.mTlsPort) == 2 );
607 }
608 else
609 {
610 // unknown version
611 ErrLog( <<"Data in Config database with unknown version " << version );
612 ErrLog( <<"record size is " << data.size() );
613 }
614
615 return rec;
616}
617
618
621{
623
625 while ( !key.empty() )
626 {
628
629 ret.push_back(rec);
630
631 key = nextConfigKey();
632 }
633
634 return ret;
635}
636
637
643
644
650
651
652bool
654 const AbstractDb::StaticRegRecord& rec )
655{
656 resip_assert( !key.empty() );
657
658 Data data;
659 {
660 oDataStream s(data);
661
662 short version=1;
663 resip_assert( sizeof( version) == 2 );
664 s.write( (char*)(&version) , sizeof(version) );
665
666 encodeString( s, rec.mAor );
667 encodeString( s, rec.mContact );
668 encodeString( s, rec.mPath );
669
670 s.flush();
671 }
672
673 return dbWriteRecord( StaticRegTable, key, data );
674}
675
676
677void
682
683
686{
688 Data data;
689 bool stat = dbReadRecord( StaticRegTable, key, data );
690 if ( !stat )
691 {
692 return rec;
693 }
694 if ( data.empty() )
695 {
696 return rec;
697 }
698
699 iDataStream s(data);
700
701 short version;
702 resip_assert( sizeof(version) == 2 );
703 s.read( (char*)(&version), sizeof(version) );
704
705 if ( version == 1 )
706 {
707 decodeString(s, rec.mAor);
708 decodeString(s, rec.mContact);
709 decodeString(s, rec.mPath);
710 }
711 else
712 {
713 // unknown version
714 ErrLog( <<"Data in StaticReg database with unknown version " << version );
715 ErrLog( <<"record size is " << data.size() );
716 }
717
718 return rec;
719}
720
721
724{
726
728 while ( !key.empty() )
729 {
731
732 ret.push_back(rec);
733
734 key = nextStaticRegKey();
735 }
736
737 return ret;
738}
739
740
746
747
753
754
755void
757{
758 oDataStream s(data);
759
760 short version=1;
761 resip_assert(sizeof( version) == 2);
762 s.write((char*)(&version) , sizeof(version));
763
768 encodeString(s, rec.mMethod);
769 encodeString(s, rec.mEvent);
770 s.write((char*)(&rec.mAction), sizeof (rec.mAction));
771 resip_assert(sizeof(rec.mAction) == 2);
773 s.write((char*)(&rec.mOrder), sizeof(rec.mOrder));
774 resip_assert(sizeof(rec.mOrder) == 2);
775
776 s.flush();
777}
778
779
780bool
782 const AbstractDb::FilterRecord& rec)
783{
784 resip_assert( !key.empty() );
785
786 Data data;
787 encodeFilter(rec, data);
788 return dbWriteRecord(FilterTable, key, data);
789}
790
791
792void
797
798
801{
803 Data data;
804 bool stat = dbReadRecord(FilterTable, key, data);
805 if (!stat)
806 {
807 return rec;
808 }
809 if (data.empty())
810 {
811 return rec;
812 }
813
814 iDataStream s(data);
815
816 short version;
817 resip_assert(sizeof(version) == 2);
818 s.read((char*)(&version), sizeof(version));
819
820 if (version == 1)
821 {
826 decodeString(s, rec.mMethod);
827 decodeString(s, rec.mEvent);
828 s.read((char*)(&rec.mAction), sizeof(rec.mAction));
829 resip_assert(sizeof(rec.mAction) == 2);
831 s.read((char*)(&rec.mOrder), sizeof(rec.mOrder));
832 resip_assert(sizeof(rec.mOrder) == 2);
833 }
834 else
835 {
836 // unknown version
837 ErrLog( <<"Data in filter database with unknown version " << version );
838 ErrLog( <<"record size is " << data.size() );
839 }
840
841 return rec;
842}
843
844
847{
849
851 while ( !key.empty() )
852 {
854
855 ret.push_back(rec);
856
857 key = nextFilterKey();
858 }
859
860 return ret;
861}
862
863
869
870
876
877bool
878AbstractDb::addToSilo(const Key& key, const SiloRecord& rec)
879{
880 resip_assert( !key.empty() );
881
882 Data data;
883 {
884 oDataStream s(data);
885
886 short version=1;
887 resip_assert(sizeof( version) == 2);
888 s.write((char*)(&version) , sizeof(version));
889
890 encodeString(s, rec.mDestUri);
891 encodeString(s, rec.mSourceUri);
892 s.write((char*)(&rec.mOriginalSentTime), sizeof (rec.mOriginalSentTime));
893 resip_assert(sizeof(rec.mOriginalSentTime) == 8);
894 encodeString(s, rec.mTid);
895 encodeString(s, rec.mMimeType);
897
898 s.flush();
899 }
900 return dbWriteRecord(SiloTable, key, data);
901}
902
903void
905{
906 iDataStream s(data);
907
908 short version;
909 resip_assert(sizeof(version) == 2);
910 s.read((char*)(&version), sizeof(version));
911
912 if (version == 1)
913 {
914 decodeString(s, rec.mDestUri);
915 decodeString(s, rec.mSourceUri);
916 s.read((char*)(&rec.mOriginalSentTime), sizeof(rec.mOriginalSentTime));
917 resip_assert(sizeof(rec.mOriginalSentTime) == 8);
918 decodeString(s, rec.mTid);
919 decodeString(s, rec.mMimeType);
921 }
922 else
923 {
924 // unknown version
925 ErrLog( <<"Data in silo database with unknown version " << version );
926 ErrLog( <<"record size is " << data.size() );
927 }
928}
929
930bool
932{
934
935 Data data;
936 bool moreRecords = dbFirstRecord(SiloTable, skey, data, false /* forUpdate? */);
937 if(moreRecords)
938 {
939 // Decode and store data
940 decodeSiloRecord(data,rec);
941 recordList.push_back(rec);
942 while((moreRecords = dbNextRecord(SiloTable, skey, data, false /* forUpdate? */)))
943 {
944 // Decode and store data
945 decodeSiloRecord(data,rec);
946 recordList.push_back(rec);
947 }
948 }
949
950 return true;
951}
952
953void
958
959void
960AbstractDb::cleanupExpiredSiloRecords(uint64_t now, unsigned long expirationTime)
961{
962 AbstractDb::Key key = dbFirstKey(SiloTable); // Iterate on primary key
963 // Iterate through all silo records - retrieve Original send time embedded into the
964 // primary key and see if the record has expired.
965 Data originalSendTimeData;
966 uint64_t originalSendTime;
967 while(!key.empty())
968 {
969 ParseBuffer pb(key);
970 const char* anchor = pb.position();
971 pb.skipToChar(':');
972 pb.data(originalSendTimeData, anchor);
973 originalSendTime = originalSendTimeData.convertUInt64();
974 if((unsigned long)(now - originalSendTime) > expirationTime)
975 {
976 eraseSiloRecord(key);
977 }
978 key = dbNextKey(SiloTable);
979 }
980}
981
982/* ====================================================================
983 * The Vovida Software License, Version 1.0
984 *
985 * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved.
986 *
987 * Redistribution and use in source and binary forms, with or without
988 * modification, are permitted provided that the following conditions
989 * are met:
990 *
991 * 1. Redistributions of source code must retain the above copyright
992 * notice, this list of conditions and the following disclaimer.
993 *
994 * 2. Redistributions in binary form must reproduce the above copyright
995 * notice, this list of conditions and the following disclaimer in
996 * the documentation and/or other materials provided with the
997 * distribution.
998 *
999 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
1000 * and "Vovida Open Communication Application Library (VOCAL)" must
1001 * not be used to endorse or promote products derived from this
1002 * software without prior written permission. For written
1003 * permission, please contact vocal@vovida.org.
1004 *
1005 * 4. Products derived from this software may not be called "VOCAL", nor
1006 * may "VOCAL" appear in their name, without prior written
1007 * permission of Vovida Networks, Inc.
1008 *
1009 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
1010 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1011 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
1012 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
1013 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
1014 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
1015 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
1016 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
1017 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
1018 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1019 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
1020 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
1021 * DAMAGE.
1022 *
1023 * ====================================================================
1024 */
#define REPRO_DB_VERSION_USERS
static void decodeString(iDataStream &s, Data &data)
static void encodeString(oDataStream &s, const Data &data)
#define ErrLog(args_)
Definition Logger.hxx:137
#define resip_assert(x)
This file needs to work for both C and C++ code.
std::vector< RouteRecord > RouteRecordList
virtual bool dbNextRecord(const Table table, const resip::Data &key, resip::Data &data, bool forUpdate, bool first=false)=0
virtual bool addToSilo(const Key &key, const SiloRecord &rec)
virtual bool addTlsPeerIdentity(const Key &key, const TlsPeerIdentityRecord &rec)
virtual ConfigRecord getConfig(const Key &key) const
std::vector< ConfigRecord > ConfigRecordList
virtual Key nextStaticRegKey()
virtual Key nextTlsPeerIdentityKey()
virtual Key firstConfigKey()
virtual resip::Data dbNextKey(const Table table, bool first=false)=0
virtual void decodeSiloRecord(resip::Data &data, SiloRecord &rec)
virtual void eraseStaticReg(const Key &key)
virtual ~AbstractDb()
virtual RouteRecord getRoute(const Key &key) const
virtual Key firstAclKey()
virtual resip::Data dbFirstKey(const Table table)
virtual void cleanupExpiredSiloRecords(uint64_t now, unsigned long expirationTime)
virtual AclRecord getAcl(const Key &key) const
virtual Key firstStaticRegKey()
std::vector< SiloRecord > SiloRecordList
virtual bool addAcl(const Key &key, const AclRecord &rec)
virtual bool addStaticReg(const Key &key, const StaticRegRecord &rec)
virtual void eraseSiloRecord(const Key &key)
virtual bool dbFirstRecord(const Table table, const resip::Data &key, resip::Data &data, bool forUpdate)
virtual FilterRecordList getAllFilters()
virtual void eraseTlsPeerIdentity(const Key &key)
virtual StaticRegRecord getStaticReg(const Key &key) const
virtual Key nextFilterKey()
virtual void eraseRoute(const Key &key)
virtual Key firstRouteKey()
virtual AclRecordList getAllAcls()
virtual Key nextUserKey()
std::vector< StaticRegRecord > StaticRegRecordList
virtual Key nextRouteKey()
virtual bool dbWriteRecord(const Table table, const resip::Data &key, const resip::Data &data)=0
virtual RouteRecordList getAllRoutes()
virtual bool addFilter(const Key &key, const FilterRecord &rec)
virtual Key firstUserKey()
virtual void eraseUser(const Key &key)
virtual bool isAuthorized(const std::set< resip::Data > &peerNames, const std::set< resip::Data > &identities) const
virtual void eraseAcl(const Key &key)
std::vector< FilterRecord > FilterRecordList
virtual Key firstTlsPeerIdentityKey()
virtual void eraseFilter(const Key &key)
virtual StaticRegRecordList getAllStaticRegs()
virtual void encodeRoute(const RouteRecord &rec, resip::Data &buffer)
virtual ConfigRecordList getAllConfigs()
virtual resip::Data getUserAuthInfo(const Key &key) const
virtual bool dbReadRecord(const Table table, const resip::Data &key, resip::Data &data) const =0
return false if not found
virtual Key nextAclKey()
virtual void encodeFilter(const FilterRecord &rec, resip::Data &buffer)
virtual bool getSiloRecords(const Key &skey, SiloRecordList &recordList)
virtual void eraseConfig(const Key &key)
virtual FilterRecord getFilter(const Key &key) const
virtual bool addUser(const Key &key, const UserRecord &rec)
virtual bool addRoute(const Key &key, const RouteRecord &rec)
virtual Key nextConfigKey()
virtual Key firstFilterKey()
virtual bool addConfig(const Key &key, const ConfigRecord &rec)
virtual UserRecord getUser(const Key &key) const
virtual void dbEraseRecord(const Table table, const resip::Data &key, bool isSecondaryKey=false)=0
virtual TlsPeerIdentityRecord getTlsPeerIdentity(const Key &key) const
virtual void encodeUser(const UserRecord &rec, resip::Data &buffer)
std::vector< AclRecord > AclRecordList
virtual int getSecondaryKey(const Table table, const Key &key, const resip::Data &data, void **secondaryKey, unsigned int *secondaryKeyLen)
An alternative to std::string, encapsulates an arbitrary buffer of bytes.
Definition Data.hxx:90
static const Data Empty
Constant that represents a zero-length data.
Definition Data.hxx:882
@ Share
The Data instance will use the buffer in a read-only mode.
Definition Data.hxx:266
char * getBuf(size_type length)
Set size to be exactly {length}, extending buffer if needed.
Definition Data.cxx:723
uint64_t convertUInt64() const
Takes the contents of the Data and converts them to an unsigned 64-bit integer.
Definition Data.cxx:1758
bool empty() const noexcept
Checks whether the Data is empty.
Definition Data.hxx:591
size_type size() const noexcept
Returns the number of bytes in this Data.
Definition Data.hxx:599
Data & clear()
Clears the contents of this Data.
Definition Data.hxx:800
const char * data() const noexcept
Returns a pointer to the contents of this Data.
Definition Data.hxx:608
Provides string-parsing functionality with protection from buffer overflow.
CurrentPosition skipToChar(char c)
CurrentPosition position() const
void data(Data &data, const char *start) const
make the passed in data share memory with the buffer (uses Data::Share)
An istream that operates on an existing Data.
An ostream that operates on an existing Data.
This Class is used to implement a primitive form of RPC using loose XML formatting.
dcm! – add UnusedChecking(_enum) below;
unsigned __int64 uint64_t
Definition stdint.h:95