Raised This Month: $12 Target: $400
 3% 

INI File Reader/Writer AMXX 1.9


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
CrazY.
Veteran Member
Join Date: May 2015
Location: SP, Brazil
Old 03-17-2019 , 16:08   INI File Reader/Writer AMXX 1.9
Reply With Quote #1


This is an include version of Settings API.


About the include [top]
With INI File Reader/Writer you can easily create and parse data from a INI. It does not require any special plugin or module, only:

Code:
#include <amxmodx> #include <amxmisc> #include <ini_file>


Functions
Reading Data [top]
  • Integer:
    Code:
    /**  * Reads an integer value from a INI file.  *  * @param file    The filename of the INI file  * @param section     The section name in the INI file  * @param key       The key name in the INI file  * @param var       Variable to store the value in  *  * @return     1 on success or 0 if the file, section or key does not exists.  */ stock ini_read_int(const file[], const section[], const key[], &var)

    Code:
    /**  * Reads every single comma separated integer value from a INI file and store to a cellarray.  *  * @param file    The filename of the INI file  * @param section     The section name in the INI file  * @param key       The key name in the INI file  * @param array         The cellarray handle to store the values in  *  * @return     1 on success or 0 if an invalid cellarray handle is provided  *       or the file, section or key does not exists.  */ stock ini_read_int_array(const file[], const section[], const key[], Array:array)
  • Float:
    Code:
    /**  * Reads a float value from a INI file.  *  * @param file    The filename of the INI file  * @param section     The section name in the INI file  * @param key       The key name in the INI file  * @param var       Variable to store the value in  *  * @return     1 on success or 0 if the file, section or key does not exists.  */ stock ini_read_float(const file[], const section[], const key[], &Float:var)

    Code:
    /**  * Reads every single comma separated float value from a INI file and store to a cellarray.  *  * @param file    The filename of the INI file  * @param section     The section name in the INI file  * @param key       The key name in the INI file  * @param array         The cellarray handle to store the values in  *  * @return     1 on success or 0 if an invalid cellarray handle is provided  *       or the file, section or key does not exists.  */ stock ini_read_float_array(const file[], const section[], const key[], Array:array)
  • String:
    Code:
    /**  * Reads a string from a INI file.  *  * @param file    The filename of the INI file  * @param section     The section name in the INI file  * @param key       The key name in the INI file  * @param dest    Buffer to copy the value to  * @param len       Max length of the buffer  *  * @return     Number of cells written to buffer on success  *       or 0 if the file, section or key does not exists.  */ stock ini_read_string(const file[], const section[], const key[], dest[], len)

    Code:
    /**  * Reads every single comma separated string from a INI file and store to a cellarray.  *  * @param file    The filename of the INI file  * @param section     The section name in the INI file  * @param key       The key name in the INI file  * @param array         The cellarray handle to store the values in  *  * @return     1 on success or 0 if an invalid cellarray handle is provided  *       or the file, section or key does not exists.  */ stock ini_read_string_array(const file[], const section[], const key[], Array:array)

