Author Topic: An efficient string parser?  (Read 342 times)

Legacy_Kato -

  • Hero Member
  • *****
  • Posts: 747
  • Karma: +0/-0
An efficient string parser?
« on: November 20, 2011, 05:30:56 pm »


               Hi all,

Does that exist or I should instead use a custom one(or re-write the ones below)? I mean:

- x0_i0_stringlib functions are slow and unadvised by the lexicon team.
- x3_inc_string StringParse() seems to work with two-part strings only, and I don't know if it's a better alternative anyway.

Maybe I have missed another include file. Any thoughts?

Thank you!


Kato 
               
               

               


                     Modifié par Kato_Yang, 20 novembre 2011 - 05:48 .
                     
                  


            

Legacy_FunkySwerve

  • Hero Member
  • *****
  • Posts: 2325
  • Karma: +0/-0
An efficient string parser?
« Reply #1 on: November 20, 2011, 10:39:50 pm »


               We use our own custom library for string manipulation, written by acaos. My favorite is GetFirstSubstring, which lets you loop through concatenated strings with dividers, making them into pseudolists. I did a quick snatchngrab of string functions - not sure all the declarations have matching functions and vice versa, lmk if you want more, or examples of usage:


/* Replace the first (or all) occurrence of sFind in sStr with sRepl. */
string ReplaceString (string sStr, string sFind, string sRepl, int bAll=FALSE, int nLen=-1);

/* Return the specified digit nDigit of nInt. nDigit is the number of
 * powers of 10 to use (hence, 0 = 1s, 1 = 10s, 2 = 100s, etc). */
int GetIntegerDigit (int nInt, int nDigit);

/* Set the specified digit nDigit of nInt. */
int SetIntegerDigit (int nInt, int nDigit, int nValue);

/* Return an IntList struct containing all the digits of nInt. */
struct IntList GetDigitList (int nInt);

/* Get a random floating-point number in the range [-1.0, 1.0]. If fRange
 * is specified, a random number in the range [0.0, fRange] will be returned. */
float RandomFloat (float fRange=0.0);

/* Return the substring at the given index nIndex of sString, separating
 * sString with sSep. */
string GetStringSubString (string sString, int nIndex, string sSep=" ");

/* Return the number of substrings sString would have if it were separated
 * by sSep. */
int GetStringSubStrings (string sString, string sSep=" ");

/* Return a random string of sString separated by sSep. */
string GetRandomSubString (string sString, string sSep=" ");

/* Return a SubString struct containing the first substring of sString
 * separated by sSep, as well as the remainder of sString. The idiom
 * would be:
 *
 *   struct SubString ss;
 *
 *   ss.rest = sString;
 *
 *   while (ss.rest != "") {
 *       ss = GetFirstSubString(ss.rest);
 *
 *       (do things here)
 *   }
 */
struct SubString GetFirstSubString (string sString, string sSep = " ");

/* Return a StringList struct containing strings extracted from sString
 * separated by sSep. */
struct StringList GetStringList (string sString, string sSep=" ", int nLimit=16);

/* Return an IntList struct containing integers extracted from sString
 * separated by sSep. */
struct IntList GetIntList (string sString, string sSep=" ", int nLimit=10);

/* Justify a string to a given number of pixels wide. */
string JustifyString (string sStr, int nPixelWidth, int bRight=FALSE, int nFont=0, string sJustifyWith=" ");

/* Return either the resref or playername of oObject. */
string GetObjectString (object oObject);

/* Return vPos in string form X, Y, Z. */
string GetPositionStringFromVector (vector vPos);

/* Return the position of lLoc in string form [X, Y, Z | F] */
string GetPositionStringFromLocation (location lLoc);

/* Return the position of oObject in string form [X, Y, Z | F] */
string GetPositionString (object oObject);

string ReplaceString (string sStr, string sFind, string sRepl, int bAll=FALSE, int nLen=-1) {
    int nPos = FindSubString(sStr, sFind);

    if (nPos < 0 || sStr == "")
        return sStr;

    if (nLen < 0)
        nLen = GetStringLength(sFind);

    do {
        sStr = GetStringLeft(sStr, nPos) + sRepl +
               GetStringRight(sStr, GetStringLength(sStr) - (nPos + nLen));

        if (!bAll)
            break;
        nPos = FindSubString(sStr, sFind);
    } while (nPos >= 0);

    return sStr;
}

