Skip to content

Instantly share code, notes, and snippets.

@IS4Code
Created April 24, 2017 20:36
Show Gist options
  • Save IS4Code/2c530684f9d758103a8394b34c191500 to your computer and use it in GitHub Desktop.
Save IS4Code/2c530684f9d758103a8394b34c191500 to your computer and use it in GitHub Desktop.
/*
The MIT License (MIT)
Copyright (c) 2017 IllidanS4
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
//Documentation: http://forum.sa-mp.com/showthread.php?t=633072
//Version 1.0
#include <string>
/*
native lstrnew(string[], length=-1);
native strc(string[], pos)
native lstrgetc(const lstring[], pos);
native lstrsetc(lstring[], pos, value);
native lstrsetlen(lstring[], newlength, padding='\0');
native strtype(const string[]);
native stranylen(const string[]);
native lstrlen(const lstring[]);
native lstrdel(lstring[], start, end);
native lstrins(lstring[], const substr[], pos, maxlength=sizeof(lstring));
native lstrcat(ldest[], const source[], maxlength=sizeof(ldest));
native lfwrite(File:handle, lstring[]);
native lfread(File:handle, lstring[], size=sizeof(lstring));
*/
#define CHARMASK ((1<<charbits-1)-1+(1<<charbits-1))
#define CDATMASK (~((1<<(cellbits-charbits)-1)-1+(1<<(cellbits-charbits)-1)) | CHARMASK)
#define INFOMASK (~CDATMASK)
#define INFOMAX (INFOMASK>>charbits)
#define INFOSIZE (cellbits-charbits)
#define CHARCOEF (cellbits/charbits)
#assert CHARMASK == 0x000000FF
#assert CDATMASK == 0xFF0000FF
#assert INFOMASK == 0x00FFFF00
#assert INFOMAX == 0x0000FFFF
#assert INFOSIZE == 24
#assert CHARCOEF == 4
enum
{
STRING_TYPE_EMPTY,
STRING_TYPE_UNPACKED,
STRING_TYPE_PACKED,
STRING_TYPE_LSTRING,
}
//Converts a normal string to an lstring. The string must be unpacked.
stock lstrnew(string[], length=-1)
{
if(length == -1) length = strlen(string);
if(length > INFOMAX) return false;
if(string[0] & (CDATMASK & ~CHARMASK)) return false;
for(new i = 0; i <= length; i++)
{
string[i] = ((length - i) << charbits) | (string[i] & CHARMASK);
}
return true;
}
//Defines the storage location of a character at a specified position in an lstring.
#define strc(%1,%2) (%1{CHARCOEF*(%2)+(CHARCOEF-1)})
//Returns the value of a character at a specified position in an lstring.
stock lstrgetc(const lstring[], pos)
{
new len = lstrlen(lstring);
if(len < 0 || pos < 0 || pos >= len) return -1;
return lstring[pos] & CHARMASK;
}
//Changes the value of a character at a specified position in an lstring.
stock lstrsetc(lstring[], pos, value)
{
new len = lstrlen(lstring);
if(len < 0 || pos < 0 || pos >= len) return false;
lstring[pos] = (lstring[pos]&~CHARMASK) | (value & CHARMASK);
return true;
}
stock lstrsetlen(lstring[], newlength, padding='\0')
{
new length = lstrlen(lstring);
if(length == -1) return false;
for(new i = length; i < newlength; i++)
{
lstring[i] = padding;
}
return lstrnew(lstring, newlength);
}
//Obtains the type of a string (empty, unpacked, packed, lstring).
stock strtype(const string[])
{
if(!string[0]) return STRING_TYPE_EMPTY;
if(string[0] & (CDATMASK & ~CHARMASK)) return STRING_TYPE_PACKED;
if((string[0] & INFOMASK) != 0) return STRING_TYPE_LSTRING;
return STRING_TYPE_UNPACKED;
}
//Retrieves the length of a string of any type.
stock stranylen(const string[])
{
if(strtype(string) == STRING_TYPE_LSTRING) return lstrlen(string);
else return strlen(string);
}
//Obtains a length of an lstring, in constant time.
stock lstrlen(const lstring[])
{
if(!lstring[0]) return 0;
new info = lstring[0] & INFOMASK;
if(info == 0) return -1;
return info >> charbits;
}
//Deletes a part of an lstring.
stock lstrdel(lstring[], start, end)
{
if(end < start) return -1;
if(!lstring[0]) return 0;
new info = lstring[0] & INFOMASK;
if(info == 0) return -1;
new len = lstrlen(lstring);
if(start >= len) return 0;
if(end >= len) end = len-1;
if(start < 0) start = 0;
new offset = end-start+1;
new newlen = len-offset;
for(new i = 0; i <= newlen; i++)
{
if(i < start)
{
lstring[i] = ((newlen - i) << charbits) | (lstring[i] & CHARMASK);
}else if(i+offset >= len)
{
lstring[i] = 0;
break;
}else{
lstring[i] = ((newlen - i) << charbits) | (lstring[i+offset] & CHARMASK);
}
}
return len-newlen;
}
//Inserts a substring (of any type) into an lstring at a given position.
stock lstrins(lstring[], const substr[], pos, maxlength=sizeof(lstring))
{
if(pos < -1) return -1;
new info = lstring[0] & INFOMASK;
if(info == 0) return -1;
new len = lstrlen(lstring);
if(pos > len) return -1;
if(pos == -1) pos = len;
new type = strtype(substr);
new offset = stranylen(substr);
if(offset == 0) return 0;
new newlen = len+offset;
if(newlen >= maxlength-1) newlen = maxlength-2;
for(new i = 0; i < pos; i++)
{
lstring[i] = ((newlen - i) << charbits) | (lstring[i] & CHARMASK);
}
for(new i = newlen; i >= pos+offset; i--)
{
lstring[i] = ((newlen - i) << charbits) | (lstring[i-offset] & CHARMASK);
}
for(new i = 0; i < offset; i++)
{
new c;
if(type == STRING_TYPE_PACKED)
{
c = substr{i};
}else{
c = substr[i] & CHARMASK;
}
lstring[pos+i] = ((newlen - i - pos) << charbits) | c;
}
return newlen-len;
}
//Appends a string (of any type) to an lstring.
stock lstrcat(ldest[], const source[], maxlength=sizeof(ldest))
{
return lstrins(ldest, source, -1, maxlength);
}
//Writes an lstring to a file.
stock lfwrite(File:handle, lstring[])
{
new len = lstrlen(lstring);
if(len < 0) return -1;
for(new i = 0; i < len; i++)
{
fputchar(handle, strc(lstring, i), false);
}
return len;
}
//Reads a line from a file as an lstring
stock lfread(File:handle, lstring[], size=sizeof(lstring))
{
for(new i = 0; i < size-1; i++)
{
new c = fgetchar(handle, 0, false);
if(c == EOF || c == '\n')
{
size = i+2;
break;
}
if(c == '\r')
{
new c2 = fgetchar(handle, 0, false);
if(c2 == '\n')
{
size = i+2;
break;
}
lstring[i++] = c;
c = c2;
}
lstring[i] = c;
}
lstring[size-1] = 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment