Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

Library: Arrays in LSL

Pavcules Superior
Registered User
Join date: 30 Oct 2006
Posts: 69
01-18-2009 14:30
Hi all,

I would like to introduce the "VeryPav Array" system, which is the concept of arrays in LSL. This is an extension to "Very Keynes" VK-DBMS-VM work last was released in 2008. If you go to the documentation links below it will explain what arrays are, plus documentation of all the functions. This page also has a license agreement, which follows the DBMS license as well.

Note, arrays in LSL is not something new, as other members of the community have submitted their own code on this over the years. The VeryPav Array shown here is a demonstration of how powerful the DBMS code base is.

Documentation of what an array is, and its associate functions:
http://docs.google.com/Doc?docid=ddd96bqf_25fntnb8d9

The Array functions code:
http://docs.google.com/Doc?docid=ddd96bqf_26gf3qfkcb

Example demo code:
http://docs.google.com/Doc?docid=ddd96bqf_28gpwvc9dj

Example demo code 2:
http://docs.google.com/Doc?docid=ddd96bqf_27dphgbrf7

For more info about the VK-DBMS-VM system, see this topic:
/54/4a/290413/1.html

Comments, suggestions, etc. are welcomed.

The code below has been split into two separate posts due to the forum limiting the size.
Pavcules Superior
Registered User
Join date: 30 Oct 2006
Posts: 69
01-18-2009 14:31
CODE


// VeryPav Array
// Release Date : 2009-01-18
// VK-DBMS-VM : Created by "Very Keynes"
// Arrays : Created by "Pavcules Superior"



