Whiskerstore Library v1.0

for DarkBASIC Professional

Copyright (C) 2005-2006 Keith Leinenbach
One Man And A Cat Software

www.onecatweb.com

Installation

DarkBASIC Professional makes it very easy to add DLL plugins. Just copy the whiskerstore.dll to the directory:

C:\Program Files\The Game Creators\Dark Basic Professional Online\Compiler\plugins-user

An example program which includes the examples given in this document is also included with this installation.

Two Versions

There are two versions of the Whiskerstore Library: Free and Professional. Both the Free version and the Professional can be used for free and commercial uses with the restrictions set out in the License Agreement. Functions that are reserved for the Professional version (available from onecatweb.com) are marked with a P. The main advantages of the Professional Version is index optimization, file encryption, list, and lookup management.

Introduction

Whiskerstore is a simple to use, but powerful DLL that provides the data handling functionality needed to create today's games. It combines a very simple data storage format that is easy to read and edit with support for flexible objects, classes, optimized indexing, queries, list management, and lookup tables. You can keep your data in an easy to edit text file or encrypt it to keep your game secrets away from prying eyes.

Getting started with Whiskerstore is very simple. You can create a data store with a text editor to get you started or begin from scratch. Below is a sample program that loads a data store, sets some attributes in the object, retrieves the attributes values, and then saves the datastore.

Basic Datastore Access Example




` Specify some variables

objname as string

stringval as string

s as string

intval as integer

floatval as double float

boolval as boolean



` Unlock the library

WskUnlock "Your Name","Your Code"



` Load in a Whiskerstore Datastore

WskLoadDB "test","test1.txt",""



` Create the object if it doesn't exist

objname="example_basics"

if WskObjExists(objname)=0 then s=WskNewObj("Name=example_basics",0)



` Set some attributes of an object

WskSetAttrib objname,"Data","Greetings"

WskSetAttribAsInt objname,"Points",23

WskSetAttribAsBool objname,"Finished",0

WskSetAttribAsFloat objname,"Times",34.895



` Retrieve the attributes of an object.

if WskObjExists(objname)=1

  stringval=WskGetAttrib(objname,"Data")

  intval=WskGetAttribAsInt(objname,"Points")

  floatval=WskGetAttribAsFloat(objname,"Times")

  boolval=WskGetAttribAsBool(objname,"Finished")

endif



` Print out the results

print "--------------------------------"

print "example_basics()"

print "Attributes: Data=";stringval;" Points=";intval;" Times=";

print floatval;" Finished=";boolval





` Save the datastore out to a file

WskSaveDB "test1.txt",""



Whiskerstore can also work with lists of integers, floating points, and strings. Since DarkBASIC Pro does not have a mechanism for passing lists into functions, the library provides a set of handling functions for accessing and maintaining lists. Lists can be used independently of objects or as attributes. Below is an example of handling lists in Whiskerstore.

List Handling Example

List management is available only in the Professional Version.




` Specify some variables

objname as string

treelist as integer

monsterlist as integer

listind as integer

num as integer

i as integer

s as string



` Unlock the library

WskUnlock "Your Name","Your Code"



` Load in a Whiskerstore Datastore

WskLoadDB "test","test1.txt",""



` Create the object if it doesn't exist

objname="example_lists"

if WskObjExists(objname)=0 then s=WskNewObj("Name=example_lists",0)





` SETTING LISTS

` Create a two lists.

treelist=WskNewList()

monsterlist=WskNewList()



` Method 1: Add items independently

` -1 will add the items at the end.

` Other values replace whatever is at that location.

i=WskAddItemAsString(treelist,-1,"Spruce")

i=WskAddItemAsString(treelist,-1,"Pine")

i=WskAddItemAsString(treelist,-1,"Maple")

i=WskAddItemAsString(treelist,-1,"Oak")



` Method 2: Add items all at once from a string

WskStringToList monsterlist,"goblins,trolls,spiders,snakes,orcs",","



` Store the lists in the created object

WskSetAttribAsList objname,"Trees",treelist,"}"

WskSetAttribAsList objname,"Monsters",monsterlist,"}"



` Clean up the lists

WskDeleteList treelist