Writing Data [top]
  • Integer:
    Code:
    /**  * Writes an integer value to a INI file.  *  * @note If the file does not already exists, it is created in the ${amxx_configsdir} directory.  *    Keys and/or sections are added to the end.  *  * @param file    The filename of the INI file  * @param section     The section name in the INI file  * @param key       The key name in the INI file  * @param value         The value to write/change  *  * @return     1 on success, 0 otherwise.  */ stock ini_write_int(const file[], const section[], const key[], value)

    Code:
    /**  * Writes every integer value stored in the cellarray to a INI file.  *  * @note If the file does not already exists, it is created in the ${amxx_configsdir} directory.  *    Keys and/or sections are added to the end.  * @note The values will be separated by commas (e.g. val1 , val2 , val3 , val4)  *  * @param file    The filename of the INI file  * @param section     The section name in the INI file  * @param key       The key name in the INI file  * @param array         The cellarray handle to parse the values from  *  * @return     1 on success, 0 otherwise.  */ stock ini_write_int_array(const file[], const section[], const key[], Array:array)
  • Float:
    Code:
    /**  * Writes an float value to a INI file.  *  * @note If the file does not already exists, it is created in the ${amxx_configsdir} directory.  *    Keys and/or sections are added to the end.  *  * @param file    The filename of the INI file  * @param section     The section name in the INI file  * @param key       The key name in the INI file  * @param value         The value to write/change  *  * @return     1 on success, 0 otherwise.  */ stock ini_write_float(const file[], const section[], const key[], Float:value)

    Code:
    /**  * Writes every float value stored in the cellarray to a INI file.  *  * @note If the file does not already exists, it is created in the ${amxx_configsdir} directory.  *    Keys and/or sections are added to the end.  * @note The values will be separated by commas (e.g. val1 , val2 , val3 , val4)  *  * @param file    The filename of the INI file  * @param section     The section name in the INI file  * @param key       The key name in the INI file  * @param array         The cellarray handle to parse the values from  *  * @return     1 on success, 0 otherwise.  */ stock ini_write_float_array(const file[], const section[], const key[], Array:array)
  • String:
    Code:
    /**  * Writes a string to a INI file.  *  * @note If the file does not already exists, it is created in the ${amxx_configsdir} directory.  *    Keys and/or sections are added to the end.  *  * @param file    The filename of the INI file  * @param section     The section name in the INI file  * @param key       The key name in the INI file  * @param value         The value to write/change  *  * @return     1 on success, 0 otherwise.  */ stock ini_write_string(const file[], const section[], const key[], value[])

    Code:
    /**  * Writes every string stored in the cellarray to a INI file.  *  * @note If the file does not already exists, it is created in the ${amxx_configsdir} directory.  *    Keys and/or sections are added to the end.  * @note The values will be separated by commas (e.g. str1 , str2 , str3 , str4)  *  * @param file    The filename of the INI file  * @param section     The section name in the INI file  * @param key       The key name in the INI file  * @param array         The cellarray handle to parse the values from  *  * @return     1 on success, 0 otherwise.  */ stock ini_write_string_array(const file[], const section[], const key[], Array:array)


Constants and Notes [top]
Code:
/**  * Hardcoded max length of a line.  * Increase this if the values are being cut.  */ #define INI_MAX_STRING_LEN 512

Code:
/**  * Each value type has a maximum length of:  *  * integer - 22 characters  * float - 22 characters  * string - 64 characters  *  *  * A standard INI file looks like:  *  * [SectionName]  * Key=Value  *  * Visit this page for more information: en.wikipedia.org/wiki/INI_file  */


Examples [top]
Code:
#include <amxmodx> #include <ini_file> new SQL_HOST[] = "myhost"; new SQL_USER[] = "username"; new SQL_PASSWORD[] = "password"; new SQL_DATABASE[] = "database"; public plugin_init() {     register_plugin("INI File Reader/Writer Example", "1.0", "Crazy");     new const FILENAME[] = "sql.ini";     new const SECTION[] = "SQL";     if (!ini_read_string(FILENAME, SECTION, "Host", SQL_HOST, charsmax(SQL_HOST)))         ini_write_string(FILENAME, SECTION, "Host", SQL_HOST);     if (!ini_read_string(FILENAME, SECTION, "User", SQL_USER, charsmax(SQL_USER)))         ini_write_string(FILENAME, SECTION, "User", SQL_USER);     if (!ini_read_string(FILENAME, SECTION, "Password", SQL_PASSWORD, charsmax(SQL_PASSWORD)))         ini_write_string(FILENAME, SECTION, "Password", SQL_PASSWORD);     if (!ini_read_string(FILENAME, SECTION, "Database", SQL_DATABASE, charsmax(SQL_DATABASE)))         ini_write_string(FILENAME, SECTION, "Database", SQL_DATABASE);     server_print("SQL_HOST=%s^nSQL_USER=%s^nSQL_PASSWORD=%s^nSQL_DATABASE=%s", SQL_HOST, SQL_USER, SQL_PASSWORD, SQL_DATABASE); }
Result:
Code:
Server console:
SQL_HOST=myhost
SQL_USER=username
SQL_PASSWORD=password
SQL_DATABASE=database


