07.04.2018, 06:32
Quote:
Introduction
This is a bit of a clean up of the old ini system in YSI. Not much has actually changed, just a few bug fixes and added support for tagless ini files such as dini files. I will in the next few days release a user system based on this, as well as a wrapper to allow modes using dini to take advantage of the improved file reading and writing. Tutorial There is now a tutorial on reading and writing y_ini files: How to use y_ini Download This library is a part of YSI, which can be found here. Keep your eye on that topic and your server log for updates. YSI Download Topic Use To use this simply include the header: Код:
#include <YSI\y_ini> Код:
#define MAX_INI_ENTRY_TEXT 160 #include <YSI\y_ini> This system differs in use quite significantly from dini, but with good reason. In dini you open a file, search for a single value, read that value, close the file and repeat. Imagine this code: Код:
gA = dini_Get("myini.ini", "c"); gB = dini_Get("myini.ini", "b"); gC = dini_Get("myini.ini", "a"); Код:
a = 10 b = 67 c = 42 Код:
INI:myini[](name[], value[]) { INI_String("a", gA, len_of_gA); INI_String("b", gB, len_of_gB); INI_String("c", gC, len_of_gC); return 0; // This is now required. } Код:
INI_Load("myini.ini"); The syntax of the file is also a little odd, but we'll come to that later. Note that the trailing semicolon used to be a bug, it's now not. Writing y_ini writes values in a very similar way to dini, though you explicitly open and close the file - dini opens and closes it on every value. In addition it buffers writes - you don't need to worry about exactly how it works, it just means that it writes lots of values at once. Код:
new INI:ini = INI_Open("myini.ini"); INI_WriteString(ini, "NAME", "******"); INI_WriteInt(ini, "SCORE", gScore); INI_WriteFloat(ini, "HEALTH", health); INI_Close(ini); You can also delete values from a file: Код:
new INI:ini = INI_Open("myini.ini"); INI_RemoveEntry(ini, "NAME"); INI_Close(ini); Код:
new INI:ini = INI_Open("myini.ini"); INI_WriteString(ini, "NAME", "******"); INI_WriteInt(ini, "SCORE", gScore); INI_RemoveEntry(ini, "NAME"); INI_WriteFloat(ini, "HEALTH", health); INI_Close(ini); The other feature in yini not in dini is tags within ini files: Код:
[LVDM] health = 4.23 pos = 2500 1968 7.3 [SFTDM] health = 100 pos = -2134 -980 2
Код:
INI:filename[LVDM](name[], value[]) { INI_Float("health", gHealth); if (!strcmp(name, "pos") && !sscanf(value, "fff", gX, gY, gZ)) { return; } } Код:
INI:filename[tagname](name[], value[]) { }
Код:
new INI:ini = INI_Open("myini.ini"); INI_SetTag(ini, "LVDM"); INI_WriteString(ini, "NAME", "******"); INI_WriteInt(ini, "SCORE", gScore); INI_Close(ini);
There is one function not covered above, which is the function INI_Load calls:
Often to read in files "INI_Load" will do, but that is very restrictive in what functions it calls. If you have user files based on their name you would need a function for every user ever, which is clearly impossible, so you want to remove the filename from the function being called. This is where the "remoteFormat", "bFileFirst" and "bPassTag" parameters come in. remoteFormat - This defines the format of the function to call, in standard "format" structure. There are two string parameters it can take - the current filename and the current tag within the file. For example, if you have a function defined as: Код:
forward User_LVDM(name[], value[]); public User_LVDM(name[], value[]) Код:
"User_%s" bFileFirst - This swaps the order of the data passed to the function format, if this is true (default false) the first %s in the remoteFormat is the filename and the second is the tag. bPassTag - If this is true it adds an extra parameter to the callback with the current tag, so you can load an entire file from a single function. The tag name comes immediatedly before the "name" parameter, so after any optional extra parameter: Load a whole file at once: Код:
forward LoadOneFile(tag[], name[], value[]); public LoadOneFile(tag[], name[], value[]) { } Код:
INI_ParseFile("myini.ini", "LoadOneFile", .bPassTag = true); Код:
forward LoadOneUser(playerid, tag[], name[], value[]); public LoadOneUser(playerid, tag[], name[], value[]) { } Код:
INI_ParseFile(playerfile, "LoadOneUser", .bExtra = true, .extra = playerid, .bPassTag = true); Код:
forward LoadOneUser_LVDM(playerid, name[], value[]); public LoadOneUser_LVDM(playerid, name[], value[]) { } Код:
INI_ParseFile(playerfile, "LoadOneUser_%s", false, true, playerid); Код:
forward LoadOneUser_LVDM(playerid, name[], value[]); public LoadOneUser_LVDM(playerid, name[], value[]) { } Код:
INI_ParseFile(playerfile, "LoadOneUser_%s", false, true, playerid, false); Код:
forward Load_myini(playerid, tag[], name[], value[]); public Load_myini(playerid, tag[], name[], value[]) { } Код:
INI_ParseFile("myini.ini", "Load_%s", true, true, playerid, false, true); Timings Timing comparisons to dini and SII. This is loading 400000 values from ini files of a modest size (less than 64 entries (42)). Note that the "less than 64" is important - by default yini can buffer 64 values when pretending to be dini (which is a feature in my local version but not yet released): Код:
dini: 63810 - Yes, that's just over 1 minute yini: 1564 - Yes, that's just over 1 second yini as dini 1: 6009 - Just over 6 seconds yini as dini 2: 91159 - About a minute and a half SII: 52807 The blatantly obvious conclusion from these results is use yini as it was designed, however if you can't there are ways to get around it. The two examples of yini posing as dini are the two extremes. The yini/dini system reads the file and buffers it. If the file is still in the buffer when the next request from the same file arrives the result is returned from memory instead of from re-reading the file as dini does. The first of these two results is where you read many values all at once. In this version the file is read once and buffered, then all the data is got from the buffer. This is frankly the most likely outcome. The second version, which is actually slower than dini, is where you read a few values, then read other ini files, then read more values. yini can buffer up to four files (by default) at once, however if you read your dini file, then read four other files, the system will dump the dini file to make room in memory. yini's dini emulation takes slightly longer to read a file than dini, but it only reads the file once in general, instead of meny times - which is where the speed comes from. In this version it has to do a slightly longer read and buffering many times, the worst of both worlds. In general if you are using dini emulation mode you're likely to get an average weighted heavily towards the faster time, especially if you don't open ini files and leave them open: Код:
((6009 * 3) + 91159) / 4 = 27296.5 Код:
yini: 1564 dini: 63810 emu : 27297 SII: 52807 Credits I am reposting this include (made by ******) with the thought of what he said to several members of the community. Everything that could help someone should not be deleted from the forums, which is something I agree with since I learned a lot by reading the tutorials on here. He made a lot of things that are used by lots of servers and that knowledge should not be lost for present and future developers. |