WskDeleteList monsterlist





` RETRIEVING LISTS (presumably at a later time!)

` Create a list to hold the data

listind=WskNewList()



` Method 1: Getting the items individually

WskGetAttribAsList objname,"Trees",listind

num=WskGetItemCount(listind)



print "--------------------------------"

print "example_lists()"

print "TREES: ";

for i=0 to num-1

  s=WskGetItemAsString(listind,i)

  print "[";i;"]";s;" ";

next i

print ""



` Method 2: Getting the items all at once in a string.

` Note you don't have to create a new list everytime, you can

` reuse lists as is done below.

WskGetAttribAsList objname,"Monsters",listind

s=WskListToString(listind,";")

print "MONSTERS: ";s



WskDeleteList listind



For those who are looking for handling lookup tables (often referred to as hash tables), Whiskerstore offers a solution. Simply create a lookup table, set some values, and access them. Like lists, lookup tables are managed by the library. You can create as many lookup tables as you wish. While you can store lookup tables as strings in data store objects, they are currently not an intrinsic type. If you do store these tables, make sure you use delimiters that don't clash with the parametrized object format (see Data Format). An example is provided below.

Lookup Table Example

Lookup management is available only in the Professional Version.




` Specify some variables

ind as integer



` Unlock the library (just for completeness, need only be done once)

WskUnlock "Your Name","Your Code"



` Lookup Tables

ind=WskNewLookup()



`Populate a lookup table using a string using = and : as the delimiters

WskStringToLookup ind,"Broadsword=450:Dagger=10:Club=5","=:"

`Add a value to the lookup table

WskSetLookup ind,"Mace","200"

`Change a value in the lookup table

WskSetLookup ind,"Dagger","12"



print "--------------------------------"

print "example_lookups()"

` Lookup some results

print "WskGetLookup: Dagger="; WskGetLookup(ind,"Dagger");

print " - Mace="; WskGetLookup(ind,"Mace")



` Convert the lookup back to a string using : and ; as the delimiters

print "WskLookupToString: ";WskLookupToString(ind,":;")



WskDeleteLookup ind



 

Data Format

There is nothing mysterious about the data format used for Whiskerstore, it is simply a listing of parametrized objects, with one object per line. Each object consists of a list of attribute name=value pairs separated by a vertical bar, |. The vertical bar, | is located on the right side of most keyboards above the Enter key. Since the bar is very rare in regular text there is no need to use extra delimiters such as ", making it easier to read and a smaller file. The data store escapes the |, LF, and CR characters into the non-printable character codes of 1,6, and 7 respectively. Calls to WskGetAttrib and WskSetAttrib automatically escape and unescape these characters for you.

Parametrized object format:

Name=object name|attribute1=value1|...|attributei=valuei

Examples:

Name=DoorNumber3|Class=door|Status=open|Prize=A New Car!
Name=Contestant2|Class=person|Status=Jumping up and down.

As you can see, very easy to read and edit on the fly. This will provide a simple method of visually debugging game databases. Also, notice that unlike table-based databases and files, each object can have different attribute values. There is no need to have a different table for each class of object. You may store integers, floating point numbers, strings, and lists as the values of attributes. Lists are stored in a special format that both indicates that they are lists and provides a delimiter, which by default is the character }.

List format:

_list}value1}...}valuei

Examples:

_list}apples}oranges}grapes
_list}3.7814}8.582}2.45

 

Function List

Note: Functions that are reserved for the Professional version (available from onecatweb.com) are marked with a P.

 

Datastore

 

WskLoadDB DBName,FileName,EncryptMap

Loads a data store with the path FileName and stores it under the name DBName. If the file is encrypted, be sure to supply the EncryptMap used to store the database.

 

WskSaveDB FileName,EncryptMap

Saves the active data store to FileName and stores it under the name DBName. You can save the file in plain text or supply an EncryptMap encrypt the data. Use WskCreateEncryptMapFile to create a key you can use for your data file. It is recommended that you save the datastore in an unencrypted state during the development of your game, since the file format has been designed to be easy to read with any text editor.

 

WskClearDB

