SqlStringAscii.cpp File Reference

Go to the source code of this file.

Functions

FENNEL_BEGIN_NAMESPACE int SqlStrCat_Ascii (char *dest, int destStorageBytes, int destLenBytes, char const *const str, int strLenBytes)
 Strcat.
int SqlStrCat_Ascii (char *dest, int destStorageBytes, char const *const str1, int str1LenBytes, char const *const str2, int str2LenBytes)
 StrCat.
int SqlStrCmp_Ascii_Fix (char const *const str1, int str1LenBytes, char const *const str2, int str2LenBytes, char trimchar)
 StrCmp.
int SqlStrCmp_Ascii_Var (char const *const str1, int str1LenBytes, char const *const str2, int str2LenBytes)
 StrCmp.
int SqlStrLenBit_Ascii (char const *const str, int strLenBytes)
 StrLen in bits.
int SqlStrLenChar_Ascii (char const *const str, int strLenBytes)
 StrLen in characters.
int SqlStrLenOct_Ascii (char const *const str, int strLenBytes)
 StrLen in octets.
int SqlStrOverlay_Ascii (char *dest, int destStorageBytes, char const *const str, int strLenBytes, char const *const over, int overLenBytes, int startChar, int lengthChar, int lenSpecified)
 Overlay.
int SqlStrPos_Ascii (char const *const str, int strLenBytes, char const *const find, int findLenBytes)
 Position.
int SqlStrSubStr_Ascii (char const **dest, int destStorageBytes, char const *const str, int strLenBytes, int subStartChar, int subLengthChar, int subLenSpecified)
 Substring by reference.
int SqlStrToLower_Ascii (char *dest, int destStorageBytes, char const *src, int srcLenBytes)
 toLower. Ascii. CHAR/VARCHAR. Returns length.
int SqlStrToUpper_Ascii (char *dest, int destStorageBytes, char const *src, int srcLenBytes)
 toUpper. Ascii. CHAR/VARCHAR. Returns length.
int SqlStrTrim_Ascii (char *dest, int destStorageBytes, char const *const str, int strLenBytes, int trimLeft, int trimRight, char trimchar)
 Trim padding.
int SqlStrTrim_Ascii (char const **result, char const *const str, int strLenBytes, int trimLeft, int trimRight, char trimchar)
 Trim padding by reference.


Function Documentation

int SqlStrCat_Ascii ( char *  dest,
int  destStorageBytes,
char const *const  str1,
int  str1LenBytes,
char const *const  str2,
int  str2LenBytes 
)

StrCat.

Ascii. SQL VARCHAR & CHAR. dest = str1 || str2. dest = str1 || str2

Returns new length in bytes.

This is an optimization for creating a concatenated string from two other strings, eliminating a separate string copy. The assumption is that this is the common case with concatenation. Subsequent concatenations may occur with other form.

If either string is variable width, the result is variable width: per SQL99 Part 2 Section 6.27 Syntax Rule 3.a.i. If both strings are fixed width, the result is fixed width, item ii.

Note: CHAR('1 ') || CHAR('2 ') is CHAR('1 2 ') and is not CHAR('12 ').

When used with CHARs, ignore the return value, and set destLenBytes = destStorageBytes

Definition at line 51 of file SqlStringAscii.cpp.

00058 {
00059     if (str1LenBytes + str2LenBytes > destStorageBytes) {
00060         // SQL99 Part 2 Section 22.1 22-001 "String Data Right truncation"
00061         throw "22001";
00062     }
00063 
00064     memcpy(dest, str1, str1LenBytes);
00065     memcpy(dest + str1LenBytes, str2, str2LenBytes);
00066     return str1LenBytes + str2LenBytes;
00067 }

FENNEL_BEGIN_NAMESPACE int SqlStrCat_Ascii ( char *  dest,
int  destStorageBytes,
int  destLenBytes,
char const *const  str,
int  strLenBytes 
)

Strcat.

Ascii. SQL VARCHAR & CHAR. dest = dest || str. Returns new length in bytes.

If either string is variable width, the result is variable width: per SQL99 Part 2 Section 6.27 Syntax Rule 3.a.i. If both strings are fixed width, the result is fixed width, per item ii.

