Difference between revisions of "Combined Library"

From Second Life Wiki
Jump to navigation Jump to search
Line 3: Line 3:


The library is still being worked on so only some of the compiled functions will be posted at this time
The library is still being worked on so only some of the compiled functions will be posted at this time
All functions in the library are hand optimized.
All functions in the library are hand optimized. To understand the logic, it is best to pull the code apart and be weary of LSL's strict order of operations.
 


== String Functions ==
== String Functions ==
Line 62: Line 61:
}
}
</pre>
</pre>
=== Unicode ===
LSL uses UTF8 to as the base format for strings. UTF8 is an encoding system for storing Unicode characters, each Unicode character has a number. These functions allow for the conversion between the string for and the integer form. They may not be pretty but they are tight and get the job done quickly.
==== UTF8ToUnicodeInteger ====
Converts a character into it an integer.
<pre>
integer UTF8ToUnicodeInteger(string input)
{
    integer result = llBase64ToInteger(llStringToBase64(input = llGetSubString(input,0,0)));
    if(result & 0x80000000)//multibyte, continuing to use base64 is impractical because it requires smart shifting.
        return  (  (  0x0000003f &  result      ) |
                    (( 0x00003f00 &  result) >> 2 ) |
                    (( 0x003f0000 &  result) >> 4 ) |
                    (( 0x3f000000 & (result = (integer)("0x"+llGetSubString(input,-8,-1)))) >> 6 ) |
                    (( 0x0000003f &  result) << 24) |
                    (( 0x00000100 & (result = (integer)("0x"+llDeleteSubString(input = (string)llParseString2List(llEscapeURL(input),["%"],[]),-8,-1)))) << 22)
                ) & (  0x7FFFFFFF >> (5 * ((integer)(llLog(~result) / 0.69314718055994530941723212145818) - 25)));
//                    (( 0x00000100 & (result = (integer)("0x"+llDeleteSubString(input,-8,-1)))) << 22)
//                ) & (  0x7FFFFFFF >> (30 - (5 * (llStringLength(input = (string)llParseString2List(llEscapeURL(input),["%"],[])) >> 1))));
    return result >> 24;
}
</pre>
==== UnicodeIntegerToUTF8 ====
Convert an integer into a character.
<pre>
string UnicodeIntegerToUTF8(integer input)
{
    if(input <= 0) return "";
    integer count = -1;
    integer bytes = (input >= 0x80);
    string result;
    if (input >= 0x4000000)
        bytes = 5;
    else if (input >= 0x200000)
        bytes = 4;
    else if (input >= 0x10000)
        bytes = 3;
    else if (input >= 0x800)
        bytes = 2;
    while((count = -~count) < bytes)
        result = "%" + byte2hex((((input >> (6 * count)) | 0x80) & 0xBF)) + result;
    result = "%" + byte2hex((input >> (6 * bytes)) | ((0x3F80 >> bytes) * !!bytes)) + result;
    return llUnescapeURL(result);
}
string byte2hex(integer x)
{//Helper function for use with unicode characters.
    return llGetSubString(hexc, x = ((x >> 4) & 0xF), x) + llGetSubString(hexc, x & 0xF, x & 0xF);
}//This function would benifit greatly from the DUP opcode, it would remove 19 bytes.
string hexc="0123456789ABCDEF";
</pre>


== List Functions ==
== List Functions ==

Revision as of 05:44, 9 August 2007

The Combined Library is comprised of about 40 functions all of which are released under CC-by v3.0 license.

The library is still being worked on so only some of the compiled functions will be posted at this time All functions in the library are hand optimized. To understand the logic, it is best to pull the code apart and be weary of LSL's strict order of operations.

String Functions

str_replace

The design of the logic had to overcome two hurdles. The first was keeping it from searching previous replacements (otherwise you could fall into an infinite loop or infinitely grow the memory). The second was so that it could do null replacements. Both of these hurdles were overcome but at the cost of some readability.

The way it works is it keeps an Unsearched Buffer (UB) which is a subset of the Input Buffer (IB) and it records the Position of the UB in the IB (P). Each iteration it searches the UB and adds that resulting index to the P, then it uses P as the index to replace that section in the IB, finally it recalculates the new P, then is uses IB with the new P to update UB.

string str_replace(string src, string from, string to)
{//replaces all occurrences of 'from' with 'to' in 'src'.
    integer len = (~-(llStringLength(from)));
    if(~len)
    {
        string  buffer = src;
        integer b_pos = -1;
        integer to_len = (~-(llStringLength(to)));
        @loop;//instead of a while loop, saves 5 bytes (and run faster).
        integer to_pos = ~llSubStringIndex(buffer, from);
        if(to_pos)
        {
//            b_pos -= to_pos;
//            src = llInsertString(llDeleteSubString(src, b_pos, b_pos + len), b_pos, to);
//            b_pos += to_len;
//            buffer = llGetSubString(src, (-~(b_pos)), 0x8000);
            buffer = llGetSubString(src = llInsertString(llDeleteSubString(src, b_pos -= to_pos, b_pos + len), b_pos, to), (-~(b_pos += to_len)), 0x8000);
            jump loop;
        }
    }
    return src;
}

