jprop.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  1. /*##############################################################################
  2. HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems®.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. ############################################################################## */
  13. #include "jiface.hpp"
  14. #include "jprop.hpp"
  15. #include "jhash.hpp"
  16. #include "jhash.ipp"
  17. #include "jexcept.hpp"
  18. #include "jiter.ipp"
  19. #include "jregexp.hpp"
  20. #include <stdio.h>
  21. #ifdef _WIN32
  22. #include <stdlib.h>
  23. #elif defined(__linux__) || defined(__FreeBSD__)
  24. extern char **environ;
  25. #endif
  26. #if defined(__APPLE__)
  27. #include <crt_externs.h>
  28. #endif
  29. const char *conv2char_ptr(const char *p) { return p; }
  30. const char *convchar_ptr2(const char *p) { return p; }
  31. const char *tokvchar_ptr(const void *p) { return (const char *)p; }
  32. template <class PTYPE, class PITER>
  33. class PropertyIteratorOf : implements PITER, public CInterface
  34. {
  35. protected:
  36. HashIterator *piter;
  37. const HashTable &properties;
  38. public:
  39. IMPLEMENT_IINTERFACE;
  40. PropertyIteratorOf(const HashTable &_properties) : properties(_properties)
  41. {
  42. properties.Link();
  43. piter = new HashIterator(properties);
  44. }
  45. ~PropertyIteratorOf()
  46. {
  47. properties.Release();
  48. piter->Release();
  49. }
  50. virtual bool first()
  51. {
  52. return piter->first();
  53. }
  54. virtual bool next()
  55. {
  56. return piter->next();
  57. }
  58. virtual bool isValid()
  59. {
  60. return piter->isValid();
  61. }
  62. virtual PTYPE getPropKey() = 0;
  63. };
  64. typedef IPropertyIterator char_ptrIPropertyIterator;
  65. class char_ptrPropertyIterator : public PropertyIteratorOf<const char *, char_ptrIPropertyIterator>
  66. {
  67. public:
  68. char_ptrPropertyIterator(const HashTable &_properties) : PropertyIteratorOf<const char *, char_ptrIPropertyIterator>(_properties) { }
  69. virtual const char *getPropKey()
  70. {
  71. IMapping &cur = piter->query();
  72. const char *key = (const char *) (cur.getKey());
  73. return key;
  74. }
  75. };
  76. template <class PTYPE, class MAPPING, class IPROP, class IPROPITER, class PROPITER>
  77. class CPropertiesBase : implements IPROP, public CInterface
  78. {
  79. private:
  80. MAPPING properties;
  81. public:
  82. IMPLEMENT_IINTERFACE;
  83. CPropertiesBase(bool nocase) : properties(nocase)
  84. {
  85. }
  86. virtual ~CPropertiesBase()
  87. {
  88. properties.kill();
  89. }
  90. void loadProp(const char *finger)
  91. {
  92. StringBuffer prop, val;
  93. while (*finger && *finger != '=')
  94. prop.append(*finger++);
  95. if (*finger)
  96. {
  97. finger++;
  98. while (isspace(*finger))
  99. finger++;
  100. while (*finger)
  101. val.append(*finger++);
  102. prop.clip();
  103. val.clip();
  104. if (prop.length())
  105. setProp(toPType(prop.str()), val.str());
  106. }
  107. }
  108. void loadProp(const char *finger, int dft)
  109. {
  110. if (strchr(finger, '='))
  111. loadProp(finger);
  112. else
  113. setProp(toPType(finger), dft);
  114. }
  115. void loadProp(const char *finger, bool dft)
  116. {
  117. if (strchr(finger, '='))
  118. loadProp(finger);
  119. else
  120. setProp(toPType(finger), dft);
  121. }
  122. void loadProp(const char *finger, const char * dft)
  123. {
  124. if (strchr(finger, '='))
  125. loadProp(finger);
  126. else
  127. setProp(toPType(finger), dft);
  128. }
  129. void loadSystem()
  130. {
  131. #ifdef _WIN32
  132. char **e = _environ;
  133. #else
  134. #if defined (__APPLE__)
  135. char **e = *_NSGetEnviron();
  136. #else
  137. char **e = environ;
  138. #endif
  139. #endif
  140. while (*e)
  141. {
  142. loadProp (*e);
  143. e++;
  144. }
  145. }
  146. void loadFile(const char *filename)
  147. {
  148. FILE *inFile = fopen(filename, "r" TEXT_TRANS);
  149. if (inFile)
  150. {
  151. StringBuffer sbuff;
  152. char buf[1024];
  153. while (fgets(buf,1024,inFile))
  154. {
  155. sbuff.clear();
  156. do // handle lines longer than 1024 (bit kludgy)
  157. {
  158. size32_t l=(size32_t)strlen(buf);
  159. if (!l || (buf[l-1]=='\n')) // should end in \n unless overflowed
  160. break;
  161. sbuff.append(buf);
  162. } while (fgets(buf,1024,inFile));
  163. const char *s=buf;
  164. if (sbuff.length())
  165. s = sbuff.append(buf).str();
  166. if (*s == '#')
  167. continue;
  168. char *comment = (char *) strstr(s, "#");
  169. if (comment != NULL)
  170. *comment = 0;
  171. loadProp(s);
  172. sbuff.setLength(0);
  173. }
  174. fclose(inFile);
  175. }
  176. }
  177. void loadProps(const char *finger)
  178. {
  179. while (*finger)
  180. {
  181. StringBuffer prop, val;
  182. while (*finger && *finger != '\n' && *finger != '=')
  183. prop.append(*finger++);
  184. if (*finger && *finger != '\n')
  185. {
  186. finger++;
  187. while (isspace(*finger) && *finger != '\n')
  188. finger++;
  189. while (*finger && *finger != '\n')
  190. val.append(*finger++);
  191. prop.clip();
  192. val.clip();
  193. if (prop.length())
  194. setProp(toPType(prop.str()), val.str());
  195. }
  196. if (*finger)
  197. finger++;
  198. }
  199. }
  200. virtual PTYPE toPType(const char *p) const = 0;
  201. virtual const char *fromPType(PTYPE p) const = 0;
  202. virtual PTYPE toKeyVal(const void *) const = 0;
  203. virtual int getPropInt(PTYPE propname, int dft) const override
  204. {
  205. if (propname)
  206. {
  207. const char *val = queryProp(propname);
  208. if (val)
  209. return (int)_atoi64(val);
  210. }
  211. return dft;
  212. }
  213. virtual bool getPropBool(PTYPE propname, bool dft) const override
  214. {
  215. if (propname)
  216. {
  217. const char *val = queryProp(propname);
  218. if (val&&*val)
  219. return strToBool(val);
  220. }
  221. return dft;
  222. }
  223. virtual bool getProp(PTYPE propname, StringBuffer &ret) const override
  224. {
  225. if (propname)
  226. {
  227. StringAttr * match = properties.getValue(propname);
  228. if (match)
  229. {
  230. ret.append(*match);
  231. return true;
  232. }
  233. }
  234. return false;
  235. }
  236. virtual const char *queryProp(PTYPE propname) const override
  237. {
  238. if (propname)
  239. {
  240. StringAttr * match = properties.getValue(propname);
  241. if (match)
  242. return(*match);
  243. }
  244. return NULL;
  245. }
  246. virtual void saveFile(const char *filename) const override
  247. {
  248. FILE *outFile = fopen(filename, "w" TEXT_TRANS);
  249. if (outFile)
  250. {
  251. HashIterator it(properties);
  252. StringBuffer line;
  253. for (it.first();it.isValid();it.next())
  254. {
  255. IMapping &cur = it.query();
  256. PTYPE key = toKeyVal(cur.getKey());
  257. StringAttr &attr = * (StringAttr *) properties.getValue(key);
  258. line.clear().append(key).append('=').append(attr).newline();
  259. fwrite(line.str(),line.length(),1,outFile);
  260. }
  261. fclose(outFile);
  262. }
  263. }
  264. virtual void setProp(PTYPE propname, int val)
  265. {
  266. char buf[15];
  267. sprintf(buf, "%d", val);
  268. setProp(propname, buf);
  269. }
  270. virtual void setProp(PTYPE propname, const char *val)
  271. {
  272. if (propname)
  273. {
  274. if (val)
  275. properties.setValue(propname, val);
  276. else
  277. properties.remove(propname);
  278. }
  279. }
  280. virtual void appendProp(PTYPE propname, const char *val)
  281. {
  282. if (propname && val)
  283. {
  284. StringAttr * mapping = properties.getValue(propname);
  285. if (mapping)
  286. {
  287. if (*val)
  288. {
  289. char * str = mapping->detach();
  290. size_t len1 = strlen(str);
  291. size_t len2 = strlen(val);
  292. char * newstr = (char *)realloc(str, len1 + len2+1);
  293. assertex(newstr);
  294. memcpy(newstr+len1, val, len2);
  295. newstr[len1+len2] = '\0';
  296. mapping->setown(newstr);
  297. }
  298. }
  299. else
  300. properties.setValue(propname, val);
  301. }
  302. }
  303. virtual bool removeProp(PTYPE propname)
  304. {
  305. if (propname)
  306. return properties.remove(propname);
  307. return false;
  308. }
  309. virtual bool hasProp(PTYPE propname) const override
  310. {
  311. if (propname)
  312. {
  313. StringAttr * match = properties.getValue(propname);
  314. if (match)
  315. return true;
  316. }
  317. return false;
  318. }
  319. // serializable impl.
  320. virtual void serialize(MemoryBuffer &tgt)
  321. {
  322. HashIterator it(properties);
  323. tgt.append((unsigned) properties.count());
  324. it.first();
  325. while (it.isValid())
  326. {
  327. IMapping &cur = it.query();
  328. PTYPE key = toKeyVal(cur.getKey());
  329. StringAttr &attr = * (StringAttr *) properties.getValue(key);
  330. char_ptr cp = fromPType(key);
  331. tgt.append((size32_t) strlen(cp)+1);
  332. tgt.append(cp);
  333. tgt.append(attr);
  334. it.next();
  335. }
  336. }
  337. virtual void deserialize(MemoryBuffer &src)
  338. {
  339. unsigned count;
  340. src.read(count);
  341. for (; count>0; count--)
  342. {
  343. char *key;
  344. StringAttr value;
  345. size32_t sz;
  346. src.read(sz);
  347. key = (char *) alloca(sz);
  348. src.read(sz, key);
  349. src.read(value);
  350. PTYPE ptype = toPType(key);
  351. setProp(ptype, value);
  352. }
  353. }
  354. virtual IPROPITER *getIterator() const override
  355. {
  356. return new PROPITER(properties);
  357. }
  358. };
  359. #define MAKECPropertyOf(PHTYPE, PTYPE, MAPPING, PCLASS) \
  360. class PCLASS : public CPropertiesBase<PTYPE, MAPPING, PTYPE##IProperties, PTYPE##IPropertyIterator, PTYPE##PropertyIterator> \
  361. { \
  362. public: \
  363. PCLASS(const char *filename, bool nocase) : CPropertiesBase<PTYPE, MAPPING, PTYPE##IProperties, PTYPE##IPropertyIterator, PTYPE##PropertyIterator>(nocase) { loadFile(filename); } \
  364. PCLASS(bool nocase) : CPropertiesBase<PTYPE, MAPPING, PTYPE##IProperties, PTYPE##IPropertyIterator, PTYPE##PropertyIterator>(nocase) { } \
  365. virtual PTYPE toPType(const char *p) const override { return conv2##PTYPE(p); } \
  366. virtual const char *fromPType(PTYPE p) const override { return conv##PTYPE##2(p); } \
  367. virtual PTYPE toKeyVal(const void *p) const override { return tokv##PTYPE(p); } \
  368. };
  369. typedef IProperties char_ptrIProperties;
  370. MAKECPropertyOf(Atom, char_ptr, StringAttrMapping, CProperties);
  371. extern jlib_decl IProperties *createProperties(bool nocase)
  372. {
  373. return new CProperties(nocase);
  374. }
  375. extern jlib_decl IProperties *createProperties(const char *filename, bool nocase)
  376. {
  377. if (filename)
  378. return new CProperties(filename, nocase);
  379. else
  380. return new CProperties(nocase);
  381. }
  382. static CProperties *sysProps = NULL;
  383. extern jlib_decl IProperties *querySystemProperties()
  384. {
  385. if (!sysProps)
  386. {
  387. sysProps = new CProperties(false);
  388. sysProps->loadSystem();
  389. }
  390. return sysProps;
  391. }
  392. extern jlib_decl IProperties *getSystemProperties()
  393. {
  394. IProperties *p = querySystemProperties();
  395. p->Link();
  396. return p;
  397. }
  398. MODULE_INIT(INIT_PRIORITY_JPROP)
  399. {
  400. return true;
  401. }
  402. MODULE_EXIT()
  403. {
  404. ::Release(sysProps);
  405. }