Clears the objects from the current datastore, deleting all of the objects. The actual datastore is not deleted and is still available and chosen as the current datastore.

 

WskCloseDB

Closes the current datastore, freeing the memory allocated to it.

 

WskChooseDB (DBName) - returns index, -1 on failure

Selects the datastore DBName as the currently active datastore. Most operations in the library work on the currently selected datastore.

 

WskCreateAttribIndex AttribName     P

Indexes the attribute specified by AttribName so that searches on that attribute are considerably faster. Attribute indices are saved to the datastore and restored upon reloading.

 

WskGetObjNames (Criteria,ListHandle) - returns number found     P

Searches the active datastore for objects that match the specified Criteria. This function returns a list of the object's names that are matches. The string list handling functions can be used to access the list.

Criteria is specified as follows:
and expression | and expression 2 | ... and expression x
 
where and expression is defined as:
boolean expression 1 & boolean expression 2 & ... boolean expression x
 
where boolean expression is defined as:
a comparison op b
 
comparison ops are:
= is equal to
> is greater than
< is less than
>= is greater than or equal to
<= is less than or equal to
<> is not equal to

Examples:

type=fightertype is equal to "fighter"
hitpoints>20&lives>1(hitpoints > 20) and (lives>1)
door=open&alarm=false|door=closed&key=true((door=open) and (alarm=false)) or ((door=closed) and (key=true))

 

WskEncryptMapFile FileName     P

Creates an encrypt map key to be used for encrypting the game datastore and stores it in the file specified by FileName. This key must be passed to the save and load functions to unscramble the data. It is recommended that you save the datastore in an unencrypted state during the development of your game, since the file format has been designed to be easy to read with any text editor.

 

Object Handling

Whiskerstore stores each data entry as an object. Each object must have a unique name, optionally a class, and a set of attributes that define it. Unlike many databases which are organized in tables of columns and rows, Whiskerstore allows every object to have an arbitrary number of attributes. This flexibility is important when building a game database.

Like most things in the library, objects have a concept of currently selected (active). Calling WskChooseObj or any function where you specify the ObjName will set the active object. Subsequent calls can retrieve values or act on the selected object by leaving the ObjName as an empty string ( "" ). This speeds up object access as well as saves you some coding.

 

WskChooseObj (ObjName) - returns index, -1 on failure

Sets the current object. Most object handling functions act on the object selected by this function.

 

WskChooseObjByAttrib (AttribName,AttribValue) - returns index, -1 on failure

Sets the current object by searching for the first object which the attribute AttribName has the value AttribValue. Most object handling functions act on the object selected by this function.

 

WskGetAttrib (ObjName, Attrib) - returns value
WskGetAttribAsInt (ObjName, Attrib) - returns value
WskGetAttribAsFloat (ObjName, Attrib) - returns value
WskGetAttribAsBool (ObjName, Attrib) - returns value
WskGetAttribAsList (ObjName, Attrib, ListHandle) - returns value     P

Retrieves the attribute value of the specified object, ObjName. The item can be retrieved as an integer, float, boolean, string, or list. As in all object functions setting ObjName="" acts on the currenty selected object, specifying ObjName will select a new object.

Retrieving lists is a bit different than the simpler integer, float, and string. Instead of returning the actual list, the number of items in the list is returned. The internally maintained list is updated with the results of this function. You may use the list handling functions to retrieve the list values.

 

WskSetAttrib ObjName, Attrib, Value
WskSetAttribAsInt ObjName, Attrib, Value
WskSetAttribAsFloat ObjName, Attrib, Value
WskSetAttribAsBool ObjName, Attrib, Value
WskSetAttribAsList ObjName, Attrib, ListHandle, Delim     P

Sets the attribute value of the specified object, ObjName. The item can be set as an integer, float, boolean, string, or list. As in all object functions setting ObjName="" acts on the currenty selected object, specifying ObjName will select a new object.

Setting lists is a bit different than the simpler integer, float, and string. Instead of passing the list as a value, use the list handling functions to set the values of an internally maintained list first and then make the call to WskSetAttribAsList passing the ListHandle. You can choose the delimiter for the list when it is in string form or pass "" to use the default.

 

WskGetObjString (ObjName) - returns delimited object string

