08.05.2015, 07:17
(
Last edited by Yashas; 01/01/2017 at 05:00 PM.
Reason: New Information
)
eXtended INI Processor
Fast,simple,unique,feature rich,user friendly INI Reader/Writer
Latest Version: 1.1 - 2/9/2015
eXtended INI Processor, eINI in short, is an amazing INI Processor include which comes with lot of new features,innumerable configurable options and lot more without compromising speed and efficiency of the server.This system works by caching the whole INI File and storing each and every single line in the memory where all manipulations are done.This means that the file is opened twice, once for parsing and once for saving.eINI stores sections,keys,lines in data structures which are commonly knows as linked lists where each node(i.e:line or key) stores the id of the next as well as the previous key which makes deleting,inserting operations easier and efficient.
There are many INI Processor Includes around but this one is a whole lot different from other.This is exclusively made for those who don't use YSI and who need some of the features which are not available in y_ini but comes with eINI.
Contents:
Firstly, eINI is way much faster than dini(as ****** says, though very popular it is insanely slow),SII and similar INI Readers.When compared with y_ini, eINI writes values much faster than y_ini but y_ini is slightly faster while reading smaller ini files.Given the fact that eINI parser is more careful and does more work, eINI working slower was expected but surprisingly eINI is faster than y_ini when large files are used.
Secondly, eINI provides some exiting features such as Replacements and different mods of parsing which has never been implemented in any other INI Processors.
Thirdly, easy to use and well documented.
List of functions:
INI files are simple text files usually with .ini extension which are composed of sections,keys and their values.There have been different standards for ini files over many years.eINI supports many INI Standards with a variety of options which can be toggled as per ones needs.One must follow these rules while manually creating or editing INI files so that the file makes sense to the eINI Parser.
Keys(properties)
The basic element contained in an INI File is a key(also known as property). Each key consists of a name and a value which is delimited by a '=' or an ':' sign depending on your settings('=' by default).
By default, eINI treats all of the keys that are given below as equivalent.The leading spaces and the ending spaces of a key name are insignificant.The leading spaces are insignificant for a key value but terminal spaces are significant.These examples must make this clear.
The name must be made up of alphanumeric characters.An underscore may be used.Spaces in the name aren't allowed by default but they can be enabled by defining INI_ENABLE_WHITESPACE before including this script.You can use almost any character(characters which cause ambiguity are not allowed such as '=') in the key name if you are running the processor in LIBERAL mode.
The following are invalid key definitions.
Sections
Keys can(but not compulsory) be grouped into arbitrarily named sections.The beginning of each section is indicated by enclosing the section name within square brackets.The keys that do not belong to any section(the keys that are defined before any section is defined) are termed as Global Keys.Global Keys belong to the global section.There is no explicit delimiter that indicates end of a section;the sections end at the declaration of the next section.
Here too, the leading and ending spaces in the section name are not significant.The following section declarations are identical
Every section name must be made up of alphanumeric characters.An underscore can be used.Spaces aren't allowed by default but they can be enabled by defining INI_ENABLE_WHITESPACE before including this script.Any character(characters which cause ambiguity are not allowed such as ']') can be used in the section names if you are running the processor in LIBERAL mode.The following section declarations are invalid.
Comments
Comments can take their own line or can be used in key/section declarations as depicted in the above examples.Comment lines are indicated by beginning the line with a ';' or a '#'. Comment lines are ignored by the parser.
Blank Lines
You can have blank lines in the file.These lines will be ignored by the parser.These lines can be used to format the file and make it more readable to the human eye.
Random Lines
Random Lines are the lines which make no sense to the parser.Such lines are not allowed until you are in LIBERAL mode where random lines are treated as comment lines.
Duplicate Names
Only one key with a particular name can exist within a section.Duplicate keys which are found later will give rise to a warning and will be ignored while reading(the first key with that name will be considered). This implies for section names also.
Case Sensitivity
Both case sensitive and non-case-sensitive parsing are supported.They can be toggled by defining INI_DISABLE_CASE_SENSITIVITY before including this script.
Escape Characters & Replacements
Escape Characters can be used in the key values.These are necessary because using a ; or # or any other special character in the value would cause problems.For example using ';' would indicate a comment and the rest of the value will be ignored.So to add a ';' in the value of a key, you must use '\;' which the parser will count as a character that is a part of the value.
There is a topic dedicated to Escape Characters & Replacements and everything will be discussed in detail in that section.
Getting Started & Configuration
To use eINI, you simply need to include header after defining all the configurable options.All the options or settings must be defined before including.Stating the options after including the header has no effect and the option will assume default value.
Here is a list of options or settings which eINI provides
To change a default setting just define it with value of your choice before including eINI.
Liberal Mode:
This mode liberalizes the INI standard allowing bad INI files to be parsed without issuing any errors.Enabling this mode only affects the parser.It will slightly improve the performance of the parser.
List of changes from default mode:
Tells the parser that the file is neatly formatted and it needn't do format checks.This will improve the efficiency of the parser by 30%-40% but decreases the versatility of the INI files.
In this mode the parser makes the following assumptions:
Example of a formatted INI:
If INI files are not in the expected format when this mode is enabled then the parser will show some kind of undefined behavior.
Careful Mode:
This mode assumes that programmer is very careful.Tells the script to assume that no invalid handles or any such careless mistake will not happen.This will make negligible difference in performance of the script in this version.Just a useless feature right now in this version.
I strongly recommend this mode to be turned off since it is has negligible impact on the performance in the current release and humans are stupid and can never be perfect.
Opening/Closing Files & INI Handles
Just like a File Handle(File:file), eINI uses INI Handles(INI:ini).This is similar to the INI: tag used in y_ini.This is basically used to identify an INI File and also to distinguish between INI Handles,File Handles and normal variables.
To learn more about tags in PAWN, visit Scripting:tags
Creating an INI Handle is as simple as declaring a variable:
Every function that belongs to eINI needs to be prefixed with INI:: before calling.This work just like C++ Namespaces.
These are the basic functions:
CreateINI
Definition:INI::CreateINI(const fname)
Parameters:fname takes the location along with the filename that is to be created
Returns:INI Handle (with INI:) for the newly created file or an error code
Remarks:The file is not physically created until CloseINI is called
Exceptions:
INI_ERR_FILE_ALREADY_EXISTS - The file already exists
INI_ERR_MAX_FILE_LIMIT - Maximum simultaneously operable files limit has been reached
OpenINI
Definition:INI::OpenINI(const fname,mode=INI_READ_WRITE)
Parameters:
Remarks:Use the mode parameter to enhance performance
Exceptions:
INI_ERR_FILE_DOES_NOT_EXIST - The file doesn't exist
INI_ERR_MAX_FILE_LIMIT - Maximum simultaneously operable files limit has been reached
Why use mode parameter?
Suppose you are only writing to the file then do you think the parser needs to store the value of every key?
The answer is no because we won't need the values.So by setting the mode to INI_WRITE we tell the parser that we are only writing so parse only key and section names.Will improve performance to a great extent for large files.
Suppose you are only reading the file then do you think it is necessary to save the file?
The answer is no because you won't be making any changes to the file.
CloseINI
Definition:INI::CloseINI(INI:filehandle,bool:savebuffer=true)
Parameters:
Remarks:The file won't be saved and you will lose an INI Handle if CloseINI is not called
Exceptions:
INI_ERR_INVALID_HANDLE - An invalid handle was passed to CloseINI
INI_ERR_PARSING_FAILED - The file couldn't be parsed.This would only happen if the file was opened, not used and there is a syntax error in the file.
IsValidHandle
Definition:INI::IsValidHandle(INI:handle)
Parameters:INI Handle that has to be checked for validity
Returns:True if the given INI Handle is valid else false
Remarks:Primarily used to check if OpenINI or CreateINI was successful
[code]new INI:handle = INI::OpenINI("sql.ini");
if(INI::IsValidHandle(handle))
{
//Safe to use the handle
}
else print("Couldn't load sql configuration");
[/code
eINI Log File
By default, eINI prints all warnings/errors/notices directly into the server console. You can enable logging using file by defining INI_USE_LOG_FILE before including eINI.
The log file is named as "eini_log.txt". You can find the log file in scriptfiles folder.
How the parser works(Advanced & Optional)
The parser checks each and every line and stores the information regarding the line in an user-defined enumerator array.It uses linked lists to the store the lines.Once the parser identifies the type of the line, it creates a key or a section element in an user-defined enumerator array of keys or sections respectively.The keys are also stored in linked lists.Each section and key is given an id based on the segment-offset method.
Segment-Offset Method:
A segment is an index or an address which indicates the start of a region of memory and offset is also an index or an address which tells how far the variable from the segment is situated in the memory.
If you have had a glimpse through the include, you would have probably noticed these
Let's investigate INI_Key.The number of elements with INI_Key is INI_MAX_MULTI_FILES*INI_MAX_KEYS.This variable 'INI_Key' stores the Keys for all the keys of different files.Each file gets its segment and each key gets an offset.The indexes that belong to the first file would be from 0 to INI_MAX_KEYS and of the second file would be INI_MAX_KEYS to INI_MAX_KEYS*2 and so on...
For nth file, INI_MAX_KEYS*(n-1) to INI_MAX_KEYS*n belongs to the nth INI Handle.
Now to access a key of the file, we would need an offset.The offset indicates how far away from the segment the key is.
Lets take an example:
Lets assume that this was the second file that was opened and has been assigned the INI Handle 2.So this handle would own the keys with index starting from INI_MAX_KEYS to INI_MAX_KEYS*2.So its starting index of the segment would be INI_MAX_LINES.The key one(i.e:"key1") gets its absolute index as INI_MAX_KEYS and offset as 0, the second key(i.e:"key2") gets an absolute index as INI_MAX_KEYSS+1, an offset of 1, third key(i.e:"key3") gets an absolute index as INI_MAX_KEYS+2 and offset as 2 and so on.All of these keys have the segment index as INI_MAX_KEYS.
This is how eINI assigns key ids.
Now to get the name of the key of key 'n' of this file, we use the following formula
I hope that now you have a fair idea about how indexing(giving ids) in eINI works.
So we would come across two terms while using eINI namely relative keyid/sectionid and absolute keyid/sectionid.
This is exactly same as segment and offset.
The parser assigns IDs linearly.The first key of the file gets offset 0,second gets offset 1 and so on.Similarly the first section gets an offset of 1, second gets an offset of 2 and so on.Where did the offset 0 go?Its reserved for global section irrespective if there is any global key or not(global keys could be added later).
Why do we need to know this?
You can exploit the way the parser assigns IDs linearly to improve the performance of the script.Instead of asking eINI to search and find the section or the key, you could directly tell the Read or Write functions the keyids and sectionids knowing the file already which would improve the performance to a large extent(we would avoid so many strcmps for finding sections and keys). We'll see more examples later in the Reading and Writing Sections.
Example:
Relative Key ID Assignments:
key1 = 0 (Global Key, therefore has a sectionid 0)
key1 = 1(key1 of SEC1)
key2 = 2
a = 3
b= 4
c = 5
Relative Section ID Assignments:
Global Section = 0 (irrespective of if there is any element or not)
SEC1 = 1
SEC2 = 2
SEC3 = 3
SEC4 = 4
Reading
eINI supports reading by calling reading functions individually as well as dynamic reading/loading(which is similar to y_ini).We will look into both of them separately.
Static Loading
eINI provides functions to read strings,integers,floats,hexadecimal numbers,binary numbers,arrays,enumerators.It also provides lazy programmers with a function which can be used to read multiple keys simultaneously at the cost efficiency.
These are the functions that can be used to obtain values of the keys.
ReadString
Gets the value of a key as a string.
Definition:INI::ReadString(INI:filehandle,result[],const key[],const section[]="",keyid=-1,sectionid=-1,result_size=sizeof(result),section_size=sizeof(s ection),key_size=sizeof(key))
Parameters:
Remarks:Use keyid parameter when ever possible or at least sectionid parameter if known to improve performance.
Exceptions:
INI_KEY_NOT_FOUND - The key whose value was requested was not found in the file
INI_ERR_INVALID_HANDLE - The INI Handle passed is invalid
INI_ERR_PARSING_FAILED - The parsing of the file failed
ReadBool
This function interprets the value of the given key and tells the Boolean value associated with it.If the value is equal to '1' or 'true' then the variable parameter will be set to true.If the value is equal to '0' or 'false' then the variable parameter is set to false.
Definition:INI::ReadBool(INI:filehandle,&bool:variable,const key[]="",const section[]="",keyid=-1,sectionid=-1,section_size=sizeof(section),key_size=sizeof(key ))
Parameters:
Remarks:Use keyid parameter when ever possible or at least sectionid parameter if known to improve performance.
Exceptions:
INI_KEY_NOT_FOUND - The key whose value was requested was not found in the file
INI_ERR_INVALID_HANDLE - The INI Handle passed is invalid
INI_ERR_PARSING_FAILED - The parsing of the file failed
INI_ERR_INVALID_BOOL - The value cannot be interpreted (value is not acceptable)
Example:
Assume that we are working on this file
If we use ReadBool on all the keys, these will be the results:
ReadBool will set variable to true when key1 is read
ReadBool will set variable to false when key2 is read
ReadBool will set variable to true when key3 is read
ReadBool will set variable to false when key4 is read
ReadBool will not touch the variable and will return that it is an invalid bool
ReadInteger
Gets the integral value of a key
Definition:INI::ReadInteger(INI:filehandle,&variable,const key[]="",const section[]="",keyid=-1,sectionid=-1,section_size=sizeof(section),key_size=sizeof(key ))
Parameters:
Remarks:
INI_KEY_NOT_FOUND - The key whose value was requested was not found in the file
INI_ERR_INVALID_HANDLE - The INI Handle passed is invalid
INI_ERR_PARSING_FAILED - The parsing of the file failed
ReadFloat
Gets a floating point number from the key
Definition:INI::ReadFloat(INI:filehandle,&Float:variable,cons t key[]="",const section[]="",keyid=-1,sectionid=-1,section_size=sizeof(section),key_size=sizeof(key ))
Parameters:
Remarks:
INI_KEY_NOT_FOUND - The key whose value was requested was not found in the file
INI_ERR_INVALID_HANDLE - The INI Handle passed is invalid
INI_ERR_PARSING_FAILED - The parsing of the file failed
ReadHex
Gets the integral value of a key where the value is expressed in hexadecimal notation
Definition:INI::ReadHex(INI:filehandle,&variable,const key[]="",const section[]="",keyid=-1,sectionid=-1,section_size=sizeof(section),key_size=sizeof(key ))
Parameters:
Remarks:
INI_KEY_NOT_FOUND - The key whose value was requested was not found in the file
INI_ERR_INVALID_HANDLE - The INI Handle passed is invalid
INI_ERR_PARSING_FAILED - The parsing of the file failed
ReadBinary
Gets the integral value of a key where the value is expressed in binary notation
Definition:INI::ReadBinary(INI:filehandle,&variable,const key[]="",const section[]="",keyid=-1,sectionid=-1,section_size=sizeof(section),key_size=sizeof(key ))
Parameters:
Remarks:
INI_KEY_NOT_FOUND - The key whose value was requested was not found in the file
INI_ERR_INVALID_HANDLE - The INI Handle passed is invalid
INI_ERR_PARSING_FAILED - The parsing of the file failed
ReadArray
Parses an array key and fills the given array with the correct values.
Definition:INI::ReadArray(INI:filehandle,array[],const key[]="",const section[]="",keyid=-1,sectionid=-1,array_size=sizeof(array),section_size=sizeof(sec tion),key_size=sizeof(key))
Parameters:
Remarks:
INI_KEY_NOT_FOUND - The key whose value was requested was not found in the file
INI_ERR_INVALID_HANDLE - The INI Handle passed is invalid
INI_ERR_PARSING_FAILED - The parsing of the file failed
ReadEnum
Parses an enum key and loads an enum array.
Definition:INI::ReadEnum(INI:filehandle,enum_array[],enum_unit_size,const key[]="",const section[]="",keyid=-1,sectionid=-1,section_size=sizeof(section),key_size=sizeof(key ))
Parameters:
Remarks:
INI_KEY_NOT_FOUND - The key whose value was requested was not found in the file
INI_ERR_INVALID_HANDLE - The INI Handle passed is invalid
INI_ERR_PARSING_FAILED - The parsing of the file failed
ReadFormat
Read multiple keys in one line at the cost of efficiency.
Definition:INI::ReadFormat(INI:filehandle,sectionid,const format[],{Float,_}:...)
Parameters:
Remarks:
NOTE:Using an invalid specifier will stop the reading process.
Dynamic Loading using ParseINI
Dynamic Loading is the other method to read keys.This system is similar to y_ini.The parser calls a function each time a key is parsed. There are different ways of dynamic loading which will be explained in this section. Dynamic Loading also provides an option to broadcast data across all scripts which means you can share the contents of the INI file with different scripts without having to parse the file again in that script.
ParseINI
Parses the INI File and caches keys and sections
Definition:INI::ParseINI(INI:filehandle,const LoadFunction[] = "",bool:dynamic=false,extra=0,bool:pass_extra=fals e,bool:func_with_key=false);
Parameters:
Returns 0 for normal execution
It also returns 0 if file was not meant to be parsed(in case of a new file)
Or an error code
Exceptions:
INI_ERR_INVALID_HANDLE - Invalid File Handle
INI_ERR_SYNTAX - The INI file does not meet the required format
Load Function must be passed with a '%s' specifier where you want the parser to add the Section Name before calling, i.e: if Load Function is "Load_func_%s" will be changed to "Load_func_SECTION_NAME" during parsing.The keys in the global section will call the callback with ""(i.e:Nothing will be substituted) as section name.
To understand better, lets take an example.Let the text given below be our example INI File.
Lets assume that the "MyFunc_%s" is passed to ParseINI as LoadFunction parameter.
The Load Function will be called 6 times as there are 6 keys.
To read all the keys, we would need a total of 3 functions.
The returns from the Load Function are not handled by the parser.The key and value will have the name of the key and its value respectively.
If you are using func_with_key then the second occurrence of '%s' will be replaced with the key name.For example, if "MyFunc_%s_%s" was passed to ParseINI as Argument then "MyFunc_SECTION_KEY" will be called for each key.
Traditional way of dynamic reading passes the key and the section name as arguments to the Load Function.
By default the information read from the INI is not broadcasted across all scripts. You can enable broadcasting by setting the broadcast parameter to true. By enabling broadcast, the LoadFunction will be called in every running script.
Escape Characters & Replacements
The escape characters present in a string in an ini file are not replaced when it is read by the server.So you'll have to do it manually.But eINI makes your work easier by providing ready-made functions which will do the replacement of escape characters for you.
Lets look at an example to understand what I mean:
If you read this string and then print it in your server console, you'll see this
"This is SA-MP\\0.3.7\nDownload at sa-mp.com"
You won't get the expected output, i.e:
"This is SA-MP\0.3.7
Download at sa-mp.com"
You won't get that output because '\n' or any other escape sequences are not replaced with their appropriate ASCII Value.
This can be easily fixed with the help of Replace Function provided by eINI.
Replace
Replaces escape characters with their real ASCII Value.
Definition:INI::Replace(const src[],dest[],const ReplacementFunction[]="",extra=0,bool:pass_extra=false,sz=sizeof(src),s z_dest=sizeof(dest),sz_rf=sizeof(ReplacementFuncti on))
Parameters:
You cannot directly use ';' or '#' or characters that are sensitive to the parser directly.Instead you must use the appropriate escape character.
List of valid escape characters:
Custom Replacements:
Replace has another amazing feature that allows to have your own escape strings.All custom escape sequences must be enclosed within [THE ESCAPE SEQUENCE NAME]. The function will parse the line and call your Replacement Function where you'll decide what to substitute(the string set using SetReplacementText) in place of that escape sequence.
Lets take an example to understand better:
Now the array dest will have
"Password must have 20 to 5 characters"
What you return in the ReplacementFunction matters.The replacement will be carried out only if your Replacement Function returns a non-zero integer.Returning 0 means that eINI won't carry out the replacement and will replace it with "[]".
SetReplacementText
Will set the replacement text
Definition:INI::SetReplacementText(const str[])
Parameters:
Extra Parameter:
The extra parameter is passed to the replacement function and it optional.
To use this extra parameter you must enable the extra parameter and pass the extra value to the Replace Function which will in turn pass it to the Replacement Function.
Writing
eINI provides lots of different methods to write keys to files efficiently.It stores all the new values in a buffer and writes them all at once instead of having to open a file every time to write something.
These are the functions that eINI provides for writing data to files.
WriteString
Writes a string
Definition:INI::WriteString(INI:filehandle,const data[],const key[],const section[],keyid=-1,sectionid=-1,data_size=sizeof(data),section_size=sizeof(secti on),key_size=sizeof(key))
Parameters:
Remarks:Use keyid parameter when ever possible or at least sectionid parameter if known to improve performance.
Exceptions:
INI_ERR_INVALID_HANDLE - The INI Handle passed is invalid
INI_KEY_NOT_FOUND - Key with the given keyid doesn't exist
INI_ERR_PARSING_FAILED - Parsing failed
WriteBool
Checks for falsity of the boolean variable passed and writes its equivalent to the key.
Definition:INI::WriteBool(INI:filehandle,bool:variable,const key[],const section[],keyid=-1,sectionid=-1,section_size=sizeof(section),key_size=sizeof(key ))
Parameters:
Remarks:Use keyid parameter when ever possible or at least sectionid parameter if known to improve performance.
Exceptions:
INI_ERR_INVALID_HANDLE - The INI Handle passed is invalid
INI_KEY_NOT_FOUND - Key with the given keyid doesn't exist
INI_ERR_PARSING_FAILED - Parsing failed
WriteInteger
Writes an integer
Definition:INI::WriteInteger(INI:filehandle,variable,const key[],const section[],keyid=-1,sectionid=-1,section_size=sizeof(section),key_size=sizeof(key ))
Parameters:
Remarks:Use keyid parameter when ever possible or at least sectionid parameter if known to improve performance.
Exceptions:
INI_ERR_INVALID_HANDLE - The INI Handle passed is invalid
INI_KEY_NOT_FOUND - Key with the given keyid doesn't exist
INI_ERR_PARSING_FAILED - Parsing failed
WriteFloat
Writs a float to the key
Definition:INI::WriteFloat(INI:filehandle,Float:variable,cons t key[],const section[],keyid=-1,sectionid=-1,section_size=sizeof(section),key_size=sizeof(key ))
Parameters:
Remarks:Use keyid parameter when ever possible or at least sectionid parameter if known to improve performance.
Exceptions:
INI_ERR_INVALID_HANDLE - The INI Handle passed is invalid
INI_KEY_NOT_FOUND - Key with the given keyid doesn't exist
INI_ERR_PARSING_FAILED - Parsing failed
WriteHex
Writs an integer in hexadecimal notation
Definition:INI::WriteHex(INI:filehandle,variable,const key[],const section[],keyid=-1,sectionid=-1,section_size=sizeof(section),key_size=sizeof(key ));
Parameters:
Remarks:Use keyid parameter when ever possible or at least sectionid parameter if known to improve performance.
Exceptions:
INI_ERR_INVALID_HANDLE - The INI Handle passed is invalid
INI_KEY_NOT_FOUND - Key with the given keyid doesn't exist
INI_ERR_PARSING_FAILED - Parsing failed
WriteBinary
Writes an integer value to a key in binary form
Definition:INI::WriteBinary(INI:filehandle,variable,const key[],const section[],keyid=-1,sectionid=-1,section_size=sizeof(section),key_size=sizeof(key ))
Parameters:
Remarks:Use keyid parameter when ever possible or at least sectionid parameter if known to improve performance.
Exceptions:
INI_ERR_INVALID_HANDLE - The INI Handle passed is invalid
INI_KEY_NOT_FOUND - Key with the given keyid doesn't exist
INI_ERR_PARSING_FAILED - Parsing failed
WritesArray
Writes an array
Definition:INI::WriteArray(INI:filehandle,array[],const key[]="",const section[]="",keyid=-1,sectionid=-1,array_size=sizeof(array),section_size=sizeof(sec tion),key_size=sizeof(key))
Parameters:
Remarks:Use keyid parameter when ever possible or at least sectionid parameter if known to improve performance.
Exceptions:
INI_ERR_INVALID_HANDLE - The INI Handle passed is invalid
INI_KEY_NOT_FOUND - Key with the given keyid doesn't exist
INI_ERR_PARSING_FAILED - Parsing failed
WriteEnum
Writes an enum element to the file
Definition:INI::WriteEnum(INI:filehandle,enum_array[],enum_unit_size,const key[]="",const section[]="",keyid=-1,sectionid=-1,section_size=sizeof(section),key_size=sizeof(key ))
Parameters:
Remarks:Use keyid parameter when ever possible or at least sectionid parameter if known to improve performance.
Exceptions:
INI_ERR_INVALID_HANDLE - The INI Handle passed is invalid
INI_KEY_NOT_FOUND - Key with the given keyid doesn't exist
INI_ERR_PARSING_FAILED - Parsing failed
WriteFormat
Write multiple keys in one line at the cost of efficiency.
Definition:INI::WriteFormat(INI:filehandle,sectionid,const format[],{Float,_}:...)
Parameters:
Remarks:
NOTE:Using an invalid specifier will stop the writing process.
Miscellaneous Functions
eINI has some more functions which will be discussed here.
List of Miscellaneous Functions:
DeleteSection
Delete an entire section
Definition:INI::DeleteSection(INI:filehandle,const section[]="",sectionid=-1,section_size=sizeof(section))
Parameters:
Exceptions:
INI_ERR_INVALID_HANDLE - Invalid INI Handle was passed to the function
INI_SECTION_NOT_FOUND - Section does not exist
INI_ERR_INVALID_ID - Invalid Section ID
DeleteKey
Deletes a key
Definition:INI::DeleteKey(INI:filehandle,const key[],const section[]="",keyid=-1,sectionid=-1,key_size=sizeof(key),section_size=sizeof(section ));
Parameters:
Exceptions:
INI_ERR_INVALID_HANDLE - Invalid INI Handle was passed to the function
INI_KEY_NOT_FOUND - Key does not exist
INI_ERR_INVALID_ID - Invalid Section ID
GetSectionID
Get relative section id from section name
Definition:INI::GetSectionID(INI:filehandle,const section[],section_size=sizeof(section))
Parameters:
Exceptions:
INI_ERR_INVALID_HANDLE - Invalid INI Handle was passed to the function
INI_SECTION_NOT_FOUND - Section does not exist
GetKeyID
Get relative key id from key name
Definition:INI::GetKeyID(INI:filehandle,const key[],const section[]="",sectionid=-1,section_size=sizeof(section),key_size=sizeof(key ))
Parameters:
Exceptions:
INI_ERR_INVALID_HANDLE - Invalid INI Handle was passed to the function
INI_KEY_NOT_FOUND - Key does not exist
GetSectionName
Get section name from section id
Definition:INI::GetSectionName(INI:filehandle,result[],sectionid,result_size=sizeof(result))
Parameters:
Exceptions:
INI_ERR_INVALID_HANDLE - Invalid INI Handle was passed to the function
INI_ERR_INVALID_ID - Invalid Section ID
GetKeyName
Get key name from key id
Definition:INI::GetKeyName(INI:filehandle,result[],keyid,result_size=sizeof(result))
Parameters:
Exceptions:
INI_ERR_INVALID_HANDLE - Invalid INI Handle was passed to the function
INI_ERR_INVALID_ID - Invalid Key ID
WriteBuffer
Writes the buffer to the file
Definition:INI::WriteBuffer(INI:filehandle)
Parameters:
Exceptions:
INI_ERR_INVALID_HANDLE - Invalid INI Handle was passed to the function
INI_ERR_FILE_CREATION_FAILED - Could not create a new file
INI_ERR_PARSING_FAILED - Parsing of the file failed
INI_ERR_FAILED_TO_OPEN - Could not open the file
DumpINI
Dumps the contents of an INI File on to the Server Window
Definition:INI::DumpINI(INI:filehandle)
Parameters:
Exceptions:
INI_ERR_INVALID_HANDLE - Invalid INI Handle was passed to the function
Benchmarks
Writing Speed Test
NOTE:These speed tests are outdated. New speed tests haven't been conducted for the latest version.
eINI is faster at all times while writing when compared with y_ini.
TST1.txt and TST2.txt have the same contents.I made two different files so that any changes made by y_ini won't affect eINI.
Results:
SPEED TEST YSI:1685 eINI:1203
SPEED TEST YSI:1667 eINI:1175
SPEED TEST YSI:1666 eINI:1283
Reading Speed Test
y_ini wins when the file is small and eINI wins where the file is large.
Results:
SPEED TEST YSI:6141 eINI:6839 - Small File - 7 Lines
SPEED TEST YSI:6099 eINI:6686 - Small File - 6 Lines
SPEED TEST YSI:7664 eINI:7665- Small File - 10 Lines
SPEED TEST YSI:12614 eINI:10490 - Large File - 20 Lines
SPEED TEST YSI:19184 eINI:14487 - Very Large File - 36 lines
Issues & Notes
I had written this include in 2013 for my personal use.I have heavily modified the include this year(2015).I have added LIBERAL Mode so that any INI format/standard can be used or else I would be forcing people to use the style I like.
I am expecting bugs because its very old and moreover I have done lot of edits to the code to improve it.I have tested though and fixed all the bugs I could find.There could be some more.
Report bugs via PM or Create an issue at github
Report Typos this thread via PM
Change Log
Version 1.0:
(7/5/2015)
First Release
Version 1.0.3:
(10/5/2015)
(10/6/2015)
(19/8/2015)
(2/9/2015)
GitHub
Example Filterscript
Credits
Yashas
******,Dracoblue,Slick,Neufox and everyone else for their INI Readers which helped me a lot
Slice,****** and many others who used to amaze me every time
Special Thanks to:
****** a.k.a Alex "******" Cole
Kye/Kalcor & the whole SA-MP Team
Thiadmer for PAWN
Fast,simple,unique,feature rich,user friendly INI Reader/Writer
Latest Version: 1.1 - 2/9/2015
eXtended INI Processor, eINI in short, is an amazing INI Processor include which comes with lot of new features,innumerable configurable options and lot more without compromising speed and efficiency of the server.This system works by caching the whole INI File and storing each and every single line in the memory where all manipulations are done.This means that the file is opened twice, once for parsing and once for saving.eINI stores sections,keys,lines in data structures which are commonly knows as linked lists where each node(i.e:line or key) stores the id of the next as well as the previous key which makes deleting,inserting operations easier and efficient.
There are many INI Processor Includes around but this one is a whole lot different from other.This is exclusively made for those who don't use YSI and who need some of the features which are not available in y_ini but comes with eINI.
Contents:
- Features
- INI Specifications
- Getting Started & Configuration
- Reading
- Escape Characters & Replacements
- Writing
- Miscellaneous Functions
- Benchmarks
- Issues & Notes
- Change Log
- Download
- Credits
- Very fast and efficient
- Supports Comments(inline as well line comments)
- Read/Write Arrays,Enums
- Read/Write Multiple Keys
- Replacement Feature
- Custom Replacements
- Allows use of different INI Standards
- Highly Customizable
- Well Documented
- Multiple File Support
- Supports Section Tags
- Saves the file the way it was(i.e:doesn't delete comments or blank lines)
Firstly, eINI is way much faster than dini(as ****** says, though very popular it is insanely slow),SII and similar INI Readers.When compared with y_ini, eINI writes values much faster than y_ini but y_ini is slightly faster while reading smaller ini files.Given the fact that eINI parser is more careful and does more work, eINI working slower was expected but surprisingly eINI is faster than y_ini when large files are used.
Secondly, eINI provides some exiting features such as Replacements and different mods of parsing which has never been implemented in any other INI Processors.
Thirdly, easy to use and well documented.
List of functions:
- INI::CreateINI
- INI::OpenINI
- INI::IsValidHandle
- INI::CloseINI
- INI::WriteBuffer
- INI::ParseINI
- INI::ReadString, INI::ReadBool, INI::ReadInteger, INI::ReadFloat, INI::ReadHex, INI::ReadBinary, INI::ReadArray, INI::ReadEnum, INI::ReadFormat
- INI::WriteString, INI::WriteBool,INI::WriteInteger, INI::WriteFloat, INI::WriteHex, INI::WriteBinary, INI::WriteArray, INI::WriteEnum, INI::WriteFormat
- INI::Replace,INI::SetReplacementText
- INI::DeleteSection,INI::DeleteKey
- INI::GetSectionID,INI::GetKeyID
- INI::GetSectionName,INI::GetKeyName
- INI::DumpINI
INI files are simple text files usually with .ini extension which are composed of sections,keys and their values.There have been different standards for ini files over many years.eINI supports many INI Standards with a variety of options which can be toggled as per ones needs.One must follow these rules while manually creating or editing INI files so that the file makes sense to the eINI Parser.
Keys(properties)
The basic element contained in an INI File is a key(also known as property). Each key consists of a name and a value which is delimited by a '=' or an ':' sign depending on your settings('=' by default).
Code:
name=value myinteger=123 myfloat=12.3 mystring=this is a string
By default, eINI treats all of the keys that are given below as equivalent.The leading spaces and the ending spaces of a key name are insignificant.The leading spaces are insignificant for a key value but terminal spaces are significant.These examples must make this clear.
Code:
example=123 example =123 example = 123 example = 123; example = 123#Comments can be indicated by either using a '#' or a ';' example = 123;Anything after a ';' or a '#' will be considered as a comment line example = 123;Comments will not contribute to the value of the key example = 123 ; example = 123; These two keys are not equivalent since the previous key has a terminal space and this one doesn't
The name must be made up of alphanumeric characters.An underscore may be used.Spaces in the name aren't allowed by default but they can be enabled by defining INI_ENABLE_WHITESPACE before including this script.You can use almost any character(characters which cause ambiguity are not allowed such as '=') in the key name if you are running the processor in LIBERAL mode.
The following are invalid key definitions.
Code:
e$x%ample = 123 ;The key name has $ and % which are invalid characters until you are in LIBERAL mode example key = 123 ;This key name has a space in it which isn't allowed by default
Keys can(but not compulsory) be grouped into arbitrarily named sections.The beginning of each section is indicated by enclosing the section name within square brackets.The keys that do not belong to any section(the keys that are defined before any section is defined) are termed as Global Keys.Global Keys belong to the global section.There is no explicit delimiter that indicates end of a section;the sections end at the declaration of the next section.
Code:
key1 = 123124 ;This is a global key [SECTION_NAME] key1= 123 key2 = 145 ;Section ends here [ANOTHER_SECTION] key1 = 234 key2 = 134 key3= 454
Code:
[SECTION] [ SECTION ] [ SECTION] ;You can also have comments here too
Code:
[SECT ION] ;The space isn't supposed to be there [$ection] ; $ is not an alphanumeric character nor an underscore - allowed if you are in LIBERAL mode [Section ;This is invalid because ']' character is missing;this can be disabled [] ; Empty or Null Sections are not allowed
Comments can take their own line or can be used in key/section declarations as depicted in the above examples.Comment lines are indicated by beginning the line with a ';' or a '#'. Comment lines are ignored by the parser.
Code:
; this is a comment line - can write any gibberish crap here like asdasdas bdku asgdbasdb #Hey! I am a comment line to!! ;The leading spaces don't matter
You can have blank lines in the file.These lines will be ignored by the parser.These lines can be used to format the file and make it more readable to the human eye.
Code:
[Section1] key1=23 [Section2] ;The previous line was a blank line and will be ignored thekey=12324
Random Lines are the lines which make no sense to the parser.Such lines are not allowed until you are in LIBERAL mode where random lines are treated as comment lines.
Code:
$512341Dasd ;Parser says "WTF is this" 1238912y 39p8 1230 hihd asld.
Only one key with a particular name can exist within a section.Duplicate keys which are found later will give rise to a warning and will be ignored while reading(the first key with that name will be considered). This implies for section names also.
Case Sensitivity
Both case sensitive and non-case-sensitive parsing are supported.They can be toggled by defining INI_DISABLE_CASE_SENSITIVITY before including this script.
Escape Characters & Replacements
Escape Characters can be used in the key values.These are necessary because using a ; or # or any other special character in the value would cause problems.For example using ';' would indicate a comment and the rest of the value will be ignored.So to add a ';' in the value of a key, you must use '\;' which the parser will count as a character that is a part of the value.
There is a topic dedicated to Escape Characters & Replacements and everything will be discussed in detail in that section.
Getting Started & Configuration
To use eINI, you simply need to include header after defining all the configurable options.All the options or settings must be defined before including.Stating the options after including the header has no effect and the option will assume default value.
Code:
#define INI_ENABLE_WHITESPACE #include <eINI> #define INI_DISABLE_CASE_SENSITIVITY //Case Sensitivity won't be disabled since this line comes after the include
Setting | Default | Description |
INI_USE_LOG_FILE | By default errors/warnings/notices are printed directly into the server console | Defining will enable |
INI_ENABLE_WHITESPACE | By default white-spaces are not allowed | Defining will enable white-spaces in key and section names |
INI_DISABLE_CASE_SENSITIVITY | By default names are case sensitive | Defining will disable case sensitivity |
INI_DISABLE_WARNINGS | All warnings are printed in the server window by default | Defining will disable all warning messages |
INI_DISABLE_ERRORS | All errors are printed in the server window by default | Defining will disable all error messages |
INI_DISABLE_NOTICES | All notice messages are printed in the server window by default | Defining will disable all notice messages |
INI_LIBERAL_MODE | Disabled by default | Defining will enable LIBERAL mode |
INI_ASSUME_FORMATTED_INI | Assumes the worst case(poorly formatted) by default | Defining will tell the parser to assume the ini to be formatted |
INI_CAREFUL_MODE | By default the mistakes that are made by the programmer are taken care such as passing an invalid handle | Defining will tell eINI that the programmer is perfect and won't make mistakes |
INI_MAX_MULTI_FILES | By default it is set to 2 | Number of files that can be operated simultaneously |
INI_MAX_LINES | By default it will be set to 128 | The maximum number of lines that an INI file can have |
INI_MAX_SECTIONS | By default it will be set to 32 | Maximum number of sections that are allowed in an INI File |
INI_MAX_KEYS | By default it will be set to the value of INI_MAX_LINES | Maximum number of keys allowed in an INI File |
INI_NAME_VALUE_DELIMITER | '=' to by default | Key Name-Value Delimiter(must be '=' or ':') |
INI_ESCAPE_CHARACTER | By default '\' will be the escape character starter | You don't get any option here, it has to be '\' |
INI_MAX_LINE_LENGTH | By default it will be 256 | Maximum number of characters allowed per line |
INI_MAX_FILE_NAME_LENGTH | 32 by default | Maximum length of a file location |
INI_MAX_SECTION_NAME_LENGTH | 32 by default | Maximum number of characters allowed in a section name |
INI_MAX_SECTION_NAME_LENGTH | 32 by default | Maximum number of characters allowed in a section name |
INI_MAX_KEY_NAME_LENGTH | 64 by default | Maximum number of characters allowed in a key name |
INI_MAX_KEY_VALUE_LENGTH | INI_MAX_LINE_LENGTH by default | Maximum number of characters allowed in a key value |
INI_MAX_REPLACEMENT_TAG | 24 by default | Maximum number of characters allowed in a replacement tag |
INI_MAX_REPLACEMENT_TEXT | (INI_MAX_KEY_VALUE_LENGTH-3) by default | Maximum number of characters that are allowed in ReplacementText |
INI_FLOATING_POINT_PRECISION | 16 by default | Maximum number of characters required to store the largest and most precise float + 1 |
INI_INTEGER_DIGITS | 10 by default | Maximum number of characters required to store the largest integer + 1 |
INI_HEX_DIGITS | 8 by default | Maximum number of characters required to store the largest hexadecimal number + 1 |
INI_BIN_DIGITS | 33 by default | Maximum number of characters required to store the longest binary number + 1 |
INI_MAX_FUNCTION_NAME_LENGTH | 32 by default | Length of PAWN function identifiers(can be lesser than the maximum limit) |
INI_WRITE_FALSE_VALUE | "flase" by default | String to be used in WriteBool as well as ReadBool for false |
INI_WRITE_FALSE_VALUE_SIZE | 6 by default | Size of INI_WRITE_FALSE_VALUE string |
INI_WRITE_TRUE_VALUE | 32 by default | String to be used in WriteBool as well as ReadBool for true |
INI_WRITE_TRUE_VALUE_SIZE | "true" by default | Size of INI_WRITE_TRUE_VALUE string |
Liberal Mode:
This mode liberalizes the INI standard allowing bad INI files to be parsed without issuing any errors.Enabling this mode only affects the parser.It will slightly improve the performance of the parser.
List of changes from default mode:
- If white-spaces are not enabled then any section or key name containing space will be ignored instead of giving an error and halting the parser.You can enable whitespace along with LIBERAL Mode.
Code:[SECTION ONE] ;This section declaration will be ignored and treated as if it wasn't there key one = 123123 ; This line will be ignored
- Empty sections, invalid sections, invalid keys, invalid lines will be ignored
[code][] ;This line will be ignored
$$$ ;This line will be ignored - Section or key names can now contain symbols such as $,%,&,etc.They can be made up of anything even non graphical characters.
The following lines are valid:
Code:[$ection] k$ey=123123 a!b@c#d$e%f^g&h*i(j)k-l+=123123 ;The '=' will mean end of the key name
Tells the parser that the file is neatly formatted and it needn't do format checks.This will improve the efficiency of the parser by 30%-40% but decreases the versatility of the INI files.
In this mode the parser makes the following assumptions:
- The INI File follows the INI Standard mentioned in INI Specificiations
- No leading spaces before a section name
- No whitespace are found in section or key names until its enabled
- No terminal spaces in section or key names
- Terminated Section Tags
- Section and key names are valid
- No random lines(i.e: a line which is not a key or a section or a comment or a blank line)
- No warning will be given for empty keys
Example of a formatted INI:
Code:
key1=123123 ;No leading spaces [SECTION] ;no leading spaces here too key34=45356 key345=2342634 ;Comment lines are still allowed ;Blank lines are also allowed
Careful Mode:
This mode assumes that programmer is very careful.Tells the script to assume that no invalid handles or any such careless mistake will not happen.This will make negligible difference in performance of the script in this version.Just a useless feature right now in this version.
I strongly recommend this mode to be turned off since it is has negligible impact on the performance in the current release and humans are stupid and can never be perfect.
Opening/Closing Files & INI Handles
Just like a File Handle(File:file), eINI uses INI Handles(INI:ini).This is similar to the INI: tag used in y_ini.This is basically used to identify an INI File and also to distinguish between INI Handles,File Handles and normal variables.
To learn more about tags in PAWN, visit Scripting:tags
Creating an INI Handle is as simple as declaring a variable:
Code:
new INI:handle;
These are the basic functions:
Function | Description |
CreateINI | Creates an INI file for writing |
OpenINI | Opens an INI File for reading or writing or both depending on the mode argument passed |
CloseINI | Saves the INI file and invalidates the INI Handle |
IsValidHandle | Returns true if the handle is valid else false |
Definition:INI::CreateINI(const fname)
Parameters:fname takes the location along with the filename that is to be created
Returns:INI Handle (with INI:) for the newly created file or an error code
Remarks:The file is not physically created until CloseINI is called
Exceptions:
INI_ERR_FILE_ALREADY_EXISTS - The file already exists
INI_ERR_MAX_FILE_LIMIT - Maximum simultaneously operable files limit has been reached
Code:
new INI:handle = INI::CreateINI("config \\mysql.ini");
Definition:INI::OpenINI(const fname,mode=INI_READ_WRITE)
Parameters:
- fname takes the location along with the filename that is to be opened
- mode can take INI_READ_WRITE/INI_READ/INI_WRITE
Remarks:Use the mode parameter to enhance performance
Exceptions:
INI_ERR_FILE_DOES_NOT_EXIST - The file doesn't exist
INI_ERR_MAX_FILE_LIMIT - Maximum simultaneously operable files limit has been reached
Code:
new INI:handle = INI::OpenINI("config \\mysql.ini");
Suppose you are only writing to the file then do you think the parser needs to store the value of every key?
The answer is no because we won't need the values.So by setting the mode to INI_WRITE we tell the parser that we are only writing so parse only key and section names.Will improve performance to a great extent for large files.
Suppose you are only reading the file then do you think it is necessary to save the file?
The answer is no because you won't be making any changes to the file.
CloseINI
Definition:INI::CloseINI(INI:filehandle,bool:savebuffer=true)
Parameters:
- filehandle takes the INI handle which is to be closed
- savebuffer should be set to false if you do not want CloseINI to save the buffer to the file
Remarks:The file won't be saved and you will lose an INI Handle if CloseINI is not called
Exceptions:
INI_ERR_INVALID_HANDLE - An invalid handle was passed to CloseINI
INI_ERR_PARSING_FAILED - The file couldn't be parsed.This would only happen if the file was opened, not used and there is a syntax error in the file.
Code:
INI::CloseINI(handle); INI::CloseINI(handle,false);
Definition:INI::IsValidHandle(INI:handle)
Parameters:INI Handle that has to be checked for validity
Returns:True if the given INI Handle is valid else false
Remarks:Primarily used to check if OpenINI or CreateINI was successful
[code]new INI:handle = INI::OpenINI("sql.ini");
if(INI::IsValidHandle(handle))
{
//Safe to use the handle
}
else print("Couldn't load sql configuration");
[/code
eINI Log File
By default, eINI prints all warnings/errors/notices directly into the server console. You can enable logging using file by defining INI_USE_LOG_FILE before including eINI.
The log file is named as "eini_log.txt". You can find the log file in scriptfiles folder.
How the parser works(Advanced & Optional)
The parser checks each and every line and stores the information regarding the line in an user-defined enumerator array.It uses linked lists to the store the lines.Once the parser identifies the type of the line, it creates a key or a section element in an user-defined enumerator array of keys or sections respectively.The keys are also stored in linked lists.Each section and key is given an id based on the segment-offset method.
Segment-Offset Method:
A segment is an index or an address which indicates the start of a region of memory and offset is also an index or an address which tells how far the variable from the segment is situated in the memory.
If you have had a glimpse through the include, you would have probably noticed these
Code:
static stock INI_Line[INI_MAX_MULTI_FILES*INI_MAX_LINES][E_INI_LINE]; static stock INI_Section[INI_MAX_MULTI_FILES*INI_MAX_SECTIONS][E_INI_SECTION]; static stock INI_Key[INI_MAX_MULTI_FILES*INI_MAX_KEYS][E_INI_KEY];
For nth file, INI_MAX_KEYS*(n-1) to INI_MAX_KEYS*n belongs to the nth INI Handle.
Now to access a key of the file, we would need an offset.The offset indicates how far away from the segment the key is.
Lets take an example:
Code:
[SECTION1] key1=123 key2=4534 [SECTION2] key3=23423 . . .
This is how eINI assigns key ids.
Now to get the name of the key of key 'n' of this file, we use the following formula
Code:
INI_Key[segment + offset][E_INI_KEY_name]; INI_Key[INI_MAX_KEYS + n][E_INI_KEY_name] INI_Key[INI_MAX_KEYS + 2][E_INI_KEY_name] //Gets the name of key3
So we would come across two terms while using eINI namely relative keyid/sectionid and absolute keyid/sectionid.
This is exactly same as segment and offset.
The parser assigns IDs linearly.The first key of the file gets offset 0,second gets offset 1 and so on.Similarly the first section gets an offset of 1, second gets an offset of 2 and so on.Where did the offset 0 go?Its reserved for global section irrespective if there is any global key or not(global keys could be added later).
Why do we need to know this?
You can exploit the way the parser assigns IDs linearly to improve the performance of the script.Instead of asking eINI to search and find the section or the key, you could directly tell the Read or Write functions the keyids and sectionids knowing the file already which would improve the performance to a large extent(we would avoid so many strcmps for finding sections and keys). We'll see more examples later in the Reading and Writing Sections.
Example:
Code:
key1=asd [SEC1] key1=asdasd key2=34234 [SEC2] a=123 b=234 ;some gibberish..asdasd.sd.ad.as.da.sd.sad c=345 [SEC3] [SEC4] note=the previous section was empty ;random comment
key1 = 0 (Global Key, therefore has a sectionid 0)
key1 = 1(key1 of SEC1)
key2 = 2
a = 3
b= 4
c = 5
Relative Section ID Assignments:
Global Section = 0 (irrespective of if there is any element or not)
SEC1 = 1
SEC2 = 2
SEC3 = 3
SEC4 = 4
Reading
eINI supports reading by calling reading functions individually as well as dynamic reading/loading(which is similar to y_ini).We will look into both of them separately.
Static Loading
eINI provides functions to read strings,integers,floats,hexadecimal numbers,binary numbers,arrays,enumerators.It also provides lazy programmers with a function which can be used to read multiple keys simultaneously at the cost efficiency.
These are the functions that can be used to obtain values of the keys.
Function | Description |
ReadString | Gets the value of a key as a string |
ReadBool | Used to read keys with Boolean values |
ReadInteger | Gets the value of a key as an integer |
ReadFloat | Gets the value of a key has a floating point number |
ReadHex | Reads a value in hexadecimal format and gets an integer equivalent for it |
ReadBinary | Reads a value in binary format and gets an integer equivalent for it |
ReadArray | Reads an array |
ReadEnum | Reads an enum(fills the whole enum with data) |
ReadFormat | For lazy programmers who want to read multiple keys in one go |
Gets the value of a key as a string.
Definition:INI::ReadString(INI:filehandle,result[],const key[],const section[]="",keyid=-1,sectionid=-1,result_size=sizeof(result),section_size=sizeof(s ection),key_size=sizeof(key))
Parameters:
- filehandle takes the INI Handle on which to operate
- result is the array where the read string has to be stored
- key is the name of the key
- section is the name of the section where the key has to be searched
- keyid is the relative key id if it is known
- sectionid is the relative section id if it is known
- result_size is the size of the result parameter
- section_size is the size of the section parameter
- key_size is the size of the key parameter
Remarks:Use keyid parameter when ever possible or at least sectionid parameter if known to improve performance.
Exceptions:
INI_KEY_NOT_FOUND - The key whose value was requested was not found in the file
INI_ERR_INVALID_HANDLE - The INI Handle passed is invalid
INI_ERR_PARSING_FAILED - The parsing of the file failed
Code:
new password[64]; INI::ReadString(handle,password,"pass","login_cred"); //Searches for pass in login_cred INI::ReadString(handle,password,"pass"); //Searches for pass in the global section INI::ReadString(handle,password,"pass","",-1,sectionid); //Searches for pass in section with id sectionid INI::ReadString(handle,password,"","",1); //Gets the value of key with keyid 1
This function interprets the value of the given key and tells the Boolean value associated with it.If the value is equal to '1' or 'true' then the variable parameter will be set to true.If the value is equal to '0' or 'false' then the variable parameter is set to false.
Definition:INI::ReadBool(INI:filehandle,&bool:variable,const key[]="",const section[]="",keyid=-1,sectionid=-1,section_size=sizeof(section),key_size=sizeof(key ))
Parameters:
- filehandle takes the INI Handle on which to operate
- variable is the boolean variable where the result has to be stored
- key is the name of the key
- section is the name of the section where the key has to be searched
- keyid is the relative key id if it is known
- sectionid is the relative section id if it is known
- section_size is the size of the section parameter
- key_size is the size of the key parameter
Remarks:Use keyid parameter when ever possible or at least sectionid parameter if known to improve performance.
Exceptions:
INI_KEY_NOT_FOUND - The key whose value was requested was not found in the file
INI_ERR_INVALID_HANDLE - The INI Handle passed is invalid
INI_ERR_PARSING_FAILED - The parsing of the file failed
INI_ERR_INVALID_BOOL - The value cannot be interpreted (value is not acceptable)
Code:
new bool:rcon_password_enabled; INI::ReadBool(handle,rcon_password_enabled,"ispass","login_cred"); //Searches for ispass in login_cred INI::ReadBool(handle,rcon_password_enabled,"ispass"); //Searches for ispass in the global section INI::ReadBool(handle,rcon_password_enabled,"ispass","",-1,sectionid); //Searches for ispass in section with id sectionid INI::ReadBool(handle,rcon_password_enabled,"","",1); //Gets the value of key with keyid 1
Assume that we are working on this file
Code:
[SECTION1] key1=true key2=false key3=1 key4=0 key5=not a bool
ReadBool will set variable to true when key1 is read
ReadBool will set variable to false when key2 is read
ReadBool will set variable to true when key3 is read
ReadBool will set variable to false when key4 is read
ReadBool will not touch the variable and will return that it is an invalid bool
ReadInteger
Gets the integral value of a key
Definition:INI::ReadInteger(INI:filehandle,&variable,const key[]="",const section[]="",keyid=-1,sectionid=-1,section_size=sizeof(section),key_size=sizeof(key ))
Parameters:
- filehandle takes the INI Handle on which to operate
- variable is the variable where the result has to be stored
- key is the name of the key
- section is the name of the section where the key has to be searched
- keyid is the relative key id if it is known
- sectionid is the relative section id if it is known
- section_size is the size of the section parameter
- key_size is the size of the key parameter
Remarks:
- Use keyid parameter when ever possible or at least sectionid parameter if known to improve performance.
- variable will be set to zero if the value associated with the key is not numeric
INI_KEY_NOT_FOUND - The key whose value was requested was not found in the file
INI_ERR_INVALID_HANDLE - The INI Handle passed is invalid
INI_ERR_PARSING_FAILED - The parsing of the file failed
Code:
new var; INI::ReadInteger(handle,var,"int","nums"); //Searches for int in nums INI::ReadInteger(handle,var,"int"); //Searches for int in the global section INI::ReadInteger(handle,var,"int","",-1,sectionid); //Searches for int in section with id sectionid INI::ReadInteger(handle,var,"","",1); //Gets the value of key with keyid 1
Gets a floating point number from the key
Definition:INI::ReadFloat(INI:filehandle,&Float:variable,cons t key[]="",const section[]="",keyid=-1,sectionid=-1,section_size=sizeof(section),key_size=sizeof(key ))
Parameters:
- filehandle takes the INI Handle on which to operate
- variable is the variable where the result has to be stored
- key is the name of the key
- section is the name of the section where the key has to be searched
- keyid is the relative key id if it is known
- sectionid is the relative section id if it is known
- section_size is the size of the section parameter
- key_size is the size of the key parameter
Remarks:
- Use keyid parameter when ever possible or at least sectionid parameter if known to improve performance.
- Some precision will be lost while the key value which is read as string is converted to a float
INI_KEY_NOT_FOUND - The key whose value was requested was not found in the file
INI_ERR_INVALID_HANDLE - The INI Handle passed is invalid
INI_ERR_PARSING_FAILED - The parsing of the file failed
Code:
new var; INI::ReadFloat(handle,var,"float","nums"); //Searches for float in nums INI::ReadFloat(handle,var,"float"); //Searches for float in the global section INI::ReadFloat(handle,var,"float","",-1,sectionid); //Searches for float in section with id sectionid INI::ReadFloat(handle,var,"","",1); //Gets the value of key with keyid 1
Gets the integral value of a key where the value is expressed in hexadecimal notation
Definition:INI::ReadHex(INI:filehandle,&variable,const key[]="",const section[]="",keyid=-1,sectionid=-1,section_size=sizeof(section),key_size=sizeof(key ))
Parameters:
- filehandle takes the INI Handle on which to operate
- variable is the variable where the result has to be stored
- key is the name of the key
- section is the name of the section where the key has to be searched
- keyid is the relative key id if it is known
- sectionid is the relative section id if it is known
- section_size is the size of the section parameter
- key_size is the size of the key parameter
Remarks:
- Use keyid parameter when ever possible or at least sectionid parameter if known to improve performance.
- variable will be set to the integral value of the hex value until an unknown hex digit is encountered or end of the value
INI_KEY_NOT_FOUND - The key whose value was requested was not found in the file
INI_ERR_INVALID_HANDLE - The INI Handle passed is invalid
INI_ERR_PARSING_FAILED - The parsing of the file failed
Code:
new var; INI::ReadHex(handle,var,"inth","nums"); //Searches for inth in nums INI::ReadHex(handle,var,"int"); //Searches for inth in the global section INI::ReadHex(handle,var,"int","",-1,sectionid); //Searches for inth in section with id sectionid INI::ReadHex(handle,var,"","",1); //Gets the value of key with keyid 1
Gets the integral value of a key where the value is expressed in binary notation
Definition:INI::ReadBinary(INI:filehandle,&variable,const key[]="",const section[]="",keyid=-1,sectionid=-1,section_size=sizeof(section),key_size=sizeof(key ))
Parameters:
- filehandle takes the INI Handle on which to operate
- variable is the variable where the result has to be stored
- key is the name of the key
- section is the name of the section where the key has to be searched
- keyid is the relative key id if it is known
- sectionid is the relative section id if it is known
- section_size is the size of the section parameter
- key_size is the size of the key parameter
Remarks:
- Use keyid parameter when ever possible or at least sectionid parameter if known to improve performance.
- variable will be set to the integral value of the hex value until an unknown binary digit is encountered or end of the value
INI_KEY_NOT_FOUND - The key whose value was requested was not found in the file
INI_ERR_INVALID_HANDLE - The INI Handle passed is invalid
INI_ERR_PARSING_FAILED - The parsing of the file failed
Code:
new var; INI::ReadBinary(handle,var,"intb","nums"); //Searches for intb in nums INI::ReadBinary(handle,var,"intb"); //Searches for intb in the global section INI::ReadBinary(handle,var,"intb","",-1,sectionid); //Searches for intb in section with id sectionid INI::ReadBinary(handle,var,"","",1); //Gets the value of key with keyid 1
Parses an array key and fills the given array with the correct values.
Definition:INI::ReadArray(INI:filehandle,array[],const key[]="",const section[]="",keyid=-1,sectionid=-1,array_size=sizeof(array),section_size=sizeof(sec tion),key_size=sizeof(key))
Parameters:
- filehandle takes the INI Handle on which to operate
- array where the value has to be stored
- key is the name of the key
- section is the name of the section where the key has to be searched
- keyid is the relative key id if it is known
- sectionid is the relative section id if it is known
- array_size is the size of the section parameter
- section_size is the size of the section parameter
- key_size is the size of the key parameter
Remarks:
- Use keyid parameter when ever possible or at least sectionid parameter if known to improve performance.
- Filling of the array will stop if an exception occurs
INI_KEY_NOT_FOUND - The key whose value was requested was not found in the file
INI_ERR_INVALID_HANDLE - The INI Handle passed is invalid
INI_ERR_PARSING_FAILED - The parsing of the file failed
Code:
new var[5]; INI::ReadArray(handle,var,"arr","nums"); //Searches for arr in nums INI::ReadArray(handle,var,"arr"); //Searches for arr in the global section INI::ReadArray(handle,var,"arr","",-1,sectionid); //Searches for arr in section with id sectionid INI::ReadArray(handle,var,"","",1); //Gets the value of key with keyid 1
Parses an enum key and loads an enum array.
Definition:INI::ReadEnum(INI:filehandle,enum_array[],enum_unit_size,const key[]="",const section[]="",keyid=-1,sectionid=-1,section_size=sizeof(section),key_size=sizeof(key ))
Parameters:
- filehandle takes the INI Handle on which to operate
- array where the value has to be stored
- enum_unit_size is the size of the enum
- key is the name of the key
- section is the name of the section where the key has to be searched
- keyid is the relative key id if it is known
- sectionid is the relative section id if it is known
- section_size is the size of the section parameter
- key_size is the size of the key parameter
Remarks:
- Use keyid parameter when ever possible or at least sectionid parameter if known to improve performance.
- Filling of the array will stop if an exception occurs
INI_KEY_NOT_FOUND - The key whose value was requested was not found in the file
INI_ERR_INVALID_HANDLE - The INI Handle passed is invalid
INI_ERR_PARSING_FAILED - The parsing of the file failed
Code:
new var[5][ENUM]; INI::ReadEnum(handle,var[0],sizeof(var[]),"arr","nums"); //Searches for arr in nums INI::ReadEnum(handle,var[1],sizeof(var[]),"arr"); //Searches for arr in the global section INI::ReadEnum(handle,var[2],sizeof(var[]),"arr","",-1,sectionid); //Searches for arr in section with id sectionid INI::ReadEnum(handle,var[3],sizeof(var[]),"","",1); //Gets the value of key with keyid 1
Read multiple keys in one line at the cost of efficiency.
Definition:INI::ReadFormat(INI:filehandle,sectionid,const format[],{Float,_}:...)
Parameters:
- filehandle takes the INI Handle on which to operate
- sectionid takes the relative section id
- format must give the type of data of the section in key order
- key1,result1,key2,result2....
Remarks:
- This function is very slow, so try to avoid using this function
Specifier | Symbol | Data Type |
Integer Data Type | d or i | Calls ReadInteger to get the integral value |
String Data Type | s | Calls ReadString directly |
Float Data Type | f | Calls ReadFloat to get the value of the key |
Binary Data Type | b | Calls ReadBinary to parse the key |
Hexadecimal Data Type | X or x | Calls ReadHex to parse the key |
Boolean Data Type | T or F | Calls ReadBool to parse the key |
Code:
;Example INI [SECTION1] a=5.4 b=str c=0xFF d=234234
Code:
new var1[10],Float:var2,var3,var4; INI::ReadFormat(handle,1,"fsxi","a",var2,"b",var1,"c",var3,"d",var4);
Dynamic Loading is the other method to read keys.This system is similar to y_ini.The parser calls a function each time a key is parsed. There are different ways of dynamic loading which will be explained in this section. Dynamic Loading also provides an option to broadcast data across all scripts which means you can share the contents of the INI file with different scripts without having to parse the file again in that script.
ParseINI
Parses the INI File and caches keys and sections
Definition:INI::ParseINI(INI:filehandle,const LoadFunction[] = "",bool:dynamic=false,extra=0,bool:pass_extra=fals e,bool:func_with_key=false);
Parameters:
- filehandle is the INI Handle which should be parsed
- LoadFunction is the function name which should be called for dynamic loading
- dynamic should be set to true for Dynamic Loading else false for just parsing
- extra is the extra information that has to be passed to the Load Function
- pass_extra tells if the extra parameter is used
- func_with_key If false,first occurrence of %s in LoadFunction will be replaced with section name only
If true,the first two occurrences of %s in LoadFunction will be replaced with section
name followed by key name respectively - tradition_func If true the section name and key name will be passed as arguments to the LoadFunction. The LoadFunction will be called as it is without any modifications. (false by default)
- broadcast If true the data will be sent to all running scripts.If set to false, only the local script
callbacks will be called. (false by deafult)
Returns 0 for normal execution
It also returns 0 if file was not meant to be parsed(in case of a new file)
Or an error code
Exceptions:
INI_ERR_INVALID_HANDLE - Invalid File Handle
INI_ERR_SYNTAX - The INI file does not meet the required format
Code:
INI::ParseINI(myhandle); //Normal Parsing INI::ParseINI(myhandle,"Load_%s",true); //Parsing with dynamic loading.The %s will be replaced with the section name INI::ParseINI(myhandle,"Load_%s",true,playerid,true); //Parsing with dynamic loading with extra parameter INI::ParseINI(myhandle,"Load_%s_%s",true,random_number,false,true); //Parsing with dynamic loading.The %s will be replaced with section and key name INI::ParseINI(myhandle,"Load_%s_%s",true,playerid,true,true); //Parsing with dynamic loading with extra paramter INI::ParseINI(myhandle,"LoadFunction",true,playerid,true,false,true); //Parsing with traditional dynamic loading with extra paramter INI::ParseINI(myhandle,"LoadFunction",true,playerid,true,false,true,true); //Parsing with traditional dynamic loading and broadcast across all scripts
To understand better, lets take an example.Let the text given below be our example INI File.
Code:
key=234567 [SECTION1] asd=23 eqwe=123 eqwaxe=88 [SECTION2] asd=2 iii=66
The Load Function will be called 6 times as there are 6 keys.
To read all the keys, we would need a total of 3 functions.
Code:
//If you are not using the extra parameter public MyFunc_(const key[],const value[]) //For global keys { if(!strcmp(key,"key")) MyVar=strval(value); } public MyFunc_SECTION1(const key[],const value[]) //Called three times { if(!strcmp(key,"asd")) MyVar=strval(value); } public MyFunc_SECTION2(const key[],const value[]) //Called two times { //Do whatever you want with the key } //If you are using the extra parameter public MyFunc_(const key[],const value[],extra); //For global keys public MyFunc_SECTION1(const key[],const value[],extra); //Called for asd,eqwe,eqwaxe public MyFunc_SECTION2(const key[],const value[],extra); //Called for asd,iii
If you are using func_with_key then the second occurrence of '%s' will be replaced with the key name.For example, if "MyFunc_%s_%s" was passed to ParseINI as Argument then "MyFunc_SECTION_KEY" will be called for each key.
Traditional way of dynamic reading passes the key and the section name as arguments to the Load Function.
Code:
public LoadFunction(const key[],const section[],const value[]);
Escape Characters & Replacements
The escape characters present in a string in an ini file are not replaced when it is read by the server.So you'll have to do it manually.But eINI makes your work easier by providing ready-made functions which will do the replacement of escape characters for you.
Lets look at an example to understand what I mean:
Code:
[SAMP] samp=This is SA-MP\\0.3.7\nDownload at sa-mp.com
"This is SA-MP\\0.3.7\nDownload at sa-mp.com"
You won't get the expected output, i.e:
"This is SA-MP\0.3.7
Download at sa-mp.com"
You won't get that output because '\n' or any other escape sequences are not replaced with their appropriate ASCII Value.
This can be easily fixed with the help of Replace Function provided by eINI.
Replace
Replaces escape characters with their real ASCII Value.
Definition:INI::Replace(const src[],dest[],const ReplacementFunction[]="",extra=0,bool:pass_extra=false,sz=sizeof(src),s z_dest=sizeof(dest),sz_rf=sizeof(ReplacementFuncti on))
Parameters:
- src takes the source string
- dest is the array where the result has to be stored
- ReplacementFunction is the function name
- extra is the extra information that has to be passed to the replacement function
- pass_extra tells if the extra parameter is used
- sz is the size of the source string
- sz_dest is the size of the destination string
- sz_rf is the size of the replacement function string
You cannot directly use ';' or '#' or characters that are sensitive to the parser directly.Instead you must use the appropriate escape character.
List of valid escape characters:
Name | Escape Character | Data Type |
Backward Slash | \\ | Replaces '\\' with a single slash |
Null | \0 | Adds a null character when '\0' is encountered |
Tab | \t | Adds a tab space |
Carriage Return | \r | Adds a carriage reuturn |
New Line | \n | Adds a new line character |
Semi-colon | \; | Replaces '\;' with ';' | Hash | \# | Replaces '\#' with '#' | Square Brackets | \[ or \] | Replaces '\[' or '\]' with '[' and ']' respectively |
Code:
new res[128]; INI::Replace("This a \n TEST LINE slash \\ SEMI \;",res);
Replace has another amazing feature that allows to have your own escape strings.All custom escape sequences must be enclosed within [THE ESCAPE SEQUENCE NAME]. The function will parse the line and call your Replacement Function where you'll decide what to substitute(the string set using SetReplacementText) in place of that escape sequence.
Lets take an example to understand better:
Code:
str = "Password must have [MAX] to [MIN] characters" Replace(str,dest,"MyFunc"); public MyFunc(const text[]) { if(!strcmp(text,"MAX")) { new str[] = "32"; INI::SetReplacementText(str); return 1; } if(!strcmp(text,"MIN")) { new str[] = "5"; INI::SetReplacementText(str); return 1; } return 0; }
"Password must have 20 to 5 characters"
What you return in the ReplacementFunction matters.The replacement will be carried out only if your Replacement Function returns a non-zero integer.Returning 0 means that eINI won't carry out the replacement and will replace it with "[]".
SetReplacementText
Will set the replacement text
Definition:INI::SetReplacementText(const str[])
Parameters:
- str takes the string
Code:
new str[] = "replace text"; INI::SetReplacementText(str); INI::SetReplacementText("text"); //This is not allowed
The extra parameter is passed to the replacement function and it optional.
Code:
public MyFunc(extra,const text[])
Code:
Replace(str,dest,"MyFunc",playerid,true);
eINI provides lots of different methods to write keys to files efficiently.It stores all the new values in a buffer and writes them all at once instead of having to open a file every time to write something.
These are the functions that eINI provides for writing data to files.
Function | Description |
WriteString | Writes a string to the file |
WriteBool | Writes a boolean value |
WriteInteger | Writes an integer value |
WriteFloat | Writes a floating point number value |
WriteHex | Writes an integer in hexadecimal notation |
WriteBinary | Writes an integer in binary notation |
WriteArray | Writes an array |
WriteEnum | Writs an enum unit |
WriteFormat | For lazy programmers who want to write multiple keys in one go |
Writes a string
Definition:INI::WriteString(INI:filehandle,const data[],const key[],const section[],keyid=-1,sectionid=-1,data_size=sizeof(data),section_size=sizeof(secti on),key_size=sizeof(key))
Parameters:
- filehandle takes the INI Handle on which to operate
- data is the string that is to be saved
- key is the name of the key
- section is the name of the section where the key resides.
- keyid is the relative key id if it is known
- sectionid is the relative section id if it is known
- data_size is the size of the result parameter
- section_size is the size of the section parameter
- key_size is the size of the key parameter
Remarks:Use keyid parameter when ever possible or at least sectionid parameter if known to improve performance.
Exceptions:
INI_ERR_INVALID_HANDLE - The INI Handle passed is invalid
INI_KEY_NOT_FOUND - Key with the given keyid doesn't exist
INI_ERR_PARSING_FAILED - Parsing failed
Code:
INI::WriteString(handle,"this is not my password","pass","login_cred"); //Searches for pass in login_cred,if not found it will be created INI::WriteString(handle,"this is not my password","pass"); //Searches for pass in the global section if not found,it will be created INI::WriteString(handle,"this is not my password","pass","",-1,sectionid); //Searches for pass in section with id sectionid, if not found it will be created INI::WriteString(handle,"this is not my password","","",1); //Writes the data to the key with keyid 1
Checks for falsity of the boolean variable passed and writes its equivalent to the key.
Definition:INI::WriteBool(INI:filehandle,bool:variable,const key[],const section[],keyid=-1,sectionid=-1,section_size=sizeof(section),key_size=sizeof(key ))
Parameters:
- filehandle takes the INI Handle on which to operate
- variable is the boolean variable
- key is the name of the key
- section is the name of the section where the key resides
- keyid is the relative key id if it is known
- sectionid is the relative section id if it is known
- section_size is the size of the section parameter
- key_size is the size of the key parameter
Remarks:Use keyid parameter when ever possible or at least sectionid parameter if known to improve performance.
Exceptions:
INI_ERR_INVALID_HANDLE - The INI Handle passed is invalid
INI_KEY_NOT_FOUND - Key with the given keyid doesn't exist
INI_ERR_PARSING_FAILED - Parsing failed
Code:
INI::WriteBool(handle,rcon_password_enabled,"ispass","login_cred"); //Searches for ispass in login_cred, will create the key if not found INI::WriteBool(handle,rcon_password_enabled,"ispass"); //Searches for ispass in the global section,will create the key if not found INI::WriteBool(handle,rcon_password_enabled,"ispass","",-1,sectionid); //Searches for ispass in section with id sectionid,will create the key if not found INI::WriteBool(handle,rcon_password_enabled,"","",1); //Write the value to the key with id keyid
Writes an integer
Definition:INI::WriteInteger(INI:filehandle,variable,const key[],const section[],keyid=-1,sectionid=-1,section_size=sizeof(section),key_size=sizeof(key ))
Parameters:
- filehandle takes the INI Handle on which to operate
- variable is the integer that has to be saved
- key is the name of the key
- section is the name of the section where the key resides
- keyid is the relative key id if it is known
- sectionid is the relative section id if it is known
- section_size is the size of the section parameter
- key_size is the size of the key parameter
Remarks:Use keyid parameter when ever possible or at least sectionid parameter if known to improve performance.
Exceptions:
INI_ERR_INVALID_HANDLE - The INI Handle passed is invalid
INI_KEY_NOT_FOUND - Key with the given keyid doesn't exist
INI_ERR_PARSING_FAILED - Parsing failed
Code:
INI::WriteInteger(handle,var,"int","nums"); //Searches for int in nums, will create the key if it doesn't exist INI::WriteInteger(handle,var,"int"); //Searches for int in the global section, will create the key if it doesn't exist INI::WriteInteger(handle,var,"int","",-1,sectionid); //Searches for int in section with id sectionid, will create the key if it doesn't exist INI::WriteInteger(handle,var,"","",1); //Writes the value to the key with keyid 1
Writs a float to the key
Definition:INI::WriteFloat(INI:filehandle,Float:variable,cons t key[],const section[],keyid=-1,sectionid=-1,section_size=sizeof(section),key_size=sizeof(key ))
Parameters:
- filehandle takes the INI Handle on which to operate
- variable is the where the float to be saved is stored
- key is the name of the key
- section is the name of the section where the key resides
- keyid is the relative key id if it is known
- sectionid is the relative section id if it is known
- section_size is the size of the section parameter
- key_size is the size of the key parameter
Remarks:Use keyid parameter when ever possible or at least sectionid parameter if known to improve performance.
Exceptions:
INI_ERR_INVALID_HANDLE - The INI Handle passed is invalid
INI_KEY_NOT_FOUND - Key with the given keyid doesn't exist
INI_ERR_PARSING_FAILED - Parsing failed
Code:
INI::WriteFloat(handle,var,"float","nums"); //Searches for float in nums, will create the key if it doesn't exist INI::WriteFloat(handle,var,"float"); //Searches for float in the global section, will create the key if it doesn't exist INI::WriteFloat(handle,var,"float","",-1,sectionid); //Searches for float in section with id sectionid, will create the key if it doesn't exist INI::WriteFloat(handle,var,"","",1); //Writes the value to the key with keyid 1
Writs an integer in hexadecimal notation
Definition:INI::WriteHex(INI:filehandle,variable,const key[],const section[],keyid=-1,sectionid=-1,section_size=sizeof(section),key_size=sizeof(key ));
Parameters:
- filehandle takes the INI Handle on which to operate
- variable is the integer that has to be saved in hexadecimal notation
- key is the name of the key
- section is the name of the section where the key resides
- keyid is the relative key id if it is known
- sectionid is the relative section id if it is known
- section_size is the size of the section parameter
- key_size is the size of the key parameter
Remarks:Use keyid parameter when ever possible or at least sectionid parameter if known to improve performance.
Exceptions:
INI_ERR_INVALID_HANDLE - The INI Handle passed is invalid
INI_KEY_NOT_FOUND - Key with the given keyid doesn't exist
INI_ERR_PARSING_FAILED - Parsing failed
Code:
new var = 123213; INI::WriteHex(handle,var,"inth","nums"); //Searches for inth in nums, will create the key if it doesn't exist INI::WriteHex(handle,var,"int"); //Searches for inth in the global section, will create the key if it doesn't exist INI::WriteHex(handle,var,"int","",-1,sectionid); //Searches for inth in section with id sectionid, will create the key if it doesn't exist INI::WriteHex(handle,var,"","",1); //Writes the value to the key with keyid 1
Writes an integer value to a key in binary form
Definition:INI::WriteBinary(INI:filehandle,variable,const key[],const section[],keyid=-1,sectionid=-1,section_size=sizeof(section),key_size=sizeof(key ))
Parameters:
- filehandle takes the INI Handle on which to operate
- variable is the integer that has to be saved in binary form
- key is the name of the key
- section is the name of the section where the key resides
- keyid is the relative key id if it is known
- sectionid is the relative section id if it is known
- section_size is the size of the section parameter
- key_size is the size of the key parameter
Remarks:Use keyid parameter when ever possible or at least sectionid parameter if known to improve performance.
Exceptions:
INI_ERR_INVALID_HANDLE - The INI Handle passed is invalid
INI_KEY_NOT_FOUND - Key with the given keyid doesn't exist
INI_ERR_PARSING_FAILED - Parsing failed
Code:
new var = 123123; INI::WriteBinary(handle,var,"intb","nums"); //Searches for intb in nums, will create the key if it doesn't exist INI::WriteBinary(handle,var,"intb"); //Searches for intb in the global section, will create the key if it doesn't exist INI::WriteBinary(handle,var,"intb","",-1,sectionid); //Searches for intb in section with id sectionid, will create the key if it doesn't exist INI::WriteBinary(handle,var,"","",1); //Writes the value to the key with keyid 1
Writes an array
Definition:INI::WriteArray(INI:filehandle,array[],const key[]="",const section[]="",keyid=-1,sectionid=-1,array_size=sizeof(array),section_size=sizeof(sec tion),key_size=sizeof(key))
Parameters:
- filehandle takes the INI Handle on which to operate
- array is the array which will be saved
- key is the name of the key
- section is the name of the section where the key resides
- keyid is the relative key id if it is known
- sectionid is the relative section id if it is known
- array_size is the size of the section parameter
- section_size is the size of the section parameter
- key_size is the size of the key parameter
Remarks:Use keyid parameter when ever possible or at least sectionid parameter if known to improve performance.
Exceptions:
INI_ERR_INVALID_HANDLE - The INI Handle passed is invalid
INI_KEY_NOT_FOUND - Key with the given keyid doesn't exist
INI_ERR_PARSING_FAILED - Parsing failed
Code:
new var[5] = {1,2,3,4,5}; INI::WriteArray(handle,var,"arr","nums"); //Searches for arr in nums, will create the key if it doesn't exist INI::WriteArray(handle,var,"arr"); //Searches for arr in the global section, will create the key if it doesn't exist INI::WriteArray(handle,var,"arr","",-1,sectionid); //Searches for arr in section with id sectionid, will create the key if it doesn't exist INI::ReadArray(handle,var,"","",1); //Writes the value to the key with keyid 1
Writes an enum element to the file
Definition:INI::WriteEnum(INI:filehandle,enum_array[],enum_unit_size,const key[]="",const section[]="",keyid=-1,sectionid=-1,section_size=sizeof(section),key_size=sizeof(key ))
Parameters:
- filehandle takes the INI Handle on which to operate
- enum_array whose data has to be saved
- enum_unit_size is the size of the enum
- key is the name of the key
- section is the name of the section where the key resides
- keyid is the relative key id if it is known
- sectionid is the relative section id if it is known
- section_size is the size of the section parameter
- key_size is the size of the key parameter
Remarks:Use keyid parameter when ever possible or at least sectionid parameter if known to improve performance.
Exceptions:
INI_ERR_INVALID_HANDLE - The INI Handle passed is invalid
INI_KEY_NOT_FOUND - Key with the given keyid doesn't exist
INI_ERR_PARSING_FAILED - Parsing failed
Code:
//new var[MAX_PLAYERS][P_ENUM]; INI::WriteEnum(handle,var[0],sizeof(var[]),"arr","nums"); //Searches for arr in nums, will create the key if it doesn't exist INI::WriteEnum(handle,var[1],sizeof(var[]),"arr"); //Searches for arr in the global section, will create the key if it doesn't exist INI::WriteEnum(handle,var[2],sizeof(var[]),"arr","",-1,sectionid); //Searches for arr in section with id sectionid, will create the key if it doesn't exist INI::WriteEnum(handle,var[3],sizeof(var[]),"","",1); //Gets the value of key with keyid 1
Write multiple keys in one line at the cost of efficiency.
Definition:INI::WriteFormat(INI:filehandle,sectionid,const format[],{Float,_}:...)
Parameters:
- filehandle takes the INI Handle on which to operate
- sectionid takes the relative section id
- format must give the type of data of the section in key order
- data1,key1,data2,key2,....
Remarks:
- This function is very slow, so try to avoid using this function
Specifier | Symbol | Data Type |
Integer Data Type | d or i | Calls WriteInteger to save |
String Data Type | s | Calls WriteString to save |
Float Data Type | f | Calls WriteFloat to save |
Binary Data Type | b | Calls WriteBinary to save the key |
Hexadecimal Data Type | X or x | Calls WriteHex to save the key |
Boolean Data Type | T or F | Calls WriteBool to save the key |
Code:
;Example INI [SECTION1] a=5.4 b=str c=0xFF
Code:
INI::WriteFormat(handle,1,"fsxi",2.5,"a","Awesome","b",15,"c",23123,"d");
Code:
;Resultant INI [SECTION1] a=2.5 b=Awesome c=0xF d=23123 ;created this just now
eINI has some more functions which will be discussed here.
List of Miscellaneous Functions:
Function | Description |
DeleteSection | Delete an entire section |
DeleteKey | Delete a key |
GetSectionID | Get relative section ID from section name |
GetKeyID | Get relative key ID from key name |
GetSectionName | Get Section Name from relative section id |
GetKeyName | Get Key Name from relative key id |
WriteBuffer | Saves the buffer to the file |
DumpINI | Dumps the contents of a file in the Server Window |
Delete an entire section
Definition:INI::DeleteSection(INI:filehandle,const section[]="",sectionid=-1,section_size=sizeof(section))
Parameters:
- filehandle takes the INI Handle on which to operate
- section is the name of the section that should be deleted
- sectionid is the relative section id if it is known
- section_size is the size of the section parameter
Exceptions:
INI_ERR_INVALID_HANDLE - Invalid INI Handle was passed to the function
INI_SECTION_NOT_FOUND - Section does not exist
INI_ERR_INVALID_ID - Invalid Section ID
Code:
new var = 123123; INI::DeleteSection(handle,"DELETEME"); //Delete DELETEME INI::DeleteSection(INI:filehandle,"",2); //Delete Section with section id 2
Deletes a key
Definition:INI::DeleteKey(INI:filehandle,const key[],const section[]="",keyid=-1,sectionid=-1,key_size=sizeof(key),section_size=sizeof(section ));
Parameters:
- filehandle takes the INI Handle on which to operate
- key is the name of the key that has to be deleted
- section is the name of the section where the key resides
- keyid is the relative key id if it is know
- sectionid is the relative section id if it is known
- key_size is the size of the key parameter
- section_size is the size of the section parameter
Exceptions:
INI_ERR_INVALID_HANDLE - Invalid INI Handle was passed to the function
INI_KEY_NOT_FOUND - Key does not exist
INI_ERR_INVALID_ID - Invalid Section ID
Code:
INI::DeleteKey(handle,"DELKEY","SEC"); INI::DeleteKey(handle,"DELKEY","",-1,2); INI::DeleteKey(handle,"","",2); INI::DeleteKey(handle,"DELKEY","");
Get relative section id from section name
Definition:INI::GetSectionID(INI:filehandle,const section[],section_size=sizeof(section))
Parameters:
- filehandle takes the INI Handle on which to operate
- section is the name of the section
- section_size is the size of the section parameter
Exceptions:
INI_ERR_INVALID_HANDLE - Invalid INI Handle was passed to the function
INI_SECTION_NOT_FOUND - Section does not exist
Code:
INI::GetSectionID(handle,"SECTION");
Get relative key id from key name
Definition:INI::GetKeyID(INI:filehandle,const key[],const section[]="",sectionid=-1,section_size=sizeof(section),key_size=sizeof(key ))
Parameters:
- filehandle takes the INI Handle on which to operate
- key is the name of the key
- section is the name of the section
- sectionid is the relative section id if known
- section_size is the size of the section parameter
- key_size is the size of the key parameter
Exceptions:
INI_ERR_INVALID_HANDLE - Invalid INI Handle was passed to the function
INI_KEY_NOT_FOUND - Key does not exist
Code:
INI::GetKeyID(handle,"KEY","SECTION"); INI::GetKeyID(handle,"KEY","",1); INI::GetKeyID(handle,"KEY","");
Get section name from section id
Definition:INI::GetSectionName(INI:filehandle,result[],sectionid,result_size=sizeof(result))
Parameters:
- filehandle takes the INI Handle on which to operate
- result is the array where the section name has to be stored
- sectionid is the relative section id
- result_size is the size of result
Exceptions:
INI_ERR_INVALID_HANDLE - Invalid INI Handle was passed to the function
INI_ERR_INVALID_ID - Invalid Section ID
Code:
new res[32]; INI::GetSectionName(handle,res,1);
Get key name from key id
Definition:INI::GetKeyName(INI:filehandle,result[],keyid,result_size=sizeof(result))
Parameters:
- filehandle takes the INI Handle on which to operate
- result is the array where the section name has to be stored
- keyid is the relative section id
- result_size is the size of result
Exceptions:
INI_ERR_INVALID_HANDLE - Invalid INI Handle was passed to the function
INI_ERR_INVALID_ID - Invalid Key ID
Code:
new res[32]; INI::GetKeyName(handle,res,1);
Writes the buffer to the file
Definition:INI::WriteBuffer(INI:filehandle)
Parameters:
- filehandle takes the INI Handle which has to be saved
Exceptions:
INI_ERR_INVALID_HANDLE - Invalid INI Handle was passed to the function
INI_ERR_FILE_CREATION_FAILED - Could not create a new file
INI_ERR_PARSING_FAILED - Parsing of the file failed
INI_ERR_FAILED_TO_OPEN - Could not open the file
Code:
INI::WriteBuffer(handle);
Dumps the contents of an INI File on to the Server Window
Definition:INI::DumpINI(INI:filehandle)
Parameters:
- filehandle takes the INI Handle on which to operate
Exceptions:
INI_ERR_INVALID_HANDLE - Invalid INI Handle was passed to the function
Code:
new res[32]; INI::DumpINI(handle);
Writing Speed Test
NOTE:These speed tests are outdated. New speed tests haven't been conducted for the latest version.
eINI is faster at all times while writing when compared with y_ini.
TST1.txt and TST2.txt have the same contents.I made two different files so that any changes made by y_ini won't affect eINI.
Code:
new a = GetTickCount(); new INI:ini = INI_Open("TST1.txt"); for(new i = 0;i < 100000;i++) { INI_SetTag(ini, "XXXX"); INI_WriteString(ini,"k","1234"); INI_WriteString(ini,"k2","1234"); INI_WriteString(ini,"k3","1234"); INI_WriteString(ini,"k4","1234"); INI_WriteString(ini,"k5","1234"); INI_SetTag(ini, "XXXX2"); INI_WriteString(ini,"k","1234"); INI_WriteString(ini,"k2","1234"); INI_WriteString(ini,"k3","1234"); INI_WriteString(ini,"k4","1234"); INI_WriteString(ini,"k5","1234"); } INI_Close(ini); new b = GetTickCount(); new INI:handle = INI::OpenINI("TST2.txt",INI_WRITE); for(new i = 0;i < 100000;i++) { new id = INI::GetSectionID(handle,"XXXX"); INI::WriteString(handle,"1234","k","",-1,id); INI::WriteString(handle,"1234","k2","",-1,id); INI::WriteString(handle,"1234","k3","",-1,id); INI::WriteString(handle,"1234","k4","",-1,id); INI::WriteString(handle,"1234","k5","",-1,id); id = INI::GetSectionID(handle,"XXXX2"); INI::WriteString(handle,"1234","k","",-1,id); INI::WriteString(handle,"1234","k2","",-1,id); INI::WriteString(handle,"1234","k3","",-1,id); INI::WriteString(handle,"1234","k4","",-1,id); INI::WriteString(handle,"1234","k5","",-1,id); } INI::CloseINI(handle); new c = GetTickCount(); printf("SPEED TEST YSI:%d eINI:%d",b-a,c-b);
SPEED TEST YSI:1685 eINI:1203
SPEED TEST YSI:1667 eINI:1175
SPEED TEST YSI:1666 eINI:1283
Reading Speed Test
y_ini wins when the file is small and eINI wins where the file is large.
Code:
main() { new a = GetTickCount(); for(new i = 0;i < 100000;i++) { INI_ParseFile("TEST.txt", "Load1"); } new b = GetTickCount(); for(new i = 0;i < 100000;i++) { new INI:handle = INI::OpenINI("TEST.txt",INI_READ); INI::ParseINI(handle,"Load2",true); INI::CloseINI(handle); } new c = GetTickCount(); printf("SPEED TEST YSI:%d eINI:%d",b-a,c-b); } forward Load1(tag[],key[],value[]); public Load1(tag[],key[],value[]) { } forward Load2(key[],value[]); public Load2(key[],value[]) { }
SPEED TEST YSI:6141 eINI:6839 - Small File - 7 Lines
SPEED TEST YSI:6099 eINI:6686 - Small File - 6 Lines
SPEED TEST YSI:7664 eINI:7665- Small File - 10 Lines
SPEED TEST YSI:12614 eINI:10490 - Large File - 20 Lines
SPEED TEST YSI:19184 eINI:14487 - Very Large File - 36 lines
Issues & Notes
I had written this include in 2013 for my personal use.I have heavily modified the include this year(2015).I have added LIBERAL Mode so that any INI format/standard can be used or else I would be forcing people to use the style I like.
I am expecting bugs because its very old and moreover I have done lot of edits to the code to improve it.I have tested though and fixed all the bugs I could find.There could be some more.
Report bugs via PM or Create an issue at github
Report Typos this thread via PM
Change Log
Version 1.0:
(7/5/2015)
First Release
Version 1.0.3:
(10/5/2015)
- Added SetReplacementText
- Added new setting - INI_MAX_REPLACEMENT_TEXT
- Minor Fixes
(10/6/2015)
- Bug Fix
(19/8/2015)
- Improved ReadString
- Fixed a bug which created duplicate sections when WriteString was used.
(2/9/2015)
- New Parameter for ParseINI where you can specify if you would want eINI to broadcast the loaded data across all scripts
- New Parameter for ParseINI which adds a new way of dynamic loading where key and section name will be passed as arguments to LoadFunctions
- Overall improvement in Speed
- Bug Fixes
- New Log System (tracks eINI events)
GitHub
Example Filterscript
Credits
Yashas
******,Dracoblue,Slick,Neufox and everyone else for their INI Readers which helped me a lot
Slice,****** and many others who used to amaze me every time
Special Thanks to:
****** a.k.a Alex "******" Cole
Kye/Kalcor & the whole SA-MP Team
Thiadmer for PAWN