Difference between revisions of "User:Void Singer/Functions"

From Second Life Wiki
Jump to navigation Jump to search
(pffft i forgot about 0x80000000, that loop was unsightly; you can be clever with the values just don't cross the 1969/1970 border or it will think it has flowed. Use clever dates to avoid the border.)
m (corrected mismatch, thanks KittenPaws)
 
(12 intermediate revisions by 3 users not shown)
Line 5: Line 5:


{{void-box
{{void-box
|title=String: Get Reverse Order
|title=uParseEquation
|content=
|content=
=== Reverse String Order (faster version) ===
* Parses a string equation and returns a formatted result
<lsl>string uStringRevF( string vStrSrc ){
* Supports the following operations and proper order of operations:
     integer vIntCnt = llStringLength( vStrSrc );
** Parenthesis("'''('''","''')'''")
     @Loop; if (vIntCnt--){
** Negation ("'''-'''")
        vStrSrc += llGetSubString( vStrSrc, vIntCnt, vIntCnt );
** Exponentiation ("'''^'''")
         jump Loop;
** Division and Multiplication ("'''/'''", "'''*'''")
** Subtraction & Addition ("'''-'''", "'''+'''")
* Supports (Case insensitive) constant replacement:
** "'''e'''" ([http://en.wikipedia.org/wiki/E_(mathematical_constant) Euler's Number]: '''2.7182817''')
** "'''pi'''" ([http://en.wikipedia.org/wiki/Pi Archimedes' Constant]: '''3.1415927''')
** "'''phi'''" ([http://en.wikipedia.org/wiki/Golden_ratio Golden Ratio]: '''1.6180340''')
* Supports implied multiplication of parenthesis and constants
** (2)3 == 2*3
** 2pi == 2*pi
* Supports Roots in the format of '''x^(1/y)''' (the "y" root of "x", where both are decimal numbers)
* Supports error detection:
** Unsuported characters
** Invalid/Missing Operators
** Divide by Zero
** Empty/Missing Parenthesis
** Ignores spaces
<source lang="lsl2">string uParseEquation( string vStrTmp ){
    list    lst_OPS = ["+", "-", "*", "/", "^"];
    list    vLstEqn;
    list    vLstTmp;
    list    vLstSwp;
    integer vIdxFnd;
    integer vIdxBgn;
    integer vIdxEnd;
     integer vIntCnt;
    integer vIntErr;
   
    vStrTmp = llToLower( "(" + vStrTmp + ")" );
     vLstTmp = llParseString2List( vStrTmp, lst_OPS + ["pi", "phi"], [] );
    vLstTmp = llParseString2List( (string)vLstTmp, ["0", "1", "2", "3", "4", "5", "6", "7"], [] );
    vLstTmp = llParseString2List( (string)vLstTmp, ["8", "9", ".", "e", "(", ")", " ", "="], [] );
    if (vLstTmp != []){
         jump Err0;
     }
     }
     return llGetSubString( vStrSrc, llStringLength( vStrSrc ) >> 1, -1 );
     vStrTmp = llDumpList2String( llParseStringKeepNulls( vStrTmp, ["e"], [] ), "(2.7182817)" );
}
    vStrTmp = llDumpList2String( llParseStringKeepNulls( vStrTmp, ["pi"], [] ), "(3.1415927)" );
/*//--                       Anti-License Text                        --//*/
    vStrTmp = llDumpList2String( llParseStringKeepNulls( vStrTmp, ["phi"], [] ), "(1.6180340)" );
/*//    Contributed Freely to the Public Domain without limitation.    //*/
    vLstEqn = llParseString2List( vStrTmp, [" ", "="], lst_OPS + ["(", ")"] );
/*//  2009 (CC0) [ http://creativecommons.org/publicdomain/zero/1.0 ]  //*/
    while (~(vIdxEnd = vIdxBgn = llListFindList( vLstEqn, (list)")" ))){
/*//  Void Singer [ https://wiki.secondlife.com/wiki/User:Void_Singer ] //*/
        while (llList2String( vLstEqn, vIdxBgn ) != "(" && ~(--vIdxBgn));
/*//--                                                                --//*/</lsl>
        if (~vIdxBgn){
 
            if (vIdxEnd - vIdxBgn > 1){
=== Reverse String Order (smaller memory version) ===
                if (~llListFindList( lst_OPS,
<lsl>string uStringRevS( string vStrSrc ){
                                    (list)llList2String( vLstTmp = llList2List( vLstEqn, -~vIdxBgn, ~-vIdxEnd ),
    integer vIntCnt = llStringLength( vStrSrc );
                                    0xFFFFFFFF ) )){
    @Loop; if (vIntCnt--){
                    jump Err1;
        vStrSrc += llGetSubString( vStrSrc, vIntCnt, vIntCnt );
                }
        vStrSrc = llDeleteSubString( vStrSrc, vIntCnt, vIntCnt );
                if (~(vIdxFnd = llListFindList( lst_OPS, (list)llList2String( vLstTmp, 0 ) ))){
         jump Loop;
                    if (1 == vIdxFnd  && !~llListFindList( lst_OPS, (list)llList2String( vLstTmp, 1 ) )){
                        vLstTmp = llListReplaceList( vLstTmp, (list)(-llList2Float( vLstTmp, 1 )), 0, 1 );
                    }else{
                        jump Err2;
                    }
                }
                vIntCnt = ([] != vLstTmp);
                while(++vIntCnt < 0){
                    if (~llListFindList( lst_OPS, (list)llList2String( vLstTmp, vIntCnt) )){
                        if (~(vIdxFnd = llListFindList( lst_OPS, (list)llList2String( vLstTmp, ++vIntCnt ) ))){
                            if (1 == vIdxFnd && !~llListFindList( lst_OPS, (list)llList2String( vLstTmp, -~vIntCnt) )){
                                vLstTmp = llListReplaceList( vLstTmp, (list)(-llList2Float( vLstTmp, vIntCnt )), vIntCnt, -~vIntCnt );
                                --vIntCnt;
                            }else{
                                jump Err3;
                            }
                        }
                    }else{
                        jump Err4;
                    }
                }
                vIntCnt = 4;
                do{
                    while (~(vIdxFnd = llListFindList( vLstTmp, (list)llList2String( lst_OPS, vIntCnt ) ))){
                        if (1 & vIntCnt){
                            if (2 & vIntCnt){
                                if (llList2String( vLstTmp, -~vIdxFnd )){
                                    vLstSwp = ["*", 1 / llList2Float( vLstTmp, -~vIdxFnd )];
                                }else{
                                    jump Err5;
                                }
                            }else{
                                vLstSwp = ["+", -llList2Float( vLstTmp, -~vIdxFnd )];
                            }
                        }else{
                            if (vIntCnt){
                                if (4 & vIntCnt){
                                    vLstSwp = (list)llPow( llList2Float( vLstTmp, ~-vIdxFnd ), llList2Float( vLstTmp, -~vIdxFnd ) );
                                }else{
                                    vLstSwp = (list)( llList2Float( vLstTmp, ~-vIdxFnd ) * llList2Float( vLstTmp, -~vIdxFnd ) );
                                }
                            }else{
                                vLstSwp = (list)( llList2Float( vLstTmp, ~-vIdxFnd ) + llList2Float( vLstTmp, -~vIdxFnd ) );
                            }
                        }
                        vLstTmp = llListReplaceList( vLstTmp, vLstSwp, vIdxFnd - !(1 & vIntCnt), -~vIdxFnd );
                    }
                }while (~(--vIntCnt));
                vLstEqn = llListReplaceList( vLstEqn, vLstTmp, vIdxBgn, vIdxEnd );
            }else{
                jump Err6;
            }
            if (!~llListFindList( lst_OPS + [")", ""], (list)llList2String( vLstEqn, -~vIdxBgn ) )){
                vLstEqn = llListInsertList( vLstEqn, (list)"*", -~vIdxBgn );
            }
            if (vIdxBgn){
                if (!~llListFindList( lst_OPS + (list)"(", (list)llList2String( vLstEqn, ~-vIdxBgn ) )){
                    vLstEqn = llListInsertList( vLstEqn, (list)"*", vIdxBgn );
                }
            }
        }else{
            jump Err7;
        }
    }
    if (~llListFindList( vLstEqn, (list)"(" )){
         jump Err8;
     }
     }
     return vStrSrc;
     if (vLstEqn != ["="]){
}
         jump Err9;
/*//--                      Anti-License Text                        --//*/
/*//    Contributed Freely to the Public Domain without limitation.    //*/
/*//  2009 (CC0) [ http://creativecommons.org/publicdomain/zero/1.0 ]  //*/
/*//  Void Singer [ https://wiki.secondlife.com/wiki/User:Void_Singer ]  //*/
/*//--                                                                --//*/</lsl>
:[[User:Void_Singer/Functions#Return_to_Void_Singers_user_page|Return to top]]
}}
 
{{void-box
|title=String: Find Last Index
|content=
* This function is a companion to [[llSubStringIndex]].
=== Get Last Index of String Test in String Source ===
<lsl>integer uGetStrIdxRev1( string vStrSrc, string vStrTst ){
    integer vIdxFnd =
      llStringLength( vStrSrc ) -
      llStringLength( vStrTst ) -
      llStringLength(
        llList2String(
          llParseStringKeepNulls( vStrSrc, (list)vStrTst, [] ),
          -1)
        );
    return (vIdxFnd | (vIdxFnd >> 31));
}
/*//--                      Anti-License Text                        --//*/
/*//    Contributed Freely to the Public Domain without limitation.    //*/
/*//  2009 (CC0) [ http://creativecommons.org/publicdomain/zero/1.0 ]  //*/
/*//  Void Singer [ https://wiki.secondlife.com/wiki/User:Void_Singer ]  //*/
/*//--                                                                --//*/</lsl>
:[[User:Void_Singer/Functions#Return_to_Void_Singers_user_page|Return to top]]
}}
 
{{void-box
|title=List: Get Reverse Order
|content=
* These functions are companions to [[llListSort]].
=== Reverse List Order (faster version) ===
<lsl>list uListRevF( list vLstSrc ){
    integer vIntCnt = (vLstSrc != []);
    @Loop; if (vIntCnt--){
        vLstSrc += llList2List( vLstSrc, vIntCnt, vIntCnt );
         jump Loop;
     }
     }
     return llList2List( vLstSrc, (vLstSrc != []) >> 1, -1 );
     if ((integer)vStrTmp == (float)(vStrTmp = llList2String( vLstEqn, 0 ))){
}
        vStrTmp = (string)((integer)vStrTmp);
/*//--                      Anti-License Text                        --//*/
    }else{
/*//    Contributed Freely to the Public Domain without limitation.    //*/
        vIntCnt = llStringLength( vStrTmp );
/*//  2009 (CC0) [ http://creativecommons.org/publicdomain/zero/1.0 ]  //*/
        while ("0" == llGetSubString( vStrTmp, --vIntCnt, vIntCnt ));
/*//  Void Singer [ https://wiki.secondlife.com/wiki/User:Void_Singer ]  //*/
         vStrTmp = llGetSubString( vStrTmp, 0, vIntCnt );
/*//--                                                                --//*/</lsl>
 
=== Reverse List Order (smaller memory version) ===
<lsl>list uListRevS( list vLstSrc ){
    integer vIntCnt = (vLstSrc != []);
    @Loop; if (vIntCnt--){
        vLstSrc += llList2List( vLstSrc, vIntCnt, vIntCnt );
         vLstSrc = llDeleteSubList( vLstSrc, vIntCnt, vIntCnt );
        jump Loop;
     }
     }
     return vLstSrc;
    jump Errors;
    @Err9; ++vIntErr;
    @Err7; @Err8; ++vIntErr;
    @Err6; ++vIntErr;
    @Err5; ++vIntErr;
    @Err4; ++vIntErr;
    @Err3; ++vIntErr;
    @Err1; @Err2; ++vIntErr;
    @Err0;
    vStrTmp =
      "Error: " +
      llList2String( ["Unsupported Character(s)",
                      "Outside Operator(s)",
                      "Stacked Operator(s)",
                      "Missing Operator(s)",
                      "Divide By Zero",
                      "Empty Parenthesis",
                      "Missing Parenthesis",
                      "Catastrophic Failure"],
                    vIntErr ) +
      "\n" + llDumpList2String( vLstEqn, " " ) + "\n" + vStrTmp;
    @Errors;
     return vStrTmp;
}
}
/*//--                       Anti-License Text                         --//*/
/*//--                           License Text                           --//*/
/*//     Contributed Freely to the Public Domain without limitation.     //*/
/*// Free to copy, use, modify, distribute, or sell, with attribution.   //*/
/*//   2009 (CC0) [ http://creativecommons.org/publicdomain/zero/1.0 ]   //*/
/*//   (C)2010 (CC-BY) [ http://creativecommons.org/licenses/by/3.0 ]   //*/
/*// Void Singer [ https://wiki.secondlife.com/wiki/User:Void_Singer ]  //*/
/*//   Void Singer [ https://wiki.secondlife.com/wiki/User:Void_Singer ] //*/
/*//--                                                                 --//*/</lsl>
/*//  All usages must contain a plain text copy of the previous 2 lines. //*/
/*//--                                                                 --//*/</source>
:[[User:Void_Singer/Functions#Return_to_Void_Singers_user_page|Return to top]]
:[[User:Void_Singer/Functions#Return_to_Void_Singers_user_page|Return to top]]
}}
}}


{{void-box
{{void-box
|title=List: Find Last Index
|title=uListFindListLast
|content=
|content=
* This function is a companion to [[llListFindList]].
* This function is a companion to [[llListFindList]].
** '''SPECIAL NOTE''': this is only designed to work on string data that will NOT contain the "•" character(alt+7)... please use a different character to suit your needs.
** designed for string data only.
=== Get Last Index of List Test in List Source ===
** Can not handle empty string elements
<lsl>integer uGetLstIdxRev( list vLstSrc, list vLstTst ){
** Returns 0 if list test is empty, but list source is not; just like llListFindList
    integer vIdxFnd =
** '''SPECIAL NOTE''': data should NOT contain the "•" character(alt+7)... please use a different character if this one is expected.
      (vLstSrc != []) +
'''Get Last Index of List Test in List Source'''
      ([] != vLstTst) +
<source lang="lsl2">integer uListFindListLast( list vLstSrc, list vLstTst ){
      ([] != llParseString2List(
integer vIdxFnd =
              llList2String(
  (vLstSrc !=  
                llParseStringKeepNulls(
  (vLstTst +
                  llDumpList2String( vLstSrc, "•" ),
  llParseString2List(
                  (list)llDumpList2String( vLstTst, "•" ),
    llList2String(
                  [] ),
      llParseStringKeepNulls(
                -1 ),
        llDumpList2String( vLstSrc, "•" ),
              (list)"•",
        (list)llDumpList2String( vLstTst, "•" ),
              [] ));
        [] ),
    return (vIdxFnd | (vIdxFnd >> 31));
      0xFFFFFFFF ),
    ["•"],
    [] )));
return (vIdxFnd | (vIdxFnd >> 31));
}
}
/*//--                      Anti-License Text                        --//*/
/*//--                      Anti-License Text                        --//*/
/*//    Contributed Freely to the Public Domain without limitation.    //*/
/*//    Contributed Freely to the Public Domain without limitation.    //*/
/*//  2009 (CC0) [ http://creativecommons.org/publicdomain/zero/1.0 ]  //*/
/*//  2012 (CC0) [ http://creativecommons.org/publicdomain/zero/1.0 ]  //*/
/*//  Void Singer [ https://wiki.secondlife.com/wiki/User:Void_Singer ]  //*/
/*//  Void Singer [ https://wiki.secondlife.com/wiki/User:Void_Singer ]  //*/
/*//--                                                                --//*/</lsl>
/*//--                                                                --//*/</source>
:[[User:Void_Singer/Functions#Return_to_Void_Singers_user_page|Return to top]]
:[[User:Void_Singer/Functions#Return_to_Void_Singers_user_page|Return to top]]
}}
}}


{{void-box
{{void-box
|title=List: Multi-Find Index (First or Last)
|title=uListFindAny*
|content=
|content=
* These functions are companions to [[llListFindList]].
* These functions are companions to [[llListFindList]].
=== Get First Index in List Source of any element in List Test ===
** designed for string data only.
<lsl>integer uMatchLstIdxFwd( list vLstSrc, list vLstTst ){
** Can not handle empty string elements
  return ((llParseString2List(
** '''SPECIAL NOTE''': data should NOT contain the "•" character(alt+7)... please use a different character if this one is expected.
            llList2String(
              llParseStringKeepNulls(
                llDumpList2String( vLstSrc, ";" ),
                vLstTst, [] ),
              0 ),
            (list)";", [] ) != []) + 1) %
        ((vLstSrc != []) + 1) - 1;
}
/*//--                      Anti-License Text                        --//*/
/*//    Contributed Freely to the Public Domain without limitation.    //*/
/*//  2009 (CC0) [ http://creativecommons.org/publicdomain/zero/1.0 ]  //*/
/*//  Void Singer [ https://wiki.secondlife.com/wiki/User:Void_Singer ]  //*/
/*//--                                                                --//*/</lsl>


=== Get Last Index in List Source of any element in List Test ===
<br/><div style="display:none"><h3>uListFindAnyFirst</h3></div>'''Get the First index in List Source of Any element in List Test'''
<lsl>integer uMatchLstIdxRev( list vLstSrc, list vLstTst ){
<source lang="lsl2">integer uListFindAnyFirst( list vLstSrc, list vLstTst ){
  return (vLstSrc != []) -
return ~(~(
    (llParseString2List(
  llParseString2List(
      llList2String(
    llList2String(
        llParseString2List(  
      llParseStringKeepNulls(
          llDumpList2String( vLstSrc, ";" ),
        llDumpList2String( vLstSrc, "" ),
          vLstTst, [] ),
        vLstTst, [] ),
        -1 ),
      0 ),
      (list)";",
    [""], [] ) != []) %
      [] ) != []) - 1;
  ~(vLstSrc != []));
}
}
/*//--                      Anti-License Text                        --//*/
/*//--                      Anti-License Text                        --//*/
/*//    Contributed Freely to the Public Domain without limitation.    //*/
/*//    Contributed Freely to the Public Domain without limitation.    //*/
/*//  2009 (CC0) [ http://creativecommons.org/publicdomain/zero/1.0 ]  //*/
/*//  2012 (CC0) [ http://creativecommons.org/publicdomain/zero/1.0 ]  //*/
/*//  Void Singer [ https://wiki.secondlife.com/wiki/User:Void_Singer ]  //*/
/*//  Void Singer [ https://wiki.secondlife.com/wiki/User:Void_Singer ]  //*/
/*//--                                                                --//*/</lsl>
/*//--                                                                --//*/</source>
:[[User:Void_Singer/Functions#Return_to_Void_Singers_user_page|Return to top]]
}}


{{void-box
<div style="display:none"><h3>uListFindAnyLast</h3></div>'''Get the Last index in List Source of Any element in List Test'''
|title=Timestamp: Converters
<source lang="lsl2">integer uListFindAnyLast( list vLstSrc, list vLstTst ){
|content=
return ~(
* These Functions are companions to [[llGetUnixTime]] and [[llGetTimestamp]].
  llParseString2List(
=== Unix time code to list format. ===
    llList2String(
<lsl>
      llParseStringKeepNulls(
/*//-- Notes:
        llDumpList2String( vLstSrc, "•" ),
Time codes before the year 1902 or past the end of 2037
        vLstTst, [] ),
  are capped to the first second of 1902 and 2038 respectively
      0xFFFFFFFF ),
    ["•"], [] )
Output is [Y, M, D, h, m, s] list format.
  != vLstSrc);
This version could be improved.
//*/
 
list uUnix2StampLst( integer vIntDate ){
if (vIntDate / 2145916801){
vIntDate = 2145916800 * (1 | (vIntDate >> 31));
}
integer vIntYear = 126230400;
integer vIntDays = 86400;
integer vIntHour = 3600;
integer vIntMnit = 60;
integer vIntScnd = vIntDate % vIntMnit;
vIntMnit = vIntDate % vIntHour / vIntMnit;
vIntHour = vIntDate % vIntDays / vIntHour;
vIntDays = vIntDate % vIntYear / vIntDays;
vIntYear = 1970 + (( vIntDate / vIntYear ) << 2);
if (789 == llAbs( vIntDays )){
vIntDays = 29;
vIntDate = 2;
vIntYear +=2;
}else{
vIntYear += ((vIntDays -= (llAbs( vIntDays ) > 789)) / 365);
vIntDays %= 365;
vIntDays += vIntDate = 1;
integer vIntTmp;
@Loop; if (llAbs( vIntDays ) > (vIntTmp = (30 | (vIntDate & 1) ^ (vIntDate > 7)) - ((vIntDate == 2) << 1))){
vIntDays -= vIntTmp;
++vIntDate;
jump Loop;
}
}
return [vIntYear, vIntDate, vIntDays, vIntHour, vIntMnit, vIntScnd];
}
}
/*//--                      Anti-License Text                        --//*/
/*//--                      Anti-License Text                        --//*/
/*//    Contributed Freely to the Public Domain without limitation.    //*/
/*//    Contributed Freely to the Public Domain without limitation.    //*/
/*//  2009 (CC0) [ http://creativecommons.org/publicdomain/zero/1.0 ]  //*/
/*//  2012 (CC0) [ http://creativecommons.org/publicdomain/zero/1.0 ]  //*/
/*//  Void Singer [ https://wiki.secondlife.com/wiki/User:Void_Singer ]  //*/
/*//  Void Singer [ https://wiki.secondlife.com/wiki/User:Void_Singer ]  //*/
/*//--                                                                --//*/</lsl>
/*//--                                                                --//*/</source>
 
=== List format to Unix time code. ===
<lsl>/*//-- Notes:
Time codes before 13 Dec 1901 20:45:52 return the value for 13 Dec 1901 20:45:52 (-2147483648).
Time codes after 19 Jan 2038 03:14:07 return the value for 19 Jan 2038 03:14:07 (2147483647).
Input format is [Y, M, D, h, m, s] in numerals. Strings are converted.
Elements past the end are safely ignored, for compatibility with
  llParseString2List( llGetTimestamp(), ["-", "T", ":", "."], [] )
//*/
 
integer uStamp2UnixInt( list vLstStp ){
integer vIntYear = llList2Integer( vLstStp, 0 );
integer vIntRtn;
if ((vIntYear - 1845) >> 8){//try to avoid double flows
vIntRtn = 0x7FFFFFFF + (vIntYear < 1970);
} else {
integer vIntMnth = llList2Integer( vLstStp, 1 );
vIntRtn = llList2Integer( vLstStp, 3 ) * 3600 +
          llList2Integer( vLstStp, 4 ) * 60 +
          llList2Integer( vLstStp, 5 ) +
        (llList2Integer( vLstStp, 2 ) +
          (vIntYear * 365) + ((vIntYear - 2878293) >> 2) +
          (vIntMnth *  30) +
          ((vIntMnth + (vIntMnth > 8)) >> 1) -
          ((vIntMnth > 2) << ((vIntYear & 3) && ((vIntYear - 100) % 200)))
        ) * 86400;
if((vIntRtn ^ (vIntYear - 1970)) & 0x80000000) { //sign mismatch
vIntRtn = 0x80000000 + (vIntRtn >> 31);
                }//This could be an (over|under)flow or it could be the user being clever.
}
return vIntRtn;
}
/*//--                      Anti-License Text                        --//*/
/*//    Contributed Freely to the Public Domain without limitation.    //*/
/*//  2009 (CC0) [ http://creativecommons.org/publicdomain/zero/1.0 ]  //*/
/*//  Void Singer [ https://wiki.secondlife.com/wiki/User:Void_Singer ]  //*/
/*//--                                                                --//*/</lsl>
:[[User:Void_Singer/Functions#Return_to_Void_Singers_user_page|Return to top]]
:[[User:Void_Singer/Functions#Return_to_Void_Singers_user_page|Return to top]]
}}
}}


{{void-box
{{void-box
|title=Timestamp: Get Weekday from timestamp
|title=uDlgBtnPagList
|content=
|content=
* These Functions are related to [[llGetUnixTime]] and [[llGetTimestamp]].
* Effectively allows more than 12 button on a dialog by breaking them up into pages and adding page change buttons as needed
=== Weekday from Unix timestamp ===
* Corrects the button order to [left to right, top to bottom] (AKA English Order]
<lsl>/*//-- Note:
* Automatically wraps around from the last and first pages
  Accurate from 1901 to 2099 (no limiting code)
* Supports up to 22 pages safely (220 items in the list)
//*/
* Supports multiple simultaneous users
 
* Support Re-menuing
string uUnix2WeekdayStr( integer vIntDat ){
* Requires the button text(s) to be in a global list named gLstMnu (which you can fill however you like)
     return llList2String( ["Thursday", "Friday", "Saturday", "Sunday", "Monday", "Tuesday", "Wednesday"],
** this function does NOT check that button text is valid (0 < button_text_length < 25), that's your job
                          vIntDate % 604800 / 86400  - (vIntDate < 0) );
* Individual button texts ''cannot''' start with a non-breaking space (alt+255).
<source lang="lsl2">list uDlgBtnLst( integer vIdxPag ){
    list vLstRtn;
    if ((gLstMnu != []) > 12){ //-- we have more than one possible page
        integer vIntTtl = -~((~([] != gLstMnu)) / 10);                                //-- Total possible pages
        integer vIdxBgn = (vIdxPag = (vIntTtl + vIdxPag) % vIntTtl) * 10;              //-- first menu index
        string vStrPag = llGetSubString( "                    ", 21 - vIdxPag, 21 ); //-- encode page number as spaces
        //-- get ten (or less for the last page) entries from the list and insert back/fwd buttons
        vLstRtn = llListInsertList( llList2List( gLstMnu, vIdxBgn, vIdxBgn + 9 ), (list)(" «" + vStrPag), 0xFFFFFFFF ) +
                  (list)(" »" + vStrPag);
    }else{ //-- we only have 1 page
        vLstRtn = gLstMnu; //-- just use the list as is
    }
     return //-- fix the order for [L2R,T2B] and send it out
      llList2List( vLstRtn, -3, -1 ) + llList2List( vLstRtn, -6, -4 ) +
      llList2List( vLstRtn, -9, -7 ) + llList2List( vLstRtn, -12, -10 );
}
}
/*//--                      Anti-License Text                        --//*/
/*//--                      Anti-License Text                        --//*/
/*//    Contributed Freely to the Public Domain without limitation.    //*/
/*//    Contributed Freely to the Public Domain without limitation.    //*/
/*//  2009 (CC0) [ http://creativecommons.org/publicdomain/zero/1.0 ]  //*/
/*//  2012 (CC0) [ http://creativecommons.org/publicdomain/zero/1.0 ]  //*/
/*//  Void Singer [ https://wiki.secondlife.com/wiki/User:Void_Singer ]  //*/
/*//  Void Singer [ https://wiki.secondlife.com/wiki/User:Void_Singer ]  //*/
/*//--                                                                --//*/</lsl>
/*//--                                                                --//*/</source>


=== Weekday from ( Y, M, D ) format ===
<div style="display:none"><h3>Example Usage</h3></div>'''How to incorporate into [[llDialog]] calls:'''
<lsl>/*//-- Note:
<source lang="lsl2">llDialog( Target_avatar_key, text_for_dialog_header, uDlgBtnLst( 0 ), chat_channel_to_use );</source>
Accurate from 1901 to 2099 (no limiting code)


This version could be improved.
<div style="display:none"><h3>Response Detection</h3></div>'''How to detect and handle responses:'''
//*/
<source lang="lsl2">    listen( integer vIntChn, string vStrNom, key vKeySpk, string vStrMsg ){
 
        if (!llSubStringIndex( vStrMsg, " " )){ //-- detects (hidden) leading non-breaking space of page change buttons
string uStamp2WeekdayStr( integer vIntYear, integer vIntMonth, integer vIntDay ){
            llDialog( vKeySpk,
return llList2String ( ["Friday", "Saturday", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday"],
                      "your dialog text goes here",
                      (vIntYear + (vIntYear >> 2) - ((vIntMonth < 3) & !(vIntYear & 3)) + vIntDay
                      uDlgBtnLst( llStringLength( vStrMsg ) + llSubStringIndex( vStrMsg, "»" ) - 2 ),
                      + (integer)llGetSubString( "_033614625035", vIntMonth, vIntMonth )) % 7 );
                      vIntChn );
}
        }else{
/*//--                       Anti-License Text                        --//*/
            //-- button was not a page button, your code goes here,
/*//    Contributed Freely to the Public Domain without limitation.    //*/
            //-- use (llListFindList( gLstMnu, (list)vStrMsg ) / 10) for remenu command if present
/*//  2009 (CC0) [ http://creativecommons.org/publicdomain/zero/1.0 ]  //*/
        }
/*//  Void Singer [ https://wiki.secondlife.com/wiki/User:Void_Singer ]  //*/
    }</source>
/*//--                                                                --//*/</lsl>
:[[User:Void_Singer/Functions#Return_to_Void_Singers_user_page|Return to top]]
:[[User:Void_Singer/Functions#Return_to_Void_Singers_user_page|Return to top]]
}}
}}

Latest revision as of 19:49, 27 November 2016

uParseEquation

  • Parses a string equation and returns a formatted result
  • Supports the following operations and proper order of operations:
    • Parenthesis("(",")")
    • Negation ("-")
    • Exponentiation ("^")
    • Division and Multiplication ("/", "*")
    • Subtraction & Addition ("-", "+")
  • Supports (Case insensitive) constant replacement:
  • Supports implied multiplication of parenthesis and constants
    • (2)3 == 2*3
    • 2pi == 2*pi
  • Supports Roots in the format of x^(1/y) (the "y" root of "x", where both are decimal numbers)
  • Supports error detection:
    • Unsuported characters
    • Invalid/Missing Operators
    • Divide by Zero
    • Empty/Missing Parenthesis
    • Ignores spaces
string uParseEquation( string vStrTmp ){
    list    lst_OPS = ["+", "-", "*", "/", "^"];
    list    vLstEqn;
    list    vLstTmp;
    list    vLstSwp;
    integer vIdxFnd;
    integer vIdxBgn;
    integer vIdxEnd;
    integer vIntCnt;
    integer vIntErr;
    
    vStrTmp = llToLower( "(" + vStrTmp + ")" );
    vLstTmp = llParseString2List( vStrTmp, lst_OPS + ["pi", "phi"], [] );
    vLstTmp = llParseString2List( (string)vLstTmp, ["0", "1", "2", "3", "4", "5", "6", "7"], [] );
    vLstTmp = llParseString2List( (string)vLstTmp, ["8", "9", ".", "e", "(", ")", " ", "="], [] );
    if (vLstTmp != []){
        jump Err0;
    }
    vStrTmp = llDumpList2String( llParseStringKeepNulls( vStrTmp, ["e"], [] ), "(2.7182817)" );
    vStrTmp = llDumpList2String( llParseStringKeepNulls( vStrTmp, ["pi"], [] ), "(3.1415927)" );
    vStrTmp = llDumpList2String( llParseStringKeepNulls( vStrTmp, ["phi"], [] ), "(1.6180340)" );
    vLstEqn = llParseString2List( vStrTmp, [" ", "="], lst_OPS + ["(", ")"] );
    while (~(vIdxEnd = vIdxBgn = llListFindList( vLstEqn, (list)")" ))){
        while (llList2String( vLstEqn, vIdxBgn ) != "(" && ~(--vIdxBgn));
        if (~vIdxBgn){
             if (vIdxEnd - vIdxBgn > 1){
                if (~llListFindList( lst_OPS,
                                     (list)llList2String( vLstTmp = llList2List( vLstEqn, -~vIdxBgn, ~-vIdxEnd ),
                                     0xFFFFFFFF ) )){
                    jump Err1;
                }
                if (~(vIdxFnd = llListFindList( lst_OPS, (list)llList2String( vLstTmp, 0 ) ))){
                    if (1 == vIdxFnd  && !~llListFindList( lst_OPS, (list)llList2String( vLstTmp, 1 ) )){
                        vLstTmp = llListReplaceList( vLstTmp, (list)(-llList2Float( vLstTmp, 1 )), 0, 1 );
                    }else{
                        jump Err2;
                    }
                }
                vIntCnt = ([] != vLstTmp);
                while(++vIntCnt < 0){
                    if (~llListFindList( lst_OPS, (list)llList2String( vLstTmp, vIntCnt) )){
                        if (~(vIdxFnd = llListFindList( lst_OPS, (list)llList2String( vLstTmp, ++vIntCnt ) ))){
                            if (1 == vIdxFnd && !~llListFindList( lst_OPS, (list)llList2String( vLstTmp, -~vIntCnt) )){
                                vLstTmp = llListReplaceList( vLstTmp, (list)(-llList2Float( vLstTmp, vIntCnt )), vIntCnt, -~vIntCnt );
                                --vIntCnt;
                            }else{
                                jump Err3;
                            } 
                        }
                    }else{
                        jump Err4;
                    } 
                }
                vIntCnt = 4;
                do{
                    while (~(vIdxFnd = llListFindList( vLstTmp, (list)llList2String( lst_OPS, vIntCnt ) ))){
                        if (1 & vIntCnt){
                            if (2 & vIntCnt){
                                if (llList2String( vLstTmp, -~vIdxFnd )){
                                    vLstSwp = ["*", 1 / llList2Float( vLstTmp, -~vIdxFnd )];
                                }else{
                                    jump Err5;
                                } 
                            }else{
                                vLstSwp = ["+", -llList2Float( vLstTmp, -~vIdxFnd )];
                            }
                        }else{
                            if (vIntCnt){
                                if (4 & vIntCnt){
                                    vLstSwp = (list)llPow( llList2Float( vLstTmp, ~-vIdxFnd ), llList2Float( vLstTmp, -~vIdxFnd ) );
                                }else{
                                    vLstSwp = (list)( llList2Float( vLstTmp, ~-vIdxFnd ) * llList2Float( vLstTmp, -~vIdxFnd ) );
                                }
                            }else{
                                vLstSwp = (list)( llList2Float( vLstTmp, ~-vIdxFnd ) + llList2Float( vLstTmp, -~vIdxFnd ) );
                            }
                        }
                        vLstTmp = llListReplaceList( vLstTmp, vLstSwp, vIdxFnd - !(1 & vIntCnt), -~vIdxFnd );
                    }
                }while (~(--vIntCnt));
                vLstEqn = llListReplaceList( vLstEqn, vLstTmp, vIdxBgn, vIdxEnd );
            }else{
                jump Err6;
            }
            if (!~llListFindList( lst_OPS + [")", ""], (list)llList2String( vLstEqn, -~vIdxBgn ) )){
                vLstEqn = llListInsertList( vLstEqn, (list)"*", -~vIdxBgn );
            }
            if (vIdxBgn){
                if (!~llListFindList( lst_OPS + (list)"(", (list)llList2String( vLstEqn, ~-vIdxBgn ) )){
                    vLstEqn = llListInsertList( vLstEqn, (list)"*", vIdxBgn );
                }
            }
        }else{
            jump Err7;
        } 
    }
    if (~llListFindList( vLstEqn, (list)"(" )){
        jump Err8;
    }
    if (vLstEqn != ["="]){
        jump Err9;
    }
    if ((integer)vStrTmp == (float)(vStrTmp = llList2String( vLstEqn, 0 ))){
        vStrTmp = (string)((integer)vStrTmp);
    }else{
        vIntCnt = llStringLength( vStrTmp );
        while ("0" == llGetSubString( vStrTmp, --vIntCnt, vIntCnt  ));
        vStrTmp = llGetSubString( vStrTmp, 0, vIntCnt );
    }
    jump Errors;
    @Err9; ++vIntErr;
    @Err7; @Err8; ++vIntErr;
    @Err6; ++vIntErr;
    @Err5; ++vIntErr;
    @Err4; ++vIntErr;
    @Err3; ++vIntErr;
    @Err1; @Err2; ++vIntErr;
    @Err0;
    vStrTmp =
      "Error: " +
      llList2String( ["Unsupported Character(s)",
                      "Outside Operator(s)",
                      "Stacked Operator(s)",
                      "Missing Operator(s)",
                      "Divide By Zero",
                      "Empty Parenthesis",
                      "Missing Parenthesis",
                      "Catastrophic Failure"],
                     vIntErr ) +
      "\n" + llDumpList2String( vLstEqn, " " ) + "\n" + vStrTmp;
    @Errors;
    return vStrTmp;
}
/*//--                           License Text                           --//*/
/*//  Free to copy, use, modify, distribute, or sell, with attribution.   //*/
/*//    (C)2010 (CC-BY) [ http://creativecommons.org/licenses/by/3.0 ]    //*/
/*//   Void Singer [ https://wiki.secondlife.com/wiki/User:Void_Singer ]  //*/
/*//  All usages must contain a plain text copy of the previous 2 lines.  //*/
/*//--                                                                  --//*/
Return to top

uListFindListLast

  • This function is a companion to llListFindList.
    • designed for string data only.
    • Can not handle empty string elements
    • Returns 0 if list test is empty, but list source is not; just like llListFindList
    • SPECIAL NOTE: data should NOT contain the "•" character(alt+7)... please use a different character if this one is expected.

Get Last Index of List Test in List Source

integer uListFindListLast( list vLstSrc, list vLstTst ){
	integer vIdxFnd =
	  (vLstSrc != 
	  (vLstTst +
	  llParseString2List(
	    llList2String(
	      llParseStringKeepNulls(
	        llDumpList2String( vLstSrc, "•" ),
	        (list)llDumpList2String( vLstTst, "•" ),
	        [] ),
	      0xFFFFFFFF ),
	    ["•"],
	    [] )));
	return (vIdxFnd | (vIdxFnd >> 31));
}
/*//--                       Anti-License Text                         --//*/
/*//     Contributed Freely to the Public Domain without limitation.     //*/
/*//   2012 (CC0) [ http://creativecommons.org/publicdomain/zero/1.0 ]   //*/
/*//  Void Singer [ https://wiki.secondlife.com/wiki/User:Void_Singer ]  //*/
/*//--                                                                 --//*/
Return to top

uListFindAny*

  • These functions are companions to llListFindList.
    • designed for string data only.
    • Can not handle empty string elements
    • SPECIAL NOTE: data should NOT contain the "•" character(alt+7)... please use a different character if this one is expected.

uListFindAnyFirst

Get the First index in List Source of Any element in List Test
integer uListFindAnyFirst( list vLstSrc, list vLstTst ){
	return ~(~(
	  llParseString2List(
	    llList2String(
	      llParseStringKeepNulls(
	        llDumpList2String( vLstSrc, "•" ),
	        vLstTst, [] ),
	      0 ),
	    ["•"], [] ) != []) %
	  ~(vLstSrc != []));
}
/*//--                       Anti-License Text                         --//*/
/*//     Contributed Freely to the Public Domain without limitation.     //*/
/*//   2012 (CC0) [ http://creativecommons.org/publicdomain/zero/1.0 ]   //*/
/*//  Void Singer [ https://wiki.secondlife.com/wiki/User:Void_Singer ]  //*/
/*//--                                                                 --//*/

uListFindAnyLast

Get the Last index in List Source of Any element in List Test
integer uListFindAnyLast( list vLstSrc, list vLstTst ){
	return ~(
	  llParseString2List(
	    llList2String(
	      llParseStringKeepNulls(
	        llDumpList2String( vLstSrc, "•" ),
	        vLstTst, [] ),
	      0xFFFFFFFF ),
	    ["•"], [] )
	  != vLstSrc);
}
/*//--                       Anti-License Text                         --//*/
/*//     Contributed Freely to the Public Domain without limitation.     //*/
/*//   2012 (CC0) [ http://creativecommons.org/publicdomain/zero/1.0 ]   //*/
/*//  Void Singer [ https://wiki.secondlife.com/wiki/User:Void_Singer ]  //*/
/*//--                                                                 --//*/
Return to top

uDlgBtnPagList

  • Effectively allows more than 12 button on a dialog by breaking them up into pages and adding page change buttons as needed
  • Corrects the button order to [left to right, top to bottom] (AKA English Order]
  • Automatically wraps around from the last and first pages
  • Supports up to 22 pages safely (220 items in the list)
  • Supports multiple simultaneous users
  • Support Re-menuing
  • Requires the button text(s) to be in a global list named gLstMnu (which you can fill however you like)
    • this function does NOT check that button text is valid (0 < button_text_length < 25), that's your job
  • Individual button texts cannot' start with a non-breaking space (alt+255).
list uDlgBtnLst( integer vIdxPag ){
    list vLstRtn;
    if ((gLstMnu != []) > 12){ //-- we have more than one possible page
        integer vIntTtl = -~((~([] != gLstMnu)) / 10);                                 //-- Total possible pages
        integer vIdxBgn = (vIdxPag = (vIntTtl + vIdxPag) % vIntTtl) * 10;              //-- first menu index
        string  vStrPag = llGetSubString( "                     ", 21 - vIdxPag, 21 ); //-- encode page number as spaces
         //-- get ten (or less for the last page) entries from the list and insert back/fwd buttons
        vLstRtn = llListInsertList( llList2List( gLstMnu, vIdxBgn, vIdxBgn + 9 ), (list)(" «" + vStrPag), 0xFFFFFFFF ) +
                  (list)(" »" + vStrPag);
    }else{ //-- we only have 1 page
        vLstRtn = gLstMnu; //-- just use the list as is
    }
    return //-- fix the order for [L2R,T2B] and send it out
      llList2List( vLstRtn, -3, -1 ) + llList2List( vLstRtn, -6, -4 ) +
      llList2List( vLstRtn, -9, -7 ) + llList2List( vLstRtn, -12, -10 );
}
/*//--                       Anti-License Text                         --//*/
/*//     Contributed Freely to the Public Domain without limitation.     //*/
/*//   2012 (CC0) [ http://creativecommons.org/publicdomain/zero/1.0 ]   //*/
/*//  Void Singer [ https://wiki.secondlife.com/wiki/User:Void_Singer ]  //*/
/*//--                                                                 --//*/

Example Usage

How to incorporate into llDialog calls:
llDialog( Target_avatar_key, text_for_dialog_header, uDlgBtnLst( 0 ), chat_channel_to_use );

Response Detection

How to detect and handle responses:
    listen( integer vIntChn, string vStrNom, key vKeySpk, string vStrMsg ){
        if (!llSubStringIndex( vStrMsg, " " )){ //-- detects (hidden) leading non-breaking space of page change buttons
            llDialog( vKeySpk,
                      "your dialog text goes here",
                      uDlgBtnLst( llStringLength( vStrMsg ) + llSubStringIndex( vStrMsg, "»" ) - 2 ),
                      vIntChn );
        }else{
            //-- button was not a page button, your code goes here,
            //-- use (llListFindList( gLstMnu, (list)vStrMsg ) / 10) for remenu command if present
        }
    }
Return to top

Questions or Comments?

Feel free to leave me a note on my User Talk page.