addons/amxmodx/configs/sql.ini:
[SQL]
SQL_HOST = myhost
SQL_USER = username
SQL_PASSWORD = password
SQL_DATABASE = database
Code:
#include <amxmodx> #include <ini_file> new PLAYER_MODELS[][] = { "sas", "zombie_source", "vip" } public plugin_init() {     register_plugin("INI File Reader/Writer Example", "1.0", "Crazy");     new const FILENAME[] = "player_models.ini";     new const SECTION[] = "Models";     new Array:array = ArrayCreate(32, 1);     ini_read_string_array(FILENAME, SECTION, "Filename", array);     new array_size, buffer[32];     array_size = ArraySize(array);     if (array_size == 0)     {         for (new i = 0; i < sizeof PLAYER_MODELS; i++)             ArrayPushString(array, PLAYER_MODELS[i]);         ini_write_string_array(FILENAME, SECTION, "Filename", array);     }         server_print("array models:");     for (new i = 0; i < array_size; i++)     {         ArrayGetString(array, i, buffer, charsmax(buffer));         server_print("-- %s", buffer);     }     ArrayDestroy(array); }

Result:
Code:
Server console:
array models:
-- sas
-- zombie_source
-- vip


addons/amxmodx/configs/player_models.ini:
[Models]
Filename = sas , zombie_source , vip

ini_file.inc [top]
Code:
#if defined _ini_file_included
	#endinput
#endif
#define _ini_file_included

/**
 * INI File Reader/Writer was created by CrazY. on 03/17/2019
 * This INI system uses actual files and no modules and it is very flexible
 * Visit this page for more information: https://forums.alliedmods.net/showthread.php?p=2643837
 *
 * Credits goes to:
 *	MeRcyLeZZ (Settings API: https://forums.alliedmods.net/showthread.php?t=243202)
 *	Exolent (FVault: https://forums.alliedmods.net/showthread.php?t=76453)
 */

#include <amxmodx>
#include <amxmisc>

/**
 * Each value type has a maximum length of:
 *
 * integer - 22 characters
 * float - 22 characters
 * string - 64 characters
 *
 *
 * A standard INI file looks like:
 *
 * [SectionName]
 * Key=Value
 * 
 * Visit this page for more information: https://en.wikipedia.org/wiki/INI_file
 */

/**
 * Hardcoded max length of a line.
 * Increase this if the values are being cut.
 */
#define INI_MAX_STRING_LEN 512

/**
 * Reads an integer value from a INI file.
 *
 * @param file 			The filename of the INI file
 * @param section 		The section name in the INI file
 * @param key 			The key name in the INI file
 * @param var 			Variable to store the value in
 *
 * @return 				1 on success or 0 if the file, section or key does not exists.
 */
stock ini_read_int(const file[], const section[], const key[], &var)
{
	new szBuffer[22];

	if (!_ini_read(file, section, key, szBuffer, charsmax(szBuffer)))
		return 0;

	var = str_to_num(szBuffer);
	return 1;
}

/**
 * Writes an integer value to a INI file.
 *
 * @note If the file does not already exists, it is created in the ${amxx_configsdir} directory.
 * 		 Keys and/or sections are added to the end.
 *
 * @param file 			The filename of the INI file
 * @param section 		The section name in the INI file
 * @param key 			The key name in the INI file
 * @param value 		The value to write/change
 *
 * @return 				1 on success, 0 otherwise.
 */
stock ini_write_int(const file[], const section[], const key[], value)
{
	new szBuffer[22];
	num_to_str(value, szBuffer, charsmax(szBuffer));
	return _ini_write(file, section, key, szBuffer);
}

/**
 * Reads every single comma separated integer value from a INI file and store to a cellarray.
 *
 * @param file 			The filename of the INI file
 * @param section 		The section name in the INI file
 * @param key 			The key name in the INI file
 * @param array 		The cellarray handle to store the values in
 *
 * @return 				1 on success or 0 if an invalid cellarray handle is provided
 * 						or the file, section or key does not exists.
 */
stock ini_read_int_array(const file[], const section[], const key[], Array:array)
{
	if (array == Invalid_Array)
		return 0;

	new szBuffer[INI_MAX_STRING_LEN], Data[32][22];
	new iStringCount, i;

	if (!_ini_read(file, section, key, szBuffer, charsmax(szBuffer)))
		return 0;

	iStringCount = explode_string(szBuffer, ",", Data, sizeof Data, charsmax(Data[]));

	for (i = 0; i < iStringCount; i++)
	{
		trim(Data[i]);
		ArrayPushCell(array, str_to_num(Data[i]));
	}

	return 1;
}