Note that CHAR('1 ') || CHAR('2 ') = CHAR('1 2 ') and not CHAR('12 ').

When called repeatedly to cat multiple strings together (e.g. A || B || C), the final destLength must be exactly equal to the defined resulting width. (e.g. width of A+B+C) for both VARCHAR & CHAR. Take care that these length semantics are adhered to in the final result, even though intermediate results (say A || B) may not have the correct length.

When used with CHARs, set strLenBytes to strStorageBytes. On intermediate results set destLenBytes = return value of previous call. Final result should/must have return value == destStorage.

Definition at line 33 of file SqlStringAscii.cpp.

Referenced by SqlStringAsciiTest::testSqlStringCat_Ascii_Fix(), SqlStringAsciiTest::testSqlStringCat_Ascii_Var(), and SqlStringAsciiTest::testSqlStringCat_Ascii_Var2().

00039 {
00040     if (destLenBytes + strLenBytes > destStorageBytes) {
00041         // SQL99 Part 2 Section 22.1 22-001 "String Data Right truncation"
00042         throw "22001";
00043     }
00044 
00045     memcpy(dest + destLenBytes, str, strLenBytes);
00046     return destLenBytes + strLenBytes;
00047 }

int SqlStrCmp_Ascii_Fix ( char const *const  str1,
int  str1LenBytes,
char const *const  str2,
int  str2LenBytes,
char  trimchar = ' ' 
)

StrCmp.

Ascii. Fixed Width / SQL CHAR.

Returns -1, 0, 1.

Definition at line 70 of file SqlStringAscii.cpp.

Referenced by SqlStringAsciiTest::testSqlStringCmp_Ascii_Fix_Helper().

00076 {
00077     char const * start = str1;
00078     char const * end = str1 + str1LenBytes;
00079 
00080     if (end != start) {
00081         end--;
00082         while (end != start && *end == trimchar) {
00083             end--;
00084         }
00085         if (end != start || *end != trimchar) {
00086             end++;
00087         }
00088     }
00089     int str1TrimLenBytes = end - start;
00090 
00091     start = str2;
00092     end = str2 + str2LenBytes;
00093 
00094     if (end != start) {
00095         end--;
00096         while (end != start && *end == trimchar) {
00097             end--;
00098         }
00099         if (end != start || *end != trimchar) {
00100             end++;
00101         }
00102     }
00103     int str2TrimLenBytes = end - start;
00104 
00105     if (str1TrimLenBytes > str2TrimLenBytes) {
00106         return 1;
00107     } else if (str1TrimLenBytes < str2TrimLenBytes) {
00108         return -1;
00109     }
00110 
00111     assert(str1TrimLenBytes == str2TrimLenBytes);
00112 
00113     // comparison must be unsigned to work for > 128
00114     unsigned char const *s1 = reinterpret_cast<unsigned char const *>(str1);
00115     unsigned char const *s2 = reinterpret_cast<unsigned char const *>(str2);
00116     int len = str1TrimLenBytes;
00117 
00118     while (len-- > 0) {
00119         if (*s1 != *s2) {
00120             return (*s1 > *s2) ? 1 : -1;
00121         }
00122         s1++;
00123         s2++;
00124     }
00125     return 0;
00126 }

int SqlStrCmp_Ascii_Var ( char const *const  str1,
int  str1LenBytes,
char const *const  str2,
int  str2LenBytes 
)

StrCmp.

Ascii. Variable Width / VARCHAR.

Returns -1, 0, 1

Definition at line 129 of file SqlStringAscii.cpp.

Referenced by SqlStringAsciiTest::testSqlStringCmp_Ascii_Var_Helper().

00134 {
00135     // consider strcoll for I18N
00136     if (str1LenBytes > str2LenBytes) {
00137         return 1;
00138     } else if (str1LenBytes < str2LenBytes) {
00139         return -1;
00140     }
00141 
00142     assert(str1LenBytes == str2LenBytes);
00143 
00144     // comparison must be unsigned to work for > 128
00145     unsigned char const *s1 = reinterpret_cast<unsigned char const *>(str1);
00146     unsigned char const *s2 = reinterpret_cast<unsigned char const *>(str2);
00147     int len = str1LenBytes;
00148 
00149     while (len-- > 0) {
00150         if (*s1 != *s2) {
00151             return (*s1 > *s2) ? 1 : -1;
00152         }
00153         s1++;
00154         s2++;
00155     }
00156     return 0;
00157 }