int GetIntegerDigit (int nInt, int nDigit) {
    switch (nDigit) {
        case 0: nDigit = 1; break;
        case 1: nDigit = 10; break;
        case 2: nDigit = 100; break;
        case 3: nDigit = 1000; break;
        case 4: nDigit = 10000; break;
        case 5: nDigit = 100000; break;
        case 6: nDigit = 1000000; break;
        case 7: nDigit = 10000000; break;
        case 8: nDigit = 100000000; break;
        case 9: nDigit = 1000000000; break;
        default:
            return 0;
    }

    return ((nInt / nDigit) % 10);
}

int SetIntegerDigit (int nInt, int nDigit, int nValue) {
    if (nValue < 0)
        nValue = 0;
    else if (nValue > 9)
        nValue = 9;

    switch (nDigit) {
        case 0: nDigit = 1; break;
        case 1: nDigit = 10; break;
        case 2: nDigit = 100; break;
        case 3: nDigit = 1000; break;
        case 4: nDigit = 10000; break;
        case 5: nDigit = 100000; break;
        case 6: nDigit = 1000000; break;
        case 7: nDigit = 10000000; break;
        case 8: nDigit = 100000000; break;
        case 9: nDigit = 1000000000; break;
        default:
            return 0;
    }

    nInt -= ((nInt / nDigit) % 10) * nDigit;
    nInt += nValue * nDigit;

    return nInt;
}

struct IntList GetDigitList (int nInt) {
    struct IntList ret;

    ret.i0 = (nInt % 10);
    ret.i1 = (nInt /= 10) % 10;
    ret.i2 = (nInt /= 10) % 10;
    ret.i3 = (nInt /= 10) % 10;
    ret.i4 = (nInt /= 10) % 10;
    ret.i5 = (nInt /= 10) % 10;
    ret.i6 = (nInt /= 10) % 10;
    ret.i7 = (nInt /= 10) % 10;
    ret.i8 = (nInt /= 10) % 10;
    ret.i9 = (nInt /= 10) % 10;

    return ret;
}

float RandomFloat (float fRange=0.0) {
    if (fRange > 0.0)
        return (Random(FloatToInt(fRange * 1000)) / 1000.0);

    return ((Random(10000001) - 5000000) / 5000000.0);
}

float RandomNormal (float fStdDev=1.0, float fMean=0.0) {
    float u1, u2, v1, v2, s;

    do {
        u1 = RandomFloat();
        u2 = RandomFloat();
        v1 = (2.0 * u1) - 1.0;
        v2 = (2.0 * u2) - 1.0;
        s  = (v1 * v1) + (v2 * v2);
    } while (s > 1.0);

    return (sqrt((-2.0 * log(s)) / s) * v1 * fStdDev) + fMean;
}

string GetStringSubString (string sString, int nIndex, string sSep=" ") {
    int nSep, nStart = 0, nSkip = GetStringLength(sSep);

    while (nIndex-- > 0) {
        nSep = FindSubString(sString, sSep, nStart);

        if (nSep < 0)
            return "";

        nStart = nSep + nSkip;
    }

    if ((nSep = FindSubString(sString, sSep, nStart)) < 0)
        nSep = GetStringLength(sString);

    return GetSubString(sString, nStart, (nSep - nStart));
}

int GetStringSubStrings (string sString, string sSep=" ") {
    int nCount = 1, nStart = 0;
    int nSep = FindSubString(sString, sSep);
    int nSkip = GetStringLength(sSep);

    if (nSkip < 1)
        return 1;

    while (nSep >= 0) {
        nCount++;
        nSep = FindSubString(sString, sSep, nSep + nSkip);
    }

    return nCount;
}

string GetRandomSubString (string sString, string sSep=" ") {
    int nCount = GetStringSubStrings(sString, sSep);

    return GetStringSubString(sString, Random(nCount), sSep);
}