Get the delimited object string named ObjName. If ObjName is left blank the delimited string for the currently selected object is returned.

 

WskObjExists (ObjName) - returns 0 or 1

Returns a 1 when the object ObjName exists or a 0 if it doesn't.

 

WskDeleteObj ObjName

Deletes the object ObjName. If ObjName is left blank the delimited string for the currently selected object is deleted.

 

WskNewObj (ObjDef,bAutoName) - returns delimited object string

Creates a new object defined by the delimited string ObjDef. Set bAutoName if you want an auto generated unique name. The = character separates attribute names from values and the | character (over the \ on most keyboards) separates one attribute from the next. There should be no space before or after each = or | delimiter.

If you want to create an object using a class template, simply specify a Class attribute in your list. If a the class is specified, the default values for the class will be initialized in the object, unless overriden by new values in the definition string. By convention the Class attribute is specified directly after the Name.

Name=object name|attribute1=value1|...|attributei=valuei

 

List Handling

List management is available only in the Professional Version.

Since DarkBASIC Pro does not support passing lists or arrays in functions, WhiskerStore provides a simple interface to work with lists when using the data store. You may also create and manage lists unassociated with the data store if you wish. Lists are identified by an integer based handle (referred to as the ListHandle). Lists are populated by functions such as WskGetAttribAsList and WskAddToList. They can also be cleared and reused with WskClearList. You can set or get an attribute of an object with the values of a list with the functions WskSetAttribAsList and WskGetAttribAsList.

 

WskNewList () - returns index, 0 on failure    P

Creates a new list and returns an integer handle to the newly created list. After creating a list you can then add and delete items to the list using the WskAddToList and WskDeleteFromList series of functions.

WskClearList ListHandle     P

Clears the internally stored list identified by ListHandle. Note that WskGetAttribAsList and WskStrToList automatically clear the list, so there is no need to call this function before using those calls.

WskDeleteList ListHandle     P

Deletes the internally stored list identified by ListHandle freeing up the memory. While all created lists are freed upon exiting the DLL, it is good programming practice to free lists when you are finished with them.

 

WskGetItemCount (ListHandle) - returns number of items     P

Returns the number of items in the list.

 

WskGetItemAsString (ListHandle, Index) - returns item     P
WskGetItemAsInt (ListHandle, Index) - returns item     P
WskGetItemAsFloat (ListHandle, Index) - returns item     P

Retrieves the list item at the given index. The item can be retrieved as an integer, float, or string. ListHandle identifies which list you wish to work with.

 

WskSetItemAsString (ListHandle, Index, Value) - returns -1 on failure     P
WskSetItemAsInt (ListHandle, Index, Value) - returns -1 on failure     P
WskSetItemAsFloat (ListHandle, Index, Value) - returns -1 on failure     P

Sets the list item at the given index. The item can be stored as an integer, float, or string. ListHandle identifies which list you wish to work with.

 

WskAddItemAsString (ListHandle, Index, Value) - returns index, -1 on failure     P
WskAddItemAsInt (ListHandle, Index, Value) - returns index, -1 on failure     P
WskAddItemAsFloat (ListHandle, Index, Value) - returns index, -1 on failure     P

Adds a list item at the given Index, moving all the items from Index to the end of the list up one index value to make room for the new item. Passing a -1 in Index creates an entry at the end of the list and returns the index of the new item. The item's Value can be set as an integer, float, or string.

 

WskDeleteItem ListHandle, Index     P

Removes the list item at the given index. All indices above the deleted index are moved down one to accomodate the deletion. ListHandle identifies which list you wish to work with.

 

WskStringToList ListHandle, StrList, Delim     P

Converts a delimited string, StrList into a list. The delimiter is set by Delim. The function clears the list before converting the string. This is a great way to pass an entire list in one call. ListHandle is an integer identifying which list you wish to work with.

 

WskListToString (ListHandle, Delim) - returns delimited string     P

Converts the list identified by ListHandle into a string delimited by Delim. Note that if you are converting a lookup list, you may provide two characters, the equals delimited followed by the item delimiter (ie. =|).

 

Lookup Tables

