You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

configuration.cpp 116KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792
  1. // configuration.cpp
  2. //
  3. // Copyright (C) 2004-2020 MicroNeil Research Corporation.
  4. //
  5. // This software is released under the MIT license. See LICENSE.TXT.
  6. //
  7. // Tools for efficiently parsing XML, usually in configuration files.
  8. #include "configuration.hpp"
  9. namespace codedweller {
  10. //// Configuration Element /////////////////////////////////////////////////////
  11. ConfigurationElement::ConfigurationElement(const char* Name) : // Construct with a cstring.
  12. myName(std::string(Name)),
  13. myParent(NULL),
  14. myLine(0),
  15. myIndex(0),
  16. myLength(0),
  17. myCleanFlag(true),
  18. myInitOnInterpretFlag(false) {
  19. }
  20. ConfigurationElement::ConfigurationElement(const std::string Name) : // Construct with a c++ string.
  21. myName(Name),
  22. myParent(NULL),
  23. myLine(0),
  24. myIndex(0),
  25. myLength(0),
  26. myCleanFlag(true),
  27. myInitOnInterpretFlag(false) {
  28. }
  29. ConfigurationElement::ConfigurationElement( // Construct sub element w/ cstring.
  30. const char* Name,
  31. ConfigurationElement& Parent) :
  32. myName(std::string(Name)),
  33. myParent(&Parent),
  34. myLine(0),
  35. myIndex(0),
  36. myLength(0),
  37. myCleanFlag(true),
  38. myInitOnInterpretFlag(false) {
  39. }
  40. ConfigurationElement::ConfigurationElement( // Construct sub element w/ string.
  41. const std::string Name,
  42. ConfigurationElement& Parent) :
  43. myName(Name),
  44. myParent(&Parent),
  45. myLine(0),
  46. myIndex(0),
  47. myLength(0),
  48. myCleanFlag(true),
  49. myInitOnInterpretFlag(false) {
  50. }
  51. std::string ConfigurationElement::Name() { return myName; } // Get the name of this element.
  52. ConfigurationElement& ConfigurationElement::Parent() { // Get the parrent of this element.
  53. if(NULL != myParent) { // If I have a parent
  54. return (*myParent); // then I dereference and return it.
  55. } // If I don't have a parent
  56. return (*this); // then I return myself.
  57. }
  58. ConfigurationElement& ConfigurationElement::Parent( // Set the parrent of this element.
  59. ConfigurationElement& Parent) { // Given this parent
  60. myParent = &Parent; // I take and store it's address
  61. return (*myParent); // then dereference and return it.
  62. }
  63. int ConfigurationElement::Line() { return myLine; } // Get the last line number.
  64. int ConfigurationElement::Index() { return myIndex; } // Get the last data position.
  65. int ConfigurationElement::Length() { return myLength; } // Get the last length.
  66. void ConfigurationElement::notifyDirty() { myCleanFlag = false; } // Attributes do this when they change.
  67. ConfigurationElement& ConfigurationElement::Element(const char* Name) { // Add a new sub element by c string name.
  68. return Element(std::string(Name)); // Use the string name version
  69. }
  70. ConfigurationElement& ConfigurationElement::Element(const std::string Name) { // Add a new sub element by c++ string name.
  71. ConfigurationElement* N = new ConfigurationElement( // Create a new Element with the
  72. Name, // name provided and
  73. (*this)); // myself as the parent.
  74. myElements.push_back(N); // Add it to the list.
  75. return (*N); // Return the new element.
  76. }
  77. ConfigurationElement& ConfigurationElement::Element( // Mapping factory for convenience,
  78. const char* Name, // requires a name, of course,
  79. ConfigurationTranslator& newTranslator) { // Add a Translator to this element.
  80. return Element(std::string(Name), newTranslator); // Use the string name version
  81. }
  82. ConfigurationElement& ConfigurationElement::Element( // Mapping factory for convenience,
  83. const char* Name, // requires a name, of course,
  84. std::string& x, std::string init) { // Map to a string.
  85. return Element(std::string(Name), x, init); // Use the string name version
  86. }
  87. ConfigurationElement& ConfigurationElement::Element( // Mapping factory for convenience,
  88. const char* Name, // requires a name, of course,
  89. int& x, int init, int radix) { // Map to an int.
  90. return Element(std::string(Name), x, init, radix); // Use the string name version
  91. }
  92. ConfigurationElement& ConfigurationElement::Element( // Mapping factory for convenience,
  93. const char* Name, // requires a name, of course,
  94. double& x, double init) { // Map to a double.
  95. return Element(std::string(Name), x, init); // Use the string name version
  96. }
  97. ConfigurationElement& ConfigurationElement::Element( // Mapping factory for convenience,
  98. const char* Name, // requires a name, of course,
  99. bool& x, bool init) { // Map to a boolean.
  100. return Element(std::string(Name), x, init); // Use the string name version
  101. }
  102. ConfigurationElement& ConfigurationElement::End() { // Return this element's parent.
  103. return Parent(); // Borrow Parent()
  104. }
  105. ConfigurationElement& ConfigurationElement::End(const char* Name) { // Check the name and return the parent
  106. return End(std::string(Name)); // Borrow End(string)
  107. }
  108. ConfigurationElement& ConfigurationElement::End(const std::string Name) { // if the name is correct - or throw!
  109. if(0 != Name.compare(myName)) { // If Name is not myName
  110. throw EndNameDoesNotMatch(); // throw an exception!
  111. } // If the names match then
  112. return Parent(); // return the parent.
  113. }
  114. ConfigurationAttribute& ConfigurationElement::Attribute( // Add an attribute using a cstring.
  115. const char* Name) { // Given this cstring name
  116. return Attribute(std::string(Name)); // Convert it to a string and borrow
  117. } // Attribute(string)
  118. ConfigurationAttribute& ConfigurationElement::Attribute( // Mapping factory for convenience,
  119. const char* Name, // requires a name, of course,
  120. ConfigurationTranslator& newTranslator) { // Add a Translator to this element.
  121. return Attribute(std::string(Name), newTranslator); // Borrow the string name version
  122. }
  123. ConfigurationAttribute& ConfigurationElement::Attribute( // Mapping factory for convenience,
  124. const char* Name, // requires a name, of course,
  125. std::string& x, std::string init) { // Map to a string.
  126. return Attribute(std::string(Name), x, init); // Borrow the string name version
  127. }
  128. ConfigurationAttribute& ConfigurationElement::Attribute( // Mapping factory for convenience,
  129. const char* Name, // requires a name, of course,
  130. int& x, int init, int radix) { // Map to an int.
  131. return Attribute(std::string(Name), x, init); // Borrow the string name version
  132. }
  133. ConfigurationAttribute& ConfigurationElement::Attribute( // Mapping factory for convenience,
  134. const char* Name, // requires a name, of course,
  135. double& x, double init) { // Map to a double.
  136. return Attribute(std::string(Name), x, init); // Borrow the string name version
  137. }
  138. ConfigurationAttribute& ConfigurationElement::Attribute( // Mapping factory for convenience,
  139. const char* Name, // requires a name, of course,
  140. bool& x, bool init) { // Map to a boolean.
  141. return Attribute(std::string(Name), x, init); // Borrow the string name version
  142. }
  143. ConfigurationElement& ConfigurationElement::setInitOnInterpret() { // Set the init on interpret flag.
  144. myInitOnInterpretFlag = true; // Set the flag.
  145. return(*this); // Dereference and return self.
  146. }
  147. ConfigurationElement& ConfigurationElement::atStartCall( // Add an atStart call-back.
  148. Configurator& Functor) { // Given this Functor,
  149. myStartConfigurators.push_back(&Functor); // add it to my atStart list then
  150. return(*this); // dereference and return myself.
  151. }
  152. ConfigurationElement& ConfigurationElement::atEndCall( // Add an atEnd call-back.
  153. Configurator& Functor) { // Given this Functor,
  154. myEndConfigurators.push_back(&Functor); // add it to my atEnd list then
  155. return(*this); // dereference and return myself.
  156. }
  157. ConfigurationElement& ConfigurationElement::Mnemonic( // Add a mnemonic using c strings.
  158. const char* name, const char* value) { // Given char* and char*
  159. return Mnemonic(std::string(name), std::string(value)); // make strings and borrow that method.
  160. }
  161. ConfigurationElement& ConfigurationElement::Mnemonic( // Add a mnemonic using mixed strings.
  162. const char* name, const std::string value) { // Given char* and string
  163. return Mnemonic(std::string(name), value); // make strings and borrow that method.
  164. }
  165. ConfigurationElement& ConfigurationElement::Mnemonic( // Add a mnemonic using mixed strings.
  166. const std::string name, const char* value) { // Given string and char*
  167. return Mnemonic(name, std::string(value)); // make strings and borrow that method.
  168. }
  169. ConfigurationElement& ConfigurationElement::Mnemonic( // Add a mnemonic using c++ strings.
  170. const std::string name, const std::string value) { // Givent string and string
  171. ConfigurationMnemonic* N = // Create a new Mnemonic
  172. new ConfigurationMnemonic(name, value); // using the values provided,
  173. myMnemonics.push_back(N); // add it to my list, then
  174. return(*this); // dereference and return myself.
  175. }
  176. //// Configuration Attribute ///////////////////////////////////////////////////
  177. ConfigurationAttribute::ConfigurationAttribute( // Attributes are constructed with a
  178. const char* Name, ConfigurationElement& Parent) : // Name and a Parent.
  179. myName(std::string(Name)), // We convert the name to a string.
  180. myParent(Parent), // We just grab the parent.
  181. myLine(0), // Everything else gets zeroed.
  182. myIndex(0),
  183. myLength(0) {
  184. }
  185. ConfigurationAttribute::ConfigurationAttribute( // Attributes are constrictued with a
  186. const std::string Name, ConfigurationElement& Parent) : // Name and a Parent.
  187. myName(Name), // We grab them and zero the rest.
  188. myParent(Parent),
  189. myLine(0),
  190. myIndex(0),
  191. myLength(0) {
  192. }
  193. std::string ConfigurationAttribute::Name() { // Get the name of this attribute.
  194. return myName;
  195. }
  196. ConfigurationElement& ConfigurationAttribute::Parent() { // Get the parent of this attribute.
  197. return myParent;
  198. }
  199. int ConfigurationAttribute::Line() { // Get the last line number.
  200. return myLine;
  201. }
  202. int ConfigurationAttribute::Index() { // Get the last data position.
  203. return myIndex;
  204. }
  205. int ConfigurationAttribute::Length() { // Get the last length.
  206. return myLength;
  207. }
  208. ConfigurationElement& ConfigurationAttribute::Element( // Add a new sub element by c string name.
  209. const char* Name) {
  210. return myParent.Element(Name);
  211. }
  212. ConfigurationElement& ConfigurationAttribute::Element( // Add a new sub element by c++ string name.
  213. const std::string Name) {
  214. return myParent.Element(Name);
  215. }
  216. ConfigurationElement& ConfigurationAttribute::Element( // Mapping factory for convenience,
  217. const char* Name, // requires a name, of course,
  218. ConfigurationTranslator& newTranslator) { // Add a Translator to this element.
  219. return myParent.Element(Name, newTranslator);
  220. }
  221. ConfigurationElement& ConfigurationAttribute::Element( // Mapping factory for convenience,
  222. const char* Name, // requires a name, of course,
  223. std::string& x, std::string init) { // Map to a string.
  224. return myParent.Element(Name, x, init);
  225. }
  226. ConfigurationElement& ConfigurationAttribute::Element( // Mapping factory for convenience,
  227. const char* Name, // requires a name, of course,
  228. int& x, int init, int radix) { // Map to an int.
  229. return myParent.Element(Name, x, init, radix);
  230. }
  231. ConfigurationElement& ConfigurationAttribute::Element( // Mapping factory for convenience,
  232. const char* Name, // requires a name, of course,
  233. double& x, double init) { // Map to a double.
  234. return myParent.Element(Name, x, init);
  235. }
  236. ConfigurationElement& ConfigurationAttribute::Element( // Mapping factory for convenience,
  237. const char* Name, // requires a name, of course,
  238. bool& x, bool init) { // Map to a boolean.
  239. return myParent.Element(Name, x, init);
  240. }
  241. ConfigurationElement& ConfigurationAttribute::Element( // Mapping factory for convenience,
  242. const std::string Name, // requires a name, of course,
  243. ConfigurationTranslator& newTranslator) { // Add a Translator to this element.
  244. return myParent.Element(Name, newTranslator);
  245. }
  246. ConfigurationElement& ConfigurationAttribute::Element( // Mapping factory for convenience,
  247. const std::string Name, // requires a name, of course,
  248. std::string& x, std::string init) { // Map to a string.
  249. return myParent.Element(Name, x, init);
  250. }
  251. ConfigurationElement& ConfigurationAttribute::Element( // Mapping factory for convenience,
  252. const std::string Name, // requires a name, of course,
  253. int& x, int init, int radix) { // Map to an int.
  254. return myParent.Element(Name, x, init, radix);
  255. }
  256. ConfigurationElement& ConfigurationAttribute::Element( // Mapping factory for convenience,
  257. const std::string Name, // requires a name, of course,
  258. double& x, double init) { // Map to a double.
  259. return myParent.Element(Name, x, init);
  260. }
  261. ConfigurationElement& ConfigurationAttribute::Element( // Mapping factory for convenience,
  262. const std::string Name, // requires a name, of course,
  263. bool& x, bool init) { // Map to a boolean.
  264. return myParent.Element(Name, x, init);
  265. }
  266. ConfigurationElement& ConfigurationAttribute::End() { // Return this element's parent.
  267. return myParent.End();
  268. }
  269. ConfigurationElement& ConfigurationAttribute::End(const char* Name) { // Check the name and return the parent
  270. return myParent.End(Name);
  271. }
  272. ConfigurationElement& ConfigurationAttribute::End(const std::string Name) { // if the name is correct - or throw!
  273. return myParent.End(Name);
  274. }
  275. ConfigurationAttribute& ConfigurationAttribute::Attribute( // Add an attribute using a cstring.
  276. const char* Name) {
  277. return myParent.Attribute(Name);
  278. }
  279. ConfigurationAttribute& ConfigurationAttribute::Attribute( // Add an attribute using a c++ string.
  280. const std::string Name) {
  281. return myParent.Attribute(Name);
  282. }
  283. ConfigurationAttribute& ConfigurationAttribute::Attribute( // Mapping factory for convenience,
  284. const char* Name, // requires a name, of course,
  285. ConfigurationTranslator& newTranslator) { // Add a Translator to this element.
  286. return myParent.Attribute(Name, newTranslator);
  287. }
  288. ConfigurationAttribute& ConfigurationAttribute::Attribute( // Mapping factory for convenience,
  289. const char* Name, // requires a name, of course,
  290. std::string& x, std::string init) { // Map to a string.
  291. return myParent.Attribute(Name, x, init);
  292. }
  293. ConfigurationAttribute& ConfigurationAttribute::Attribute( // Mapping factory for convenience,
  294. const char* Name, // requires a name, of course,
  295. int& x, int init, int radix) { // Map to an int.
  296. return myParent.Attribute(Name, x, init, radix);
  297. }
  298. ConfigurationAttribute& ConfigurationAttribute::Attribute( // Mapping factory for convenience,
  299. const char* Name, // requires a name, of course,
  300. double& x, double init) { // Map to a double.
  301. return myParent.Attribute(Name, x, init);
  302. }
  303. ConfigurationAttribute& ConfigurationAttribute::Attribute( // Mapping factory for convenience,
  304. const char* Name, // requires a name, of course,
  305. bool& x, bool init) { // Map to a boolean.
  306. return myParent.Attribute(Name, x, init);
  307. }
  308. ConfigurationAttribute& ConfigurationAttribute::Attribute( // Mapping factory for convenience,
  309. const std::string Name, // requires a name, of course,
  310. ConfigurationTranslator& newTranslator) { // Add a Translator to this element.
  311. return myParent.Attribute(Name, newTranslator);
  312. }
  313. ConfigurationAttribute& ConfigurationAttribute::Attribute( // Mapping factory for convenience,
  314. const std::string Name, // requires a name, of course,
  315. std::string& x, std::string init) { // Map to a string.
  316. return myParent.Attribute(Name, x, init);
  317. }
  318. ConfigurationAttribute& ConfigurationAttribute::Attribute( // Mapping factory for convenience,
  319. const std::string Name, // requires a name, of course,
  320. int& x, int init, int radix) { // Map to an int.
  321. return myParent.Attribute(Name, x, init, radix);
  322. }
  323. ConfigurationAttribute& ConfigurationAttribute::Attribute( // Mapping factory for convenience,
  324. const std::string Name, // requires a name, of course,
  325. double& x, double init) { // Map to a double.
  326. return myParent.Attribute(Name, x, init);
  327. }
  328. ConfigurationAttribute& ConfigurationAttribute::Attribute( // Mapping factory for convenience,
  329. const std::string Name, // requires a name, of course,
  330. bool& x, bool init) { // Map to a boolean.
  331. return myParent.Attribute(Name, x, init);
  332. }
  333. ConfigurationElement& ConfigurationAttribute::setInitOnInterpret() { // Set the init on interpret flag.
  334. return myParent.setInitOnInterpret();
  335. }
  336. ConfigurationElement& ConfigurationAttribute::atStartCall( // Add an atStart call-back to this element.
  337. Configurator& Functor) {
  338. return myParent.atStartCall(Functor);
  339. }
  340. ConfigurationElement& ConfigurationAttribute::atEndCall( // Add an atEnd call-back to this element.
  341. Configurator& Functor) {
  342. return myParent.atEndCall(Functor);
  343. }
  344. ConfigurationAttribute& ConfigurationAttribute::Mnemonic( // Add a mnemonic using c strings.
  345. const char* name, const char* value) { // Given char* and char*
  346. return Mnemonic(std::string(name), std::string(value)); // make strings and borrow that method.
  347. }
  348. ConfigurationAttribute& ConfigurationAttribute::Mnemonic( // Add a mnemonic using mixed strings.
  349. const char* name, const std::string value) { // Given char* and string
  350. return Mnemonic(std::string(name), value); // make strings and borrow that method.
  351. }
  352. ConfigurationAttribute& ConfigurationAttribute::Mnemonic( // Add a mnemonic using mixed strings.
  353. const std::string name, const char* value) { // Given string and char*
  354. return Mnemonic(name, std::string(value)); // make strings and borrow that method.
  355. }
  356. ConfigurationAttribute& ConfigurationAttribute::Mnemonic( // Add a mnemonic using c++ strings.
  357. const std::string name, const std::string value) { // Givent string and string
  358. ConfigurationMnemonic* N = // Create a new Mnemonic
  359. new ConfigurationMnemonic(name, value); // using the values provided,
  360. myMnemonics.push_back(N); // add it to my list, then
  361. return(*this); // dereference and return myself.
  362. }
  363. //// Configuration Data ////////////////////////////////////////////////////////
  364. char ConfigurationData::Data(int Index) { // Returns char from Data[Index]
  365. if(0 > Index || Index >= myBufferSize) { // Check that index is in range
  366. return 0; // and return 0 if it is not.
  367. } // If Index is within range then
  368. return myDataBuffer[Index]; // return the byte requested.
  369. }
  370. int ConfigurationData::Index() { // Reads the current Index.
  371. return myIndex;
  372. }
  373. int ConfigurationData::Index(int i) { // Changes the current Index.
  374. if(0 > i || i >= myBufferSize) { // If i is out of range then
  375. return myIndex; // return the current Index unchanged.
  376. } // If i is within range then
  377. myIndex = i; // change the Index to i and
  378. return myIndex; // return the changed Index.
  379. }
  380. int ConfigurationData::Line() { // Reads the current Line number.
  381. return myLine;
  382. }
  383. int ConfigurationData::addNewLines(int Count) { // Increments the Line number.
  384. myLine += Count; // Add the number of new lines.
  385. return myLine; // Return the current Line number.
  386. }
  387. //// Configuration Translator //////////////////////////////////////////////////
  388. StringTranslator::StringTranslator( // Construct this with
  389. std::string& Variable, // the variable to map,
  390. std::string Initializer) : // and the default value.
  391. myVariable(Variable),
  392. myInitializer(Initializer) {
  393. }
  394. void StringTranslator::translate(const char* Value) { // Provide a translation method.
  395. myVariable = std::string(Value); // String to String = simple copy.
  396. }
  397. void StringTranslator::initialize() { // Provide an initialization method.
  398. myVariable = myInitializer; // Revert to the initializer value.
  399. }
  400. IntegerTranslator::IntegerTranslator( // Construct this with
  401. int& Variable, // the variable to map,
  402. int Initializer, // and the default value.
  403. int Radix) : // For this one we also need a Radix.
  404. myVariable(Variable),
  405. myInitializer(Initializer),
  406. myRadix(Radix) {
  407. }
  408. void IntegerTranslator::translate(const char* Value) { // Provide a translation method.
  409. char* dummy; // Throw away ptr for strtol().
  410. myVariable = strtol(Value, &dummy, myRadix); // Convert the string w/ strtol().
  411. }
  412. void IntegerTranslator::initialize() { // Provide an initialization method.
  413. myVariable = myInitializer; // Revert to the initializer value.
  414. }
  415. DoubleTranslator::DoubleTranslator( // Construct this with
  416. double& Variable, // the variable to map,
  417. double Initializer) : // and the default value.
  418. myVariable(Variable),
  419. myInitializer(Initializer) {
  420. }
  421. void DoubleTranslator::translate(const char* Value) { // Provide a translation method.
  422. char* dummy; // Throw away ptr for strtod().
  423. myVariable = strtod(Value, &dummy); // Convert the string w/ strtod().
  424. }
  425. void DoubleTranslator::initialize() { // Provide an initialization method.
  426. myVariable = myInitializer; // Revert to the initializer value.
  427. }
  428. BoolTranslator::BoolTranslator( // Construct this with
  429. bool& Variable, // the variable to map,
  430. bool Initializer) : // and the default value.
  431. myVariable(Variable),
  432. myInitializer(Initializer) {
  433. }
  434. void BoolTranslator::translate(const char* Value) { // Provide a translation method.
  435. if(
  436. (0 == strcmp(Value,"on")) ||
  437. (0 == strcmp(Value,"true")) || // on, true, yes, and 1 are
  438. (0 == strcmp(Value, "yes")) || // interpreted as a boolean true.
  439. (0 == strcmp(Value, "1"))
  440. ) {
  441. myVariable = true;
  442. } else { // Anything else is interpreted as
  443. myVariable = false; // boolean false.
  444. }
  445. }
  446. void BoolTranslator::initialize() { // Provide an initialization method.
  447. myVariable = myInitializer; // Revert to the initializer value.
  448. }
  449. //// Configuration Mnemonic ////////////////////////////////////////////////////
  450. ConfigurationMnemonic::ConfigurationMnemonic( // To make one, provide both parts.
  451. std::string Name, std::string Value) :
  452. myName(Name),
  453. myValue(Value) {
  454. }
  455. bool ConfigurationMnemonic::test(std::string Name) { // Test to see if this Mnemonic matches.
  456. return (0 == Name.compare(myName)); // Return true if Name and myName match.
  457. }
  458. std::string ConfigurationMnemonic::Value() { // If it does then we will need it's value.
  459. return myValue;
  460. }
  461. //// Helper functions //////////////////////////////////////////////////////////
  462. // isNameChar(const char x)
  463. // true if the character can be used in a name.
  464. bool isNameChar(const char x) {
  465. return (
  466. isalnum(x) ||
  467. ('.' == x) ||
  468. ('-' == x) ||
  469. ('_' == x) ||
  470. (':' == x)
  471. );
  472. }
  473. // Eat Spaces and Count Lines
  474. // While we're parsing the configuration file there are times we will need to
  475. // skip some amount of whitespace. While doing that we need to keep track of
  476. // any new-lines we cross so that we always know what line number we are on.
  477. // This function makes that work a one-liner in our parsing routines.
  478. int eatSpacesCountLines(ConfigurationData& Data, int& Index) { // Eat spaces and count lines.
  479. int LineCount = 0; // Keep the line count here.
  480. char C = 0; // Keep the current character here.
  481. for(;;) { // We'll be looping like this...
  482. C = Data.Data(Index); // Grab the character at the Index.
  483. if(0 == C) { // If we have run out of data
  484. break; // then we are certainly done.
  485. }
  486. if(isspace(C)) { // If it is a whitespace
  487. if('\n' == C) { // check to see if it's a new line
  488. ++LineCount; // and count it if it is.
  489. } // Since it was a space in any case
  490. ++Index; // move the index past it.
  491. } else { // As soon as we hit something not
  492. break; // a whitespace we are done looping.
  493. }
  494. }
  495. return LineCount; // In the end return the line count.
  496. }
  497. // Eat NonTagText Count Lines
  498. // This is a variation on the Eat Spaces theme except that it is used in an
  499. // element to bypass any floating text or spaces that might be in the file. In
  500. // a perfect world such a thing would not exist -- but just in case it does we
  501. // want to handle it gracefully. This function will get us to the first < that
  502. // we can find - presumably the opening tag of an element.
  503. int eatNonTagTextCountLines(ConfigurationData& Data, int& Index) { // Eat "stuff" and count lines.
  504. int LineCount = 0; // Keep the line count here.
  505. char C = 0; // Keep the current character here.
  506. for(;;) { // We'll be looping like this...
  507. C = Data.Data(Index); // Grab the character at the Index.
  508. if(0 == C) { // If we have run out of data
  509. break; // then we are certainly done.
  510. }
  511. if('\n' == C) { // check to see if it's a new line
  512. ++LineCount; // and count it if it is.
  513. } else
  514. if('<' == C) { // When we find our < we're done!
  515. break;
  516. } // If C wasn't what we're after
  517. ++Index; // move the index past this byte.
  518. }
  519. return LineCount; // In the end return the line count.
  520. }
  521. // Eat Comments Count Lines
  522. // This is another variant of Eat Spaces. In this if we are on a <!-- tag
  523. // opening, then we will eat the rest of it through -->
  524. int eatCommentsCountLines(ConfigurationData& Data, int& Index) { // Eat any <!-- -->
  525. int LineCount = 0; // Keep the line count here.
  526. char C = 0; // Keep the current character here.
  527. // First - are we on a comment?
  528. if( // If the text at Index doesn't
  529. Data.Data(Index) != '<' || // look like the start of a
  530. Data.Data(Index + 1) != '!' || // comment then we are done.
  531. Data.Data(Index + 2) != '-' ||
  532. Data.Data(Index + 3) != '-'
  533. ) {
  534. return 0; // Return after no changes.
  535. }
  536. // Since we are on a comment, let's eat
  537. Index += 4; // Move past the comment start.
  538. for(;;) { // We'll be looping like this...
  539. C = Data.Data(Index); // Grab the character at the Index.
  540. if(0 == C) { // If we have run out of data
  541. break; // then we are certainly done.
  542. }
  543. if('\n' == C) { // check to see if it's a new line
  544. ++LineCount; // and count it if it is.
  545. } else
  546. if('-' == C) { // When we find a - we check for -->
  547. if(
  548. '-' == Data.Data(Index + 1) && // If we have found the end of our
  549. '>' == Data.Data(Index + 2) // comment then we are ready to
  550. ) { // stop.
  551. Index += 3; // Move the Index past the end
  552. break; // and break out of the loop.
  553. }
  554. } // If C wasn't what we're after
  555. ++Index; // move the index past this byte.
  556. }
  557. return LineCount; // In the end return the line count.
  558. }
  559. // Eat DocSpecs Count Lines
  560. // Another variation of Eat Spaces - this time to eat <? doc specs ?>
  561. int eatDocSpecsCountLines(ConfigurationData& Data, int& Index) { // Eat any <? ?>
  562. int LineCount = 0; // Keep the line count here.
  563. char C = 0; // Keep the current character here.
  564. // First - are we on a doc spec?
  565. if( // If the text at Index doesn't
  566. Data.Data(Index) != '<' || // look like the start of a
  567. Data.Data(Index + 1) != '?' // doc spec then we are done.
  568. ) {
  569. return 0; // Return after no changes.
  570. }
  571. // Since we are on a doc spec, let's eat
  572. for(;;) { // We'll be looping like this...
  573. C = Data.Data(Index); // Grab the character at the Index.
  574. if(0 == C) { // If we have run out of data
  575. break; // then we are certainly done.
  576. }
  577. if('\n' == C) { // check to see if it's a new line
  578. ++LineCount; // and count it if it is.
  579. } else
  580. if('?' == C) { // When we find a - we check for ?>
  581. if('>' == Data.Data(Index + 1)) { // If we foudn the end we're done!
  582. Index += 2; // Move the Index past the end
  583. break; // and break out of the loop.
  584. }
  585. } // If C wasn't what we're after
  586. ++Index; // move the index past this byte.
  587. }
  588. return LineCount; // In the end return the line count.
  589. }
  590. // Eat Attribute Count Lines
  591. // Another variation of Eat Spaces - this time to eat unknown attributes.
  592. int eatAttributeCountLines(ConfigurationData& Data, int& Index) { // Eat Attribute ( name='data' )
  593. int LineCount = 0; // Keep the line count here.
  594. char C = 0; // Keep the current character here.
  595. while(isNameChar(Data.Data(Index))) ++Index; // Eat through the name.
  596. LineCount += eatSpacesCountLines(Data, Index); // Eat any spaces.
  597. if('=' != Data.Data(Index)) { // We should have found our = sign.
  598. return LineCount; // If we did NOT then we're done.
  599. } else { // If we did, then we're still
  600. ++Index; // going - so move past it.
  601. }
  602. LineCount += eatSpacesCountLines(Data, Index); // Eat any extra spaces.
  603. C = Data.Data(Index); // Grab the next byte.
  604. if( // It should be either a
  605. '\'' != Data.Data(Index) && // single quote or a
  606. '\"' != Data.Data(Index) // double quote.
  607. ) { // If it is neither of these
  608. return LineCount; // then we are done.
  609. } else { // If it was a quote then
  610. ++Index; // get ready to go.
  611. }
  612. while(Data.Data(Index) != C) { // Carefully eat the data.
  613. if(0 == Data.Data(Index)) { // If we run out of Data
  614. return LineCount; // we are done.
  615. } else
  616. if('\n' == Data.Data(Index)) { // If we find a newline then
  617. ++LineCount; // we count it.
  618. }
  619. ++Index; // Whatever it is move past it.
  620. } // Once we've found our ending
  621. ++Index; // quote, we move past it and
  622. return LineCount; // return our Line count.
  623. }
  624. // Eat DocSpecs Count Lines
  625. // Another variation of Eat Spaces - this time to eat unknown elements.
  626. int eatElementCountLines(ConfigurationData& Data, int& Index) { // Eat Element ( <name>..</name> )
  627. int LineCount = 0; // Keep the line count here.
  628. // Are we on a tag?
  629. if( // If we are on an element tag then
  630. '<' != Data.Data(Index) || // it will start with a < followed by
  631. false == isNameChar(Data.Data(Index + 1)) // a name char (usually alpha).
  632. ) { // If that is not the case then
  633. return 0; // we are already done.
  634. }
  635. // Capture the tag name position.
  636. ++Index; // Move the Index to the start of the
  637. int NameIndex = Index; // name and record that spot.
  638. while(isNameChar(Data.Data(Index))) ++Index; // Move the Index past the name.
  639. int NameEndex = Index; // Record the end position.
  640. // Scan for the end of this tag.
  641. for(;;) { // We're looking for a > character.
  642. if(0 == Data.Data(Index)) { // If we run out of data
  643. return LineCount; // we are done.
  644. }
  645. LineCount += eatSpacesCountLines(Data, Index); // Eat any spaces.
  646. if( // Check for an empty element tag.
  647. '/' == Data.Data(Index) && // It will look like a /
  648. '>' == Data.Data(Index + 1) // followed by a >
  649. ) { // If this is an empty element
  650. Index += 2; // Move past it and return our
  651. return LineCount; // Line Count... consider it
  652. } // eaten.
  653. if('>' == Data.Data(Index)) { // If we come to an ordinary end
  654. ++Index; // of element start tag then move
  655. break; // past it and break out for the
  656. } // next phase.
  657. ++Index; // Just move past anything else.
  658. }
  659. // At this point we've passed the start tag for this element and
  660. // we know it's name. We also know the element is not empty so we'll
  661. // need to go inside it, eat those things, and look for it's end
  662. // tag.
  663. // Scan for the matching end tag and eat children.
  664. while( // Keep going until we get to
  665. '<' != Data.Data(Index) || // an end tag (starts with < followed
  666. '/' != Data.Data(Index + 1) // by a /). If we get to something that
  667. ) { // isn't a tag we're done anyway.
  668. int CheckIndex = Index; // Keep track of where we start.
  669. LineCount += eatNonTagTextCountLines(Data, Index); // Eat up to the next < we encounter.
  670. LineCount += eatElementCountLines(Data, Index); // Eat any elements we encounter.
  671. LineCount += eatCommentsCountLines(Data, Index); // Eat any comments we encounter.
  672. LineCount += eatDocSpecsCountLines(Data, Index); // Eat any doc specs we encounter.
  673. // If we stop moving break out!
  674. if(CheckIndex == Index) { // If we didn't move at all then
  675. break; // we need to break out. Could be
  676. } // out of data or just confused.
  677. };
  678. if( // If we find we are not even on
  679. '<' != Data.Data(Index) || // an end tag then we'll just quit
  680. '/' != Data.Data(Index + 1) // right now.
  681. ) {
  682. return LineCount; // Even so we return our line count.
  683. }
  684. // If we find an end tag - it had better be the one we want.
  685. // If it is not then we'll return with the index pointing at the
  686. // offending end tag so that parent instances will have a shot at it
  687. // and/or discover the problem.
  688. int t = 0; // t is for terminus, it stays in scope.
  689. for(t = 0; (NameIndex + t) < NameEndex; t++) { // Scan over the name and make sure
  690. if(Data.Data(NameIndex + t) != Data.Data(Index + 2 + t)) { // it matches character by character.
  691. return LineCount; // If any don't match, the end tag is
  692. } // wron so we return w/ Index pointing
  693. } // at the bad end tag.
  694. if('>' == Data.Data(Index + 2 + t)) { // If the name matched and the next
  695. Index += (3 + t); // character is our > then we move the
  696. } // Index past it - all is good.
  697. // If not then we leave the index.
  698. return LineCount; // Either way we return the Line Count.
  699. }
  700. // Copy Data and Count Lines
  701. // At some point in the parsing, we need to extract content from our Data
  702. // stream and convert it into a null terminated c string. While we're at it
  703. // we also need to keep track of any new-line characters we cross so we will
  704. // still know what line we're on. This function makes that task a one-liner.
  705. int copyDataCountLines(char* Bfr, ConfigurationData& Data, int Start, int End) {
  706. int Lines = 0; // Keep track of the lines we cross.
  707. int DataIndex = Start; // The Data index is separate from
  708. int BfrIndex = 0; // our Bfr index.
  709. char C = 0; // We will be looking at each character.
  710. while(DataIndex < End) { // While there's more segment to do...
  711. C = Data.Data(DataIndex); // Grab each byte.
  712. Bfr[BfrIndex] = C; // Copy it to our buffer.
  713. if('\n' == C) { // Check to see if it's a new-line
  714. ++Lines; // and count it if it is.
  715. }
  716. ++BfrIndex; // Move our buffer and our
  717. ++DataIndex; // data index pointers and
  718. } // keep on going.
  719. Bfr[BfrIndex] = 0; // At the end, null terminate.
  720. return Lines; // Return our line count.
  721. }
  722. //// Configuration Element /////////////////////////////////////////////////////
  723. ConfigurationElement::~ConfigurationElement() { // The descrutor clears and deletes all!
  724. // A configuration Element is "in charge of" or "owns" all of it's
  725. // down-stream components. So, when it is destroyed, it is responsible
  726. // for destroying all of those parts to prevent memory leaks.
  727. // Delete my attributes
  728. if(0 < myAttributes.size()) { // If we have attributes...
  729. std::list<ConfigurationAttribute*>::iterator iAttribute; // Iterate through our attributes list.
  730. iAttribute = myAttributes.begin(); // Start at the beginning and
  731. while(iAttribute != myAttributes.end()) { // loop through the whole list.
  732. delete (*iAttribute); // Delete each attribute
  733. iAttribute++; // then move the iterator.
  734. } // When we're done deleting them
  735. myAttributes.clear(); // clear the list.
  736. }
  737. // Delete my sub-elements
  738. if(0 < myElements.size()) { // If we have elements...
  739. std::list<ConfigurationElement*>::iterator iElement; // Iterate through our elements list.
  740. iElement = myElements.begin(); // Start at the beginning and
  741. while(iElement != myElements.end()) { // loop through the whole list.
  742. delete (*iElement); // Delete each element
  743. iElement++; // then move the iterator.
  744. } // When we're done deleting them
  745. myElements.clear(); // clear the list.
  746. }
  747. // Delete my mnemonics
  748. if(0 < myMnemonics.size()) { // If we have mnemonics...
  749. std::list<ConfigurationMnemonic*>::iterator iMnemonic; // Iterate through our mnemonics list.
  750. iMnemonic = myMnemonics.begin(); // Start at the beginning and
  751. while(iMnemonic != myMnemonics.end()) { // loop through the whole list.
  752. delete (*iMnemonic); // Delete each mnemonic
  753. iMnemonic++; // then move the iterator.
  754. } // When we're done deleting them
  755. myMnemonics.clear(); // clear the list.
  756. }
  757. // Delete my translators
  758. if(0 < myTranslators.size()) { // If we have translators...
  759. std::list<ConfigurationTranslator*>::iterator iTranslator; // Iterate through our translators list.
  760. iTranslator = myTranslators.begin(); // Start at the beginning and
  761. while(iTranslator != myTranslators.end()) { // loop through the whole list.
  762. delete (*iTranslator); // Delete each translator
  763. iTranslator++; // then move the iterator.
  764. } // When we're done deleting them
  765. myTranslators.clear(); // clear the list.
  766. }
  767. // zero things out
  768. myLine = 0; // If I'm going away then I will leave
  769. myIndex = 0; // with everything at zero and clean.
  770. myLength = 0;
  771. myCleanFlag = true;
  772. }
  773. ConfigurationElement& ConfigurationElement::Element( // Mapping factory for convenience,
  774. const std::string Name, // requires a name, of course,
  775. ConfigurationTranslator& newTranslator) { // Add a Translator to this element.
  776. ConfigurationElement* N = new ConfigurationElement( // Create a new Element with the
  777. Name, // name provided and
  778. (*this)); // myself as the parent.
  779. myElements.push_back(N); // Add it to the list.
  780. N->mapTo(newTranslator); // Map the translator to it.
  781. return (*N); // Return the new element.
  782. }
  783. ConfigurationElement& ConfigurationElement::Element( // Mapping factory for convenience,
  784. const std::string Name, // requires a name, of course,
  785. std::string& x, std::string init) { // Map to a string.
  786. ConfigurationElement* N = new ConfigurationElement( // Create a new Element with the
  787. Name, // name provided and
  788. (*this)); // myself as the parent.
  789. myElements.push_back(N); // Add it to the list.
  790. N->mapTo(x, init); // Map the variable into it.
  791. return (*N); // Return the new element.
  792. }
  793. ConfigurationElement& ConfigurationElement::Element( // Mapping factory for convenience,
  794. const std::string Name, // requires a name, of course,
  795. int& x, int init, int radix) { // Map to an int.
  796. ConfigurationElement* N = new ConfigurationElement( // Create a new Element with the
  797. Name, // name provided and
  798. (*this)); // myself as the parent.
  799. myElements.push_back(N); // Add it to the list.
  800. N->mapTo(x, init, radix); // Map the variable into it.
  801. return (*N); // Return the new element.
  802. }
  803. ConfigurationElement& ConfigurationElement::Element( // Mapping factory for convenience,
  804. const std::string Name, // requires a name, of course,
  805. double& x, double init) { // Map to a double.
  806. ConfigurationElement* N = new ConfigurationElement( // Create a new Element with the
  807. Name, // name provided and
  808. (*this)); // myself as the parent.
  809. myElements.push_back(N); // Add it to the list.
  810. N->mapTo(x, init); // Map the variable into it.
  811. return (*N); // Return the new element.
  812. }
  813. ConfigurationElement& ConfigurationElement::Element( // Mapping factory for convenience,
  814. const std::string Name, // requires a name, of course,
  815. bool& x, bool init) { // Map to a boolean.
  816. ConfigurationElement* N = new ConfigurationElement( // Create a new Element with the
  817. Name, // name provided and
  818. (*this)); // myself as the parent.
  819. myElements.push_back(N); // Add it to the list.
  820. N->mapTo(x, init); // Map the variable into it.
  821. return (*N); // Return the new element.
  822. }
  823. ConfigurationAttribute& ConfigurationElement::Attribute(const std::string Name) { // Add an attribute using a c++ string.
  824. ConfigurationAttribute* N = // Create a new attribute by name and
  825. new ConfigurationAttribute(Name, (*this)); // provide myself as the parent.
  826. myCleanFlag = false; // New attributes make us dirty.
  827. myAttributes.push_back(N); // Add the attribute to my list,
  828. return (*N); // dereference and return it.
  829. }
  830. ConfigurationAttribute& ConfigurationElement::Attribute( // Mapping factory for convenience,
  831. const std::string Name, // requires a name, of course,
  832. ConfigurationTranslator& newTranslator) { // Add a Translator to this element.
  833. myCleanFlag = false; // New attributes make us dirty.
  834. ConfigurationAttribute* N = // Create a new attribute by name and
  835. new ConfigurationAttribute(Name, (*this)); // provide myself as the parent.
  836. myAttributes.push_back(N); // Add the attribute to my list.
  837. N->mapTo(newTranslator); // Map in the provided translator.
  838. return(*N); // Dereference and return the attribute.
  839. }
  840. ConfigurationAttribute& ConfigurationElement::Attribute( // Mapping factory for convenience,
  841. const std::string Name, // requires a name, of course,
  842. std::string& x, std::string init) { // Map to a string.
  843. myCleanFlag = false; // New attributes make us dirty.
  844. ConfigurationAttribute* N = // Create a new attribute by name and
  845. new ConfigurationAttribute(Name, (*this)); // provide myself as the parent.
  846. myAttributes.push_back(N); // Add the attribute to my list.
  847. N->mapTo(x, init); // Map in the provided variable.
  848. return(*N); // Dereference and return the attribute.
  849. }
  850. ConfigurationAttribute& ConfigurationElement::Attribute( // Mapping factory for convenience,
  851. const std::string Name, // requires a name, of course,
  852. int& x, int init, int radix) { // Map to an int.
  853. myCleanFlag = false; // New attributes make us dirty.
  854. ConfigurationAttribute* N = // Create a new attribute by name and
  855. new ConfigurationAttribute(Name, (*this)); // provide myself as the parent.
  856. myAttributes.push_back(N); // Add the attribute to my list.
  857. N->mapTo(x, init, radix); // Map in the provided variable.
  858. return(*N); // Dereference and return the attribute.
  859. }
  860. ConfigurationAttribute& ConfigurationElement::Attribute( // Mapping factory for convenience,
  861. const std::string Name, // requires a name, of course,
  862. double& x, double init) { // Map to a double.
  863. myCleanFlag = false; // New attributes make us dirty.
  864. ConfigurationAttribute* N = // Create a new attribute by name and
  865. new ConfigurationAttribute(Name, (*this)); // provide myself as the parent.
  866. myAttributes.push_back(N); // Add the attribute to my list.
  867. N->mapTo(x, init); // Map in the provided variable.
  868. return(*N); // Dereference and return the attribute.
  869. }
  870. ConfigurationAttribute& ConfigurationElement::Attribute( // Mapping factory for convenience,
  871. const std::string Name, // requires a name, of course,
  872. bool& x, bool init) { // Map to a boolean.
  873. myCleanFlag = false; // New attributes make us dirty.
  874. ConfigurationAttribute* N = // Create a new attribute by name and
  875. new ConfigurationAttribute(Name, (*this)); // provide myself as the parent.
  876. myAttributes.push_back(N); // Add the attribute to my list.
  877. N->mapTo(x, init); // Map in the provided variable.
  878. return(*N); // Dereference and return the attribute.
  879. }
  880. ConfigurationElement& ConfigurationElement::mapTo( // Add a Translator to this element.
  881. ConfigurationTranslator& newTranslator) { // Given a new translator I can own,
  882. myTranslators.push_back(&newTranslator); // add the translator to my list
  883. myCleanFlag = false; // get dirty for the new translator
  884. return(*this); // then dereference and return myself.
  885. }
  886. ConfigurationElement& ConfigurationElement::mapTo( // Map to a string.
  887. std::string& x, std::string init) { // Given a string and init value,
  888. ConfigurationTranslator* N = // create a new translator for it
  889. new StringTranslator(x, init); // with the values i'm given,
  890. myTranslators.push_back(N); // push it onto my list, then
  891. myCleanFlag = false; // get dirty for the new translator
  892. return(*this); // then dereference and return myself.
  893. }
  894. ConfigurationElement& ConfigurationElement::mapTo( // Map to an int.
  895. int& x, int init, int radix) { // Given an int and init values,
  896. ConfigurationTranslator* N = // create a new translator for it
  897. new IntegerTranslator(x, init, radix); // with the values i'm given,
  898. myTranslators.push_back(N); // push it onto my list, then
  899. myCleanFlag = false; // get dirty for the new translator
  900. return(*this); // then dereference and return myself.
  901. }
  902. ConfigurationElement& ConfigurationElement::mapTo( // Map to a double.
  903. double& x, double init) { // Given a double and it's init value,
  904. ConfigurationTranslator* N = // create a new translator for it
  905. new DoubleTranslator(x, init); // with the values i'm given,
  906. myTranslators.push_back(N); // push it onto my list, then
  907. myCleanFlag = false; // get dirty for the new translator
  908. return(*this); // then dereference and return myself.
  909. }
  910. ConfigurationElement& ConfigurationElement::mapTo( // Map to a boolean.
  911. bool& x, bool init) { // Given a bool and it's init value,
  912. ConfigurationTranslator* N = // create a new translator for it
  913. new BoolTranslator(x, init); // with the values i'm given,
  914. myTranslators.push_back(N); // push it onto my list, then
  915. myCleanFlag = false; // get dirty for the new translator
  916. return(*this); // then dereference and return myself.
  917. }
  918. void ConfigurationElement::initialize() { // Reset all translators to defaults.
  919. // Initialize the elements below me
  920. if(0 < myElements.size()) { // If we have elements...
  921. std::list<ConfigurationElement*>::iterator iElement; // Iterate through our elements list.
  922. iElement = myElements.begin(); // Start at the beginning and
  923. while(iElement != myElements.end()) { // loop through the whole list.
  924. (*iElement)->initialize(); // Initialize each element
  925. iElement++; // then move the iterator.
  926. }
  927. }
  928. // Once that's done, see about myself
  929. if(true == myCleanFlag) return; // If I'm already clean, return.
  930. // Initialize my own translators
  931. if(0 < myTranslators.size()) { // If we have translators...
  932. std::list<ConfigurationTranslator*>::iterator iTranslator; // Iterate through our translators list.
  933. iTranslator = myTranslators.begin(); // Start at the beginning and
  934. while(iTranslator != myTranslators.end()) { // loop through the whole list.
  935. (*iTranslator)->initialize(); // Initialize each translator
  936. iTranslator++; // then move the iterator.
  937. }
  938. }
  939. // Initialize my own attributes
  940. if(0 < myAttributes.size()) { // If we have attributes...
  941. std::list<ConfigurationAttribute*>::iterator iAttribute; // Iterate through our attributes list.
  942. iAttribute = myAttributes.begin(); // Start at the beginning and
  943. while(iAttribute != myAttributes.end()) { // loop through the whole list.
  944. (*iAttribute)->initialize(); // Initialize each attribute
  945. ++iAttribute; // then move the iterator.
  946. }
  947. }
  948. // Zero things out
  949. myLine = 0; // Initialized means to be as if
  950. myIndex = 0; // no interpet() call has been made.
  951. myLength = 0;
  952. // At this point we know we are clean
  953. myCleanFlag = true; // Clean as a whistle!
  954. }
  955. void ConfigurationElement::runStartConfigurators(ConfigurationData& D) { // Does what it says ;-)
  956. std::list<Configurator*>::iterator iConfigurator; // Iterate through our Configurators list.
  957. iConfigurator = myStartConfigurators.begin(); // Start at the beginning and
  958. while(iConfigurator != myStartConfigurators.end()) { // loop through the whole list.
  959. (** iConfigurator)(*this, D); // Launch each configurator with self.
  960. ++iConfigurator; // Move to the next.
  961. }
  962. }
  963. void ConfigurationElement::runEndConfigurators(ConfigurationData& D) { // Does what it says ;-)
  964. std::list<Configurator*>::iterator iConfigurator; // Iterate through our Configurators list.
  965. iConfigurator = myEndConfigurators.begin(); // Start at the beginning and
  966. while(iConfigurator != myEndConfigurators.end()) { // loop through the whole list.
  967. (** iConfigurator)(*this, D); // Launch each configurator with self.
  968. ++iConfigurator; // Move to the next.
  969. }
  970. }
  971. bool ConfigurationElement::interpret(ConfigurationData& Data) { // (re) Interpret this data.
  972. int Index = Data.Index(); // Our working index.
  973. int Startdex = 0; // Where our data starts.
  974. int Stopdex = 0; // Where our data stops.
  975. int NewLines = 0; // Keep a count of new lines.
  976. //// Pre-Processing / Cleanup / Find <name...
  977. // Eat anything up to the first <
  978. // Eat any comments <!-- this is a comment etc -->
  979. // Eat any doctype headers <?xml version="1.0" etc ?>
  980. for(;;) {
  981. int StartingPoint = Index; // Where did we start each pass?
  982. NewLines += eatNonTagTextCountLines(Data, Index); // Eat any spaces we find.
  983. NewLines += eatCommentsCountLines(Data, Index); // Eat any <!-- -->
  984. NewLines += eatDocSpecsCountLines(Data, Index); // Eat any <? ?>
  985. if(StartingPoint == Index) { break; } // If we didn't move on this pass
  986. } // then we are done with cleanup!
  987. // Update Data to move past any of the preceeding junk. This way, other
  988. // element processors will be able to skip any cleanup work we did.
  989. Data.Index(Index); // Move the Index.
  990. Data.addNewLines(NewLines); // Update the Line Number.
  991. NewLines = 0; // Reset our internal Lines counter.
  992. // Find my name.
  993. if(Data.Data(Index) != '<') { // If we're not on a tag open then
  994. return false; // we are not at an element.
  995. } else { // Otherwise we are safe to move
  996. ++Index; // past it and scan for our name.
  997. }
  998. for(unsigned int I = 0; I < myName.length(); I++) { // For the length of our name,
  999. char x = Data.Data(Index + I); // get each corresponding Data byte
  1000. if(x != myName.at(I)) { // check it sudden death style.
  1001. return false; // No-Match means we are not it.
  1002. }
  1003. } // If the name checks out then
  1004. Index += myName.length(); // move the Index past our name.
  1005. // At this point we have found ourselves so we will activate and interpret
  1006. // our Data.
  1007. if(true == myInitOnInterpretFlag) { // If we are supposed to Init before
  1008. initialize(); // we Interpret then do it.
  1009. }
  1010. // Since we are activating we must set our state so we know where we are.
  1011. myLine = Data.Line(); // We know where we start...
  1012. myIndex = Data.Index(); // We know our index...
  1013. myLength = 0; // We don't know our length yet.
  1014. runStartConfigurators(Data); // Run the start configurators.
  1015. myCleanFlag = false; // Now we start to get dirty.
  1016. // First, we will run through any attributes we have.
  1017. bool ThisIsAnEmptyElement = false; // We'll use this to signal empties.
  1018. for(;;) { // This is how we roll..
  1019. NewLines += eatSpacesCountLines(Data, Index); // Eat any spaces we find.
  1020. Data.Index(Index); // Move the Index.
  1021. Data.addNewLines(NewLines); // Update the Line Number.
  1022. NewLines = 0; // Reset our internal Lines counter.
  1023. // Now we look at the next character. Either it's an attribute, or
  1024. // it's the end of the tag, or it's some kind of junk. If it's junk
  1025. // we will skip it. We will continue parsing until we get to the end
  1026. // of the Data or the end of the opening tag (either stopping at / if
  1027. // the element is empty or > if the element is not empty.
  1028. if(isalpha(Data.Data(Index))) { // If it looks like an attribute...
  1029. bool ParseHappened = false; // Start pessimistically at each pass.
  1030. std::list<ConfigurationAttribute*>::iterator iAttribute; // Iterate through our attributes list.
  1031. iAttribute = myAttributes.begin(); // Start at the beginning and
  1032. while(iAttribute != myAttributes.end()) { // loop through the whole list.
  1033. ParseHappened = (* iAttribute)->interpret(Data); // Have each attribute interpret(Data)
  1034. ++iAttribute; // Remember to move to the next one.
  1035. if(ParseHappened) break; // If a Parse Happened, break the inner
  1036. } // loop and start the next pass.
  1037. if(false == ParseHappened) { // If we didn't recognize the attribute
  1038. NewLines += eatAttributeCountLines(Data, Index); // then eat it.
  1039. Data.Index(Index); // Sync up our Index.
  1040. Data.addNewLines(NewLines); // Sync up our NewLines.
  1041. NewLines = 0; // Zero our NewLines count.
  1042. } else { // If we DID recognize the attribute then
  1043. Index = Data.Index(); // sync up our Index for the next one.
  1044. }
  1045. } else
  1046. if(0 == Data.Data(Index)) { // If it looks like the end of Data
  1047. break; // we will break out - we're done.
  1048. } else
  1049. if( // If it looks like the end of an empty
  1050. '/' == Data.Data(Index) && // element (starts with / and ends with
  1051. '>' == Data.Data(Index + 1) // >) then this must be an empty element.
  1052. ) {
  1053. ThisIsAnEmptyElement = true; // Set the empty element flag and
  1054. Index += 2; // Move past the end of the tag and
  1055. break; // break out of the loop.
  1056. } else
  1057. if('>' == Data.Data(Index)) { // If it looks like the end of an open
  1058. Index += 1; // tag then move past the end and
  1059. break; // break out of the loop.
  1060. } else { // If it looks like anything else then
  1061. ++Index; // we don't know what it is so we creep
  1062. } // past it.
  1063. }
  1064. Data.Index(Index); // Sync up our index
  1065. // At this point we're done processing our open tag and any attributes it
  1066. // may have contained, and we are syncrhonized with Data.
  1067. if(ThisIsAnEmptyElement) { // If the element was self closing then
  1068. runEndConfigurators(Data); // run the End Configurators and return
  1069. return true; // true to the caller.
  1070. }
  1071. // At this point we have contents and/or elements to process. We will keep
  1072. // track of any contents using Startdex and Stopdex.
  1073. Startdex = Index;
  1074. // Now we will process through any elements there may be until we reach
  1075. // our end tag. If we have no sub-elements listed, we'll simply skip that
  1076. // step on each pass... So, we roll like this:
  1077. // Check for end of Data.
  1078. // Check for our end tag.
  1079. // Check for a sub-element.
  1080. // If none of these work then break out.
  1081. for(;;) { // Loop through our content like this.
  1082. int CheckPoint = Index; // Where did we start each pass?
  1083. // Check for end of data //
  1084. if(0 == Data.Data(Index)) { // If we are at end of data then we're
  1085. return false; // broken so we return false.
  1086. } else
  1087. // Check for our own end tag //
  1088. if( // If this looks like an end tag
  1089. '<' == Data.Data(Index) && // (Starts with < followed by
  1090. '/' == Data.Data(Index + 1) // a / character)
  1091. ) { // Then it _should_ be our own.
  1092. Stopdex = Index; // Capture this position for content.
  1093. Index += 2; // Move Index to where the name starts.
  1094. for(unsigned int I = 0; I < myName.length(); I++) { // For the length of the name,
  1095. char x = Data.Data(Index + I); // check each corresponding Data byte.
  1096. if(x != myName.at(I)) { // If we fail to match at any point
  1097. return false; // then things are very broken
  1098. } // so we return false.
  1099. } // If the name checks out then
  1100. Index += myName.length(); // move past our name.
  1101. if('>' != Data.Data(Index)) { // Being very strict, if the next
  1102. return false; // byte is not > then fail!
  1103. } else { // If all goes well then we move
  1104. ++Index; // past the > and we are done.
  1105. break; // Break to move to the next step.
  1106. }
  1107. } else
  1108. // Check for a subordinate element //
  1109. if( // If this looks like an element
  1110. '<' == Data.Data(Index) && // starting with < and a name
  1111. isalpha(Data.Data(Index + 1)) // beginning with an alpha character...
  1112. ) {
  1113. bool ElementHappened = false; // We'll check our elements.
  1114. Data.Index(Index); // Sync our index.
  1115. Data.addNewLines(NewLines); // Sync our lines.
  1116. NewLines = 0; // Reset our new lines count.
  1117. if(0 < myElements.size()) { // If we have elements check them.
  1118. std::list<ConfigurationElement*>::iterator iElement; // Iterate through our elements list.
  1119. iElement = myElements.begin(); // Start at the beginning and
  1120. while(iElement != myElements.end()) { // loop through the whole list.
  1121. ConfigurationElement& doNode = **iElement; // Grab the element we're on.
  1122. ElementHappened = doNode.interpret(Data); // Have each element interpret(Data)
  1123. Index = Data.Index(); // Capitalze on any cleanup work.
  1124. ++iElement; // Remember to move to the next.
  1125. if(ElementHappened) break; // If an Element Happened, break the
  1126. } // loop and start the next pass.
  1127. if(false == ElementHappened) { // If we did not recognize the Element
  1128. NewLines += eatElementCountLines(Data, Index); // then eat it *****
  1129. Data.Index(Index); // Resync our Index.
  1130. Data.addNewLines(NewLines); // Sync our line count.
  1131. NewLines = 0; // Reset our internal count.
  1132. }
  1133. } else { // If we don't own any elements then
  1134. NewLines += eatElementCountLines(Data, Index); // eat the ones we find.
  1135. }
  1136. // Handle any untidy messes here //
  1137. } else { // If we're on something unknown then
  1138. NewLines += eatSpacesCountLines(Data, Index); // Eat any spaces we find.
  1139. NewLines += eatCommentsCountLines(Data, Index); // Eat any <!-- -->
  1140. NewLines += eatDocSpecsCountLines(Data, Index); // Eat any <? ?>
  1141. NewLines += eatNonTagTextCountLines(Data, Index); // Eat any non tag bytes.
  1142. Data.Index(Index); // Sync our Index.
  1143. Data.addNewLines(NewLines); // Sync our line number.
  1144. NewLines = 0; // Clear our lines count.
  1145. }
  1146. // If we get stuck looping on something we don't know how to clean
  1147. // and don't know how to interpret then we need to break out of the
  1148. // insanity. This way, anything that doesn't make sense won't be able
  1149. // to stall us or cause us to interpret something incorrectly later
  1150. // on... If we're the top element, the interpret() process will end.
  1151. // If we are deeper then it is likely our superirors will also not
  1152. // understand and so they will also end the same way.
  1153. if(CheckPoint == Index) return false; // If we haven't moved, punt!
  1154. }
  1155. // When we're done with our loop sync up with Data again.
  1156. Data.Index(Index); // Sync up our Index.
  1157. Data.addNewLines(NewLines); // Sync up our NewLines count.
  1158. NewLines = 0; // zero our local count.
  1159. // Once our elements have been procssed and we get to our end tag we can
  1160. // process our content (if we have Translators registered).
  1161. if(
  1162. 0 < myTranslators.size() && // If we have translators and
  1163. Stopdex > Startdex // we have content to translate
  1164. ) { // then translate the content!
  1165. // Create the Content buffer...
  1166. int BfrSize = Stopdex - Startdex +1; // How big a buffer do we need?
  1167. std::vector<char> heapBfr(BfrSize,0); // Make one that size.
  1168. char* Bfr = &heapBfr[0];
  1169. copyDataCountLines(Bfr, Data, Startdex, Stopdex); // Get our data and ignore our lines.
  1170. // Now we can get on with translation.
  1171. char* TranslationData = Bfr; // TranslationData is what we translate.
  1172. // Translate our data by Mnemonic
  1173. if(0 < myMnemonics.size()) { // If we have mnemonics...
  1174. std::list<ConfigurationMnemonic*>::iterator iMnemonic; // Iterate through our mnemonics list.
  1175. iMnemonic = myMnemonics.begin(); // Start at the beginning and
  1176. while(iMnemonic != myMnemonics.end()) { // loop through the whole list.
  1177. if(true == ((*iMnemonic)->test(TranslationData))) { // Check to see if the mnemonic matches.
  1178. TranslationData = const_cast<char*>( // If it does match, substitute it's
  1179. (*iMnemonic)->Value().c_str()); // value for translation and stop
  1180. break; // looking.
  1181. } else { // If it does not match, move to the
  1182. ++iMnemonic; // next mnemonic and test again.
  1183. } // That is, until we run out of
  1184. } // mnemonics to test.
  1185. }
  1186. // Put our TranslationData through each Translator.
  1187. std::list<ConfigurationTranslator*>::iterator iTranslator; // Iterate through our translators list.
  1188. iTranslator = myTranslators.begin(); // Start at the beginning and
  1189. while(iTranslator != myTranslators.end()) { // loop through the whole list.
  1190. (*iTranslator)->translate(TranslationData); // Pass the data to each one then
  1191. ++iTranslator; // move on to the next.
  1192. }
  1193. }
  1194. // And finally, after all is done successfully...
  1195. runEndConfigurators(Data); // Launch the End Configurators.
  1196. return true; // Return our success!
  1197. }
  1198. //// Configuration Attribute ///////////////////////////////////////////////////
  1199. ConfigurationAttribute::~ConfigurationAttribute() { // Crush, Kill, Destroy!
  1200. // Delete my mnemonics
  1201. if(0 < myMnemonics.size()) { // If we have mnemonics...
  1202. std::list<ConfigurationMnemonic*>::iterator iMnemonic; // Iterate through our mnemonics list.
  1203. iMnemonic = myMnemonics.begin(); // Start at the beginning and
  1204. while(iMnemonic != myMnemonics.end()) { // loop through the whole list.
  1205. delete (*iMnemonic); // Delete each mnemonic
  1206. iMnemonic++; // then move the iterator.
  1207. } // When we're done deleting them
  1208. myMnemonics.clear(); // clear the list.
  1209. }
  1210. // Delete my translators
  1211. if(0 < myTranslators.size()) { // If we have translators...
  1212. std::list<ConfigurationTranslator*>::iterator iTranslator; // Iterate through our translators list.
  1213. iTranslator = myTranslators.begin(); // Start at the beginning and
  1214. while(iTranslator != myTranslators.end()) { // loop through the whole list.
  1215. delete (*iTranslator); // Delete each translator
  1216. iTranslator++; // then move the iterator.
  1217. } // When we're done deleting them
  1218. myTranslators.clear(); // clear the list.
  1219. }
  1220. // zero things out
  1221. myLine = 0; // If I'm going away then I will leave
  1222. myIndex = 0; // with everything at zero and clean.
  1223. myLength = 0;
  1224. }
  1225. ConfigurationAttribute& ConfigurationAttribute::mapTo( // Add a Translator to this attribute.
  1226. ConfigurationTranslator& newTranslator) { // Given a new translator I can own,
  1227. myTranslators.push_back(&newTranslator); // add the translator to my list
  1228. myParent.notifyDirty(); // get dirty for the new translator
  1229. return(*this); // then dereference and return myself.
  1230. }
  1231. ConfigurationAttribute& ConfigurationAttribute::mapTo( // Map to a string.
  1232. std::string& x, std::string init) { // Given a string and init value,
  1233. ConfigurationTranslator* N = // create a new translator for it
  1234. new StringTranslator(x, init); // with the values i'm given,
  1235. myTranslators.push_back(N); // push it onto my list, then
  1236. myParent.notifyDirty(); // get dirty for the new translator
  1237. return(*this); // dereference and return myself.
  1238. }
  1239. ConfigurationAttribute& ConfigurationAttribute::mapTo( // Map to an int.
  1240. int& x, int init, int radix) { // Given an int and init values,
  1241. ConfigurationTranslator* N = // create a new translator for it
  1242. new IntegerTranslator(x, init, radix); // with the values i'm given,
  1243. myTranslators.push_back(N); // push it onto my list, then
  1244. myParent.notifyDirty(); // get dirty for the new translator
  1245. return(*this); // dereference and return myself.
  1246. }
  1247. ConfigurationAttribute& ConfigurationAttribute::mapTo( // Map to a double.
  1248. double& x, double init) { // Given a double and it's init value,
  1249. ConfigurationTranslator* N = // create a new translator for it
  1250. new DoubleTranslator(x, init); // with the values i'm given,
  1251. myTranslators.push_back(N); // push it onto my list, then
  1252. myParent.notifyDirty(); // get dirty for the new translator
  1253. return(*this); // then dereference and return myself.
  1254. }
  1255. ConfigurationAttribute& ConfigurationAttribute::mapTo( // Map to a boolean.
  1256. bool& x, bool init) { // Given a bool and it's init value,
  1257. ConfigurationTranslator* N = // create a new translator for it
  1258. new BoolTranslator(x, init); // with the values i'm given,
  1259. myTranslators.push_back(N); // push it onto my list, then
  1260. myParent.notifyDirty(); // get dirty for the new translator
  1261. return(*this); // then dereference and return myself.
  1262. }
  1263. void ConfigurationAttribute::initialize() { // Reset all translators to defaults.
  1264. if(0 < myTranslators.size()) { // If we have translators...
  1265. std::list<ConfigurationTranslator*>::iterator iTranslator; // Iterate through our translators list.
  1266. iTranslator = myTranslators.begin(); // Start at the beginning and
  1267. while(iTranslator != myTranslators.end()) { // loop through the whole list.
  1268. (*iTranslator)->initialize(); // initialize each translator
  1269. iTranslator++; // then move the iterator.
  1270. } // When we're done deleting them
  1271. }
  1272. // zero things out
  1273. myLine = 0; // Initialized means to be as if
  1274. myIndex = 0; // no interpet() call has been made.
  1275. myLength = 0;
  1276. }
  1277. bool ConfigurationAttribute::interpret(ConfigurationData& Data) { // (re) Interpret this data.
  1278. int Index = Data.Index(); // Our working index.
  1279. int Startdex = 0; // Where our data starts.
  1280. int Stopdex = 0; // Where our data stops.
  1281. int NewLines = 0; // Keep a count of new lines.
  1282. // Find our name.
  1283. for(unsigned int I = 0; I < myName.length(); I++) { // For the length of the name,
  1284. char x = Data.Data(Index + I); // get each corresponding Data byte
  1285. if(x != myName.at(I)) { // check it sudden death style.
  1286. return false; // No-Match means we are not it.
  1287. }
  1288. } // If the name checks out then
  1289. Index += myName.length(); // move the Index past our name.
  1290. NewLines += eatSpacesCountLines(Data, Index); // Eat any spaces we find.
  1291. // Find our = sign.
  1292. if('=' != Data.Data(Index)) { // Next we should see an =
  1293. return false; // If we don't we're done.
  1294. } else { // If we do then we can
  1295. ++Index; // move past it.
  1296. }
  1297. NewLines += eatSpacesCountLines(Data, Index); // Eat any spaces we find.
  1298. // Find our first quote character.
  1299. char QuoteCharacter = 0;
  1300. if('\'' == Data.Data(Index) || '\"' == Data.Data(Index)) { // Next we should find ' or "
  1301. QuoteCharacter = Data.Data(Index); // If we found it record it then
  1302. ++Index; Startdex = Index; // move to and record our start of data.
  1303. } else { // If we don't
  1304. return false; // we are done.
  1305. }
  1306. // Find our last quote character.
  1307. for(;;) { // Here is how we will roll...
  1308. char C = Data.Data(Index); // Grab the character at Index.
  1309. if(0 == C) { // If we run out of Data then
  1310. return false; // We didn't find anything.
  1311. }
  1312. if(QuoteCharacter == C) { // If we find our QuoteCharacter
  1313. Stopdex = Index; // we have our Stopdex and
  1314. break; // we can stop the loop.
  1315. }
  1316. ++Index; // Otherwise keep on looking.
  1317. }
  1318. // Read our data.
  1319. int BfrSize = Stopdex - Startdex +1; // How big a buffer do we need?
  1320. std::vector<char> heapBfr(BfrSize,0); // Make one that size.
  1321. char* Bfr = &heapBfr[0];
  1322. NewLines += copyDataCountLines(Bfr, Data, Startdex, Stopdex); // Get our data and count our lines.
  1323. // Now we can get on with translation.
  1324. char* TranslationData = Bfr; // TranslationData is what we translate.
  1325. // Translate our data by Mnemonic
  1326. if(0 < myMnemonics.size()) { // If we have mnemonics...
  1327. std::list<ConfigurationMnemonic*>::iterator iMnemonic; // Iterate through our mnemonics list.
  1328. iMnemonic = myMnemonics.begin(); // Start at the beginning and
  1329. while(iMnemonic != myMnemonics.end()) { // loop through the whole list.
  1330. if(true == ((*iMnemonic)->test(TranslationData))){ // Check to see if the mnemonic matches.
  1331. TranslationData = const_cast<char*>( // If it does match, substitute it's
  1332. (*iMnemonic)->Value().c_str()); // value for translation and stop
  1333. break; // looking.
  1334. } else { // If it does not match, move to the
  1335. ++iMnemonic; // next mnemonic and test again.
  1336. } // That is, until we run out of
  1337. } // mnemonics to test.
  1338. }
  1339. // Put our TranslationData through each Translator.
  1340. if(0 < myTranslators.size()) { // We'd better have translators!
  1341. std::list<ConfigurationTranslator*>::iterator iTranslator; // Iterate through our translators list.
  1342. iTranslator = myTranslators.begin(); // Start at the beginning and
  1343. while(iTranslator != myTranslators.end()) { // loop through the whole list.
  1344. (*iTranslator)->translate(TranslationData); // Pass the data to each one and
  1345. ++iTranslator; // move on to the next one.
  1346. }
  1347. }
  1348. // Capture our position data.
  1349. myLine = Data.Line(); // Capture the line I was on.
  1350. myIndex = Data.Index(); // Capture the Index where I started.
  1351. myLength = Stopdex + 1 - myIndex; // Capture my segment length.
  1352. // Update Data for the next segment.
  1353. Data.Index(Stopdex + 1); // Move the Index.
  1354. Data.addNewLines(NewLines); // Update the Line Number.
  1355. return true; // If we got here, we succeeded!
  1356. }
  1357. //// Configuratino Data ////////////////////////////////////////////////////////
  1358. char* newCStringBuffer(size_t requestedSize) {
  1359. const char NullTerminator = 0;
  1360. size_t safeSize = requestedSize + 1;
  1361. char* theBufferPointer = new char[safeSize];
  1362. theBufferPointer[requestedSize] = NullTerminator;
  1363. return theBufferPointer;
  1364. }
  1365. ConfigurationData::ConfigurationData(const char* Data, int Length) : // Raw constructor from buffer.
  1366. myBufferSize(Length), // and it's length.
  1367. myIndex(0), // Our Index is zero
  1368. myLine(1) { // We start on line 1
  1369. myDataBuffer = newCStringBuffer(myBufferSize); // Allocate a buffer.
  1370. memcpy(myDataBuffer, Data, myBufferSize); // Copy the data.
  1371. }
  1372. ConfigurationData::ConfigurationData(const char* FileName) :
  1373. myDataBuffer(NULL), // No data buffer yet.
  1374. myBufferSize(0), // No length yet.
  1375. myIndex(0), // Our Index is zero
  1376. myLine(1) { // We start on line 1
  1377. try { // Capture any throws.
  1378. std::ifstream CFGFile(FileName); // Open the file.
  1379. CFGFile.seekg(0,std::ios::end); // Seek to the end
  1380. myBufferSize = CFGFile.tellg(); // to find out what size it is.
  1381. myDataBuffer = newCStringBuffer(myBufferSize); // Make a new buffer the right size.
  1382. CFGFile.seekg(0,std::ios::beg); // Seek to the beginning and
  1383. CFGFile.read(myDataBuffer, myBufferSize); // read the file into the buffer.
  1384. if(CFGFile.bad()) { // If the read failed, we're unusable!
  1385. delete[] myDataBuffer; // Delete the buffer
  1386. myDataBuffer = NULL; // and Null it's pointer.
  1387. myBufferSize = 0; // Set the length to zero.
  1388. } // Usually everything will work
  1389. CFGFile.close(); // At the end, always close our file.
  1390. } catch (...) { // If something went wrong clean up.
  1391. if(NULL != myDataBuffer) { // If the data buffer was allocated
  1392. delete[] myDataBuffer; // Delete the buffer
  1393. myDataBuffer = NULL; // and Null it's pointer.
  1394. }
  1395. myBufferSize = 0; // The BufferSize will be zero
  1396. } // indicating there is no Data.
  1397. }
  1398. ConfigurationData::ConfigurationData(const std::string FileName) : // Raw constructor from file.
  1399. myDataBuffer(NULL), // No data buffer yet.
  1400. myBufferSize(0), // No length yet.
  1401. myIndex(0), // Our Index is zero
  1402. myLine(1) { // We start on line 1
  1403. try { // Capture any throws.
  1404. std::ifstream CFGFile(FileName.c_str()); // Open the file.
  1405. CFGFile.seekg(0,std::ios::end); // Seek to the end
  1406. myBufferSize = CFGFile.tellg(); // to find out what size it is.
  1407. myDataBuffer = newCStringBuffer(myBufferSize); // Make a new buffer the right size.
  1408. CFGFile.seekg(0,std::ios::beg); // Seek to the beginning and
  1409. CFGFile.read(myDataBuffer, myBufferSize); // read the file into the buffer.
  1410. if(CFGFile.bad()) { // If the read failed, we're unusable!
  1411. delete[] myDataBuffer; // Delete the buffer
  1412. myDataBuffer = NULL; // and Null it's pointer.
  1413. myBufferSize = 0; // Set the length to zero.
  1414. } // Usually everything will work
  1415. CFGFile.close(); // At the end, always close our file.
  1416. } catch (...) { // If something went wrong clean up.
  1417. if(NULL != myDataBuffer) { // If the data buffer was allocated
  1418. delete[] myDataBuffer; // Delete the buffer
  1419. myDataBuffer = NULL; // and Null it's pointer.
  1420. }
  1421. myBufferSize = 0; // The BufferSize will be zero
  1422. } // indicating there is no Data.
  1423. }
  1424. ConfigurationData::~ConfigurationData() { // Destroys the internal buffer etc.
  1425. if(NULL != myDataBuffer) { // If we have allocated a buffer,
  1426. delete[] myDataBuffer; // delete that buffer
  1427. myDataBuffer = NULL; // and null the pointer.
  1428. }
  1429. myBufferSize = 0; // Zero everything for safety.
  1430. myIndex = 0;
  1431. myLine = 0;
  1432. }
  1433. //// Utilities /////////////////////////////////////////////////////////////////
  1434. // SetTrueOnComplete Configurator //////////////////////////////////////////////
  1435. ConfiguratorSetTrueOnComplete::ConfiguratorSetTrueOnComplete() : // Constructor ensures the pointer
  1436. myBoolean(NULL) { // is NULL for safety.
  1437. }
  1438. void ConfiguratorSetTrueOnComplete::setup(bool& Target) { // The setup() method links us to a
  1439. myBoolean = &Target; // target boolean.
  1440. }
  1441. void ConfiguratorSetTrueOnComplete::operator()( // The operator()
  1442. ConfigurationElement& E, ConfigurationData& D) { // When activated, this fellow
  1443. if(NULL != myBoolean) { // checks it's pointer for safety
  1444. *myBoolean = true; // and if ok, sets the target to
  1445. } // true.
  1446. }
  1447. } // End namespace codedweller