ini.cpp 113 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070
  1. /*
  2. ** Command & Conquer Generals(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. *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
  20. ***********************************************************************************************
  21. * *
  22. * Project Name : Command & Conquer *
  23. * *
  24. * $Archive:: /Commando/Code/wwlib/ini.cpp $*
  25. * *
  26. * $Author:: Byon_g $*
  27. * *
  28. * $Modtime:: 7/23/01 6:20p $*
  29. * *
  30. * $Revision:: 17 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * INIClass::Clear -- Clears out a section (or all sections) of the INI data. *
  35. * INIClass::Entry_Count -- Fetches the number of entries in a specified section. *
  36. * INIClass::Find_Entry -- Find specified entry within section. *
  37. * INIClass::Find_Section -- Find the specified section within the INI data. *
  38. * INIClass::Get_Bool -- Fetch a boolean value for the section and entry specified. *
  39. * INIClass::Get_Entry -- Get the entry identifier name given ordinal number and section name*
  40. * INIClass::Get_Float -- Fetch a floating point number from the database. *
  41. * INIClass::Get_Hex -- Fetches integer [hex format] from the section and entry specified. *
  42. * INIClass::Get_Int -- Fetch an integer entry from the specified section. *
  43. * INIClass::Get_PKey -- Fetch a key from the ini database. *
  44. * INIClass::Get_String -- Fetch the value of a particular entry in a specified section. *
  45. * INIClass::Get_TextBlock -- Fetch a block of normal text. *
  46. * INIClass::Get_UUBlock -- Fetch an encoded block from the section specified. *
  47. * INIClass::INISection::Find_Entry -- Finds a specified entry and returns pointer to it. *
  48. * INIClass::Load -- Load INI data from the file specified. *
  49. * INIClass::Load -- Load the INI data from the data stream (straw). *
  50. * INIClass::Put_Bool -- Store a boolean value into the INI database. *
  51. * INIClass::Put_Float -- Store a floating point number to the database. *
  52. * INIClass::Put_Hex -- Store an integer into the INI database, but use a hex format. *
  53. * INIClass::Put_Int -- Stores a signed integer into the INI data base. *
  54. * INIClass::Put_PKey -- Stores the key to the INI database. *
  55. * INIClass::Put_String -- Output a string to the section and entry specified. *
  56. * INIClass::Put_TextBlock -- Stores a block of text into an INI section. *
  57. * INIClass::Put_UUBlock -- Store a binary encoded data block into the INI database. *
  58. * INIClass::Save -- Save the ini data to the file specified. *
  59. * INIClass::Save -- Saves the INI data to a pipe stream. *
  60. * INIClass::Section_Count -- Counts the number of sections in the INI data. *
  61. * INIClass::Strip_Comments -- Strips comments of the specified text line. *
  62. * INIClass::~INIClass -- Destructor for INI handler. *
  63. * INIClass::Put_Rect -- Store a rectangle into the INI database. *
  64. * INIClass::Get_Rect -- Retrieve a rectangle data from the database. *
  65. * INIClass::Put_Point -- Store a point value to the database. *
  66. * INIClass::Get_Point -- Fetch a point value from the INI database. *
  67. * INIClass::Put_Point -- Stores a 3D point to the database. *
  68. * INIClass::Get_Point -- Fetch a 3D point from the database. *
  69. * INIClass::Get_Point -- Fetch a 2D point from the INI database. *
  70. * INIClass::CRC - returns a (hopefully) unique 32-bit value for a string *
  71. * -- Displays debug information when a duplicate entry is found in an INI file *
  72. * INIClass::Enumerate_Entries -- Count how many entries begin with a certain prefix followed by a range *
  73. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  74. #include "always.h"
  75. #include "b64pipe.h"
  76. #include "b64straw.h"
  77. #include "cstraw.h"
  78. #include "ini.h"
  79. #include "readline.h"
  80. #include "trim.h"
  81. #include "win.h"
  82. #include "xpipe.h"
  83. #include "xstraw.h"
  84. #include <stdio.h>
  85. #ifdef _UNIX
  86. #include <ctype.h>
  87. #endif
  88. #include "rawfile.h"
  89. #include "ffactory.h"
  90. // recently transferred from ini.h
  91. #include "inisup.h"
  92. #include "trect.h"
  93. #include "wwfile.h"
  94. #include "pk.h"
  95. #include "pipe.h"
  96. #include "wwstring.h"
  97. #if defined(__WATCOMC__)
  98. // Disable the "temporary object used to initialize a non-constant reference" warning.
  99. #pragma warning 665 9
  100. #endif
  101. INIEntry::~INIEntry(void)
  102. {
  103. free(Entry);
  104. Entry = NULL;
  105. free(Value);
  106. Value = NULL;
  107. }
  108. INISection::~INISection(void)
  109. {
  110. free(Section);
  111. Section = 0;
  112. EntryList.Delete();
  113. }
  114. bool INIClass::Is_Loaded(void) const
  115. {
  116. return(!SectionList->Is_Empty());
  117. }
  118. void INIClass::Initialize(void)
  119. {
  120. SectionList = W3DNEW List<INISection *> ();
  121. SectionIndex = W3DNEW IndexClass<int, INISection *> ();
  122. }
  123. void INIClass::Shutdown(void)
  124. {
  125. delete SectionList;
  126. delete SectionIndex;
  127. }
  128. /***********************************************************************************************
  129. * INIClass::INIClass -- Constructor for INI handler. *
  130. * *
  131. * *
  132. * INPUT: FileClass object *
  133. * *
  134. * OUTPUT: none *
  135. * *
  136. * WARNINGS: none *
  137. * *
  138. * HISTORY: *
  139. *=============================================================================================*/
  140. INIClass::INIClass(void)
  141. {
  142. Initialize();
  143. }
  144. /***********************************************************************************************
  145. * INIClass::INIClass -- Constructor for INI handler. *
  146. * *
  147. * *
  148. * INPUT: FileClass object *
  149. * *
  150. * OUTPUT: none *
  151. * *
  152. * WARNINGS: none *
  153. * *
  154. * HISTORY: *
  155. *=============================================================================================*/
  156. INIClass::INIClass(FileClass & file)
  157. {
  158. Initialize();
  159. Load(file);
  160. }
  161. /***********************************************************************************************
  162. * INIClass::INIClass -- Constructor for INI handler. *
  163. * *
  164. * *
  165. * INPUT: filename string *
  166. * *
  167. * OUTPUT: none *
  168. * *
  169. * WARNINGS: none *
  170. * *
  171. * HISTORY: *
  172. *=============================================================================================*/
  173. INIClass::INIClass(const char *filename)
  174. {
  175. Initialize();
  176. FileClass *file=_TheFileFactory->Get_File(filename);
  177. if ( file ) {
  178. Load(*file);
  179. _TheFileFactory->Return_File(file);
  180. }
  181. }
  182. /***********************************************************************************************
  183. * INIClass::~INIClass -- Destructor for INI handler. *
  184. * *
  185. * This is the destructor for the INI class. It handles deleting all of the allocations *
  186. * it might have done. *
  187. * *
  188. * INPUT: none *
  189. * *
  190. * OUTPUT: none *
  191. * *
  192. * WARNINGS: none *
  193. * *
  194. * HISTORY: *
  195. * 07/02/1996 JLB : Created. *
  196. *=============================================================================================*/
  197. INIClass::~INIClass(void)
  198. {
  199. Clear();
  200. Shutdown();
  201. }
  202. /***********************************************************************************************
  203. * INIClass::Clear -- Clears out a section (or all sections) of the INI data. *
  204. * *
  205. * This routine is used to clear out the section specified. If no section is specified, *
  206. * then the entire INI data is cleared out. Optionally, this routine can be used to clear *
  207. * out just an individual entry in the specified section. *
  208. * *
  209. * INPUT: section -- Pointer to the section to clear out [pass NULL to clear all]. *
  210. * *
  211. * entry -- Pointer to optional entry specifier. If this parameter is specified, *
  212. * then only this specific entry (if found) will be cleared. Otherwise, *
  213. * the entire section specified will be cleared. *
  214. * *
  215. * OUTPUT: none *
  216. * *
  217. * WARNINGS: none *
  218. * *
  219. * HISTORY: *
  220. * 07/02/1996 JLB : Created. *
  221. * 08/21/1996 JLB : Optionally clears section too. *
  222. * 11/02/1996 JLB : Updates the index list. *
  223. *=============================================================================================*/
  224. bool INIClass::Clear(char const * section, char const * entry)
  225. {
  226. if (section == NULL) {
  227. SectionList->Delete();
  228. SectionIndex->Clear();
  229. } else {
  230. INISection * secptr = Find_Section(section);
  231. if (secptr != NULL) {
  232. if (entry != NULL) {
  233. INIEntry * entptr = secptr->Find_Entry(entry);
  234. if (entptr != NULL) {
  235. /*
  236. ** Remove the entry from the entry index list.
  237. */
  238. secptr->EntryIndex.Remove_Index(entptr->Index_ID());
  239. delete entptr;
  240. }
  241. } else {
  242. /*
  243. ** Remove this section index from the section index list.
  244. */
  245. SectionIndex->Remove_Index(secptr->Index_ID());
  246. delete secptr;
  247. }
  248. }
  249. }
  250. return(true);
  251. }
  252. /***********************************************************************************************
  253. * INIClass::Load -- Load INI data from the file specified. *
  254. * *
  255. * Use this routine to load the INI class with the data from the specified file. *
  256. * *
  257. * INPUT: file -- Reference to the file that will be used to fill up this INI manager. *
  258. * *
  259. * OUTPUT: bool; Was the file loaded successfully? *
  260. * *
  261. * WARNINGS: This routine allocates memory. *
  262. * *
  263. * HISTORY: *
  264. * 07/02/1996 JLB : Created. *
  265. *=============================================================================================*/
  266. int INIClass::Load(FileClass & file)
  267. {
  268. FileStraw fs(file);
  269. return(Load(fs));
  270. }
  271. /***********************************************************************************************
  272. * INIClass::Load -- Load INI data from the file specified. *
  273. * *
  274. * Use this routine to load the INI class with the data from the specified file. *
  275. * *
  276. * INPUT: filename -- Path for the file to open, factory - thing to make file *
  277. * *
  278. * OUTPUT: bool; Was the file loaded successfully? *
  279. * *
  280. * WARNINGS: This routine allocates memory. *
  281. * *
  282. * HISTORY: *
  283. * 08/01/2000 NAK : Created. *
  284. *=============================================================================================*/
  285. int INIClass::Load(const char *filename)
  286. {
  287. file_auto_ptr file(_TheFileFactory, filename);
  288. int retval=Load(*file);
  289. return(retval);
  290. }
  291. /***********************************************************************************************
  292. * INIClass::Load -- Load the INI data from the data stream (straw). *
  293. * *
  294. * This will fetch data from the straw and build an INI database from it. *
  295. * *
  296. * INPUT: straw -- The straw that the data will be provided from. *
  297. * *
  298. * OUTPUT: bool; Was the database loaded ok? *
  299. * *
  300. * WARNINGS: none *
  301. * *
  302. * HISTORY: *
  303. * 07/10/1996 JLB : Created. *
  304. * 09/29/1997 JLB : Handles the merging case. *
  305. * 12/09/1997 EHC : Detects duplicate entry CRCs and fails in that case *
  306. * 03/22/2001 AJA : Treat "foobar=" as a valid entry with value " ". *
  307. *=============================================================================================*/
  308. int INIClass::Load(Straw & ffile)
  309. {
  310. bool end_of_file = false;
  311. char buffer[MAX_LINE_LENGTH];
  312. /*
  313. ** Determine if the INI database has preexisting entries. If it does,
  314. ** then the slower merging method of loading is required.
  315. */
  316. bool merge = false;
  317. if (Section_Count() > 0) {
  318. merge = true;
  319. }
  320. CacheStraw file;
  321. file.Get_From(ffile);
  322. /*
  323. ** Prescan until the first section is found.
  324. */
  325. while (!end_of_file) {
  326. Read_Line(file, buffer, sizeof(buffer), end_of_file);
  327. if (end_of_file) return(false);
  328. if (buffer[0] == '[' && strchr(buffer, ']') != NULL) break;
  329. }
  330. if (merge) {
  331. /*
  332. ** Process a section. The buffer is prefilled with the section name line.
  333. */
  334. while (!end_of_file) {
  335. /*
  336. ** Fetch the section name. Preserve it while the section's entries are
  337. ** being parsed.
  338. */
  339. buffer[0] = ' ';
  340. char * ptr = strchr(buffer, ']');
  341. if (ptr != NULL) *ptr = '\0';
  342. strtrim(buffer);
  343. char section[64];
  344. strcpy(section, buffer);
  345. /*
  346. ** Read in the entries of this section.
  347. */
  348. while (!end_of_file) {
  349. /*
  350. ** If this line is the start of another section, then bail out
  351. ** of the entry loop and let the outer section loop take
  352. ** care of it.
  353. */
  354. int len = Read_Line(file, buffer, sizeof(buffer), end_of_file);
  355. if (buffer[0] == '[' && strchr(buffer, ']') != NULL) break;
  356. /*
  357. ** Determine if this line is a comment or blank line. Throw it out if it is.
  358. */
  359. Strip_Comments(buffer);
  360. if (len == 0 || buffer[0] == ';' || buffer[0] == '=') continue;
  361. /*
  362. ** The line isn't an obvious comment. Make sure that there is the "=" character
  363. ** at an appropriate spot.
  364. */
  365. char * divider = strchr(buffer, '=');
  366. if (!divider) continue;
  367. /*
  368. ** Split the line into entry and value sections. Be sure to catch the
  369. ** "=foobar" and "foobar=" cases. "=foobar" lines are ignored, while
  370. ** "foobar=" lines are stores has having " " as their value.
  371. */
  372. *divider++ = '\0';
  373. strtrim(buffer);
  374. if (!strlen(buffer)) continue;
  375. strtrim(divider);
  376. if (!strlen(divider))
  377. divider = " ";
  378. if (Put_String(section, buffer, divider) == false) {
  379. return(false);
  380. }
  381. }
  382. }
  383. } else {
  384. /*
  385. ** Process a section. The buffer is prefilled with the section name line.
  386. */
  387. while (!end_of_file) {
  388. buffer[0] = ' ';
  389. char * ptr = strchr(buffer, ']');
  390. if (ptr != NULL) *ptr = '\0';
  391. strtrim(buffer);
  392. INISection * secptr = W3DNEW INISection(strdup(buffer));
  393. if (secptr == NULL) {
  394. Clear();
  395. return(false);
  396. }
  397. /*
  398. ** Read in the entries of this section.
  399. */
  400. while (!end_of_file) {
  401. /*
  402. ** If this line is the start of another section, then bail out
  403. ** of the entry loop and let the outer section loop take
  404. ** care of it.
  405. */
  406. int len = Read_Line(file, buffer, sizeof(buffer), end_of_file);
  407. if (buffer[0] == '[' && strchr(buffer, ']') != NULL) break;
  408. /*
  409. ** Determine if this line is a comment or blank line. Throw it out if it is.
  410. */
  411. Strip_Comments(buffer);
  412. if (len == 0 || buffer[0] == ';' || buffer[0] == '=') continue;
  413. /*
  414. ** The line isn't an obvious comment. Make sure that there is the "=" character
  415. ** at an appropriate spot.
  416. */
  417. char * divider = strchr(buffer, '=');
  418. if (!divider) continue;
  419. /*
  420. ** Split the line into entry and value sections. Be sure to catch the
  421. ** "=foobar" and "foobar=" cases. "=foobar" lines are ignored, while
  422. ** "foobar=" lines are stores has having " " as their value.
  423. */
  424. *divider++ = '\0';
  425. strtrim(buffer);
  426. if (!strlen(buffer)) continue;
  427. strtrim(divider);
  428. if (!strlen(divider))
  429. divider = " ";
  430. INIEntry * entryptr = W3DNEW INIEntry(strdup(buffer), strdup(divider));
  431. if (entryptr == NULL) {
  432. delete secptr;
  433. Clear();
  434. return(false);
  435. }
  436. // 12/09/97 EHC - check to see if an entry with this ID already exists
  437. if (secptr->EntryIndex.Is_Present(entryptr->Index_ID())) {
  438. WWDEBUG_SAY(( "Duplicate Entry CRC Section \"%s\" Entry \"%s\"\n", secptr->Section, buffer ));
  439. DuplicateCRCError("INIClass::Load", buffer);
  440. return false;
  441. }
  442. secptr->EntryIndex.Add_Index(entryptr->Index_ID(), entryptr);
  443. secptr->EntryList.Add_Tail(entryptr);
  444. }
  445. /*
  446. ** All the entries for this section have been parsed. If this section is blank, then
  447. ** don't bother storing it.
  448. */
  449. if (secptr->EntryList.Is_Empty()) {
  450. delete secptr;
  451. } else {
  452. SectionIndex->Add_Index(secptr->Index_ID(), secptr);
  453. SectionList->Add_Tail(secptr);
  454. }
  455. }
  456. }
  457. return(true);
  458. }
  459. /***********************************************************************************************
  460. * INIClass::Save -- Save the ini data to the file specified. *
  461. * *
  462. * Use this routine to save the ini data to the file specified. All existing data in the *
  463. * file, if it was present, is replaced. *
  464. * *
  465. * INPUT: file -- Reference to the file to write the INI data to. *
  466. * *
  467. * OUTPUT: bool; Was the data written to the file? *
  468. * *
  469. * WARNINGS: none *
  470. * *
  471. * HISTORY: *
  472. * 07/02/1996 JLB : Created. *
  473. *=============================================================================================*/
  474. int INIClass::Save(FileClass & file) const
  475. {
  476. FilePipe fp(file);
  477. return(Save(fp));
  478. }
  479. /***********************************************************************************************
  480. * INIClass::Save -- Save the ini data to the file specified. *
  481. * *
  482. * Use this routine to save the ini data to the file specified. All existing data in the *
  483. * file, if it was present, is replaced. *
  484. * *
  485. * INPUT: filename -- Filename to save to. *
  486. * *
  487. * OUTPUT: bool; Was the data written to the file? *
  488. * *
  489. * WARNINGS: none *
  490. * *
  491. * HISTORY: *
  492. * 01/22/2001 NAK : Created. *
  493. *=============================================================================================*/
  494. int INIClass::Save(const char *filename) const
  495. {
  496. FileClass *file=_TheWritingFileFactory->Get_File(filename);
  497. int retval=0;
  498. if ( file ) {
  499. retval=Save(*file);
  500. _TheWritingFileFactory->Return_File(file);
  501. }
  502. file=NULL;
  503. return(retval);
  504. }
  505. /***********************************************************************************************
  506. * INIClass::Save -- Saves the INI data to a pipe stream. *
  507. * *
  508. * This routine will output the data of the INI file to a pipe stream. *
  509. * *
  510. * INPUT: pipe -- Reference to the pipe stream to pump the INI image to. *
  511. * *
  512. * OUTPUT: Returns with the number of bytes output to the pipe. *
  513. * *
  514. * WARNINGS: none *
  515. * *
  516. * HISTORY: *
  517. * 07/02/1996 JLB : Created. *
  518. *=============================================================================================*/
  519. int INIClass::Save(Pipe & pipe) const
  520. {
  521. int total = 0;
  522. #ifdef _UNIX
  523. const char *EOL="\n";
  524. #else
  525. const char *EOL="\r\n";
  526. #endif
  527. INISection * secptr = SectionList->First();
  528. while (secptr && secptr->Is_Valid()) {
  529. /*
  530. ** Output the section identifier.
  531. */
  532. total += pipe.Put("[", 1);
  533. total += pipe.Put(secptr->Section, strlen(secptr->Section));
  534. total += pipe.Put("]", 1);
  535. total += pipe.Put(EOL, strlen(EOL));
  536. /*
  537. ** Output all the entries and values in this section.
  538. */
  539. INIEntry * entryptr = secptr->EntryList.First();
  540. while (entryptr && entryptr->Is_Valid()) {
  541. total += pipe.Put(entryptr->Entry, strlen(entryptr->Entry));
  542. total += pipe.Put("=", 1);
  543. total += pipe.Put(entryptr->Value, strlen(entryptr->Value));
  544. total += pipe.Put(EOL, strlen(EOL));
  545. entryptr = entryptr->Next();
  546. }
  547. /*
  548. ** After the last entry in this section, output an extra
  549. ** blank line for readability purposes.
  550. */
  551. total += pipe.Put(EOL, strlen(EOL));
  552. secptr = secptr->Next();
  553. }
  554. total += pipe.End();
  555. return(total);
  556. }
  557. /***********************************************************************************************
  558. * INIClass::Find_Section -- Find the specified section within the INI data. *
  559. * *
  560. * This routine will scan through the INI data looking for the section specified. If the *
  561. * section could be found, then a pointer to the section control data is returned. *
  562. * *
  563. * INPUT: section -- The name of the section to search for. Don't enclose the name in *
  564. * brackets. Case is NOT sensitive in the search. *
  565. * *
  566. * OUTPUT: Returns with a pointer to the INI section control structure if the section was *
  567. * found. Otherwise, NULL is returned. *
  568. * *
  569. * WARNINGS: none *
  570. * *
  571. * HISTORY: *
  572. * 07/02/1996 JLB : Created. *
  573. * 11/02/1996 JLB : Uses index manager. *
  574. * 12/08/1996 EHC : Uses member CRC function *
  575. *=============================================================================================*/
  576. INISection * INIClass::Find_Section(char const * section) const
  577. {
  578. if (section != NULL) {
  579. // long crc = CRCEngine()(section, strlen(section));
  580. long crc = CRC(section);
  581. if (SectionIndex->Is_Present(crc)) {
  582. return((*SectionIndex)[crc]);
  583. }
  584. }
  585. return(NULL);
  586. }
  587. /***********************************************************************************************
  588. * INIClass::Section_Count -- Counts the number of sections in the INI data. *
  589. * *
  590. * This routine will scan through all the sections in the INI data and return a count *
  591. * of the number it found. *
  592. * *
  593. * INPUT: none *
  594. * *
  595. * OUTPUT: Returns with the number of sections recorded in the INI data. *
  596. * *
  597. * WARNINGS: none *
  598. * *
  599. * HISTORY: *
  600. * 07/02/1996 JLB : Created. *
  601. * 11/02/1996 JLB : Uses index manager. *
  602. *=============================================================================================*/
  603. int INIClass::Section_Count(void) const
  604. {
  605. return(SectionIndex->Count());
  606. }
  607. /***********************************************************************************************
  608. * INIClass::Entry_Count -- Fetches the number of entries in a specified section. *
  609. * *
  610. * This routine will examine the section specified and return with the number of entries *
  611. * associated with it. *
  612. * *
  613. * INPUT: section -- Pointer to the section that will be examined. *
  614. * *
  615. * OUTPUT: Returns with the number entries in the specified section. *
  616. * *
  617. * WARNINGS: none *
  618. * *
  619. * HISTORY: *
  620. * 07/02/1996 JLB : Created. *
  621. * 11/02/1996 JLB : Uses index manager. *
  622. *=============================================================================================*/
  623. int INIClass::Entry_Count(char const * section) const
  624. {
  625. INISection * secptr = Find_Section(section);
  626. if (secptr != NULL) {
  627. return(secptr->EntryIndex.Count());
  628. }
  629. return(0);
  630. }
  631. /***********************************************************************************************
  632. * INIClass::Find_Entry -- Find specified entry within section. *
  633. * *
  634. * This support routine will find the specified entry in the specified section. If found, *
  635. * a pointer to the entry control structure will be returned. *
  636. * *
  637. * INPUT: section -- Pointer to the section name to search under. *
  638. * *
  639. * entry -- Pointer to the entry name to search for. *
  640. * *
  641. * OUTPUT: If the entry was found, then a pointer to the entry control structure will be *
  642. * returned. Otherwise, NULL will be returned. *
  643. * *
  644. * WARNINGS: none *
  645. * *
  646. * HISTORY: *
  647. * 07/02/1996 JLB : Created. *
  648. *=============================================================================================*/
  649. INIEntry * INIClass::Find_Entry(char const * section, char const * entry) const
  650. {
  651. INISection * secptr = Find_Section(section);
  652. if (secptr != NULL) {
  653. return(secptr->Find_Entry(entry));
  654. }
  655. return(NULL);
  656. }
  657. /***********************************************************************************************
  658. * INIClass::Get_Entry -- Get the entry identifier name given ordinal number and section name. *
  659. * *
  660. * This will return the identifier name for the entry under the section specified. The *
  661. * ordinal number specified is used to determine which entry to retrieve. The entry *
  662. * identifier is the text that appears to the left of the "=" character. *
  663. * *
  664. * INPUT: section -- The section to use. *
  665. * *
  666. * index -- The ordinal number to use when fetching an entry name. *
  667. * *
  668. * OUTPUT: Returns with a pointer to the entry name. *
  669. * *
  670. * WARNINGS: none *
  671. * *
  672. * HISTORY: *
  673. * 07/02/1996 JLB : Created. *
  674. *=============================================================================================*/
  675. char const * INIClass::Get_Entry(char const * section, int index) const
  676. {
  677. INISection * secptr = Find_Section(section);
  678. if (secptr != NULL && index < secptr->EntryIndex.Count()) {
  679. INIEntry * entryptr = secptr->EntryList.First();
  680. while (entryptr != NULL && entryptr->Is_Valid()) {
  681. if (index == 0) return(entryptr->Entry);
  682. index--;
  683. entryptr = entryptr->Next();
  684. }
  685. }
  686. return(NULL);
  687. }
  688. /***********************************************************************************************
  689. * Enumerate_Entries -- Count how many entries begin with a certain prefix followed by a range *
  690. * of numbers. *
  691. * *
  692. * *
  693. * *
  694. * *
  695. * INPUT: *
  696. * *
  697. * OUTPUT: *
  698. * *
  699. * WARNINGS: *
  700. * *
  701. * HISTORY: *
  702. * 9/29/99 EHC : Created. *
  703. *=============================================================================================*/
  704. unsigned INIClass::Enumerate_Entries(const char *Section, const char * Entry_Prefix, unsigned StartNumber, unsigned EndNumber)
  705. {
  706. unsigned count = StartNumber;
  707. bool present = false;
  708. char entry[256];
  709. do
  710. {
  711. sprintf(entry, "%s%d", Entry_Prefix, count);
  712. present = Is_Present(Section, entry);
  713. if(present)
  714. count++;
  715. } while(present && (count < EndNumber));
  716. return (count - StartNumber);
  717. }
  718. /***********************************************************************************************
  719. * INIClass::Put_UUBlock -- Store a binary encoded data block into the INI database. *
  720. * *
  721. * Use this routine to store an arbitrary length binary block of data into the INI database.*
  722. * This routine will covert the data into displayable form and then break it into lines *
  723. * that are stored in sequence to the section. A section used to store data in this *
  724. * fashion can not be used for any other entries. *
  725. * *
  726. * INPUT: section -- The section identifier to place the data into. *
  727. * *
  728. * block -- Pointer to the block of binary data to store. *
  729. * *
  730. * len -- The length of the binary data. *
  731. * *
  732. * OUTPUT: bool; Was the data stored to the database? *
  733. * *
  734. * WARNINGS: none *
  735. * *
  736. * HISTORY: *
  737. * 07/03/1996 JLB : Created. *
  738. *=============================================================================================*/
  739. bool INIClass::Put_UUBlock(char const * section, void const * block, int len)
  740. {
  741. if (section == NULL || block == NULL || len < 1) return(false);
  742. Clear(section);
  743. BufferStraw straw(block, len);
  744. Base64Straw bstraw(Base64Straw::ENCODE);
  745. bstraw.Get_From(straw);
  746. int counter = 1;
  747. for (;;) {
  748. char buffer[71];
  749. char sbuffer[32];
  750. int length = bstraw.Get(buffer, sizeof(buffer)-1);
  751. buffer[length] = '\0';
  752. if (length == 0) break;
  753. sprintf(sbuffer, "%d", counter);
  754. Put_String(section, sbuffer, buffer);
  755. counter++;
  756. }
  757. return(true);
  758. }
  759. /***********************************************************************************************
  760. * INIClass::Get_UUBlock -- Fetch an encoded block from the section specified. *
  761. * *
  762. * This routine will take all the entries in the specified section and decompose them into *
  763. * a binary block of data that will be stored into the buffer specified. By using this *
  764. * routine [and the Put_UUBLock counterpart], arbitrary blocks of binary data may be *
  765. * stored in the INI file. A section processed by this routine can contain no other *
  766. * entries than those put there by a previous call to Put_UUBlock. *
  767. * *
  768. * INPUT: section -- The section name to process. *
  769. * *
  770. * block -- Pointer to the buffer that will hold the retrieved data. *
  771. * *
  772. * len -- The length of the buffer. The retrieved data will not fill past this *
  773. * limit. *
  774. * *
  775. * OUTPUT: Returns with the number of bytes decoded into the buffer specified. *
  776. * *
  777. * WARNINGS: If the number of bytes retrieved exactly matches the length of the buffer *
  778. * specified, then you might have a condition of buffer "overflow". *
  779. * *
  780. * HISTORY: *
  781. * 07/02/1996 JLB : Created. *
  782. *=============================================================================================*/
  783. int INIClass::Get_UUBlock(char const * section, void * block, int len) const
  784. {
  785. if (section == NULL) return(0);
  786. Base64Pipe b64pipe(Base64Pipe::DECODE);
  787. BufferPipe bpipe(block, len);
  788. b64pipe.Put_To(&bpipe);
  789. int total = 0;
  790. int counter = Entry_Count(section);
  791. for (int index = 0; index < counter; index++) {
  792. char buffer[128];
  793. int length = Get_String(section, Get_Entry(section, index), "=", buffer, sizeof(buffer));
  794. int outcount = b64pipe.Put(buffer, length);
  795. total += outcount;
  796. }
  797. total += b64pipe.End();
  798. return(total);
  799. }
  800. /***********************************************************************************************
  801. * INIClass::Put_TextBlock -- Stores a block of text into an INI section. *
  802. * *
  803. * This routine will take an arbitrarily long block of text and store it into the INI *
  804. * database. The text is broken up into lines and each line is then stored as a numbered *
  805. * entry in the specified section. A section used to store text in this way can not be used *
  806. * to hold any other entries. The text is presumed to contain space characters scattered *
  807. * throughout it and that one space between words and sentences is natural. *
  808. * *
  809. * INPUT: section -- The section to place the text block into. *
  810. * *
  811. * text -- Pointer to a null terminated text string that holds the block of *
  812. * text. The length can be arbitrary. *
  813. * *
  814. * OUTPUT: bool; Was the text block placed into the database? *
  815. * *
  816. * WARNINGS: none *
  817. * *
  818. * HISTORY: *
  819. * 07/03/1996 JLB : Created. *
  820. *=============================================================================================*/
  821. bool INIClass::Put_TextBlock(char const * section, char const * text)
  822. {
  823. if (section == NULL) return(false);
  824. Clear(section);
  825. int index = 1;
  826. while (text != NULL && *text != 0) {
  827. char buffer[128];
  828. strncpy(buffer, text, 75);
  829. buffer[75] = '\0';
  830. char b[32];
  831. sprintf(b, "%d", index);
  832. /*
  833. ** Scan backward looking for a good break position.
  834. */
  835. int count = strlen(buffer);
  836. if (count > 0) {
  837. if (count >= 75) {
  838. while (count) {
  839. char c = buffer[count];
  840. if (isspace(c)) break;
  841. count--;
  842. }
  843. if (count == 0) {
  844. break;
  845. } else {
  846. buffer[count] = '\0';
  847. }
  848. }
  849. strtrim(buffer);
  850. Put_String(section, b, buffer);
  851. index++;
  852. text = ((char *)text) + count;
  853. } else {
  854. break;
  855. }
  856. }
  857. return(true);
  858. }
  859. /***********************************************************************************************
  860. * INIClass::Get_TextBlock -- Fetch a block of normal text. *
  861. * *
  862. * This will take all entries in the specified section and format them into a block of *
  863. * normalized text. That is, text with single spaces between each concatenated line. All *
  864. * entries in the specified section are processed by this routine. Use Put_TextBlock to *
  865. * build the entries in the section. *
  866. * *
  867. * INPUT: section -- The section name to process. *
  868. * *
  869. * buffer -- Pointer to the buffer that will hold the complete text. *
  870. * *
  871. * len -- The length of the buffer specified. The text will, at most, fill this *
  872. * buffer with the last character being forced to null. *
  873. * *
  874. * OUTPUT: Returns with the number of characters placed into the buffer. The trailing null *
  875. * is not counted. *
  876. * *
  877. * WARNINGS: none *
  878. * *
  879. * HISTORY: *
  880. * 07/02/1996 JLB : Created. *
  881. *=============================================================================================*/
  882. int INIClass::Get_TextBlock(char const * section, char * buffer, int len) const
  883. {
  884. if (len <= 0) return(0);
  885. buffer[0] = '\0';
  886. if (len <= 1) return(0);
  887. int elen = Entry_Count(section);
  888. int total = 0;
  889. for (int index = 0; index < elen; index++) {
  890. /*
  891. ** Add spacers between lines of fetched text.
  892. */
  893. if (index > 0) {
  894. *buffer++ = ' ';
  895. len--;
  896. total++;
  897. }
  898. Get_String(section, Get_Entry(section, index), "", buffer, len);
  899. int partial = strlen(buffer);
  900. total += partial;
  901. buffer += partial;
  902. len -= partial;
  903. if (len <= 1) break;
  904. }
  905. return(total);
  906. }
  907. /***********************************************************************************************
  908. * INIClass::Put_Int -- Stores a signed integer into the INI data base. *
  909. * *
  910. * Use this routine to store an integer value into the section and entry specified. *
  911. * *
  912. * INPUT: section -- The identifier for the section that the entry will be placed in. *
  913. * *
  914. * entry -- The entry identifier used for the integer number. *
  915. * *
  916. * number -- The integer number to store in the database. *
  917. * *
  918. * format -- The format to store the integer. The format is generally only a *
  919. * cosmetic affect. The Get_Int operation will interpret the value the *
  920. * same regardless of what format was used to store the integer. *
  921. * *
  922. * 0 : plain decimal digit *
  923. * 1 : hexadecimal digit (trailing "h") *
  924. * 2 : hexadecimal digit (leading "$") *
  925. * *
  926. * OUTPUT: bool; Was the number stored? *
  927. * *
  928. * WARNINGS: none *
  929. * *
  930. * HISTORY: *
  931. * 07/03/1996 JLB : Created. *
  932. * 07/10/1996 JLB : Handles multiple integer formats. *
  933. *=============================================================================================*/
  934. bool INIClass::Put_Int(char const * section, char const * entry, int number, int format)
  935. {
  936. char buffer[MAX_LINE_LENGTH];
  937. switch (format) {
  938. default:
  939. case 0:
  940. sprintf(buffer, "%d", number);
  941. break;
  942. case 1:
  943. sprintf(buffer, "%Xh", number);
  944. break;
  945. case 2:
  946. sprintf(buffer, "$%X", number);
  947. break;
  948. }
  949. return(Put_String(section, entry, buffer));
  950. }
  951. /***********************************************************************************************
  952. * INIClass::Get_Int -- Fetch an integer entry from the specified section. *
  953. * *
  954. * This routine will fetch an integer value from the entry and section specified. If no *
  955. * entry could be found, then the default value will be returned instead. *
  956. * *
  957. * INPUT: section -- The section name to search under. *
  958. * *
  959. * entry -- The entry name to search for. *
  960. * *
  961. * defvalue -- The default value to use if the specified entry could not be found. *
  962. * *
  963. * OUTPUT: Returns with the integer value specified in the INI database or else returns the *
  964. * default value. *
  965. * *
  966. * WARNINGS: none *
  967. * *
  968. * HISTORY: *
  969. * 07/02/1996 JLB : Created. *
  970. * 07/10/1996 JLB : Handles multiple integer formats. *
  971. *=============================================================================================*/
  972. int INIClass::Get_Int(char const * section, char const * entry, int defvalue) const
  973. {
  974. /*
  975. ** Verify that the parameters are nominally correct.
  976. */
  977. if (section == NULL || entry == NULL) return(defvalue);
  978. INIEntry * entryptr = Find_Entry(section, entry);
  979. if (entryptr && entryptr->Value != NULL) {
  980. if (*entryptr->Value == '$') {
  981. sscanf(entryptr->Value, "$%x", &defvalue);
  982. } else {
  983. if (tolower(entryptr->Value[strlen(entryptr->Value)-1]) == 'h') {
  984. sscanf(entryptr->Value, "%xh", &defvalue);
  985. } else {
  986. defvalue = atoi(entryptr->Value);
  987. }
  988. }
  989. }
  990. return(defvalue);
  991. }
  992. /***********************************************************************************************
  993. * INIClass::Put_Rect -- Store a rectangle into the INI database. *
  994. * *
  995. * This routine will store the four values that constitute the specified rectangle into *
  996. * the database under the section and entry specified. *
  997. * *
  998. * INPUT: section -- Name of the section to place the entry under. *
  999. * *
  1000. * entry -- Name of the entry that the rectangle data will be stored to. *
  1001. * *
  1002. * value -- The rectangle value to store. *
  1003. * *
  1004. * OUTPUT: bool; Was the rectangle data written to the database? *
  1005. * *
  1006. * WARNINGS: none *
  1007. * *
  1008. * HISTORY: *
  1009. * 09/19/1997 JLB : Created. *
  1010. *=============================================================================================*/
  1011. bool INIClass::Put_Rect(char const * section, char const * entry, Rect const & value)
  1012. {
  1013. char buffer[64];
  1014. sprintf(buffer, "%d,%d,%d,%d", value.X, value.Y, value.Width, value.Height);
  1015. return(Put_String(section, entry, buffer));
  1016. }
  1017. /***********************************************************************************************
  1018. * INIClass::Get_Rect -- Retrieve a rectangle data from the database. *
  1019. * *
  1020. * This routine will retrieve the rectangle data from the database at the section and entry *
  1021. * specified. *
  1022. * *
  1023. * INPUT: section -- The name of the section that the entry will be scanned for. *
  1024. * *
  1025. * entry -- The entry that the rectangle data will be lifted from. *
  1026. * *
  1027. * defvalue -- The rectangle value to return if the specified section and entry could *
  1028. * not be found. *
  1029. * *
  1030. * OUTPUT: Returns with the rectangle data from the database or the default value if not *
  1031. * found. *
  1032. * *
  1033. * WARNINGS: none *
  1034. * *
  1035. * HISTORY: *
  1036. * 09/19/1997 JLB : Created. *
  1037. *=============================================================================================*/
  1038. Rect const INIClass::Get_Rect(char const * section, char const * entry, Rect const & defvalue) const
  1039. {
  1040. char buffer[64];
  1041. if (Get_String(section, entry, "0,0,0,0", buffer, sizeof(buffer))) {
  1042. Rect retval = defvalue;
  1043. sscanf(buffer, "%d,%d,%d,%d", &retval.X, &retval.Y, &retval.Width, &retval.Height);
  1044. return(retval);
  1045. }
  1046. return(defvalue);
  1047. }
  1048. /***********************************************************************************************
  1049. * INIClass::Put_Hex -- Store an integer into the INI database, but use a hex format. *
  1050. * *
  1051. * This routine is similar to the Put_Int routine, but the number is stored as a hexadecimal*
  1052. * number. *
  1053. * *
  1054. * INPUT: section -- The identifier for the section that the entry will be placed in. *
  1055. * *
  1056. * entry -- The entry identifier to tag to the integer number specified. *
  1057. * *
  1058. * number -- The number to assign the the specified entry and placed in the *
  1059. * specified section. *
  1060. * *
  1061. * OUTPUT: bool; Was the number placed into the INI database? *
  1062. * *
  1063. * WARNINGS: none *
  1064. * *
  1065. * HISTORY: *
  1066. * 07/03/1996 JLB : Created. *
  1067. *=============================================================================================*/
  1068. bool INIClass::Put_Hex(char const * section, char const * entry, int number)
  1069. {
  1070. char buffer[MAX_LINE_LENGTH];
  1071. sprintf(buffer, "%X", number);
  1072. return(Put_String(section, entry, buffer));
  1073. }
  1074. /***********************************************************************************************
  1075. * INIClass::Get_Hex -- Fetches integer [hex format] from the section and entry specified. *
  1076. * *
  1077. * This routine will search under the section specified, looking for a matching entry. The *
  1078. * value is interpreted as a hexadecimal number and then returned. If no entry could be *
  1079. * found, then the default value is returned instead. *
  1080. * *
  1081. * INPUT: section -- The section identifier to search under. *
  1082. * *
  1083. * entry -- The entry identifier to search for. *
  1084. * *
  1085. * defvalue -- The default value to use if the entry could not be located. *
  1086. * *
  1087. * OUTPUT: Returns with the integer value from the specified section and entry. If no entry *
  1088. * could be found, then the default value will be returned instead. *
  1089. * *
  1090. * WARNINGS: none *
  1091. * *
  1092. * HISTORY: *
  1093. * 07/02/1996 JLB : Created. *
  1094. *=============================================================================================*/
  1095. int INIClass::Get_Hex(char const * section, char const * entry, int defvalue) const
  1096. {
  1097. /*
  1098. ** Verify that the parameters are nominally correct.
  1099. */
  1100. if (section == NULL || entry == NULL) return(defvalue);
  1101. INIEntry * entryptr = Find_Entry(section, entry);
  1102. if (entryptr && entryptr->Value != NULL) {
  1103. sscanf(entryptr->Value, "%x", &defvalue);
  1104. }
  1105. return(defvalue);
  1106. }
  1107. /***********************************************************************************************
  1108. * INIClass::Get_Float -- Fetch a floating point number from the database. *
  1109. * *
  1110. * This routine will retrieve a floating point number from the database. *
  1111. * *
  1112. * INPUT: section -- The section name to find the entry under. *
  1113. * *
  1114. * entry -- The entry name to fetch the float value from. *
  1115. * *
  1116. * defvalue -- Return value to use if the section and entry could not be found. *
  1117. * *
  1118. * OUTPUT: Returns with the float value from the section and entry specified. If not found, *
  1119. * then the default value is returned. *
  1120. * *
  1121. * WARNINGS: none *
  1122. * *
  1123. * HISTORY: *
  1124. * 05/31/1997 JLB : Created. *
  1125. *=============================================================================================*/
  1126. float INIClass::Get_Float(char const * section, char const * entry, float defvalue) const
  1127. {
  1128. /*
  1129. ** Verify that the parameters are nominally correct.
  1130. */
  1131. if (section == NULL || entry == NULL) return(defvalue);
  1132. INIEntry * entryptr = Find_Entry(section, entry);
  1133. if (entryptr != NULL && entryptr->Value != NULL) {
  1134. float val;
  1135. sscanf(entryptr->Value, "%f", &val);
  1136. defvalue = val;
  1137. if (strchr(entryptr->Value, '%') != NULL) {
  1138. defvalue /= 100.0f;
  1139. }
  1140. }
  1141. return(defvalue);
  1142. }
  1143. /***********************************************************************************************
  1144. * INIClass::Put_Float -- Store a floating point number to the database. *
  1145. * *
  1146. * This routine will store a flaoting point number to the section and entry of the *
  1147. * database. *
  1148. * *
  1149. * INPUT: section -- The section to store the entry under. *
  1150. * *
  1151. * entry -- The entry to store the floating point number to. *
  1152. * *
  1153. * number -- The floating point number to store. *
  1154. * *
  1155. * OUTPUT: bool; Was the floating point number stored without error? *
  1156. * *
  1157. * WARNINGS: none *
  1158. * *
  1159. * HISTORY: *
  1160. * 05/31/1997 JLB : Created. *
  1161. *=============================================================================================*/
  1162. bool INIClass::Put_Float(char const * section, char const * entry, double number)
  1163. {
  1164. char buffer[MAX_LINE_LENGTH];
  1165. sprintf(buffer, "%f", (float)number);
  1166. return(Put_String(section, entry, buffer));
  1167. }
  1168. /***********************************************************************************************
  1169. * INIClass::Put_String -- Output a string to the section and entry specified. *
  1170. * *
  1171. * This routine will put an arbitrary string to the section and entry specified. Any *
  1172. * previous matching entry will be replaced. *
  1173. * *
  1174. * INPUT: section -- The section identifier to place the string under. *
  1175. * *
  1176. * entry -- The entry identifier to identify this string [placed under the section]*
  1177. * *
  1178. * string -- Pointer to the string to assign to this entry. *
  1179. * *
  1180. * OUTPUT: bool; Was the entry assigned without error? *
  1181. * *
  1182. * WARNINGS: none *
  1183. * *
  1184. * HISTORY: *
  1185. * 07/02/1996 JLB : Created. *
  1186. * 11/02/1996 JLB : Uses index handler. *
  1187. * 12/08/1997 EHC : Debug message for duplicate entries *
  1188. * 03/13/1998 NH : On duplicate CRC, check if strings identical. *
  1189. *=============================================================================================*/
  1190. bool INIClass::Put_String(char const * section, char const * entry, char const * string)
  1191. {
  1192. if (section == NULL || entry == NULL) return(false);
  1193. INISection * secptr = Find_Section(section);
  1194. if (secptr == NULL) {
  1195. secptr = W3DNEW INISection(strdup(section));
  1196. if (secptr == NULL) return(false);
  1197. SectionList->Add_Tail(secptr);
  1198. SectionIndex->Add_Index(secptr->Index_ID(), secptr);
  1199. }
  1200. /*
  1201. ** Remove the old entry if found and print debug message
  1202. */
  1203. INIEntry * entryptr = secptr->Find_Entry(entry);
  1204. if (entryptr != NULL) {
  1205. if (strcmp(entryptr->Entry, entry)) {
  1206. DuplicateCRCError("INIClass::Put_String", entry);
  1207. } else {
  1208. OutputDebugString("INIClass::Put_String - Duplicate Entry \"");
  1209. OutputDebugString(entry);
  1210. OutputDebugString("\"\n");
  1211. }
  1212. secptr->EntryIndex.Remove_Index(entryptr->Index_ID());
  1213. delete entryptr;
  1214. }
  1215. /*
  1216. ** Create and add the new entry.
  1217. */
  1218. if (string != NULL && strlen(string) > 0) {
  1219. entryptr = W3DNEW INIEntry(strdup(entry), strdup(string));
  1220. if (entryptr == NULL) {
  1221. return(false);
  1222. }
  1223. secptr->EntryList.Add_Tail(entryptr);
  1224. secptr->EntryIndex.Add_Index(entryptr->Index_ID(), entryptr);
  1225. }
  1226. return(true);
  1227. }
  1228. /***********************************************************************************************
  1229. * INIClass::Get_String -- Fetch the value of a particular entry in a specified section. *
  1230. * *
  1231. * This will retrieve the entire text to the right of the "=" character. The text is *
  1232. * found by finding a matching entry in the section specified. If no matching entry could *
  1233. * be found, then the default value will be stored in the output string buffer. *
  1234. * *
  1235. * INPUT: section -- Pointer to the section name to search under. *
  1236. * *
  1237. * entry -- The entry identifier to search for. *
  1238. * *
  1239. * defvalue -- If no entry could be found, then this text will be returned. *
  1240. * *
  1241. * buffer -- Output buffer to store the retrieved string into. *
  1242. * *
  1243. * size -- The size of the output buffer. The maximum string length that could *
  1244. * be retrieved will be one less than this length. This is due to the *
  1245. * forced trailing zero added to the end of the string. *
  1246. * *
  1247. * OUTPUT: Returns with the length of the string retrieved. *
  1248. * *
  1249. * WARNINGS: none *
  1250. * *
  1251. * HISTORY: *
  1252. * 07/02/1996 JLB : Created. *
  1253. *=============================================================================================*/
  1254. int INIClass::Get_String(char const * section, char const * entry, char const * defvalue, char * buffer, int size) const
  1255. {
  1256. /*
  1257. ** Verify that the parameters are nominally legal.
  1258. */
  1259. // if (buffer != NULL && size > 0) {
  1260. // buffer[0] = '\0';
  1261. // }
  1262. if (buffer == NULL || size < 2 || section == NULL || entry == NULL) return(0);
  1263. /*
  1264. ** Fetch the entry string if it is present. If not, then the normal default
  1265. ** value will be used as the entry value.
  1266. */
  1267. INIEntry * entryptr = Find_Entry(section, entry);
  1268. if (entryptr != NULL && entryptr->Value != NULL) {
  1269. defvalue = entryptr->Value;
  1270. }
  1271. /*
  1272. ** Fill in the buffer with the entry value and return with the length of the string.
  1273. */
  1274. if (defvalue == NULL) {
  1275. buffer[0] = '\0';
  1276. return(0);
  1277. } else {
  1278. strncpy(buffer, defvalue, size);
  1279. buffer[size-1] = '\0';
  1280. strtrim(buffer);
  1281. return(strlen(buffer));
  1282. }
  1283. }
  1284. /*
  1285. ** GetString
  1286. */
  1287. StringClass INIClass::Get_String(char const * section, char const * entry, char const * defvalue) const
  1288. {
  1289. if (section == NULL || entry == NULL) return StringClass();
  1290. /*
  1291. ** Fetch the entry string if it is present. If not, then the normal default
  1292. ** value will be used as the entry value.
  1293. */
  1294. INIEntry * entryptr = Find_Entry(section, entry);
  1295. if (entryptr != NULL) {
  1296. defvalue = entryptr->Value;
  1297. }
  1298. if (defvalue == NULL) return StringClass();
  1299. return StringClass( defvalue );
  1300. }
  1301. /***********************************************************************************************
  1302. * INIClass::Get_String -- Fetch the value of a particular entry in a specified section. *
  1303. * *
  1304. * This will retrieve the entire text to the right of the "=" character. The text is *
  1305. * found by finding a matching entry in the section specified. If no matching entry could *
  1306. * be found, then the default value will be stored in the output string buffer. *
  1307. * *
  1308. * INPUT: section -- Pointer to the section name to search under. *
  1309. * *
  1310. * entry -- The entry identifier to search for. *
  1311. * *
  1312. * defvalue -- If no entry could be found, then this text will be returned. *
  1313. * *
  1314. * buffer -- Output buffer to store the retrieved string into. *
  1315. * *
  1316. * size -- The size of the output buffer. The maximum string length that could *
  1317. * be retrieved will be one less than this length. This is due to the *
  1318. * forced trailing zero added to the end of the string. *
  1319. * *
  1320. * OUTPUT: Returns with the length of the string retrieved. *
  1321. * *
  1322. * WARNINGS: none *
  1323. * *
  1324. * HISTORY: *
  1325. * 07/02/1996 JLB : Created. *
  1326. *=============================================================================================*/
  1327. char *INIClass::Get_Alloc_String(char const * section, char const * entry, char const * defvalue) const
  1328. {
  1329. if (section == NULL || entry == NULL) return(NULL);
  1330. /*
  1331. ** Fetch the entry string if it is present. If not, then the normal default
  1332. ** value will be used as the entry value.
  1333. */
  1334. INIEntry * entryptr = Find_Entry(section, entry);
  1335. if (entryptr != NULL) {
  1336. defvalue = entryptr->Value;
  1337. }
  1338. if (defvalue == NULL) return NULL;
  1339. return(strdup(defvalue));
  1340. }
  1341. int INIClass::Get_List_Index(char const * section, char const * entry, int const defvalue, char *list[])
  1342. {
  1343. if (section == NULL || entry == NULL) return(0);
  1344. INIEntry * entryptr = Find_Entry(section, entry);
  1345. if (entryptr == NULL || entryptr->Value == NULL) {
  1346. return defvalue;
  1347. }
  1348. for (int lp = 0; list[lp]; lp++) {
  1349. if (stricmp(entryptr->Value, list[lp]) == 0) {
  1350. return lp;
  1351. }
  1352. assert(lp < 1000);
  1353. }
  1354. return defvalue;
  1355. }
  1356. int INIClass::Get_Int_Bitfield(char const * section, char const * entry, int defvalue, char *list[])
  1357. {
  1358. // if we can't find the entry or the entry is null just return the default value
  1359. INIEntry * entryptr = Find_Entry(section, entry);
  1360. if (entryptr == NULL || entryptr->Value == NULL) {
  1361. return defvalue;
  1362. }
  1363. // swim through the entry breaking it down into its token pieces and
  1364. // get the bitfield value for each piece.
  1365. // int count = 0; (gth) initailized but not referenced...
  1366. int retval = 0;
  1367. char *str = strdup(entryptr->Value);
  1368. int lp;
  1369. for (char *token = strtok(str, "|+"); token; token = strtok(NULL, "|+")) {
  1370. for (lp = 0; list[lp]; lp++) {
  1371. // if this list entry matches our string token then we need
  1372. // to set this bit.
  1373. if (stricmp(token, list[lp]) == 0) {
  1374. retval |= (1 << lp);
  1375. break;
  1376. }
  1377. }
  1378. // if we reached the end of the list and found nothing then we need
  1379. // to assert since we have an unidentified value
  1380. if (list[lp] == NULL) assert(lp < 1000);
  1381. }
  1382. free(str);
  1383. return retval;
  1384. }
  1385. int * INIClass::Get_Alloc_Int_Array(char const * section, char const * entry, int listend)
  1386. {
  1387. int *retval = NULL;
  1388. INIEntry * entryptr = Find_Entry(section, entry);
  1389. if (entryptr == NULL || entryptr->Value == NULL) {
  1390. retval = W3DNEWARRAY int[1];
  1391. retval[0] = listend;
  1392. return retval;
  1393. }
  1394. // count all the tokens in the string. Each token should represent an
  1395. // integer number.
  1396. int count = 0;
  1397. char *str = strdup(entryptr->Value);
  1398. char *token;
  1399. for (token = strtok(str, " "); token; token = strtok(NULL, " ")) {
  1400. count++;
  1401. }
  1402. free(str);
  1403. // now that we know how many tokens there are in the string, allocate a int
  1404. // array to hold the tokens and parse out the actual values.
  1405. retval = W3DNEWARRAY int[count+1];
  1406. count = 0;
  1407. str = strdup(entryptr->Value);
  1408. for (token = strtok(str, " "); token; token = strtok(NULL, " ")) {
  1409. retval[count] = atoi(token);
  1410. count++;
  1411. }
  1412. free(str);
  1413. // arrays of integers are terminated with the listend variable passed in
  1414. retval[count] = listend;
  1415. // now that we have the allocated array with the results filled in lets return
  1416. // the results.
  1417. return retval;
  1418. }
  1419. /***********************************************************************************************
  1420. * INIClass::Put_Bool -- Store a boolean value into the INI database. *
  1421. * *
  1422. * Use this routine to place a boolean value into the INI database. The boolean value will *
  1423. * be stored as "yes" or "no". *
  1424. * *
  1425. * INPUT: section -- The section to place the entry and boolean value into. *
  1426. * *
  1427. * entry -- The entry identifier to tag to the boolean value. *
  1428. * *
  1429. * value -- The boolean value to place into the database. *
  1430. * *
  1431. * OUTPUT: bool; Was the boolean value placed into the database? *
  1432. * *
  1433. * WARNINGS: none *
  1434. * *
  1435. * HISTORY: *
  1436. * 07/03/1996 JLB : Created. *
  1437. *=============================================================================================*/
  1438. bool INIClass::Put_Bool(char const * section, char const * entry, bool value)
  1439. {
  1440. if (value) {
  1441. return(Put_String(section, entry, "yes"));
  1442. } else {
  1443. return(Put_String(section, entry, "no"));
  1444. }
  1445. }
  1446. /***********************************************************************************************
  1447. * INIClass::Get_Bool -- Fetch a boolean value for the section and entry specified. *
  1448. * *
  1449. * This routine will search under the section specified, looking for a matching entry. If *
  1450. * one is found, the value is interpreted as a boolean value and then returned. In the case *
  1451. * of no matching entry, the default value will be returned instead. The boolean value *
  1452. * is interpreted using the standard boolean conventions. e.g., "Yes", "Y", "1", "True", *
  1453. * "T" are all consider to be a TRUE boolean value. *
  1454. * *
  1455. * INPUT: section -- The section to search under. *
  1456. * *
  1457. * entry -- The entry to search for. *
  1458. * *
  1459. * defvalue -- The default value to use if no matching entry could be located. *
  1460. * *
  1461. * OUTPUT: Returns with the boolean value of the specified section and entry. If no match *
  1462. * then the default boolean value is returned. *
  1463. * *
  1464. * WARNINGS: none *
  1465. * *
  1466. * HISTORY: *
  1467. * 07/02/1996 JLB : Created. *
  1468. *=============================================================================================*/
  1469. bool INIClass::Get_Bool(char const * section, char const * entry, bool defvalue) const
  1470. {
  1471. /*
  1472. ** Verify that the parameters are nominally correct.
  1473. */
  1474. if (section == NULL || entry == NULL) return(defvalue);
  1475. INIEntry * entryptr = Find_Entry(section, entry);
  1476. if (entryptr && entryptr->Value != NULL) {
  1477. switch (toupper(*entryptr->Value)) {
  1478. case 'Y':
  1479. case 'T':
  1480. case '1':
  1481. return(true);
  1482. case 'N':
  1483. case 'F':
  1484. case '0':
  1485. return(false);
  1486. }
  1487. }
  1488. return(defvalue);
  1489. }
  1490. /***********************************************************************************************
  1491. * INIClass::Put_Point -- Store a point value to the database. *
  1492. * *
  1493. * This routine will store the point value to the INI database under the section and entry *
  1494. * specified. *
  1495. * *
  1496. * INPUT: section -- The name of the section to store the entry under. *
  1497. * *
  1498. * entry -- The entry to store the point data to. *
  1499. * *
  1500. * value -- The point value to store. *
  1501. * *
  1502. * OUTPUT: bool; Was the point value stored to the database? *
  1503. * *
  1504. * WARNINGS: none *
  1505. * *
  1506. * HISTORY: *
  1507. * 09/19/1997 JLB : Created. *
  1508. *=============================================================================================*/
  1509. bool INIClass::Put_Point(char const * section, char const * entry, TPoint2D<int> const & value)
  1510. {
  1511. char buffer[54];
  1512. sprintf(buffer, "%d,%d", value.X, value.Y);
  1513. return(Put_String(section, entry, buffer));
  1514. }
  1515. /***********************************************************************************************
  1516. * INIClass::Get_Point -- Fetch a point value from the INI database. *
  1517. * *
  1518. * This routine will retrieve a point value from the database by looking in the section and *
  1519. * entry specified. *
  1520. * *
  1521. * INPUT: section -- The name of the section to search for the entry under. *
  1522. * *
  1523. * entry -- The entry to search for. *
  1524. * *
  1525. * defvalue -- The default value to return if the section and entry were not found. *
  1526. * *
  1527. * OUTPUT: Returns with the point value retrieved from the database or the default value if *
  1528. * the section and entry were not found. *
  1529. * *
  1530. * WARNINGS: none *
  1531. * *
  1532. * HISTORY: *
  1533. * 09/19/1997 JLB : Created. *
  1534. *=============================================================================================*/
  1535. TPoint2D<int> const INIClass::Get_Point(char const * section, char const * entry, TPoint2D<int> const & defvalue) const
  1536. {
  1537. char buffer[64];
  1538. if (Get_String(section, entry, "", buffer, sizeof(buffer))) {
  1539. int x,y;
  1540. sscanf(buffer, "%d,%d", &x, &y);
  1541. return(TPoint2D<int>(x, y));
  1542. }
  1543. return(defvalue);
  1544. }
  1545. /***********************************************************************************************
  1546. * INIClass::Put_Point -- Stores a 3D point to the database. *
  1547. * *
  1548. * This routine will store the 3D point value to the database under the section and entry *
  1549. * specified. *
  1550. * *
  1551. * INPUT: section -- The name of the section that the entry will be stored under. *
  1552. * *
  1553. * entry -- The name of the entry that the point will be stored to. *
  1554. * *
  1555. * value -- The 3D point value to store. *
  1556. * *
  1557. * OUTPUT: bool; Was the point stored to the database? *
  1558. * *
  1559. * WARNINGS: none *
  1560. * *
  1561. * HISTORY: *
  1562. * 09/19/1997 JLB : Created. *
  1563. *=============================================================================================*/
  1564. bool INIClass::Put_Point(char const * section, char const * entry, TPoint3D<int> const & value)
  1565. {
  1566. char buffer[54];
  1567. sprintf(buffer, "%d,%d,%d", value.X, value.Y, value.Z);
  1568. return(Put_String(section, entry, buffer));
  1569. }
  1570. /***********************************************************************************************
  1571. * INIClass::Get_Point -- Fetch a 3D point from the database. *
  1572. * *
  1573. * This routine will retrieve a 3D point from the database from the section and entry *
  1574. * specified. *
  1575. * *
  1576. * INPUT: section -- The name of the section to search for th entry under. *
  1577. * *
  1578. * entry -- The name of the entry to search for. *
  1579. * *
  1580. * defvaule -- The default value to return if the section and entry could not be *
  1581. * found. *
  1582. * *
  1583. * OUTPUT: Returns with the 3D point from the database or the default value if the section *
  1584. * and entry could not be found. *
  1585. * *
  1586. * WARNINGS: none *
  1587. * *
  1588. * HISTORY: *
  1589. * 09/19/1997 JLB : Created. *
  1590. *=============================================================================================*/
  1591. TPoint3D<int> const INIClass::Get_Point(char const * section, char const * entry, TPoint3D<int> const & defvalue) const
  1592. {
  1593. char buffer[64];
  1594. if (Get_String(section, entry, "", buffer, sizeof(buffer))) {
  1595. int x,y,z;
  1596. sscanf(buffer, "%d,%d,%d", &x, &y, &z);
  1597. return(TPoint3D<int>(x, y, z));
  1598. }
  1599. return(defvalue);
  1600. }
  1601. /***********************************************************************************************
  1602. * INIClass::Put_Point -- Stores a 3D point to the database. *
  1603. * *
  1604. * This routine will store the 3D point value to the database under the section and entry *
  1605. * specified. *
  1606. * *
  1607. * INPUT: section -- The name of the section that the entry will be stored under. *
  1608. * *
  1609. * entry -- The name of the entry that the point will be stored to. *
  1610. * *
  1611. * value -- The 3D point value to store. *
  1612. * *
  1613. * OUTPUT: bool; Was the point stored to the database? *
  1614. * *
  1615. * WARNINGS: none *
  1616. * *
  1617. * HISTORY: *
  1618. * 09/19/1997 JLB : Created. *
  1619. *=============================================================================================*/
  1620. bool INIClass::Put_Point(char const * section, char const * entry, TPoint3D<float> const & value)
  1621. {
  1622. char buffer[54];
  1623. sprintf(buffer, "%f,%f,%f", (float)value.X, (float)value.Y, (float)value.Z);
  1624. return(Put_String(section, entry, buffer));
  1625. }
  1626. /***********************************************************************************************
  1627. * INIClass::Get_Point -- Fetch a 3D point from the database. *
  1628. * *
  1629. * This routine will retrieve a 3D point from the database from the section and entry *
  1630. * specified. *
  1631. * *
  1632. * INPUT: section -- The name of the section to search for th entry under. *
  1633. * *
  1634. * entry -- The name of the entry to search for. *
  1635. * *
  1636. * defvaule -- The default value to return if the section and entry could not be *
  1637. * found. *
  1638. * *
  1639. * OUTPUT: Returns with the 3D point from the database or the default value if the section *
  1640. * and entry could not be found. *
  1641. * *
  1642. * WARNINGS: none *
  1643. * *
  1644. * HISTORY: *
  1645. * 09/19/1997 JLB : Created. *
  1646. *=============================================================================================*/
  1647. TPoint3D<float> const INIClass::Get_Point(char const * section, char const * entry, TPoint3D<float> const & defvalue) const
  1648. {
  1649. char buffer[64];
  1650. if (Get_String(section, entry, "", buffer, sizeof(buffer))) {
  1651. float x,y,z;
  1652. sscanf(buffer, "%f,%f,%f", &x, &y, &z);
  1653. return(TPoint3D<float>(x, y, z));
  1654. }
  1655. return(defvalue);
  1656. }
  1657. /***********************************************************************************************
  1658. * INIClass::Get_Point -- Fetch a point value from the INI database. *
  1659. * *
  1660. * This routine will retrieve a point value from the database by looking in the section and *
  1661. * entry specified. *
  1662. * *
  1663. * INPUT: section -- The name of the section to search for the entry under. *
  1664. * *
  1665. * entry -- The entry to search for. *
  1666. * *
  1667. * defvalue -- The default value to return if the section and entry were not found. *
  1668. * *
  1669. * OUTPUT: Returns with the point value retrieved from the database or the default value if *
  1670. * the section and entry were not found. *
  1671. * *
  1672. * WARNINGS: none *
  1673. * *
  1674. * HISTORY: *
  1675. * 07/14/1999 NH : Created. *
  1676. *=============================================================================================*/
  1677. TPoint2D<float> const INIClass::Get_Point(char const * section, char const * entry, TPoint2D<float> const & defvalue) const
  1678. {
  1679. char buffer[64];
  1680. if (Get_String(section, entry, "", buffer, sizeof(buffer))) {
  1681. float x,y;
  1682. sscanf(buffer, "%f,%f", &x, &y);
  1683. return(TPoint2D<float>(x, y));
  1684. }
  1685. return(defvalue);
  1686. }
  1687. /***********************************************************************************************
  1688. * INISection::Find_Entry -- Finds a specified entry and returns pointer to it. *
  1689. * *
  1690. * This routine scans the supplied entry for the section specified. This is used for *
  1691. * internal database maintenance. *
  1692. * *
  1693. * INPUT: entry -- The entry to scan for. *
  1694. * *
  1695. * OUTPUT: Returns with a pointer to the entry control structure if the entry was found. *
  1696. * Otherwise it returns NULL. *
  1697. * *
  1698. * WARNINGS: none *
  1699. * *
  1700. * HISTORY: *
  1701. * 07/03/1996 JLB : Created. *
  1702. * 11/02/1996 JLB : Uses index handler. *
  1703. * 12/08/1997 EHC : Uses member CRC function
  1704. *=============================================================================================*/
  1705. INIEntry * INISection::Find_Entry(char const * entry) const
  1706. {
  1707. if (entry != NULL) {
  1708. // int crc = CRCEngine()(entry, strlen(entry));
  1709. int crc = CRC::String(entry);
  1710. if (EntryIndex.Is_Present(crc)) {
  1711. return(EntryIndex[crc]);
  1712. }
  1713. }
  1714. return(NULL);
  1715. }
  1716. /***********************************************************************************************
  1717. * INIClass::Put_PKey -- Stores the key to the INI database. *
  1718. * *
  1719. * The key stored to the database will have both the exponent and modulus portions saved. *
  1720. * Since the fast key only requires the modulus, it is only necessary to save the slow *
  1721. * key to the database. However, storing the slow key stores the information necessary to *
  1722. * generate the fast and slow keys. Because public key encryption requires one key to be *
  1723. * completely secure, only store the fast key in situations where the INI database will *
  1724. * be made public. *
  1725. * *
  1726. * INPUT: key -- The key to store the INI database. *
  1727. * *
  1728. * OUTPUT: bool; Was the key stored to the database? *
  1729. * *
  1730. * WARNINGS: Store the fast key for public INI database availability. Store the slow key if *
  1731. * the INI database is secure. *
  1732. * *
  1733. * HISTORY: *
  1734. * 07/08/1996 JLB : Created. *
  1735. *=============================================================================================*/
  1736. bool INIClass::Put_PKey(PKey const & key)
  1737. {
  1738. char buffer[512];
  1739. int len = key.Encode_Modulus(buffer);
  1740. Put_UUBlock("PublicKey", buffer, len);
  1741. len = key.Encode_Exponent(buffer);
  1742. Put_UUBlock("PrivateKey", buffer, len);
  1743. return(true);
  1744. }
  1745. /***********************************************************************************************
  1746. * INIClass::Get_PKey -- Fetch a key from the ini database. *
  1747. * *
  1748. * This routine will fetch the key from the INI database. The key fetched is controlled by *
  1749. * the parameter. There are two choices of key -- the fast or slow key. *
  1750. * *
  1751. * INPUT: fast -- Should the fast key be retrieved? The fast key has the advantage of *
  1752. * requiring only the modulus value. *
  1753. * *
  1754. * OUTPUT: Returns with the key retrieved. *
  1755. * *
  1756. * WARNINGS: none *
  1757. * *
  1758. * HISTORY: *
  1759. * 07/08/1996 JLB : Created. *
  1760. *=============================================================================================*/
  1761. PKey INIClass::Get_PKey(bool fast) const
  1762. {
  1763. PKey key;
  1764. char buffer[512];
  1765. /*
  1766. ** When retrieving the fast key, the exponent is a known constant. Don't parse the
  1767. ** exponent from the database.
  1768. */
  1769. if (fast) {
  1770. BigInt exp = PKey::Fast_Exponent();
  1771. exp.DEREncode((unsigned char *)buffer);
  1772. key.Decode_Exponent(buffer);
  1773. } else {
  1774. Get_UUBlock("PrivateKey", buffer, sizeof(buffer));
  1775. key.Decode_Exponent(buffer);
  1776. }
  1777. Get_UUBlock("PublicKey", buffer, sizeof(buffer));
  1778. key.Decode_Modulus(buffer);
  1779. return(key);
  1780. }
  1781. /***********************************************************************************************
  1782. * INIClass::Strip_Comments -- Strips comments of the specified text line. *
  1783. * *
  1784. * This routine will scan the string (text line) supplied and if any comment portions are *
  1785. * found, they will be trimmed off. Leading and trailing blanks are also removed. *
  1786. * *
  1787. * INPUT: buffer -- Pointer to the null terminate string to be processed. *
  1788. * *
  1789. * OUTPUT: none *
  1790. * *
  1791. * WARNINGS: none *
  1792. * *
  1793. * HISTORY: *
  1794. * 07/03/1996 JLB : Created. *
  1795. *=============================================================================================*/
  1796. void INIClass::Strip_Comments(char * buffer)
  1797. {
  1798. if (buffer != NULL) {
  1799. char * comment = strchr(buffer, ';');
  1800. if (comment) {
  1801. *comment = '\0';
  1802. strtrim(buffer);
  1803. }
  1804. }
  1805. }
  1806. /***********************************************************************************************
  1807. * INIClass::CRC - returns a (hopefully) unique 32-bit value for a string *
  1808. * *
  1809. * *
  1810. * *
  1811. * *
  1812. * INPUT: pointer to null terminated string *
  1813. * *
  1814. * OUTPUT: integer that is highly likely to be unique for a given INI file. *
  1815. * *
  1816. * WARNINGS: *
  1817. * *
  1818. * HISTORY: *
  1819. * 12/8/97 EHC : Created. *
  1820. *=============================================================================================*/
  1821. int INIClass::CRC(const char *string)
  1822. {
  1823. // simply call the CRC class string evaluator.
  1824. return CRC::String(string);
  1825. }
  1826. /***********************************************************************************************
  1827. * -- Displays debug information when a duplicate entry is found in an INI file *
  1828. * *
  1829. * *
  1830. * *
  1831. * *
  1832. * INPUT: message - text description of function with problem *
  1833. * entry - text buffer for duplicate entry name *
  1834. * OUTPUT: *
  1835. * *
  1836. * WARNINGS: will assert(0) and exit program. INI errors are considered fatal at this time. *
  1837. * *
  1838. * HISTORY: *
  1839. * 12/9/97 EHC : Created. *
  1840. *=============================================================================================*/
  1841. void INIClass::DuplicateCRCError(const char *message, const char *entry)
  1842. {
  1843. OutputDebugString(message);
  1844. OutputDebugString(" - Duplicate Entry CRC \"");
  1845. OutputDebugString(entry);
  1846. OutputDebugString("\"\n");
  1847. assert(0);
  1848. // MessageBox(0, "Duplicate entry CRC in INI file.", message, MB_OK);
  1849. }