summaryrefslogtreecommitdiffstats
path: root/storage/connect/valblk.cpp
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 18:07:14 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 18:07:14 +0000
commita175314c3e5827eb193872241446f2f8f5c9d33c (patch)
treecd3d60ca99ae00829c52a6ca79150a5b6e62528b /storage/connect/valblk.cpp
parentInitial commit. (diff)
downloadmariadb-10.5-upstream.tar.xz
mariadb-10.5-upstream.zip
Adding upstream version 1:10.5.12.upstream/1%10.5.12upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'storage/connect/valblk.cpp')
-rw-r--r--storage/connect/valblk.cpp1417
1 files changed, 1417 insertions, 0 deletions
diff --git a/storage/connect/valblk.cpp b/storage/connect/valblk.cpp
new file mode 100644
index 00000000..40d97517
--- /dev/null
+++ b/storage/connect/valblk.cpp
@@ -0,0 +1,1417 @@
+/************ Valblk C++ Functions Source Code File (.CPP) *************/
+/* Name: VALBLK.CPP Version 2.3 */
+/* */
+/* (C) Copyright to the author Olivier BERTRAND 2005-2017 */
+/* */
+/* This file contains the VALBLK and derived classes functions. */
+/* Second family is VALBLK, representing simple suballocated arrays */
+/* of values treated sequentially by FIX, BIN and VCT tables and */
+/* columns, as well for min/max blocks as for VCT column blocks. */
+/* Q&A: why not using only one family ? Simple values are arrays that */
+/* have only one element and arrays could have functions for all kind */
+/* of processing. The answer is a-because historically it was simpler */
+/* to do that way, b-because of performance on single values, and c- */
+/* to avoid too complicated classes and unuseful duplication of many */
+/* functions used on one family only. The drawback is that for new */
+/* types of objects, we shall have more classes to update. */
+/* This is why we are now using a template class for many types. */
+/* Currently the only implemented types are PSZ, chars, int, short, */
+/* DATE, longlong, double and tiny. Fix numeric ones can be unsigned. */
+/***********************************************************************/
+
+/***********************************************************************/
+/* Include relevant MariaDB header file. */
+/***********************************************************************/
+#include "my_global.h"
+#if defined(_WIN32)
+//#include <windows.h>
+#else
+#include "osutil.h"
+#include "string.h"
+#endif
+
+/***********************************************************************/
+/* Include required application header files */
+/* global.h is header containing all global Plug declarations. */
+/* plgdbsem.h is header containing the DB applic. declarations. */
+/* valblk.h is header containing VALBLK derived classes declares. */
+/***********************************************************************/
+#include "global.h"
+#include "plgdbsem.h"
+#include "valblk.h"
+
+#define CheckBlanks assert(!Blanks);
+#define CheckParms(V, N) ChkIndx(N); ChkTyp(V);
+
+extern MBLOCK Nmblk; /* Used to initialize MBLOCK's */
+
+/***********************************************************************/
+/* AllocValBlock: allocate a VALBLK according to type. */
+/***********************************************************************/
+PVBLK AllocValBlock(PGLOBAL g, void *mp, int type, int nval, int len,
+ int prec, bool check, bool blank, bool un)
+ {
+ PVBLK blkp;
+
+ if (trace(1))
+ htrc("AVB: mp=%p type=%d nval=%d len=%d check=%u blank=%u\n",
+ mp, type, nval, len, check, blank);
+
+ switch (type) {
+ case TYPE_STRING:
+ case TYPE_BIN:
+ case TYPE_DECIM:
+ if (len)
+ blkp = new(g) CHRBLK(mp, nval, type, len, prec, blank);
+ else
+ blkp = new(g) STRBLK(g, mp, nval, type);
+
+ break;
+ case TYPE_SHORT:
+ if (un)
+ blkp = new(g) TYPBLK<ushort>(mp, nval, type, 0, true);
+ else
+ blkp = new(g) TYPBLK<short>(mp, nval, type);
+
+ break;
+ case TYPE_INT:
+ if (un)
+ blkp = new(g) TYPBLK<uint>(mp, nval, type, 0, true);
+ else
+ blkp = new(g) TYPBLK<int>(mp, nval, type);
+
+ break;
+ case TYPE_DATE: // ?????
+ blkp = new(g) DATBLK(mp, nval);
+ break;
+ case TYPE_BIGINT:
+ if (un)
+ blkp = new(g) TYPBLK<ulonglong>(mp, nval, type, 0, true);
+ else
+ blkp = new(g) TYPBLK<longlong>(mp, nval, type);
+
+ break;
+ case TYPE_DOUBLE:
+ blkp = new(g) TYPBLK<double>(mp, nval, type, prec);
+ break;
+ case TYPE_TINY:
+ if (un)
+ blkp = new(g) TYPBLK<uchar>(mp, nval, type, 0, true);
+ else
+ blkp = new(g) TYPBLK<char>(mp, nval, type);
+
+ break;
+ case TYPE_PCHAR:
+ blkp = new(g) PTRBLK(g, mp, nval);
+ break;
+ default:
+ sprintf(g->Message, MSG(BAD_VALBLK_TYPE), type);
+ return NULL;
+ } // endswitch Type
+
+ return (blkp->Init(g, check)) ? NULL : blkp;
+ } // end of AllocValBlock
+
+/* -------------------------- Class VALBLK --------------------------- */
+
+/***********************************************************************/
+/* Constructor. */
+/***********************************************************************/
+VALBLK::VALBLK(void *mp, int type, int nval, bool un)
+ {
+ Mblk = Nmblk;
+ Blkp = mp;
+ To_Nulls = NULL;
+ Check = true;
+ Nullable = false;
+ Unsigned = un;
+ Type = type;
+ Nval = nval;
+ Prec = 0;
+ } // end of VALBLK constructor
+
+/***********************************************************************/
+/* Raise error for numeric types. */
+/***********************************************************************/
+PSZ VALBLK::GetCharValue(int)
+ {
+ PGLOBAL& g = Global;
+
+ assert(g);
+ sprintf(g->Message, MSG(NO_CHAR_FROM), Type);
+ throw Type;
+ return NULL;
+ } // end of GetCharValue
+
+/***********************************************************************/
+/* Set format so formatted dates can be converted on input. */
+/***********************************************************************/
+bool VALBLK::SetFormat(PGLOBAL g, PCSZ, int, int)
+ {
+ sprintf(g->Message, MSG(NO_DATE_FMT), Type);
+ return true;
+ } // end of SetFormat
+
+/***********************************************************************/
+/* Set the index of the location of value and return true if found. */
+/* To be used on ascending sorted arrays only. */
+/* Currently used by some BLKFIL classes only. */
+/***********************************************************************/
+bool VALBLK::Locate(PVAL vp, int& i)
+ {
+ ChkTyp(vp);
+
+ int n = 1;
+
+ for (i = 0; i < Nval; i++)
+ if ((n = CompVal(vp, i)) <= 0)
+ break;
+
+ return (!n);
+ } // end of Locate
+
+/***********************************************************************/
+/* Set Nullable and allocate the Null array. */
+/***********************************************************************/
+void VALBLK::SetNullable(bool b)
+ {
+ if ((Nullable = b)) {
+ To_Nulls = (char*)PlugSubAlloc(Global, NULL, Nval);
+ memset(To_Nulls, 0, Nval);
+ } else
+ To_Nulls = NULL;
+
+ } // end of SetNullable
+
+/***********************************************************************/
+/* Buffer allocation routine. */
+/***********************************************************************/
+bool VALBLK::AllocBuff(PGLOBAL g, size_t size)
+ {
+ Mblk.Size = size;
+
+ if (!(Blkp = PlgDBalloc(g, NULL, Mblk))) {
+ sprintf(g->Message, MSG(MEM_ALLOC_ERR), "Blkp", (int) Mblk.Size);
+ fprintf(stderr, "%s\n", g->Message);
+ return true;
+ } // endif Blkp
+
+ return false;
+ } // end of AllocBuff
+
+/***********************************************************************/
+/* Check functions. */
+/***********************************************************************/
+void VALBLK::ChkIndx(int n)
+ {
+ if (n < 0 || n >= Nval) {
+ PGLOBAL& g = Global;
+ xtrc(1, "ChkIndx: n=%d Nval=%d\n", n, Nval);
+ strcpy(g->Message, MSG(BAD_VALBLK_INDX));
+ throw Type;
+ } // endif n
+
+ } // end of ChkIndx
+
+void VALBLK::ChkTyp(PVAL v)
+ {
+ if (Check && (Type != v->GetType() || Unsigned != v->IsUnsigned())) {
+ PGLOBAL& g = Global;
+ xtrc(1, "ChkTyp: Type=%d valType=%d\n", Type, v->GetType());
+ strcpy(g->Message, MSG(VALTYPE_NOMATCH));
+ throw Type;
+ } // endif Type
+
+ } // end of ChkTyp
+
+void VALBLK::ChkTyp(PVBLK vb)
+ {
+ if (Check && (Type != vb->GetType() || Unsigned != vb->IsUnsigned())) {
+ PGLOBAL& g = Global;
+ strcpy(g->Message, MSG(VALTYPE_NOMATCH));
+ throw Type;
+ } // endif Type
+
+ } // end of ChkTyp
+
+/* -------------------------- Class TYPBLK --------------------------- */
+
+/***********************************************************************/
+/* Constructor. */
+/***********************************************************************/
+template <class TYPE>
+TYPBLK<TYPE>::TYPBLK(void *mp, int nval, int type, int prec, bool un)
+ : VALBLK(mp, type, nval, un), Typp((TYPE*&)Blkp)
+ {
+ Prec = prec;
+ Fmt = GetFmt(Type);
+ } // end of TYPBLK constructor
+
+/***********************************************************************/
+/* Initialization routine. */
+/***********************************************************************/
+template <class TYPE>
+bool TYPBLK<TYPE>::Init(PGLOBAL g, bool check)
+ {
+ if (!Blkp)
+ if (AllocBuff(g, Nval * sizeof(TYPE)))
+ return true;
+
+ Check = check;
+ Global = g;
+ return false;
+ } // end of Init
+
+/***********************************************************************/
+/* TYPVAL GetCharString: get string representation of a typed value. */
+/***********************************************************************/
+template <class TYPE>
+char *TYPBLK<TYPE>::GetCharString(char *p, int n)
+ {
+ sprintf(p, Fmt, Typp[n]);
+ return p;
+ } // end of GetCharString
+
+template <>
+char *TYPBLK<double>::GetCharString(char *p, int n)
+ {
+ sprintf(p, Fmt, Prec, Typp[n]);
+ return p;
+ } // end of GetCharString
+
+/***********************************************************************/
+/* Set one value in a block. */
+/***********************************************************************/
+template <class TYPE>
+void TYPBLK<TYPE>::SetValue(PVAL valp, int n)
+ {
+ bool b;
+
+ ChkIndx(n);
+ ChkTyp(valp);
+
+ if (!(b = valp->IsNull()))
+ Typp[n] = GetTypedValue(valp);
+ else
+ Reset(n);
+
+ SetNull(n, b && Nullable);
+ } // end of SetValue
+
+template <>
+int TYPBLK<int>::GetTypedValue(PVAL valp)
+ {return valp->GetIntValue();}
+
+template <>
+uint TYPBLK<uint>::GetTypedValue(PVAL valp)
+ {return valp->GetUIntValue();}
+
+template <>
+short TYPBLK<short>::GetTypedValue(PVAL valp)
+ {return valp->GetShortValue();}
+
+template <>
+ushort TYPBLK<ushort>::GetTypedValue(PVAL valp)
+ {return valp->GetUShortValue();}
+
+template <>
+longlong TYPBLK<longlong>::GetTypedValue(PVAL valp)
+ {return valp->GetBigintValue();}
+
+template <>
+ulonglong TYPBLK<ulonglong>::GetTypedValue(PVAL valp)
+ {return valp->GetUBigintValue();}
+
+template <>
+double TYPBLK<double>::GetTypedValue(PVAL valp)
+ {return valp->GetFloatValue();}
+
+template <>
+char TYPBLK<char>::GetTypedValue(PVAL valp)
+ {return valp->GetTinyValue();}
+
+template <>
+uchar TYPBLK<uchar>::GetTypedValue(PVAL valp)
+ {return valp->GetUTinyValue();}
+
+/***********************************************************************/
+/* Set one value in a block from a zero terminated string. */
+/***********************************************************************/
+template <class TYPE>
+void TYPBLK<TYPE>::SetValue(PCSZ p, int n)
+ {
+ ChkIndx(n);
+
+ if (Check) {
+ PGLOBAL& g = Global;
+ strcpy(g->Message, MSG(BAD_SET_STRING));
+ throw Type;
+ } // endif Check
+
+ bool minus;
+ ulonglong maxval = MaxVal();
+ ulonglong val = CharToNumber(p, strlen(p), maxval, Unsigned, &minus);
+
+ if (minus && val < maxval)
+ Typp[n] = (TYPE)(-(signed)val);
+ else
+ Typp[n] = (TYPE)val;
+
+ SetNull(n, false);
+ } // end of SetValue
+
+template <class TYPE>
+ulonglong TYPBLK<TYPE>::MaxVal(void) {DBUG_ASSERT(false); return 0;}
+
+template <>
+ulonglong TYPBLK<short>::MaxVal(void) {return INT_MAX16;}
+
+template <>
+ulonglong TYPBLK<ushort>::MaxVal(void) {return UINT_MAX16;}
+
+template <>
+ulonglong TYPBLK<int>::MaxVal(void) {return INT_MAX32;}
+
+template <>
+ulonglong TYPBLK<uint>::MaxVal(void) {return UINT_MAX32;}
+
+template <>
+ulonglong TYPBLK<char>::MaxVal(void) {return INT_MAX8;}
+
+template <>
+ulonglong TYPBLK<uchar>::MaxVal(void) {return UINT_MAX8;}
+
+template <>
+ulonglong TYPBLK<longlong>::MaxVal(void) {return INT_MAX64;}
+
+template <>
+ulonglong TYPBLK<ulonglong>::MaxVal(void) {return ULONGLONG_MAX;}
+
+template <>
+void TYPBLK<double>::SetValue(PCSZ p, int n)
+ {
+ ChkIndx(n);
+
+ if (Check) {
+ PGLOBAL& g = Global;
+ strcpy(g->Message, MSG(BAD_SET_STRING));
+ throw Type;
+ } // endif Check
+
+ Typp[n] = atof(p);
+ SetNull(n, false);
+ } // end of SetValue
+
+/***********************************************************************/
+/* Set one value in a block from an array of characters. */
+/***********************************************************************/
+template <class TYPE>
+void TYPBLK<TYPE>::SetValue(PCSZ sp, uint len, int n)
+ {
+ PGLOBAL& g = Global;
+ PSZ spz = (PSZ)PlugSubAlloc(g, NULL, 0); // Temporary
+
+ if (sp)
+ memcpy(spz, sp, len);
+
+ spz[len] = 0;
+ SetValue(spz, n);
+ } // end of SetValue
+
+/***********************************************************************/
+/* Set one value in a block from a value in another block. */
+/***********************************************************************/
+template <class TYPE>
+void TYPBLK<TYPE>::SetValue(PVBLK pv, int n1, int n2)
+ {
+ bool b;
+
+ ChkIndx(n1);
+ ChkTyp(pv);
+
+ if (!(b = pv->IsNull(n2) && Nullable))
+ Typp[n1] = GetTypedValue(pv, n2);
+ else
+ Reset(n1);
+
+ SetNull(n1, b);
+ } // end of SetValue
+
+template <>
+int TYPBLK<int>::GetTypedValue(PVBLK blk, int n)
+ {return blk->GetIntValue(n);}
+
+template <>
+uint TYPBLK<uint>::GetTypedValue(PVBLK blk, int n)
+ {return blk->GetUIntValue(n);}
+
+template <>
+short TYPBLK<short>::GetTypedValue(PVBLK blk, int n)
+ {return blk->GetShortValue(n);}
+
+template <>
+ushort TYPBLK<ushort>::GetTypedValue(PVBLK blk, int n)
+ {return blk->GetUShortValue(n);}
+
+template <>
+longlong TYPBLK<longlong>::GetTypedValue(PVBLK blk, int n)
+ {return blk->GetBigintValue(n);}
+
+template <>
+ulonglong TYPBLK<ulonglong>::GetTypedValue(PVBLK blk, int n)
+ {return blk->GetUBigintValue(n);}
+
+template <>
+double TYPBLK<double>::GetTypedValue(PVBLK blk, int n)
+ {return blk->GetFloatValue(n);}
+
+template <>
+char TYPBLK<char>::GetTypedValue(PVBLK blk, int n)
+ {return blk->GetTinyValue(n);}
+
+template <>
+uchar TYPBLK<uchar>::GetTypedValue(PVBLK blk, int n)
+ {return blk->GetUTinyValue(n);}
+
+/***********************************************************************/
+/* Set one value in a block if val is less than the current value. */
+/***********************************************************************/
+template <class TYPE>
+void TYPBLK<TYPE>::SetMin(PVAL valp, int n)
+ {
+ CheckParms(valp, n)
+ TYPE tval = GetTypedValue(valp);
+ TYPE& tmin = Typp[n];
+
+ if (tval < tmin)
+ tmin = tval;
+
+ } // end of SetMin
+
+/***********************************************************************/
+/* Set one value in a block if val is greater than the current value. */
+/***********************************************************************/
+template <class TYPE>
+void TYPBLK<TYPE>::SetMax(PVAL valp, int n)
+ {
+ CheckParms(valp, n)
+ TYPE tval = GetTypedValue(valp);
+ TYPE& tmin = Typp[n];
+
+ if (tval > tmin)
+ tmin = tval;
+
+ } // end of SetMax
+
+#if 0
+/***********************************************************************/
+/* Set many values in a block from values in another block. */
+/***********************************************************************/
+template <class TYPE>
+void TYPBLK<TYPE>::SetValues(PVBLK pv, int k, int n)
+ {
+ CheckType(pv)
+ TYPE *lp = ((TYPBLK*)pv)->Typp;
+
+ for (int i = k; i < n; i++) // TODO
+ Typp[i] = lp[i];
+
+ } // end of SetValues
+#endif // 0
+
+/***********************************************************************/
+/* Move one value from i to j. */
+/***********************************************************************/
+template <class TYPE>
+void TYPBLK<TYPE>::Move(int i, int j)
+ {
+ Typp[j] = Typp[i];
+ MoveNull(i, j);
+ } // end of Move
+
+/***********************************************************************/
+/* Compare a Value object with the nth value of the block. */
+/***********************************************************************/
+template <class TYPE>
+int TYPBLK<TYPE>::CompVal(PVAL vp, int n)
+ {
+#if defined(_DEBUG)
+ ChkIndx(n);
+ ChkTyp(vp);
+#endif // _DEBUG
+ TYPE mlv = Typp[n];
+ TYPE vlv = GetTypedValue(vp);
+
+ return (vlv > mlv) ? 1 : (vlv < mlv) ? (-1) : 0;
+ } // end of CompVal
+
+/***********************************************************************/
+/* Compare two values of the block. */
+/***********************************************************************/
+template <class TYPE>
+int TYPBLK<TYPE>::CompVal(int i1, int i2)
+ {
+ TYPE lv1 = Typp[i1];
+ TYPE lv2 = Typp[i2];
+
+ return (lv1 > lv2) ? 1 : (lv1 < lv2) ? (-1) : 0;
+ } // end of CompVal
+
+/***********************************************************************/
+/* Get a pointer on the nth value of the block. */
+/***********************************************************************/
+template <class TYPE>
+void *TYPBLK<TYPE>::GetValPtr(int n)
+ {
+ ChkIndx(n);
+ return Typp + n;
+ } // end of GetValPtr
+
+/***********************************************************************/
+/* Get a pointer on the nth value of the block. */
+/***********************************************************************/
+template <class TYPE>
+void *TYPBLK<TYPE>::GetValPtrEx(int n)
+ {
+ ChkIndx(n);
+ return Typp + n;
+ } // end of GetValPtrEx
+
+/***********************************************************************/
+/* Returns index of matching value in block or -1. */
+/***********************************************************************/
+template <class TYPE>
+int TYPBLK<TYPE>::Find(PVAL vp)
+ {
+ ChkTyp(vp);
+
+ int i;
+ TYPE n = GetTypedValue(vp);
+
+ for (i = 0; i < Nval; i++)
+ if (n == Typp[i])
+ break;
+
+ return (i < Nval) ? i : (-1);
+ } // end of Find
+
+/***********************************************************************/
+/* Returns the length of the longest string in the block. */
+/***********************************************************************/
+template <class TYPE>
+int TYPBLK<TYPE>::GetMaxLength(void)
+ {
+ char buf[64];
+ int i, n, m;
+
+ for (i = n = 0; i < Nval; i++) {
+ m = sprintf(buf, Fmt, Typp[i]);
+ n = MY_MAX(n, m);
+ } // endfor i
+
+ return n;
+ } // end of GetMaxLength
+
+
+/* -------------------------- Class CHRBLK --------------------------- */
+
+/***********************************************************************/
+/* Constructor. */
+/***********************************************************************/
+CHRBLK::CHRBLK(void *mp, int nval, int type, int len, int prec, bool blank)
+ : VALBLK(mp, type, nval), Chrp((char*&)Blkp)
+ {
+ Valp = NULL;
+ Blanks = blank;
+ Ci = (prec != 0);
+ Long = len;
+ } // end of CHRBLK constructor
+
+/***********************************************************************/
+/* Initialization routine. */
+/***********************************************************************/
+bool CHRBLK::Init(PGLOBAL g, bool check)
+ {
+ Valp = (char*)PlugSubAlloc(g, NULL, Long + 1);
+ Valp[Long] = '\0';
+
+ if (!Blkp)
+ if (AllocBuff(g, Nval * Long))
+ return true;
+
+ Check = check;
+ Global = g;
+ return false;
+ } // end of Init
+
+/***********************************************************************/
+/* Reset nth element to a null string. */
+/***********************************************************************/
+void CHRBLK::Reset(int n)
+ {
+ if (Blanks)
+ memset(Chrp + n * Long, ' ', Long);
+ else
+ *(Chrp + n * Long) = '\0';
+
+ } // end of Reset
+
+/***********************************************************************/
+/* Return the zero ending value of the nth element. */
+/***********************************************************************/
+char *CHRBLK::GetCharValue(int n)
+ {
+ return (char *)GetValPtrEx(n);
+ } // end of GetCharValue
+
+/***********************************************************************/
+/* Return the value of the nth element converted to tiny int. */
+/***********************************************************************/
+char CHRBLK::GetTinyValue(int n)
+ {
+ bool m;
+ ulonglong val = CharToNumber((char*)GetValPtr(n), Long, INT_MAX8,
+ false, &m);
+
+ return (m && val < INT_MAX8) ? (char)(-(signed)val) : (char)val;
+ } // end of GetTinyValue
+
+/***********************************************************************/
+/* Return the value of the nth element converted to unsigned tiny int.*/
+/***********************************************************************/
+uchar CHRBLK::GetUTinyValue(int n)
+ {
+ return (uchar)CharToNumber((char*)GetValPtr(n), Long, UINT_MAX8, true);
+ } // end of GetTinyValue
+
+/***********************************************************************/
+/* Return the value of the nth element converted to short. */
+/***********************************************************************/
+short CHRBLK::GetShortValue(int n)
+ {
+ bool m;
+ ulonglong val = CharToNumber((char*)GetValPtr(n), Long, INT_MAX16,
+ false, &m);
+
+ return (m && val < INT_MAX16) ? (short)(-(signed)val) : (short)val;
+ } // end of GetShortValue
+
+/***********************************************************************/
+/* Return the value of the nth element converted to ushort. */
+/***********************************************************************/
+ushort CHRBLK::GetUShortValue(int n)
+ {
+ return (ushort)CharToNumber((char*)GetValPtr(n), Long, UINT_MAX16, true);
+ } // end of GetShortValue
+
+/***********************************************************************/
+/* Return the value of the nth element converted to int. */
+/***********************************************************************/
+int CHRBLK::GetIntValue(int n)
+ {
+ bool m;
+ ulonglong val = CharToNumber((char*)GetValPtr(n), Long, INT_MAX32,
+ false, &m);
+
+ return (m && val < INT_MAX32) ? (int)(-(signed)val) : (int)val;
+ } // end of GetIntValue
+
+/***********************************************************************/
+/* Return the value of the nth element converted to uint. */
+/***********************************************************************/
+uint CHRBLK::GetUIntValue(int n)
+ {
+ return (uint)CharToNumber((char*)GetValPtr(n), Long, UINT_MAX32, true);
+ } // end of GetIntValue
+
+/***********************************************************************/
+/* Return the value of the nth element converted to big int. */
+/***********************************************************************/
+longlong CHRBLK::GetBigintValue(int n)
+ {
+ bool m;
+ ulonglong val = CharToNumber((char*)GetValPtr(n), Long, INT_MAX64,
+ false, &m);
+
+ return (m && val < INT_MAX64) ? (longlong)(-(signed)val) : (longlong)val;
+ } // end of GetBigintValue
+
+/***********************************************************************/
+/* Return the value of the nth element converted to unsigned big int. */
+/***********************************************************************/
+ulonglong CHRBLK::GetUBigintValue(int n)
+ {
+ return CharToNumber((char*)GetValPtr(n), Long, ULONGLONG_MAX, true);
+ } // end of GetUBigintValue
+
+/***********************************************************************/
+/* Return the value of the nth element converted to double. */
+/***********************************************************************/
+double CHRBLK::GetFloatValue(int n)
+ {
+ return atof((char *)GetValPtrEx(n));
+ } // end of GetFloatValue
+
+/***********************************************************************/
+/* STRING GetCharString: get string representation of a char value. */
+/***********************************************************************/
+char *CHRBLK::GetCharString(char *, int n)
+ {
+ return (char *)GetValPtrEx(n);
+ } // end of GetCharString
+
+/***********************************************************************/
+/* Set one value in a block. */
+/***********************************************************************/
+void CHRBLK::SetValue(PVAL valp, int n)
+ {
+ bool b;
+
+ ChkIndx(n);
+ ChkTyp(valp);
+
+ if (!(b = valp->IsNull()))
+ SetValue((PSZ)valp->GetCharValue(), n);
+ else
+ Reset(n);
+
+ SetNull(n, b && Nullable);
+ } // end of SetValue
+
+/***********************************************************************/
+/* Set one value in a block from a zero terminated string. */
+/***********************************************************************/
+void CHRBLK::SetValue(PCSZ sp, int n)
+ {
+ uint len = (sp) ? strlen(sp) : 0;
+ SetValue(sp, len, n);
+ } // end of SetValue
+
+/***********************************************************************/
+/* Set one value in a block from an array of characters. */
+/***********************************************************************/
+void CHRBLK::SetValue(const char *sp, uint len, int n)
+ {
+ char *p = Chrp + n * Long;
+
+#if defined(_DEBUG)
+ if (Check && (signed)len > Long) {
+ PGLOBAL& g = Global;
+ strcpy(g->Message, MSG(SET_STR_TRUNC));
+ throw Type;
+ } // endif Check
+#endif // _DEBUG
+
+ if (sp)
+ memcpy(p, sp, MY_MIN((unsigned)Long, len));
+
+ if (Blanks) {
+ // Suppress eventual ending zero and right fill with blanks
+ for (int i = len; i < Long; i++)
+ p[i] = ' ';
+
+ } else if ((signed)len < Long)
+ p[len] = 0;
+
+ SetNull(n, false);
+ } // end of SetValue
+
+/***********************************************************************/
+/* Set one value in a block from a value in another block. */
+/***********************************************************************/
+void CHRBLK::SetValue(PVBLK pv, int n1, int n2)
+ {
+ bool b;
+
+ if (Type != pv->GetType() || Long != ((CHRBLK*)pv)->Long) {
+ PGLOBAL& g = Global;
+ strcpy(g->Message, MSG(BLKTYPLEN_MISM));
+ throw Type;
+ } // endif Type
+
+ if (!(b = pv->IsNull(n2)))
+ memcpy(Chrp + n1 * Long, ((CHRBLK*)pv)->Chrp + n2 * Long, Long);
+ else
+ Reset(n1);
+
+ SetNull(n1, b && Nullable);
+ } // end of SetValue
+
+/***********************************************************************/
+/* Set one value in a block if val is less than the current value. */
+/***********************************************************************/
+void CHRBLK::SetMin(PVAL valp, int n)
+ {
+ CheckParms(valp, n)
+ CheckBlanks
+ char *vp = valp->GetCharValue();
+ char *bp = Chrp + n * Long;
+
+ if (((Ci) ? strnicmp(vp, bp, Long) : strncmp(vp, bp, Long)) < 0)
+ memcpy(bp, vp, Long);
+
+ } // end of SetMin
+
+/***********************************************************************/
+/* Set one value in a block if val is greater than the current value. */
+/***********************************************************************/
+void CHRBLK::SetMax(PVAL valp, int n)
+ {
+ CheckParms(valp, n)
+ CheckBlanks
+ char *vp = valp->GetCharValue();
+ char *bp = Chrp + n * Long;
+
+ if (((Ci) ? strnicmp(vp, bp, Long) : strncmp(vp, bp, Long)) > 0)
+ memcpy(bp, vp, Long);
+
+ } // end of SetMax
+
+#if 0
+/***********************************************************************/
+/* Set many values in a block from values in another block. */
+/***********************************************************************/
+void CHRBLK::SetValues(PVBLK pv, int k, int n)
+ {
+#if defined(_DEBUG)
+ if (Type != pv->GetType() || Long != ((CHRBLK*)pv)->Long) {
+ PGLOBAL& g = Global;
+ strcpy(g->Message, MSG(BLKTYPLEN_MISM));
+ throw Type;
+ } // endif Type
+#endif // _DEBUG
+ char *p = ((CHRBLK*)pv)->Chrp;
+
+ if (!k)
+ memcpy(Chrp, p, Long * n);
+ else
+ memcpy(Chrp + k * Long, p + k * Long, Long * (n - k));
+
+ } // end of SetValues
+#endif // 0
+
+/***********************************************************************/
+/* Move one value from i to j. */
+/***********************************************************************/
+void CHRBLK::Move(int i, int j)
+ {
+ if (i != j) {
+ memcpy(Chrp + j * Long, Chrp + i * Long, Long);
+ MoveNull(i, j);
+ } // endif i
+
+ } // end of Move
+
+/***********************************************************************/
+/* Compare a Value object with the nth value of the block. */
+/***********************************************************************/
+int CHRBLK::CompVal(PVAL vp, int n)
+ {
+ ChkIndx(n);
+ ChkTyp(vp);
+
+ char *xvp = vp->GetCharValue(); // Get Value zero ended string
+ bool ci = Ci || vp->IsCi(); // true if is case insensitive
+
+ GetValPtrEx(n); // Get a zero ended string in Valp
+ return (ci) ? stricmp(xvp, Valp) : strcmp(xvp, Valp);
+ } // end of CompVal
+
+/***********************************************************************/
+/* Compare two values of the block. */
+/***********************************************************************/
+int CHRBLK::CompVal(int i1, int i2)
+ {
+ return (Ci) ? strnicmp(Chrp + i1 * Long, Chrp + i2 * Long, Long)
+ : strncmp(Chrp + i1 * Long, Chrp + i2 * Long, Long);
+ } // end of CompVal
+
+/***********************************************************************/
+/* Get a pointer on the nth value of the block. */
+/***********************************************************************/
+void *CHRBLK::GetValPtr(int n)
+ {
+ ChkIndx(n);
+ return Chrp + n * Long;
+ } // end of GetValPtr
+
+/***********************************************************************/
+/* Get a pointer on a zero ended string equal to nth value. */
+/***********************************************************************/
+void *CHRBLK::GetValPtrEx(int n)
+ {
+ ChkIndx(n);
+ memcpy(Valp, Chrp + n * Long, Long);
+
+ if (IsNull(n))
+ return const_cast<char *>("");
+
+ if (Blanks) {
+ // The (fast) way this is done works only for blocks such
+ // as Min and Max where strings are stored with the ending 0
+ // except for those whose length is equal to Len.
+ // For VCT blocks we must remove rightmost blanks.
+ char *p = Valp + Long;
+
+ for (p--; p >= Valp && *p == ' '; p--) ;
+
+ *(++p) = '\0';
+ } // endif Blanks
+
+ return Valp;
+ } // end of GetValPtrEx
+
+/***********************************************************************/
+/* Returns index of matching value in block or -1. */
+/***********************************************************************/
+int CHRBLK::Find(PVAL vp)
+ {
+ ChkTyp(vp);
+
+ int i;
+ bool ci = Ci || vp->IsCi();
+ PSZ s = vp->GetCharValue();
+
+ if (vp->IsNull())
+ return -1;
+
+ for (i = 0; i < Nval; i++) {
+ if (IsNull(i))
+ continue;
+
+ GetValPtrEx(i); // Get a zero ended string in Valp
+
+ if (!((ci) ? strnicmp(s, Valp, Long) : strncmp(s, Valp, Long)))
+ break;
+
+ } // endfor i
+
+ return (i < Nval) ? i : (-1);
+ } // end of Find
+
+/***********************************************************************/
+/* Returns the length of the longest string in the block. */
+/***********************************************************************/
+int CHRBLK::GetMaxLength(void)
+ {
+ int i, n;
+
+ for (i = n = 0; i < Nval; i++)
+ if (!IsNull(i)) {
+ GetValPtrEx(i);
+ n = MY_MAX(n, (signed)strlen(Valp));
+ } // endif null
+
+ return n;
+ } // end of GetMaxLength
+
+
+/* -------------------------- Class STRBLK --------------------------- */
+
+/***********************************************************************/
+/* Constructor. */
+/***********************************************************************/
+STRBLK::STRBLK(PGLOBAL g, void *mp, int nval, int type)
+ : VALBLK(mp, type, nval), Strp((PSZ*&)Blkp)
+ {
+ Global = g;
+ Nullable = true;
+ Sorted = false;
+ } // end of STRBLK constructor
+
+/***********************************************************************/
+/* Initialization routine. */
+/***********************************************************************/
+bool STRBLK::Init(PGLOBAL g, bool check)
+ {
+ if (!Blkp)
+ if (AllocBuff(g, Nval * sizeof(PSZ)))
+ return true;
+
+ Check = check;
+ Global = g;
+ return false;
+ } // end of Init
+
+/***********************************************************************/
+/* Get the tiny value represented by the Strp string. */
+/***********************************************************************/
+char STRBLK::GetTinyValue(int n)
+ {
+ bool m;
+ ulonglong val = CharToNumber(Strp[n], strlen(Strp[n]), INT_MAX8,
+ false, &m);
+
+ return (m && val < INT_MAX8) ? (char)(-(signed)val) : (char)val;
+ } // end of GetTinyValue
+
+/***********************************************************************/
+/* Get the unsigned tiny value represented by the Strp string. */
+/***********************************************************************/
+uchar STRBLK::GetUTinyValue(int n)
+ {
+ return (uchar)CharToNumber(Strp[n], strlen(Strp[n]), UINT_MAX8, true);
+ } // end of GetUTinyValue
+
+/***********************************************************************/
+/* Get the short value represented by the Strp string. */
+/***********************************************************************/
+short STRBLK::GetShortValue(int n)
+ {
+ bool m;
+ ulonglong val = CharToNumber(Strp[n], strlen(Strp[n]), INT_MAX16,
+ false, &m);
+
+ return (m && val < INT_MAX16) ? (short)(-(signed)val) : (short)val;
+ } // end of GetShortValue
+
+/***********************************************************************/
+/* Get the unsigned short value represented by the Strp string. */
+/***********************************************************************/
+ushort STRBLK::GetUShortValue(int n)
+ {
+ return (ushort)CharToNumber(Strp[n], strlen(Strp[n]), UINT_MAX16, true);
+ } // end of GetUshortValue
+
+/***********************************************************************/
+/* Get the integer value represented by the Strp string. */
+/***********************************************************************/
+int STRBLK::GetIntValue(int n)
+ {
+ bool m;
+ ulonglong val = CharToNumber(Strp[n], strlen(Strp[n]), INT_MAX32,
+ false, &m);
+
+ return (m && val < INT_MAX32) ? (int)(-(signed)val) : (int)val;
+ } // end of GetIntValue
+
+/***********************************************************************/
+/* Get the unsigned integer value represented by the Strp string. */
+/***********************************************************************/
+uint STRBLK::GetUIntValue(int n)
+ {
+ return (uint)CharToNumber(Strp[n], strlen(Strp[n]), UINT_MAX32, true);
+ } // end of GetUintValue
+
+/***********************************************************************/
+/* Get the big integer value represented by the Strp string. */
+/***********************************************************************/
+longlong STRBLK::GetBigintValue(int n)
+ {
+ bool m;
+ ulonglong val = CharToNumber(Strp[n], strlen(Strp[n]), INT_MAX64,
+ false, &m);
+
+ return (m && val < INT_MAX64) ? (-(signed)val) : (longlong)val;
+ } // end of GetBigintValue
+
+/***********************************************************************/
+/* Get the unsigned big integer value represented by the Strp string. */
+/***********************************************************************/
+ulonglong STRBLK::GetUBigintValue(int n)
+ {
+ return CharToNumber(Strp[n], strlen(Strp[n]), ULONGLONG_MAX, true);
+ } // end of GetUBigintValue
+
+/***********************************************************************/
+/* Set one value in a block from a value in another block. */
+/***********************************************************************/
+void STRBLK::SetValue(PVBLK pv, int n1, int n2)
+ {
+ ChkTyp(pv);
+ Strp[n1] = (!pv->IsNull(n2)) ? ((STRBLK*)pv)->Strp[n2] : NULL;
+ } // end of SetValue
+
+#if 0
+/***********************************************************************/
+/* Set many values in a block from values in another block. */
+/***********************************************************************/
+void STRBLK::SetValues(PVBLK pv, int k, int n)
+ {
+ CheckType(pv)
+ PSZ *sp = ((STRBLK*)pv)->Strp;
+
+ for (int i = k; i < n; i++)
+ Strp[i] = (!pv->IsNull(i)) ? sp[i] : NULL;
+
+ } // end of SetValues
+#endif // 0
+
+/***********************************************************************/
+/* Set one value in a block. */
+/***********************************************************************/
+void STRBLK::SetValue(PVAL valp, int n)
+ {
+ ChkIndx(n);
+ ChkTyp(valp);
+
+ if (!valp->IsNull())
+ SetValue((PSZ)valp->GetCharValue(), n);
+ else
+ Strp[n] = NULL;
+
+ } // end of SetValue
+
+/***********************************************************************/
+/* Set one value in a block from a zero terminated string. */
+/***********************************************************************/
+void STRBLK::SetValue(PCSZ p, int n)
+ {
+ if (p) {
+ if (!Sorted || !n || !Strp[n-1] || strcmp(p, Strp[n-1]))
+ Strp[n] = (PSZ)PlugDup(Global, p);
+ else
+ Strp[n] = Strp[n-1];
+
+ } else
+ Strp[n] = NULL;
+
+ } // end of SetValue
+
+/***********************************************************************/
+/* Set one value in a block from an array of characters. */
+/***********************************************************************/
+void STRBLK::SetValue(const char *sp, uint len, int n)
+ {
+ PSZ p;
+
+ if (sp) {
+ if (!Sorted || !n || !Strp[n-1] || strlen(Strp[n-1]) != len ||
+ strncmp(sp, Strp[n-1], len)) {
+ p = (PSZ)PlugSubAlloc(Global, NULL, len + 1);
+ memcpy(p, sp, len);
+ p[len] = 0;
+ } else
+ p = Strp[n-1];
+
+ } else
+ p = NULL;
+
+ Strp[n] = p;
+ } // end of SetValue
+
+/***********************************************************************/
+/* Set one value in a block if val is less than the current value. */
+/***********************************************************************/
+void STRBLK::SetMin(PVAL valp, int n)
+ {
+ CheckParms(valp, n)
+ char *vp = valp->GetCharValue();
+ char *bp = Strp[n];
+
+ if (strcmp(vp, bp) < 0)
+ SetValue(valp, n);
+
+ } // end of SetMin
+
+/***********************************************************************/
+/* Set one value in a block if val is greater than the current value. */
+/***********************************************************************/
+void STRBLK::SetMax(PVAL valp, int n)
+ {
+ CheckParms(valp, n)
+ char *vp = valp->GetCharValue();
+ char *bp = Strp[n];
+
+ if (strcmp(vp, bp) > 0)
+ SetValue(valp, n);
+
+ } // end of SetMax
+
+/***********************************************************************/
+/* Move one value from i to j. */
+/***********************************************************************/
+void STRBLK::Move(int i, int j)
+ {
+ Strp[j] = Strp[i];
+ } // end of Move
+
+/***********************************************************************/
+/* Compare a Value object with the nth value of the block. */
+/***********************************************************************/
+int STRBLK::CompVal(PVAL vp, int n)
+ {
+ ChkIndx(n);
+ ChkTyp(vp);
+
+ if (vp->IsNull() || !Strp[n])
+ DBUG_ASSERT(false);
+
+ return strcmp(vp->GetCharValue(), Strp[n]);
+ } // end of CompVal
+
+/***********************************************************************/
+/* Compare two values of the block. */
+/***********************************************************************/
+int STRBLK::CompVal(int i1, int i2)
+ {
+ if (!Strp[i1] || !Strp[i2])
+ DBUG_ASSERT(false);
+
+ return (strcmp(Strp[i1], Strp[i2]));
+ } // end of CompVal
+
+/***********************************************************************/
+/* Get a pointer on the nth value of the block. */
+/***********************************************************************/
+void *STRBLK::GetValPtr(int n)
+ {
+ ChkIndx(n);
+ return Strp + n;
+ } // end of GetValPtr
+
+/***********************************************************************/
+/* Get a pointer on a zero ended string equal to nth value. */
+/***********************************************************************/
+void *STRBLK::GetValPtrEx(int n)
+ {
+ ChkIndx(n);
+ return (Strp[n]) ? Strp[n] : const_cast<char*>("");
+ } // end of GetValPtrEx
+
+/***********************************************************************/
+/* Returns index of matching value in block or -1. */
+/***********************************************************************/
+int STRBLK::Find(PVAL vp)
+ {
+ int i;
+ PSZ s;
+
+ ChkTyp(vp);
+
+ if (vp->IsNull())
+ return -1;
+ else
+ s = vp->GetCharValue();
+
+ for (i = 0; i < Nval; i++)
+ if (Strp[i] && !strcmp(s, Strp[i]))
+ break;
+
+ return (i < Nval) ? i : (-1);
+ } // end of Find
+
+/***********************************************************************/
+/* Returns the length of the longest string in the block. */
+/***********************************************************************/
+int STRBLK::GetMaxLength(void)
+ {
+ int i, n;
+
+ for (i = n = 0; i < Nval; i++)
+ if (Strp[i])
+ n = MY_MAX(n, (signed)strlen(Strp[i]));
+
+ return n;
+ } // end of GetMaxLength
+
+/* -------------------------- Class DATBLK --------------------------- */
+
+/***********************************************************************/
+/* Constructor. */
+/***********************************************************************/
+DATBLK::DATBLK(void *mp, int nval) : TYPBLK<int>(mp, nval, TYPE_INT)
+ {
+ Type = TYPE_DATE;
+ Dvalp = NULL;
+ } // end of DATBLK constructor
+
+/***********************************************************************/
+/* Set format so formatted dates can be converted on input. */
+/***********************************************************************/
+bool DATBLK::SetFormat(PGLOBAL g, PCSZ fmt, int len, int year)
+ {
+ if (!(Dvalp = AllocateValue(g, TYPE_DATE, len, year, false, fmt)))
+ return true;
+
+ return false;
+ } // end of SetFormat
+
+/***********************************************************************/
+/* DTVAL GetCharString: get string representation of a date value. */
+/***********************************************************************/
+char *DATBLK::GetCharString(char *p, int n)
+ {
+ char *vp;
+
+ if (Dvalp) {
+ Dvalp->SetValue(Typp[n]);
+ vp = Dvalp->GetCharString(p);
+ } else
+ vp = TYPBLK<int>::GetCharString(p, n);
+
+ return vp;
+ } // end of GetCharString
+
+/***********************************************************************/
+/* Set one value in a block from a char string. */
+/***********************************************************************/
+void DATBLK::SetValue(PCSZ p, int n)
+ {
+ if (Dvalp) {
+ // Decode the string according to format
+ Dvalp->SetValue_psz(p);
+ Typp[n] = Dvalp->GetIntValue();
+ } else
+ TYPBLK<int>::SetValue(p, n);
+
+ } // end of SetValue
+
+
+/* -------------------------- Class PTRBLK --------------------------- */
+
+/***********************************************************************/
+/* Compare two values of the block. */
+/***********************************************************************/
+int PTRBLK::CompVal(int i1, int i2)
+ {
+ return (Strp[i1] > Strp[i2]) ? 1 : (Strp[i1] < Strp[i2]) ? (-1) : 0;
+ } // end of CompVal
+
+
+/* -------------------------- Class MBVALS --------------------------- */
+
+/***********************************************************************/
+/* Allocate a value block according to type,len, and nb of values. */
+/***********************************************************************/
+PVBLK MBVALS::Allocate(PGLOBAL g, int type, int len, int prec,
+ int n, bool sub)
+ {
+ Mblk.Sub = sub;
+ Mblk.Size = n * GetTypeSize(type, len);
+
+ if (!PlgDBalloc(g, NULL, Mblk)) {
+ sprintf(g->Message, MSG(ALLOC_ERROR), "MBVALS::Allocate");
+ return NULL;
+ } else
+ Vblk = AllocValBlock(g, Mblk.Memp, type, n, len, prec,
+ TRUE, TRUE, FALSE);
+
+ return Vblk;
+ } // end of Allocate
+
+/***********************************************************************/
+/* Reallocate the value block according to the new size. */
+/***********************************************************************/
+bool MBVALS::ReAllocate(PGLOBAL g, int n)
+ {
+ if (!PlgDBrealloc(g, NULL, Mblk, n * Vblk->GetVlen())) {
+ sprintf(g->Message, MSG(ALLOC_ERROR), "MBVALS::ReAllocate");
+ return TRUE;
+ } else
+ Vblk->ReAlloc(Mblk.Memp, n);
+
+ return FALSE;
+ } // end of ReAllocate
+
+/***********************************************************************/
+/* Free the value block. */
+/***********************************************************************/
+void MBVALS::Free(void)
+ {
+ PlgDBfree(Mblk);
+ Vblk = NULL;
+ } // end of Free
+
+/* ------------------------- End of Valblk --------------------------- */
+