int SqlStrLenBit_Ascii ( char const *const  str,
int  strLenBytes 
)

StrLen in bits.

Ascii. CHAR/VARCHAR.

Parameter str is ignored for ascii strings.

Definition at line 161 of file SqlStringAscii.cpp.

Referenced by SqlStringAsciiTest::testSqlStringLenBit_Ascii().

00164 {
00165     return 8 * strLenBytes;
00166 }

int SqlStrLenChar_Ascii ( char const *const  str,
int  strLenBytes 
)

StrLen in characters.

Ascii. CHAR/VARCHAR.

Parameter str is ignored for ascii strings.

Definition at line 169 of file SqlStringAscii.cpp.

Referenced by SqlStringAsciiTest::testSqlStringLenChar_Ascii().

00172 {
00173     return strLenBytes;
00174 }

int SqlStrLenOct_Ascii ( char const *const  str,
int  strLenBytes 
)

StrLen in octets.

Ascii. CHAR/VARCHAR.

Parameter str is ignored for ascii strings.

Definition at line 177 of file SqlStringAscii.cpp.

Referenced by SqlStringAsciiTest::testSqlStringLenOct_Ascii().

00180 {
00181     return strLenBytes;
00182 }

int SqlStrOverlay_Ascii ( char *  dest,
int  destStorageBytes,
char const *const  str,
int  strLenBytes,
char const *const  over,
int  overLenBytes,
int  startChar,
int  lengthChar,
int  lenSpecified 
)

Overlay.

Ascii. CHAR/VARCHAR. Returns new length in bytes

See SQL99 Part 2 Section 6.18 Syntax Rule 10. Overlay is defined in terms of Substring an concatenation. If start is < 1 or length < 0, a substring error may be thrown. Result is VARCHAR, as the result of substring is always VARCHAR, and concatenation results in VARCHAR if any of its operands are VARCHAR. startChar is 1-indexed, as per SQL standard.

Definition at line 186 of file SqlStringAscii.cpp.

Referenced by SqlStringAsciiTest::testSqlStringOverlay_Ascii().

00196 {
00197     if (!lenSpecified) {
00198         lengthChar = overLenBytes;
00199     }
00200     if (lengthChar < 0 || startChar < 1) {
00201         // Overlay is defined in terms of substring. These conditions
00202         // would, I believe, generate a substring error. Also
00203         // another "reference" sql database gets angry under these
00204         // conditions. Therefore, per:
00205         // SQL99 Part 2 Section 6.18 General Rule 3.d generate a
00206         // SQL99 Part 2 Section 22.1 22-011 "data exception substring error".
00207         throw "22011";
00208     }
00209 
00210     int leftLenBytes = startChar - 1;         // 1-index to 0-index
00211     if (leftLenBytes > strLenBytes) {
00212         leftLenBytes = strLenBytes;
00213     }
00214     char const *rightP = str + leftLenBytes + lengthChar;
00215     int rightLenBytes = strLenBytes - (leftLenBytes + lengthChar);
00216     if (rightLenBytes < 0) {
00217         rightLenBytes = 0;
00218     }
00219     assert(leftLenBytes >= 0);
00220     assert(rightLenBytes >= 0);
00221     assert(rightP >= str);
00222 
00223     if (leftLenBytes + rightLenBytes + overLenBytes > destStorageBytes) {
00224         // SQL99 Part 2 Section 22.1 22-001 "String Data Right truncation"
00225         throw "22001";
00226     }
00227 
00228     char *dp = dest;
00229 
00230     memcpy(dp, str, leftLenBytes);
00231     dp += leftLenBytes;
00232     memcpy(dp, over, overLenBytes);
00233     dp += overLenBytes;
00234     memcpy(dp, rightP, rightLenBytes);
00235     dp += rightLenBytes;
00236 
00237     return dp - dest;
00238 }

