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