1 /*
2    Copyright (c) 2011, 2021, Oracle and/or its affiliates.
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     const void* get_data_buf() const;
281     Uint32 get_cnt() const;
282     bool is_empty() const;
283     bool is_full() const;
284     // print
285     friend NdbOut& operator<<(NdbOut&, const DataC&);
286     void print(NdbOut& out) const;
287     const char* print(char* buf, Uint32 bufsz, bool convert_flag = false) const;
validate() const288     int validate() const { return 0; }
289 
290   private:
291     friend class Iter;
292     friend class Data;
293     friend class BoundC;
294     // undefined
295     DataC(const Data&);
296     DataC& operator=(const DataC&);
297     const Spec& m_spec;
298     const bool m_allNullable;
299     const Uint8* m_buf;
300     Uint32 m_bufMaxLen;
301     // can be updated as part of Data instance
302     Uint32 m_cnt;
303   };
304 
305   /*
306    * Instance of an array of data values.  The values are packed into
307    * a byte buffer.  The buffer is also maintained as a single varbinary
308    * value if non-zero var bytes (length bytes) is specified.
309    *
310    * Data instances can be received from another source (such as table
311    * in database) and may not be native-endian.  Such instances must
312    * first be completed with desc_all() and convert().
313    */
314   class Data : public DataC {
315   public:
316     Data(const Spec& spec, bool allNullable, Uint32 varBytes);
317     // set buffer (calls reset)
318     void set_buf(void* buf, Uint32 bufMaxLen);
319     // reset but keep buffer (header is zeroed)
320     void reset();
321     // add non-null data items and return length in bytes
322     int add(const void* data, Uint32* len_out);
323     int add(const void* data, Uint32 cnt, Uint32* len_out);
324     // add null data items and return length 0 bytes
325     int add_null(Uint32* len_out);
326     int add_null(Uint32 cnt, Uint32* len_out);
327     // add from "plain old attr info"
328     int add_poai(const Uint32* poai, Uint32* len_out);
329     int add_poai(const Uint32* poai, Uint32 cnt, Uint32* len_out);
330     // call this before first use
331     int finalize();
332     // copy from
333     int copy(const DataC& d2);
334     // convert endian
335     int convert(Endian::Value to_endian);
336     // create complete instance from buffer contents
337     int desc_all(Uint32 cnt, Endian::Value from_endian);
338     // getters
339     Uint32 get_max_len() const;
340     Uint32 get_max_len4() const;
341     Uint32 get_var_bytes() const;
342     const void* get_full_buf() const;
343     Uint32 get_full_len() const;
344     Uint32 get_data_len() const;
345     Uint32 get_null_cnt() const;
346     Endian::Value get_endian() const;
347     // print
348     friend NdbOut& operator<<(NdbOut&, const Data&);
349     void print(NdbOut& out) const;
350     const char* print(char* buf, Uint32 bufsz) const;
351     int validate() const;
352 
353   private:
354     friend class Iter;
355     friend class Bound;
356     // undefined
357     Data(const Data&);
358     Data& operator=(const Data&);
359     int finalize_impl();
360     int convert_impl(Endian::Value to_endian);
361     const Uint32 m_varBytes;
362     Uint8* m_buf;
363     Uint32 m_bufMaxLen;
364     Endian::Value m_endian;
365     // iterator on items added
366     Iter m_iter;
367   };
368 
369   /*
370    * Read-only superclass of BoundC, analogous to DataC.  Initialized
371    * from a previously constructed Bound or DataC buffer.
372    */
373   class BoundC : public Error {
374   public:
375     BoundC(DataC& data);
~BoundC()376     ~BoundC() {}
377     // call this before first use
378     int finalize(int side);
379     // compare bound to key (may return 0 if bound is longer)
380     int cmp(const DataC& d2, Uint32 cnt, Uint32& num_eq) const;
381     // compare bounds (may return 0 if cnt is less than min length)
382     int cmp(const BoundC& b2, Uint32 cnt, Uint32& num_eq) const;
383     // getters
384     DataC& get_data() const;
385     int get_side() const;
386     // print
387     friend NdbOut& operator<<(NdbOut&, const BoundC&);
388     void print(NdbOut& out) const;
389     const char* print(char* buf, Uint32 bufsz) const;
390     int validate() const;
391 
392   private:
393     friend class Bound;
394     // undefined
395     BoundC(const BoundC&);
396     BoundC& operator=(const BoundC&);
397     DataC& m_data;
398     int m_side;
399   };
400 
401   /*
402    * Ordered index range bound consists of a partial key and a "side".
403    * The partial key is a Data instance where some initial number of
404    * values are present.  It is defined separately by the caller and
405    * passed to Bound ctor by reference.
406    */
407   class Bound : public BoundC {
408   public:
409     Bound(Data& data);
~Bound()410     ~Bound() {}
411     void reset();
412     // call this before first use
413     int finalize(int side);
414     // getters
415     Data& get_data() const;
416     // print
417     friend NdbOut& operator<<(NdbOut&, const Bound&);
418     void print(NdbOut& out) const;
419     const char* print(char* buf, Uint32 bufsz) const;
420     int validate() const;
421 
422   private:
423     // undefined
424     Bound(const Bound&);
425     Bound& operator=(const Bound&);
426     Data& m_data;
427   };
428 
429   /*
430    * Helper for print() methods.
431    */
432   struct Print {
433   private:
434     friend class Endian;
435     friend class Type;
436     friend class Spec;
437     friend class Iter;
438     friend class DataC;
439     friend class Data;
440     friend class BoundC;
441     friend class Bound;
442     Print(char* buf, Uint32 bufsz);
443     void print(const char* frm, ...);
444     char* m_buf;
445     Uint32 m_bufsz;
446     Uint32 m_sz;
447   };
448 };
449 
450 // NdbPack
451 
452 inline const NdbSqlUtil::Type&
getSqlType(Uint32 typeId)453 NdbPack::getSqlType(Uint32 typeId)
454 {
455   return NdbSqlUtil::m_typeList[typeId];
456 }
457 
458 // NdbPack::Error
459 
460 inline
Error()461 NdbPack::Error::Error()
462 {
463   m_error_code = 0;
464   m_error_line = 0;
465 }
466 
467 // NdbPack::Endian
468 
469 inline NdbPack::Endian::Value
get_endian()470 NdbPack::Endian::get_endian()
471 {
472 #ifndef WORDS_BIGENDIAN
473   return Little;
474 #else
475   return Big;
476 #endif
477 }
478 
479 // NdbPack::Type
480 
481 inline
Type()482 NdbPack::Type::Type()
483 {
484   m_typeId = NDB_TYPE_UNDEFINED;
485   m_byteSize = 0;
486   m_nullable = true;
487   m_csNumber = 0;
488   m_arrayType = 0;
489   m_nullbitPos = 0;
490 }
491 
492 inline
Type(int typeId,Uint32 byteSize,bool nullable,Uint32 csNumber)493 NdbPack::Type::Type(int typeId, Uint32 byteSize, bool nullable, Uint32 csNumber)
494 {
495   set(typeId, byteSize, nullable, csNumber);
496 }
497 
498 inline void
set(Uint32 typeId,Uint32 byteSize,bool nullable,Uint32 csNumber)499 NdbPack::Type::set(Uint32 typeId, Uint32 byteSize, bool nullable, Uint32 csNumber)
500 {
501   m_typeId = typeId;
502   m_byteSize = byteSize;
503   m_nullable = nullable;
504   m_csNumber = csNumber;
505 }
506 
507 inline Uint32
get_type_id() const508 NdbPack::Type::get_type_id() const
509 {
510   return m_typeId;
511 }
512 
513 inline Uint32
get_byte_size() const514 NdbPack::Type::get_byte_size() const
515 {
516   return m_byteSize;
517 }
518 
519 inline bool
get_nullable() const520 NdbPack::Type::get_nullable() const
521 {
522   return (bool)m_nullable;
523 }
524 
525 inline Uint32
get_cs_number() const526 NdbPack::Type::get_cs_number() const
527 {
528   return m_csNumber;
529 }
530 
531 inline Uint32
get_array_type() const532 NdbPack::Type::get_array_type() const
533 {
534   return m_arrayType;
535 }
536 
537 // NdbPack::Spec
538 
539 inline
Spec()540 NdbPack::Spec::Spec()
541 {
542   reset();
543   m_buf = 0;
544   m_bufMaxCnt = 0;
545 }
546 
547 inline void
set_buf(Type * buf,Uint32 bufMaxCnt)548 NdbPack::Spec::set_buf(Type* buf, Uint32 bufMaxCnt)
549 {
550   reset();
551   m_buf = buf;
552   m_bufMaxCnt = bufMaxCnt;
553 }
554 
555 inline void
set_buf(Type * buf)556 NdbPack::Spec::set_buf(Type* buf)
557 {
558   m_buf = buf;
559 }
560 
561 inline void
reset()562 NdbPack::Spec::reset()
563 {
564   m_cnt = 0;
565   m_nullableCnt = 0;
566   m_varsizeCnt = 0;
567   m_maxByteSize = 0;
568 }
569 
570 inline const NdbPack::Type&
get_type(Uint32 i) const571 NdbPack::Spec::get_type(Uint32 i) const
572 {
573   assert(i < m_cnt);
574   return m_buf[i];
575 }
576 
577 inline Uint32
get_cnt() const578 NdbPack::Spec::get_cnt() const
579 {
580   return m_cnt;
581 }
582 
583 inline Uint32
get_nullable_cnt(bool allNullable) const584 NdbPack::Spec::get_nullable_cnt(bool allNullable) const
585 {
586   if (!allNullable)
587     return m_nullableCnt;
588   else
589     return m_cnt;
590 }
591 
592 inline Uint32
get_nullmask_len(bool allNullable) const593 NdbPack::Spec::get_nullmask_len(bool allNullable) const
594 {
595   return (get_nullable_cnt(allNullable) + 7) / 8;
596 }
597 
598 inline Uint32
get_max_data_len(bool allNullable) const599 NdbPack::Spec::get_max_data_len(bool allNullable) const
600 {
601   return get_nullmask_len(allNullable) + m_maxByteSize;
602 }
603 
604 inline Uint32
get_min_var_bytes(bool allNullable) const605 NdbPack::Spec::get_min_var_bytes(bool allNullable) const
606 {
607   const Uint32 len = get_max_data_len(allNullable);
608   return (len < 256 ? 1 : 2);
609 }
610 
611 // NdbPack::Iter
612 
613 inline
Iter(const DataC & data)614 NdbPack::Iter::Iter(const DataC& data) :
615   m_spec(data.m_spec),
616   m_allNullable(data.m_allNullable)
617 {
618   reset();
619 }
620 
621 inline void
reset()622 NdbPack::Iter::reset()
623 {
624   m_itemPos = m_spec.get_nullmask_len(m_allNullable);
625   m_cnt = 0;
626   m_nullCnt = 0;
627   m_lenBytes = 0;
628   m_bareLen = 0;
629   m_itemLen = 0;
630 }
631 
632 // NdbPack::DataC
633 
634 inline
DataC(const Spec & spec,bool allNullable)635 NdbPack::DataC::DataC(const Spec& spec, bool allNullable) :
636   m_spec(spec),
637   m_allNullable(allNullable)
638 {
639   m_buf = 0;
640   m_bufMaxLen = 0;
641   m_cnt = 0;
642 }
643 
644 inline void
set_buf(const void * buf,Uint32 bufMaxLen,Uint32 cnt)645 NdbPack::DataC::set_buf(const void* buf, Uint32 bufMaxLen, Uint32 cnt)
646 {
647   m_buf = static_cast<const Uint8*>(buf);
648   m_bufMaxLen = bufMaxLen;
649   m_cnt = cnt;
650 }
651 
652 inline const NdbPack::Spec&
get_spec() const653 NdbPack::DataC::get_spec() const
654 {
655   return m_spec;
656 }
657 
658 inline const void*
get_data_buf() const659 NdbPack::DataC::get_data_buf() const
660 {
661   return &m_buf[0];
662 }
663 
664 inline Uint32
get_cnt() const665 NdbPack::DataC::get_cnt() const
666 {
667   return m_cnt;
668 }
669 
670 inline bool
is_empty() const671 NdbPack::DataC::is_empty() const
672 {
673   return m_cnt == 0;
674 }
675 
676 inline bool
is_full() const677 NdbPack::DataC::is_full() const
678 {
679   return m_cnt == m_spec.m_cnt;
680 }
681 
682 // NdbPack::Data
683 
684 inline
Data(const Spec & spec,bool allNullable,Uint32 varBytes)685 NdbPack::Data::Data(const Spec& spec, bool allNullable, Uint32 varBytes) :
686   DataC(spec, allNullable),
687   m_varBytes(varBytes),
688   m_iter(*this)
689 {
690   m_buf = 0;
691   m_bufMaxLen = 0;
692   m_endian = Endian::get_endian();
693 }
694 
695 inline void
set_buf(void * buf,Uint32 bufMaxLen)696 NdbPack::Data::set_buf(void* buf, Uint32 bufMaxLen)
697 {
698   m_buf = static_cast<Uint8*>(buf);
699   m_bufMaxLen = bufMaxLen;
700   reset();
701   assert(bufMaxLen >= m_varBytes);
702   DataC::set_buf(&m_buf[m_varBytes], m_bufMaxLen - m_varBytes, 0);
703 }
704 
705 inline void
reset()706 NdbPack::Data::reset()
707 {
708   m_cnt = 0;  // in DataC
709   const Uint32 bytes = m_varBytes + m_spec.get_nullmask_len(m_allNullable);
710   memset(m_buf, 0, bytes);
711   m_endian = Endian::get_endian();
712   m_iter.reset();
713 }
714 
715 inline int
finalize()716 NdbPack::Data::finalize()
717 {
718   if (m_varBytes == 0 ||
719       finalize_impl() == 0)
720     return 0;
721   return -1;
722 }
723 
724 inline int
convert(Endian::Value to_endian)725 NdbPack::Data::convert(Endian::Value to_endian)
726 {
727   if (to_endian == Endian::Native)
728     to_endian = Endian::get_endian();
729   if (m_endian == to_endian)
730     return 0;
731   if (convert_impl(to_endian) == 0)
732   {
733     m_endian = to_endian;
734     return 0;
735   }
736   return -1;
737 }
738 
739 inline Uint32
get_max_len() const740 NdbPack::Data::get_max_len() const
741 {
742   return m_varBytes + m_spec.get_max_data_len(m_allNullable);
743 }
744 
745 inline Uint32
get_max_len4() const746 NdbPack::Data::get_max_len4() const
747 {
748   Uint32 len4 = get_max_len();
749   len4 += 3;
750   len4 /= 4;
751   len4 *= 4;
752   return len4;
753 }
754 
755 inline Uint32
get_var_bytes() const756 NdbPack::Data::get_var_bytes() const
757 {
758   return m_varBytes;
759 }
760 
761 inline const void*
get_full_buf() const762 NdbPack::Data::get_full_buf() const
763 {
764   return &m_buf[0];
765 }
766 
767 inline Uint32
get_full_len() const768 NdbPack::Data::get_full_len() const
769 {
770   return m_varBytes + m_iter.m_itemPos + m_iter.m_itemLen;
771 }
772 
773 inline Uint32
get_data_len() const774 NdbPack::Data::get_data_len() const
775 {
776   return m_iter.m_itemPos + m_iter.m_itemLen;
777 }
778 
779 inline Uint32
get_null_cnt() const780 NdbPack::Data::get_null_cnt() const
781 {
782   return m_iter.m_nullCnt;
783 }
784 
785 inline NdbPack::Endian::Value
get_endian() const786 NdbPack::Data::get_endian() const
787 {
788   return m_endian;
789 }
790 
791 // NdbPack::BoundC
792 
793 inline
BoundC(DataC & data)794 NdbPack::BoundC::BoundC(DataC& data) :
795   m_data(data)
796 {
797   m_side = 0;
798 }
799 
800 inline int
cmp(const DataC & d2,Uint32 cnt,Uint32 & num_eq) const801 NdbPack::BoundC::cmp(const DataC& d2, Uint32 cnt, Uint32& num_eq) const
802 {
803   const BoundC& b1 = *this;
804   const DataC& d1 = b1.m_data;
805   int res = d1.cmp(d2, cnt, num_eq);
806   if (res == 0 && d1.m_cnt <= d2.m_cnt)
807     res = b1.m_side;
808   return res;
809 }
810 
811 inline NdbPack::DataC&
get_data() const812 NdbPack::BoundC::get_data() const
813 {
814   return m_data;
815 }
816 
817 inline int
get_side() const818 NdbPack::BoundC::get_side() const
819 {
820   return m_side;
821 }
822 
823 // NdbPack::Bound
824 
825 inline
Bound(Data & data)826 NdbPack::Bound::Bound(Data& data) :
827   BoundC(data),
828   m_data(data)
829 {
830 }
831 
832 inline void
reset()833 NdbPack::Bound::reset()
834 {
835   m_data.reset();
836   m_side = 0;
837 }
838 
839 inline int
finalize(int side)840 NdbPack::Bound::finalize(int side)
841 {
842   if (m_data.finalize() == -1)
843   {
844     set_error(m_data);
845     return -1;
846   }
847   if (BoundC::finalize(side) == -1)
848     return -1;
849   return 0;
850 }
851 
852 inline NdbPack::Data&
get_data() const853 NdbPack::Bound::get_data() const
854 {
855   return m_data;
856 }
857 
858 #endif // NDB_PACK_HPP
859