User talk:Becky Pippen/Text Storage

From Second Life Wiki
Jump to navigation Jump to search

Memory optimized versions

Someone recently asked for a more memory efficient version so I hacked one together. It could be made faster by using two loops, and pealing off characters in bigger groups more infrequently.

<lsl>string encode15BitsToChar(integer num) {

   // Check the incoming range

   if (num < 0 || num >= 0x8000) {
       // illegal input -- do whatever is appropriate
       return "�";
   }

   // Bias the incoming numeric value by 0x1000 to avoid illegal Unicode codes:

   num += 0x1000;

   // construct UTF-8 layout:

   num = 0xE0808000 | (num << 12) | ((num << 10) & 0x3f0000) | ((num << 8) & 0x3f00);

   // Convert the UTF-8 into a 16-bit Unicode character:

   return llGetSubString(llBase64ToString(llIntegerToBase64(num)), 0, 0);

}

integer decodeCharTo15Bits(string ch) {

   integer val = llBase64ToInteger(llStringToBase64(ch));

   if((val & 0xE0000000) ^ 0xE0000000)
       return -1; //The character is not 3 bytes.

   return  ((val & 0x0f000000) >> 12) +
           ((val & 0x003f0000) >> 10) +
           ((val & 0x00003f00) >>  8) - 0x1000;

}

string compressAscii(string s) {

   integer len = llStringLength(s);
   // Append a space if needed to make s an even number of chars
   if (len & 1) {
       s += " ";
   }
   string encodedChars = "";
   while( (len -= 2) > -2 ) {
       string chars = llGetSubString(s, 0, 1);
       s = llGetSubString(s, 2, 0x7ffffff0);
       encodedChars += encode15BitsToChar(
           charToUnicodeIdNumber(chars) << 7 |
           charToUnicodeIdNumber(llGetSubString(chars, 1, 1)));
   }
   return encodedChars;

}

string uncompressAscii(string s) {

   string result = "";
   integer len = llStringLength(s);
   while ( 0 <= --len ) {
       integer cInt15 = decodeCharTo15Bits(llGetSubString(s, 0, 0));
       s = llGetSubString(s, 1, 0x7ffffff0);
       result += llGetSubString(llBase64ToString(llIntegerToBase64(
                           ((cInt15 << 17) & 0x7f000000) | 
                           ((cInt15 << 16) & 0x007f0000)
                   )), 0, 1);
   }
   return result;

}</lsl>