Lookup management is available only in the Professional Version.

Lookup tables are a special type of data store where one textual string is associated with another. These are also referred to as maps. Lookups are identified by an integer based handle (referred to as the LookupHandle).

WskNewLookup () - returns index, -1 on failure    P

Creates a new lookup table and returns an integer handle to the newly created lookup. After creating a lookup you can then add and delete items to the list using the WskSetLookup and WskDeleteLookupItem series of functions.

WskClearLookup LookupHandle     P

Clears the internally stored list identified by LookupHandle. Note that WskStrToLookup automatically clear the list, so there is no need to call this function before using those calls.

WskDeleteLookup LookupHandle     P

Deletes the internally stored lookup identified by LookupHandle freeing up the memory. While all created lookups are freed upon exiting the DLL, it is good programming practice to free lookups when you are finished with them.

 

WskGetLookup (LookupHandle, Index) - returns value    P

Gets the value for the textual entry Index in the lookup identified by LookupHandle. Returns a string value. Lookup tables are created by using the WskNewLookup function.

WskSetLookup LookupHandle, Index, Value     P

Sets the string value for the textual entry Index in the lookup identified by LookupHandle. Lookup tables are created by using the WskNewLookup function.

WskStringToLookup LookupHandle, StrList, Delims     P

Converts a delimited string delimited by Delims to a lookup table and stores it in the LookupHandle given. Delims is a string with the first character being the delimiter between the name and the value, typically "=", and the second being the delimiter between name/value pairs. So to convert the delimited string "cows=moo:dogs=bark", Delims would equal "=:". As with all lookup functions, lookup tables are created by using the WskNewLookup function.

WskLookupToString (LookupHandle, StrList, Delims) - returns delimited string     P

Converts the lookup table designated by LookupHandle and returns it as a delimited string delimited by Delims. Delims is a string with the first character being the delimiter between the name and the value, typically "=", and the second being the delimiter between name/value pairs. For example, the delimited string "cows=moo:dogs=bark" would need Delims to equal "=:". As with all lookup functions, lookup tables are created by using the WskNewLookup function.

 

Classes

Classes are available only in the Professional Version.

While it is not a requirement that one use classes when defining objects it can make life a bit easier. Classes in Whiskerstore are not rigid definitions that all objects of that class have to adhere to. They simply define the minimum set of attributes for objects of a given class. You are free to add new attributes to any object of a class you wish. For this reason classes provide a quick way to instantiate a new object with an initial set of values defined in the class specification. Classes are specific to each datastore and are stored on save and restored on load.

 

WskRegisterClass ClassDef     P

Registers a class with the datastore you are currently using. Objects with that class set are instantiated with the base definition given by ClassDef. Same named attributes specified in the ObjectDef in object creation override the default values specified by the class.

Like objects, classes are defined by a parameterized string delimited by the "=" and the "|" characters. The format is the same as that for an object, except that no class attribute is specified. The name attribute defines the name of the class.

   ClassDef format: Name=classname |attrib1 =value1 | attrib2 =value2 | ...

 

WskUnregisterClass ClassName     P

Unregisters a class from the datastore you are currently using. Note that it does not remove objects of the class specified.

 

WskGetClass (ClassName) - returns delimited string     P

Returns the Name=value|.. delimited string for the class defining the attributes and their default values.

 

WskListClasses (ListHandle) returns count, -1 on failure     P

Returns a list of the names of the classes available in the currently selected datastore. The list specified by the integer ListHandle is populated with the results. See List Handling for information on creating and handling lists. You can use any of the list handling functions to retrieve the list of classes.

 

Miscellaneous Functions

 

WskGetVersion() - returns version number

Returns the current version of the DLL. The version is returned as an integer of the following format:

vvmmrrb

Where v is the major version number, m is the minor version number, r is the revision, and b indicates whether it is a beta version or not. For example 101020 is version 1.1, revision 2 and is not in beta.

 

WskUnlock Name,Code

Unlocks the Whiskerstore library so that you can use it. Use the name you registered under and the code you received when registering your product. You may register Whiskerstore DLL at onecatweb.com. There is no return value.

Important: This must be called before any other Whisker DLL calls in your program.