/**
 * Writes every integer value stored in the cellarray to a INI file.
 *
 * @note If the file does not already exists, it is created in the ${amxx_configsdir} directory.
 * 		 Keys and/or sections are added to the end.
 * @note The values will be separated by commas (e.g. val1 , val2 , val3 , val4)
 *
 * @param file 			The filename of the INI file
 * @param section 		The section name in the INI file
 * @param key 			The key name in the INI file
 * @param array 		The cellarray handle to parse the values from
 *
 * @return 				1 on success, 0 otherwise.
 */
stock ini_write_int_array(const file[], const section[], const key[], Array:array)
{
	if (array == Invalid_Array)
		return 0;

	new szBuffer[INI_MAX_STRING_LEN];
	new i, iStringCount, iLen, iTotalLen;

	iStringCount = ArraySize(array);

	for (i = 0; i < iStringCount; i++)
	{
		iTotalLen += formatex(szBuffer[iTotalLen], charsmax(szBuffer) - iTotalLen, "%i", ArrayGetCell(array, i));

		if (i != iStringCount - 1)
		{
			iLen = copy(szBuffer[iTotalLen], charsmax(szBuffer) - iTotalLen, " , ");
			iTotalLen += iLen;

			if (iLen < 3)
				break;
		}
	}

	return _ini_write(file, section, key, szBuffer);
}

/**
 * Reads a float value from a INI file.
 *
 * @param file 			The filename of the INI file
 * @param section 		The section name in the INI file
 * @param key 			The key name in the INI file
 * @param var 			Variable to store the value in
 *
 * @return 				1 on success or 0 if the file, section or key does not exists.
 */
stock ini_read_float(const file[], const section[], const key[], &Float:var)
{
	new szBuffer[22];

	if (!_ini_read(file, section, key, szBuffer, charsmax(szBuffer)))
		return 0;

	var = str_to_float(szBuffer);
	return 1;
}

/**
 * Writes an float value to a INI file.
 *
 * @note If the file does not already exists, it is created in the ${amxx_configsdir} directory.
 * 		 Keys and/or sections are added to the end.
 *
 * @param file 			The filename of the INI file
 * @param section 		The section name in the INI file
 * @param key 			The key name in the INI file
 * @param value 		The value to write/change
 *
 * @return 				1 on success, 0 otherwise.
 */
stock ini_write_float(const file[], const section[], const key[], Float:value)
{
	new szBuffer[22];
	formatex(szBuffer, charsmax(szBuffer), "%.2f", value);
	return _ini_write(file, section, key, szBuffer);
}

/**
 * Reads every single comma separated float value from a INI file and store to a cellarray.
 *
 * @param file 			The filename of the INI file
 * @param section 		The section name in the INI file
 * @param key 			The key name in the INI file
 * @param array 		The cellarray handle to store the values in
 *
 * @return 				1 on success or 0 if an invalid cellarray handle is provided
 * 						or the file, section or key does not exists.
 */
stock ini_read_float_array(const file[], const section[], const key[], Array:array)
{
	if (array == Invalid_Array)
		return 0;
	
	new szBuffer[INI_MAX_STRING_LEN], Data[32][22];
	new iStringCount, i;

	if (!_ini_read(file, section, key, szBuffer, charsmax(szBuffer)))
		return 0;

	iStringCount = explode_string(szBuffer, ",", Data, sizeof Data, charsmax(Data[]));

	for (i = 0; i < iStringCount; i++)
	{
		trim(Data[i]);
		ArrayPushCell(array, str_to_float(Data[i]));
	}

	return 1;
}

/**
 * Writes every float value stored in the cellarray to a INI file.
 *
 * @note If the file does not already exists, it is created in the ${amxx_configsdir} directory.
 * 		 Keys and/or sections are added to the end.
 * @note The values will be separated by commas (e.g. val1 , val2 , val3 , val4)
 *
 * @param file 			The filename of the INI file
 * @param section 		The section name in the INI file
 * @param key 			The key name in the INI file
 * @param array 		The cellarray handle to parse the values from
 *
 * @return 				1 on success, 0 otherwise.
 */
