diff options
Diffstat (limited to 'storage/connect/valblk.cpp')
-rw-r--r-- | storage/connect/valblk.cpp | 1417 |
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 --------------------------- */ + |