Difference between revisions of "BaseN"
Jump to navigation
Jump to search
(Created page with '{{LSL Header}} __Toc__ This script allows you to make maximum use of available bits in strings for transport or storage in memory. By being able to code integers into the usable...') |
(Added upgraded list-based version) |
||
Line 6: | Line 6: | ||
Note that this script does not code to the same standards such as Base64, but instead maps dynamically to the ''usable code points'' as allowed by Linden Lab. | Note that this script does not code to the same standards such as Base64, but instead maps dynamically to the ''usable code points'' as allowed by Linden Lab. | ||
{{box| | {{box|Portable List-based Coding| | ||
<lsl> | <lsl> | ||
/*/ | /*/ | ||
Line 13: | Line 13: | ||
unless otherwise noted | unless otherwise noted | ||
/*/ | /*/ | ||
integer UTF8ToInt(string input) {// by Strife | |||
integer result = llBase64ToInteger(llStringToBase64(input));//input = llGetSubString(input,0,0))); | |||
if(result & 0x80000000){ | |||
integer end = (integer)("0x"+llGetSubString(input = (string)llParseString2List(llEscapeURL(input),(list)"%",[]),-8,-1)); | |||
integer begin = (integer)("0x"+llDeleteSubString(input,-8,-1)); | |||
return ( ( 0x0000003f & end ) | (( 0x00003f00 & end) >> 2 ) | | |||
(( 0x003f0000 & end) >> 4 ) | (( 0x3f000000 & end) >> 6 ) | | |||
(( 0x0000003f & begin) << 24) | (( 0x00000100 & begin) << 22) ) & | |||
(0x7FFFFFFF >> (5 * ((integer)(llLog(~result) / 0.69314718055994530941723212145818) - 25))); | |||
} return result >> 24; } | |||
string IntToUTF8(integer input) {// by Strife | |||
integer bytes = llCeil(llLog(input) / 0.69314718055994530941723212145818); | |||
bytes = (input >= 0x80) * (bytes + ~(((1 << bytes) - input) > 0)) / 5; | |||
string result = "%" + byte2hex((input >> (6 * bytes)) | ((0x3F80 >> bytes) << !bytes)); | |||
while (bytes) result += "%" + byte2hex((((input >> (6 * (bytes = ~-bytes))) | 0x80) & 0xBF)); | |||
return llUnescapeURL(result); } | |||
string byte2hex(integer x) { integer y = (x >> 4) & 0xF;// By Strife | |||
return llGetSubString(Hex, y, y) + llGetSubString(Hex, x & 0xF, x & 0xF); } | |||
string Hex = "0123456789abcdef"; | |||
key Ints2Key( integer a, integer b, integer c, integer d ) { | |||
return byte2hex(a>>24)+byte2hex(a>>16)+byte2hex(a>>8)+byte2hex(a)+"-"+ | |||
byte2hex(b>>24)+byte2hex(b>>16)+"-"+byte2hex(b>>8)+byte2hex(b)+"-"+ | |||
byte2hex(c>>24)+byte2hex(c>>16)+"-"+byte2hex(c>>8)+byte2hex(c)+ | |||
byte2hex(d>>24)+byte2hex(d>>16)+byte2hex(d>>8)+byte2hex(d); } | |||
integer fui(float input){// by Strife | |||
if((input) != 0.0){ | |||
integer sign = (input < 0) << 31; | |||
if((input = llFabs(input)) < 2.3509887016445750159374730744445e-38) | |||
return sign | (integer)(input / 1.4012984643248170709237295832899e-45); | |||
integer exp = llFloor((llLog(input) / 0.69314718055994530941723212145818)); | |||
return (0x7FFFFF & (integer)(input * (0x1000000 >> sign))) | (((exp + 126 + (sign = ((integer)input - (3 <= (input /= (float)("0x1p"+(string)(exp -= ((exp >> 31) | 1)))))))) << 23 ) | sign); | |||
} return ((string)input == (string)(-0.0)) << 31; } | |||
float iuf(integer input){// by Strife | |||
return llPow(2.0, (input | !input) - 150) * (((!!(input = (0xff & (input >> 23)))) << 23) | ((input & 0x7fffff))) * (1 | (input >> 31)); } | |||
list Unusable = [0x00,1, 0x0D,1, /*|*/0x7C,1, /*~*/0x7E,1, 0xD800,2047, 0xFDD0,31, 0xFFFE,2]; | |||
// Unusable: 0000, 000D, D800-DFFF, FDD0-FDEF, FFFE and FFFF. | |||
// 0(1), 13(1), 124(1), 126(1), 55296(2047), 64976(31), 65534(2), | |||
// Reserved for delimiters: '~' and '|'. | |||
// 1-byte: Base123, 2-byte: Base2043, 3-byte: Base1112025 | |||
string IntToBaseToUTF8( integer Int, integer Base ) { | |||
// Integer to Base | |||
integer Sign = (Int < 0); if(Sign) Int = -Int; | |||
integer M = Int%(Base/2); | |||
list Coded = [M + (Base/2)*Sign]; | |||
Int = Int / (Base/2); | |||
while( Int > Base ) { Coded = [Int%Base] + Coded; Int /= Base; } | |||
if(Int) Coded = [Int] + Coded; | |||
// Base to UTF8 | |||
integer a; integer b = llGetListLength(Coded); list lEnc; | |||
for( ; a < b; ++a ) { | |||
Int = llList2Integer(Coded,a); | |||
integer c; integer d = llGetListLength(Unusable); | |||
for(; c < d; c += 2 ) { | |||
if( Int >= llList2Integer(Unusable,c) ) | |||
Int += llList2Integer(Unusable,c+1); | |||
else c = d; | |||
} lEnc += IntToUTF8(Int); | |||
} | |||
if(Base > 60000) return llDumpList2String(lEnc,"|"); | |||
else return (string)lEnc; | |||
} | |||
integer UTF8ToBaseToInt( string UTF8, integer Base ) { | |||
// UTF8 to Base | |||
list lDec; | |||
if(Base > 60000) lDec = llParseString2List(UTF8,["|"],[]); | |||
else { integer h = llStringLength(UTF8); | |||
while(h--) lDec = llGetSubString(UTF8,h,h) + lDec; } | |||
integer i; integer j = llGetListLength(lDec); list Coded; | |||
for(; i < j; ++i ) { | |||
string Char = llList2String(lDec,i); | |||
integer Int = UTF8ToInt(Char); integer l = llGetListLength(Unusable)-1; | |||
for(; l > 0; l -= 2 ) { | |||
if( Int >= llList2Integer(Unusable,l-1) ) | |||
Int -= llList2Integer(Unusable,l); | |||
} Coded += [Int]; | |||
} | |||
// Base to Integer | |||
integer Int; integer k = llGetListLength(Coded); integer Exp = Base/2; integer Sign; | |||
Int = llList2Integer(Coded,--k); | |||
if( Int > Exp ) { Sign = 1; Int -= Exp; } | |||
while( k-- ){ Int += llList2Integer(Coded,k) * Exp; Exp *= Base; } | |||
if(Sign) Int = -Int; | |||
return Int; | |||
} | |||
string Compress( integer Bytes, list Input ) { | |||
integer Base; | |||
if(Bytes == 1) Base = 123; else | |||
if(Bytes == 2) Base = 2043; else | |||
if(Bytes == 3) Base = 1112025; | |||
list Types; list Compressed; integer x; integer y = llGetListLength(Input); | |||
for( ; x < y; ++x ) { | |||
// Get as Integer(s) from List Entry, and compress | |||
integer Type = llGetListEntryType(Input,x); | |||
if(Type == TYPE_INTEGER) { | |||
integer Int0 = llList2Integer(Input,x); | |||
Compressed += [IntToBaseToUTF8(Int0,Base)]; | |||
} else if(Type == TYPE_FLOAT) { | |||
integer Int0 = fui(llList2Float(Input,x)); | |||
Compressed += [IntToBaseToUTF8(Int0,Base)]; | |||
} else if(Type == TYPE_KEY) { | |||
string s = llDumpList2String(llParseString2List(llList2String(Input,x), ["-"], []), ""); | |||
integer Int0 = (integer)("0x"+llGetSubString(s,0,7)); | |||
integer Int1 = (integer)("0x"+llGetSubString(s,8,15)); | |||
integer Int2 = (integer)("0x"+llGetSubString(s,16,23)); | |||
integer Int3 = (integer)("0x"+llGetSubString(s,24,31)); | |||
Compressed += [IntToBaseToUTF8(Int0,Base), | |||
IntToBaseToUTF8(Int1,Base), | |||
IntToBaseToUTF8(Int2,Base), | |||
IntToBaseToUTF8(Int3,Base)]; | |||
} else if(Type == TYPE_VECTOR) { | |||
vector v = llList2Vector(Input,x); | |||
integer Int0 = fui(v.x); | |||
integer Int1 = fui(v.y); | |||
integer Int2 = fui(v.z); | |||
Compressed += [IntToBaseToUTF8(Int0,Base), | |||
IntToBaseToUTF8(Int1,Base), | |||
IntToBaseToUTF8(Int2,Base)]; | |||
} else if(Type == TYPE_ROTATION) { | |||
rotation v = llList2Rot(Input,x); | |||
integer Int0 = fui(v.x); | |||
integer Int1 = fui(v.y); | |||
integer Int2 = fui(v.z); | |||
integer Int3 = fui(v.s); | |||
Compressed += [IntToBaseToUTF8(Int0,Base), | |||
IntToBaseToUTF8(Int1,Base), | |||
IntToBaseToUTF8(Int2,Base), | |||
IntToBaseToUTF8(Int3,Base)]; | |||
} else if(Type == TYPE_STRING) { | |||
Compressed += llList2String(Input,x); | |||
} | |||
// Add to header | |||
integer Row = x%10; | |||
if(!Row) Types += Type; else { | |||
integer Col = x/10; | |||
integer t = llList2Integer( Types, Col ); | |||
t = t | (Type<<(Row*3)); | |||
Types = llListReplaceList( Types, [t], Col, Col ); | |||
} } | |||
// Compress header | |||
y = llGetListLength((Types = y + Types)); | |||
for( x = 0; x < y; ++x ) | |||
Types = llListReplaceList( Types, [IntToBaseToUTF8(llList2Integer(Types,x),Base)], x, x ); | |||
return llDumpList2String(Types + Compressed,"~"); } | |||
list Decompress( integer Bytes, string Encrypted ) { | |||
integer Base; | |||
if(Bytes == 1) Base = 123; else | |||
if(Bytes == 2) Base = 2043; else | |||
if(Bytes == 3) Base = 1112025; | |||
list Input = llParseString2List(Encrypted,["~"],[]); | |||
integer Total = UTF8ToBaseToInt( llList2String(Input,0), Base ); | |||
integer x; integer y; list Types; | |||
for( y = 1+(Total/10); x < y; ++x ) | |||
Types += UTF8ToBaseToInt( llList2String(Input,x+1), Base ); | |||
list Output; integer Ptr = y; | |||
for( x = 0; x < Total; ++x ) { | |||
integer Row = x%10; | |||
integer Col = x/10; | |||
integer Type = (llList2Integer(Types,Col)>>(Row*3))&7; | |||
if(Type == TYPE_INTEGER) { | |||
Output += [UTF8ToBaseToInt(llList2String(Input,Ptr++),Base)]; | |||
} else if(Type == TYPE_FLOAT) { | |||
Output += [iuf(UTF8ToBaseToInt(llList2String(Input,Ptr++),Base))]; | |||
} else if(Type == TYPE_KEY) { | |||
integer Int0 = UTF8ToBaseToInt(llList2String(Input,Ptr++),Base); | |||
integer Int1 = UTF8ToBaseToInt(llList2String(Input,Ptr++),Base); | |||
integer Int2 = UTF8ToBaseToInt(llList2String(Input,Ptr++),Base); | |||
integer Int3 = UTF8ToBaseToInt(llList2String(Input,Ptr++),Base); | |||
Output += [Ints2Key(Int0,Int1,Int2,Int3)]; | |||
} else if(Type == TYPE_VECTOR) { | |||
integer Int0 = UTF8ToBaseToInt(llList2String(Input,Ptr++),Base); | |||
integer Int1 = UTF8ToBaseToInt(llList2String(Input,Ptr++),Base); | |||
integer Int2 = UTF8ToBaseToInt(llList2String(Input,Ptr++),Base); | |||
Output += [<iuf(Int0),iuf(Int1),iuf(Int2)>]; | |||
} else if(Type == TYPE_ROTATION) { | |||
integer Int0 = UTF8ToBaseToInt(llList2String(Input,Ptr++),Base); | |||
integer Int1 = UTF8ToBaseToInt(llList2String(Input,Ptr++),Base); | |||
integer Int2 = UTF8ToBaseToInt(llList2String(Input,Ptr++),Base); | |||
integer Int3 = UTF8ToBaseToInt(llList2String(Input,Ptr++),Base); | |||
Output += [<iuf(Int0),iuf(Int1),iuf(Int2),iuf(Int3)>]; | |||
} else if(Type == TYPE_STRING) { | |||
Output += [llList2String(Input,Ptr++)]; | |||
} | |||
} | |||
return Output; | |||
} | |||
integer UTF8Length(string msg) {// by kimmie Loveless | |||
integer rNum = llStringLength(msg); return rNum + ((llStringLength(llEscapeURL(msg)) - rNum)/4); } | |||
default { | |||
state_entry() { | |||
string HR = "------"; | |||
list In = [ 25.6, 29555, 655960, -90005, 65.0125, <6, 6, 6>, <7, 7, 7, 7>, | |||
(key)"75078730-ebc8-4a80-adb9-1cfd2d95b5ca", 9, 10., 1, <2.,0,0>, 3, 4., 5, | |||
<6.,0,0,0>, 7, <8.,0,0>, 9, 1564.756560 ]; | |||
list Counts = [10, 10, 10, 10, 10, 18, 22, | |||
54, 10, 10, 10, 18, 10, 10, 10, | |||
22, 10, 18, 10, 10 ]; | |||
llOwnerSay((string)[HR," Elements: ",llGetListLength(Counts), | |||
" (",(integer)llListStatistics(LIST_STAT_SUM,Counts)," bytes) ",HR]); | |||
llOwnerSay(HR+" Compress "+HR); | |||
string Enc = Compress( 1, In ); | |||
llOwnerSay(HR+" Decompress "+HR); | |||
list Dec = Decompress( 1, Enc ); | |||
string dIn = llDumpList2String(In,","); | |||
string dDec = llDumpList2String(Dec,","); | |||
llOwnerSay( (string)[HR," Debug ",HR, | |||
"\n",HR," Input ",HR,"\n",dIn, | |||
"\n",HR," Encrypted (",UTF8Length(Enc)," bytes) ",HR,"\n",Enc, | |||
"\n",HR," Output ",HR,"\n",dDec] ); | |||
} | |||
} | |||
</lsl> | </lsl> | ||
}} | }} | ||
{{box| | |||
{{box|Single Integer Coding| | |||
<lsl> | <lsl> | ||
/*/ | |||
Variable Base | |||
created by Nexii | |||
unless otherwise noted | |||
/*/ | |||
list Int2Base( integer Base, integer Int ) { | list Int2Base( integer Base, integer Int ) { | ||
integer Sign = (Int < 0); if(Sign) Int = -Int; | integer Sign = (Int < 0); if(Sign) Int = -Int; | ||
Line 50: | Line 297: | ||
Int -= llList2Integer(Unusable,y); | Int -= llList2Integer(Unusable,y); | ||
} return Int; } | } return Int; } | ||
integer UTF8ToInt(string input) {// by Strife | integer UTF8ToInt(string input) {// by Strife | ||
integer result = llBase64ToInteger(llStringToBase64(input = llGetSubString(input,0,0))); | integer result = llBase64ToInteger(llStringToBase64(input = llGetSubString(input,0,0))); | ||
Line 74: | Line 318: | ||
return llGetSubString(Hex, y, y) + llGetSubString(Hex, x & 0xF, x & 0xF); } | return llGetSubString(Hex, y, y) + llGetSubString(Hex, x & 0xF, x & 0xF); } | ||
string Hex = "0123456789ABCDEF"; | string Hex = "0123456789ABCDEF"; | ||
integer UTF8Length(string msg) {// by kimmie Loveless | integer UTF8Length(string msg) {// by kimmie Loveless | ||
integer rNum = llStringLength(msg); return rNum + ((llStringLength(llEscapeURL(msg)) - rNum)/4); } | integer rNum = llStringLength(msg); return rNum + ((llStringLength(llEscapeURL(msg)) - rNum)/4); } | ||
Line 130: | Line 371: | ||
</lsl> | </lsl> | ||
}} | }} | ||
{{LSLC|Library}} | {{LSLC|Library}} |
Revision as of 14:18, 5 August 2010
LSL Portal | Functions | Events | Types | Operators | Constants | Flow Control | Script Library | Categorized Library | Tutorials |
This script allows you to make maximum use of available bits in strings for transport or storage in memory. By being able to code integers into the usable space of UTF-8 and UTF-16.
Note that this script does not code to the same standards such as Base64, but instead maps dynamically to the usable code points as allowed by Linden Lab.
Portable List-based Coding
(( 0x00003f00 & end) >> 2 )
Single Integer Coding
(( 0x00003f00 & end) >> 2 )