stock ini_write_float_array(const file[], const section[], const key[], Array:array)
{
	if (array == Invalid_Array)
		return 0;

	new szBuffer[INI_MAX_STRING_LEN];
	new i, iStringCount, iLen, iTotalLen;

	iStringCount = ArraySize(array);

	for (i = 0; i < iStringCount; i++)
	{
		iTotalLen += formatex(szBuffer[iTotalLen], charsmax(szBuffer) - iTotalLen, "%.2f", ArrayGetCell(array, i));

		if (i != iStringCount - 1)
		{
			iLen = copy(szBuffer[iTotalLen], charsmax(szBuffer) - iTotalLen, " , ");
			iTotalLen += iLen;

			if (iLen < 3)
				break;
		}
	}

	return _ini_write(file, section, key, szBuffer);
}

/**
 * Reads a string from a INI file.
 *
 * @param file 			The filename of the INI file
 * @param section 		The section name in the INI file
 * @param key 			The key name in the INI file
 * @param dest 			Buffer to copy the value to
 * @param len 			Max length of the buffer
 *
 * @return 				Number of cells written to buffer on success 
 * 						or 0 if the file, section or key does not exists.
 */
stock ini_read_string(const file[], const section[], const key[], dest[], len)
{
	return _ini_read(file, section, key, dest, len);
}

/**
 * Writes a string to a INI file.
 *
 * @note If the file does not already exists, it is created in the ${amxx_configsdir} directory.
 * 		 Keys and/or sections are added to the end.
 *
 * @param file 			The filename of the INI file
 * @param section 		The section name in the INI file
 * @param key 			The key name in the INI file
 * @param value 		The value to write/change
 *
 * @return 				1 on success, 0 otherwise.
 */
stock ini_write_string(const file[], const section[], const key[], value[])
{
	return _ini_write(file, section, key, value);
}

/**
 * Reads every single comma separated string from a INI file and store to a cellarray.
 *
 * @param file 			The filename of the INI file
 * @param section 		The section name in the INI file
 * @param key 			The key name in the INI file
 * @param array 		The cellarray handle to store the values in
 *
 * @return 				1 on success or 0 if an invalid cellarray handle is provided
 * 						or the file, section or key does not exists.
 */
stock ini_read_string_array(const file[], const section[], const key[], Array:array)
{
	if (array == Invalid_Array)
		return 0;
	
	new szBuffer[INI_MAX_STRING_LEN], Data[32][64];
	new iStringCount, i;

	if (!_ini_read(file, section, key, szBuffer, charsmax(szBuffer)))
		return 0;

	iStringCount = explode_string(szBuffer, ",", Data, sizeof Data, charsmax(Data[]));

	for (i = 0; i < iStringCount; i++)
	{
		trim(Data[i]);
		ArrayPushString(array, Data[i]);
	}

	return 1;
}

/**
 * Writes every string stored in the cellarray to a INI file.
 *
 * @note If the file does not already exists, it is created in the ${amxx_configsdir} directory.
 * 		 Keys and/or sections are added to the end.
 * @note The values will be separated by commas (e.g. str1 , str2 , str3 , str4)
 *
 * @param file 			The filename of the INI file
 * @param section 		The section name in the INI file
 * @param key 			The key name in the INI file
 * @param array 		The cellarray handle to parse the values from
 *
 * @return 				1 on success, 0 otherwise.
 */
stock ini_write_string_array(const file[], const section[], const key[], Array:array)
{
	if (array == Invalid_Array)
		return 0;

	new szBuffer[INI_MAX_STRING_LEN];
	new i, iStringCount, iLen, iTotalLen;

	iStringCount = ArraySize(array);

	for (i = 0; i < iStringCount; i++)
	{
		iTotalLen += ArrayGetString(array, i, szBuffer[iTotalLen], charsmax(szBuffer) - iTotalLen);

		if (i != iStringCount - 1)
		{
			iLen = copy(szBuffer[iTotalLen], charsmax(szBuffer) - iTotalLen, " , ");
			iTotalLen += iLen;

			if (iLen < 3)
				break;
		}
	}

	return _ini_write(file, section, key, szBuffer);
}

