PROFILE.CPP 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870
  1. /*
  2. ** Command & Conquer Red Alert(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. /* $Header: /CounterStrike/PROFILE.CPP 1 3/03/97 10:25a Joe_bostic $ */
  19. /***********************************************************************************************
  20. *** 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 ***
  21. ***********************************************************************************************
  22. * *
  23. * Project Name : Command & Conquer *
  24. * *
  25. * File Name : PROFILE.CPP *
  26. * *
  27. * Programmer : Joe L. Bostic *
  28. * *
  29. * Start Date : September 10, 1993 *
  30. * *
  31. * Last Update : September 10, 1993 [JLB] *
  32. * *
  33. *---------------------------------------------------------------------------------------------*
  34. * Functions: *
  35. * WWGetPrivateProfileInt -- Fetches integer value from INI. *
  36. * WWGetPrivateProfileString -- Fetch string from INI. *
  37. * WWWritePrivateProfileInt -- Write a profile int to the profile data block. *
  38. * WWWritePrivateProfileString -- Write a string to the profile data block. *
  39. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  40. #include "function.h"
  41. static char * WriteBinBuffer = NULL;
  42. static int WriteBinBufferLen = 0;
  43. static int WriteBinBufferPos = 0;
  44. static int WriteBinBufferMax = 0;
  45. static char * ReadBinBuffer = NULL;
  46. static int ReadBinBufferLen = 0;
  47. static int ReadBinBufferPos = 0;
  48. static int ReadBinBufferMax = 0;
  49. /***************************************************************************
  50. * Read_Private_Config_Struct -- Fetches override integer value. *
  51. * *
  52. * INPUT: *
  53. * OUTPUT: *
  54. * WARNINGS: *
  55. * HISTORY: *
  56. * 08/05/1992 JLB : Created. *
  57. *=========================================================================*/
  58. bool Read_Private_Config_Struct(FileClass & file, NewConfigType * config)
  59. {
  60. INIClass ini;
  61. ini.Load(file);
  62. config->DigitCard = ini.Get_Hex("Sound", "Card", 0);
  63. config->IRQ = ini.Get_Int("Sound", "IRQ", 0);
  64. config->DMA = ini.Get_Int("Sound", "DMA", 0);
  65. config->Port = ini.Get_Hex("Sound", "Port", 0);
  66. config->BitsPerSample= ini.Get_Int("Sound", "BitsPerSample", 0);
  67. config->Channels = ini.Get_Int("Sound", "Channels", 0);
  68. config->Reverse = ini.Get_Int("Sound", "Reverse", 0);
  69. config->Speed = ini.Get_Int("Sound", "Speed", 0);
  70. ini.Get_String("Language", "Language", NULL, config->Language, sizeof(config->Language));
  71. // config->DigitCard = WWGetPrivateProfileHex("Sound", "Card", profile);
  72. // config->IRQ = WWGetPrivateProfileInt("Sound", "IRQ", 0,profile);
  73. // config->DMA = WWGetPrivateProfileInt("Sound", "DMA", 0,profile);
  74. // config->Port = WWGetPrivateProfileHex("Sound", "Port", profile);
  75. // config->BitsPerSample= WWGetPrivateProfileInt("Sound", "BitsPerSample",0,profile);
  76. // config->Channels = WWGetPrivateProfileInt("Sound", "Channels", 0,profile);
  77. // config->Reverse = WWGetPrivateProfileInt("Sound", "Reverse", 0,profile);
  78. // config->Speed = WWGetPrivateProfileInt("Sound", "Speed", 0,profile);
  79. // WWGetPrivateProfileString("Language", "Language", NULL, config->Language, 3, profile);
  80. return((config->DigitCard == 0) && (config->IRQ == 0) && (config->DMA == 0));
  81. }
  82. /***************************************************************************
  83. * Get_Private_Profile_Hex -- Fetches override integer value. *
  84. * *
  85. * INPUT: *
  86. * OUTPUT: *
  87. * WARNINGS: *
  88. * HISTORY: *
  89. * 08/05/1992 MML : Created. *
  90. *=========================================================================*/
  91. unsigned WWGetPrivateProfileHex (char const * section, char const * entry, char * profile)
  92. {
  93. char buffer[16]; // Integer staging buffer.
  94. unsigned card;
  95. memset (buffer, '0', sizeof(buffer)); // MAX_ENTRY_SIZE = 15
  96. buffer[sizeof(buffer)-1] = '\0';
  97. WWGetPrivateProfileString(section, entry, "0", buffer, sizeof(buffer), profile);
  98. if (strlen (buffer) > 0) {
  99. sscanf (buffer, "%x", &card);
  100. } else {
  101. card = 0;
  102. }
  103. return(card);
  104. }
  105. /***********************************************************************************************
  106. * WWGetPrivateProfileInt -- Fetches integer value. *
  107. * *
  108. * INPUT: *
  109. * section section to read from *
  110. * *
  111. * entry name of entry to read *
  112. * *
  113. * def default value, if entry isn't found *
  114. * *
  115. * profile buffer containing INI data *
  116. * *
  117. * OUTPUT: *
  118. * integer requested *
  119. * *
  120. * WARNINGS: *
  121. * none. *
  122. * *
  123. * HISTORY: *
  124. * 08/05/1992 JLB : Created. *
  125. *=============================================================================================*/
  126. int WWGetPrivateProfileInt(char const * section, char const * entry, int def, char * profile)
  127. {
  128. char buffer[16]; // Integer staging buffer.
  129. /*
  130. ** Store the default in the buffer.
  131. */
  132. sprintf(buffer, "%d", def);
  133. /*
  134. ** Get the buffer; use itself as the default.
  135. */
  136. WWGetPrivateProfileString(section, entry, buffer, buffer, sizeof(buffer)-1, profile);
  137. /*
  138. ** Convert to int & return.
  139. */
  140. return(atoi(buffer));
  141. }
  142. /***********************************************************************************************
  143. * WWWritePrivateProfileInt -- Write a profile int to the profile data block. *
  144. * *
  145. * INPUT: *
  146. * section section name to write to *
  147. * *
  148. * entry name of entry to write; if NULL, the entire section is deleted *
  149. * *
  150. * value value to write *
  151. * *
  152. * profile INI buffer *
  153. * *
  154. * OUTPUT: *
  155. * true = success, false = failure *
  156. * *
  157. * WARNINGS: *
  158. * none. *
  159. * *
  160. * HISTORY: *
  161. * 10/07/1992 JLB : Created. *
  162. *=============================================================================================*/
  163. bool WWWritePrivateProfileInt(char const * section, char const * entry, int value, char * profile)
  164. {
  165. char buffer[250]; // Working section buffer.
  166. /*
  167. ** Just return if nothing to do.
  168. */
  169. if (!profile || !section) {
  170. return(true);
  171. }
  172. /*
  173. ** Generate string to save.
  174. */
  175. sprintf(buffer, "%d", value);
  176. /*
  177. ** Save the string.
  178. */
  179. return(WWWritePrivateProfileString(section, entry, buffer, profile));
  180. }
  181. /***********************************************************************************************
  182. * WWGetPrivateProfileString -- Fetch game override string. *
  183. * *
  184. * INPUT: *
  185. * section section name to read from *
  186. * *
  187. * entry name of entry to read; if NULL, all entry names are returned *
  188. * *
  189. * def default string to use if not found; can be NULL *
  190. * *
  191. * retbuffer buffer to store result in *
  192. * *
  193. * retlen max length of return buffer *
  194. * *
  195. * profile INI buffer *
  196. * *
  197. * OUTPUT: *
  198. * ptr to entry found in INI buf; NULL if not found *
  199. * *
  200. * WARNINGS: *
  201. * On the PC, the "\n" (10) is translated to "\r\n" (13,10) when it's written *
  202. * to disk. This routine must take this into consideration, by searching *
  203. * for \n when scanning backward, and for \r when scanning forward. *
  204. * *
  205. * HISTORY: *
  206. * 08/05/1992 JLB : Created. *
  207. *=============================================================================================*/
  208. char * WWGetPrivateProfileString(char const * section, char const * entry, char const * def, char * retbuffer, int retlen, char const * profile)
  209. {
  210. char const * workptr; // Working pointer into profile block.
  211. char * altworkptr; // Alternate work pointer.
  212. char sec[50]; // Working section buffer.
  213. char const * retval; // Start of section or entry pointer.
  214. char * next; // Pointer to start of next section (or EOF).
  215. char c,c2; // Working character values.
  216. int len; // Working substring length value.
  217. int entrylen; // Byte length of specified entry.
  218. char * orig_retbuf; // original retbuffer ptr
  219. // if (!retlen) return(NULL);
  220. /*
  221. ** Fill in the default value just in case the entry could not be found.
  222. */
  223. if (retbuffer) {
  224. retbuffer[0] = '\0';
  225. if (retlen > 1 || retlen == 0) retbuffer[1] = '\0';
  226. if (def) {
  227. strncpy(retbuffer, def, retlen);
  228. }
  229. retbuffer[retlen-1] = '\0';
  230. orig_retbuf = retbuffer;
  231. }
  232. /*
  233. ** Make sure a profile string was passed in
  234. */
  235. if (!profile || !section) {
  236. return(retbuffer);
  237. }
  238. /*
  239. ** Build section string to match file image.
  240. */
  241. sprintf(sec, "[%s]", section); // sec = section name including []'s
  242. strupr(sec);
  243. len = strlen(sec); // len = section name length, incl []'s
  244. /*
  245. ** Scan for a matching section
  246. */
  247. retval = profile;
  248. workptr = profile;
  249. for (;;) {
  250. /*
  251. ** 'workptr' = start of next section
  252. */
  253. workptr = strchr(workptr, '[');
  254. /*
  255. ** If the end has been reached without finding the desired section
  256. ** then abort with a failure flag.
  257. */
  258. if (!workptr) {
  259. return(NULL);
  260. }
  261. /*
  262. ** 'c' = character just before the '['
  263. */
  264. if (workptr==profile) {
  265. c = '\n';
  266. } else {
  267. c = *(workptr-1);
  268. }
  269. /*
  270. ** If this is the section name & the character before is a newline,
  271. ** process this section
  272. */
  273. if (memicmp(workptr, sec, len) == 0 && (c == '\n')) {
  274. /*
  275. ** Skip work pointer to start of first valid entry.
  276. */
  277. workptr += len;
  278. while (isspace(*workptr)) {
  279. workptr++;
  280. }
  281. /*
  282. ** If the section name is empty, we will have stepped onto the start
  283. ** of the next section name; inserting new entries here will leave
  284. ** a blank line between this section's name & 1st entry. So, check
  285. ** for 2 newlines in a row & step backward.
  286. */
  287. if (workptr - profile > 4) {
  288. if ( *(workptr-1)=='\n' && *(workptr-3)=='\n')
  289. workptr -= 2;
  290. }
  291. /*
  292. ** 'next = end of section or end of file.
  293. */
  294. next = strchr(workptr, '[');
  295. for (;;) {
  296. if (next) {
  297. c = *(next-1);
  298. /*
  299. ** If character before '[' is newline, this is the start of the
  300. ** next section
  301. */
  302. if (c == '\n') {
  303. if (*(next-1)=='\n' && *(next-3)=='\n') {
  304. next -= 2;
  305. }
  306. break;
  307. }
  308. /*
  309. ** This bracket was in the section; keep looking
  310. */
  311. next = strchr(next+1, '[');
  312. } else {
  313. /*
  314. ** No bracket found; set 'next' to the end of the file
  315. */
  316. next = (char*)workptr + strlen(workptr)-1;
  317. break;
  318. }
  319. }
  320. /*
  321. ** If a specific entry was specified then return with the associated
  322. ** string.
  323. */
  324. if (entry) {
  325. retval = workptr;
  326. entrylen = strlen(entry);
  327. for (;;) {
  328. /*
  329. ** Search for the 1st character of the entry
  330. */
  331. workptr = strchr(workptr, *entry);
  332. /*
  333. ** If the end of the file has been reached or we have spilled
  334. ** into the next section, then abort
  335. */
  336. if (!workptr || workptr >= next) {
  337. return(NULL);
  338. }
  339. /*
  340. ** 'c' = character before possible entry; must be a newline
  341. ** 'c2' = character after possible entry; must be '=' or space
  342. */
  343. c = *(workptr-1);
  344. c2 = *(workptr+entrylen);
  345. /*
  346. ** Entry found; extract it
  347. */
  348. if (memicmp(workptr, entry, entrylen) == 0 && (c == '\n') &&
  349. (c2 == '=' || isspace(c2))) {
  350. retval = workptr;
  351. workptr += entrylen; // skip entry name
  352. workptr = strchr(workptr, '='); // find '='
  353. /*
  354. ** 'altworkptr' = next newline; \r is used here since we're
  355. ** scanning forward!
  356. */
  357. if (workptr) {
  358. altworkptr = strchr(workptr, '\r'); // find next newline
  359. }
  360. /*
  361. ** Return if there was no '=', or if the newline is before
  362. ** the next '='
  363. */
  364. if (workptr == NULL || altworkptr < workptr) {
  365. return((char *)retval);
  366. }
  367. /*
  368. ** Skip any white space after the '=' and before the first
  369. ** valid character of the parameter.
  370. */
  371. workptr++; // Skip the '='.
  372. while (isspace(*workptr)) {
  373. /*
  374. ** Just return if there's no entry past the '='.
  375. */
  376. if (workptr >= altworkptr)
  377. return((char*)retval);
  378. workptr++; // Skip the whitespace
  379. }
  380. /*
  381. ** Copy the entry into the return buffer.
  382. */
  383. len = (int)(altworkptr - workptr);
  384. if (len > retlen-1) {
  385. len = retlen-1;
  386. }
  387. if (retbuffer) {
  388. memcpy(retbuffer, workptr, len);
  389. *(retbuffer + len) = '\0'; // Insert trailing null.
  390. strtrim(retbuffer);
  391. }
  392. return((char*)retval);
  393. }
  394. /*
  395. ** Entry was not found; go to the next one
  396. */
  397. workptr++;
  398. }
  399. } else {
  400. /*
  401. ** No entry was specified, so build a list of all entries.
  402. ** 'workptr' is at 1st entry after section name
  403. ** 'next' is next bracket, or end of file
  404. */
  405. retval = workptr;
  406. if (retbuffer) {
  407. /*
  408. ** Keep accumulating the identifier strings in the retbuffer.
  409. */
  410. while (workptr && workptr < next) {
  411. altworkptr = strchr(workptr, '='); // find '='
  412. if (altworkptr && altworkptr < next) {
  413. int length; // Length of ID string.
  414. length = (int)(altworkptr - workptr);
  415. /*
  416. ** Make sure we don't write past the end of the retbuffer;
  417. ** add '3' for the 3 NULL's at the end
  418. */
  419. if (retbuffer - orig_retbuf + length + 3 < retlen) {
  420. memcpy(retbuffer, workptr, length); // copy entry name
  421. *(retbuffer+length) = '\0'; // NULL-terminate it
  422. strtrim(retbuffer); // trim spaces
  423. retbuffer += strlen(retbuffer)+1; // next pos in dest buf
  424. } else {
  425. break;
  426. }
  427. /*
  428. ** Advance the work pointer to the start of the next line
  429. ** by skipping the end of line character.
  430. */
  431. workptr = strchr(altworkptr, '\n');
  432. if (!workptr) {
  433. break;
  434. }
  435. workptr++;
  436. } else {
  437. /*
  438. ** If no '=', break out of loop
  439. */
  440. break;
  441. }
  442. }
  443. /*
  444. ** Final trailing terminator. Make double sure the double
  445. ** trailing null is added.
  446. */
  447. *retbuffer++ = '\0';
  448. *retbuffer++ = '\0';
  449. }
  450. break;
  451. }
  452. } else {
  453. /*
  454. ** Section name not found; go to the next bracket & try again
  455. ** Advance past '[' and keep scanning.
  456. */
  457. workptr++;
  458. }
  459. }
  460. return((char*)retval);
  461. }
  462. /***********************************************************************************************
  463. * WritePrivateProfileString -- Write a string to the profile data block. *
  464. * *
  465. * INPUT: *
  466. * section section name to write to *
  467. * entry name of entry to write; if NULL, the section is deleted *
  468. * string string to write; if NULL, the entry is deleted *
  469. * profile INI buffer *
  470. * *
  471. * OUTPUT: *
  472. * true = success, false = failure *
  473. * *
  474. * WARNINGS: *
  475. * This function has to translate newlines into \r\n sequences. *
  476. * *
  477. * HISTORY: *
  478. * 10/07/1992 JLB : Created. *
  479. *=============================================================================================*/
  480. bool WWWritePrivateProfileString(char const * section, char const * entry, char const * string, char * profile)
  481. {
  482. char buffer[250]; // Working section buffer
  483. char const * offset;
  484. char const * next; // ptr to next section
  485. char c; // Working character value
  486. /*
  487. ** Just return if nothing to do.
  488. */
  489. if (!profile || !section) {
  490. return(true);
  491. }
  492. /*
  493. ** Try to find the section. WWGetPrivateProfileString with NULL entry name
  494. ** will return all entry names in the given buffer, truncated to the given
  495. ** buffer length. 'offset' will point to 1st entry in the section, NULL if
  496. ** section not found.
  497. */
  498. offset = WWGetPrivateProfileString(section, NULL, NULL, NULL, 0, profile);
  499. /*
  500. ** If the section could not be found, then add it to the end. Don't add
  501. ** anything if a removal of an entry is requested (it is obviously already
  502. ** non-existent). Make sure two newlines precede the section name.
  503. */
  504. if (!offset && entry) {
  505. sprintf(buffer, "\r\n[%s]\r\n", section);
  506. strcat(profile, buffer);
  507. }
  508. /*
  509. ** If the section is there and 'entry' is NULL, remove the entire section
  510. */
  511. if (offset && !entry) {
  512. /*
  513. ** 'next = end of section or end of file.
  514. */
  515. next = strchr(offset, '[');
  516. for (;;) {
  517. if (next) {
  518. c = *(next-1);
  519. /*
  520. ** If character before '[' is newline, this is the start of the
  521. ** next section
  522. */
  523. if (c == '\n') {
  524. if ( *(next-1)=='\n' && *(next-3)=='\n') {
  525. next -= 2;
  526. }
  527. break;
  528. }
  529. /*
  530. ** This bracket was in the section; keep looking
  531. */
  532. next = strchr(next+1, '[');
  533. } else {
  534. /*
  535. ** No bracket found; set 'next' to the end of the file
  536. */
  537. next = offset + strlen(offset);
  538. break;
  539. }
  540. }
  541. /*
  542. ** Remove the section
  543. */
  544. strcpy((char*)offset, (char*)next);
  545. return(true);
  546. }
  547. /*
  548. ** Find the matching entry within the desired section. A NULL return buffer
  549. ** with 0 length will just return the offset of the found entry, NULL if
  550. ** entry not found.
  551. */
  552. offset = WWGetPrivateProfileString(section, entry, NULL, NULL, 0, profile);
  553. /*
  554. ** Remove any existing entry
  555. */
  556. if (offset) {
  557. int eol; // Working EOL offset.
  558. /*
  559. ** Get # characters up to newline; \n is used since we're after the end
  560. ** of this line
  561. */
  562. eol = strcspn(offset, "\n");
  563. /*
  564. ** Erase the entry by strcpy'ing the entire INI file over this entry
  565. */
  566. if (eol) {
  567. strcpy((char*)offset, offset + eol + 1);
  568. }
  569. } else {
  570. /*
  571. ** Entry doesn't exist, so point 'offset' to the 1st entry position in
  572. ** the section.
  573. */
  574. offset = WWGetPrivateProfileString(section, NULL, NULL, NULL, 0, profile);
  575. }
  576. /*
  577. ** Add the desired entry.
  578. */
  579. if (entry && string) {
  580. /*
  581. ** Generate entry string.
  582. */
  583. sprintf(buffer, "%s=%s\r\n", entry, string);
  584. /*
  585. ** Make room for new entry.
  586. */
  587. memmove((char*)offset+strlen(buffer), offset, strlen(offset)+1);
  588. /*
  589. ** Copy the entry into the INI buffer.
  590. */
  591. memcpy((char*)offset, buffer, strlen(buffer));
  592. }
  593. return(true);
  594. }
  595. char * Read_Bin_Buffer( void )
  596. {
  597. return( ReadBinBuffer );
  598. }
  599. bool Read_Bin_Init( char * buffer, int length )
  600. {
  601. ReadBinBuffer = buffer;
  602. ReadBinBufferLen = length;
  603. ReadBinBufferPos = 0;
  604. ReadBinBufferMax = 0;
  605. return( true );
  606. }
  607. int Read_Bin_Length( char * buffer )
  608. {
  609. if (buffer != ReadBinBuffer) {
  610. return( -1 );
  611. } else {
  612. return( ReadBinBufferMax );
  613. }
  614. }
  615. bool Read_Bin_Num( void * num, int length, char * buffer )
  616. {
  617. char * ptr;
  618. if (buffer != ReadBinBuffer || length <= 0 || length > 4 ||
  619. (ReadBinBufferPos + length) >= ReadBinBufferLen) {
  620. return( false );
  621. } else {
  622. ptr = ReadBinBuffer + ReadBinBufferPos;
  623. memcpy( num, ptr, length );
  624. ReadBinBufferPos += length;
  625. if (ReadBinBufferPos > ReadBinBufferMax) {
  626. ReadBinBufferMax = ReadBinBufferPos;
  627. }
  628. return( true );
  629. }
  630. }
  631. int Read_Bin_Pos( char * buffer )
  632. {
  633. if (buffer != ReadBinBuffer) {
  634. return( -1 );
  635. } else {
  636. return( ReadBinBufferPos );
  637. }
  638. }
  639. int Read_Bin_PosSet( unsigned int pos, char * buffer )
  640. {
  641. if (buffer != ReadBinBuffer) {
  642. return( -1 );
  643. } else {
  644. ReadBinBufferPos = pos;
  645. return( ReadBinBufferPos );
  646. }
  647. }
  648. bool Read_Bin_String( char * string, char * buffer )
  649. {
  650. char * ptr;
  651. unsigned char length;
  652. if (buffer != ReadBinBuffer ||
  653. ReadBinBufferPos >= ReadBinBufferLen) {
  654. return( false );
  655. } else {
  656. ptr = ReadBinBuffer + ReadBinBufferPos;
  657. length = (unsigned char)*ptr++;
  658. if ( (ReadBinBufferPos + length + 2) <= ReadBinBufferLen) {
  659. memcpy( string, ptr, (unsigned int)(length + 1) );
  660. ReadBinBufferPos += (length + 2);
  661. if (ReadBinBufferPos > ReadBinBufferMax) {
  662. ReadBinBufferMax = ReadBinBufferPos;
  663. }
  664. return( true );
  665. } else {
  666. return( false );
  667. }
  668. }
  669. }
  670. char * Write_Bin_Buffer( void )
  671. {
  672. return( WriteBinBuffer );
  673. }
  674. bool Write_Bin_Init( char * buffer, int length )
  675. {
  676. WriteBinBuffer = buffer;
  677. WriteBinBufferLen = length;
  678. WriteBinBufferPos = 0;
  679. WriteBinBufferMax = 0;
  680. return( true );
  681. }
  682. int Write_Bin_Length( char * buffer )
  683. {
  684. if (buffer != WriteBinBuffer) {
  685. return( -1 );
  686. } else {
  687. return( WriteBinBufferMax );
  688. }
  689. }
  690. bool Write_Bin_Num( void * num, int length, char * buffer )
  691. {
  692. char * ptr;
  693. if (buffer != WriteBinBuffer || length <= 0 || length > 4 ||
  694. (WriteBinBufferPos + length) > WriteBinBufferLen) {
  695. return( false );
  696. } else {
  697. ptr = WriteBinBuffer + WriteBinBufferPos;
  698. memcpy( ptr, num, length );
  699. WriteBinBufferPos += length;
  700. if (WriteBinBufferPos > WriteBinBufferMax) {
  701. WriteBinBufferMax = WriteBinBufferPos;
  702. }
  703. return( true );
  704. }
  705. }
  706. int Write_Bin_Pos( char * buffer )
  707. {
  708. if (buffer != WriteBinBuffer) {
  709. return( -1 );
  710. } else {
  711. return( WriteBinBufferPos );
  712. }
  713. }
  714. int Write_Bin_PosSet( unsigned int pos, char * buffer )
  715. {
  716. if (buffer != WriteBinBuffer) {
  717. return( -1 );
  718. } else {
  719. WriteBinBufferPos = pos;
  720. return( WriteBinBufferPos );
  721. }
  722. }
  723. bool Write_Bin_String( char * string, int length, char * buffer )
  724. {
  725. char * ptr;
  726. if (buffer != WriteBinBuffer || length < 0 || length > 255 ||
  727. (WriteBinBufferPos + length + 2) > WriteBinBufferLen) {
  728. return( false );
  729. } else {
  730. ptr = WriteBinBuffer + WriteBinBufferPos;
  731. *ptr++ = (char)length;
  732. memcpy( ptr, string, (length + 1) );
  733. WriteBinBufferPos += (length + 2);
  734. if (WriteBinBufferPos > WriteBinBufferMax) {
  735. WriteBinBufferMax = WriteBinBufferPos;
  736. }
  737. return( true );
  738. }
  739. }