//Very Keynes - 2008
//
// 2008-10-31, 22:24 GMT
// Release Candidate
//
// For usage information and examples please see
// http://docs.google.com/Doc?id=d79kx35_26df2pbbd8
//
//------------------Begin VK-dbms-VM----------------------------\\
//--------------------Introduction------------------------------\\
//
// Very Keynes - db - Virtual Machine
//
// Implements a core set of registers and root functions
// to create and manage multi-table database structures as
// an LSL list. Although intended to under pin higher level
// database management tools such as VK-SQL it is usable as
// a small footprint database facility for system level
// applications.
//
//
// Naming Conventions and Code Style
//
// This Code is intended to be included as a header to user generated
// code. As such it's naming convention was selected so that it would
// minimise the possibility of duplicate names in the user code portion
// of the application.
//
// Licencing
//
// The concept and code are hereby released to the public domain on an honer system.
// If expanded upon, or altered in any positive way, please post the update,
// else use it in any way you wish for non commercial applications. If used in a
// commercial application then please be mindful of the time spent to develop this system
// and contact the author about a distribution agreement
//
// Table Control Registers
//
integer th_; // Table Handle / Index Pointer
integer tc_; // Columns in Active Table
integer tr_; // Rows in Active Table
integer ts_; // Active Table Start Address
//
list _d_ = []; // Database File
list _i_ = [0]; // Index File
//
// Exposed Variables
//
integer dbIndex; // Active Row Table Pointer
list dbRow; // User Scratch List
string dbError; // System Error String
//
// Temporary / Working Variables
//
integer t_i;
string t_s;
float t_f;
list t_l;
//
// System Functions
//
// string dbCreate( TableName, ColumnList )
//
// Creates a new Table in the database
//
string dbCreate(string tab, list col)
{
if(dbOpen(tab)) // Integrity test
{
dbError = tab + " already exists";
return "";
}
// Create a new index record for the table
_i_ += [tab, tc_ = llGetListLength(col), 0, 0, 0];
th_= 0; // release current handle
dbOpen(tab); // Activate the new table
dbInsert(col); // insert the header record
return tab; // Return the alis
}
//
// Helper function returns Col# for Column Name
//
integer dbCol(string col){return llListFindList(dbGet(0), [_trm(col)]);}
//
// integer dbDelete( Row# )
//
// Deletes the specified Row of the Active Table
//
integer dbDelete(integer ptr)
{
if(ptr > 0 && ptr < tr_) // Bounds test
{
_d_ = llDeleteSubList(_d_, t_i = ts_ + tc_ * ptr, t_i + tc_ - 1);
--tr_;
return tr_ - 1;
}
else {
dbError = (string)ptr+" is outside the Table Bounds";
return FALSE;}
}
//
// integer dbDrop( TableName )
//
// Complement to dbCreate - Removes a Table and its data
//
integer dbDrop(string tab)
{
if(-1 != (t_i = llListFindList(_i_, [tab])))
{ dbOpen(tab);
_d_ = llDeleteSubList(_d_, ts_, ts_ + tc_ * tr_ - 1);
_i_ = llDeleteSubList(_i_, th_, th_ + 4);th_= 0;
return TRUE; }
else {dbError = tab + " : Table name not recognised"; return FALSE;}
}
//
// integer dbExists( condition list )
//
// searches from last row towards row 1 stopping and returning the first match
//
integer dbExists(list cnd)
{ for(dbIndex = tr_ ; --dbIndex > 0 ; ){if(dbTest(cnd))return dbIndex;}
return FALSE;}
//
// list dbGet( row# )
//
// returns the specified row
//
list dbGet(integer ptr)
{
if(ptr < tr_ && ptr >= 0)return llList2List(_d_, t_i = ts_ + tc_ * ptr, t_i + tc_ - 1);
else dbError = (string)ptr+" is outside the Table Bounds";return [];
}
//
// Internal function to calculate a tables start address
integer _idx(integer hdl){return (integer)llListStatistics(6, llList2ListStrided(_i_, 0, hdl, 5));}
//
// integer dbInsert( list Row Data )
//
// Creates a new row at the end of the table, returns rumber of rows
//
integer dbInsert(list val)
{
if(llGetListLength(val) == tc_){_d_ = llListInsertList(_d_, val, ts_ + tc_ * (dbIndex = tr_++));return dbIndex;}
else{dbError = "Insert Failed - too many or too few Columns specified"; return FALSE;}
}
//
// integer dbOpen ( Table Name )
//
// saves current registers and opens a table if it exists
// returns Number of rows in opened table
//
integer dbOpen(string tab)
{
if(th_)_i_ = llListReplaceList(_i_, [tr_, dbIndex, tc_ * tr_], th_ + 2, th_ + 4);
if(-1 == (t_i = llListFindList(_i_, [tab]))) //if tab does not exist abort
{dbError = tab + " : Table name not recognised"; return FALSE;}
else if(th_ != t_i){th_ = t_i++;ts_ = _idx(th_);
tc_ = llList2Integer(_i_, t_i++);
tr_ = llList2Integer(_i_, t_i++);
dbIndex = llList2Integer(_i_, t_i);}
;return tr_ - 1;
}
//
// integer dbPut( list Row Data )
//
// Replaces the currently Active Row of the Table with the new data
integer dbPut(list val){if(llGetListLength(val) == tc_)
{
_d_ = llListReplaceList(_d_, val, t_i = ts_ + tc_ * dbIndex, t_i + tc_ - 1); return dbIndex;}
else {dbError = "Update Failed - too many or too few Columns specified"; return FALSE;}
}
//
// integer dbTest( condition list )
//
// tests condition against current row, returns true or false
//
integer dbTest(list cnd)
{
if(llGetListEntryType(cnd,2) >= 3){
t_s = llList2String(dbGet(dbIndex), dbCol(llList2String(cnd, 0)));
if ("==" == llList2String(cnd, 1)){t_i = t_s == _trm(llList2String(cnd, 2));}
else if("!=" == llList2String(cnd, 1)){t_i = t_s != _trm(llList2String(cnd, 2));}
else if("~=" == llList2String(cnd, 1))
{t_i = !(llSubStringIndex(llToLower(t_s), llToLower(_trm(llList2String(cnd, 2)))));}}
else{
t_f = llList2Float(dbGet(dbIndex), dbCol(llList2String(cnd, 0)));
t_s = llList2String(cnd, 1);
if ("==" == t_s){t_i = t_f == llList2Float(cnd, 2);}
else if("!=" == t_s){t_i = t_f != llList2Float(cnd, 2);}
else if("<=" == t_s){t_i = t_f <= llList2Float(cnd, 2);}
else if(">=" == t_s){t_i = t_f >= llList2Float(cnd, 2);}
else if("<" == t_s){t_i = t_f < llList2Float(cnd, 2);}
else if(">" == t_s){t_i = t_f > llList2Float(cnd, 2);}}
if(t_i)return dbIndex; else return FALSE;
}
// Internal function encapsulates llStringTrim
string _trm(string val){return llStringTrim(val, STRING_TRIM);}
//
// dbTruncate ( table Name )
//
// removes all rows from a table but leaves the header intact
//
dbTruncate(string tab){dbIndex = dbOpen(tab);while(dbIndex > 0)dbDelete(dbIndex--);}
//
// dbSort ( integer Order )
//
// permanently sorts a table by the first column, ascending or descending
//
dbSort(integer dir){_d_ = llListReplaceList(_d_,llListSort(llList2List
(_d_, t_i = ts_ + tc_, t_i + tc_ * tr_ - 2), tc_, dir), t_i, t_i + tc_ * tr_ - 2);
}
//
// dbFn( Function, Column )
//
// Preforms Statistical functions on the Column Specified
//
float dbFn(string fn, string col)
{
t_l = llList2List(_d_, t_i = ts_ + tc_, t_i + tc_ * tr_ - 2);
if(dbCol(col) != 0) t_l = llDeleteSubList(t_l, 0, dbCol(col) - 1);
return llListStatistics(llSubStringIndex("ramimaavmedesusqcoge", llGetSubString(llToLower(fn),0,1)) / 2,
llList2ListStrided(t_l, 0, -1, tc_));
}