_ini_copyc(dest[], len, const src[], ch)
{
	new i, iRetVal;
	new bool:bCharFound;

	for (i = len; i >= 0; i--)
	{
		dest[i] = 0;

		if (!src[i])
			continue;

		if (!bCharFound && src[i] == ch)
		{
			bCharFound = true;
			continue;
		}

		dest[i] = src[i];
		iRetVal++;
	}

	return iRetVal;
}

_ini_read(const file[], const section[], const key[], dest[], len)
{
	new hFile;
	new iRetVal;
	new bool:bSectionFound;
	new szBuffer[INI_MAX_STRING_LEN], szFile[64], szKey[32], szSection[32];

	formatex(szFile[get_configsdir(szFile, charsmax(szFile))], charsmax(szFile), "/%s.ini", file);

	if (!(hFile = fopen(szFile, "rt")))
		return 0;

	while (!feof(hFile))
	{
		if (fgets(hFile, szBuffer, charsmax(szBuffer)) == 0)
			break;

		trim(szBuffer);

		if (!szBuffer[0] || szBuffer[0] == ';')
			continue;

		if (szBuffer[0] == '[')
		{
			if (bSectionFound)
				break;

			_ini_copyc(szSection, charsmax(szSection), szBuffer[1], ']');

			if (equali(section, szSection))
				bSectionFound = true;
		}

		if (bSectionFound)
		{
			split(szBuffer, szKey, charsmax(szKey), szBuffer, charsmax(szBuffer), "=");
			trim(szKey);
			trim(szBuffer);

			if (equali(szKey, key))
				iRetVal = copy(dest, len, szBuffer);
		}
	}

	fclose(hFile);
	return iRetVal;
}

_ini_write(const file[], const section[], const key[], value[])
{
	new hFile, hTempFile;
	new bool:bSectionExists, bool:bKeyExists, bool:bReplace;
	new iKeyPosStart, iKeyPosEnd;
	new szBuffer[INI_MAX_STRING_LEN], szFile[64], szTempFile[64], szKey[32], szSection[32];

	formatex(szFile[get_configsdir(szFile, charsmax(szFile))], charsmax(szFile), "/%s.ini", file);
	bReplace = true;

	if (!(hFile = fopen(szFile, "a+t")))
		return 0;

	while (!feof(hFile))
	{
		if (fgets(hFile, szBuffer, charsmax(szBuffer)) == 0)
			break;

		trim(szBuffer);

		if (szBuffer[0] == '[')
		{
			_ini_copyc(szSection, charsmax(szSection), szBuffer[1], ']');

			if (equali(section, szSection))
			{
				bSectionExists = true;
				break;
			}
		}
	}

	if (!bSectionExists)
	{
		fprintf(hFile, "^n[%s]^n%s = %s^n", section, key, value);
		fclose(hFile);
		return 1;
	}

	while (!feof(hFile))
	{
		iKeyPosStart = ftell(hFile);

		if (fgets(hFile, szBuffer, charsmax(szBuffer)) == 0)
			break;

		trim(szBuffer);

		if (szBuffer[0] == '[')
			break;

		if (!szBuffer[0] || szBuffer[0] == ';')
			continue;

		split(szBuffer, szKey, charsmax(szKey), szBuffer, charsmax(szBuffer), "=");
		trim(szKey);
		trim(szBuffer);

		iKeyPosEnd = ftell(hFile);

		if (equali(szKey, key))
		{
			bKeyExists = true;
			break;
		}
	}

	if (!bKeyExists)
	{
		if (feof(hFile))
		{
			fprintf(hFile, "%s = %s^n", key, value);
			fclose(hFile);
			return 1;
		}

		bReplace = false;
	}

	formatex(szTempFile[get_configsdir(szTempFile, charsmax(szTempFile))], charsmax(szTempFile), "/ini_file_temp.ini");
	hTempFile = fopen(szTempFile, "wt");

	if (!hTempFile)
	{
		fclose(hTempFile);
		fclose(hFile);
		return 0;
	}

	if (!bReplace)
	{
		fseek(hFile, 0, SEEK_SET);

		while (ftell(hFile) < iKeyPosEnd)
		{
			fgets(hFile, szBuffer, charsmax(szBuffer));
			fputs(hTempFile, szBuffer);
		}
	}
	else
	{
		fseek(hFile, 0, SEEK_SET);

		while (ftell(hFile) < iKeyPosStart)
		{
			fgets(hFile, szBuffer, charsmax(szBuffer));
			fputs(hTempFile, szBuffer);
		}

		fgets(hFile, szBuffer, charsmax(szBuffer));
	}

	fprintf(hTempFile, "%s = %s^n", key, value);

	while (!feof(hFile))
	{
		fgets(hFile, szBuffer, charsmax(szBuffer));
		fputs(hTempFile, szBuffer);
	}

	fclose(hFile);
	fclose(hTempFile);

	delete_file(szFile);

	if (!rename_file(szTempFile, szFile, 1))
		return 0;

	return 1;
}