int SqlStrPos_Ascii ( char const *const  str,
int  strLenBytes,
char const *const  find,
int  findLenBytes 
)

Position.

Ascii. CHAR/VARHCAR. Returns 1-index string position.

Returns 0 if not found. Returns 1 if find is zero length. See SQL99 Part 2 Section 6.17 General Rule 2.

Definition at line 241 of file SqlStringAscii.cpp.

Referenced by SqlStringAsciiTest::testSqlStringPos_Ascii().

00246 {
00247     // SQL99 Part 2 Section 6.17 General Rule 2.a.
00248     if (!findLenBytes) {
00249         return 1;
00250     }
00251     // SQL99 Part 2 Section 6.17 General Rule 2.c.
00252     if (findLenBytes > strLenBytes) {
00253         return 0;
00254     }
00255     assert(findLenBytes > 0);
00256     assert(strLenBytes > 0);
00257     assert(strLenBytes - findLenBytes >= 0);
00258 
00259     register char const * s = str;
00260     char const * end = 1 + s + (strLenBytes - findLenBytes);
00261 
00262     while (s < end) {
00263         // search for first char of find
00264         s = reinterpret_cast<char const *>(memchr(s, *find, end - s));
00265         if (!s) {
00266             return 0;                // Case C.
00267         }
00268         if (!memcmp(s, find, findLenBytes)) {
00269             // add 1 to make result 1-indexed.
00270             return (s - str) + 1;   // Case B.
00271         } else {
00272             s++;
00273         }
00274     }
00275     return 0;                            // Case C.
00276 }

int SqlStrSubStr_Ascii ( char const **  dest,
int  destStorageBytes,
char const *const  str,
int  strLenBytes,
int  subStartChar,
int  subLenChar,
int  subLenBytesSpecified 
)

Substring by reference.

Ascii. Returns VARCHAR. Accepts CHAR/VARCHAR. Sets dest to start of of substring. Returns length of substring.

Note that subStart is 1-indexed, as per SQL99 spec. All substring parameters are handled as signed, as spec implies that they could be negative. Some combinations of subStart and subLenBytes may throw an exception. Results in a VARCHAR. See SQL99 Part 2 Section 6.18 General Rule 3. subStartChar is 1-indexed.

Definition at line 280 of file SqlStringAscii.cpp.

Referenced by SqlStringAsciiTest::testSqlStringSubStr_Ascii().

00288 {
00289     int e;
00290     if (subLenSpecified) {
00291         e = subStartChar + subLengthChar;
00292     } else {
00293         e = strLenBytes + 1;
00294         if (subStartChar > e) {
00295             e = subStartChar;
00296         }
00297     }
00298 
00299     if (e < subStartChar) {
00300         // Per SQL99 Part 2 Section 6.18 General Rule 3.d, generate a
00301         // "data exception substring error". SQL99 Part 2 Section 22.1 22-011
00302         throw "22011";
00303     }
00304 
00305     if (subStartChar > strLenBytes || e < 1) {
00306         return 0;
00307     }
00308 
00309     int s1 = 1;
00310     if (subStartChar > s1) {
00311         s1 = subStartChar;
00312     }
00313 
00314     int e1 = strLenBytes + 1;
00315     if (e < e1) {
00316         e1 = e;
00317     }
00318     int l1 = e1 - s1;
00319 
00320 
00321     if (l1 > destStorageBytes) {
00322         // SQL99 Part 2 Section 22.1 22-001 "String Data Right truncation"
00323         throw "22001";
00324     }
00325     if (l1 < 0) {
00326         // Expected behavior not clear.
00327         // SQL99 Part 2 Section 22.1 22-011 "data exception substring error".
00328         throw "22011";
00329     }
00330 
00331     // - 1 converts from 1-indexed to 0-indexed
00332     *dest = str + s1 - 1;
00333     return l1;
00334 }

int SqlStrToLower_Ascii ( char *  dest,
int  destStorageBytes,
char const *  src,
int  srcLenBytes 
)