//------------------End VK-dbms-VM----------------------------\\

Pavcules Superior
Registered User
Join date: 30 Oct 2006
Posts: 69
01-18-2009 14:32
CODE

// ----------------------------------------------------------------------\\
// --------------------- Start of VeryPav Array -------------------------\\
// ----------------------------------------------------------------------\\

// Set this to FALSE if you don't want to see Error messages appearing.
integer m_intShowErrorMessages = TRUE;


// Creates a new array.
integer arrayNew(list p_lstName, list p_lstDimensions, list p_lstItems)
{

string strName = llList2String(p_lstName, 0);

// Check if the collection exists, if it does not, then create one.
if(!dbOpen(strName))
{
list lstFields;
integer intIndex;

lstFields = [ "_arrayfield_" ];
lstFields = lstFields + [ "_arraydimensions_" + llDumpList2String(p_lstDimensions, ",") ];


if(llGetListLength(p_lstItems) == 0)
{
lstFields = lstFields + [ "_arrayvalue_" ];
}
else
{
lstFields = lstFields + p_lstItems;
}

dbCreate(strName, lstFields);

return TRUE;
}

// Collection not created, as one already exists.
return FALSE;

}

// Opens an array.
integer arrayOpen(string p_strName)
{
return dbOpen(p_strName);
}

// Deletes an array.
integer arrayDelete(string p_strName)
{
return dbDrop(p_strName);
}

// Checks if the array index exists, and returns the Row number if it does.
integer arrayIndexExists(list p_lstIndex)
{
list lstDimension = arrayGetDimensions();

if(llList2String(lstDimension, 0) != "")
{
integer intIndex;

for(intIndex = 0; intIndex < llGetListLength(p_lstIndex); intIndex++)
{
if(llList2Integer(p_lstIndex, intIndex) > llList2Integer(lstDimension, intIndex))
{
if(m_intShowErrorMessages)
{
llOwnerSay("ERROR: Array element (" + llDumpList2String(p_lstIndex, ",") + ") is out of bounds.");
}
return FALSE;
}
}
}

if(dbExists(["_arrayfield_", "==", llDumpList2String(p_lstIndex, ",") ]))
{
return dbIndex;
}
else
{
return FALSE;
}

}