Credits [top]
Attached Files
File Type: inc ini_file.inc (14.5 KB, 595 views)

Last edited by CrazY.; 03-17-2019 at 16:10.
CrazY. is offline
JocAnis
Veteran Member
Join Date: Jun 2010
Old 03-18-2019 , 05:11   Re: INI File Reader/Writer AMXX 1.9
Reply With Quote #2

Good job

can be this used for saving/loading players informations for example (because nvault is more code + complicated to read results)?
you could also implement Update_line/player ?
__________________
KZ Public Autocup - PrimeKZ

My blog: http://primekz.xyz (in progress...) - not active (dec 2022)
JocAnis is offline
CrazY.
Veteran Member
Join Date: May 2015
Location: SP, Brazil
Old 03-18-2019 , 09:41   Re: INI File Reader/Writer AMXX 1.9
Reply With Quote #3

In a way yes, but I am not sure about the performance while working with a big number of data inside the file. You could save player's authid as section and organize the data between the keys.

Code:
new const FILENAME[] = "player_data.ini"; SavePlayerData(this) {     new szAuthId[MAX_AUTHID_LENGTH], iMoney;     get_user_authid(this, szAuthId, charsmax(szAuthId));     iMoney = cs_get_user_money(this); // e.g. 16000     ini_write_int(FILENAME, szAuthId, "Money", iMoney);     /* Result:     [STEAM_0:0:0000000]     Money = 16000     */ } LoadPlayerData(this) {     new szAuthId[MAX_AUTHID_LENGTH], iMoney;     get_user_authid(this, szAuthId, charsmax(szAuthId));     iMoney = cs_get_user_money(this);     ini_read_int(FILENAME, szAuthId, "Money", iMoney);     cs_set_user_money(this, iMoney); }

Update is already implemented. ini_write_* adds the key and value if the key does not already exists, otherwise it update.
__________________








CrazY. is offline
E1_531G
Senior Member
Join Date: Dec 2017
Old 03-18-2019 , 19:41   Re: INI File Reader/Writer AMXX 1.9
Reply With Quote #4

AMXX 1.9 already has INI Parser, doesn't it?
https://wiki.alliedmods.net/AMX_Mod_...rser_INI.2FSMC

Which differences/improvements it has? Excluding saving ofc.

What is wrong with MeRcyLeZZ's API?
__________________
My English is A0

Last edited by E1_531G; 03-18-2019 at 19:45.
E1_531G is offline
CrazY.
Veteran Member
Join Date: May 2015
Location: SP, Brazil
Old 03-18-2019 , 20:46   Re: INI File Reader/Writer AMXX 1.9
Reply With Quote #5

The INI Parser of AMXX only allows you to read the data and it's entirely event based (you must hook events), technically:

Code:
ParseFromINI() {     new INIParser:Parser = INI_CreateParser();     INI_SetReaders(Parser, "OnKeyValue", "OnNewSection");     INI_ParseFile(Parser, "path/to/file.ini");     INI_DestroyParser(Parser); } public bool:OnNewSection(INIParser:handle, const section[], bool:invalid_tokens, bool:close_bracket, bool:extra_tokens, curtok, any:data) {     if (!equali(section, "SectionName"))         return true;     return true; } public bool:OnKeyValue(INIParser:handle, const key[], const value[], bool:invalid_tokens, bool:equal_token, bool:quotes, curtok, any:data) {     if (!equali(key, "KeyName"))         return true;     server_print("%s=%s", key, value);     return true; }

To work with INI Parser of amxx you need to create handlers and a number of checks/code. In a way there is nothing wrong with this but it may be a hard and extensive work if you are working with multiple plugins to perform the parse and not just one. On the other hand, in Settings API or INI File Reader/Writer all you have to do is specify the file, section and key that you are looking for

Code:
new buffer[64]; ini_read_string("path/to/file.ini", "SectionName", "KeyName", buffer, charsmax(buffer));

and you can not only read as you can also adds data to the file as you already cited.

Code:
new buffer[64]; copy(buffer, charsmax(buffer), "KeyValue"); ini_write_string("path/to/file.ini", "SectionName", "KeyName", buffer); /* [SectionName] KeyName = KeyValue */

So in short, if you are looking for a simple and flexible way to work with INI files I believe both Settings API and this include are the best choices, but you are free to choose the best method for you.

Actually there is nothing wrong with MeRcyLeZZ's API, just a little bug when there is double brackets in section name (e.g. [[SectionName]]). I did the include for flexibility reason so you do not need to enable any "extra" plugin just like fvault, nfvault, dhudmessage, ROG, CromChat and whatever more; and I coded it the way I believe it is improved.
__________________









Last edited by CrazY.; 03-18-2019 at 20:52.
CrazY. is offline
E1_531G
Senior Member
Join Date: Dec 2017
Old 03-18-2019 , 21:07   Re: INI File Reader/Writer AMXX 1.9
Reply With Quote #6

Thank you for the explanations. Well, good job.
__________________
My English is A0
E1_531G is offline
E1_531G
Senior Member
Join Date: Dec 2017
Old 04-05-2019 , 05:06   Re: INI File Reader/Writer AMXX 1.9
Reply With Quote #7

Hello again.
I did not do any test yet, but my attention stucked here:
PHP Code:
_ini_write(const file[], const section[], const key[], value[])
{
    
// some code here

    
while (!feof(hFile))
    {
        if (
fgets(hFileszBuffercharsmax(szBuffer)) == 0// HERE
            
break;

        
// some code here 
Doesn't it means that it stops to search if it finds an empty line?
So, if our file is looking this way:
PHP Code:
[sec1]
key1=value1

[sec2]
key2=value2 
it won't find [sec2] when we are looking for it, because of an empty line at the middle.
Am i right?
__________________
My English is A0
E1_531G is offline
CrazY.
Veteran Member
Join Date: May 2015
Location: SP, Brazil
Old 04-05-2019 , 09:21   Re: INI File Reader/Writer AMXX 1.9
Reply With Quote #8

Actually, empty lines are equivalent to one (1) char. fgets() will only return 0 when reach the end of the file or if the file is totally empty. Well, that's what I noticed in the tests.

Code:
            // fgets=1 [Section]   // fgets=10 key=value   // fgets=10             // fgets=1 [Section]   // fgets=10 key=value   // fgets=10             // fgets=1 [Section]   // fgets=10 key=value   // fgets=10             // fgets=1             // fgets=1 [Section]   // fgets=10 key=value   // fgets=10             // fgets=0
__________________









Last edited by CrazY.; 04-05-2019 at 09:28.
CrazY. is offline
E1_531G
Senior Member
Join Date: Dec 2017
Old 04-05-2019 , 14:29   Re: INI File Reader/Writer AMXX 1.9
Reply With Quote #9

Well, good to know. I never used to look at fgets() return when i use it.
__________________
My English is A0
E1_531G is offline
fysiks
Veteran Member
Join Date: Sep 2007
Location: Flatland, USA
Old 04-06-2019 , 00:42   Re: INI File Reader/Writer AMXX 1.9
Reply With Quote #10

Quote:
Originally Posted by CrazY. View Post
Actually, empty lines are equivalent to one (1) char.
Or two (2) for \r\n (Windows® style end of line).
__________________
fysiks is offline
Reply


Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 08:07.


Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.
Theme made by Freecode