123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432 |
- /*##############################################################################
- HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems®.
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ############################################################################## */
- #include "jiface.hpp"
- #include "jprop.hpp"
- #include "jhash.hpp"
- #include "jhash.ipp"
- #include "jexcept.hpp"
- #include "jiter.ipp"
- #include "jregexp.hpp"
- #include <stdio.h>
- #ifdef _WIN32
- #include <stdlib.h>
- #elif defined(__linux__) || defined(__FreeBSD__)
- extern char **environ;
- #endif
- #if defined(__APPLE__)
- #include <crt_externs.h>
- #endif
- const char *conv2char_ptr(const char *p) { return p; }
- const char *convchar_ptr2(const char *p) { return p; }
- const char *tokvchar_ptr(const void *p) { return (const char *)p; }
- template <class PTYPE, class PITER>
- class PropertyIteratorOf : implements PITER, public CInterface
- {
- protected:
- HashIterator *piter;
- const HashTable &properties;
- public:
- IMPLEMENT_IINTERFACE;
- PropertyIteratorOf(const HashTable &_properties) : properties(_properties)
- {
- properties.Link();
- piter = new HashIterator(properties);
- }
- ~PropertyIteratorOf()
- {
- properties.Release();
- piter->Release();
- }
- virtual bool first()
- {
- return piter->first();
- }
- virtual bool next()
- {
- return piter->next();
- }
- virtual bool isValid()
- {
- return piter->isValid();
- }
- virtual PTYPE getPropKey() = 0;
- };
- typedef IPropertyIterator char_ptrIPropertyIterator;
- class char_ptrPropertyIterator : public PropertyIteratorOf<const char *, char_ptrIPropertyIterator>
- {
- public:
- char_ptrPropertyIterator(const HashTable &_properties) : PropertyIteratorOf<const char *, char_ptrIPropertyIterator>(_properties) { }
- virtual const char *getPropKey()
- {
- IMapping &cur = piter->query();
- const char *key = (const char *) (cur.getKey());
- return key;
- }
- };
- template <class PTYPE, class MAPPING, class IPROP, class IPROPITER, class PROPITER>
- class CPropertiesBase : implements IPROP, public CInterface
- {
- private:
- MAPPING properties;
- public:
- IMPLEMENT_IINTERFACE;
- CPropertiesBase(bool nocase) : properties(nocase)
- {
- }
- virtual ~CPropertiesBase()
- {
- properties.kill();
- }
- void loadProp(const char *finger)
- {
- StringBuffer prop, val;
- while (*finger && *finger != '=')
- prop.append(*finger++);
- if (*finger)
- {
- finger++;
- while (isspace(*finger))
- finger++;
- while (*finger)
- val.append(*finger++);
- prop.clip();
- val.clip();
- if (prop.length())
- setProp(toPType(prop.str()), val.str());
- }
- }
- void loadProp(const char *finger, int dft)
- {
- if (strchr(finger, '='))
- loadProp(finger);
- else
- setProp(toPType(finger), dft);
- }
- void loadProp(const char *finger, bool dft)
- {
- if (strchr(finger, '='))
- loadProp(finger);
- else
- setProp(toPType(finger), dft);
- }
- void loadProp(const char *finger, const char * dft)
- {
- if (strchr(finger, '='))
- loadProp(finger);
- else
- setProp(toPType(finger), dft);
- }
- void loadSystem()
- {
- #ifdef _WIN32
- char **e = _environ;
- #else
- #if defined (__APPLE__)
- char **e = *_NSGetEnviron();
- #else
- char **e = environ;
- #endif
- #endif
- while (*e)
- {
- loadProp (*e);
- e++;
- }
- }
- void loadFile(const char *filename)
- {
- FILE *inFile = fopen(filename, "r" TEXT_TRANS);
- if (inFile)
- {
- StringBuffer sbuff;
- char buf[1024];
- while (fgets(buf,1024,inFile))
- {
- sbuff.clear();
- do // handle lines longer than 1024 (bit kludgy)
- {
- size32_t l=(size32_t)strlen(buf);
- if (!l || (buf[l-1]=='\n')) // should end in \n unless overflowed
- break;
- sbuff.append(buf);
- } while (fgets(buf,1024,inFile));
- const char *s=buf;
- if (sbuff.length())
- s = sbuff.append(buf).str();
- if (*s == '#')
- continue;
- char *comment = (char *) strstr(s, "#");
- if (comment != NULL)
- *comment = 0;
- loadProp(s);
- sbuff.setLength(0);
- }
- fclose(inFile);
- }
- }
- void loadProps(const char *finger)
- {
- while (*finger)
- {
- StringBuffer prop, val;
- while (*finger && *finger != '\n' && *finger != '=')
- prop.append(*finger++);
- if (*finger && *finger != '\n')
- {
- finger++;
- while (isspace(*finger) && *finger != '\n')
- finger++;
- while (*finger && *finger != '\n')
- val.append(*finger++);
- prop.clip();
- val.clip();
- if (prop.length())
- setProp(toPType(prop.str()), val.str());
- }
- if (*finger)
- finger++;
- }
- }
- virtual PTYPE toPType(const char *p) const = 0;
- virtual const char *fromPType(PTYPE p) const = 0;
- virtual PTYPE toKeyVal(const void *) const = 0;
- virtual int getPropInt(PTYPE propname, int dft) const override
- {
- if (propname)
- {
- const char *val = queryProp(propname);
- if (val)
- return (int)_atoi64(val);
- }
- return dft;
- }
- virtual bool getPropBool(PTYPE propname, bool dft) const override
- {
- if (propname)
- {
- const char *val = queryProp(propname);
- if (val&&*val)
- return strToBool(val);
- }
- return dft;
- }
- virtual bool getProp(PTYPE propname, StringBuffer &ret) const override
- {
- if (propname)
- {
- StringAttr * match = properties.getValue(propname);
- if (match)
- {
- ret.append(*match);
- return true;
- }
- }
- return false;
- }
- virtual const char *queryProp(PTYPE propname) const override
- {
- if (propname)
- {
- StringAttr * match = properties.getValue(propname);
- if (match)
- return(*match);
- }
- return NULL;
- }
- virtual void saveFile(const char *filename) const override
- {
- FILE *outFile = fopen(filename, "w" TEXT_TRANS);
- if (outFile)
- {
- HashIterator it(properties);
- StringBuffer line;
- for (it.first();it.isValid();it.next())
- {
- IMapping &cur = it.query();
- PTYPE key = toKeyVal(cur.getKey());
- StringAttr &attr = * (StringAttr *) properties.getValue(key);
- line.clear().append(key).append('=').append(attr).newline();
- fwrite(line.str(),line.length(),1,outFile);
- }
- fclose(outFile);
- }
- }
- virtual void setProp(PTYPE propname, int val)
- {
- char buf[15];
- sprintf(buf, "%d", val);
- setProp(propname, buf);
- }
- virtual void setProp(PTYPE propname, const char *val)
- {
- if (propname)
- {
- if (val)
- properties.setValue(propname, val);
- else
- properties.remove(propname);
- }
- }
- virtual void appendProp(PTYPE propname, const char *val)
- {
- if (propname && val)
- {
- StringAttr * mapping = properties.getValue(propname);
- if (mapping)
- {
- if (*val)
- {
- char * str = mapping->detach();
- size_t len1 = strlen(str);
- size_t len2 = strlen(val);
- char * newstr = (char *)realloc(str, len1 + len2+1);
- assertex(newstr);
- memcpy(newstr+len1, val, len2);
- newstr[len1+len2] = '\0';
- mapping->setown(newstr);
- }
- }
- else
- properties.setValue(propname, val);
- }
- }
- virtual bool removeProp(PTYPE propname)
- {
- if (propname)
- return properties.remove(propname);
- return false;
- }
- virtual bool hasProp(PTYPE propname) const override
- {
- if (propname)
- {
- StringAttr * match = properties.getValue(propname);
- if (match)
- return true;
- }
- return false;
- }
- // serializable impl.
- virtual void serialize(MemoryBuffer &tgt)
- {
- HashIterator it(properties);
- tgt.append((unsigned) properties.count());
- it.first();
- while (it.isValid())
- {
- IMapping &cur = it.query();
- PTYPE key = toKeyVal(cur.getKey());
- StringAttr &attr = * (StringAttr *) properties.getValue(key);
- char_ptr cp = fromPType(key);
- tgt.append((size32_t) strlen(cp)+1);
- tgt.append(cp);
- tgt.append(attr);
- it.next();
- }
- }
- virtual void deserialize(MemoryBuffer &src)
- {
- unsigned count;
- src.read(count);
- for (; count>0; count--)
- {
- char *key;
- StringAttr value;
- size32_t sz;
- src.read(sz);
- key = (char *) alloca(sz);
- src.read(sz, key);
- src.read(value);
- PTYPE ptype = toPType(key);
- setProp(ptype, value);
- }
- }
- virtual IPROPITER *getIterator() const override
- {
- return new PROPITER(properties);
- }
- };
- #define MAKECPropertyOf(PHTYPE, PTYPE, MAPPING, PCLASS) \
- class PCLASS : public CPropertiesBase<PTYPE, MAPPING, PTYPE##IProperties, PTYPE##IPropertyIterator, PTYPE##PropertyIterator> \
- { \
- public: \
- PCLASS(const char *filename, bool nocase) : CPropertiesBase<PTYPE, MAPPING, PTYPE##IProperties, PTYPE##IPropertyIterator, PTYPE##PropertyIterator>(nocase) { loadFile(filename); } \
- PCLASS(bool nocase) : CPropertiesBase<PTYPE, MAPPING, PTYPE##IProperties, PTYPE##IPropertyIterator, PTYPE##PropertyIterator>(nocase) { } \
- virtual PTYPE toPType(const char *p) const override { return conv2##PTYPE(p); } \
- virtual const char *fromPType(PTYPE p) const override { return conv##PTYPE##2(p); } \
- virtual PTYPE toKeyVal(const void *p) const override { return tokv##PTYPE(p); } \
- };
- typedef IProperties char_ptrIProperties;
- MAKECPropertyOf(Atom, char_ptr, StringAttrMapping, CProperties);
- extern jlib_decl IProperties *createProperties(bool nocase)
- {
- return new CProperties(nocase);
- }
- extern jlib_decl IProperties *createProperties(const char *filename, bool nocase)
- {
- if (filename)
- return new CProperties(filename, nocase);
- else
- return new CProperties(nocase);
- }
- static CProperties *sysProps = NULL;
- extern jlib_decl IProperties *querySystemProperties()
- {
- if (!sysProps)
- {
- sysProps = new CProperties(false);
- sysProps->loadSystem();
- }
- return sysProps;
- }
- extern jlib_decl IProperties *getSystemProperties()
- {
- IProperties *p = querySystemProperties();
- p->Link();
- return p;
- }
- MODULE_INIT(INIT_PRIORITY_JPROP)
- {
- return true;
- }
- MODULE_EXIT()
- {
- ::Release(sysProps);
- }
|