toLower. Ascii. CHAR/VARCHAR. Returns length.

Definition at line 337 of file SqlStringAscii.cpp.

Referenced by SqlStringAsciiTest::testSqlStringToLower_Ascii().

00342 {
00343     register char const * s = src;
00344     register char* d = dest;
00345     char* e = dest + srcLenBytes;
00346 
00347     if (srcLenBytes > destStorageBytes) {
00348         // SQL99 Part 2 Section 22.1 22-001 "String Data Right truncation"
00349         throw "22001";
00350     }
00351 
00352     while (d < e) {
00353         *(d++) = tolower(*(s++));
00354     }
00355     return srcLenBytes;
00356 }

int SqlStrToUpper_Ascii ( char *  dest,
int  destStorageBytes,
char const *  src,
int  srcLenBytes 
)

toUpper. Ascii. CHAR/VARCHAR. Returns length.

Definition at line 359 of file SqlStringAscii.cpp.

Referenced by SqlStringAsciiTest::testSqlStringToUpper_Ascii().

00364 {
00365     register char const * s = src;
00366     register char* d = dest;
00367     char* e = dest + srcLenBytes;
00368 
00369     if (srcLenBytes > destStorageBytes) {
00370         // SQL99 Part 2 Section 22.1 22-001 "String Data Right truncation"
00371         throw "22001";
00372     }
00373 
00374     while (d < e) {
00375         *(d++) = toupper(*(s++));
00376     }
00377     return srcLenBytes;
00378 }

int SqlStrTrim_Ascii ( char const **  result,
char const *const  str,
int  strLenBytes,
int  trimLeft,
int  trimRight,
char  trimchar = ' ' 
)

Trim padding by reference.

Ascii. CHAR/VARCHAR. Returns new length.

See SQL99 Part 2 Section 6.18 General Rule 8. Results in a VARCHAR. Note: Does not check that result has enough capacity to contain substring as this is irrelevant. If a program depends on the size of result not changing, and this instruction enforcing that invariant -- probably a bad practice anyway -- trouble could result.

Definition at line 420 of file SqlStringAscii.cpp.

00427 {
00428     char const * start = str;
00429     char const * end = str + strLenBytes;
00430 
00431     // If many pad characters are expected, consider using memrchr()
00432     if (trimLeft) {
00433         while (start != end && *start == trimchar) {
00434             start++;
00435         }
00436     }
00437     if (trimRight && end != start) {
00438         end--;
00439         while (end != start && *end == trimchar) {
00440             end--;
00441         }
00442         if (end != start || *end != trimchar) {
00443             end++;
00444         }
00445     }
00446 
00447     *result = start;
00448     return end - start;
00449 }

int SqlStrTrim_Ascii ( char *  dest,
int  destStorageBytes,
char const *const  str,
int  strLenBytes,
int  trimLeft,
int  trimRight,
char  trimchar = ' ' 
)

Trim padding.

Ascii. CHAR/VARCHAR. Returns new length.

See SQL99 Part 2 Section 6.18 General Rule 8. Results in a VARCHAR.

Definition at line 381 of file SqlStringAscii.cpp.

Referenced by SqlStringAsciiTest::testSqlStringTrim_Ascii().

00389 {
00390     char const * start = str;
00391     char const * end = str + strLenBytes;
00392     int newLenBytes;
00393 
00394     // If many pad characters are expected, consider using memrchr()
00395     if (trimLeft) {
00396         while (start != end && *start == trimchar) {
00397             start++;
00398         }
00399     }
00400     if (trimRight && end != start) {
00401         end--;
00402         while (end != start && *end == trimchar) {
00403             end--;
00404         }
00405         if (end != start || *end != trimchar) {
00406             end++;
00407         }
00408     }
00409     newLenBytes = end - start;
00410 
00411     if (newLenBytes > destStorageBytes) {
00412         // SQL99 Part 2 Section 22.1 22-001 "String Data Right truncation"
00413         throw "22001";
00414     }
00415     memcpy(dest, start, newLenBytes);
00416     return newLenBytes;
00417 }


Generated on Mon Jun 22 04:00:22 2009 for Fennel by  doxygen 1.5.1