1
0

y_bini.inc 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. /*
  2. y_bin - Binary file storage.
  3. */
  4. /*
  5. Binary file format:
  6. 4 bytes - Number of chunks in the file.
  7. Chunk header:
  8. These are not garbage collected, and memory is allocated for a huge number.
  9. Actually, I'm not sure of the best way to do this well... The original idea was
  10. to just have fixed blocks, I don't know if that is still the best method.
  11. Actually, maybe the best method is separate files created and destroyed as
  12. required, that would be a LOT less coding!
  13. */
  14. stock INI_WriteArray(const INI:f, const string:name[], const arr[], const len = sizeof (arr))
  15. {
  16. // First things first, determine the filename for the data. This is done as:
  17. //
  18. // <f path>\<f name>.INI[<tag>]<name>=
  19. //
  20. // Also, unlike all other INI data, this data is not buffered - doing so is
  21. // not only hard, but pointless because we are writing to a different file.
  22. new
  23. fname[64];
  24. format(fname, sizeof (fname), "%s[%s]%s=.bin", YSI_g_sINIWriteFile[f], YSI_g_sINITagBuffer[YSI_g_sINICurrentTag[f]][E_INI_TAGS_NAME], name);
  25. new
  26. File:b = fopen(fname, io_write);
  27. if (b)
  28. {
  29. fblockwrite(b, arr, len);
  30. INI_WriteString(f, name, fname),
  31. fclose(b);
  32. }
  33. }
  34. stock INI_ReadArray(const string:fname[], dest[], len = sizeof (dest))
  35. {
  36. new
  37. File:b = fopen(fname, io_read);
  38. if (b)
  39. {
  40. new
  41. l2 = flength(b);
  42. if (l2 > len) P:W("%s buffer has shrunk since writing.", fname);
  43. else if (l2 < len) P:W("%s buffer has grown since writing.", fname);
  44. return
  45. fblockread(b, arr, len);
  46. fclose(b),
  47. 1;
  48. }
  49. else
  50. {
  51. // Do something special to detect old style arrays. Sadly, we can't
  52. // upgrade them as they may not be writing (actually, why can't we?)
  53. }
  54. return 0;
  55. }
  56. #define INI_Array(%1,%2) \
  57. if (!strcmp((%1), name, true)) return INI_ReadArray(value, %2)
  58. /*
  59. BIN_WriteChunk(const BIN:f, const pos, const arr[], const len = sizeof (arr), buffer = sizeof (arr))
  60. {
  61. if (buffer < len)
  62. {
  63. // Blank the file location, return the new location. Can NEVER garbage
  64. // collect the wasted storage. Actually, why can't we? Use double
  65. // indirection!
  66. }
  67. else if (buffer > len)
  68. {
  69. // Pad the data.
  70. }
  71. }
  72. */
  73. /*-------------------------------------------------------------------------*//**
  74. * <param name="start">Start position of the possibly current key.</param>
  75. * <param name="end">End position of the found key.</param>
  76. * <remarks>
  77. * The INI system uses basic string functions to find candidate keys. They
  78. * always start searching from the known start of the current tag, and check
  79. * that the found key is before the start of the next known tag. If both those
  80. * conditions are true, this function is called to further verify the found
  81. * text - it could be a substring in a larger key, it could be a value, or it
  82. * could be commented out. This function therefore checks that the found
  83. * position in the stored string is the first item on a line, and is followed
  84. * only by either nothing or an equals sign.
  85. *
  86. * If this IS the key we are searching for, then we return a later position
  87. * corresponding to the start of the value (or cellmax if there is no value).
  88. * If this isn't a valid key, we return -1.
  89. * </remarks>
  90. *//*------------------------------------------------------------------------**/
  91. static stock bool:INI_TryGetValue(start, end)
  92. {
  93. // Check everything before this position is whitespace only.
  94. new
  95. cur = start;
  96. for ( ; ; )
  97. {
  98. switch (YSI_gMallocMemory[--cur])
  99. {
  100. case '\0', '\r', '\n': break;
  101. case ' ', '\t': {}
  102. default: return -1;
  103. }
  104. }
  105. cur = end;
  106. for ( ; ; )
  107. {
  108. switch (YSI_gMallocMemory[cur++])
  109. {
  110. // Has no value, just a key.
  111. case '\0', '\r', '\n': return cellmax;
  112. // Has a value, find the start.
  113. case '=':
  114. {
  115. // "cur" has already been incremented by this point.
  116. for ( ; ; )
  117. {
  118. switch (YSI_gMallocMemory[cur])
  119. {
  120. case '\0', '\r', '\n': return cellmax;
  121. case ' ', '\t': ++cur;
  122. default: return cur;
  123. }
  124. }
  125. }
  126. case ' ', '\t': {}
  127. default: break;
  128. }
  129. }
  130. return -1;
  131. }