SqlStringAscii.cpp

Go to the documentation of this file.
00001 /*
00002 // $Id: //open/dev/fennel/calculator/SqlStringAscii.cpp#2 $
00003 // Fennel is a library of data storage and processing components.
00004 // Copyright (C) 2005-2009 The Eigenbase Project
00005 // Copyright (C) 2004-2009 SQLstream, Inc.
00006 // Copyright (C) 2009-2009 LucidEra, Inc.
00007 //
00008 // This program is free software; you can redistribute it and/or modify it
00009 // under the terms of the GNU General Public License as published by the Free
00010 // Software Foundation; either version 2 of the License, or (at your option)
00011 // any later version approved by The Eigenbase Project.
00012 //
00013 // This program is distributed in the hope that it will be useful,
00014 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016 // GNU General Public License for more details.
00017 //
00018 // You should have received a copy of the GNU General Public License
00019 // along with this program; if not, write to the Free Software
00020 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021 //
00022 // SqlString
00023 //
00024 // An ascii string library that adheres to the SQL99 standard definitions
00025 */
00026 
00027 #include "fennel/common/CommonPreamble.h"
00028 #include "fennel/calculator/SqlStringAscii.h"
00029 
00030 FENNEL_BEGIN_NAMESPACE
00031 
00032 int
00033 SqlStrCat_Ascii(
00034     char* dest,
00035     int destStorageBytes,
00036     int destLenBytes,
00037     char const * const str,
00038     int strLenBytes)
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 }
00048 
00049 
00050 int
00051 SqlStrCat_Ascii(
00052     char* dest,
00053     int destStorageBytes,
00054     char const * const str1,
00055     int str1LenBytes,
00056     char const * const str2,
00057     int str2LenBytes)
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 }
00068 
00069 int
00070 SqlStrCmp_Ascii_Fix(
00071     char const * const str1,
00072     int str1LenBytes,
00073     char const * const str2,
00074     int str2LenBytes,
00075     char trimchar)
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 }
00127 
00128 int
00129 SqlStrCmp_Ascii_Var(
00130     char const * const str1,
00131     int str1LenBytes,
00132     char const * const str2,
00133     int str2LenBytes)
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 }
00158 
00159 
00160 int
00161 SqlStrLenBit_Ascii(
00162     char const * const str,
00163     int strLenBytes)
00164 {
00165     return 8 * strLenBytes;
00166 }
00167 
00168 int
00169 SqlStrLenChar_Ascii(
00170     char const * const str,
00171     int strLenBytes)
00172 {
00173     return strLenBytes;
00174 }
00175 
00176 int
00177 SqlStrLenOct_Ascii(
00178     char const * const str,
00179     int strLenBytes)
00180 {
00181     return strLenBytes;
00182 }
00183 
00184 
00185 int
00186 SqlStrOverlay_Ascii(
00187     char* dest,
00188     int destStorageBytes,
00189     char const * const str,
00190     int strLenBytes,
00191     char const * const over,
00192     int overLenBytes,
00193     int startChar,
00194     int lengthChar,
00195     int lenSpecified)
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 }
00239 
00240 int
00241 SqlStrPos_Ascii(
00242     char const * const str,
00243     int strLenBytes,
00244     char const * const find,
00245     int findLenBytes)
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 }
00277 
00278 
00279 int
00280 SqlStrSubStr_Ascii(
00281     char const ** dest,
00282     int destStorageBytes,
00283     char const * const str,
00284     int strLenBytes,
00285     int subStartChar,
00286     int subLengthChar,
00287     int subLenSpecified)
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 }
00335 
00336 int
00337 SqlStrToLower_Ascii(
00338     char* dest,
00339     int destStorageBytes,
00340     char const * src,
00341     int srcLenBytes)
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 }
00357 
00358 int
00359 SqlStrToUpper_Ascii(
00360     char* dest,
00361     int destStorageBytes,
00362     char const * src,
00363     int srcLenBytes)
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 }
00379 
00380 int
00381 SqlStrTrim_Ascii(
00382     char* dest,
00383     int destStorageBytes,
00384     char const * const str,
00385     int strLenBytes,
00386     int trimLeft,
00387     int trimRight,
00388     char trimchar)
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 }
00418 
00419 int
00420 SqlStrTrim_Ascii(
00421     char const ** result,
00422     char const * const str,
00423     int strLenBytes,
00424     int trimLeft,
00425     int trimRight,
00426     char trimchar)
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 }
00450 
00451 
00452 FENNEL_END_NAMESPACE
00453 
00454 // End SqlStringAscii.cpp

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