1 /*
2    Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License, version 2.0,
6    as published by the Free Software Foundation.
7 
8    This program is also distributed with certain software (including
9    but not limited to OpenSSL) that is licensed under separate terms,
10    as designated in a particular file or component or in included license
11    documentation.  The authors of MySQL hereby grant you an additional
12    permission to link the program and your derivative works with the
13    separately licensed software that they have included with MySQL.
14 
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License, version 2.0, for more details.
19 
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
23 */
24 
25 #ifndef NDB_PACK_HPP
26 #define NDB_PACK_HPP
27 
28 #include <ndb_global.h>
29 #include <my_sys.h>
30 #include <kernel/AttributeHeader.hpp>
31 #include <NdbSqlUtil.hpp>
32 #include <NdbEnv.h>
33 class NdbOut;
34 
35 /*
36  * Pack an array of NDB data values.  The types are specified by an
37  * array of data types.  There is no associated table or attribute ids.
38  * All or an initial sequence of the specified values are present.
39  *
40  * Currently used for ordered index keys and bounds in kernel (DBTUX)
41  * and in index statistics (mysqld).  The comparison methods use the
42  * primitive type comparisons from NdbSqlUtil.
43  *
44  * Keys and bounds use same spec.  However a value in an index bound can
45  * be NULL even if the key attribute is not nullable.  Therefore bounds
46  * set the "allNullable" property and have a longer null mask.
47  *
48  * There are two distinct use occasions: 1) construction of data or
49  * bound 2) operating on previously constructed data or bound.  There
50  * are classes Data/DataC and Bound/BoundC for these uses.  The latter
51  * often can return a result without interpreting the full value.
52  *
53  * Methods return -1 on error and 0 on success.  Comparison methods
54  * assume well-formed data and return negative, zero, positive for less,
55  * equal, greater.
56  */
57 
58 class NdbPack {
59 public:
60   class Endian;
61   class Type;
62   class Spec;
63   class Iter;
64   class DataC;
65   class Data;
66   class BoundC;
67   class Bound;
68 
69   /*
70    * Get SQL type.
71    */
72   static const NdbSqlUtil::Type& getSqlType(Uint32 typeId);
73 
74   /*
75    * Error codes for core dumps.
76    */
77   class Error {
78   public:
79     enum {
80       TypeNotSet = -101,          // type id was not set
81       TypeOutOfRange = -102,      // type id is out of range
82       TypeNotSupported = -103,    // blob (and for now bit) types
83       TypeSizeZero = -104,        // max size was set to zero
84       TypeFixSizeInvalid = -105,  // fixed size specified wrong
85       TypeNullableNotBool = -106, // nullable must be 0 or 1
86       CharsetNotSpecified = -107, // char type with no charset number
87       CharsetNotFound = -108,     // cannot install in all_charsets[]
88       CharsetNotAllowed = -109,   // non-char type with charset
89       SpecBufOverflow = -201,     // more spec items than allocated
90       DataCntOverflow = -301,     // more data items than in spec
91       DataBufOverflow = -302,     // more data bytes than allocated
92       DataValueOverflow = -303,   // var length exceeds max size
93       DataNotNullable = -304,     // NULL value to not-nullable type
94       InvalidAttrInfo = -305,     // invalid plain old attr info
95       BoundEmptySide = -401,      // side not 0 for empty bound
96       BoundNonemptySide = -402,   // side not -1,+1 for non-empty bound
97       InternalError = -901,
98       ValidationError = -902,
99       NoError = 0
100     };
101     Error();
~Error()102     ~Error() {}
103     int get_error_code() const;
104     int get_error_line() const;
105 
106   private:
107     friend class Endian;
108     friend class Type;
109     friend class Spec;
110     friend class Iter;
111     friend class DataC;
112     friend class Data;
113     friend class BoundC;
114     friend class Bound;
115     void set_error(int code, int line) const;
116     void set_error(const Error& e2) const;
117     mutable int m_error_code;
118     mutable int m_error_line;
119   };
120 
121   /*
122    * Endian definitions.
123    */
124   class Endian {
125   public:
126     enum Value {
127       Native = 0, // replaced by actual value
128       Little = 1,
129       Big = 2
130     };
131     static Value get_endian();
132     static void convert(void* ptr, Uint32 len);
133   };
134 
135   /*
136    * Data type.
137    */
138   class Type : public Error {
139   public:
140     Type();
141     Type(int typeId, Uint32 byteSize, bool nullable, Uint32 csNumber);
~Type()142     ~Type() {}
143     /*
144      * Define the type.  Size is fixed or max size.  Values of variable
145      * length have length bytes.  The definition is verified when the
146      * type is added to the specification.  This also installs missing
147      * CHARSET_INFO* into all_charsets[].
148      */
149     void set(Uint32 typeId, Uint32 byteSize, bool nullable, Uint32 csNumber);
150     // getters
151     Uint32 get_type_id() const;
152     Uint32 get_byte_size() const;
153     bool get_nullable() const;
154     Uint32 get_cs_number() const;
155     Uint32 get_array_type() const;
156     // print
157     friend NdbOut& operator<<(NdbOut&, const Type&);
158     void print(NdbOut& out) const;
159     const char* print(char* buf, Uint32 bufsz) const;
160     int validate() const;
161 
162   private:
163     friend class Spec;
164     friend class Iter;
165     friend class DataC;
166     friend class Data;
167     // verify and complete when added to specification
168     int complete();
169     Uint16 m_typeId;
170     Uint16 m_byteSize;    // fixed or max size in bytes
171     Uint16 m_nullable;
172     Uint16 m_csNumber;
173     Uint16 m_arrayType;   // 0,1,2 length bytes
174     Uint16 m_nullbitPos;  // computed as part of Spec
175   };
176 
177   /*
178    * Data specification i.e. array of types.  Usually constructed on the
179    * heap, so keep fairly small.  Used for boths keys and bounds.
180    */
181   class Spec : public Error {
182   public:
183     Spec();
~Spec()184     ~Spec() {}
185     // set initial buffer (calls reset)
186     void set_buf(Type* buf, Uint32 bufMaxCnt);
187     // use if buffer is relocated
188     void set_buf(Type* buf);
189     // reset but keep buffer
190     void reset();
191     // add type to specification once or number of times
192     int add(Type type);
193     int add(Type type, Uint32 cnt);
194     // copy from
195     void copy(const Spec& s2);
196     // getters (bounds set allNullable)
197     const Type& get_type(Uint32 i) const;
198     Uint32 get_cnt() const;
199     Uint32 get_nullable_cnt(bool allNullable) const;
200     Uint32 get_nullmask_len(bool allNullable) const;
201     // max data length including null mask
202     Uint32 get_max_data_len(bool allNullable) const;
203     // minimum var bytes (if used by Data instance)
204     Uint32 get_min_var_bytes(bool allNullable) const;
205     // print
206     friend NdbOut& operator<<(NdbOut&, const Spec&);
207     void print(NdbOut& out) const;
208     const char* print(char* buf, Uint32 bufsz) const;
209     int validate() const;
210 
211   private:
212     friend class Iter;
213     friend class DataC;
214     friend class Data;
215     friend class BoundC;
216     // undefined
217     Spec(const Spec&);
218     Spec& operator=(const Spec&);
219     Type* m_buf;
220     Uint16 m_bufMaxCnt;
221     Uint16 m_cnt;
222     Uint16 m_nullableCnt;
223     Uint16 m_varsizeCnt;
224     Uint32 m_maxByteSize; // excludes null mask
225   };
226 
227   /*
228    * Iterator over data items.  DataC uses external Iter instances in
229    * comparison methods etc.  Data contains an Iter instance which
230    * iterates on items added.
231    */
232   class Iter : public Error {
233   public:
234     // the data instance is only used to set metadata
235     Iter(const DataC& data);
~Iter()236     ~Iter() {}
237     void reset();
238 
239   private:
240     friend class DataC;
241     friend class Data;
242     friend class BoundC;
243     // undefined
244     Iter(const Iter&);
245     Iter& operator=(const Iter&);
246     // describe next non-null or null item and advance iterator
247     int desc(const Uint8* item);
248     int desc_null();
249     // compare current items (DataC buffers are passed)
250     int cmp(const Iter& r2, const Uint8* buf1, const Uint8* buf2) const;
251 
252     const Spec& m_spec;
253     const bool m_allNullable;
254     // iterator
255     Uint32 m_itemPos;     // position of current item in DataC buffer
256     Uint32 m_cnt;         // number of items described so far
257     Uint32 m_nullCnt;
258     // current item
259     Uint32 m_lenBytes;    // 0-2
260     Uint32 m_bareLen;     // excludes length bytes
261     Uint32 m_itemLen;     // full length, value zero means null
262   };
263 
264   /*
265    * Read-only superclass of Data.  Initialized from a previously
266    * constructed Data buffer (any var bytes skipped).  Methods interpret
267    * one data item at a time.  Values are native endian.
268    */
269   class DataC : public Error {
270   public:
271     DataC(const Spec& spec, bool allNullable);
272     // set buffer to previously constructed one with given item count
273     void set_buf(const void* buf, Uint32 bufMaxLen, Uint32 cnt);
274     // interpret next data item
275     int desc(Iter& r) const;
276     // compare cnt attrs and also return number of initial equal attrs
277     int cmp(const DataC& d2, Uint32 cnt, Uint32& num_eq) const;
278     // getters
279     const Spec& get_spec() const;
280     bool get_all_nullable() const;
281     const void* get_data_buf() const;
282     Uint32 get_cnt() const;
283     bool is_empty() const;
284     bool is_full() const;
285     // print
286     friend NdbOut& operator<<(NdbOut&, const DataC&);
287     void print(NdbOut& out) const;
288     const char* print(char* buf, Uint32 bufsz, bool convert_flag = false) const;
validate() const289     int validate() const { return 0; }
290 
291   private:
292     friend class Iter;
293     friend class Data;
294     friend class BoundC;
295     // undefined
296     DataC(const Data&);
297     DataC& operator=(const DataC&);
298     const Spec& m_spec;
299     const bool m_allNullable;
300     const Uint8* m_buf;
301     Uint32 m_bufMaxLen;
302     // can be updated as part of Data instance
303     Uint32 m_cnt;
304   };
305 
306   /*
307    * Instance of an array of data values.  The values are packed into
308    * a byte buffer.  The buffer is also maintained as a single varbinary
309    * value if non-zero var bytes (length bytes) is specified.
310    *
311    * Data instances can be received from another source (such as table
312    * in database) and may not be native-endian.  Such instances must
313    * first be completed with desc_all() and convert().
314    */
315   class Data : public DataC {
316   public:
317     Data(const Spec& spec, bool allNullable, Uint32 varBytes);
318     // set buffer (calls reset)
319     void set_buf(void* buf, Uint32 bufMaxLen);
320     // reset but keep buffer (header is zeroed)
321     void reset();
322     // add non-null data items and return length in bytes
323     int add(const void* data, Uint32* len_out);
324     int add(const void* data, Uint32 cnt, Uint32* len_out);
325     // add null data items and return length 0 bytes
326     int add_null(Uint32* len_out);
327     int add_null(Uint32 cnt, Uint32* len_out);
328     // add from "plain old attr info"
329     int add_poai(const Uint32* poai, Uint32* len_out);
330     int add_poai(const Uint32* poai, Uint32 cnt, Uint32* len_out);
331     // call this before first use
332     int finalize();
333     // copy from
334     int copy(const DataC& d2);
335     // convert endian
336     int convert(Endian::Value to_endian);
337     // create complete instance from buffer contents
338     int desc_all(Uint32 cnt, Endian::Value from_endian);
339     // getters
340     Uint32 get_max_len() const;
341     Uint32 get_max_len4() const;
342     Uint32 get_var_bytes() const;
343     const void* get_full_buf() const;
344     Uint32 get_full_len() const;
345     Uint32 get_data_len() const;
346     Uint32 get_null_cnt() const;
347     Endian::Value get_endian() const;
348     // print
349     friend NdbOut& operator<<(NdbOut&, const Data&);
350     void print(NdbOut& out) const;
351     const char* print(char* buf, Uint32 bufsz) const;
352     int validate() const;
353 
354   private:
355     friend class Iter;
356     friend class Bound;
357     // undefined
358     Data(const Data&);
359     Data& operator=(const Data&);
360     int finalize_impl();
361     int convert_impl(Endian::Value to_endian);
362     const Uint32 m_varBytes;
363     Uint8* m_buf;
364     Uint32 m_bufMaxLen;
365     Endian::Value m_endian;
366     // iterator on items added
367     Iter m_iter;
368   };
369 
370   /*
371    * Read-only superclass of BoundC, analogous to DataC.  Initialized
372    * from a previously constructed Bound or DataC buffer.
373    */
374   class BoundC : public Error {
375   public:
376     BoundC(DataC& data);
~BoundC()377     ~BoundC() {}
378     // call this before first use
379     int finalize(int side);
380     // compare bound to key (may return 0 if bound is longer)
381     int cmp(const DataC& d2, Uint32 cnt, Uint32& num_eq) const;
382     // compare bounds (may return 0 if cnt is less than min length)
383     int cmp(const BoundC& b2, Uint32 cnt, Uint32& num_eq) const;
384     // getters
385     DataC& get_data() const;
386     int get_side() const;
387     // print
388     friend NdbOut& operator<<(NdbOut&, const BoundC&);
389     void print(NdbOut& out) const;
390     const char* print(char* buf, Uint32 bufsz) const;
391     int validate() const;
392 
393   private:
394     friend class Bound;
395     // undefined
396     BoundC(const BoundC&);
397     BoundC& operator=(const BoundC&);
398     DataC& m_data;
399     int m_side;
400   };
401 
402   /*
403    * Ordered index range bound consists of a partial key and a "side".
404    * The partial key is a Data instance where some initial number of
405    * values are present.  It is defined separately by the caller and
406    * passed to Bound ctor by reference.
407    */
408   class Bound : public BoundC {
409   public:
410     Bound(Data& data);
~Bound()411     ~Bound() {}
412     void reset();
413     // call this before first use
414     int finalize(int side);
415     // getters
416     Data& get_data() const;
417     // print
418     friend NdbOut& operator<<(NdbOut&, const Bound&);
419     void print(NdbOut& out) const;
420     const char* print(char* buf, Uint32 bufsz) const;
421     int validate() const;
422 
423   private:
424     // undefined
425     Bound(const Bound&);
426     Bound& operator=(const Bound&);
427     Data& m_data;
428   };
429 
430   /*
431    * Helper for print() methods.
432    */
433   struct Print {
434   private:
435     friend class Endian;
436     friend class Type;
437     friend class Spec;
438     friend class Iter;
439     friend class DataC;
440     friend class Data;
441     friend class BoundC;
442     friend class Bound;
443     Print(char* buf, Uint32 bufsz);
444     void print(const char* frm, ...);
445     char* m_buf;
446     Uint32 m_bufsz;
447     Uint32 m_sz;
448   };
449 };
450 
451 // NdbPack
452 
453 inline const NdbSqlUtil::Type&
getSqlType(Uint32 typeId)454 NdbPack::getSqlType(Uint32 typeId)
455 {
456   return NdbSqlUtil::m_typeList[typeId];
457 }
458 
459 // NdbPack::Error
460 
461 inline
Error()462 NdbPack::Error::Error()
463 {
464   m_error_code = 0;
465   m_error_line = 0;
466 }
467 
468 // NdbPack::Endian
469 
470 inline NdbPack::Endian::Value
get_endian()471 NdbPack::Endian::get_endian()
472 {
473 #ifndef WORDS_BIGENDIAN
474   return Little;
475 #else
476   return Big;
477 #endif
478 }
479 
480 // NdbPack::Type
481 
482 inline
Type()483 NdbPack::Type::Type()
484 {
485   m_typeId = NDB_TYPE_UNDEFINED;
486   m_byteSize = 0;
487   m_nullable = true;
488   m_csNumber = 0;
489   m_arrayType = 0;
490   m_nullbitPos = 0;
491 }
492 
493 inline
Type(int typeId,Uint32 byteSize,bool nullable,Uint32 csNumber)494 NdbPack::Type::Type(int typeId, Uint32 byteSize, bool nullable, Uint32 csNumber)
495 {
496   set(typeId, byteSize, nullable, csNumber);
497 }
498 
499 inline void
set(Uint32 typeId,Uint32 byteSize,bool nullable,Uint32 csNumber)500 NdbPack::Type::set(Uint32 typeId, Uint32 byteSize, bool nullable, Uint32 csNumber)
501 {
502   m_typeId = typeId;
503   m_byteSize = byteSize;
504   m_nullable = nullable;
505   m_csNumber = csNumber;
506 }
507 
508 inline Uint32
get_type_id() const509 NdbPack::Type::get_type_id() const
510 {
511   return m_typeId;
512 }
513 
514 inline Uint32
get_byte_size() const515 NdbPack::Type::get_byte_size() const
516 {
517   return m_byteSize;
518 }
519 
520 inline bool
get_nullable() const521 NdbPack::Type::get_nullable() const
522 {
523   return (bool)m_nullable;
524 }
525 
526 inline Uint32
get_cs_number() const527 NdbPack::Type::get_cs_number() const
528 {
529   return m_csNumber;
530 }
531 
532 inline Uint32
get_array_type() const533 NdbPack::Type::get_array_type() const
534 {
535   return m_arrayType;
536 }
537 
538 // NdbPack::Spec
539 
540 inline
Spec()541 NdbPack::Spec::Spec()
542 {
543   reset();
544   m_buf = 0;
545   m_bufMaxCnt = 0;
546 }
547 
548 inline void
set_buf(Type * buf,Uint32 bufMaxCnt)549 NdbPack::Spec::set_buf(Type* buf, Uint32 bufMaxCnt)
550 {
551   reset();
552   m_buf = buf;
553   m_bufMaxCnt = bufMaxCnt;
554 }
555 
556 inline void
set_buf(Type * buf)557 NdbPack::Spec::set_buf(Type* buf)
558 {
559   m_buf = buf;
560 }
561 
562 inline void
reset()563 NdbPack::Spec::reset()
564 {
565   m_cnt = 0;
566   m_nullableCnt = 0;
567   m_varsizeCnt = 0;
568   m_maxByteSize = 0;
569 }
570 
571 inline const NdbPack::Type&
get_type(Uint32 i) const572 NdbPack::Spec::get_type(Uint32 i) const
573 {
574   assert(i < m_cnt);
575   return m_buf[i];
576 }
577 
578 inline Uint32
get_cnt() const579 NdbPack::Spec::get_cnt() const
580 {
581   return m_cnt;
582 }
583 
584 inline Uint32
get_nullable_cnt(bool allNullable) const585 NdbPack::Spec::get_nullable_cnt(bool allNullable) const
586 {
587   if (!allNullable)
588     return m_nullableCnt;
589   else
590     return m_cnt;
591 }
592 
593 inline Uint32
get_nullmask_len(bool allNullable) const594 NdbPack::Spec::get_nullmask_len(bool allNullable) const
595 {
596   return (get_nullable_cnt(allNullable) + 7) / 8;
597 }
598 
599 inline Uint32
get_max_data_len(bool allNullable) const600 NdbPack::Spec::get_max_data_len(bool allNullable) const
601 {
602   return get_nullmask_len(allNullable) + m_maxByteSize;
603 }
604 
605 inline Uint32
get_min_var_bytes(bool allNullable) const606 NdbPack::Spec::get_min_var_bytes(bool allNullable) const
607 {
608   const Uint32 len = get_max_data_len(allNullable);
609   return (len < 256 ? 1 : 2);
610 }
611 
612 // NdbPack::Iter
613 
614 inline
Iter(const DataC & data)615 NdbPack::Iter::Iter(const DataC& data) :
616   m_spec(data.m_spec),
617   m_allNullable(data.m_allNullable)
618 {
619   reset();
620 }
621 
622 inline void
reset()623 NdbPack::Iter::reset()
624 {
625   m_itemPos = m_spec.get_nullmask_len(m_allNullable);
626   m_cnt = 0;
627   m_nullCnt = 0;
628   m_lenBytes = 0;
629   m_bareLen = 0;
630   m_itemLen = 0;
631 }
632 
633 // NdbPack::DataC
634 
635 inline
DataC(const Spec & spec,bool allNullable)636 NdbPack::DataC::DataC(const Spec& spec, bool allNullable) :
637   m_spec(spec),
638   m_allNullable(allNullable)
639 {
640   m_buf = 0;
641   m_bufMaxLen = 0;
642   m_cnt = 0;
643 }
644 
645 inline void
set_buf(const void * buf,Uint32 bufMaxLen,Uint32 cnt)646 NdbPack::DataC::set_buf(const void* buf, Uint32 bufMaxLen, Uint32 cnt)
647 {
648   m_buf = static_cast<const Uint8*>(buf);
649   m_bufMaxLen = bufMaxLen;
650   m_cnt = cnt;
651 }
652 
653 inline const NdbPack::Spec&
get_spec() const654 NdbPack::DataC::get_spec() const
655 {
656   return m_spec;
657 }
658 
659 inline bool
get_all_nullable() const660 NdbPack::DataC::get_all_nullable() const
661 {
662   return &m_allNullable;
663 }
664 
665 inline const void*
get_data_buf() const666 NdbPack::DataC::get_data_buf() const
667 {
668   return &m_buf[0];
669 }
670 
671 inline Uint32
get_cnt() const672 NdbPack::DataC::get_cnt() const
673 {
674   return m_cnt;
675 }
676 
677 inline bool
is_empty() const678 NdbPack::DataC::is_empty() const
679 {
680   return m_cnt == 0;
681 }
682 
683 inline bool
is_full() const684 NdbPack::DataC::is_full() const
685 {
686   return m_cnt == m_spec.m_cnt;
687 }
688 
689 // NdbPack::Data
690 
691 inline
Data(const Spec & spec,bool allNullable,Uint32 varBytes)692 NdbPack::Data::Data(const Spec& spec, bool allNullable, Uint32 varBytes) :
693   DataC(spec, allNullable),
694   m_varBytes(varBytes),
695   m_iter(*this)
696 {
697   m_buf = 0;
698   m_bufMaxLen = 0;
699   m_endian = Endian::get_endian();
700 }
701 
702 inline void
set_buf(void * buf,Uint32 bufMaxLen)703 NdbPack::Data::set_buf(void* buf, Uint32 bufMaxLen)
704 {
705   m_buf = static_cast<Uint8*>(buf);
706   m_bufMaxLen = bufMaxLen;
707   reset();
708   assert(bufMaxLen >= m_varBytes);
709   DataC::set_buf(&m_buf[m_varBytes], m_bufMaxLen - m_varBytes, 0);
710 }
711 
712 inline void
reset()713 NdbPack::Data::reset()
714 {
715   m_cnt = 0;  // in DataC
716   const Uint32 bytes = m_varBytes + m_spec.get_nullmask_len(m_allNullable);
717   memset(m_buf, 0, bytes);
718   m_endian = Endian::get_endian();
719   m_iter.reset();
720 }
721 
722 inline int
finalize()723 NdbPack::Data::finalize()
724 {
725   if (m_varBytes == 0 ||
726       finalize_impl() == 0)
727     return 0;
728   return -1;
729 }
730 
731 inline int
convert(Endian::Value to_endian)732 NdbPack::Data::convert(Endian::Value to_endian)
733 {
734   if (to_endian == Endian::Native)
735     to_endian = Endian::get_endian();
736   if (m_endian == to_endian)
737     return 0;
738   if (convert_impl(to_endian) == 0)
739   {
740     m_endian = to_endian;
741     return 0;
742   }
743   return -1;
744 }
745 
746 inline Uint32
get_max_len() const747 NdbPack::Data::get_max_len() const
748 {
749   return m_varBytes + m_spec.get_max_data_len(m_allNullable);
750 }
751 
752 inline Uint32
get_max_len4() const753 NdbPack::Data::get_max_len4() const
754 {
755   Uint32 len4 = get_max_len();
756   len4 += 3;
757   len4 /= 4;
758   len4 *= 4;
759   return len4;
760 }
761 
762 inline Uint32
get_var_bytes() const763 NdbPack::Data::get_var_bytes() const
764 {
765   return m_varBytes;
766 }
767 
768 inline const void*
get_full_buf() const769 NdbPack::Data::get_full_buf() const
770 {
771   return &m_buf[0];
772 }
773 
774 inline Uint32
get_full_len() const775 NdbPack::Data::get_full_len() const
776 {
777   return m_varBytes + m_iter.m_itemPos + m_iter.m_itemLen;
778 }
779 
780 inline Uint32
get_data_len() const781 NdbPack::Data::get_data_len() const
782 {
783   return m_iter.m_itemPos + m_iter.m_itemLen;
784 }
785 
786 inline Uint32
get_null_cnt() const787 NdbPack::Data::get_null_cnt() const
788 {
789   return m_iter.m_nullCnt;
790 }
791 
792 inline NdbPack::Endian::Value
get_endian() const793 NdbPack::Data::get_endian() const
794 {
795   return m_endian;
796 }
797 
798 // NdbPack::BoundC
799 
800 inline
BoundC(DataC & data)801 NdbPack::BoundC::BoundC(DataC& data) :
802   m_data(data)
803 {
804   m_side = 0;
805 }
806 
807 inline int
cmp(const DataC & d2,Uint32 cnt,Uint32 & num_eq) const808 NdbPack::BoundC::cmp(const DataC& d2, Uint32 cnt, Uint32& num_eq) const
809 {
810   const BoundC& b1 = *this;
811   const DataC& d1 = b1.m_data;
812   int res = d1.cmp(d2, cnt, num_eq);
813   if (res == 0 && d1.m_cnt <= d2.m_cnt)
814     res = b1.m_side;
815   return res;
816 }
817 
818 inline NdbPack::DataC&
get_data() const819 NdbPack::BoundC::get_data() const
820 {
821   return m_data;
822 }
823 
824 inline int
get_side() const825 NdbPack::BoundC::get_side() const
826 {
827   return m_side;
828 }
829 
830 // NdbPack::Bound
831 
832 inline
Bound(Data & data)833 NdbPack::Bound::Bound(Data& data) :
834   BoundC(data),
835   m_data(data)
836 {
837 }
838 
839 inline void
reset()840 NdbPack::Bound::reset()
841 {
842   m_data.reset();
843   m_side = 0;
844 }
845 
846 inline int
finalize(int side)847 NdbPack::Bound::finalize(int side)
848 {
849   if (m_data.finalize() == -1)
850   {
851     set_error(m_data);
852     return -1;
853   }
854   if (BoundC::finalize(side) == -1)
855     return -1;
856   return 0;
857 }
858 
859 inline NdbPack::Data&
get_data() const860 NdbPack::Bound::get_data() const
861 {
862   return m_data;
863 }
864 
865 #endif // NDB_PACK_HPP
866