struct SubString GetFirstSubString (string sString, string sSep = " ") {
    struct SubString ret;
    int nSep = FindSubString(sString, sSep);

    if (nSep < 0) {
        ret.first = sString;
        ret.rest  = "";

        return ret;
    }

    ret.first = GetStringLeft(sString, nSep);
    ret.rest  = GetStringRight(sString, GetStringLength(sString) - (nSep + GetStringLength(sSep)));

    return ret;
}

struct StringList GetStringList (string sString, string sSep=" ", int nLimit=16) {
    int nCount = 0, nSep = 0, nStart = 0;
    int nSkip = GetStringLength(sSep);
    int nLen = GetStringLength(sString);
    struct StringList sl;

    if (nSkip < 1) {
        sl.size = 0;
        return sl;
    }

    while (nSep < nLen && nCount < nLimit) {
        nSep = FindSubString(sString, sSep, nStart);
        if (nSep < 0)
            nSep = nLen;

        switch (nCount & 1) {
            case 0: switch (nCount++) {
                case  0: sl.s0  = GetSubString(sString, nStart, (nSep - nStart)); break;
                case  2: sl.s2  = GetSubString(sString, nStart, (nSep - nStart)); break;
                case  4: sl.s4  = GetSubString(sString, nStart, (nSep - nStart)); break;
                case  6: sl.s6  = GetSubString(sString, nStart, (nSep - nStart)); break;
                case  8: sl.s8  = GetSubString(sString, nStart, (nSep - nStart)); break;
                case 10: sl.s10 = GetSubString(sString, nStart, (nSep - nStart)); break;
                case 12: sl.s12 = GetSubString(sString, nStart, (nSep - nStart)); break;
                case 14: sl.s14 = GetSubString(sString, nStart, (nSep - nStart)); break;
            }
            break;

            case 1: switch (nCount++) {
                case  1: sl.s1  = GetSubString(sString, nStart, (nSep - nStart)); break;
                case  3: sl.s3  = GetSubString(sString, nStart, (nSep - nStart)); break;
                case  5: sl.s5  = GetSubString(sString, nStart, (nSep - nStart)); break;
                case  7: sl.s7  = GetSubString(sString, nStart, (nSep - nStart)); break;
                case  9: sl.s9  = GetSubString(sString, nStart, (nSep - nStart)); break;
                case 11: sl.s11 = GetSubString(sString, nStart, (nSep - nStart)); break;
                case 13: sl.s13 = GetSubString(sString, nStart, (nSep - nStart)); break;
                case 15: sl.s15 = GetSubString(sString, nStart, (nSep - nStart)); break;
            }
            break;
        }

        nStart = nSep + nSkip;
    }

    sl.size = nCount;

    return sl;
}

struct IntList GetIntList (string sString, string sSep=" ", int nLimit=10) {
    int nCount = 0, nSep = 0, nStart = 0;
    int nLen = GetStringLength(sString);
    int nSkip = GetStringLength(sSep);
    struct IntList il;

    if (nSkip < 1) {
        il.size = 0;
        return il;
    }

    while (nSep < nLen && nCount < nLimit) {
        nSep = FindSubString(sString, sSep, nStart);
        if (nSep < 0)
            nSep = nLen;

        switch (nCount++) {
            case  0: il.i0  = StringToInt(GetSubString(sString, nStart, (nSep - nStart))); break;
            case  1: il.i1  = StringToInt(GetSubString(sString, nStart, (nSep - nStart))); break;
            case  2: il.i2  = StringToInt(GetSubString(sString, nStart, (nSep - nStart))); break;
            case  3: il.i3  = StringToInt(GetSubString(sString, nStart, (nSep - nStart))); break;
            case  4: il.i4  = StringToInt(GetSubString(sString, nStart, (nSep - nStart))); break;
            case  5: il.i5  = StringToInt(GetSubString(sString, nStart, (nSep - nStart))); break;
            case  6: il.i6  = StringToInt(GetSubString(sString, nStart, (nSep - nStart))); break;
            case  7: il.i7  = StringToInt(GetSubString(sString, nStart, (nSep - nStart))); break;
            case  8: il.i8  = StringToInt(GetSubString(sString, nStart, (nSep - nStart))); break;
            case  9: il.i9  = StringToInt(GetSubString(sString, nStart, (nSep - nStart))); break;
        }

        nStart = nSep + nSkip;
    }