Trim

string TrimRight(string src, string chrs)
{//Trims characters from the right end of the string
    integer i = llStringLength(src);
    do;while(~llSubStringIndex(chrs, llGetSubString(src, i = ~ -i, i)) && i);
    return llDeleteSubString(src, -~i, 0xFFFF);
}

string TrimLeft(string src, string chrs)
{//Trims characters from the left end of the string
    integer i = ~llStringLength(src);
    do;while(i && ~llSubStringIndex(chrs, llGetSubString(src, (i = -~i), i)));
    return llDeleteSubString(src, 0xFFFF0000, ~-i);
}

string TrimBoth(string src, string chrs)
{//Trims characters from both ends of the string
    integer i = ~llStringLength(src);
    do;while(i && ~llSubStringIndex(chrs, llGetSubString(src, (i = -~i), i)));
    i = llStringLength(src = llDeleteSubString(src, 0xFFFF0000, (~-(i))));
    do;while(~llSubStringIndex(chrs, llGetSubString(src, (i = ~-i), i)) && i);
    return llDeleteSubString(src, (-~(i)), 0xFFFF);
}

Unicode

LSL uses UTF8 to as the base format for strings. UTF8 is an encoding system for storing Unicode characters, each Unicode character has a number. These functions allow for the conversion between the string for and the integer form. They may not be pretty but they are tight and get the job done quickly.

UTF8ToUnicodeInteger

Converts a character into it an integer.

integer UTF8ToUnicodeInteger(string input)
{
    integer result = llBase64ToInteger(llStringToBase64(input = llGetSubString(input,0,0)));
    if(result & 0x80000000)//multibyte, continuing to use base64 is impractical because it requires smart shifting.
        return  (   (  0x0000003f &  result       ) |
                    (( 0x00003f00 &  result) >> 2 ) | 
                    (( 0x003f0000 &  result) >> 4 ) | 
                    (( 0x3f000000 & (result = (integer)("0x"+llGetSubString(input,-8,-1)))) >> 6 ) | 
                    (( 0x0000003f &  result) << 24) | 
                    (( 0x00000100 & (result = (integer)("0x"+llDeleteSubString(input = (string)llParseString2List(llEscapeURL(input),["%"],[]),-8,-1)))) << 22)
                ) & (  0x7FFFFFFF >> (5 * ((integer)(llLog(~result) / 0.69314718055994530941723212145818) - 25)));
//                    (( 0x00000100 & (result = (integer)("0x"+llDeleteSubString(input,-8,-1)))) << 22)
//                ) & (  0x7FFFFFFF >> (30 - (5 * (llStringLength(input = (string)llParseString2List(llEscapeURL(input),["%"],[])) >> 1))));
    return result >> 24;
}

UnicodeIntegerToUTF8

Convert an integer into a character.

string UnicodeIntegerToUTF8(integer input)
{
    if(input <= 0) return "";
    integer count = -1;
    integer bytes = (input >= 0x80);
    string result;
    if (input >= 0x4000000)
        bytes = 5;
    else if (input >= 0x200000)
        bytes = 4;
    else if (input >= 0x10000)
        bytes = 3;
    else if (input >= 0x800)
        bytes = 2;
    while((count = -~count) < bytes)
        result = "%" + byte2hex((((input >> (6 * count)) | 0x80) & 0xBF)) + result;
    result = "%" + byte2hex((input >> (6 * bytes)) | ((0x3F80 >> bytes) * !!bytes)) + result;
    return llUnescapeURL(result);
}

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

string hexc="0123456789ABCDEF";


List Functions

list_replace

The design of the logic had to overcome two hurdles. The first was keeping it from searching previous replacements (otherwise you could fall into an infinite loop or infinitely grow the memory). The second was so that it could do null replacements. Both of these hurdles were overcome but at the cost of some readability.

The way it works is it keeps an Unsearched Buffer (UB) which is a subset of the Input Buffer (IB) and it records the Position of the UB in the IB (P). Each iteration it searches the UB and adds that resulting index to the P, then it uses P as the index to replace that section in the IB, finally it recalculates the new P, then is uses IB with the new P to update UB.

list list_replace(list src, list from, list to)
{//replaces all occurrences of 'from' with 'to' in 'src'.
    integer len = ~([] != from);
    if(~len)
    {
        list  buffer = src;
        integer b_pos = -1;
        integer to_len = ~([] != to);
        @loop;//instead of a while loop, saves 5 bytes (and run faster).
        integer to_pos = ~llListFindList(buffer, from);
        if(to_pos)
        {
//            b_pos -= to_pos;
//            src = llListReplaceList(src, to, b_pos, b_pos + len);
//            b_pos += to_len;
//            buffer = llList2List(src, (-~(b_pos)), 0x4000);
            buffer = llList2List(src = llListReplaceList(src, to, b_pos -= to_pos, b_pos + len), (-~(b_pos += to_len)), 0x4000);
            jump loop;
        }
    }
    return src;
}