319 lines
9.6 KiB
Plaintext
319 lines
9.6 KiB
Plaintext
|
|
#ifndef QKEYS
|
|
#define QKEYS
|
|
|
|
/*
|
|
|
|
***********************************************************
|
|
* *
|
|
* NANITE SYSTEMS ADVANCED TACTICAL OPERATING SYSTEM *
|
|
* *
|
|
* QKEYS COMPONENT *
|
|
* *
|
|
* Copyright, (C) Nanite Systems Corp., 1984, 1985, 2018 *
|
|
* *
|
|
* Copyright, (C) University of Michigan 1977-1981 *
|
|
* *
|
|
***********************************************************
|
|
|
|
NOTICE: UNAUTHORIZED DISTRIBUTION, COPYING, MODIFICATION,
|
|
OR REVERSE ENGINEERING OF PROPRIETARY NANITE SYSTEMS
|
|
MILITARY CONTROL CODE IS A FEDERAL OFFENSE. THIS CODE IS
|
|
CONFIDENTIAL.
|
|
|
|
PRODUCED UNDER CONTRACT TO THE GOVERNMENT OF THE TERRAN
|
|
REPUBLIC OR ONE OF ITS DEPENDENT POLITIES.
|
|
|
|
IDV: F0960303D0002
|
|
VENDOR DUNS: 005128988
|
|
|
|
*/
|
|
|
|
rotation k2q(key k) {
|
|
string kt = (string)llParseStringKeepNulls(k, ["-"], []);
|
|
/*integer e0 = (integer)("0x" & llGetSubString(kt, 0, 1)) - 126;
|
|
integer m0 = (integer)("0x" & llGetSubString(kt, 2, 7));
|
|
integer e1 = (integer)("0x" & llGetSubString(kt, 8, 9)) - 126;
|
|
integer m1 = (integer)("0x" & llGetSubString(kt, 10, 15));
|
|
integer e2 = (integer)("0x" & llGetSubString(kt, 16, 17)) - 126;
|
|
integer m2 = (integer)("0x" & llGetSubString(kt, 18, 23));
|
|
integer e3 = (integer)("0x" & llGetSubString(kt, 24, 25)) - 126;
|
|
integer m3 = (integer)("0x" & llGetSubString(kt, 26, 31));
|
|
|
|
return <(float)m0 * llPow(2, e0),
|
|
(float)m1 * llPow(2, e1),
|
|
(float)m2 * llPow(2, e2),
|
|
(float)m3 * llPow(2, e3)>; */
|
|
|
|
return <
|
|
iuf((integer)llGetSubString(kt, 0, 7)),
|
|
iuf((integer)llGetSubString(kt, 8, 15)),
|
|
iuf((integer)llGetSubString(kt, 16, 23)),
|
|
iuf((integer)llGetSubString(kt, 24, 31))
|
|
>;
|
|
}
|
|
|
|
key q2k(rotation q) {
|
|
return llInsertString(llInsertString(
|
|
i2h(fui(q.x)) + "-"
|
|
+ i2h(fui(q.y)) + "-"
|
|
+ i2h(fui(q.z))
|
|
+ i2h(fui(q.s)),
|
|
21, "-"), 12, "-");
|
|
}
|
|
|
|
// Strife Onizuka's Float-Union-Integer implementation
|
|
integer fui(float a)//Mono Safe, LSO Safe, Doubles Unsupported, LSLEditor Unsafe
|
|
{//union float to integer
|
|
integer b = 0x80000000 & ~llSubStringIndex(llList2CSV([a]), "-");//the sign
|
|
if((a)){//is it nonzero?
|
|
if((a = llFabs(a)) < 2.3509887016445750159374730744445e-38)//Denormalized range check & last stride of normalized range
|
|
return b | (integer)(a / 1.4012984643248170709237295832899e-45);//the math overlaps; saves cpu time.
|
|
if(a > 3.4028234663852885981170418348452e+38)//Round up to infinity
|
|
return b | 0x7F800000;//Positive or negative infinity
|
|
if(a > 1.4012984643248170709237295832899e-45){//It should at this point, except if it's NaN
|
|
integer c = ~-llFloor(llLog(a) * 1.4426950408889634073599246810019);//extremes will error towards extremes. following yuch corrects it
|
|
return b | (0x7FFFFF & (integer)(a * (0x1000000 >> c))) | ((126 + (c = ((integer)a - (3 <= (a *= llPow(2, -c))))) + c) * 0x800000);
|
|
}//the previous requires a lot of unwinding to understand it.
|
|
return b | 0x7FC00000;//NaN time! We have no way to tell NaN's apart so lets just choose one.
|
|
}//Mono does not support indeterminates so I'm not going to worry about them.
|
|
return b;//for grins, detect the sign on zero. it's not pretty but it works.
|
|
}
|
|
|
|
float iuf(integer a) { //union integer to float
|
|
if(0x7F800000 & ~a)
|
|
return llPow(2, (a | !a) + 0xffffff6a) * (((!!(a = (0xff & (a >> 23)))) * 0x800000) | (a & 0x7fffff)) * (1 | (a >> 31));
|
|
return (!(a & 0x7FFFFF)) * (float)"inf" * ((a >> 31) | 1);
|
|
}
|
|
|
|
// int2hexdword, also by Strife Onizuka
|
|
string i2h (integer I) {
|
|
integer A = (I >> 2) & 0x3C000000;//not an unsigned rshift
|
|
integer B = (I & 0x0F000000) >> 4;
|
|
integer C = (I & 0x00F00000) >> 6;
|
|
integer D = (I & 0x000F0000) >> 8;
|
|
integer E = (I & 0x0000F000) << 14;
|
|
integer F = (I & 0x00000F00) << 12;
|
|
integer G = (I & 0x000000F0) << 10;
|
|
integer H = (I & 0x0000000F) << 8;
|
|
|
|
return llGetSubString(
|
|
llInsertString(
|
|
llIntegerToBase64(
|
|
A + B + C + D + 0xD34D3400
|
|
- (0xF8000000 * (A / 0x28000000))//lowercase=0x90000000, uppercase=0xF8000000
|
|
- (0x03E00000 * (B / 0x00A00000))//lowercase=0x02400000, uppercase=0x03E00000
|
|
- (0x000F8000 * (C / 0x00028000))//lowercase=0x00090000, uppercase=0x000F8000
|
|
- (0x00003E00 * (D / 0x00000A00))//lowercase=0x00002400, uppercase=0x00003E00
|
|
),
|
|
4,
|
|
llIntegerToBase64(
|
|
E + F + G + H + 0xD34D3400
|
|
- (0xF8000000 * (E / 0x28000000))//lowercase=0x90000000, uppercase=0xF8000000
|
|
- (0x03E00000 * (F / 0x00A00000))//lowercase=0x02400000, uppercase=0x03E00000
|
|
- (0x000F8000 * (G / 0x00028000))//lowercase=0x00090000, uppercase=0x000F8000
|
|
- (0x00003E00 * (H / 0x00000A00))//lowercase=0x00002400, uppercase=0x00003E00
|
|
)
|
|
),
|
|
0,
|
|
7
|
|
);
|
|
}
|
|
|
|
// Copyright (C) 2009 Adam Wozniak and Doran Zemlja
|
|
// Released into the public domain.
|
|
// Free for anyone to use for any purpose they like.
|
|
//
|
|
// deep voodoo base 4096 key compression
|
|
//
|
|
// It produces fixed length encodings of 11 characters.
|
|
|
|
string compress_key(key k) {
|
|
string s = llToLower((string)llParseString2List((string)k, ["-"], []) + "0");
|
|
string ret;
|
|
integer i;
|
|
|
|
string A;
|
|
string B;
|
|
string C;
|
|
// string D;
|
|
|
|
while(i < 32) {
|
|
A = llGetSubString(s, i, i);
|
|
++i;
|
|
B = llGetSubString(s, i, i);
|
|
++i;
|
|
C = llGetSubString(s, i, i);
|
|
++i;
|
|
|
|
/*if(A == "0") {
|
|
A = "e";
|
|
D = "8";
|
|
} else if(A == "d") {
|
|
A = "e";
|
|
D = "9";
|
|
} else if(A == "f") {
|
|
A = "e";
|
|
D = "a";
|
|
} else
|
|
D = "b";
|
|
|
|
ret += "%e" + A + "%" + D + B + "%b" + C;*/
|
|
|
|
if(A == "0")
|
|
ret += "%ee%8";
|
|
else if(A == "d")
|
|
ret += "%ee%9";
|
|
else if(A == "f")
|
|
ret += "%ee%a";
|
|
else
|
|
ret += "%e" + A + "%b";
|
|
|
|
ret += B + "%b" + C;
|
|
}
|
|
|
|
return llUnescapeURL(ret);
|
|
}
|
|
|
|
key uncompress_key(string s) {
|
|
integer i;
|
|
string ret;
|
|
string A;
|
|
string B;
|
|
string C;
|
|
string D;
|
|
|
|
s = llToLower(llEscapeURL(s));
|
|
for(i = 0; i < 99; i += 9) {
|
|
A = llGetSubString(s,i+2,i+2);
|
|
B = llGetSubString(s,i+5,i+5);
|
|
C = llGetSubString(s,i+8,i+8);
|
|
D = llGetSubString(s,i+4,i+4);
|
|
|
|
if(D == "8") {
|
|
A = "0";
|
|
} else if(D == "9") {
|
|
A = "d";
|
|
} else if(D == "a") {
|
|
A = "f";
|
|
}
|
|
ret += A + B + C;
|
|
}
|
|
|
|
return (key)(llGetSubString(ret, 0, 7) + "-" +
|
|
llGetSubString(ret, 8,11) + "-" +
|
|
llGetSubString(ret,12,15) + "-" +
|
|
llGetSubString(ret,16,19) + "-" +
|
|
llGetSubString(ret,20,31));
|
|
}
|
|
|
|
/*
|
|
encode/decode 8 for compact keys
|
|
minimum weight of 3774-4338 bytes with 1 invocation of each function
|
|
rhet0rica, August 9, 2021
|
|
encodes keys into exactly 8 chars weighing 24 bytes on average
|
|
using the new llChar() and llOrd() built-ins
|
|
*/
|
|
|
|
string encode_8(key k) {
|
|
string o;
|
|
string in = llDumpList2String(llParseString2List(k, ["-"], []), "");
|
|
integer ri = 8;
|
|
while(ri--) {
|
|
integer cn = (integer)("0x" + substr(in, ri << 2, (ri << 2) + 3));
|
|
string c = llChar(cn);
|
|
if(llOrd(c, 0) != cn || cn < 256)
|
|
o += llChar(cn + 0x10000);
|
|
else
|
|
o += c;
|
|
}
|
|
return o;
|
|
}
|
|
|
|
key decode_8(string s) {
|
|
string o;
|
|
integer ri = 8;
|
|
while(ri--) {
|
|
integer c = llOrd(s, ri) & 0x0ffff;
|
|
integer rii = 4;
|
|
string word;
|
|
while(rii--) {
|
|
integer cn = (c >> (rii << 2)) & 0x0f;
|
|
if(cn < 10)
|
|
word += llChar(cn + 0x30);
|
|
else
|
|
word += llChar(cn + 0x57);
|
|
}
|
|
o += word;
|
|
}
|
|
return (key)(
|
|
substr(o, 0, 7) + "-" +
|
|
substr(o, 8, 11) + "-" +
|
|
substr(o, 12, 15) + "-" +
|
|
substr(o, 16, 19) + "-" +
|
|
substr(o, 20, 31)
|
|
);
|
|
}
|
|
|
|
/*
|
|
encode/decode 22 for compact keys
|
|
weight of 3778-4392 bytes with 1 invocation of each function
|
|
rhet0rica, August 13, 2022
|
|
encodes keys into 16 chars weighing up to 32 bytes
|
|
special NULL and EMPTY values for NULL_KEY and ""
|
|
less likely than encode_8 to break mono serialization (!) on uplifted regions
|
|
uses llChar() and llOrd()
|
|
*/
|
|
|
|
string encode_22(key u) {
|
|
if(u == "")
|
|
return "EMPTY";
|
|
if(u == NULL_KEY)
|
|
return "NULL";
|
|
|
|
/*string unhyphenated = substr(u, 0, 7) + substr(u, 9, 12)
|
|
+ substr(u, 14, 17) + substr(u, 19, 22)
|
|
+ substr(u, 24, 35);*/
|
|
|
|
string unhyphenated = llDumpList2String(llParseString2List(u, ["-"], []), "");
|
|
|
|
string outs;
|
|
|
|
integer cc = 16;
|
|
while(cc--) {
|
|
integer icc = cc << 1;
|
|
integer code = (integer)("0x" + substr(unhyphenated, icc, icc + 1));
|
|
if(code < 35 || code > 126) code += 0x100;
|
|
outs = llChar(code) + outs;
|
|
}
|
|
|
|
return outs;
|
|
}
|
|
|
|
key decode_22(string c) {
|
|
if(c == "EMPTY")
|
|
return "";
|
|
if(c == "NULL")
|
|
return NULL_KEY;
|
|
|
|
string prec;
|
|
integer cc = 16;
|
|
while(cc--) {
|
|
integer bits = llOrd(c, cc);
|
|
integer low = bits & 0xf;
|
|
integer high = (bits & 0xf0) >> 4;
|
|
#define decode_22_lookup "0123456789abcdef"
|
|
prec = substr(decode_22_lookup, high, high) + substr(decode_22_lookup, low, low) + prec;
|
|
#undef decode_22_lookup
|
|
}
|
|
|
|
// inexplicably, leaving this concatenation here is better for memory than putting it in the return line:
|
|
key hyphenated = (key)(substr(prec, 0, 7) + "-" + substr(prec, 8, 11) + "-"
|
|
+ substr(prec, 12, 15) + "-" + substr(prec, 16, 19) + "-"
|
|
+ substr(prec, 20, 31));
|
|
|
|
return hyphenated;
|
|
}
|
|
|
|
#endif // QKEYS
|