    il.size = nCount;

    return il;
}

string JustifyString (string sStr, int nPixelWidth, int bRight=FALSE, int nFont=0, string sJustifyWith=" ") {
    int i, nSpace, nLen = GetStringLength(sStr), nWidth = nLen - 1;
    string sWidths;

    switch (nFont) {
        case 0:         /* normal */
            nSpace  = (sJustifyWith == "." ? 2 : 4);
            sWidths = "  3 05 13 25 35 45 55 65 75 85 95 A7 B6 C6 D6 E5 F5 G7 H6 I1 J4 K6 L5 M7 N6 O7 P5 Q7 R6 S6 T5 U6 V7 W11 X6 Y7 Z6 a5 b5 c5 d5 e5 f3 g5 h5 i1 j2 k4 l1 m7 n5 o5 p5 q5 r3 s5 t2 u5 v5 w9 x5 y5 z5 !1 #5 $5 %9 &6 '1 (3 )3 *3 +5 ,1 -5 .1 /3 :1 ;1 <5 >5 ?5 @10 [2 ]2 ^5 {3 |1 }3 ~5";
            /* double quote = 3 */
            break;

        case 1:         /* high-resolution */
            nSpace  = (sJustifyWith == "." ? 3 : 5);
            sWidths = "  4 07 14 27 37 48 57 67 77 87 97 A10 B8 C9 D9 E8 F8 G10 H8 I2 J6 K9 L8 M10 N8 O10 P8 Q10 R9 S8 T8 U8 V10 W14 X9 Y10 Z9 a7 b7 c6 d7 e7 f5 g7 h7 i2 j3 k7 l2 m10 n7 o7 p7 q7 r5 s6 t5 u7 v8 w10 x7 y8 z7 !2 #9 $8 %11 &9 '2 (4 )4 *6 +8 ,2 -5 .2 /5 :2 ;2 <7 >7 ?7 @13 [3 ]3 ^6 {4 |2 }4 ~8";
            /* double quote = 4 */
            break;

        case 2:         /* journal */
            nSpace  = (sJustifyWith == "." ? 3 : 8);
            sWidths = "  7 06 12 25 36 48 56 66 76 86 96 A9 B6 C10 D9 E6 F6 G9 H7 I2 J4 K7 L6 M10 N9 O10 P5 Q11 R7 S6 T9 U8 V10 W13 X9 Y9 Z9 a5 b7 c6 d7 e7 f7 g7 h6 i2 j4 k7 l2 m10 n6 o6 p7 q6 r4 s4 t7 u6 v6 w10 x6 y6 z6 !1 #8 $7 %9 &10 '2 (4 )4 *4 +6 ,2 -4 .2 /4 ?6 @8 [4 ]4 ^5 {5 }5 ~5";
            /* double quote = 4 */
            break;

        default:
            return sStr;
    }

    for (i = 0; i < nLen; i++) {
        string sChar = GetSubString(sStr, i, 1);
        int nCharPos = FindSubString(sWidths, " " + sChar);

        if (nCharPos >= 0) {
            int nCharWidth = StringToInt(GetSubString(sWidths, nCharPos + 2, 2));
            nWidth += nCharWidth;
        }
    }

    if (bRight) {
        while (nWidth < nPixelWidth) {
            sStr    = sJustifyWith + sStr;
            nWidth += nSpace;
        }
    } else {
        while (nWidth < nPixelWidth) {
            sStr    = sStr + sJustifyWith;
            nWidth += nSpace;
        }
    }

    return sStr;
}

string GetObjectString (object oObject) {
    if (GetIsPC(oObject))
        return GetPCPlayerName(oObject);

    return GetResRef(oObject);
}