// Return the array dimensions.
list arrayGetDimensions()
{

if(llStringLength(llList2String(dbGet(0), 1)) > 17)
{
return llCSV2List(llGetSubString(llList2String(dbGet(0), 1), 17, -1));
}

// Return an empty list if there is no maximum dimensions.
return [];
}


// Set values in an array.
integer arraySetValue(list p_lstIndex, list p_lstValues)
{

integer intLocationExists = arrayIndexExists(p_lstIndex);

if(intLocationExists)
{
dbRow = dbGet(intLocationExists);
dbPut([llDumpList2String(p_lstIndex, ",")] + [ "" ] + p_lstValues);
}
else
{
dbInsert([llDumpList2String(p_lstIndex, ",")] + [ "" ] + p_lstValues);
}

return TRUE;

}

// Gets the value from the location specified.
list arrayGetValue(list p_lstIndex)
{
integer intLocationExists = arrayIndexExists(p_lstIndex);

if(intLocationExists)
{
dbRow = dbGet(intLocationExists);
return llList2List(dbRow, 2, -1);
}

return [];
}

// Delete the value from the location specified.
integer arrayDeleteValue(list p_lstIndex)
{
integer intLocationExists = arrayIndexExists(p_lstIndex);

if(intLocationExists > 0)
{
return dbDelete(intLocationExists);
}

return FALSE;
}

// Reindexes an array from the given location.
arrayReindex(list p_lstIndex)
{

integer intIndex;
integer intCountMulti = llList2Integer(p_lstIndex, llGetListLength(p_lstIndex) - 1) - 1;
integer intCount;

for(intIndex = 1; intIndex < tr_; intIndex++)
{

dbIndex = intIndex;
dbRow = dbGet(intIndex);

if(llGetListLength(llCSV2List(llList2String(dbRow, 0))) > 1)
{
list lstPart = llCSV2List(llList2String(dbRow,0));
integer intLastNumber = llList2Integer(p_lstIndex, llGetListLength(p_lstIndex) - 1);
integer intLastNumber2 = llList2Integer(lstPart, llGetListLength(lstPart) - 1);

if( llDumpList2String(llList2List(p_lstIndex,0, llGetListLength(p_lstIndex)-2), ",") ==
llDumpList2String( llList2List(lstPart,0, llGetListLength(lstPart)-2), ",")
&& intLastNumber2 >= intLastNumber )
{
intCountMulti++;

list lstResult= [ llDumpList2String( llList2List(lstPart,0, llGetListLength(lstPart)-2), ",") +
"," + (string)intCountMulti ] + llList2List(dbRow, 1, -1) ;

dbPut(lstResult);
}
}
else
{
intCount++;
dbPut( [intCount] + llList2List(dbRow, 1, -1));
}
}

}

// Push value onto the array stack.
integer arrayPushValue(list p_lstValues)
{
list lstDimensions = arrayGetDimensions();

if(lstDimensions != [])
{
if(tr_ > llList2Integer(lstDimensions, 0))
{
return FALSE;
}
}

return dbInsert([(string)tr_] + [ "" ] + p_lstValues);
}

// Pop the last value from the array stack.
list arrayPopValue()
{
if(tr_ > 1)
{
list lstItem = llList2List(dbGet(tr_-1), 2, -1);
dbDelete(tr_-1);
return lstItem;
}

return [];
}

// Assign a list of values to the array.
arrayListValues(list p_lstValues)
{
integer intIndex;
integer intFields = llGetListLength(llList2List(dbGet(0), 2, -1));

for(intIndex = 0; intIndex < llGetListLength(p_lstValues); intIndex=intIndex+intFields)
{
dbInsert([(string)tr_] + [ "" ] + llList2List(p_lstValues, intIndex, intIndex + intFields - 1));
}

}

// ----------------------------------------------------------------- \\
// -------------------- End of VeryPav Array ----------------------- \\
// ----------------------------------------------------------------- \\