Imported Upstream version 5.3.21
[platform/upstream/libdb.git] / lang / cxx / stl / dbstl_dbt.h
1 /*-
2  * See the file LICENSE for redistribution information.
3  *
4  * Copyright (c) 2009, 2012 Oracle and/or its affiliates.  All rights reserved.
5  *
6  * $Id$
7  */
8
9 #ifndef _DB_STL_DBT_H
10 #define _DB_STL_DBT_H
11
12 #include <assert.h>
13 #include <string>
14
15 #include "dbstl_common.h"
16 #include "dbstl_exception.h"
17 #include "dbstl_utility.h"
18
19 //////////////////////////////////////////////////////////////////////////
20 //////////////////////////////////////////////////////////////////////////
21 //
22 // DataItem class template definition
23 //
24 // 1. DataItem is a Dbt wrapper, it provides both typed data to/from memory
25 // chunk mapping as well as iostream support. Note that iostream functionality
26 // is not yet implemented.
27 // 2. DataItem is used inside dbstl to provide consistent Dbt object memory
28 // management.
29 // 3. DataItem is not only capable of mapping fixed size objects, but also
30 // varying length objects and objects not located in a consecutive chunk of
31 // memory, with the condition that user configures the required methods in
32 // DbstlElemTraits.
33 // 4. DataItem can not be a class template because inside it, the "member
34 // function template override" support is needed.
35 //
36 START_NS(dbstl)
37
38 using std::string;
39 #ifdef HAVE_WSTRING
40 using std::wstring;
41 #endif
42
43 class DataItem
44 {
45 private:
46         typedef DataItem self;
47
48         ////////////////////////////////////////////////////////////////////
49         ////////////////////////////////////////////////////////////////////
50         //
51         // DataItem memory management
52         //
53         // The dbt_ member is the current dbt, data is stored in the dbt's 
54         // referenced memory, it may
55         // deep copy from constructor and from other Dbt, depending on
56         // the constructors "onstack" parameter --- if true, this object
57         // is only used as a stack object inside a function,
58         // so do shallow copy; otherwise do deep copy.
59         // There is always a DB_DBT_USERMEM flag set to the dbt,
60         // its ulen data member stores the length of referenced memory,
61         // its size data member stores the actual size of data;
62         // If onstack is true, its dlen is INVALID_DLEN, and freemem()
63         // will not free such memory because this object only reference
64         // other object's memory, its the referenced object's responsibility
65         // to free their memory.
66         //
67         // A DataItem object is not used everywhere, so it is impossible for
68         // such an object to have two kinds of usages as above at the same
69         // time, so we are safe doing so.
70         Dbt dbt_;
71
72         // Free dbt_'s referenced memory if that memory is allocated in heap
73         // and owned by dbt_.
74         inline void freemem()
75         {
76                 void *buf = dbt_.get_data();
77
78                 if (buf != NULL && (dbt_.get_flags() & DB_DBT_USERMEM) != 0
79                     && dbt_.get_dlen() != INVALID_DLEN)
80                         free(buf);
81                 memset(&dbt_, 0, sizeof(dbt_));
82         }
83
84 public:
85
86         // Deep copy, because dbt2.data pointed memory may be short lived.
87         inline void set_dbt(const DbstlDbt&dbt2, bool onstack)
88         {
89                 void *buf;
90                 u_int32_t s1, s2;
91                 DBT *pdbt2, *pdbt;
92                
93                 pdbt2 = (DBT *)&dbt2;
94                 pdbt = (DBT *)&dbt_;
95
96                 if (!onstack) {
97                         buf = pdbt->data;
98                         s1 = pdbt->ulen;
99                         s2 = pdbt2->size;
100                         if(s2 > s1) {
101                                 buf = DbstlReAlloc(buf, s2);
102                                 pdbt->size = s2;
103                                 pdbt->data = buf;
104                                 pdbt->ulen = s2;
105                                 pdbt->flags |= DB_DBT_USERMEM;
106                         } else
107                                 pdbt->size = s2;
108                         memcpy(buf, pdbt2->data, s2);
109                 } else {
110                         freemem();
111                         dbt_ = (const Dbt)dbt2;
112                         pdbt->dlen = (INVALID_DLEN);
113                 }
114         }
115
116         // Deep copy, because dbt2.data pointed memory may be short lived.
117         inline void set_dbt(const Dbt&dbt2, bool onstack)
118         {
119                 void *buf;
120                 u_int32_t s1, s2;
121                 DBT *pdbt2, *pdbt;
122                
123                 pdbt2 = (DBT *)&dbt2;
124                 pdbt = (DBT *)&dbt_;
125
126                 if (!onstack) {
127                         buf = pdbt->data;
128                         s1 = pdbt->ulen;
129                         s2 = pdbt2->size;
130                         if(s2 > s1) {
131                                 buf = DbstlReAlloc(buf, s2);
132                                 pdbt->size = s2;
133                                 pdbt->data = buf;
134                                 pdbt->ulen = s2;
135                                 pdbt->flags |= DB_DBT_USERMEM;
136                         } else
137                                 pdbt->size = s2;
138                         memcpy(buf, pdbt2->data, s2);
139                 } else {
140                         freemem();
141                         dbt_ = dbt2;
142                         pdbt->dlen = (INVALID_DLEN);
143                 }
144         }
145
146         inline void set_dbt(const DBT&dbt2, bool onstack)
147         {
148                 void *buf;
149                 u_int32_t s1, s2;
150                 DBT *pdbt = (DBT *)&dbt_;
151
152                 if (!onstack) {
153                         buf = pdbt->data;
154                         s1 = pdbt->ulen;
155                         s2 = dbt2.size;
156                         if(s2 > s1) {
157                                 buf = DbstlReAlloc(buf, s2);
158                                 pdbt->size = s2;
159                                 pdbt->data = buf;
160                                 pdbt->ulen = s2;
161                                 pdbt->flags |= DB_DBT_USERMEM;
162                         } else
163                                 pdbt->size = s2;
164                         memcpy(buf, dbt2.data, s2);
165                 } else {
166                         freemem();
167                         // The following is right because Dbt derives from
168                         // DBT with no extra members or any virtual functions.
169                         memcpy(&dbt_, &dbt2, sizeof(dbt2));
170                         pdbt->dlen = INVALID_DLEN;
171                 }
172         }
173
174         // Return to the initial state.
175         inline void reset()
176         {
177                 void *buf = dbt_.get_data();
178                 if (buf) {
179                         memset(buf, 0, dbt_.get_ulen());
180                         dbt_.set_size(0);
181                 }
182         }
183
184         inline Dbt& get_dbt()
185         {
186                 return dbt_;
187         }
188
189         // Return data of this object. If no data return -1, if it has data
190         // return 0.
191         //
192         // !!!XXX Note that the type parameter T can only be in this function
193         // because "template type parameter overload" applies only to a
194         // functions template argument list, rather than that of classes.
195         // If you put the "template<Typename T>" to this class's declaration,
196         // making it a class template, then when T is any of Dbt, DBT, or
197         // DataItem<T>, there will be two copies of this function. One will be
198         // this function's instantiated version, the other one is one of the
199         // three functions defined below.
200         //
201         template <Typename T>
202         inline int get_data(T& data) const
203         {
204                 int ret;
205                 typedef DbstlElemTraits<T> EM;
206                 typename EM::ElemRstoreFunct restore;
207                 void *pdata = NULL;
208
209                 if ((pdata = dbt_.get_data()) != NULL) {
210                         if ((restore = EM::instance()->
211                             get_restore_function()) != NULL)
212                                 restore(data, pdata);
213                         else
214                                 data = *((T*)pdata);
215                         ret = 0;
216                 } else
217                         ret = -1;
218                 return ret;
219         }
220
221         ////////////////////////////////////////////////////////////////////
222         //
223         // Begin functions supporting direct naked string storage.
224         //
225         // Always store the data, rather than the container object.
226         //
227         // The returned string lives no longer than the next iterator
228         // movement call.
229         //
230         inline int get_data(char*& data) const
231         {
232                 data = (char*)dbt_.get_data();
233                 return 0;
234         }
235
236         inline int get_data(string &data) const
237         {
238                 data = (string::pointer) dbt_.get_data();
239                 return 0;
240         }
241
242         inline int get_data(wchar_t*& data) const
243         {
244                 data = (wchar_t*)dbt_.get_data();
245                 return 0;
246         }
247
248 #ifdef HAVE_WSTRING
249         inline int get_data(wstring &data) const
250         {
251                 data = (wstring::pointer) dbt_.get_data();
252                 return 0;
253         }
254 #endif
255
256         ////////////////////////////////////////////////////////////////////
257
258         // Supporting storing arbitrary type of sequence.
259         template <Typename T>
260         inline int get_data(T*& data) const
261         {
262                 data = (T*)dbt_.get_data();
263                 return 0;
264         }
265
266         inline int get_data(DataItem& data) const
267         {
268                 int ret;
269
270                 if (dbt_.get_data()) {
271                         data.set_dbt(dbt_, false);
272                         ret = 0;
273                 } else
274                         ret = -1;
275                 return ret;
276         }
277
278         ////////////////////////////////////////////////////////////////////
279         //
280         // Begin functions supporting Dbt storage.
281         //
282         // This member function allows storing a Dbt type, so that user can
283         // store the varying length data into Dbt.
284         //
285         // This method is required to copy a data element's bytes to another 
286         // Dbt object, used inside by dbstl.
287         // If there is no data return -1, if it has data return 0.
288         //
289         inline int get_data(Dbt& data) const
290         {
291                 int ret;
292                 void *addr;
293                 u_int32_t sz;
294                 DBT *pdbt = (DBT *)&dbt_, *pdata = (DBT *)&data;
295
296                 if (pdbt->data) {
297                         addr = pdata->data;
298                         sz = pdbt->size;
299                         if (pdata->ulen < sz) {
300                                 pdata->data = DbstlReAlloc(addr, sz);
301                                 pdata->size = sz;
302                                 pdata->ulen = sz;
303                                 pdata->flags |= DB_DBT_USERMEM;
304                         } else
305                                 pdata->size = sz;
306                         memcpy(pdata->data, pdbt->data, sz);
307                         ret = 0;
308                 } else
309                         ret = -1;
310                 return ret;
311         }
312
313         inline int get_data(DBT& data) const
314         {
315                 int ret;
316                 void*addr;
317                 u_int32_t sz;
318
319                 if (dbt_.get_data()) {
320                         addr = data.data;
321                         if (data.ulen < (sz = dbt_.get_size())) {
322                                 data.data = DbstlReAlloc(addr, sz);
323                                 // User need to free this memory
324                                 data.flags = data.flags | DB_DBT_USERMEM;
325                                 data.size = sz;
326                                 data.ulen = sz;
327                         } else
328                                 data.size = sz;
329                         memcpy(data.data, dbt_.get_data(), sz);
330                         ret = 0;
331                 } else
332                         ret = -1;
333                 return ret;
334         }
335
336         inline int get_data(DbstlDbt& data) const
337         {
338                 int ret;
339                 void *addr;
340                 u_int32_t sz;
341                 DBT *pdbt = (DBT *)&dbt_, *pdata = (DBT *)&data;
342
343                 if (pdbt->data) {
344                         addr = pdata->data;
345                         sz = pdbt->size;
346                         if (pdata->ulen < sz) {
347                                 pdata->data = DbstlReAlloc(addr, sz);
348                                 pdata->size = sz;
349                                 pdata->ulen = sz;
350                                 pdata->flags |= DB_DBT_USERMEM;
351                         } else
352                                 pdata->size = sz;
353                         memcpy(pdata->data, pdbt->data, sz);
354                         ret = 0;
355                 } else
356                         ret = -1;
357                 return ret;
358         }
359
360         ////////////////////////////////////////////////////////////////////
361
362         // Deep copy in assignment and copy constructor.
363         inline const DbstlDbt& operator=(const DbstlDbt& t2)
364         {
365                 set_dbt(t2, false);
366                 return t2;
367         }
368
369         // Deep copy in assignment and copy constructor.
370         inline const Dbt& operator=(const Dbt& t2)
371         {
372                 set_dbt(t2, false);
373                 return t2;
374         }
375
376         // Deep copy in assignment and copy constructor.
377         inline const DBT& operator=(const DBT& t2)
378         {
379                 set_dbt(t2, false);
380                 return t2;
381         }
382
383         // Deep copy in assignment and copy constructor.
384         template <Typename T>
385         inline const T& operator = (const T&dt)
386         {
387
388                 make_dbt(dt, false);
389                 return dt;
390         }
391
392         // Generic way of storing an object or variable. Note that DataItem
393         // is not a class template but a class with function templates.
394         // Variable t locates on a consecutive chunk of memory, and objects 
395         // of T have the same size. 
396         //
397         template <Typename T>
398         void make_dbt(const T& dt, bool onstack)
399         {
400                 typedef DbstlElemTraits<T> EM;
401                 u_int32_t sz;
402                 typename EM::ElemSizeFunct sizef;
403                 typename EM::ElemCopyFunct copyf;
404                 DBT *pdbt = (DBT *)&dbt_;
405
406                 if ((sizef = EM::instance()->get_size_function()) != NULL)
407                         sz = sizef(dt);
408                 else
409                         sz = sizeof(dt);
410
411                 copyf = EM::instance()->get_copy_function();
412
413                 if (onstack &&  copyf == NULL) {
414                         freemem();
415                         pdbt->data = ((void*)&dt);
416                         // We have to set DB_DBT_USERMEM for DB_THREAD to work.
417                         pdbt->flags = (DB_DBT_USERMEM);
418                         pdbt->size = (sz);
419                         pdbt->ulen = (sz);
420                         // This is a flag that this memory can't be freed
421                         // because it is on stack.
422                         pdbt->dlen = (INVALID_DLEN);
423                         return;
424                 }
425
426                 // Not on stack, allocate enough space and "copy" the object
427                 // using shall copy or customized copy.
428                 if (pdbt->ulen < sz) {
429                         pdbt->data = (DbstlReAlloc(pdbt->data, sz));
430                         assert(pdbt->data != NULL);
431                         pdbt->size = (sz);
432                         pdbt->ulen = (sz);
433                         pdbt->flags = (DB_DBT_USERMEM);
434                 } else
435                         pdbt->size = (sz);
436
437                 if (copyf != NULL)
438                         copyf(pdbt->data, dt);
439                 else
440                         memcpy(pdbt->data, &dt, sz);
441         }
442
443         inline const char*&operator = (const char*&dt)
444         {
445                 make_dbt(dt, false);
446                 return dt;
447         }
448
449         inline const wchar_t*&operator = (const wchar_t*&dt)
450         {
451                 make_dbt(dt, false);
452                 return dt;
453         }
454
455         inline const string &operator=(const string &dt)
456         {
457                 make_dbt(dt, false);
458                 return dt;
459         }
460
461 #ifdef HAVE_WSTRING
462         inline const wstring &operator=(const wstring &dt)
463         {
464                 make_dbt(dt, false);
465                 return dt;
466         }
467 #endif
468
469         template <Typename T>
470         inline const T*&operator = (const T*&dt)
471         {
472                 make_dbt(dt, false);
473                 return dt;
474         }
475
476         inline const self& operator=(const self&dbt1)
477         {
478                 ASSIGNMENT_PREDCOND(dbt1)
479                 this->set_dbt(dbt1.dbt_, false);
480                 return dbt1;
481         }
482
483         // Deep copy.
484         inline DataItem(const self&dbt1)
485         {
486                 set_dbt(dbt1.dbt_, false);
487         }
488
489
490         inline DataItem(u_int32_t sz)
491         {
492                 void *buf;
493                 DBT *pdbt = (DBT *)&dbt_;
494
495                 buf = NULL;
496                 buf = DbstlMalloc(sz);
497                 memset(buf, 0, sz);
498                 pdbt->size = sz;
499                 pdbt->ulen = sz;
500                 pdbt->data = buf;
501                 pdbt->flags = DB_DBT_USERMEM;
502         }
503
504         // Deep copy. The onstack parameter means whether the object referenced
505         // by this DataItem is on used with a function call where this DataItem
506         // object is used. If so, we don't deep copy the object, simply refer
507         // to its memory location. The meaining is the same for this parameter
508         // in constructors that follow.
509         inline DataItem(const Dbt&dbt2, bool onstack)
510         {
511                 set_dbt(dbt2, onstack);
512         }
513         
514         inline DataItem(const DbstlDbt&dbt2, bool onstack)
515         {
516                 set_dbt(dbt2, onstack);
517         }
518         
519         inline DataItem(const DBT&dbt2, bool onstack)
520         {
521                 set_dbt(dbt2, onstack);
522         }
523
524         // Deep copy. There is a partial specialization for char*/wchar_t*/
525         // string/wstring.
526         template<Typename T>
527         inline DataItem(const T& dt, bool onstack)
528         {
529                 make_dbt(dt, onstack);
530         }
531
532         inline ~DataItem(void)
533         {
534                 freemem();
535         }
536
537 protected:
538
539         // Store a char*/wchar_t* string. Need four versions for char*
540         // and wchar_t* respectively to catch all
541         // possibilities otherwise the most generic one will be called.
542         // Note that the two const decorator matters when doing type
543         // matching.
544         inline void make_dbt_chars(const char *t, bool onstack)
545         {
546                 DBT *d = (DBT *)&dbt_;
547                 u_int32_t sz;
548                 sz = ((t == NULL) ? 
549                     sizeof(char) : 
550                     (u_int32_t)((strlen(t) + 1) * sizeof(char)));
551                 if (!onstack) {
552                         if (d->ulen < sz) {
553                                 d->flags |= DB_DBT_USERMEM;
554                                 d->data = DbstlReAlloc(d->data, sz);
555                                 d->ulen = sz;
556                         }
557                         d->size = sz;
558                         if (t != NULL)
559                                 strcpy((char*)d->data, t);
560                         else
561                                 memset(d->data, '\0', sizeof(char));
562                 } else {
563                         freemem();
564                         d->data = ((t == NULL) ? (void *)"" : (void *)t);
565                         d->size = sz;
566                         d->ulen = sz;
567                         d->flags = (DB_DBT_USERMEM);
568                         d->dlen = (INVALID_DLEN);
569                 }
570         }
571
572         inline void make_dbt_wchars(const wchar_t *t, bool onstack)
573         {
574                 DBT *d = (DBT *)&dbt_;
575                 u_int32_t sz;
576                 sz = ((t == NULL) ? 
577                     sizeof(wchar_t) : 
578                     (u_int32_t)((wcslen(t) + 1) * sizeof(wchar_t)));
579                 if (!onstack) {                                 
580                         if (d->ulen < sz) {
581                                 d->flags |= DB_DBT_USERMEM;
582                                 d->data = DbstlReAlloc(d->data, sz);
583                                 d->ulen = sz;
584                         }
585                         d->size = sz;
586                         if (t != NULL)
587                                 wcscpy((wchar_t*)d->data, t);
588                         else
589                                 memset(d->data, L'\0', sizeof(wchar_t));
590                 } else {
591                         freemem();
592                         d->data = ((t == NULL) ? (void *)L"" : (void *)t);
593                         d->size = sz;
594                         d->ulen = sz;
595                         d->flags = (DB_DBT_USERMEM);
596                         d->dlen = (INVALID_DLEN);
597                 }
598         }
599
600         inline void make_dbt(const char*& t, bool onstack)
601         {
602                 make_dbt_chars(t, onstack);
603         }
604
605         inline void make_dbt(const char* const& t, bool onstack)
606         {
607                 make_dbt_chars(t, onstack);
608         }
609
610         inline void make_dbt(char*& t, bool onstack)
611         {
612                 make_dbt_chars(t, onstack);
613         }
614
615         inline void make_dbt(char* const& t, bool onstack)
616         {
617                 make_dbt_chars(t, onstack);
618         }
619
620         inline void make_dbt(const string& t, bool onstack)
621         {
622                 make_dbt_chars(t.c_str(), onstack);
623         }
624
625         inline void make_dbt(const wchar_t*& t, bool onstack)
626         {
627                 make_dbt_wchars(t, onstack);
628         }
629
630         inline void make_dbt(const wchar_t* const& t, bool onstack)
631         {
632                 make_dbt_wchars(t, onstack);
633         }
634
635         inline void make_dbt(wchar_t*& t, bool onstack)
636         {
637                 make_dbt_wchars(t, onstack);
638         }
639
640         inline void make_dbt(wchar_t* const& t, bool onstack)
641         {
642                 make_dbt_wchars(t, onstack);
643         }
644
645 #ifdef HAVE_WSTRING
646         inline void make_dbt(const wstring& t, bool onstack)
647         {
648                 make_dbt_wchars(t.c_str(), onstack);
649         }
650 #endif
651
652         template <Typename T>
653         void make_dbt_internal(const T*t, bool onstack)
654         {
655                 typedef DbstlElemTraits<T> EM;
656                 u_int32_t i, sz, totalsz, sql;
657                 DBT *pdbt = (DBT *)&dbt_;
658                 typename EM::ElemSizeFunct szf = NULL;
659                 typename EM::SequenceLenFunct seqlenf = NULL;
660                 typename EM::SequenceCopyFunct seqcopyf = NULL;
661
662                 szf = EM::instance()->get_size_function();
663                 seqlenf = EM::instance()->get_sequence_len_function();
664                 seqcopyf = EM::instance()->get_sequence_copy_function();
665
666                 assert(seqlenf != NULL);
667                 sql = sz = (u_int32_t)seqlenf(t);
668                 if (szf)
669                         for (i = 0, totalsz = 0; i < sz; i++)
670                                 totalsz += szf(t[i]);
671                 else
672                         totalsz = sz * sizeof(T);
673
674                 sz = totalsz;
675
676                 if (onstack && seqcopyf == NULL) {
677                         freemem();
678                         pdbt->data = (void *)t;
679                         pdbt->size = sz;
680                         pdbt->ulen = sz;
681                         pdbt->flags = DB_DBT_USERMEM;
682                         pdbt->dlen = INVALID_DLEN; // onstack flag;
683                 } else {
684                         // ulen stores the real length of the pointed memory.
685                         if (pdbt->ulen < sz) {
686                                 pdbt->data = DbstlReAlloc(pdbt->data, sz);
687                                 pdbt->ulen = sz;
688                                 pdbt->flags |= DB_DBT_USERMEM;
689                         }
690                         pdbt->size = sz;
691
692                         EM::instance()->copy((T *)pdbt->data, t, sql);
693                 }
694         }
695
696         // Store a sequence of base type T. Need four versions to catch all
697         // possibilities otherwise the most generic one will be called.
698         template <Typename T>
699         inline void make_dbt(const T*const&tt, bool onstack)
700         {
701                 make_dbt_internal((const T*)tt, onstack);
702         }
703         template <Typename T>
704         inline void make_dbt(T*const&tt, bool onstack)
705         {
706                 make_dbt_internal((const T*)tt, onstack);
707         }
708         template <Typename T>
709         inline void make_dbt(T*&tt, bool onstack)
710         {
711                 make_dbt_internal((const T*)tt, onstack);
712         }
713         template <Typename T>
714         inline void make_dbt(const T*&tt, bool onstack)
715         {
716                 make_dbt_internal((const T*)tt, onstack);
717         }
718
719
720 public:
721         inline DataItem(const char*& t, bool onstack)
722         {
723                 make_dbt_chars(t, onstack);
724         }
725
726         inline DataItem(const char* const& t, bool onstack)
727         {
728                 make_dbt_chars(t, onstack);
729         }
730
731         inline DataItem(char*& t, bool onstack)
732         {
733                 make_dbt_chars(t, onstack);
734         }
735
736         inline DataItem(char* const& t, bool onstack)
737         {
738                 make_dbt_chars(t, onstack);
739         }
740
741         inline DataItem(const string& t, bool onstack)
742         {
743                 make_dbt_chars(t.c_str(), onstack);
744         }
745
746         inline DataItem(const wchar_t*& t, bool onstack)
747         {
748                 make_dbt_wchars(t, onstack);
749         }
750
751         inline DataItem(const wchar_t* const& t, bool onstack)
752         {
753                 make_dbt_wchars(t, onstack);
754         }
755
756         inline DataItem(wchar_t*& t, bool onstack)
757         {
758                 make_dbt_wchars(t, onstack);
759         }
760
761         inline DataItem(wchar_t* const& t, bool onstack)
762         {
763                 make_dbt_wchars(t, onstack);
764         }
765
766 #ifdef HAVE_WSTRING
767         inline DataItem(const wstring& t, bool onstack)
768         {
769                 make_dbt_wchars(t.c_str(), onstack);
770         }
771 #endif
772         template<Typename T>
773         inline DataItem(T*&tt, bool onstack)
774         {
775                 make_dbt_internal((const T*)tt, onstack);
776         }
777
778         template<Typename T>
779         inline DataItem(const T*&tt, bool onstack)
780         {
781                 make_dbt_internal((const T*)tt, onstack);
782         }
783
784         template<Typename T>
785         inline DataItem(T*const&tt, bool onstack)
786         {
787                 make_dbt_internal((const T*)tt, onstack);
788         }
789
790         template<Typename T>
791         inline DataItem(const T*const&tt, bool onstack)
792         {
793                 make_dbt_internal((const T*)tt, onstack);
794         }
795
796
797 }; // DataItem<>
798
799 bool operator==(const Dbt&d1, const Dbt&d2);
800 bool operator==(const DBT&d1, const DBT&d2);
801 END_NS
802
803 #endif // !_DB_STL_DBT_H