string GetPositionStringFromVector (vector vPos) {
    return FloatToString(vPos.x, 1, 2) + ", " +
           FloatToString(vPos.y, 1, 2) + ", " +
           FloatToString(vPos.z, 1, 2);
}

string GetPositionStringFromLocation (location lLoc) {
    vector vPos = GetPositionFromLocation(lLoc);

    return "[" + GetPositionStringFromVector(GetPositionFromLocation(lLoc)) +
        " | " + FloatToString(GetFacingFromLocation(lLoc), 1, 0) + "]";
}

string GetPositionString (object oObject) {
    return GetPositionStringFromLocation(GetLocation(oObject));
}

location GetLocationFromString (object oArea, string sLoc) {
    float fFacing;
    vector vVec;

    vVec = Vector(StringToFloat(GetStringSubString(sLoc, 0, ",")),
                  StringToFloat(GetStringSubString(sLoc, 1, ",")),
                  StringToFloat(GetStringSubString(sLoc, 2, ",")));
    fFacing = StringToFloat(GetStringSubString(sLoc, 3, ","));

    return Location(oArea, vVec, fFacing);
}


Funky
               
               

               
            

Legacy_Kato -

  • Hero Member
  • *****
  • Posts: 747
  • Karma: +0/-0
An efficient string parser?
« Reply #2 on: November 21, 2011, 12:00:32 am »


               Lol. What can I say? Thanks a lot Funky!!
               
               

               
            

Legacy_Shadooow

  • Hero Member
  • *****
  • Posts: 7698
  • Karma: +0/-0
An efficient string parser?
« Reply #3 on: November 21, 2011, 03:20:32 am »


               alternatively you can try my take, I wrote it long time ago so there might still be something to improve

// Find the position of nTh sSubstring inside sString
// * Return value on error: -1
int FindNthSubString(string sString, string sSubString, int nTh);

//returns left side of string from nTh char
//eg. ("hello",3) returns "he"
string GetStringLeftSideFrom(string sString, int nChar);

//returns right side of string from nTh char
//eg. ("hello",3) returns "o"
string GetStringRightSideFrom(string sString, int nChar);

//This function will create and return MultiString
string MultiStringCreate(string sValue, string sDelimiter="|");

//This function adds new value at the end of MultiStringt and returns it.
//sMultiString - result from MultiStringCreate or manually created MultiString
string MultiStringAdd(string sMultiString, string sValue, string sDelimiter="|");

//This function adds new value to nIdex and returns MultiString. That increase index of all values right from
//nIndex by 1.
string MultiStringInsert(string sMultiString, string sValue, int nIndex, string sDelimiter="|");

//Remove nTh value from MultiString. That lower index of all values right from nTh by 1.
string MultiStringRemove(string sMultiString, int nTh, string sDelimiter="|");

//returns first value from MultiString
string MultiStringGetFirst(string sMultiString, string sDelimiter="|");

//returns next value from MultiString
string MultiStringGetNext(string sMultiString, string sDelimiter="|");

//returns nTh value from MultiString
string MultiStringGetNth(string sMultiString, int nTh, string sDelimiter="|");

//returns value index in MultiString or 0 if value isn't in MultiString
//Index starts at 1!
int MultiStringGetIndex(string sMultiString, string sValue, int nTh=1, string sDelimiter="|");

//Returns number of variables stored in MultiString
int MultiStringGetCount(string sMultiString, string sDelimiter="|");

//returns sDelimiter used in MultiString to divide values
string MultiStringGetDelimiter(string sMultiString);



string GetStringLeftSideFrom(string sString, int nChar)
{
return GetStringLeft(sString,nChar-1);
}

string GetStringRightSideFrom(string sString, int nChar)
{
return GetStringRight(sString,GetStringLength(sString)-nChar);
}


int FindNthSubString(string sString, string sSubString, int nTh)
{
int nFind, nRet;
 for(nRet=-1;nTh > 0;nTh--)
 {
 nFind = FindSubString(sString,sSubString,nRet+1);
  if(nFind < 0)
  {
  return -1;
  }
 nRet = nFind;
 }
return nRet;
}



