1
0

mxINI.inc 100 KB

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