Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

configuration.cpp 117KB

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