string MultiStringCreate(string sValue, string sDelimiter="|")
{
return sValue+sDelimiter;
}

string MultiStringAdd(string sMultiString, string sValue, string sDelimiter="|")
{
return sMultiString+(GetStringRight(sMultiString,1) != sDelimiter ? sDelimiter : "")+sValue+sDelimiter;
}

string MultiStringRemove(string sMultiString, int nTh, string sDelimiter="|")
{
return nTh<2 ? GetStringRightSideFrom(sMultiString,FindSubString(sMultiString,sDelimiter)+1) : GetStringLeft(sMultiString,FindNthSubString(sMultiString,sDelimiter,nTh-1))+GetStringRightSideFrom(sMultiString,FindNthSubString(sMultiString,sDelimiter,nTh));
}

string MultiStringGetFirst(string sMultiString, string sDelimiter="|")
{
SetLocalInt(OBJECT_SELF,"MultiStringGetNth",1);
return GetStringLeft(sMultiString,FindSubString(sMultiString,sDelimiter)+1);
}

string MultiStringGetNext(string sMultiString, string sDelimiter="|")
{
int nTh = GetLocalInt(OBJECT_SELF,"MultiStringGetNth")+1;
SetLocalInt(OBJECT_SELF,"MultiStringGetNth",nTh);
return MultiStringGetNth(sMultiString,nTh,sDelimiter);
}

string MultiStringGetNth(string sMultiString, int nTh, string sDelimiter="|")
{
 if(nTh < 1)
 {
 return "";
 }
 if(GetStringRight(sMultiString,1) != sDelimiter)
 {
 sMultiString+= sDelimiter;
 }
int nFind, n = 1;
 while(nFind > -1 && n < nTh)
 {
 n++;
 nFind = FindSubString(sMultiString,sDelimiter,nFind)+1;
 }
 if(n < nTh)
 {
 return "";
 }
return GetSubString(sMultiString,nFind,FindSubString(sMultiString,sDelimiter,nFind)-nFind);
}

int MultiStringGetCount(string sMultiString, string sDelimiter="|")
{
 if(sMultiString == "")
 {
 return 0;
 }
 else if(GetStringRight(sMultiString,1) != sDelimiter)
 {
 sMultiString+= sDelimiter;
 }
int nTh, nFind = FindSubString(sMultiString,sDelimiter,0);
 while(nFind > -1)
 {
 nTh++;
 nFind = FindSubString(sMultiString,sDelimiter,nFind+1);
 }
return nTh;
}

int MultiStringGetIndex(string sMultiString, string sValue, int nTh=1, string sDelimiter="|")
{
 if(GetStringRight(sMultiString,1) != sDelimiter)
 {
 sMultiString+= sDelimiter;
 }
sValue+= sDelimiter;
int n = 1;
int nFind = FindSubString(sMultiString,sValue,0);
 while(nFind > -1 && n < nTh)
 {
 n++;
 nFind = FindSubString(sMultiString,sValue,nFind+GetStringLength(sValue)+1);
 }
 if(nFind < 0)
 {
 return 0;
 }
return nFind<0 ? 0 : MultiStringGetCount(GetStringLeft(sMultiString,nFind),sDelimiter)+1;
}

string MultiStringInsert(string sMultiString, string sValue, int nIndex, string sDelimiter="|")
{
int nPrevDelimiter = FindNthSubString(sMultiString,sDelimiter,nIndex-1)+1;
string sLeft = GetStringLeft(sMultiString,nPrevDelimiter);
string sRight = GetStringRightSideFrom(GetStringRightSideFrom(sMultiString,nPrevDelimiter),FindSubString(sLeft,sDelimiter)+1);
return sLeft+sValue+sDelimiter+sRight;
}

string MultiStringGetDelimiter(string sMultiString)
{
return GetStringRight(sMultiString,1);
}


               
               

               
            

Legacy_Kato -

  • Hero Member
  • *****
  • Posts: 747
  • Karma: +0/-0
An efficient string parser?
« Reply #4 on: November 21, 2011, 04:49:18 pm »


               Tyvm ShadoOow, I'll study this...