INI.h 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
  1. /*
  2. ** Command & Conquer Generals Zero Hour(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. ////////////////////////////////////////////////////////////////////////////////
  19. // //
  20. // (c) 2001-2003 Electronic Arts Inc. //
  21. // //
  22. ////////////////////////////////////////////////////////////////////////////////
  23. // FILE: INI.h ////////////////////////////////////////////////////////////////////////////////////
  24. // Author: Colin Day, November 2001
  25. // Desc: INI Reader
  26. ///////////////////////////////////////////////////////////////////////////////////////////////////
  27. #pragma once
  28. #ifndef __INI_H_
  29. #define __INI_H_
  30. // INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
  31. #include <stddef.h> // for offsetof, which we don't use but everyone who includes us does
  32. #include "Common/STLTypedefs.h"
  33. #include "Common/AsciiString.h"
  34. #include "Common/GameCommon.h"
  35. //-------------------------------------------------------------------------------------------------
  36. class INI;
  37. class Xfer;
  38. class File;
  39. enum ScienceType;
  40. //-------------------------------------------------------------------------------------------------
  41. /** These control the behavior of loading the INI data into items */
  42. //-------------------------------------------------------------------------------------------------
  43. enum INILoadType
  44. {
  45. INI_LOAD_INVALID, ///< invalid load type
  46. INI_LOAD_OVERWRITE, ///< create new or load *over* existing data instance
  47. INI_LOAD_CREATE_OVERRIDES, ///< create new or load into *new* override data instance
  48. INI_LOAD_MULTIFILE ///< create new or continue loading into existing data instance.
  49. };
  50. //-------------------------------------------------------------------------------------------------
  51. /** INI constant defines */
  52. //-------------------------------------------------------------------------------------------------
  53. enum
  54. {
  55. INI_MAX_CHARS_PER_LINE = 1028, ///< max characters per line entry in any ini file
  56. };
  57. //-------------------------------------------------------------------------------------------------
  58. /** Status return codes for the INI reader */
  59. //-------------------------------------------------------------------------------------------------
  60. enum
  61. {
  62. // we map all of these to the same "real" error code, because
  63. // we generally don't care why it failed; but since the code distinguishes,
  64. // I didn't want to wipe out that intelligence. if we ever need to distinguish
  65. // failure modes at runtime, just put in real values for these.
  66. INI_CANT_SEARCH_DIR = ERROR_BAD_INI,
  67. INI_INVALID_DIRECTORY = ERROR_BAD_INI,
  68. INI_INVALID_PARAMS = ERROR_BAD_INI,
  69. INI_INVALID_NAME_LIST = ERROR_BAD_INI,
  70. INI_INVALID_DATA = ERROR_BAD_INI,
  71. INI_MISSING_END_TOKEN = ERROR_BAD_INI,
  72. INI_UNKNOWN_TOKEN = ERROR_BAD_INI,
  73. INI_BUFFER_TOO_SMALL = ERROR_BAD_INI,
  74. INI_FILE_NOT_OPEN = ERROR_BAD_INI,
  75. INI_FILE_ALREADY_OPEN = ERROR_BAD_INI,
  76. INI_CANT_OPEN_FILE = ERROR_BAD_INI,
  77. INI_UNKNOWN_ERROR = ERROR_BAD_INI,
  78. INI_END_OF_FILE = ERROR_BAD_INI
  79. };
  80. //-------------------------------------------------------------------------------------------------
  81. /** Function typedef for parsing data block fields.
  82. *
  83. * buffer - the character buffer of the line from INI that we are reading and parsing
  84. * instance - instance of what we're loading (for example a thingtemplate instance)
  85. * store - where to store the data parsed, this is a field in the *instance* 'instance'
  86. */
  87. //-------------------------------------------------------------------------------------------------
  88. typedef void (*INIFieldParseProc)( INI *ini, void *instance, void *store, const void* userData );
  89. //-------------------------------------------------------------------------------------------------
  90. typedef const char* ConstCharPtr;
  91. typedef const ConstCharPtr* ConstCharPtrArray;
  92. //-------------------------------------------------------------------------------------------------
  93. struct LookupListRec
  94. {
  95. const char* name;
  96. Int value;
  97. };
  98. typedef const LookupListRec *ConstLookupListRecArray;
  99. //-------------------------------------------------------------------------------------------------
  100. /** Parse tables for all fields of each data block are created using these */
  101. //-------------------------------------------------------------------------------------------------
  102. struct FieldParse
  103. {
  104. const char* token; ///< token of the field
  105. INIFieldParseProc parse; ///< the parse function
  106. const void* userData; ///< field-specific data
  107. Int offset; ///< offset to data field
  108. inline void set(const char* t, INIFieldParseProc p, const void* u, Int o)
  109. {
  110. token = t;
  111. parse = p;
  112. userData = u;
  113. offset = o;
  114. }
  115. };
  116. //-------------------------------------------------------------------------------------------------
  117. class MultiIniFieldParse
  118. {
  119. private:
  120. enum { MAX_MULTI_FIELDS = 16 };
  121. const FieldParse* m_fieldParse[MAX_MULTI_FIELDS];
  122. UnsignedInt m_extraOffset[MAX_MULTI_FIELDS];
  123. Int m_count;
  124. public:
  125. MultiIniFieldParse() : m_count(0)
  126. {
  127. //Added By Sadullah Nader
  128. //Initializations missing and needed
  129. for(Int i = 0; i < MAX_MULTI_FIELDS; i++)
  130. m_extraOffset[i] = 0;
  131. //
  132. }
  133. void add(const FieldParse* f, UnsignedInt e = 0);
  134. inline Int getCount() const { return m_count; }
  135. inline const FieldParse* getNthFieldParse(Int i) const { return m_fieldParse[i]; }
  136. inline UnsignedInt getNthExtraOffset(Int i) const { return m_extraOffset[i]; }
  137. };
  138. //-------------------------------------------------------------------------------------------------
  139. /** Function typedef for parsing INI types blocks */
  140. //-------------------------------------------------------------------------------------------------
  141. typedef void (*INIBlockParse)( INI *ini );
  142. typedef void (*BuildMultiIniFieldProc)(MultiIniFieldParse& p);
  143. //-------------------------------------------------------------------------------------------------
  144. /** INI Reader interface */
  145. //-------------------------------------------------------------------------------------------------
  146. class INI
  147. {
  148. INI(const INI&);
  149. INI& operator=(const INI&);
  150. public:
  151. INI();
  152. ~INI();
  153. void loadDirectory( AsciiString dirName, Bool subdirs, INILoadType loadType, Xfer *pXfer ); ///< load directory of INI files
  154. void load( AsciiString filename, INILoadType loadType, Xfer *pXfer ); ///< load INI file
  155. static Bool isDeclarationOfType( AsciiString blockType, AsciiString blockName, char *bufferToCheck );
  156. static Bool isEndOfBlock( char *bufferToCheck );
  157. // data type parsing (the highest level of what type of thing we're parsing)
  158. static void parseObjectDefinition( INI *ini );
  159. static void parseObjectReskinDefinition( INI *ini );
  160. static void parseWeaponTemplateDefinition( INI *ini );
  161. static void parseScienceDefinition( INI *ini );
  162. static void parseRankDefinition( INI *ini );
  163. static void parseCrateTemplateDefinition( INI *ini );
  164. static void parseLocomotorTemplateDefinition( INI *ini );
  165. static void parseLanguageDefinition( INI *ini );
  166. static void parsePlayerTemplateDefinition( INI *ini );
  167. static void parseGameDataDefinition( INI *ini );
  168. static void parseMapDataDefinition( INI *ini );
  169. static void parseAnim2DDefinition( INI *ini );
  170. static void parseAudioEventDefinition( INI *ini );
  171. static void parseDialogDefinition( INI *ini );
  172. static void parseMusicTrackDefinition( INI *ini );
  173. static void parseWebpageURLDefinition( INI *ini );
  174. static void parseHeaderTemplateDefinition( INI *ini );
  175. static void parseParticleSystemDefinition( INI *ini );
  176. static void parseWaterSettingDefinition( INI *ini );
  177. static void parseWaterTransparencyDefinition( INI *ini );
  178. static void parseWeatherDefinition( INI *ini );
  179. static void parseMappedImageDefinition( INI *ini );
  180. static void parseArmorDefinition( INI *ini );
  181. static void parseDamageFXDefinition( INI *ini );
  182. static void parseDrawGroupNumberDefinition( INI *ini );
  183. static void parseTerrainDefinition( INI *ini );
  184. static void parseTerrainRoadDefinition( INI *ini );
  185. static void parseTerrainBridgeDefinition( INI *ini );
  186. static void parseMetaMapDefinition( INI *ini );
  187. static void parseFXListDefinition( INI *ini );
  188. static void parseObjectCreationListDefinition( INI* ini );
  189. static void parseMultiplayerSettingsDefinition( INI* ini );
  190. static void parseMultiplayerColorDefinition( INI* ini );
  191. static void parseMultiplayerStartingMoneyChoiceDefinition( INI* ini );
  192. static void parseOnlineChatColorDefinition( INI* ini );
  193. static void parseMapCacheDefinition( INI* ini );
  194. static void parseVideoDefinition( INI* ini );
  195. static void parseCommandButtonDefinition( INI *ini );
  196. static void parseCommandSetDefinition( INI *ini );
  197. static void parseUpgradeDefinition( INI *ini );
  198. static void parseMouseDefinition( INI* ini );
  199. static void parseMouseCursorDefinition( INI* ini );
  200. static void parseAIDataDefinition( INI *ini );
  201. static void parseSpecialPowerDefinition( INI *ini );
  202. static void parseInGameUIDefinition( INI *ini );
  203. static void parseControlBarSchemeDefinition( INI *ini );
  204. static void parseControlBarResizerDefinition( INI *ini );
  205. static void parseShellMenuSchemeDefinition( INI *ini );
  206. static void parseCampaignDefinition( INI *ini );
  207. static void parseAudioSettingsDefinition( INI *ini );
  208. static void parseMiscAudio( INI *ini );
  209. static void parseStaticGameLODDefinition( INI *ini);
  210. static void parseDynamicGameLODDefinition( INI *ini);
  211. static void parseStaticGameLODLevel( INI* ini, void * , void *store, const void*);
  212. static void parseDynamicGameLODLevel( INI* ini, void * , void *store, const void*);
  213. static void parseLODPreset( INI* ini);
  214. static void parseBenchProfile( INI* ini);
  215. static void parseEvaEvent( INI* ini );
  216. static void parseCredits( INI* ini );
  217. static void parseWindowTransitions( INI* ini );
  218. static void parseChallengeModeDefinition( INI* ini );
  219. inline AsciiString getFilename( void ) const { return m_filename; }
  220. inline INILoadType getLoadType( void ) const { return m_loadType; }
  221. inline UnsignedInt getLineNum( void ) const { return m_lineNum; }
  222. inline const char *getSeps( void ) const { return m_seps; }
  223. inline const char *getSepsPercent( void ) const { return m_sepsPercent; }
  224. inline const char *getSepsColon( void ) const { return m_sepsColon; }
  225. inline const char *getSepsQuote( void ) { return m_sepsQuote; }
  226. inline Bool isEOF( void ) const { return m_endOfFile; }
  227. void initFromINI( void *what, const FieldParse* parseTable );
  228. void initFromINIMulti( void *what, const MultiIniFieldParse& parseTableList );
  229. void initFromINIMultiProc( void *what, BuildMultiIniFieldProc proc );
  230. static void parseUnsignedByte( INI *ini, void *instance, void *store, const void* userData );
  231. static void parseShort( INI *ini, void *instance, void *store, const void* userData );
  232. static void parseUnsignedShort( INI *ini, void *instance, void *store, const void* userData );
  233. static void parseInt( INI *ini, void *instance, void *store, const void* userData );
  234. static void parseUnsignedInt( INI *ini, void *instance, void *store, const void* userData );
  235. static void parseReal( INI *ini, void *instance, void *store, const void* userData );
  236. static void parsePositiveNonZeroReal( INI *ini, void *instance, void *store, const void* userData );
  237. static void parseBool( INI *ini, void *instance, void *store, const void* userData );
  238. static void parseBitInInt32( INI *ini, void *instance, void *store, const void* userData );
  239. static void parseAsciiString( INI *ini, void *instance, void *store, const void* userData );
  240. static void parseQuotedAsciiString( INI *ini, void *instance, void *store, const void* userData );
  241. static void parseAsciiStringVector( INI *ini, void *instance, void *store, const void* userData );
  242. static void parseAsciiStringVectorAppend( INI *ini, void *instance, void *store, const void* userData );
  243. static void parseAndTranslateLabel( INI *ini, void *instance, void *store, const void* userData );
  244. static void parseMappedImage( INI *ini, void *instance, void *store, const void *userData );
  245. static void parseAnim2DTemplate( INI *ini, void *instance, void *store, const void *userData );
  246. static void parsePercentToReal( INI *ini, void *instance, void *store, const void* userData );
  247. static void parseRGBColor( INI *ini, void *instance, void *store, const void* userData );
  248. static void parseRGBAColorInt( INI *ini, void *instance, void *store, const void* userData );
  249. static void parseColorInt( INI *ini, void *instance, void *store, const void* userData );
  250. static void parseCoord3D( INI *ini, void *instance, void *store, const void* userData );
  251. static void parseCoord2D( INI *ini, void *instance, void *store, const void *userData );
  252. static void parseICoord2D( INI *ini, void *instance, void *store, const void *userData );
  253. static void parseDynamicAudioEventRTS( INI *ini, void *instance, void *store, const void* userData );
  254. static void parseAudioEventRTS( INI *ini, void *instance, void *store, const void* userData );
  255. static void parseFXList( INI *ini, void *instance, void *store, const void* userData );
  256. static void parseParticleSystemTemplate( INI *ini, void *instance, void *store, const void *userData );
  257. static void parseObjectCreationList( INI *ini, void *instance, void *store, const void* userData );
  258. static void parseSpecialPowerTemplate( INI *ini, void *instance, void *store, const void *userData );
  259. static void parseUpgradeTemplate( INI *ini, void *instance, void *store, const void *userData );
  260. static void parseScience( INI *ini, void *instance, void *store, const void *userData );
  261. static void parseScienceVector( INI *ini, void *instance, void *store, const void *userData );
  262. static void parseGameClientRandomVariable( INI* ini, void *instance, void *store, const void* userData );
  263. static void parseBitString8( INI *ini, void *instance, void *store, const void* userData );
  264. static void parseBitString32( INI *ini, void *instance, void *store, const void* userData );
  265. static void parseByteSizedIndexList( INI *ini, void *instance, void *store, const void* userData );
  266. static void parseIndexList( INI *ini, void *instance, void *store, const void* userData );
  267. static void parseLookupList( INI *ini, void *instance, void *store, const void* userData );
  268. static void parseThingTemplate( INI *ini, void *instance, void *store, const void* userData );
  269. static void parseArmorTemplate( INI *ini, void *instance, void *store, const void* userData );
  270. static void parseDamageFX( INI *ini, void *instance, void *store, const void* userData );
  271. static void parseWeaponTemplate( INI *ini, void *instance, void *store, const void* userData );
  272. // parse a duration in msec and convert to duration in frames
  273. static void parseDurationReal( INI *ini, void *instance, void *store, const void* userData );
  274. // parse a duration in msec and convert to duration in integral number of frames, (unsignedint) rounding UP
  275. static void parseDurationUnsignedInt( INI *ini, void *instance, void *store, const void* userData );
  276. static void parseDurationUnsignedShort( INI *ini, void *instance, void *store, const void *userData );
  277. // parse acceleration in (dist/sec) and convert to (dist/frame)
  278. static void parseVelocityReal( INI *ini, void *instance, void *store, const void* userData );
  279. // parse acceleration in (dist/sec^2) and convert to (dist/frame^2)
  280. static void parseAccelerationReal( INI *ini, void *instance, void *store, const void* userData );
  281. // parse angle in degrees and convert to radians
  282. static void parseAngleReal( INI *ini, void *instance, void *store, const void *userData );
  283. // note that this parses in degrees/sec, and converts to rads/frame!
  284. static void parseAngularVelocityReal( INI *ini, void *instance, void *store, const void *userData );
  285. static void parseDamageTypeFlags(INI* ini, void* instance, void* store, const void* userData);
  286. static void parseDeathTypeFlags(INI* ini, void* instance, void* store, const void* userData);
  287. static void parseVeterancyLevelFlags(INI* ini, void* instance, void* store, const void* userData);
  288. static void parseSoundsList( INI* ini, void *instance, void *store, const void* /*userData*/ );
  289. /**
  290. return the next token. if seps is null (or omitted), the standard seps are used.
  291. this will *never* return null; if there are no more tokens, an exception will be thrown.
  292. */
  293. const char* getNextToken(const char* seps = NULL);
  294. /**
  295. just like getNextToken(), except that null is returned if no more tokens are present
  296. (rather than throwing an exception). usually you should call getNextToken(),
  297. but for some cases this is handier (ie, parsing a variable-length number of tokens).
  298. */
  299. const char* getNextTokenOrNull(const char* seps = NULL);
  300. /**
  301. This is called when the next thing you expect is something like:
  302. Tag:value
  303. pass "Tag" (without the colon) for 'expected', and you will have the 'value'
  304. token returned.
  305. If "Tag" is not the next token, an error is thrown.
  306. */
  307. const char* getNextSubToken(const char* expected);
  308. /**
  309. return the next ascii string. this is usually the same the result of getNextToken(),
  310. except that it allows for quote-delimited strings (eg, "foo bar"), so you can
  311. get strings with spaces, and/or empty strings.
  312. */
  313. AsciiString getNextAsciiString();
  314. AsciiString getNextQuotedAsciiString(); //fixed version of above. We can't fix the regular one for fear of breaking existing code. :-(
  315. /**
  316. utility routine that does a sscanf() on the string to get the Science, and throws
  317. an exception if not of the right form.
  318. */
  319. static ScienceType scanScience(const char* token);
  320. /**
  321. utility routine that does a sscanf() on the string to get the int, and throws
  322. an exception if not of the right form.
  323. */
  324. static Int scanInt(const char* token);
  325. /**
  326. utility routine that does a sscanf() on the string to get the unsigned int, and throws
  327. an exception if not of the right form.
  328. */
  329. static UnsignedInt scanUnsignedInt(const char* token);
  330. /**
  331. utility routine that does a sscanf() on the string to get the real, and throws
  332. an exception if not of the right form.
  333. */
  334. static Real scanReal(const char* token);
  335. static Real scanPercentToReal(const char* token);
  336. static Int scanIndexList(const char* token, ConstCharPtrArray nameList);
  337. static Int scanLookupList(const char* token, ConstLookupListRecArray lookupList);
  338. static Bool scanBool(const char* token);
  339. protected:
  340. static Bool isValidINIFilename( const char *filename ); ///< is this a valid .ini filename
  341. void prepFile( AsciiString filename, INILoadType loadType );
  342. void unPrepFile();
  343. void readLine( void );
  344. File *m_file; ///< file pointer of file currently loading
  345. enum
  346. {
  347. INI_READ_BUFFER = 8192 ///< size of internal read buffer
  348. };
  349. char m_readBuffer[INI_READ_BUFFER]; ///< internal read buffer
  350. unsigned m_readBufferNext; ///< next char in read buffer
  351. unsigned m_readBufferUsed; ///< number of bytes in read buffer
  352. AsciiString m_filename; ///< filename of file currently loading
  353. INILoadType m_loadType; ///< load time for current file
  354. UnsignedInt m_lineNum; ///< current line number that's been read
  355. char m_buffer[ INI_MAX_CHARS_PER_LINE+1 ];///< buffer to read file contents into
  356. const char *m_seps; ///< for strtok parsing
  357. const char *m_sepsPercent; ///< m_seps with percent delimiter as well
  358. const char *m_sepsColon; ///< m_seps with colon delimiter as well
  359. const char *m_sepsQuote; ///< token to represent a quoted ascii string
  360. const char *m_blockEndToken; ///< token to represent end of data block
  361. Bool m_endOfFile; ///< TRUE when we've hit EOF
  362. #if defined(_DEBUG) || defined(_INTERNAL)
  363. char m_curBlockStart[ INI_MAX_CHARS_PER_LINE ]; ///< first line of cur block
  364. #endif
  365. };
  366. #endif // __INI_H_