AlliedModders

AlliedModders (https://forums.alliedmods.net/index.php)
-   Code Snippets/Tutorials (https://forums.alliedmods.net/forumdisplay.php?f=83)
-   -   INI File Reader/Writer AMXX 1.9 (https://forums.alliedmods.net/showthread.php?t=315031)

CrazY. 03-17-2019 16:08

INI File Reader/Writer AMXX 1.9
 
1 Attachment(s)

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]

JocAnis 03-18-2019 05:11

Re: INI File Reader/Writer AMXX 1.9
 
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 ?

CrazY. 03-18-2019 09:41

Re: INI File Reader/Writer AMXX 1.9
 
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.

E1_531G 03-18-2019 19:41

Re: INI File Reader/Writer AMXX 1.9
 
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?

CrazY. 03-18-2019 20:46

Re: INI File Reader/Writer AMXX 1.9
 
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.

E1_531G 03-18-2019 21:07

Re: INI File Reader/Writer AMXX 1.9
 
Thank you for the explanations. Well, good job.

E1_531G 04-05-2019 05:06

Re: INI File Reader/Writer AMXX 1.9
 
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?

CrazY. 04-05-2019 09:21

Re: INI File Reader/Writer AMXX 1.9
 
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

E1_531G 04-05-2019 14:29

Re: INI File Reader/Writer AMXX 1.9
 
Well, good to know. I never used to look at fgets() return when i use it.

fysiks 04-06-2019 00:42

Re: INI File Reader/Writer AMXX 1.9
 
Quote:

Originally Posted by CrazY. (Post 2646402)
Actually, empty lines are equivalent to one (1) char.

Or two (2) for \r\n (Windows® style end of line).


All times are GMT -4. The time now is 10:02.

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