Advertisement
Guest User

MXIni Include Reupload

a guest
Jun 1st, 2020
145
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Pawn 75.61 KB | None | 0 0
  1. /*
  2.     Самый быстрый INI ридер/райтер
  3.  
  4.  
  5.     ЧТО ЭТО
  6.         - Это инклуд-файл для PAWN скриптов мультиплеера GTA San Andreas (SA-MP)
  7.  
  8.     КАК ИСПОЛЬЗОВАТЬ
  9.         - Поместить этот файл в папку include, которая лежит рядом с компилятором
  10.         - В самом верху вашего скрипта добавить #include <mxINI>
  11.  
  12.     АВТОР
  13.          MX_Master
  14.  
  15.     ВЕРСИЯ
  16.         0.2 от 08.12.2009
  17.  
  18.  
  19.     ДОСТУПНЫЕ ИНСТРУМЕНТЫ
  20.     более подробные описания даны перед каждой функцией ниже в коде
  21.  
  22.         ini_createFile ( "путь/к/файлу.ini", "Содержимое файла по умолчанию" )
  23.             . вернет ИД_открытого_файла или отрицательное значение при ошибке
  24.  
  25.         ini_openFile ( "путь/к/файлу.ini" )
  26.             . вернет ИД_открытого_файла или отрицательное значение при ошибке
  27.  
  28.         ini_closeFile ( ИД_открытого_файла )
  29.             . вернет 0 при успехе или отрицательное значение при ошибке
  30.             . если ИД_открытого_файла верен и файл был изменен - запишет файл из ОЗУ на диск
  31.     --
  32.         ini_setString ( ИД_открытого_файла, "имя_ключа", "текстовое значение" )
  33.             . вернет отрицательное значение при ошибке или 0 при успехе
  34.  
  35.         ini_setInteger ( ИД_открытого_файла, "имя_ключа", 123456 )
  36.             . вернет отрицательное значение при ошибке или 0 при успехе
  37.  
  38.         ini_setFloat ( ИД_открытого_файла, "имя_ключа", 3.1416 )
  39.             . вернет отрицательное значение при ошибке или 0 при успехе
  40.     --
  41.         ini_getString ( ИД_открытого_файла, "имя_ключа", returnValue )
  42.             . вернет отрицательное значение при ошибке или 0 при успехе
  43.             . значение ключа будет помещено в returnValue, который вы должны предварительно создать
  44.  
  45.         ini_getInteger ( ИД_открытого_файла, "имя_ключа", returnValue )
  46.             . вернет отрицательное значение при ошибке или 0 при успехе
  47.             . целочисленное значение ключа будет помещено в returnValue, который вы должны предварительно создать
  48.  
  49.         ini_getFloat ( ИД_открытого_файла, "имя_ключа", returnValue )
  50.             . вернет отрицательное значение при ошибке или 0 при успехе
  51.             . дробное численное значение ключа будет помещено в returnValue, который вы должны предварительно создать
  52.  
  53.  
  54.     ПРИМЕРЫ
  55.  
  56.         new iniFile = ini_createFile ( "test4268.ini" );
  57.  
  58.         if ( iniFile != INI_OK )
  59.             iniFile = ini_openFile ( "test4268.ini" );
  60.  
  61.         if ( iniFile == INI_OK )
  62.         {
  63.             new returnString[32], returnNumber, Float: returnFloat;
  64.  
  65.             ini_setString  ( iniFile, "ключ_со_строкой", "текстовое значение" );
  66.             ini_setInteger ( iniFile, "ключ_с_числом",   123456 );
  67.             ini_setFloat   ( iniFile, "ключ_с_дробью",   3.1416 );
  68.  
  69.             ini_getString  ( iniFile, "ключ_со_строкой", returnString );
  70.             ini_getInteger ( iniFile, "ключ_с_числом",   returnNumber );
  71.             ini_getFloat   ( iniFile, "ключ_с_дробью",   returnFloat );
  72.  
  73.             ini_closeFile  ( iniFile );
  74.  
  75.             printf ( "\n `ключ_со_строкой` = `%s`,\n `ключ_с_числом` = `%d`,\n `ключ_с_дробью` = `%f` \n",
  76.                 returnString, returnNumber, returnFloat );
  77.         }
  78.         else print( "\n Не удалось открыть INI файл \n" );
  79. */
  80.  
  81.  
  82.  
  83.  
  84.  
  85.  
  86.  
  87.  
  88.  
  89.  
  90.  
  91. const
  92.  
  93.     // настройки
  94.  
  95.     // РЕКОМЕНДУЕТСЯ ИЗМЕНИТЬ ПОД СЕБЯ
  96.     INI_MAX_OPENED_FILES    = 10,       // максимум открытых файлов
  97.     INI_MAX_FILE_SIZE       = 32768,    // байт,        макс. размер файла
  98.     INI_MAX_FILENAME_SIZE   = 128,      // символов,    макс. размер пути к файлу
  99.     INI_MAX_KEYS_IN_FILE    = 2048,     // максимум ключей в открытом файле
  100.  
  101.     // в ОЗУ будет выделено для временного хранения файлов примерно вот столько байт:
  102.     // INI_MAX_OPENED_FILES * ( INI_MAX_FILE_SIZE + INI_MAX_FILENAME_SIZE*4 + INI_MAX_KEYS_IN_FILE*4 )
  103.     // в начальной настройке это:
  104.     // 10 * ( 32768 + 128*4 + 2048*4 ) = 414720 Байт  ИЛИ  405 Кб  ИЛИ  103680 pawn ячеек
  105.     // это примерный, но показательный расчет
  106.  
  107.  
  108.     // НЕЛЬЗЯ МЕНЯТЬ
  109.     INI_INTEGER_SIZE        = 12,       // размер строки с целочисленным значением
  110.     INI_FLOAT_SIZE          = 40,       // размер строки с дробным числовым значением
  111.  
  112.     INI_STRING_DELIMITER    = '\n',     // разделитель строк
  113.     INI_DELIMITER           = '=',      // разделитель ключа и значения
  114.  
  115.  
  116.     // коды ошибок, возвращаемые функциями
  117.  
  118.     // РЕКОМЕНДУЕТСЯ НЕ ИЗМЕНЯТЬ
  119.     INI_OK                  =  0,       // функция успешно выполнена
  120.  
  121.         // проверять на ошибку можно так:
  122.         // if ( возвращаемое_значение < 0 ) ...
  123.  
  124.     INI_FILE_NOT_FOUND      = -1,       // файл не найден по указанному пути
  125.     INI_FILE_ALREADY_EXIST  = -2,       // файл не найден по указанному пути
  126.     INI_TOO_LARGE_FILE      = -3,       // размер файла превысил допустимый лимит
  127.     INI_WRONG_PATH_SIZE     = -4,       // неправильный размер пути к файлу
  128.     INI_READ_ERROR          = -5,       // ошибка чтения файла
  129.     INI_WRITE_ERROR         = -6,       // ошибка при записи в файл
  130.     INI_NO_FREE_SLOT        = -7,       // нет свободного слота для открытия файла
  131.     INI_WRONG_SLOT          = -8,       // указан неверный слот открытого файла
  132.     INI_KEY_NOT_FOUND       = -9,       // ключ в открытом файле не найден
  133.  
  134.  
  135.     // другие вспомогательные константы
  136.  
  137.     // НЕЛЬЗЯ МЕНЯТЬ
  138.     cellbytes = cellbits / charbits;    // кол-во байт в одной ячейке
  139.  
  140.  
  141.  
  142.  
  143.  
  144. // списки разных символов для оператора case в одной из функций
  145.  
  146. // РЕКОМЕНДУЕТСЯ НЕ ИЗМЕНЯТЬ
  147. #define INI_SPACE_CHAR  ' ', '\t'                       // строковые пробельные символы
  148. #define INI_KEY_STARTS  ' ', '\t', '\r', '\0'           // символы, перед началом ключа
  149. #define INI_STRING_ENDS '\r', '\n', '\0'                // символы, завершающие значение
  150. #define INI_NUMBER_ENDS ' ', '\t', '\r', '\n', '\0'     // символы, завершающие численное значение
  151.  
  152.  
  153.  
  154.  
  155.  
  156. stock
  157.  
  158.     // временное хранилище открытых файлов
  159.  
  160.     _ini_nSlotUsed      [ INI_MAX_OPENED_FILES ],                               // флаг: занят ли слот
  161.     _ini_nFileChanged   [ INI_MAX_OPENED_FILES ],                               // флаг: был ли изменен файл
  162.     _ini_nFileBusy      [ INI_MAX_OPENED_FILES ],                               // флаг: изменяется ли в данный момент содержимое файла
  163.     _ini_nFileSize      [ INI_MAX_OPENED_FILES ],                               // размер открытого файла
  164.     _ini_nDelimPos      [ INI_MAX_OPENED_FILES ] [ INI_MAX_KEYS_IN_FILE ],      // список позиций INI_DELIMITER
  165.     _ini_nKeysCount     [ INI_MAX_OPENED_FILES ],                               // кол-во ключей открытого файла
  166.     _ini_szFilePath     [ INI_MAX_OPENED_FILES ] [ INI_MAX_FILENAME_SIZE ],     // путь к файлу
  167.     _ini_szFileContent  [ INI_MAX_OPENED_FILES ] [ INI_MAX_FILE_SIZE char ];    // контент файла
  168.  
  169.  
  170.  
  171.  
  172.  
  173.  
  174.  
  175.  
  176.  
  177.  
  178.  
  179.  
  180.  
  181.  
  182.  
  183.  
  184.  
  185.  
  186.  
  187.  
  188.  
  189. /*
  190.     Создает и сразу открывает INI файл для чтения/записи.
  191.  
  192.     ПОДРОБНЕЕ
  193.         Файл создается только в ОЗУ, и в него записывается строка szDefaultContent.
  194.         В szDefaultContent могут быть и ключи, которые потом парсер также будет видеть.
  195.         Только при закрытии файла, его содержимое будет записано на диск
  196.         по указанному пути к файлу.
  197.  
  198.     ПАРАМЕТРЫ:
  199.         szFilePath[]        путь к файлу
  200.         szDefaultContent    контент файла по умолчанию, обычно, можно не указывать
  201.  
  202.     ВЕРНЕТ:
  203.         код ошибки < 0 или ИД_открытого_файла
  204. */
  205.  
  206. stock ini_createFile ( szFilePath[], szDefaultContent[] = "" )
  207. {
  208.     //
  209.     //  несколько блоков с проверками
  210.     //
  211.  
  212.     // ------------
  213.     new nFileNameSize = strlen( szFilePath ); // узнаем размер пути
  214.  
  215.     // если размер пути неправильный
  216.     if ( nFileNameSize <= 0 || nFileNameSize >= INI_MAX_FILENAME_SIZE )
  217.         return INI_WRONG_PATH_SIZE; // вернем код ошибки
  218.     // ------------
  219.  
  220.  
  221.     // ------------
  222.     if ( fexist( szFilePath ) ) // если файл уже существует
  223.         return INI_FILE_ALREADY_EXIST; // вернем код ошибки - файл уже существует
  224.  
  225.     for ( new slot = 0; slot < INI_MAX_OPENED_FILES; slot++ ) // перебор всех слотов ОЗУ
  226.         if // если уже есть такой открытый файл
  227.         (
  228.                 _ini_nSlotUsed[slot] != 0
  229.             &&  strcmp( szFilePath, _ini_szFilePath[slot], false ) == 0
  230.         )
  231.             return INI_FILE_ALREADY_EXIST; // вернем код ошибки - файл уже существует
  232.     // ------------
  233.  
  234.  
  235.  
  236.     // ------------
  237.     new nFileSize = strlen( szDefaultContent ); // узнаем размер контентa файла по умолчанию
  238.  
  239.     // если размер неправильный
  240.     if ( nFileSize < 0 || nFileSize >= INI_MAX_FILE_SIZE )
  241.         return INI_TOO_LARGE_FILE; // вернем код ошибки
  242.     // ------------
  243.  
  244.  
  245.  
  246.  
  247.     //
  248.     //  поиск свободного слота для записи в ОЗУ
  249.     //
  250.  
  251.     for ( new slot = 0; slot < INI_MAX_OPENED_FILES; slot++ ) // перебор всех слотов ОЗУ
  252.     {
  253.         if ( _ini_nSlotUsed[slot] != 1 ) // если слот найден
  254.         {
  255.             // ------------
  256.             _ini_nSlotUsed[slot]        = 1; // застолбим найденное место
  257.             _ini_nFileChanged[slot]     = 0; // файл не был изменен
  258.             _ini_nFileSize[slot]        = nFileSize; // скопируем размер файла в слот
  259.             _ini_nKeysCount[slot]       = 0; // кол-во ключей выставим 0
  260.             // ------------
  261.  
  262.  
  263.             // ------------
  264.             // скопируем в ОЗУ весь файл,
  265.             // запомнив все позиции INI_DELIMITER и их кол-во
  266.             for ( new i = 0;  i < nFileSize && i < INI_MAX_FILE_SIZE;  i++ )
  267.             {
  268.                 if (
  269.                         szDefaultContent[i] == INI_DELIMITER // если символ это INI_DELIMITER
  270.                     &&  _ini_nKeysCount[slot] < INI_MAX_KEYS_IN_FILE // и лимит ключей еще не исчерпан
  271.                 ) {
  272.                     _ini_nDelimPos[slot][ _ini_nKeysCount[slot] ] = i; // добавим еще одну позицию INI_DELIMITER
  273.                     _ini_nKeysCount[slot]++; // увеличим кол-во найденных ключей
  274.                 }
  275.  
  276.                 _ini_szFileContent[slot]{i} = szDefaultContent[i];
  277.             }
  278.  
  279.             _ini_szFileContent[slot]{nFileSize} = 0; // символ конца строки для контента
  280.             // ------------
  281.  
  282.  
  283.             // ------------
  284.             // скопируем в озу путь к файлу
  285.             memcpy( _ini_szFilePath[slot], szFilePath, 0, nFileNameSize * cellbytes );
  286.  
  287.             _ini_szFilePath[slot][nFileNameSize] = 0; // символ конца строки для пути
  288.             // ------------
  289.  
  290.  
  291.             return slot; // вернем ИД слота
  292.         }
  293.     }
  294.  
  295.  
  296.  
  297.  
  298.     //
  299.     //  если свободный слот в памяти не найден
  300.     //
  301.  
  302.     return INI_NO_FREE_SLOT; // вернем код ошибки
  303.     // ------------
  304. }
  305.  
  306.  
  307.  
  308.  
  309. /*
  310.     Открывает INI файл для чтения/записи, если он существует.
  311.  
  312.     ПОДРОБНЕЕ
  313.         Копирует в ОЗУ с диска всё содержимое файла, если его размер не превышает
  314.         допустимый. Если кол-во ключей в файле больше допустимого, ошибки никакой не будет,
  315.         просто при чтении/записи значений, парсер не будет видеть лишние ключи.
  316.  
  317.     ПАРАМЕТРЫ:
  318.         szFilePath[]    путь к файлу
  319.  
  320.     ВЕРНЕТ:
  321.         код ошибки < 0 или ИД_открытого_файла
  322. */
  323.  
  324. stock ini_openFile ( szFilePath[] )
  325. {
  326.     //
  327.     //  несколько блоков с проверками
  328.     //
  329.  
  330.     // ------------
  331.     new nFileNameSize = strlen( szFilePath ); // узнаем размер пути
  332.  
  333.     // если размер пути неправильный
  334.     if ( nFileNameSize <= 0 || nFileNameSize >= INI_MAX_FILENAME_SIZE )
  335.         return INI_WRONG_PATH_SIZE; // вернем код ошибки
  336.     // ------------
  337.  
  338.  
  339.     if ( ! fexist( szFilePath ) ) // если файл не найден
  340.         return INI_FILE_NOT_FOUND; // вернем код ошибки
  341.  
  342.  
  343.     // ------------
  344.     // проверка - открыт ли уже файл с таким именем
  345.     for ( new slot = 0; slot < INI_MAX_OPENED_FILES; slot++ ) // перебор всех слотов ОЗУ
  346.         if // если уже есть такой открытый файл
  347.         (
  348.                 _ini_nSlotUsed[slot] != 0
  349.             &&  strcmp( szFilePath, _ini_szFilePath[slot], false ) == 0
  350.         )
  351.             return slot; // просто вернем его слот
  352.     // ------------
  353.  
  354.  
  355.     // ------------
  356.     new File: pFile = fopen( szFilePath, io_read ); // пытаемся открыть файл для чтения
  357.  
  358.     if ( ! pFile ) // если файл не открылся
  359.         return INI_READ_ERROR; // вернем код ошибки
  360.     // ------------
  361.  
  362.  
  363.     // ------------
  364.     new nFileSize = flength( pFile ); // узнаем размер файла
  365.  
  366.     if ( nFileSize >= INI_MAX_FILE_SIZE ) // если размер файла слишком большой
  367.     {
  368.         fclose(pFile); // закроем файл
  369.         return INI_TOO_LARGE_FILE; // вернем код ошибки
  370.     }
  371.     // ------------
  372.  
  373.  
  374.  
  375.  
  376.     //
  377.     //  поиск свободного слота для записи в ОЗУ
  378.     //
  379.  
  380.     // ------------
  381.     for ( new slot = 0; slot < INI_MAX_OPENED_FILES; slot++ ) // перебор всех слотов ОЗУ
  382.     {
  383.         if ( _ini_nSlotUsed[slot] != 1 ) // если слот найден
  384.         {
  385.             // ------------
  386.             _ini_nSlotUsed[slot]        = 1; // застолбим найденное место
  387.             _ini_nFileChanged[slot]     = 0; // файл не был изменен
  388.             _ini_nFileSize[slot]        = nFileSize; // скопируем размер файла в слот
  389.             _ini_nKeysCount[slot]       = 0; // кол-во ключей выставим 0
  390.             // ------------
  391.  
  392.  
  393.             // ------------
  394.             // скопируем в ОЗУ весь файл,
  395.             // запомнив все позиции INI_DELIMITER и их кол-во
  396.             for ( new i = 0, symbol; i < nFileSize && i < INI_MAX_FILE_SIZE; i++ )
  397.             {
  398.                 symbol = fgetchar( pFile, 0, false ); // читаем из файла следующий символ
  399.  
  400.                 if (
  401.                         symbol == INI_DELIMITER // если символ это INI_DELIMITER
  402.                     &&  _ini_nKeysCount[slot] < INI_MAX_KEYS_IN_FILE // и лимит ключей еще не исчерпан
  403.                 ) {
  404.                     _ini_nDelimPos[slot][ _ini_nKeysCount[slot] ] = i; // добавим еще одну позицию INI_DELIMITER
  405.                     _ini_nKeysCount[slot]++; // увеличим кол-во найденных ключей
  406.                 }
  407.  
  408.                 _ini_szFileContent[slot]{i} = symbol;
  409.             }
  410.  
  411.             _ini_szFileContent[slot]{nFileSize} = 0; // символ конца строки для контента
  412.  
  413.             fclose(pFile); // закроем файл
  414.             // ------------
  415.  
  416.  
  417.             // ------------
  418.             // скопируем в озу путь к файлу
  419.             memcpy( _ini_szFilePath[slot], szFilePath, 0, nFileNameSize * cellbytes );
  420.  
  421.             _ini_szFilePath[slot][nFileNameSize] = 0; // символ конца строки для пути
  422.             // ------------
  423.  
  424.  
  425.             return slot; // вернем ИД слота
  426.         }
  427.     }
  428.     // ------------
  429.  
  430.  
  431.  
  432.  
  433.     //
  434.     //  если свободный слот в памяти не найден
  435.     //
  436.  
  437.     // ------------
  438.     fclose(pFile); // закроем файл
  439.  
  440.     return INI_NO_FREE_SLOT; // вернем код ошибки
  441.     // ------------
  442. }
  443.  
  444.  
  445.  
  446.  
  447. /*
  448.     Закрывает INI файл, если он был открыт.
  449.  
  450.     ПОДРОБНЕЕ
  451.         Если файл не был изменен - освободит слот для хранения файла в ОЗУ.
  452.         Если файл был изменен - полностью перезапишет файл на диске.
  453.  
  454.     ПАРАМЕТРЫ:
  455.         nFilePointer    ИД_открытого_файла, полученный от ini_openFile / ini_createFile
  456.  
  457.     ВЕРНЕТ:
  458.         код ошибки < 0 или 0 при успехе
  459. */
  460.  
  461. stock ini_closeFile ( nFilePointer )
  462. {
  463.     if
  464.     (   // если ИД открытого файла указан верно
  465.             nFilePointer >= 0
  466.         &&  nFilePointer < INI_MAX_OPENED_FILES
  467.         &&  _ini_nSlotUsed[nFilePointer] != 0
  468.     )
  469.     {
  470.         if ( _ini_nFileChanged[nFilePointer] != 0 ) // если файл был изменен
  471.         {
  472.             new File: pFile = fopen( _ini_szFilePath[nFilePointer], io_write ); // пытаемся открыть файл для записи
  473.  
  474.             if ( ! pFile ) // если файл не открылся
  475.                 return INI_WRITE_ERROR; // вернем код ошибки
  476.  
  477.             // запишем контент файла из ОЗУ на диск
  478.             for ( new i = 0;  i < _ini_nFileSize[nFilePointer];  i++ )
  479.                 fputchar( pFile, _ini_szFileContent[nFilePointer]{i}, false );
  480.  
  481.             fclose(pFile); // закроем файл
  482.         }
  483.  
  484.         _ini_nSlotUsed[nFilePointer] = 0; // освободить слот открытого файла
  485.  
  486.         return INI_OK; // вернуть код об успешном выполнении функции
  487.     }
  488.  
  489.     return INI_WRONG_SLOT; // вернуть код: неверный указатель на открытый файл
  490. }
  491.  
  492.  
  493.  
  494.  
  495.  
  496.  
  497.  
  498.  
  499.  
  500.  
  501.  
  502. /*
  503.     Получает из открытого INI файла значение указанного ключа.
  504.  
  505.     ПОДРОБНЕЕ
  506.         Парсер ищет в ОЗУ в контенте файла указанный ключ и помещает в
  507.         szReturnValue его строковое значение. szReturnValue нужно создать заранее.
  508.         nSizeOfReturn можно не указывать, если только не нужно точное кол-во
  509.         возвращаемых символов в строке.
  510.         Как ключ так и значение в файле, могут быть любой длины и
  511.         могут содержать любые символы, кроме 2 символов конца строки \r и \n.
  512.         Парсер не видит пробелы и знаки табуляции вокруг имени ключа и
  513.         перед значением, он считает их отступами.
  514.  
  515.     ПАРАМЕТРЫ:
  516.         nFilePointer        ИД_открытого_файла, полученный от ini_openFile / ini_createFile
  517.         szKeyName[]         имя ключа
  518.         szReturnValue[]     сюда будет помещено значение ключа в виде строки
  519.         nSizeOfReturn       макс. размер возвращаемой строки, обычно, это размер szReturnValue
  520.  
  521.     ВЕРНЕТ:
  522.         код ошибки < 0 или 0 при успехе
  523. */
  524.  
  525. stock ini_getString ( nFilePointer, szKeyName[], szReturnValue[], nSizeOfReturn = sizeof(szReturnValue) )
  526. {
  527.     // ----------------
  528.     if // если ИД открытого файла указан неверно
  529.     (
  530.             nFilePointer < 0
  531.         ||  nFilePointer >= INI_MAX_OPENED_FILES
  532.         ||  _ini_nSlotUsed[nFilePointer] != 1
  533.     )
  534.         return INI_WRONG_SLOT; // вернуть код: неверный указатель на открытый файл
  535.     // ----------------
  536.  
  537.  
  538.     // ----------------
  539.     new nKeyLen = strlen(szKeyName); // узнаем длину имени указанного ключа
  540.  
  541.     if ( nKeyLen <= 0 ) // если указан пустой ключ
  542.         return INI_KEY_NOT_FOUND;
  543.     // ----------------
  544.  
  545.  
  546.     // ----------------
  547.     for // перебор и сравнение всех ключей файла с указанным ключом
  548.     (
  549.         new kPos = 0, curFilePos, found = 0;
  550.         kPos < _ini_nKeysCount[nFilePointer];
  551.         kPos++
  552.     )
  553.     {
  554.         // ----------------
  555.         found = 0; // флаг, найдена ли позиция конца ключа = 0
  556.  
  557.         for // ищем позицию конца ключа
  558.         (
  559.             curFilePos = _ini_nDelimPos[nFilePointer][kPos] - 1; // текущ. поз. файла = поз. текущ. INI_DELIMITER - 1
  560.             curFilePos >= 0; // продолжать пока поз. файла >= 0
  561.             curFilePos-- // после каждого повтора текущ. поз. файла -= 1
  562.         )
  563.         {
  564.             switch ( _ini_szFileContent[nFilePointer]{curFilePos} ) // узнаем что за символ в текущ. поз. файла
  565.             {
  566.                 case INI_SPACE_CHAR :           continue; // если это пробельный символ, перейдем к пред. символу файла
  567.                 case INI_STRING_DELIMITER :     break; // если это конец строки
  568.                 default : // если это другой символ
  569.                 {
  570.                     found = 1; // позиция конца ключа найдена
  571.                     break; // конец цикла
  572.                 }
  573.             }
  574.         }
  575.  
  576.         // если позиция конца ключа не найдена, переход к след. позиции INI_DELIMITER
  577.         if ( found != 1 ) continue;
  578.         // ----------------
  579.  
  580.  
  581.         // сравниваем посимвольно текущий ключ файла и указанный ключ
  582.         for ( new curKeyPos = nKeyLen - 1;  curKeyPos >= 0;  curFilePos--, curKeyPos-- )
  583.         {
  584.             if
  585.             (
  586.                     curFilePos < 0 // если поз файла стала < 0
  587.                 ||  _ini_szFileContent[nFilePointer]{curFilePos} != szKeyName[curKeyPos] // если символы из ключей не равны
  588.                 ||  _ini_szFileContent[nFilePointer]{curFilePos} == INI_STRING_DELIMITER // если символ из ключа это INI_STRING_DELIMITER
  589.             )
  590.             {
  591.                 found = 0; // флаг, ключ не найден
  592.                 break; // конец сравнения
  593.             }
  594.         }
  595.  
  596.  
  597.         // ----------------
  598.         if ( found != 0 ) // если указанный ключ найден в файле
  599.         {
  600.             // ----------------
  601.             // текущая позиция в файле будет на 1 больше текущей позиции INI_DELIMITER
  602.             curFilePos = _ini_nDelimPos[nFilePointer][kPos] + 1;
  603.  
  604.             // ищем позицию начала значения, она будет помещена в curFilePos
  605.             for ( ; ; curFilePos++ )
  606.             {
  607.                 if ( curFilePos >= _ini_nFileSize[nFilePointer] ) break;
  608.  
  609.                 switch ( _ini_szFileContent[nFilePointer]{curFilePos} )
  610.                 {
  611.                     case INI_SPACE_CHAR :   continue; // если это пробельный символ, перейдем к след. символу
  612.                     default :               break; // если это другой символ
  613.                 }
  614.             }
  615.             // ----------------
  616.  
  617.  
  618.             // ----------------
  619.             // скопируем посимвольно в szReturnValue значение ключа из файла
  620.             // воспользуемся созданной переменной found как позицией в возвращаемом значении
  621.             for ( found = 0;  found < nSizeOfReturn;  found++, curFilePos++ )
  622.             {
  623.                 switch ( _ini_szFileContent[nFilePointer]{curFilePos} )
  624.                 {
  625.                     case INI_STRING_ENDS : // если это символ конца значения
  626.                     {
  627.                         szReturnValue[found] = 0; // запишем символ конца строки
  628.                         break; // конец копирования
  629.                     }
  630.                     default :
  631.                         // копируем символ из файла в szReturnValue
  632.                         szReturnValue[found] = _ini_szFileContent[nFilePointer]{curFilePos};
  633.                 }
  634.             }
  635.  
  636.             szReturnValue[nSizeOfReturn - 1] = 0; // на всякий случай обрежем правильно строку
  637.  
  638.             return INI_OK;
  639.             // ----------------
  640.         }
  641.         // ----------------
  642.     }
  643.     // ----------------
  644.  
  645.  
  646.     // ----------------
  647.     return INI_KEY_NOT_FOUND;
  648.     // ----------------
  649. }
  650.  
  651.  
  652.  
  653.  
  654. /*
  655.     Получает из открытого INI файла целочисленное значение указанного ключа.
  656.  
  657.     ПОДРОБНЕЕ
  658.         Парсер ищет в ОЗУ в контенте файла указанный ключ и помещает в
  659.         nReturnValue его целочисленное значение. nReturnValue нужно создать заранее.
  660.         Имя ключа в файле может быть любой длины, а также может содержать
  661.         любые символы, кроме 2 символов конца строки \r и \n.
  662.         Значение может быть только фиксированной длины, которая равна INI_INTEGER_SIZE - 1.
  663.         Парсер не видит пробелы и знаки табуляции вокруг имени ключа/значения,
  664.         он считает их отступами.
  665.  
  666.     ПАРАМЕТРЫ:
  667.         nFilePointer        ИД_открытого_файла, полученный от ini_openFile / ini_createFile
  668.         szKeyName[]         имя ключа
  669.         nReturnValue        сюда будет помещено значение ключа в виде целого числа
  670.  
  671.     ВЕРНЕТ:
  672.         код ошибки < 0 или 0 при успехе
  673. */
  674.  
  675. stock ini_getInteger ( nFilePointer, szKeyName[], & nReturnValue )
  676. {
  677.     // ----------------
  678.     if // если ИД открытого файла указан неверно
  679.     (
  680.             nFilePointer < 0
  681.         ||  nFilePointer >= INI_MAX_OPENED_FILES
  682.         ||  _ini_nSlotUsed[nFilePointer] != 1
  683.     )
  684.         return INI_WRONG_SLOT; // вернуть код: неверный указатель на открытый файл
  685.     // ----------------
  686.  
  687.  
  688.     // ----------------
  689.     new nKeyLen = strlen(szKeyName); // узнаем длину имени указанного ключа
  690.  
  691.     if ( nKeyLen <= 0 ) // если указан пустой ключ
  692.         return INI_KEY_NOT_FOUND;
  693.     // ----------------
  694.  
  695.  
  696.     // ----------------
  697.     for // перебор и сравнение всех ключей файла с указанным ключом
  698.     (
  699.         new kPos = 0, curFilePos, found = 0;
  700.         kPos < _ini_nKeysCount[nFilePointer];
  701.         kPos++
  702.     )
  703.     {
  704.         // ----------------
  705.         found = 0; // флаг, найдена ли позиция конца ключа = 0
  706.  
  707.         for // ищем позицию конца ключа
  708.         (
  709.             curFilePos = _ini_nDelimPos[nFilePointer][kPos] - 1; // текущ. поз. файла = поз. текущ. INI_DELIMITER - 1
  710.             curFilePos >= 0; // продолжать пока поз. файла >= 0
  711.             curFilePos-- // после каждого повтора текущ. поз. файла -= 1
  712.         )
  713.         {
  714.             switch ( _ini_szFileContent[nFilePointer]{curFilePos} ) // узнаем что за символ в текущ. поз. файла
  715.             {
  716.                 case INI_SPACE_CHAR :           continue; // если это пробельный символ, перейдем к пред. символу файла
  717.                 case INI_STRING_DELIMITER :     break; // если это конец строки
  718.                 default : // если это другой символ
  719.                 {
  720.                     found = 1; // позиция конца ключа найдена
  721.                     break; // конец цикла
  722.                 }
  723.             }
  724.         }
  725.  
  726.         // если позиция конца ключа не найдена, переход к след. позиции INI_DELIMITER
  727.         if ( found != 1 ) continue;
  728.         // ----------------
  729.  
  730.  
  731.         // сравниваем посимвольно текущий ключ файла и указанный ключ
  732.         for ( new curKeyPos = nKeyLen - 1;  curKeyPos >= 0;  curFilePos--, curKeyPos-- )
  733.         {
  734.             if
  735.             (
  736.                     curFilePos < 0 // если поз файла стала < 0
  737.                 ||  _ini_szFileContent[nFilePointer]{curFilePos} != szKeyName[curKeyPos] // если символы из ключей не равны
  738.                 ||  _ini_szFileContent[nFilePointer]{curFilePos} == INI_STRING_DELIMITER // если символ из ключа это INI_STRING_DELIMITER
  739.             )
  740.             {
  741.                 found = 0; // флаг, ключ не найден
  742.                 break; // конец сравнения
  743.             }
  744.         }
  745.  
  746.  
  747.         // ----------------
  748.         if ( found != 0 ) // если указанный ключ найден в файле
  749.         {
  750.             // ----------------
  751.             // текущая позиция в файле будет на 1 больше текущей позиции INI_DELIMITER
  752.             curFilePos = _ini_nDelimPos[nFilePointer][kPos] + 1;
  753.  
  754.             // ищем позицию начала значения, она будет помещена в curFilePos
  755.             for ( ; ; curFilePos++ )
  756.             {
  757.                 if ( curFilePos >= _ini_nFileSize[nFilePointer] ) break;
  758.  
  759.                 switch ( _ini_szFileContent[nFilePointer]{curFilePos} )
  760.                 {
  761.                     case INI_SPACE_CHAR :   continue; // если это пробельный символ, перейдем к след. символу
  762.                     default :               break; // если это другой символ
  763.                 }
  764.             }
  765.             // ----------------
  766.  
  767.  
  768.             // ----------------
  769.             new strValue[INI_INTEGER_SIZE]; // временная строка для численного значения
  770.  
  771.             // скопируем посимвольно в strValue значение ключа из файла
  772.             // воспользуемся созданной переменной found как позицией в возвращаемом значении
  773.             for ( found = 0;  found < INI_INTEGER_SIZE;  found++, curFilePos++ )
  774.             {
  775.                 switch ( _ini_szFileContent[nFilePointer]{curFilePos} )
  776.                 {
  777.                     case INI_NUMBER_ENDS : // если это символ конца численного значения
  778.                     {
  779.                         strValue[found] = 0; // запишем символ конца строки
  780.                         break; // конец копирования
  781.                     }
  782.                     default :
  783.                         // копируем символ из файла в strValue
  784.                         strValue[found] = _ini_szFileContent[nFilePointer]{curFilePos};
  785.                 }
  786.             }
  787.  
  788.             strValue[INI_INTEGER_SIZE - 1] = 0; // на всякий случай обрежем правильно строку
  789.  
  790.             nReturnValue = strval(strValue); // запишем в nReturnValue численное значение ключа
  791.  
  792.             return INI_OK;
  793.             // ----------------
  794.         }
  795.         // ----------------
  796.     }
  797.     // ----------------
  798.  
  799.  
  800.     // ----------------
  801.     return INI_KEY_NOT_FOUND;
  802.     // ----------------
  803. }
  804.  
  805.  
  806.  
  807.  
  808. /*
  809.     Получает из открытого INI файла дробное численное значение указанного ключа.
  810.  
  811.     ПОДРОБНЕЕ
  812.         Парсер ищет в ОЗУ в контенте файла указанный ключ и помещает в
  813.         fReturnValue его дробное значение. fReturnValue нужно создать заранее.
  814.         Имя ключа в файле может быть любой длины, а также может содержать
  815.         любые символы, кроме 2 символов конца строки \r и \n.
  816.         Значение может быть только фиксированной длины, которая равна INI_FLOAT_SIZE - 1.
  817.         Парсер не видит пробелы и знаки табуляции вокруг имени ключа/значения,
  818.         он считает их отступами.
  819.  
  820.     ПАРАМЕТРЫ:
  821.         nFilePointer        ИД_открытого_файла, полученный от ini_openFile / ini_createFile
  822.         szKeyName[]         имя ключа
  823.         fReturnValue        сюда будет помещено значение ключа в виде дробного числа
  824.  
  825.     ВЕРНЕТ:
  826.         код ошибки < 0 или 0 при успехе
  827. */
  828.  
  829. stock ini_getFloat ( nFilePointer, szKeyName[], & Float: fReturnValue )
  830. {
  831.     // ----------------
  832.     if // если ИД открытого файла указан неверно
  833.     (
  834.             nFilePointer < 0
  835.         ||  nFilePointer >= INI_MAX_OPENED_FILES
  836.         ||  _ini_nSlotUsed[nFilePointer] != 1
  837.     )
  838.         return INI_WRONG_SLOT; // вернуть код: неверный указатель на открытый файл
  839.     // ----------------
  840.  
  841.  
  842.     // ----------------
  843.     new nKeyLen = strlen(szKeyName); // узнаем длину имени указанного ключа
  844.  
  845.     if ( nKeyLen <= 0 ) // если указан пустой ключ
  846.         return INI_KEY_NOT_FOUND;
  847.     // ----------------
  848.  
  849.  
  850.     // ----------------
  851.     for // перебор и сравнение всех ключей файла с указанным ключом
  852.     (
  853.         new kPos = 0, curFilePos, found = 0;
  854.         kPos < _ini_nKeysCount[nFilePointer];
  855.         kPos++
  856.     )
  857.     {
  858.         // ----------------
  859.         found = 0; // флаг, найдена ли позиция конца ключа = 0
  860.  
  861.         for // ищем позицию конца ключа
  862.         (
  863.             curFilePos = _ini_nDelimPos[nFilePointer][kPos] - 1; // текущ. поз. файла = поз. текущ. INI_DELIMITER - 1
  864.             curFilePos >= 0; // продолжать пока поз. файла >= 0
  865.             curFilePos-- // после каждого повтора текущ. поз. файла -= 1
  866.         )
  867.         {
  868.             switch ( _ini_szFileContent[nFilePointer]{curFilePos} ) // узнаем что за символ в текущ. поз. файла
  869.             {
  870.                 case INI_SPACE_CHAR :           continue; // если это пробельный символ, перейдем к пред. символу файла
  871.                 case INI_STRING_DELIMITER :     break; // если это конец строки
  872.                 default : // если это другой символ
  873.                 {
  874.                     found = 1; // позиция конца ключа найдена
  875.                     break; // конец цикла
  876.                 }
  877.             }
  878.         }
  879.  
  880.         // если позиция конца ключа не найдена, переход к след. позиции INI_DELIMITER
  881.         if ( found != 1 ) continue;
  882.         // ----------------
  883.  
  884.  
  885.         // сравниваем посимвольно текущий ключ файла и указанный ключ
  886.         for ( new curKeyPos = nKeyLen - 1;  curKeyPos >= 0;  curFilePos--, curKeyPos-- )
  887.         {
  888.             if
  889.             (
  890.                     curFilePos < 0 // если поз файла стала < 0
  891.                 ||  _ini_szFileContent[nFilePointer]{curFilePos} != szKeyName[curKeyPos] // если символы из ключей не равны
  892.                 ||  _ini_szFileContent[nFilePointer]{curFilePos} == INI_STRING_DELIMITER // если символ из ключа это INI_STRING_DELIMITER
  893.             )
  894.             {
  895.                 found = 0; // флаг, ключ не найден
  896.                 break; // конец сравнения
  897.             }
  898.         }
  899.  
  900.  
  901.         // ----------------
  902.         if ( found != 0 ) // если указанный ключ найден в файле
  903.         {
  904.             // ----------------
  905.             // текущая позиция в файле будет на 1 больше текущей позиции INI_DELIMITER
  906.             curFilePos = _ini_nDelimPos[nFilePointer][kPos] + 1;
  907.  
  908.             // ищем позицию начала значения, она будет помещена в curFilePos
  909.             for ( ; ; curFilePos++ )
  910.             {
  911.                 if ( curFilePos >= _ini_nFileSize[nFilePointer] ) break;
  912.  
  913.                 switch ( _ini_szFileContent[nFilePointer]{curFilePos} )
  914.                 {
  915.                     case INI_SPACE_CHAR :   continue; // если это пробельный символ, перейдем к след. символу
  916.                     default :               break; // если это другой символ
  917.                 }
  918.             }
  919.             // ----------------
  920.  
  921.  
  922.             // ----------------
  923.             new strValue[INI_FLOAT_SIZE]; // временная строка для дробного значения
  924.  
  925.             // скопируем посимвольно в strValue значение ключа из файла
  926.             // воспользуемся созданной переменной found как позицией в возвращаемом значении
  927.             for ( found = 0;  found < INI_INTEGER_SIZE;  found++, curFilePos++ )
  928.             {
  929.                 switch ( _ini_szFileContent[nFilePointer]{curFilePos} )
  930.                 {
  931.                     case INI_NUMBER_ENDS : // если это символ конца численного значения
  932.                     {
  933.                         strValue[found] = 0; // запишем символ конца строки
  934.                         break; // конец копирования
  935.                     }
  936.                     default :
  937.                         // копируем символ из файла в strValue
  938.                         strValue[found] = _ini_szFileContent[nFilePointer]{curFilePos};
  939.                 }
  940.             }
  941.  
  942.             strValue[INI_FLOAT_SIZE - 1] = 0; // на всякий случай обрежем правильно строку
  943.  
  944.             fReturnValue = floatstr(strValue); // запишем в fReturnValue дробное значение ключа
  945.  
  946.             return INI_OK;
  947.             // ----------------
  948.         }
  949.         // ----------------
  950.     }
  951.     // ----------------
  952.  
  953.  
  954.     // ----------------
  955.     return INI_KEY_NOT_FOUND;
  956.     // ----------------
  957. }
  958.  
  959.  
  960.  
  961.  
  962.  
  963.  
  964.  
  965.  
  966.  
  967.  
  968.  
  969. /*
  970.     Изменяет/добавляет в открытый INI файл указанный ключ и его значение.
  971.  
  972.     ПОДРОБНЕЕ
  973.         Парсер ищет в ОЗУ в контенте файла указанный ключ и изменяет его
  974.         строковое значение на szKeyValue. Форматирование файла не меняется,
  975.         если только указанное имя ключа не было найдено, тогда ключ и значение
  976.         будут добавлены в конец файла.
  977.         Имя ключа/значение в файле может быть любой длины, а также может содержать
  978.         любые символы, кроме 2 символов конца строки \r и \n. Если эти символы есть
  979.         в имени ключа или в значении, вы должны должны хорошо знать и осознавать
  980.         последствия.
  981.  
  982.     ПАРАМЕТРЫ:
  983.         nFilePointer        ИД_открытого_файла, полученный от ini_openFile / ini_createFile
  984.         szKeyName[]         имя ключа
  985.         szKeyValue[]        строка со значением ключа
  986.  
  987.     ВЕРНЕТ:
  988.         код ошибки < 0 или 0 при успехе
  989. */
  990.  
  991. stock ini_setString ( nFilePointer, szKeyName[], szKeyValue[] )
  992. {
  993.     // ----------------
  994.     if // если ИД открытого файла указан неверно
  995.     (
  996.             nFilePointer < 0
  997.         ||  nFilePointer >= INI_MAX_OPENED_FILES
  998.         ||  _ini_nSlotUsed[nFilePointer] != 1
  999.     )
  1000.         return INI_WRONG_SLOT; // вернуть код: неверный указатель на открытый файл
  1001.     // ----------------
  1002.  
  1003.  
  1004.     // ----------------
  1005.     new nKeyLen = strlen(szKeyName); // узнаем длину имени указанного ключа
  1006.  
  1007.     if ( nKeyLen <= 0 ) // если указан пустой ключ
  1008.         return INI_KEY_NOT_FOUND;
  1009.     // ----------------
  1010.  
  1011.  
  1012.     // ----------------
  1013.     for // перебор и сравнение всех ключей файла с указанным ключом
  1014.     (
  1015.         new kPos = 0, curFilePos, found;
  1016.         kPos < _ini_nKeysCount[nFilePointer];
  1017.         kPos++
  1018.     )
  1019.     {
  1020.         // ----------------
  1021.         found = 0; // флаг, найдена ли позиция конца ключа = 0
  1022.  
  1023.         for // ищем позицию конца ключа
  1024.         (
  1025.             curFilePos = _ini_nDelimPos[nFilePointer][kPos] - 1; // текущ. поз. файла = поз. текущ. INI_DELIMITER - 1
  1026.             curFilePos >= 0; // продолжать пока поз. файла >= 0
  1027.             curFilePos-- // после каждого повтора текущ. поз. файла -= 1
  1028.         )
  1029.         {
  1030.             switch ( _ini_szFileContent[nFilePointer]{curFilePos} ) // узнаем что за символ в текущ. поз. файла
  1031.             {
  1032.                 case INI_SPACE_CHAR :           continue; // если это пробельный символ, перейдем к пред. символу файла
  1033.                 case INI_STRING_DELIMITER :     break; // если это конец строки
  1034.                 default : // если это другой символ
  1035.                 {
  1036.                     found = 1; // позиция конца ключа найдена
  1037.                     break; // конец цикла
  1038.                 }
  1039.             }
  1040.         }
  1041.  
  1042.         // если позиция конца ключа не найдена, переход к след. позиции INI_DELIMITER
  1043.         if ( found != 1 ) continue;
  1044.         // ----------------
  1045.  
  1046.  
  1047.         // сравниваем посимвольно текущий ключ файла и указанный ключ
  1048.         for ( new curKeyPos = nKeyLen - 1;  curKeyPos >= 0;  curFilePos--, curKeyPos-- )
  1049.         {
  1050.             if
  1051.             (
  1052.                     curFilePos < 0 // если поз файла стала < 0
  1053.                 ||  _ini_szFileContent[nFilePointer]{curFilePos} != szKeyName[curKeyPos] // если символы из ключей не равны
  1054.                 ||  _ini_szFileContent[nFilePointer]{curFilePos} == INI_STRING_DELIMITER // если символ из ключа это INI_STRING_DELIMITER
  1055.             )
  1056.             {
  1057.                 found = 0; // флаг, ключ не найден
  1058.                 break; // конец сравнения
  1059.             }
  1060.         }
  1061.  
  1062.  
  1063.         if ( found != 0 ) // если указанный ключ НАЙДЕН в файле
  1064.         {
  1065.             // ----------------
  1066.             // текущая позиция в файле будет на 1 больше текущей позиции INI_DELIMITER
  1067.             curFilePos = _ini_nDelimPos[nFilePointer][kPos] + 1;
  1068.  
  1069.             // ищем позицию начала значения, она будет помещена в curFilePos
  1070.             for ( ; ; curFilePos++ )
  1071.             {
  1072.                 if ( curFilePos >= _ini_nFileSize[nFilePointer] ) break;
  1073.  
  1074.                 switch ( _ini_szFileContent[nFilePointer]{curFilePos} )
  1075.                 {
  1076.                     case INI_SPACE_CHAR :   continue; // если это пробельный символ, перейдем к след. символу
  1077.                     default :               break; // если это другой символ
  1078.                 }
  1079.             }
  1080.             // ----------------
  1081.  
  1082.  
  1083.             // ----------------
  1084.             new nValueLen = strlen(szKeyValue); // узнаем размер значения указанного ключа
  1085.  
  1086.             // если будущий размер файла превышает лимит
  1087.             if ( ( curFilePos + nValueLen ) >= INI_MAX_FILE_SIZE )
  1088.                 return INI_TOO_LARGE_FILE; // вернем код ошибки о переполнении файла
  1089.             // ----------------
  1090.  
  1091.  
  1092.             // ----------------
  1093.             new fileValueStartPos = curFilePos; // сохраним позицию начала значения
  1094.  
  1095.             // ищем позицию конца значения, она будет помещена в curFilePos
  1096.             for ( ; ; curFilePos++ )
  1097.             {
  1098.                 if ( curFilePos >= _ini_nFileSize[nFilePointer] ) break;
  1099.  
  1100.                 switch ( _ini_szFileContent[nFilePointer]{curFilePos} )
  1101.                 {
  1102.                     case INI_STRING_ENDS :  break; // если это конец строки - стоп
  1103.                     default :               continue; // если это другой символ, перейдем к след. символу
  1104.                 }
  1105.             }
  1106.  
  1107.             // вычислим смещение оставшихся позиций для INI_DELIMITER после изменения значения
  1108.             new filePosOffset = nValueLen - ( /*текущ длина значения*/ curFilePos - fileValueStartPos );
  1109.             // ----------------
  1110.  
  1111.  
  1112.             if ( _ini_nFileBusy[nFilePointer] != 0 ) // если прямо сейчас файл изменяется другой функцией
  1113.                 return INI_WRITE_ERROR; // вернем код ошибки при записи в файл
  1114.  
  1115.  
  1116.             // ----------------
  1117.             _ini_nFileBusy[nFilePointer] = 1; // флаг: файл изменяется = 1
  1118.  
  1119.             if ( filePosOffset != 0 ) // если длины старого и нового значений разные
  1120.             {
  1121.                 if ( filePosOffset < 0 ) // если длина нового значения меньше
  1122.                 {
  1123.                     for // копируем символы, стоящие после текущего значения на их новые места,
  1124.                     ( // которые теперь будут ближе к началу файла
  1125.                         ;
  1126.                         curFilePos < _ini_nFileSize[nFilePointer];
  1127.                         curFilePos++
  1128.                     )
  1129.                         _ini_szFileContent[nFilePointer]{ curFilePos + filePosOffset } =
  1130.                             _ini_szFileContent[nFilePointer]{curFilePos};
  1131.                 }
  1132.                 else if ( filePosOffset > 0 ) // если длина нового значения больше
  1133.                 {
  1134.                     new fileValueEndPos = curFilePos;
  1135.  
  1136.                     for // копируем символы, стоящие после текущего значения на их новые места,
  1137.                     ( // начиная с конца файла
  1138.                         curFilePos = _ini_nFileSize[nFilePointer] - 1;
  1139.                         curFilePos >= fileValueEndPos;
  1140.                         curFilePos--
  1141.                     )
  1142.                         _ini_szFileContent[nFilePointer]{ curFilePos + filePosOffset } =
  1143.                             _ini_szFileContent[nFilePointer]{curFilePos};
  1144.                 }
  1145.  
  1146.                 // изменим позиции всех INI_DELIMITER, которые находились после текущего INI_DELIMITER
  1147.                 for ( kPos++;  kPos < _ini_nKeysCount[nFilePointer];  kPos++ )
  1148.                     _ini_nDelimPos[nFilePointer][kPos] += filePosOffset;
  1149.  
  1150.                 _ini_nFileSize[nFilePointer] += filePosOffset; // изменим размер файла
  1151.                 _ini_szFileContent[nFilePointer]{ _ini_nFileSize[nFilePointer] } = 0; // конец строки для конца файла
  1152.             }
  1153.  
  1154.             curFilePos = fileValueStartPos; // текущ поз файла = поз начала старого значения
  1155.             for // запишем новое значение поверх старого
  1156.             (
  1157.                 new valuePos = 0;
  1158.                 valuePos < nValueLen;
  1159.                 curFilePos++, valuePos++
  1160.             )
  1161.                 _ini_szFileContent[nFilePointer]{curFilePos} = szKeyValue[valuePos];
  1162.  
  1163.             _ini_nFileChanged[nFilePointer]     = 1; // флаг: файл изменен = 1
  1164.             _ini_nFileBusy[nFilePointer]        = 0; // флаг: файл изменяется = 0
  1165.  
  1166.             return INI_OK;
  1167.             // ----------------
  1168.         }
  1169.     }
  1170.     // ----------------
  1171.  
  1172.  
  1173.     //
  1174.     // если указанный ключ НЕ НАЙДЕН в файле
  1175.     //
  1176.  
  1177.     // ----------------
  1178.     new nValueLen = strlen(szKeyValue); // узнаем размер значения ключа
  1179.  
  1180.     // если будущий размер файла превышает лимит
  1181.     if ( ( _ini_nFileSize[nFilePointer] + 5 + nKeyLen + nValueLen ) >= INI_MAX_FILE_SIZE )
  1182.         return INI_TOO_LARGE_FILE; // вернем код ошибки о переполнении файла
  1183.     // ----------------
  1184.  
  1185.  
  1186.     // ----------------
  1187.     if ( _ini_nFileBusy[nFilePointer] != 0 ) // если прямо сейчас файл изменяется другой функцией
  1188.         return INI_WRITE_ERROR; // вернем код ошибки при записи в файл
  1189.  
  1190.     _ini_nFileBusy[nFilePointer] = 1; // флаг: файл изменяется = 1
  1191.     // ----------------
  1192.  
  1193.  
  1194.     // ----------------
  1195.     if // если последний символ файла не является разделителем строк
  1196.     (
  1197.             _ini_nFileSize[nFilePointer] > 0
  1198.         &&  _ini_szFileContent[nFilePointer]{ _ini_nFileSize[nFilePointer] - 1 } != INI_STRING_DELIMITER
  1199.     )
  1200.     {
  1201.         // вставим в конец файла перевод каретки и разделитель строк
  1202.         _ini_szFileContent[nFilePointer]{ _ini_nFileSize[nFilePointer] }        = '\r';
  1203.         _ini_szFileContent[nFilePointer]{ _ini_nFileSize[nFilePointer] + 1 }    = INI_STRING_DELIMITER;
  1204.  
  1205.         _ini_nFileSize[nFilePointer] += 2; // увеличим размер файла на 2
  1206.     }
  1207.  
  1208.     new curFilePos, strPos; // будут временным хранилищами позиций в файле/ключе/значении
  1209.  
  1210.     for // добавим посимвольно имя ключа в файл
  1211.     (
  1212.         curFilePos = _ini_nFileSize[nFilePointer], strPos = 0;
  1213.         strPos < nKeyLen;
  1214.         curFilePos++, strPos++
  1215.     )
  1216.         _ini_szFileContent[nFilePointer]{curFilePos} = szKeyName[strPos];
  1217.  
  1218.     _ini_szFileContent[nFilePointer]{ curFilePos++ }                = ' '; // после ключа добавим пробел
  1219.  
  1220.     _ini_nDelimPos[nFilePointer][ _ini_nKeysCount[nFilePointer] ]   = curFilePos; // добавим новую позицию INI_DELIMITER
  1221.     _ini_nKeysCount[nFilePointer]++; // кол-во ключей в файле +1
  1222.  
  1223.     _ini_szFileContent[nFilePointer]{ curFilePos++ }                = INI_DELIMITER; // после пробела выше добавим INI_DELIMITER
  1224.     _ini_szFileContent[nFilePointer]{ curFilePos++ }                = ' '; // после INI_DELIMITER добавим пробел
  1225.  
  1226.     // добавим посимвольно значение ключа в файл
  1227.     for ( strPos = 0;  strPos < nValueLen;  curFilePos++, strPos++ )
  1228.         _ini_szFileContent[nFilePointer]{curFilePos} = szKeyValue[strPos];
  1229.  
  1230.     _ini_szFileContent[nFilePointer]{curFilePos}    = 0; // добавим символ конца строки
  1231.     _ini_nFileSize[nFilePointer]                    = curFilePos; // изменим размер файла
  1232.     _ini_nFileChanged[nFilePointer]                 = 1; // флаг: файл изменен = 1
  1233.     _ini_nFileBusy[nFilePointer]                    = 0; // флаг: файл изменяется = 0
  1234.  
  1235.     return INI_OK;
  1236.     // ----------------
  1237. }
  1238.  
  1239.  
  1240.  
  1241.  
  1242. /*
  1243.     Изменяет/добавляет в открытый INI файл указанный ключ и его целочисленное значение.
  1244.  
  1245.     ПОДРОБНЕЕ
  1246.         Парсер ищет в ОЗУ в контенте файла указанный ключ и изменяет его
  1247.         целочисленное значение на nKeyValue. Форматирование файла не меняется,
  1248.         если только указанное имя ключа не было найдено, тогда ключ и значение
  1249.         будут добавлены в конец файла.
  1250.         Имя ключа в файле может быть любой длины, а также может содержать
  1251.         любые символы, кроме 2 символов конца строки \r и \n. Если вы в качестве
  1252.         значения указываете число больше, чем cellmax или меньше, чем cellmin,
  1253.         вы должны должны хорошо знать и осознавать последствия.
  1254.  
  1255.     ПАРАМЕТРЫ:
  1256.         nFilePointer        ИД_открытого_файла, полученный от ini_openFile / ini_createFile
  1257.         szKeyName[]         имя ключа
  1258.         nKeyValue           целочисленное значение ключа
  1259.  
  1260.     ВЕРНЕТ:
  1261.         код ошибки < 0 или 0 при успехе
  1262. */
  1263.  
  1264. stock ini_setInteger ( nFilePointer, szKeyName[], nKeyValue )
  1265. {
  1266.     // ----------------
  1267.     if // если ИД открытого файла указан неверно
  1268.     (
  1269.             nFilePointer < 0
  1270.         ||  nFilePointer >= INI_MAX_OPENED_FILES
  1271.         ||  _ini_nSlotUsed[nFilePointer] != 1
  1272.     )
  1273.         return INI_WRONG_SLOT; // вернуть код: неверный указатель на открытый файл
  1274.     // ----------------
  1275.  
  1276.  
  1277.     // ----------------
  1278.     new nKeyLen = strlen(szKeyName); // узнаем длину имени указанного ключа
  1279.  
  1280.     if ( nKeyLen <= 0 ) // если указан пустой ключ
  1281.         return INI_KEY_NOT_FOUND;
  1282.     // ----------------
  1283.  
  1284.  
  1285.     // ----------------
  1286.     for // перебор и сравнение всех ключей файла с указанным ключом
  1287.     (
  1288.         new kPos = 0, curFilePos, found;
  1289.         kPos < _ini_nKeysCount[nFilePointer];
  1290.         kPos++
  1291.     )
  1292.     {
  1293.         // ----------------
  1294.         found = 0; // флаг, найдена ли позиция конца ключа = 0
  1295.  
  1296.         for // ищем позицию конца ключа
  1297.         (
  1298.             curFilePos = _ini_nDelimPos[nFilePointer][kPos] - 1; // текущ. поз. файла = поз. текущ. INI_DELIMITER - 1
  1299.             curFilePos >= 0; // продолжать пока поз. файла >= 0
  1300.             curFilePos-- // после каждого повтора текущ. поз. файла -= 1
  1301.         )
  1302.         {
  1303.             switch ( _ini_szFileContent[nFilePointer]{curFilePos} ) // узнаем что за символ в текущ. поз. файла
  1304.             {
  1305.                 case INI_SPACE_CHAR :           continue; // если это пробельный символ, перейдем к пред. символу файла
  1306.                 case INI_STRING_DELIMITER :     break; // если это конец строки
  1307.                 default : // если это другой символ
  1308.                 {
  1309.                     found = 1; // позиция конца ключа найдена
  1310.                     break; // конец цикла
  1311.                 }
  1312.             }
  1313.         }
  1314.  
  1315.         // если позиция конца ключа не найдена, переход к след. позиции INI_DELIMITER
  1316.         if ( found != 1 ) continue;
  1317.         // ----------------
  1318.  
  1319.  
  1320.         // сравниваем посимвольно текущий ключ файла и указанный ключ
  1321.         for ( new curKeyPos = nKeyLen - 1;  curKeyPos >= 0;  curFilePos--, curKeyPos-- )
  1322.         {
  1323.             if
  1324.             (
  1325.                     curFilePos < 0 // если поз файла стала < 0
  1326.                 ||  _ini_szFileContent[nFilePointer]{curFilePos} != szKeyName[curKeyPos] // если символы из ключей не равны
  1327.                 ||  _ini_szFileContent[nFilePointer]{curFilePos} == INI_STRING_DELIMITER // если символ из ключа это INI_STRING_DELIMITER
  1328.             )
  1329.             {
  1330.                 found = 0; // флаг, ключ не найден
  1331.                 break; // конец сравнения
  1332.             }
  1333.         }
  1334.  
  1335.  
  1336.         if ( found != 0 ) // если указанный ключ НАЙДЕН в файле
  1337.         {
  1338.             // ----------------
  1339.             // текущая позиция в файле будет на 1 больше текущей позиции INI_DELIMITER
  1340.             curFilePos = _ini_nDelimPos[nFilePointer][kPos] + 1;
  1341.  
  1342.             // ищем позицию начала значения, она будет помещена в curFilePos
  1343.             for ( ; ; curFilePos++ )
  1344.             {
  1345.                 if ( curFilePos >= _ini_nFileSize[nFilePointer] ) break;
  1346.  
  1347.                 switch ( _ini_szFileContent[nFilePointer]{curFilePos} )
  1348.                 {
  1349.                     case INI_SPACE_CHAR :   continue; // если это пробельный символ, перейдем к след. символу
  1350.                     default :               break; // если это другой символ
  1351.                 }
  1352.             }
  1353.             // ----------------
  1354.  
  1355.  
  1356.             // ----------------
  1357.             new szKeyValue[INI_INTEGER_SIZE]; // создадим строку для хранения целочисленного значения
  1358.             valstr( szKeyValue, nKeyValue, false ); // поместим строковое значение nKeyValue в szKeyValue
  1359.             // ----------------
  1360.  
  1361.  
  1362.             // ----------------
  1363.             new nValueLen = strlen(szKeyValue); // узнаем размер значения указанного ключа
  1364.  
  1365.             // если будущий размер файла превышает лимит
  1366.             if ( ( curFilePos + nValueLen ) >= INI_MAX_FILE_SIZE )
  1367.                 return INI_TOO_LARGE_FILE; // вернем код ошибки о переполнении файла
  1368.             // ----------------
  1369.  
  1370.  
  1371.             // ----------------
  1372.             new fileValueStartPos = curFilePos; // сохраним позицию начала значения
  1373.  
  1374.             // ищем позицию конца значения, она будет помещена в curFilePos
  1375.             for ( ; ; curFilePos++ )
  1376.             {
  1377.                 if ( curFilePos >= _ini_nFileSize[nFilePointer] ) break;
  1378.  
  1379.                 switch ( _ini_szFileContent[nFilePointer]{curFilePos} )
  1380.                 {
  1381.                     case INI_NUMBER_ENDS :  break; // если это конец числа - стоп
  1382.                     default :               continue; // если это другой символ, перейдем к след. символу
  1383.                 }
  1384.             }
  1385.  
  1386.             // вычислим смещение оставшихся позиций для INI_DELIMITER после изменения значения
  1387.             new filePosOffset = nValueLen - ( /*текущ длина значения*/ curFilePos - fileValueStartPos );
  1388.             // ----------------
  1389.  
  1390.  
  1391.             if ( _ini_nFileBusy[nFilePointer] != 0 ) // если прямо сейчас файл изменяется другой функцией
  1392.                 return INI_WRITE_ERROR; // вернем код ошибки при записи в файл
  1393.  
  1394.  
  1395.             // ----------------
  1396.             _ini_nFileBusy[nFilePointer] = 1; // флаг: файл изменяется = 1
  1397.  
  1398.             if ( filePosOffset != 0 ) // если длины старого и нового значений разные
  1399.             {
  1400.                 if ( filePosOffset < 0 ) // если длина нового значения меньше
  1401.                 {
  1402.                     for // копируем символы, стоящие после текущего значения на их новые места,
  1403.                     ( // которые теперь будут ближе к началу файла
  1404.                         ;
  1405.                         curFilePos < _ini_nFileSize[nFilePointer];
  1406.                         curFilePos++
  1407.                     )
  1408.                         _ini_szFileContent[nFilePointer]{ curFilePos + filePosOffset } =
  1409.                             _ini_szFileContent[nFilePointer]{curFilePos};
  1410.                 }
  1411.                 else if ( filePosOffset > 0 ) // если длина нового значения больше
  1412.                 {
  1413.                     new fileValueEndPos = curFilePos;
  1414.  
  1415.                     for // копируем символы, стоящие после текущего значения на их новые места,
  1416.                     ( // начиная с конца файла
  1417.                         curFilePos = _ini_nFileSize[nFilePointer] - 1;
  1418.                         curFilePos >= fileValueEndPos;
  1419.                         curFilePos--
  1420.                     )
  1421.                         _ini_szFileContent[nFilePointer]{ curFilePos + filePosOffset } =
  1422.                             _ini_szFileContent[nFilePointer]{curFilePos};
  1423.                 }
  1424.  
  1425.                 // изменим позиции всех INI_DELIMITER, которые находились после текущего INI_DELIMITER
  1426.                 for ( kPos++;  kPos < _ini_nKeysCount[nFilePointer];  kPos++ )
  1427.                     _ini_nDelimPos[nFilePointer][kPos] += filePosOffset;
  1428.  
  1429.                 _ini_nFileSize[nFilePointer] += filePosOffset; // изменим размер файла
  1430.                 _ini_szFileContent[nFilePointer]{ _ini_nFileSize[nFilePointer] } = 0; // конец строки для конца файла
  1431.             }
  1432.  
  1433.             curFilePos = fileValueStartPos; // текущ поз файла = поз начала старого значения
  1434.             for // запишем новое значение поверх старого
  1435.             (
  1436.                 new valuePos = 0;
  1437.                 valuePos < nValueLen;
  1438.                 curFilePos++, valuePos++
  1439.             )
  1440.                 _ini_szFileContent[nFilePointer]{curFilePos} = szKeyValue[valuePos];
  1441.  
  1442.             _ini_nFileChanged[nFilePointer]     = 1; // флаг: файл изменен = 1
  1443.             _ini_nFileBusy[nFilePointer]        = 0; // флаг: файл изменяется = 0
  1444.  
  1445.             return INI_OK;
  1446.             // ----------------
  1447.         }
  1448.     }
  1449.     // ----------------
  1450.  
  1451.  
  1452.     //
  1453.     // если указанный ключ НЕ НАЙДЕН в файле
  1454.     //
  1455.  
  1456.     // ----------------
  1457.     new szKeyValue[INI_INTEGER_SIZE]; // создадим строку для хранения целочисленного значения
  1458.     valstr( szKeyValue, nKeyValue, false ); // поместим строковое значение nKeyValue в szKeyValue
  1459.     // ----------------
  1460.  
  1461.  
  1462.     // ----------------
  1463.     new nValueLen = strlen(szKeyValue); // узнаем размер значения ключа
  1464.  
  1465.     // если будущий размер файла превышает лимит
  1466.     if ( ( _ini_nFileSize[nFilePointer] + 5 + nKeyLen + nValueLen ) >= INI_MAX_FILE_SIZE )
  1467.         return INI_TOO_LARGE_FILE; // вернем код ошибки о переполнении файла
  1468.     // ----------------
  1469.  
  1470.  
  1471.     // ----------------
  1472.     if ( _ini_nFileBusy[nFilePointer] != 0 ) // если прямо сейчас файл изменяется другой функцией
  1473.         return INI_WRITE_ERROR; // вернем код ошибки при записи в файл
  1474.  
  1475.     _ini_nFileBusy[nFilePointer] = 1; // флаг: файл изменяется = 1
  1476.     // ----------------
  1477.  
  1478.  
  1479.     // ----------------
  1480.     if // если последний символ файла не является разделителем строк
  1481.     (
  1482.             _ini_nFileSize[nFilePointer] > 0
  1483.         &&  _ini_szFileContent[nFilePointer]{ _ini_nFileSize[nFilePointer] - 1 } != INI_STRING_DELIMITER
  1484.     )
  1485.     {
  1486.         // вставим в конец файла перевод каретки и разделитель строк
  1487.         _ini_szFileContent[nFilePointer]{ _ini_nFileSize[nFilePointer] }        = '\r';
  1488.         _ini_szFileContent[nFilePointer]{ _ini_nFileSize[nFilePointer] + 1 }    = INI_STRING_DELIMITER;
  1489.  
  1490.         _ini_nFileSize[nFilePointer] += 2; // увеличим размер файла на 2
  1491.     }
  1492.  
  1493.     new curFilePos, strPos; // будут временным хранилищами позиций в файле/ключе/значении
  1494.  
  1495.     for // добавим посимвольно имя ключа в файл
  1496.     (
  1497.         curFilePos = _ini_nFileSize[nFilePointer], strPos = 0;
  1498.         strPos < nKeyLen;
  1499.         curFilePos++, strPos++
  1500.     )
  1501.         _ini_szFileContent[nFilePointer]{curFilePos} = szKeyName[strPos];
  1502.  
  1503.     _ini_szFileContent[nFilePointer]{ curFilePos++ }                = ' '; // после ключа добавим пробел
  1504.  
  1505.     _ini_nDelimPos[nFilePointer][ _ini_nKeysCount[nFilePointer] ]   = curFilePos; // добавим новую позицию INI_DELIMITER
  1506.     _ini_nKeysCount[nFilePointer]++; // кол-во ключей в файле +1
  1507.  
  1508.     _ini_szFileContent[nFilePointer]{ curFilePos++ }                = INI_DELIMITER; // после пробела выше добавим INI_DELIMITER
  1509.     _ini_szFileContent[nFilePointer]{ curFilePos++ }                = ' '; // после INI_DELIMITER добавим пробел
  1510.  
  1511.     // добавим посимвольно значение ключа в файл
  1512.     for ( strPos = 0;  strPos < nValueLen;  curFilePos++, strPos++ )
  1513.         _ini_szFileContent[nFilePointer]{curFilePos} = szKeyValue[strPos];
  1514.  
  1515.     _ini_szFileContent[nFilePointer]{curFilePos}    = 0; // добавим символ конца строки
  1516.     _ini_nFileSize[nFilePointer]                    = curFilePos; // изменим размер файла
  1517.     _ini_nFileChanged[nFilePointer]                 = 1; // флаг: файл изменен = 1
  1518.     _ini_nFileBusy[nFilePointer]                    = 0; // флаг: файл изменяется = 0
  1519.  
  1520.     return INI_OK;
  1521.     // ----------------
  1522. }
  1523.  
  1524.  
  1525.  
  1526.  
  1527. /*
  1528.     Изменяет/добавляет в открытый INI файл указанный ключ и его дробное численное значение.
  1529.  
  1530.     ПОДРОБНЕЕ
  1531.         Парсер ищет в ОЗУ в контенте файла указанный ключ и изменяет его
  1532.         дробное значение на fKeyValue. Форматирование файла не меняется,
  1533.         если только указанное имя ключа не было найдено, тогда ключ и значение
  1534.         будут добавлены в конец файла.
  1535.         Имя ключа в файле может быть любой длины, а также может содержать
  1536.         любые символы, кроме 2 символов конца строки \r и \n. Если вы в качестве
  1537.         значения указываете очень большое/маленькое дробное число, вы должны
  1538.         хорошо знать и осознавать последствия.
  1539.  
  1540.     ПАРАМЕТРЫ:
  1541.         nFilePointer        ИД_открытого_файла, полученный от ini_openFile / ini_createFile
  1542.         szKeyName[]         имя ключа
  1543.         fKeyValue           дробное численное значение ключа
  1544.  
  1545.     ВЕРНЕТ:
  1546.         код ошибки < 0 или 0 при успехе
  1547. */
  1548.  
  1549. stock ini_setFloat ( nFilePointer, szKeyName[], Float: fKeyValue )
  1550. {
  1551.     // ----------------
  1552.     if // если ИД открытого файла указан неверно
  1553.     (
  1554.             nFilePointer < 0
  1555.         ||  nFilePointer >= INI_MAX_OPENED_FILES
  1556.         ||  _ini_nSlotUsed[nFilePointer] != 1
  1557.     )
  1558.         return INI_WRONG_SLOT; // вернуть код: неверный указатель на открытый файл
  1559.     // ----------------
  1560.  
  1561.  
  1562.     // ----------------
  1563.     new nKeyLen = strlen(szKeyName); // узнаем длину имени указанного ключа
  1564.  
  1565.     if ( nKeyLen <= 0 ) // если указан пустой ключ
  1566.         return INI_KEY_NOT_FOUND;
  1567.     // ----------------
  1568.  
  1569.  
  1570.     // ----------------
  1571.     for // перебор и сравнение всех ключей файла с указанным ключом
  1572.     (
  1573.         new kPos = 0, curFilePos, found;
  1574.         kPos < _ini_nKeysCount[nFilePointer];
  1575.         kPos++
  1576.     )
  1577.     {
  1578.         // ----------------
  1579.         found = 0; // флаг, найдена ли позиция конца ключа = 0
  1580.  
  1581.         for // ищем позицию конца ключа
  1582.         (
  1583.             curFilePos = _ini_nDelimPos[nFilePointer][kPos] - 1; // текущ. поз. файла = поз. текущ. INI_DELIMITER - 1
  1584.             curFilePos >= 0; // продолжать пока поз. файла >= 0
  1585.             curFilePos-- // после каждого повтора текущ. поз. файла -= 1
  1586.         )
  1587.         {
  1588.             switch ( _ini_szFileContent[nFilePointer]{curFilePos} ) // узнаем что за символ в текущ. поз. файла
  1589.             {
  1590.                 case INI_SPACE_CHAR :           continue; // если это пробельный символ, перейдем к пред. символу файла
  1591.                 case INI_STRING_DELIMITER :     break; // если это конец строки
  1592.                 default : // если это другой символ
  1593.                 {
  1594.                     found = 1; // позиция конца ключа найдена
  1595.                     break; // конец цикла
  1596.                 }
  1597.             }
  1598.         }
  1599.  
  1600.         // если позиция конца ключа не найдена, переход к след. позиции INI_DELIMITER
  1601.         if ( found != 1 ) continue;
  1602.         // ----------------
  1603.  
  1604.  
  1605.         // сравниваем посимвольно текущий ключ файла и указанный ключ
  1606.         for ( new curKeyPos = nKeyLen - 1;  curKeyPos >= 0;  curFilePos--, curKeyPos-- )
  1607.         {
  1608.             if
  1609.             (
  1610.                     curFilePos < 0 // если поз файла стала < 0
  1611.                 ||  _ini_szFileContent[nFilePointer]{curFilePos} != szKeyName[curKeyPos] // если символы из ключей не равны
  1612.                 ||  _ini_szFileContent[nFilePointer]{curFilePos} == INI_STRING_DELIMITER // если символ из ключа это INI_STRING_DELIMITER
  1613.             )
  1614.             {
  1615.                 found = 0; // флаг, ключ не найден
  1616.                 break; // конец сравнения
  1617.             }
  1618.         }
  1619.  
  1620.  
  1621.         if ( found != 0 ) // если указанный ключ НАЙДЕН в файле
  1622.         {
  1623.             // ----------------
  1624.             // текущая позиция в файле будет на 1 больше текущей позиции INI_DELIMITER
  1625.             curFilePos = _ini_nDelimPos[nFilePointer][kPos] + 1;
  1626.  
  1627.             // ищем позицию начала значения, она будет помещена в curFilePos
  1628.             for ( ; ; curFilePos++ )
  1629.             {
  1630.                 if ( curFilePos >= _ini_nFileSize[nFilePointer] ) break;
  1631.  
  1632.                 switch ( _ini_szFileContent[nFilePointer]{curFilePos} )
  1633.                 {
  1634.                     case INI_SPACE_CHAR :   continue; // если это пробельный символ, перейдем к след. символу
  1635.                     default :               break; // если это другой символ
  1636.                 }
  1637.             }
  1638.             // ----------------
  1639.  
  1640.  
  1641.             // ----------------
  1642.             new szKeyValue[INI_FLOAT_SIZE]; // создадим строку для хранения дробного значения
  1643.             format( szKeyValue, INI_FLOAT_SIZE, "%f", fKeyValue ); // поместим строковое значение fKeyValue в szKeyValue
  1644.             // ----------------
  1645.  
  1646.  
  1647.             // ----------------
  1648.             new nValueLen = strlen(szKeyValue); // узнаем размер значения указанного ключа
  1649.  
  1650.             // если будущий размер файла превышает лимит
  1651.             if ( ( curFilePos + nValueLen ) >= INI_MAX_FILE_SIZE )
  1652.                 return INI_TOO_LARGE_FILE; // вернем код ошибки о переполнении файла
  1653.             // ----------------
  1654.  
  1655.  
  1656.             // ----------------
  1657.             new fileValueStartPos = curFilePos; // сохраним позицию начала значения
  1658.  
  1659.             // ищем позицию конца значения, она будет помещена в curFilePos
  1660.             for ( ; ; curFilePos++ )
  1661.             {
  1662.                 if ( curFilePos >= _ini_nFileSize[nFilePointer] ) break;
  1663.  
  1664.                 switch ( _ini_szFileContent[nFilePointer]{curFilePos} )
  1665.                 {
  1666.                     case INI_NUMBER_ENDS :  break; // если это конец числа - стоп
  1667.                     default :               continue; // если это другой символ, перейдем к след. символу
  1668.                 }
  1669.             }
  1670.  
  1671.             // вычислим смещение оставшихся позиций для INI_DELIMITER после изменения значения
  1672.             new filePosOffset = nValueLen - ( /*текущ длина значения*/ curFilePos - fileValueStartPos );
  1673.             // ----------------
  1674.  
  1675.  
  1676.             if ( _ini_nFileBusy[nFilePointer] != 0 ) // если прямо сейчас файл изменяется другой функцией
  1677.                 return INI_WRITE_ERROR; // вернем код ошибки при записи в файл
  1678.  
  1679.  
  1680.             // ----------------
  1681.             _ini_nFileBusy[nFilePointer] = 1; // флаг: файл изменяется = 1
  1682.  
  1683.             if ( filePosOffset != 0 ) // если длины старого и нового значений разные
  1684.             {
  1685.                 if ( filePosOffset < 0 ) // если длина нового значения меньше
  1686.                 {
  1687.                     for // копируем символы, стоящие после текущего значения на их новые места,
  1688.                     ( // которые теперь будут ближе к началу файла
  1689.                         ;
  1690.                         curFilePos < _ini_nFileSize[nFilePointer];
  1691.                         curFilePos++
  1692.                     )
  1693.                         _ini_szFileContent[nFilePointer]{ curFilePos + filePosOffset } =
  1694.                             _ini_szFileContent[nFilePointer]{curFilePos};
  1695.                 }
  1696.                 else if ( filePosOffset > 0 ) // если длина нового значения больше
  1697.                 {
  1698.                     new fileValueEndPos = curFilePos;
  1699.  
  1700.                     for // копируем символы, стоящие после текущего значения на их новые места,
  1701.                     ( // начиная с конца файла
  1702.                         curFilePos = _ini_nFileSize[nFilePointer] - 1;
  1703.                         curFilePos >= fileValueEndPos;
  1704.                         curFilePos--
  1705.                     )
  1706.                         _ini_szFileContent[nFilePointer]{ curFilePos + filePosOffset } =
  1707.                             _ini_szFileContent[nFilePointer]{curFilePos};
  1708.                 }
  1709.  
  1710.                 // изменим позиции всех INI_DELIMITER, которые находились после текущего INI_DELIMITER
  1711.                 for ( kPos++;  kPos < _ini_nKeysCount[nFilePointer];  kPos++ )
  1712.                     _ini_nDelimPos[nFilePointer][kPos] += filePosOffset;
  1713.  
  1714.                 _ini_nFileSize[nFilePointer] += filePosOffset; // изменим размер файла
  1715.                 _ini_szFileContent[nFilePointer]{ _ini_nFileSize[nFilePointer] } = 0; // конец строки для конца файла
  1716.             }
  1717.  
  1718.             curFilePos = fileValueStartPos; // текущ поз файла = поз начала старого значения
  1719.             for // запишем новое значение поверх старого
  1720.             (
  1721.                 new valuePos = 0;
  1722.                 valuePos < nValueLen;
  1723.                 curFilePos++, valuePos++
  1724.             )
  1725.                 _ini_szFileContent[nFilePointer]{curFilePos} = szKeyValue[valuePos];
  1726.  
  1727.             _ini_nFileChanged[nFilePointer]     = 1; // флаг: файл изменен = 1
  1728.             _ini_nFileBusy[nFilePointer]        = 0; // флаг: файл изменяется = 0
  1729.  
  1730.             return INI_OK;
  1731.             // ----------------
  1732.         }
  1733.     }
  1734.     // ----------------
  1735.  
  1736.  
  1737.     //
  1738.     // если указанный ключ НЕ НАЙДЕН в файле
  1739.     //
  1740.  
  1741.     // ----------------
  1742.     new szKeyValue[INI_FLOAT_SIZE]; // создадим строку для хранения дробного значения
  1743.     format( szKeyValue, INI_FLOAT_SIZE, "%f", fKeyValue ); // поместим строковое значение fKeyValue в szKeyValue
  1744.     // ----------------
  1745.  
  1746.  
  1747.     // ----------------
  1748.     new nValueLen = strlen(szKeyValue); // узнаем размер значения ключа
  1749.  
  1750.     // если будущий размер файла превышает лимит
  1751.     if ( ( _ini_nFileSize[nFilePointer] + 5 + nKeyLen + nValueLen ) >= INI_MAX_FILE_SIZE )
  1752.         return INI_TOO_LARGE_FILE; // вернем код ошибки о переполнении файла
  1753.     // ----------------
  1754.  
  1755.  
  1756.     // ----------------
  1757.     if ( _ini_nFileBusy[nFilePointer] != 0 ) // если прямо сейчас файл изменяется другой функцией
  1758.         return INI_WRITE_ERROR; // вернем код ошибки при записи в файл
  1759.  
  1760.     _ini_nFileBusy[nFilePointer] = 1; // флаг: файл изменяется = 1
  1761.     // ----------------
  1762.  
  1763.  
  1764.     // ----------------
  1765.     if // если последний символ файла не является разделителем строк
  1766.     (
  1767.             _ini_nFileSize[nFilePointer] > 0
  1768.         &&  _ini_szFileContent[nFilePointer]{ _ini_nFileSize[nFilePointer] - 1 } != INI_STRING_DELIMITER
  1769.     )
  1770.     {
  1771.         // вставим в конец файла перевод каретки и разделитель строк
  1772.         _ini_szFileContent[nFilePointer]{ _ini_nFileSize[nFilePointer] }        = '\r';
  1773.         _ini_szFileContent[nFilePointer]{ _ini_nFileSize[nFilePointer] + 1 }    = INI_STRING_DELIMITER;
  1774.  
  1775.         _ini_nFileSize[nFilePointer] += 2; // увеличим размер файла на 2
  1776.     }
  1777.  
  1778.     new curFilePos, strPos; // будут временным хранилищами позиций в файле/ключе/значении
  1779.  
  1780.     for // добавим посимвольно имя ключа в файл
  1781.     (
  1782.         curFilePos = _ini_nFileSize[nFilePointer], strPos = 0;
  1783.         strPos < nKeyLen;
  1784.         curFilePos++, strPos++
  1785.     )
  1786.         _ini_szFileContent[nFilePointer]{curFilePos} = szKeyName[strPos];
  1787.  
  1788.     _ini_szFileContent[nFilePointer]{ curFilePos++ }                = ' '; // после ключа добавим пробел
  1789.  
  1790.     _ini_nDelimPos[nFilePointer][ _ini_nKeysCount[nFilePointer] ]   = curFilePos; // добавим новую позицию INI_DELIMITER
  1791.     _ini_nKeysCount[nFilePointer]++; // кол-во ключей в файле +1
  1792.  
  1793.     _ini_szFileContent[nFilePointer]{ curFilePos++ }                = INI_DELIMITER; // после пробела выше добавим INI_DELIMITER
  1794.     _ini_szFileContent[nFilePointer]{ curFilePos++ }                = ' '; // после INI_DELIMITER добавим пробел
  1795.  
  1796.     // добавим посимвольно значение ключа в файл
  1797.     for ( strPos = 0;  strPos < nValueLen;  curFilePos++, strPos++ )
  1798.         _ini_szFileContent[nFilePointer]{curFilePos} = szKeyValue[strPos];
  1799.  
  1800.     _ini_szFileContent[nFilePointer]{curFilePos}    = 0; // добавим символ конца строки
  1801.     _ini_nFileSize[nFilePointer]                    = curFilePos; // изменим размер файла
  1802.     _ini_nFileChanged[nFilePointer]                 = 1; // флаг: файл изменен = 1
  1803.     _ini_nFileBusy[nFilePointer]                    = 0; // флаг: файл изменяется = 0
  1804.  
  1805.     return INI_OK;
  1806.     // ----------------
  1807. }
  1808.  
  1809.  
  1810. //
  1811. // Если вы хотите использовать другие имена функций в своем скрипте,
  1812. // измените указанные ниже макросы замены на свои и раскомментируйте нужные строки
  1813. //
  1814. //        ваше          оригинал
  1815. //
  1816. //#define iniCreate     ini_createFile
  1817. //#define iniOpen       ini_openFile
  1818. //#define iniClose      ini_closeFile
  1819. //#define iniSet        ini_setString
  1820. //#define iniSetInt     ini_setInteger
  1821. //#define iniSetFloat   ini_setFloat
  1822. //#define iniGet        ini_getString
  1823. //#define iniGetInt     ini_getInteger
  1824. //#define iniGetFloat   ini_getFloat
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement