Unescape

From Second Life Wiki
Jump to navigation Jump to search

Takes a string and unescapes "\" style escape codes

Code Replace
\\ \
\" "
\s single space
\n new line
\t 4 spaces (tab)
\uxxxx xxxx is a 4 char hex string, of the unicode character 0000xxxx
\Uxxxxxxxx xxxxxxxx is am 8 char hex string, of the unicode character xxxxxxxx
\hXxxx... X is a hex character, it's value is the number of pairs of hex characters that follow it, xxx is a raw byte array of utf-8 characters, be sure they are valid characters
//===================================================//
//                 Combined Library                  //
//             "Jan  2 2008", "04:48:12"             //
//  Copyright (C) 2004-2007, Strife Onizuka (cc-by)  //
//    http://creativecommons.org/licenses/by/3.0/    //
//===================================================//
//{

string Unescape(string a)//Mono Safe, LSO Safe
{
    string  b = a;
    integer c = -1;
    integer d;
    integer e;
    integer f = 0; 
    string g;
    while(d = (-~(llSubStringIndex(b, "\\"))))    //"    //wiki highlighter bug
    {
        c += d;
        if(2 < (e = llSubStringIndex("uUhts\"q\\n",llGetSubString(b,d,d))))
            a = llInsertString(llDeleteSubString(a,c, (-~(c))), c, llGetSubString("     \"\"\\\n",e * (e != 3), e));
        else if(e==2)//hx[11,22,33,44,55,66,77,88,99,AA,BB,CC,DD,EE,FF]
        {
            if((f = llStringLength(b)) <= ((d) - ~(e = ((integer)("0x"+llGetSubString(b,(-~(d)),(-~(d)))) << 1))))
            {
                e = (f - d) & -2;
                b += "0";//a pad may be needed.
            }
            g = "";//flush the buffer.
            if((f = e))//this may look like a mistake, it's not
            {
                do
                    g = "%"+llGetSubString(b,d + e, ((d) - ~(e))) + g;
                while((e -= 2));//(e-=2) > 0, e should always be even
            }
            a = llInsertString(llDeleteSubString(a,c, 2 + f + c),c, g = llUnescapeURL(g));
            c += (~-(llStringLength(g)));//add to c so we don't accidentily unescape result
        }
        else if(~e)// \uXXXX or  \UXXXXXXXX
        {
            a = llDeleteSubString(a, c, ((e = 4 << e) - ~(c)));
            if(0 < (e = ((integer)("0x"+(llGetSubString(b, (-~(d)), d + e))))))
            {
                f = llCeil((llLog(e) / 0.69314718055994530941723212145818));
                f = (e >= 0x80) * ((f) + ~((((1 << f) - e) > 0))) / 5;//adjust
                g = "%" + byte2hex((e >> (6 * f)) | ((0x3F80 >> f) << !f));
                while (f)
                    g += "%" + byte2hex((((e >> (6 * (f = ~-f))) | 0x80) & 0xBF));
                a = llInsertString(a, c, llUnescapeURL(g));
            }
        }
        b = llDeleteSubString(a,0,c);
    }
    return a;
}

string byte2hex(integer x)//Mono Safe, LSO Safe
{//Helper function for use with unicode characters.
    integer y = (x >> 4) & 0xF;
    return llGetSubString(hexc, y, y) + llGetSubString(hexc, x & 0xF, x & 0xF);
}//This function would benefit greatly from the DUP opcode, it would remove 19 bytes.

string hexc="0123456789ABCDEF";

//}
//Testbed
default
{
    state_entry()
    {
        llOwnerSay((string)llGetFreeMemory());
        string a = "-\\h3414243\\h3444546\\\"\\uFFFD";
        string d = Unescape(a);
        llOwnerSay(llList2CSV([a, d]));
    }
}