123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614 |
- /*##############################################################################
- HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems®.
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ############################################################################## */
- #include <platform.h>
- #include <time.h>
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
- #include <assert.h>
- #include <eclrtl.hpp>
- #include "stringlib.hpp"
- #include "wildmatch.tpp"
- static const char * compatibleVersions[] = {
- "STRINGLIB 1.1.06 [fd997dc3feb4ca385d59a12b9dc4beab]", // windows version
- "STRINGLIB 1.1.06 [f8305e66ca26a1447dee66d4a36d88dc]", // linux version
- "STRINGLIB 1.1.07",
- "STRINGLIB 1.1.08",
- "STRINGLIB 1.1.09",
- "STRINGLIB 1.1.10",
- "STRINGLIB 1.1.11",
- "STRINGLIB 1.1.12",
- "STRINGLIB 1.1.13",
- NULL };
- #define STRINGLIB_VERSION "STRINGLIB 1.1.14"
- static const char * EclDefinition =
- "export StringLib := SERVICE:fold\n"
- " string StringFilterOut(const string src, const string _within) : c, pure,entrypoint='slStringFilterOut'; \n"
- " string StringFilter(const string src, const string _within) : c, pure,entrypoint='slStringFilter'; \n"
- " string StringSubstituteOut(const string src, const string _within, const string _newchar) : c, pure,entrypoint='slStringSubsOut'; \n"
- " string StringSubstitute(const string src, const string _within, const string _newchar) : c, pure,entrypoint='slStringSubs'; \n"
- " string StringRepad(const string src, unsigned4 size) : c, pure,entrypoint='slStringRepad'; \n"
- " string StringTranslate(const string src, const string _within, const string _mapping) : c, pure,entrypoint='slStringTranslate'; \n"
- " unsigned integer4 StringFind(const string src, const string tofind, unsigned4 instance ) : c, pure,entrypoint='slStringFind'; \n"
- " unsigned integer4 StringUnboundedUnsafeFind(const string src, const string tofind ) : c,pure,nofold,entrypoint='slStringFind2'; \n"
- " unsigned integer4 StringFindCount(const string src, const string tofind) : c, pure,entrypoint='slStringFindCount'; \n"
- " unsigned integer4 EbcdicStringFind(const ebcdic string src, const ebcdic string tofind , unsigned4 instance ) : c,pure,entrypoint='slStringFind'; \n"
- " unsigned integer4 EbcdicStringUnboundedUnsafeFind(const ebcdic string src, const ebcdic string tofind ) : c,pure,nofold,entrypoint='slStringFind2'; \n"
- " string StringExtract(const string src, unsigned4 instance) : c,pure,entrypoint='slStringExtract'; \n"
- // NOTE - the next 2 are foldable but not pure, meaning it will only be folded if found in a #IF or similar
- // This is because you usually want them to be executed at runtime
- " string8 GetDateYYYYMMDD() : c,once,entrypoint='slGetDateYYYYMMDD2';\n"
- " varstring GetBuildInfo() : c,once,entrypoint='slGetBuildInfo';\n"
- " string Data2String(const data src) : c,pure,entrypoint='slData2String';\n"
- " data String2Data(const string src) : c,pure,entrypoint='slString2Data';\n"
- " string StringToLowerCase(const string src) : c,pure,entrypoint='slStringToLowerCase';\n"
- " string StringToUpperCase(const string src) : c,pure,entrypoint='slStringToUpperCase';\n"
- " string StringToProperCase(const string src) : c,pure,entrypoint='slStringToProperCase';\n"
- " string StringToCapitalCase(const string src) : c,pure,entrypoint='slStringToCapitalCase';\n"
- " string StringToTitleCase(const string src) : c,pure,entrypoint='slStringToTitleCase';\n"
- " integer4 StringCompareIgnoreCase(const string src1, const string src2) : c,pure,entrypoint='slStringCompareIgnoreCase';\n"
- " string StringReverse(const string src) : c,pure,entrypoint='slStringReverse';\n"
- " string StringFindReplace(const string src, const string stok, const string rtok) : c,pure,entrypoint='slStringFindReplace';\n"
- " string StringCleanSpaces(const string src) : c,pure,entrypoint='slStringCleanSpaces'; \n"
- " boolean StringWildMatch(const string src, const string _pattern, boolean _noCase) : c, pure,entrypoint='slStringWildMatch'; \n"
- " boolean StringWildExactMatch(const string src, const string _pattern, boolean _noCase) : c, pure,entrypoint='slStringWildExactMatch'; \n"
- " boolean StringContains(const string src, const string _pattern, boolean _noCase) : c, pure,entrypoint='slStringContains'; \n"
- " string StringExtractMultiple(const string src, unsigned8 mask) : c,pure,entrypoint='slStringExtractMultiple'; \n"
- " unsigned integer4 EditDistance(const string l, const string r) : c, time, pure,entrypoint='slEditDistanceV2'; \n"
- " boolean EditDistanceWithinRadius(const string l, const string r, unsigned4 radius) : c,time,pure,entrypoint='slEditDistanceWithinRadiusV2'; \n"
- " unsigned integer4 EditDistanceV2(const string l, const string r) : c,time,pure,entrypoint='slEditDistanceV2'; \n"
- " unsigned integer4 EditDistanceV3(const string l, const string r, unsigned4 radius) : c,time,pure,entrypoint='slEditDistanceV3'; \n"
- " boolean EditDistanceWithinRadiusV2(const string l, const string r, unsigned4 radius) : c,time,pure,entrypoint='slEditDistanceWithinRadiusV2'; \n"
- " string StringGetNthWord(const string src, unsigned4 n) : c, pure,entrypoint='slStringGetNthWord'; \n"
- " string StringExcludeLastWord(const string src) : c, pure,entrypoint='slStringExcludeLastWord'; \n"
- " string StringExcludeNthWord(const string src, unsigned4 n) : c, pure,entrypoint='slStringExcludeNthWord'; \n"
- " unsigned4 StringWordCount(const string src) : c, pure,entrypoint='slStringWordCount'; \n"
- " unsigned4 CountWords(const string src, const string _separator, BOOLEAN allow_blanks) : c, pure,entrypoint='slCountWords'; \n"
- " SET OF STRING SplitWords(const string src, const string _separator, BOOLEAN allow_blanks) : c, pure,entrypoint='slSplitWords'; \n"
- " STRING CombineWords(set of string src, const string _separator) : c, pure,entrypoint='slCombineWords'; \n"
- " UNSIGNED4 StringToDate(const string src, const varstring format) : c, pure,entrypoint='slStringToDate'; \n"
- " UNSIGNED4 StringToTimeOfDay(const string src, const varstring format) : c, pure,entrypoint='slStringToTimeOfDay'; \n"
- " UNSIGNED4 MatchDate(const string src, set of varstring formats) : c, pure,entrypoint='slMatchDate'; \n"
- " UNSIGNED4 MatchTimeOfDay(const string src, set of varstring formats) : c, pure,entrypoint='slMatchTimeOfDay'; \n"
- " STRING FormatDate(UNSIGNED4 date, const varstring format) : c, pure,entrypoint='slFormatDate'; \n"
- " STRING StringRepeat(const string src, unsigned4 n) : c, pure,entrypoint='slStringRepeat'; \n"
- "END;";
- STRINGLIB_API bool getECLPluginDefinition(ECLPluginDefinitionBlock *pb)
- {
- if (pb->size == sizeof(ECLPluginDefinitionBlockEx))
- {
- ECLPluginDefinitionBlockEx * pbx = (ECLPluginDefinitionBlockEx *) pb;
- pbx->compatibleVersions = compatibleVersions;
- }
- else if (pb->size != sizeof(ECLPluginDefinitionBlock))
- return false;
- pb->magicVersion = PLUGIN_VERSION;
- pb->version = STRINGLIB_VERSION;
- pb->moduleName = "lib_stringlib";
- pb->ECL = EclDefinition;
- pb->flags = PLUGIN_IMPLICIT_MODULE | PLUGIN_MULTIPLE_VERSIONS;
- pb->description = "StringLib string manipulation library";
- return true;
- }
- namespace nsStringlib {
-
- IPluginContext * parentCtx = NULL;
- enum { bitsInUnsigned = sizeof(unsigned) * 8 };
- static const char hexchar[] = "0123456789ABCDEF";
- static unsigned hex2digit(char c)
- {
- switch (c)
- {
- default: case 0: return 0;
- case '1': return 1;
- case '2': return 2;
- case '3': return 3;
- case '4': return 4;
- case '5': return 5;
- case '6': return 6;
- case '7': return 7;
- case '8': return 8;
- case '9': return 9;
- case 'a': case 'A': return 10;
- case 'b': case 'B': return 11;
- case 'c': case 'C': return 12;
- case 'd': case 'D': return 13;
- case 'e': case 'E': return 14;
- case 'f': case 'F': return 15;
- }
- }
- inline char char_toupper(char c) { return (char)toupper(c); }
- inline void clip(unsigned &len, const char * s)
- {
- while ( len > 0 && s[len-1]==' ' )
- len--;
- }
- inline unsigned min3(unsigned a, unsigned b, unsigned c)
- {
- unsigned mi;
- mi = a;
- if (b < mi)
- {
- mi = b;
- }
- if (c < mi)
- {
- mi = c;
- }
- return mi;
- }
- //--- Optimized versions of the edit distance functions
- inline unsigned mask(unsigned x) { return x & 1; }
- unsigned editDistance(unsigned leftLen, const char * left, unsigned rightLen, const char * right)
- {
- unsigned i, j;
- clip(leftLen, left);
- clip(rightLen, right);
- if (leftLen > 255)
- leftLen = 255;
- if (rightLen > 255)
- rightLen = 255;
- if (leftLen == 0)
- return rightLen;
- if (rightLen == 0)
- return leftLen;
- //Optimize the storage requirements by
- //i) Only storing two stripes
- //ii) Calculate, but don't store the row comparing against the null string
- unsigned char da[2][256];
- char r_0 = right[0];
- char l_0 = left[0];
- bool matched_l0 = false;
- for (j = 0; j < rightLen; j++)
- {
- if (right[j] == l_0) matched_l0 = true;
- da[0][j] = (matched_l0) ? j : j+1;
- }
- bool matched_r0 = (l_0 == r_0);
- for (i = 1; i < leftLen; i++)
- {
- char l_i = left[i];
- if (l_i == r_0)
- matched_r0 = true;
- byte da_i_0 = matched_r0 ? i : i+1;
- da[mask(i)][0] = da_i_0;
- byte da_i_prevj = da_i_0;
- for (j = 1; j < rightLen; j++)
- {
- char r_j = right[j];
- unsigned char next = (l_i == r_j) ? da[mask(i-1)][j-1] :
- min3(da[mask(i-1)][j], da_i_prevj, da[mask(i-1)][j-1]) + 1;
- da[mask(i)][j] = next;
- da_i_prevj = next;
- }
- }
- return da[mask(leftLen-1)][rightLen-1];
- }
- //This could be further improved in the following ways:
- // * Only use 2*radius bytes of temporary storage - I doubt it is worth it.
- // * special case edit1 - you could use variables for the 6 interesting array elements, and get
- // rid of the array completely. You could also unwind the first (and last iterations).
- // * I suspect the early exit condition could be improved depending the lengths of the strings.
- extern STRINGLIB_API unsigned editDistanceWithinRadius(unsigned leftLen, const char * left, unsigned rightLen, const char * right, unsigned radius)
- {
- if (radius >= 255)
- return 255;
- clip(leftLen, left);
- clip(rightLen, right);
- unsigned minED = (leftLen < rightLen)? rightLen - leftLen: leftLen - rightLen;
- if (minED > radius)
- return minED;
- if (leftLen > 255)
- leftLen = 255;
- if (rightLen > 255)
- rightLen = 255;
- //Checking for leading common substrings actually slows the function down.
- if (leftLen == 0)
- return rightLen;
- if (rightLen == 0)
- return leftLen;
- /*
- This function applies two optimizations over the function above.
- a) Adding a charcter (next row) can at most decrease the edit distance by 1, so short circuit when
- we there is no possiblity of getting within the distance.
- b) We only need to evaluate the martix da[i-radius..i+radius][j-radius..j+radius]
- not taking into account values outside that range [can use max value to prevent access]
- */
- //Optimize the storage requirements by
- //i) Only storing two stripes
- //ii) Calculate, but don't store the row comparing against the null string
- unsigned char da[2][256];
- char r_0 = right[0];
- char l_0 = left[0];
- bool matched_l0 = false;
- for (unsigned j = 0; j < rightLen; j++)
- {
- if (right[j] == l_0) matched_l0 = true;
- da[0][j] = (matched_l0) ? j : j+1;
- }
- bool matched_r0 = (l_0 == r_0);
- for (unsigned i = 1; i < leftLen; i++)
- {
- char l_i = left[i];
- if (l_i == r_0)
- matched_r0 = true;
- byte da_i_0 = matched_r0 ? i : i+1;
- da[mask(i)][0] = da_i_0;
- byte da_i_prevj = da_i_0;
- unsigned low = i-radius;
- unsigned high = i+radius;
- unsigned first = (i > radius) ? low : 1;
- unsigned last = (high >= rightLen) ? rightLen : high +1;
- for (unsigned j = first; j < last; j++)
- {
- char r_j = right[j];
- unsigned next = da[mask(i-1)][j-1];
- if (l_i != r_j)
- {
- if (j != low)
- {
- if (next > da_i_prevj)
- next = da_i_prevj;
- }
- if (j != high)
- {
- byte da_previ_j = da[mask(i-1)][j];
- if (next > da_previ_j)
- next = da_previ_j;
- }
- next++;
- }
- da[mask(i)][j] = next;
- da_i_prevj = next;
- }
- // bail out early if ed can't possibly be <= radius
- // Only considering a strip down the middle of the matrix, so the maximum the score can ever be adjusted is 2xradius
- unsigned max_valid_score = 3*radius;
- // But maximum is also 1 for every difference in string length - comes in to play when close to the end.
- //In 32bit goes slower for radius=1 I suspect because running out of registers. Retest in 64bit.
- if (radius > 1)
- {
- unsigned max_distance = radius + (leftLen - (i+1)) + (rightLen - last);
- if (max_valid_score > max_distance)
- max_valid_score = max_distance;
- }
- if (da_i_prevj > max_valid_score)
- return da_i_prevj;
- }
- return da[mask(leftLen-1)][rightLen-1];
- }
- } // namespace
- //-------------------------------------------------------------------------------------------------------------------------------------------
- // Exported functions are NOT in the namespace
- using namespace nsStringlib;
- STRINGLIB_API void setPluginContext(IPluginContext * _ctx) { parentCtx = _ctx; }
- STRINGLIB_API void STRINGLIB_CALL slStringFilterOut(unsigned & tgtLen, char * & tgt, unsigned srcLen, const char * src, unsigned hitLen, const char * hit)
- {
- char *temp = (char *)CTXMALLOC(parentCtx, srcLen);
- unsigned tlen = 0;
- if (hitLen==1)
- {
- char test = *hit;
- for ( unsigned i = 0; i < srcLen; i++ )
- {
- char c = src[i];
- if (c!=test)
- temp[tlen++] = c;
- }
- }
- else {
- unsigned filter[256/bitsInUnsigned];
- memset(filter,0,sizeof(filter));
- for (unsigned j = 0; j < hitLen; j++ )
- {
- unsigned c = (unsigned char)hit[j];
- filter[c/bitsInUnsigned] |= (1<<(c%bitsInUnsigned));
- }
- for ( unsigned i = 0; i < srcLen; i++ )
- {
- unsigned c = (unsigned char)src[i];
- if ((filter[c/bitsInUnsigned] & (1<<(c%bitsInUnsigned))) == 0)
- temp[tlen++] = (char)c;
- }
- }
- tgt = (char *)CTXREALLOC(parentCtx, temp, tlen);
- tgtLen = tlen;
- }
- STRINGLIB_API void STRINGLIB_CALL slStringFilter(unsigned & tgtLen, char * & tgt, unsigned srcLen, const char * src, unsigned hitLen, const char * hit)
- {
- char *temp = (char *)CTXMALLOC(parentCtx, srcLen);
- unsigned tlen = 0;
- unsigned filter[256/bitsInUnsigned];
- memset(filter,0,sizeof(filter));
- for (unsigned j = 0; j < hitLen; j++ )
- {
- unsigned c = (unsigned char)hit[j];
- filter[c/bitsInUnsigned] |= (1<<(c%bitsInUnsigned));
- }
- for ( unsigned i = 0; i < srcLen; i++ )
- {
- unsigned c = (unsigned char)src[i];
- if ((filter[c/bitsInUnsigned] & (1<<(c%bitsInUnsigned))) != 0)
- temp[tlen++] = (char)c;
- }
- tgt = (char *)CTXREALLOC(parentCtx, temp, tlen);
- tgtLen = tlen;
- }
- STRINGLIB_API void STRINGLIB_CALL slStringSubsOut(unsigned & tgtLen, char * & tgt, unsigned srcLen, const char * src, unsigned hitLen, const char * hit, unsigned newCharLen, const char * newChar)
- {
- bool filter[256];
- memset(filter,0,sizeof(filter));
- for (unsigned j = 0; j < hitLen; j++ )
- {
- unsigned char c = ((unsigned char *)hit)[j];
- filter[c] = true;
- }
- tgt = (char *)CTXMALLOC(parentCtx, srcLen);
-
- if (newCharLen > 0)
- {
- for ( unsigned i = 0; i < srcLen; i++ )
- {
- unsigned char c = ((unsigned char *)src)[i];
- if (!filter[c])
- tgt[i] = c;
- else
- tgt[i] = ((char *)newChar)[0];
- }
- }
- else
- {
- memcpy_iflen(tgt, src, srcLen);
- }
- tgtLen = srcLen;
- }
- STRINGLIB_API void STRINGLIB_CALL slStringSubs(unsigned & tgtLen, char * & tgt, unsigned srcLen, const char * src, unsigned hitLen, const char * hit, unsigned newCharLen, const char * newChar)
- {
- bool filter[256];
- memset(filter,0,sizeof(filter));
- for (unsigned j = 0; j < hitLen; j++ )
- {
- unsigned char c = ((unsigned char *)hit)[j];
- filter[c] = true;
- }
- tgt = (char *)CTXMALLOC(parentCtx, srcLen);
- if (newCharLen > 0)
- {
- for ( unsigned i = 0; i < srcLen; i++ )
- {
- unsigned char c = ((unsigned char *)src)[i];
- if (filter[c])
- tgt[i] = c;
- else
- tgt[i] = ((char *)newChar)[0];
- }
- }
- else
- {
- memcpy_iflen(tgt, src, srcLen);
- }
- tgtLen = srcLen;
- }
- STRINGLIB_API void STRINGLIB_CALL slStringTranslate(unsigned & tgtLen, char * & tgt, unsigned srcLen, const char * src, unsigned hitLen, const char * hit, unsigned mappingLen, const char * mapping)
- {
- char mapped[256];
- for (unsigned i=0; i < sizeof(mapped); i++)
- mapped[i] = i;
- if (hitLen == mappingLen)
- {
- for (unsigned j = 0; j < hitLen; j++ )
- {
- unsigned char c = ((unsigned char *)hit)[j];
- mapped[c] = mapping[j];
- }
- }
- char * ret = (char *)CTXMALLOC(parentCtx, srcLen);
- for ( unsigned i = 0; i < srcLen; i++ )
- {
- unsigned char c = ((unsigned char *)src)[i];
- ret[i] = mapped[c];
- }
- tgt = ret;
- tgtLen = srcLen;
- }
- STRINGLIB_API void STRINGLIB_CALL slStringRepad(unsigned & tgtLen, char * & tgt, unsigned srcLen, const char * src, unsigned tLen)
- {
- char *base = (char *)src;
- while ( srcLen && *base == ' ' )
- {
- srcLen--;
- base++;
- }
- while ( srcLen && base[srcLen-1] == ' ' )
- srcLen--;
- if ( srcLen > tLen )
- srcLen = tLen;
- if ((int) tLen < 0)
- rtlFail(0, "Invalid parameter to StringLib.StringRepad");
- if (tLen)
- {
- tgt = (char *)CTXMALLOC(parentCtx, tLen);
- if (!tgt)
- rtlThrowOutOfMemory(0, "In StringLib.StringRepad");
- tgtLen = tLen;
- memcpy_iflen(tgt,base,srcLen);
- memset(tgt+srcLen,' ',tLen-srcLen);
- }
- else
- {
- tgt = NULL;
- tgtLen = 0;
- }
- }
- STRINGLIB_API unsigned STRINGLIB_CALL slStringFind(unsigned srcLen, const char * src, unsigned hitLen, const char * hit, unsigned instance)
- {
- if ( srcLen < hitLen )
- return 0;
- if (hitLen==1) { // common case optimization
- const char *p=src;
- const char *e = p+srcLen;
- char c = *hit;
- while (p!=e)
- if ((*(p++)==c))
- if (!--instance)
- return (unsigned)(p-src);
- }
- else
- {
- unsigned steps = srcLen-hitLen+1;
- for ( unsigned i = 0; i < steps; i++ )
- {
- if ( !memcmp((char *)src+i,hit,hitLen) )
- {
- if ( !--instance )
- return i+1;
- if (hitLen > 1)
- i += (hitLen-1);
- }
- }
- }
- return 0;
- }
- STRINGLIB_API unsigned STRINGLIB_CALL slStringFindCount(unsigned srcLen, const char * src, unsigned hitLen, const char * hit)
- {
- if ( srcLen < hitLen )
- return 0;
- unsigned matches = 0;
- if (hitLen==1) { // common case optimization
- const char *p=src;
- const char *e = p+srcLen;
- char c = *hit;
- while (p!=e)
- if ((*(p++)==c))
- matches++;
- }
- else
- {
- unsigned steps = srcLen-hitLen+1;
- for ( unsigned i = 0; i < steps; i++ )
- {
- if ( !memcmp((char *)src+i,hit,hitLen) )
- {
- matches++;
- if (hitLen > 1)
- i += (hitLen-1);
- }
- }
- }
- return matches;
- }
- STRINGLIB_API unsigned STRINGLIB_CALL slStringFind2(unsigned /*srcLen*/, const char * src, unsigned hitLen, const char * hit)
- {
- if (hitLen==1) { // common case optimization
- const char *p=src;
- char c = *hit;
- while (*(p++)!=c);
- return (unsigned)(p-src);
- }
- for ( unsigned i = 0; ; i++ )
- if ( !memcmp((char *)src+i,hit,hitLen) )
- return i+1;
- return 0;
- }
- STRINGLIB_API void STRINGLIB_CALL slStringExtract(unsigned & tgtLen, char * & tgt, unsigned srcLen, const char * src, unsigned instance)
- {
- tgtLen = 0;
- tgt = NULL;
- char * finger = (char *)src;
- if ( !instance )
- return;
- while ( --instance )
- {
- while ( srcLen && *finger != ',' )
- {
- srcLen--;
- finger++;
- }
- if ( !srcLen )
- return;
- srcLen--; // Skip ,
- finger++;
- }
- unsigned len = 0;
- for ( ; len < srcLen; len++ )
- if ( finger[len] == ',' )
- break;
- tgt = (char *)CTXMALLOC(parentCtx, len);
- memcpy_iflen(tgt,finger,len);
- tgtLen = len;
- }
- STRINGLIB_API void STRINGLIB_CALL slStringExtractMultiple(unsigned & tgtLen, char * & tgt, unsigned srcLen, const char * src, unsigned __int64 mask)
- {
- tgtLen = 0;
- tgt = NULL;
- char * finger = (char *)src;
- unsigned __int64 thisInstance = 1;
- while (mask)
- {
- while ( srcLen && *finger != ',' )
- {
- srcLen--;
- finger++;
- }
- if (mask & thisInstance)
- {
- mask &= ~thisInstance;
- unsigned matchLen = (unsigned)(finger - src);
- if (!tgt)
- tgt = (char *) CTXMALLOC(parentCtx, matchLen + srcLen);
- else
- tgt[tgtLen++] = ',';
- memcpy(tgt+tgtLen, src, finger - src);
- tgtLen += matchLen;
- }
- thisInstance <<= 1;
- if ( !srcLen )
- break;
- srcLen--; // Skip the ','
- finger++;
- src = finger;
- }
- }
- STRINGLIB_API char * STRINGLIB_CALL slGetDateYYYYMMDD(void)
- {
- char * result = (char *)CTXMALLOC(parentCtx, 9);
- time_t ltime;
- time( <ime );
- tm *today = localtime( <ime );
- strftime(result, 9, "%Y%m%d", today);
- return result;
- }
- STRINGLIB_API void STRINGLIB_CALL slGetDateYYYYMMDD2(char * ret)
- {
- char temp[9];
- time_t ltime;
- time( <ime );
- tm *today = localtime( <ime );
- strftime(temp, 9, "%Y%m%d", today);
- memcpy(ret, temp, 8);
- }
- STRINGLIB_API char * STRINGLIB_CALL slGetBuildInfo(void)
- {
- return CTXSTRDUP(parentCtx, STRINGLIB_VERSION);
- }
- STRINGLIB_API void STRINGLIB_CALL slData2String(size32_t & __ret_len,char * & __ret_str,unsigned _len_y, const void * y)
- {
- char *out = (char *)CTXMALLOC(parentCtx, _len_y * 2);
- char *res = out;
-
- unsigned char *yy = (unsigned char *) y;
- for (unsigned int i = 0; i < _len_y; i++)
- {
- *out++ = hexchar[yy[i] >> 4];
- *out++ = hexchar[yy[i] & 0x0f];
- }
- __ret_len = _len_y * 2;
- __ret_str = res;
- }
- STRINGLIB_API void STRINGLIB_CALL slString2Data(size32_t & __ret_len,void * & __ret_str,unsigned _len_src,const char * src)
- {
- // trailing nibbles are ignored
- // embedded spaces are ignored
- // illegal hex values are treated as zero
- // we could do a stricter one if it was considered desirable.
- char *out = (char *)CTXMALLOC(parentCtx, _len_src / 2);
- char *target = out;
- for (;;)
- {
- while (_len_src > 1 && isspace(*src))
- {
- src++;
- _len_src--;
- }
- if (_len_src < 2)
- break;
- *target++ = (hex2digit(src[0]) << 4) | hex2digit(src[1]);
- _len_src -= 2;
- src += 2;
- }
- __ret_len = (size32_t)(target - out);
- __ret_str = out;
- }
- // -----------------------------------------------------------------
- STRINGLIB_API void STRINGLIB_CALL slStringToLowerCase(unsigned & tgtLen, char * & tgt, unsigned srcLen, const char * src)
- {
- char * res = (char *)CTXMALLOC(parentCtx, srcLen);
-
- for (unsigned int i=0;i<srcLen;i++)
- res[i] = tolower(src[i]);
-
- tgt = res;
- tgtLen = srcLen;
- }
- // -----------------------------------------------------------------
- STRINGLIB_API void STRINGLIB_CALL slStringToUpperCase(unsigned & tgtLen, char * & tgt, unsigned srcLen, const char * src)
- {
- char * res = (char *)CTXMALLOC(parentCtx, srcLen);
-
- for (unsigned int i=0;i<srcLen;i++)
- res[i] = toupper(src[i]);
-
- tgt = res;
- tgtLen = srcLen;
- }
- // -----------------------------------------------------------------
- STRINGLIB_API void STRINGLIB_CALL slStringToProperCase(unsigned & tgtLen, char * & tgt, unsigned srcLen, const char * src)
- {
- tgt = (char *)CTXMALLOC(parentCtx, srcLen);
- char * res = tgt;
-
- bool seenSpace = true;
- for (unsigned int i=0;i<srcLen;i++)
- {
- char c = src[i];
- *tgt++ = seenSpace ? toupper(c) : c;
- seenSpace = (c==' ');
- }
-
- tgt = res;
- tgtLen = srcLen;
- }
- // -----------------------------------------------------------------
- STRINGLIB_API void STRINGLIB_CALL slStringToCapitalCase(unsigned & tgtLen, char * & tgt, unsigned srcLen, const char * src)
- {
- char * const result = (char *)CTXMALLOC(parentCtx, srcLen);
-
- bool upperPending = true;
- for (unsigned int i=0;i<srcLen;i++)
- {
- byte c = src[i];
- result[i] = upperPending ? toupper(c) : c;
- upperPending = !isalnum(c);
- }
- tgt = result;
- tgtLen = srcLen;
- }
- // -----------------------------------------------------------------
- STRINGLIB_API void STRINGLIB_CALL slStringToTitleCase(unsigned & tgtLen, char * & tgt, unsigned srcLen, const char * src)
- {
- char * const result = (char *)CTXMALLOC(parentCtx, srcLen);
- bool upperPending = true;
- for (unsigned int i=0;i<srcLen;i++)
- {
- byte c = src[i];
- result[i] = upperPending ? toupper(c) : tolower(c);
- upperPending = !isalnum(c);
- }
- tgt = result;
- tgtLen = srcLen;
- }
- // -----------------------------------------------------------------
- STRINGLIB_API int STRINGLIB_CALL slStringCompareIgnoreCase (unsigned src1Len, const char * src1, unsigned src2Len, const char * src2)
- {
- unsigned int i;
- for (i=0;i < src1Len && i < src2Len;i++)
- {
- byte lc = src1[i];
- byte rc = src2[i];
- if (lc != rc)
- {
- lc = tolower(lc);
- rc = tolower(rc);
- if (lc != rc)
- return lc > rc ? 1 : -1;
- }
- }
-
- while (i < src1Len)
- {
- if (src1[i++] != ' ')
- return 1;
- }
- while (i < src2Len)
- {
- if (src2[i++] != ' ')
- return -1;
- }
- return 0;
- }
- // -----------------------------------------------------------------
- STRINGLIB_API void STRINGLIB_CALL slStringReverse (unsigned & tgtLen, char * & tgt, unsigned srcLen, const char * src)
- {
- char * res = (char *)CTXMALLOC(parentCtx, srcLen);
- unsigned int n = srcLen - 1;
- for (unsigned int i=0;i<srcLen;i++)
- res[i] = src[n-i];
-
- tgt = res;
- tgtLen = srcLen;
- }
- // -----------------------------------------------------------------
- STRINGLIB_API void STRINGLIB_CALL slStringFindReplace (unsigned & tgtLen, char * & tgt, unsigned srcLen, const char * src, unsigned stokLen, const char * stok, unsigned rtokLen, const char * rtok)
- {
- if ( srcLen < stokLen || stokLen == 0)
- {
- tgt = (char *) CTXMALLOC(parentCtx, srcLen);
- memcpy_iflen(tgt, src, srcLen);
- tgtLen = srcLen;
- }
- else
- {
- unsigned steps = srcLen-stokLen+1;
- unsigned tgtmax = rtokLen > stokLen ? srcLen + steps * (rtokLen - stokLen) : srcLen;
- // This is the upper limit on target size - not a problem if we allocate a bit too much
- char * res = (char *)CTXMALLOC(parentCtx, tgtmax);
- tgt = res;
- unsigned i;
- for ( i = 0; i < steps; )
- {
- if ( !memcmp(src+i,stok,stokLen) )
- {
- memcpy(res, rtok, rtokLen);
- res += rtokLen;
- i += stokLen;
- }
- else
- *res++ = src[i++];
- }
- while (i <srcLen)
- *res++ = src[i++];
- tgtLen = (size32_t)(res - tgt);
- }
- }
- // -----------------------------------------------------------------
- STRINGLIB_API void STRINGLIB_CALL slStringCleanSpaces(size32_t & __ret_len,char * & __ret_str,unsigned _len_instr,const char * instr)
- {
- // remove double spaces
- char *out = (char *) CTXMALLOC(parentCtx, _len_instr);
- char *origout = out;
- bool spacePending = false;
- bool atStart = true;
- for(unsigned idx = 0; idx < _len_instr; idx++)
- {
- char c = *instr++;
- switch (c)
- {
- case ' ':
- case '\t':
- spacePending = true;
- break;
- default:
- if (spacePending && !atStart)
- *out++ = ' ';
- spacePending = false;
- atStart = false;
- *out++ = c;
- break;
- }
- }
- __ret_str = origout;
- __ret_len = (size32_t)(out - origout);
- }
- STRINGLIB_API bool STRINGLIB_CALL slStringWildMatch(unsigned srcLen, const char * src, unsigned patLen, const char * pat, bool noCase)
- {
- return wildTrimMatch<char, char_toupper, '?', '*', ' '>(src, srcLen, pat, patLen, noCase);
- }
- STRINGLIB_API bool STRINGLIB_CALL slStringWildExactMatch(unsigned srcLen, const char * src, unsigned patLen, const char * pat, bool noCase)
- {
- return wildMatch<char, char_toupper, '?', '*'>(src, srcLen, pat, patLen, noCase);
- }
- STRINGLIB_API bool STRINGLIB_CALL slStringContains(unsigned srcLen, const char * src, unsigned patLen, const char * pat, bool noCase)
- {
- unsigned char srcCount[256];
- memset(srcCount, 0, 256);
- while (srcLen && src[srcLen-1]==' ')
- srcLen--;
- while(srcLen-- > 0)
- {
- byte c = *src++;
- if (noCase)
- c = toupper(c);
- srcCount[c]++;
- }
- while (patLen && pat[patLen-1]==' ')
- patLen--;
- while(patLen-- > 0)
- {
- byte c = *pat++;
- if (noCase)
- c = toupper(c);
- if (srcCount[c] == 0)
- return false;
- else
- srcCount[c]--;
- }
- return true;
- }
- STRINGLIB_API unsigned STRINGLIB_CALL slEditDistanceV2(unsigned leftLen, const char * left, unsigned rightLen, const char * right)
- {
- return nsStringlib::editDistance(leftLen, left, rightLen, right);
- }
- STRINGLIB_API unsigned STRINGLIB_CALL slEditDistanceV3(unsigned leftLen, const char * left, unsigned rightLen, const char * right, unsigned radius)
- {
- if (radius == 0)
- return nsStringlib::editDistance(leftLen, left, rightLen, right);
- else
- return nsStringlib::editDistanceWithinRadius(leftLen, left, rightLen, right, radius);
- }
- STRINGLIB_API bool STRINGLIB_CALL slEditDistanceWithinRadiusV2(unsigned leftLen, const char * left, unsigned rightLen, const char * right, unsigned radius)
- {
- return nsStringlib::editDistanceWithinRadius(leftLen, left, rightLen, right, radius) <= radius;
- }
- inline bool isWordSeparator(char x)
- {
- return (unsigned char)x <= 0x20;
- }
- STRINGLIB_API void STRINGLIB_CALL slStringGetNthWord(unsigned & tgtLen, char * & tgt, unsigned srcLen, const char * src, unsigned n)
- {
- const char* start = 0;
- const char* end = 0;
- // skip any leading white space
- while (srcLen>0 && isWordSeparator(*src)) {
- src++;
- srcLen--;
- }
- while (srcLen>0 && n>0) {
- start = src;
- n--;
- // go to the next white space
- while (srcLen>0 && !isWordSeparator(*src)) {
- src++;
- srcLen--;
- }
- end = src;
- // skip white space again
- while (srcLen>0 && isWordSeparator(*src)) {
- src++;
- srcLen--;
- }
- }
- if (!n && (end-start)) {
- tgt = (char *)CTXMALLOC(parentCtx, end-start);
- memcpy(tgt,start,end-start);
- tgtLen = end-start;
- } else {
- tgt = 0;
- tgtLen = 0;
- }
- }
- STRINGLIB_API void STRINGLIB_CALL slStringRepeat(unsigned & tgtLen, char * & tgt, unsigned srcLen, const char * src, unsigned n)
- {
- char * buffer = NULL;
- if ((int) n < 0)
- rtlFail(0, "Invalid parameter to StringLib.StringRepeat");
- if (n == 0 || (srcLen == 0))
- {
- tgtLen = 0;
- }
- else
- {
- tgtLen = srcLen*n;
- if (tgtLen/n != srcLen) // Check did not overflow
- rtlFail(0, "Invalid parameter to StringLib.StringRepeat");
- buffer = (char *)CTXMALLOC(parentCtx, tgtLen);
- if (!buffer)
- rtlThrowOutOfMemory(0, "In StringLib.StringRepeat");
- if (srcLen == 1)
- {
- memset(buffer, *src, n);
- }
- else
- {
- for (unsigned i = 0; i < n; ++i)
- {
- memcpy(buffer + i*srcLen, src, srcLen);
- }
- }
- }
- tgt = buffer;
- }
- STRINGLIB_API unsigned STRINGLIB_CALL slStringWordCount(unsigned srcLen,const char * src)
- {
- // skip any leading white space
- unsigned word_count = 0;
- while (srcLen>0 && isWordSeparator(*src)) {
- src++;
- srcLen--;
- }
- while (srcLen>0) {
- word_count++;
- // go to the next white space
- while (srcLen>0 && !isWordSeparator(*src)) {
- src++;
- srcLen--;
- }
- // skip white space again
- while (srcLen>0 && isWordSeparator(*src)) {
- src++;
- srcLen--;
- }
- }
- return word_count;
- }
- STRINGLIB_API void STRINGLIB_CALL slStringExcludeLastWord(unsigned & tgtLen, char * & tgt, unsigned srcLen, const char * src)
- {
- //Remove first word also removes leading whitespace, otherwise just remove trailing whitespace
- unsigned idx = 0;
- unsigned startLast = 0;
- while (idx < srcLen && isWordSeparator(src[idx]))
- idx++;
- for (;;)
- {
- while (idx < srcLen && !isWordSeparator(src[idx]))
- idx++;
- while (idx < srcLen && isWordSeparator(src[idx]))
- idx++;
- if (idx == srcLen)
- break;
- startLast = idx;
- }
- unsigned len = startLast;
- tgtLen = len;
- if (len)
- {
- tgt = (char *)CTXMALLOC(parentCtx, len);
- memcpy(tgt,src,len);
- }
- else
- tgt = NULL;
- }
- STRINGLIB_API void STRINGLIB_CALL slStringExcludeNthWord(unsigned & tgtLen, char * & tgt, unsigned srcLen, const char * src, unsigned n)
- {
- unsigned idx = 0;
- unsigned startLast = 0;
- while (idx < srcLen && isWordSeparator(src[idx]))
- idx++;
- unsigned matchIndex = 0;
- //Remove first word also removes leading whitespace, otherwise just remove trailing whitespace
- //No matching words returns a blank string
- if (idx != srcLen)
- {
- for (;;)
- {
- while (idx < srcLen && !isWordSeparator(src[idx]))
- idx++;
- while (idx < srcLen && isWordSeparator(src[idx]))
- idx++;
- if (++matchIndex == n)
- break;
- startLast = idx;
- if (idx == srcLen)
- break;
- }
- }
- unsigned len = startLast + (srcLen - idx);
- tgtLen = len;
- if (len)
- {
- tgt = (char *)CTXMALLOC(parentCtx, len);
- memcpy_iflen(tgt,src,startLast);
- memcpy_iflen(tgt+startLast,src+idx,(srcLen - idx));
- }
- else
- tgt = NULL;
- }
- //--------------------------------------------------------------------------------------------------------------------
- STRINGLIB_API unsigned STRINGLIB_CALL slCountWords(size32_t lenSrc, const char * src, size32_t lenSeparator, const char * separator, bool allowBlankItems)
- {
- if (lenSrc == 0)
- return 0;
- if ((lenSeparator == 0) || (lenSrc < lenSeparator))
- return 1;
- unsigned numWords=0;
- const char * end = src + lenSrc;
- const char * max = end - (lenSeparator - 1);
- const char * cur = src;
- const char * startWord = NULL;
- //MORE: optimize lenSeparator == 1!
- while (cur < max)
- {
- if (memcmp(cur, separator, lenSeparator) == 0)
- {
- if (startWord || allowBlankItems)
- {
- numWords++;
- startWord = NULL;
- }
- cur += lenSeparator;
- }
- else
- {
- if (!startWord)
- startWord = cur;
- cur++;
- }
- }
- if (startWord || (cur != end) || allowBlankItems)
- numWords++;
- return numWords;
- }
- static unsigned calcWordSetSize(size32_t lenSrc, const char * src, size32_t lenSeparator, const char * separator, bool allowBlankItems)
- {
- if (lenSrc == 0)
- return 0;
- if ((lenSeparator == 0) || (lenSrc < lenSeparator))
- return sizeof(size32_t) + lenSrc;
- unsigned sizeWords=0;
- const char * end = src + lenSrc;
- const char * max = end - (lenSeparator - 1);
- const char * cur = src;
- const char * startWord = NULL;
- //MORE: optimize lenSeparator == 1!
- while (cur < max)
- {
- if (memcmp(cur, separator, lenSeparator) == 0)
- {
- if (startWord)
- {
- sizeWords += sizeof(size32_t) + (cur - startWord);
- startWord = NULL;
- }
- else if (allowBlankItems)
- sizeWords += sizeof(size32_t);
- cur += lenSeparator;
- }
- else
- {
- if (!startWord)
- startWord = cur;
- cur++;
- }
- }
- if (startWord || (cur != end) || allowBlankItems)
- {
- if (!startWord)
- startWord = cur;
- sizeWords += sizeof(size32_t) + (end - startWord);
- }
- return sizeWords;
- }
- STRINGLIB_API void STRINGLIB_CALL slSplitWords(bool & __isAllResult, size32_t & __lenResult, void * & __result, size32_t lenSrc, const char * src, size32_t lenSeparator, const char * separator, bool allowBlankItems)
- {
- unsigned sizeRequired = calcWordSetSize(lenSrc, src, lenSeparator, separator, allowBlankItems);
- char * const result = static_cast<char *>(CTXMALLOC(parentCtx, sizeRequired));
- __isAllResult = false;
- __lenResult = sizeRequired;
- __result = result;
- if (lenSrc == 0)
- return;
- if ((lenSeparator == 0) || (lenSrc < lenSeparator))
- {
- *((size32_t *)result) = lenSrc;
- memcpy_iflen(result+sizeof(size32_t), src, lenSrc);
- return;
- }
- unsigned sizeWords=0;
- char * target = result;
- const char * end = src + lenSrc;
- const char * max = end - (lenSeparator - 1);
- const char * cur = src;
- const char * startWord = NULL;
- //MORE: optimize lenSeparator == 1!
- while (cur < max)
- {
- if (memcmp(cur, separator, lenSeparator) == 0)
- {
- if (startWord || allowBlankItems)
- {
- size32_t len = startWord ? (cur - startWord) : 0;
- memcpy(target, &len, sizeof(len));
- memcpy_iflen(target+sizeof(size32_t), startWord, len);
- target += sizeof(size32_t) + len;
- startWord = NULL;
- }
- cur += lenSeparator;
- }
- else
- {
- if (!startWord)
- startWord = cur;
- cur++;
- }
- }
- if (startWord || (cur != end) || allowBlankItems)
- {
- if (!startWord)
- startWord = cur;
- size32_t len = (end - startWord);
- memcpy(target, &len, sizeof(len));
- memcpy_iflen(target+sizeof(size32_t), startWord, len);
- target += sizeof(size32_t) + len;
- }
- assert(target == result + sizeRequired);
- // ctx->fail(1, "Size mismatch in StringLib.SplitWords");
- }
- static unsigned countWords(size32_t lenSrc, const char * src)
- {
- unsigned count = 0;
- unsigned offset = 0;
- while (offset < lenSrc)
- {
- size32_t len;
- memcpy(&len, src+offset, sizeof(len));
- offset += sizeof(len) + len;
- count++;
- }
- return count;
- }
- STRINGLIB_API void STRINGLIB_CALL slCombineWords(size32_t & __lenResult, void * & __result, bool isAllSrc, size32_t lenSrc, const char * src, size32_t lenSeparator, const char * separator, bool allowBlankItems)
- {
- if (lenSrc == 0)
- {
- __lenResult = 0;
- __result = NULL;
- return;
- }
- unsigned numWords = countWords(lenSrc, src);
- size32_t sizeRequired = lenSrc - numWords * sizeof(size32_t) + (numWords-1) * lenSeparator;
- char * const result = static_cast<char *>(CTXMALLOC(parentCtx, sizeRequired));
- __lenResult = sizeRequired;
- __result = result;
- char * target = result;
- unsigned offset = 0;
- while (offset < lenSrc)
- {
- if ((offset != 0) && lenSeparator)
- {
- memcpy(target, separator, lenSeparator);
- target += lenSeparator;
- }
- size32_t len;
- memcpy(&len, src+offset, sizeof(len));
- offset += sizeof(len);
- memcpy_iflen(target, src+offset, len);
- target += len;
- offset += len;
- }
- assert(target == result + sizeRequired);
- }
- //--------------------------------------------------------------------------------------------------------------------
- inline unsigned makeDate(const tm & tm)
- {
- return (tm.tm_year + 1900) * 10000 + (tm.tm_mon + 1) * 100 + tm.tm_mday;
- }
- inline unsigned makeTimeOfDay(const tm & tm)
- {
- return (tm.tm_hour * 10000) + (tm.tm_min * 100) + tm.tm_sec;
- }
- inline void extractDate(tm & tm, unsigned date)
- {
- tm.tm_year = (date / 10000) - 1900;
- tm.tm_mon = ((date / 100) % 100) - 1;
- tm.tm_mday = (date % 100);
- // To proper initialisation of tm
- mktime(&tm);
- }
- STRINGLIB_API unsigned STRINGLIB_CALL slStringToDate(size32_t lenS, const char * s, const char * fmtin)
- {
- struct tm tm;
- memset(&tm, 0, sizeof(tm));
- tm.tm_mday = 1;
- if (simple_strptime(lenS, s, fmtin, &tm))
- return makeDate(tm);
- return 0;
- }
- STRINGLIB_API unsigned STRINGLIB_CALL slStringToTimeOfDay(size32_t lenS, const char * s, const char * fmtin)
- {
- struct tm tm;
- memset(&tm, 0, sizeof(tm));
- if (simple_strptime(lenS, s, fmtin, &tm))
- return makeTimeOfDay(tm);
- return 0;
- }
- STRINGLIB_API unsigned STRINGLIB_CALL slMatchDate(size32_t lenS, const char * s, bool isAllFormats, unsigned lenFormats, const void * _formats)
- {
- struct tm tm;
- const char * formats = (const char *)_formats;
- for (unsigned off=0; off < lenFormats; )
- {
- const char * curFormat = formats+off;
-
- memset(&tm, 0, sizeof(tm));
- tm.tm_mday = 1;
- if (simple_strptime(lenS, s, curFormat, &tm))
- return makeDate(tm);
- off += strlen(curFormat) + 1;
- }
- return 0;
- }
- STRINGLIB_API unsigned STRINGLIB_CALL slMatchTimeOfDay(size32_t lenS, const char * s, bool isAllFormats, unsigned lenFormats, const void * _formats)
- {
- struct tm tm;
- const char * formats = (const char *)_formats;
- for (unsigned off=0; off < lenFormats; )
- {
- const char * curFormat = formats+off;
-
- memset(&tm, 0, sizeof(tm));
- if (simple_strptime(lenS, s, curFormat, &tm))
- return makeTimeOfDay(tm);
- off += strlen(curFormat) + 1;
- }
- return 0;
- }
- STRINGLIB_API void STRINGLIB_CALL slFormatDate(size32_t & __lenResult, char * & __result, unsigned date, const char * format)
- {
- size32_t len = 0;
- char * out = NULL;
- if (date)
- {
- struct tm tm;
- memset(&tm, 0, sizeof(tm));
- extractDate(tm, date);
- char buf[255];
- #if defined(__clang__) || defined(__GNUC__)
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wformat-nonliteral"
- #endif
- strftime(buf, sizeof(buf), format, &tm);
- #if defined(__clang__) || defined(__GNUC__)
- #pragma GCC diagnostic pop
- #endif
- len = strlen(buf);
- out = static_cast<char *>(CTXMALLOC(parentCtx, len));
- memcpy_iflen(out, buf, len);
- }
- __lenResult = len;
- __result = out;
- }
- //--------------------------------------------------------------------------------------------------------------------
- //--------------------------------------------------------------------------------------------------------------------
- //--------------------------------------------------------------------------------------------------------------------
- // Legacy functions that only work on fixed length strings
- //--------------------------------------------------------------------------------------------------------------------
- //--------------------------------------------------------------------------------------------------------------------
- //--------------------------------------------------------------------------------------------------------------------
- STRINGLIB_API void STRINGLIB_CALL slStringExtract50(char *tgt, unsigned srcLen, const char * src, unsigned instance)
- {
- unsigned lenret;
- char * resret;
- slStringExtract(lenret,resret,srcLen,src,instance);
- if (lenret >= 50)
- memcpy(tgt,resret,50);
- else
- {
- memcpy_iflen(tgt,resret,lenret);
- memset(tgt+lenret,' ',50-lenret);
- }
- CTXFREE(parentCtx, resret);
- }
- STRINGLIB_API void STRINGLIB_CALL slGetBuildInfo100(char *tgt)
- {
- size32_t len = (size32_t) strlen(STRINGLIB_VERSION);
- if (len >= 100)
- len = 100;
- memcpy(tgt, STRINGLIB_VERSION, len);
- memset(tgt+len, ' ', 100-len);
- }
- // -----------------------------------------------------------------
- STRINGLIB_API void STRINGLIB_CALL slStringToLowerCase80(char *tgt, unsigned srcLen, const char * src)
- {
- unsigned int i;
- for (i=0;i<srcLen && i < 80;i++)
- *tgt++ = tolower(src[i]);
- while (i < 80)
- {
- *tgt++=' ';
- i++;
- }
- }
- // -----------------------------------------------------------------
- STRINGLIB_API void STRINGLIB_CALL slStringToUpperCase80(char *tgt, unsigned srcLen, const char * src)
- {
- unsigned int i;
- for (i=0;i<srcLen && i < 80;i++)
- *tgt++ = toupper(src[i]);
- while (i < 80)
- {
- *tgt++=' ';
- i++;
- }
- }
- // -----------------------------------------------------------------
- STRINGLIB_API void STRINGLIB_CALL slStringFindReplace80(char * tgt, unsigned srcLen, const char * src, unsigned stokLen, const char * stok, unsigned rtokLen, const char * rtok)
- {
- if ( srcLen < stokLen )
- {
- if (srcLen > 80)
- srcLen = 80;
- memcpy_iflen(tgt, src, srcLen);
- if (srcLen < 80)
- memset(tgt+srcLen, ' ', 80 - srcLen);
- }
- else
- {
- unsigned steps = srcLen-stokLen+1;
- unsigned i;
- unsigned lim = 80;
- for ( i = 0; i < steps && lim > 0; )
- {
- if ( !memcmp(src+i,stok,stokLen) )
- {
- if (rtokLen > lim)
- rtokLen = lim;
- memcpy_iflen(tgt, rtok, rtokLen);
- tgt += rtokLen;
- i += stokLen;
- lim -= rtokLen;
- }
- else
- {
- *tgt++ = src[i++];
- lim--;
- }
- }
- while (i < srcLen && lim > 0)
- {
- *tgt++ = src[i++];
- lim--;
- }
- if (lim)
- memset(tgt, ' ', lim);
- }
- }
- STRINGLIB_API void STRINGLIB_CALL slStringCleanSpaces25(char *__ret_str,unsigned _len_instr,const char * instr)
- {
- // remove double spaces
- // Fixed width version for Hole
- unsigned outlen = _len_instr;
- if (outlen < 25)
- outlen = 25;
- char *out = (char *) alloca(outlen);
- char *origout = out;
- bool spacePending = false;
- bool atStart = true;
- for(unsigned idx = 0; idx < _len_instr; idx++)
- {
- char c = *instr++;
- switch (c)
- {
- case ' ':
- case '\t':
- spacePending = true;
- break;
- default:
- if (spacePending && !atStart)
- *out++ = ' ';
- spacePending = false;
- atStart = false;
- *out++ = c;
- break;
- }
- }
- unsigned len = (size32_t)(out-origout);
- if (len < 25)
- memset(out, ' ', 25 - len);
- memcpy(__ret_str, origout, 25);
- }
- STRINGLIB_API void STRINGLIB_CALL slStringCleanSpaces80(char *__ret_str,unsigned _len_instr,const char * instr)
- {
- // remove double spaces
- // Another fixed width version for Hole
- unsigned outlen = _len_instr;
- if (outlen < 80)
- outlen = 80;
- char *out = (char *) alloca(outlen);
- char *origout = out;
- bool spacePending = false;
- bool atStart = true;
- for(unsigned idx = 0; idx < _len_instr; idx++)
- {
- char c = *instr++;
- switch (c)
- {
- case ' ':
- case '\t':
- spacePending = true;
- break;
- default:
- if (spacePending && !atStart)
- *out++ = ' ';
- spacePending = false;
- atStart = false;
- *out++ = c;
- break;
- }
- }
- unsigned len = (unsigned)(out-origout);
- if (len < 80)
- memset(out, ' ', 80 - len);
- memcpy(__ret_str, origout, 80);
- }
|