Code archives/Miscellaneous/Store structured data in strings

This code has been declared by its author to be Public Domain code.

Download source code

Store structured data in strings by Zethrax2004
-------------
GENERAL INFO
-------------

This codelib contains functions for working with data strings. Data strings are basically flat databases consisting of structured strings which can optionally contain multiple named records. Each record can optionally contain multiple value fields which are used to store data. The data is stored and returned as a string, which can also be an integer or float value if you transfer the data into an int or float variable (or use the 'Int()' or 'Float()' commands to convert it).

Data strings can also optionally have a header string at the start which can be used for any purpose you wish, but which must not contain any record name delimiter characters.


------
USAGE
------

The structure of a data string is an optional header string at the start of the data string, optionally followed by any number of records. The structure of a record is a name delimiter character, followed by the record name, followed by another name delimiter character, optionally followed by any number of value fields. The structure of a value field is a string value (which can be an integer or float value, depending on how you use it) followed by a value delimiter character. Example: (uses '#' for the name delimiter, and '^' for the value delimiter.) header string#record 1#value field 1^value field 2^value field etc^record etc#value field 1^value field 2^value field etc^

The name delimiter character is stored in the global variable 'G_DS_name_delimiter$', and the value field delimiter is stored in the global variable 'G_DS_value_delimiter$'. You can change these characters to whatever you like at any time. Only a single character should be used for each, though, and the same character must not be used for both the name and value delimiters. It's also recommended that you don't use a zero ascii character value for these to avoid conflicts when using zero delimited strings (when passing a data string to a DLL, for example).

All the data string commands work on a string stored in the global string variable 'G_DS_data_string$'. When you wish to work with a data string, transfer it into this variable. When you are finished working with a data string, transfer it from this variable back to its original storage.

Use 'F_DS_CreateRecord( L_record_name$, L_num_fields )' to create a new record with the name specified in 'L_record_name$' and with the number of empty fields specified in 'L_num_fields'. The new record is added to the end of the data string. The newly created record becomes the current record and the first field of that record becomes the current field for setting and getting values. Record names are case sensitive and can contain any character other than the one used for the record name delimiter. An empty string should not be used as a record name.

Use 'F_DS_RemoveRecord( L_record_name$, L_num_fields )' to remove a record with the name specified in 'L_record_name$' and with the number of fields specified in 'L_num_fields'. If the record doesn't exist, no changes will be made to either the data string or its internal pointers, so you can call this function blind. After the record has been removed the internal pointers may not be pointing at any valid record, so you should use 'F_DS_FindRecord()' or 'F_DS_GetNextRecord$( 1 )' when you want to obain a new record to work with.

Use 'F_DS_FindRecord( L_record_name$ )' to search for a record with the name specified in 'L_record_name$' and set it as the current record and its first field as the current field for setting and getting values. If the record is not found the function will return a zero, otherwise it will return a non-zero value. You can use the value returned by this function to test if the record actually exists.

Use 'F_DS_SetValue( L_value$, [L_index] )' to set the value of the current field in the current record. After this function is called, the next field in the record (if any) becomes the current field. If the optional 'L_index' parameter is present, then the field indexed by 'L_index' will be the one that the value is set for, and the field following it will become the current field on exit from the function. Field indexes start at one for the first field, and increment by one for each successive field. You should be aware of how many fields a record contains, as there is no limit checking for the number of record fields.

Use 'F_DS_GetValue( L_value$, [L_index] )' to get the value of the current field in the current record. After this function is called, the next field in the record (if any) becomes the current field. If the optional 'L_index' parameter is present, then the field indexed by 'L_index' will be the one that the value is obtained from, and the field following it will become the current field on exit from the function. Field indexes start at one for the first field, and increment by one for each successive field. You should be aware of how many fields a record contains, as there is no limit checking for the number of record fields. The value returned by this command is a string, so you will need to use the 'Int()' or 'Float()' commands as appropriate if you wish to use the returned value inline in a numeric expression.

Use 'F_DS_GetNextRecord$( [L_search_from_start_flag] )' to get the name of the next record in the data string, or the first record if a True value is specified in the optional parameter. If no next (or first) record is found, then an empty string will be returned. If a record is found, then that record will be set as the current record and its first field as the current field.

Use 'F_DS_SetToFirstRecordField()' to set the first field in the current record as the current field.

Use 'F_DS_SetHeader( L_value$ )' to set the value of an optional header string placed at the start of the data string, before the first record. This command updates the record and field pointers so they are pointing to the same record and field after it is used as they were before it was used, so it can safely be used alongside the record and field access commands. The header must not contain any record name delimiter characters.

Use 'F_DS_GetHeader$()' to get the value of an optional header string placed at the start of the data string, before the first record. If no header is present, an empty string is returned. This command does not interfere with the record and field pointers, so it can safely be used alongside the record and field commands. The value returned by this command is a string, so you will need to use the 'Int()' or 'Float()' commands as appropriate if you wish to use the returned value inline in a numeric expression.

Note that none of the above commands are dependant on each other so you can safely remove any you don't need.


---------------
POTENTIAL USES
---------------

This codelib was created for a level editing program to store standard and custom properties of 3D entities in their namestrings, as well as for general scripting, undo-redo que abstraction layer scripting, map file generation and script loading, etc. I also use it for sending commands between a Blitz3D program and a Purebasic DLL.

; The code can be found at: http://www.blitzbasic.com/codearcs/codearcs.php?code=1220

Comments

None.

Code Archives Forum