diff options
author | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
---|---|---|
committer | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
commit | 20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch) | |
tree | 12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/Wasabi/api/config/config.cpp | |
parent | 537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff) | |
download | winamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz |
Initial community commit
Diffstat (limited to 'Src/Wasabi/api/config/config.cpp')
-rw-r--r-- | Src/Wasabi/api/config/config.cpp | 329 |
1 files changed, 329 insertions, 0 deletions
diff --git a/Src/Wasabi/api/config/config.cpp b/Src/Wasabi/api/config/config.cpp new file mode 100644 index 00000000..3b45d934 --- /dev/null +++ b/Src/Wasabi/api/config/config.cpp @@ -0,0 +1,329 @@ +#include <precomp.h> + +#include "config.h" +#include <bfc/pair.h> +#include <bfc/ptrlist.h> +#include <bfc/parse/pathparse.h> +#include <api/xml/xmlwrite.h> + +#include "../xml/ifc_xmlreadercallbackI.h" +#include "../xml/obj_xml.h" +#include <bfc/string/url.h> +#include <api/service/waservicefactory.h> + +static StringW iniFile; +#define XNFNAME L"studio.xnf" + +class StringPairCompare +{ +public: + static int compareItem(StringPair *p1, StringPair *p2) + { + int r = wcscmp(p1->a.getValue(), p2->a.getValue()); + if (r == 0) + return CMP3(p1, p2); + else + return r; + } + static int compareAttrib(const wchar_t *attrib, StringPair *item) + { + return wcscmp(attrib, item->a.getValue()); + } +}; + +static PtrListQuickSorted<StringPair, StringPairCompare> strings; + +class Reader : public ifc_xmlreadercallbackI +{ +public: + ~Reader(); + void xmlReaderOnStartElementCallback(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params); + void xmlReaderOnEndElementCallback(const wchar_t *xmlpath, const wchar_t *xmltag); + + void readem(); + +private: + PtrList<StringW> sections; +}; + +Reader::~Reader() +{ + sections.deleteAll(); +} + +void Reader::xmlReaderOnStartElementCallback(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params) +{ + if (!WCSICMP(xmltag, L"section")) + { + const wchar_t *name = params->getItemValue(L"name"); + if (name == NULL) + return ; + + StringW *strName = new StringW(name); + Url::decode(*strName); + sections.addItem(strName); + } + else if (!WCSICMP(xmltag, L"entry")) + { + const wchar_t *name = params->getItemValue(L"name"); + const wchar_t *value = params->getItemValue(L"value"); + + // just in case + if (!WCSICMP(name, L"(null)")) name = NULL; + if (!WCSICMP(value, L"(null)")) value = NULL; + + if (name == NULL /*| !*name */ || value == NULL /*|| !*value*/) return ; + StringW strName = name; + Url::decode(strName); + + StringW strValue = value; + Url::decode(strValue); + + StringW n; + for (int i = 0; i < sections.getNumItems(); i++) + { + n.catPostSeparator(*sections[i], '/'); + } + n += strName; + + StringPair *p = new StringPair(n, strValue); + strings.addItem(p); + } +} + +void Reader::xmlReaderOnEndElementCallback(const wchar_t *xmlpath, const wchar_t *xmltag) +{ + if (!WCSICMP(xmltag, L"section")) + { + StringW *last = sections.getLast(); + sections.removeLastItem(); + delete last; + } +} + +void LoadXmlFile(obj_xml *parser, const wchar_t *filename); + +void Reader::readem() +{ + strings.deleteAll(); + + if (iniFile.isempty()) + { + iniFile = StringPathCombine(WASABI_API_APP->path_getUserSettingsPath(), XNFNAME); + } + + waServiceFactory *parserFactory = WASABI_API_SVC->service_getServiceByGuid(obj_xmlGUID); + if (parserFactory) + { + obj_xml *parser = (obj_xml *)parserFactory->getInterface(); + + if (parser) + { + + parser->xmlreader_registerCallback(L"WinampXML\fconfiguration\f*", this); + parser->xmlreader_registerCallback(L"WasabiXML\fconfiguration\f*", this); + parser->xmlreader_open(); + LoadXmlFile(parser, iniFile); + + parser->xmlreader_unregisterCallback(this); + parser->xmlreader_close(); + parserFactory->releaseInterface(parser); + parser = 0; + } + } +} + +StringPair *ConfigFile::getPair(const wchar_t *name) +{ + ASSERT(!sectionname.isempty()); + StringW nname; + nname.catPostSeparator(sectionname.getValue(), '/'); + nname.cat(name); + return strings.findItem(nname.getValue()); // cast to make PtrListSorted happy +} + +StringPair *ConfigFile::makePair(const wchar_t *name, const wchar_t *value) +{ + StringPair *ret = getPair(name); + if (ret == NULL) + { + StringW nname; + nname.catPostSeparator(sectionname.getValue(), '/'); + nname.cat(name); + + ret = new StringPair(nname, value); + strings.addItem(ret); + } + else + { + ret->b.setValue(value); + } + return ret; +} + +static int ninstances, inited; + +ConfigFile::ConfigFile(const wchar_t *section, const wchar_t *name) +{ + sectionname = section; + prettyname = name; + ninstances++; +} + +void ConfigFile::initialize() +{ + Reader().readem(); +} + +ConfigFile::~ConfigFile() +{ + ninstances--; + if (ninstances == 0) + { + FILE *fp = _wfopen(iniFile, WF_WRITE_TEXT); + if (fp != NULL) + { + // write out the file + XMLWrite xml(fp, L"WasabiXML"); + const wchar_t *app = WASABI_API_APP->main_getVersionString(); + if (!app) + app = L"thousands of irascible butt monkeys"; + xml.comment(StringPrintfW(L"Generated by: %s (%d)", app, WASABI_API_APP->main_getBuildNumber())); + xml.pushCategory(L"configuration"); + + PtrList<StringW> cats; + + for (int i = 0; i < strings.getNumItems(); i++) + { + StringPair *p = strings[i]; + PathParserW pp(p->a); + + int climit = MIN(pp.getNumStrings() - 1, cats.getNumItems()); + int j; + for (j = 0; j < climit; j++) + { + if (WCSICMP(*cats[j], pp.enumString(j))) + { + climit = j; + break; + } + } + + while (cats.getNumItems() > climit) + { + StringW *s = cats.getLast(); + xml.popCategory(); + cats.removeLastItem(); + delete s; + } + for (j = climit; j < pp.getNumStrings() - 1; j++) + { + StringW *s = cats.addItem(new StringW(pp.enumString(j))); + xml.pushCategoryAttrib(L"section"); + StringW enc = *s; + Url::encode(enc, FALSE, URLENCODE_EXCLUDE_ABOVEEQ32); + xml.writeCategoryAttrib(L"name", enc); + xml.closeCategoryAttrib(); + } + + xml.pushCategoryAttrib(L"entry", TRUE); + StringW enc = pp.getLastString(); + Url::encode(enc, FALSE, URLENCODE_EXCLUDE_ABOVEEQ32); + xml.writeCategoryAttrib(L"name", enc); + enc = p->b; + Url::encode(enc, FALSE, URLENCODE_EXCLUDE_ABOVEEQ32); + if (enc.iscaseequal(L"(null)") || enc.getValue() == NULL) + enc.setValue(L""); + xml.writeCategoryAttrib(L"value", enc); + xml.closeCategoryAttrib(); + xml.popCategory(); + } + + while (xml.popCategory()) ; + + strings.deleteAll(); + fclose(fp); + } // fp != NULL + } // ninstances==0 +} + +int verifyName(const wchar_t *str) +{ + for (const wchar_t *p = str; *p; p++) + { + if (!ISALPHA(*p) && + !ISDIGIT(*p) && + !ISPUNCT(*p) && + !ISSPACE(*p) && + *p != '|' && *p != '_') + return 0; + } + return 1; +} + +void ConfigFile::setInt(const wchar_t *name, int val) +{ + INCRITICALSECTION(cs); + if (name == NULL) return ; + if (!verifyName(name)) + { + DebugStringW(L"illegal name given\n"); + //__asm { int 3 }; + return ; + } + makePair(name, StringPrintfW(val)); +} + +int ConfigFile::getInt(const wchar_t *name, int def_val) +{ + INCRITICALSECTION(cs); + if (name == NULL) return def_val; + StringPair *p = getPair(name); + if (p == NULL) return def_val; + return WTOI(p->b.getValue()); +} + +void ConfigFile::setString(const wchar_t *name, const wchar_t *str) +{ + INCRITICALSECTION(cs); + if (name == NULL) return ; + if (!verifyName(name)) + { + DebugStringW(L"illegal name given\n"); + return ; + } + if (str == NULL) + { + StringPair *p = getPair(name); + if (p != NULL) + { + strings.delItem(p); + delete p; + return ; + } + } + makePair(name, str); +} + +int ConfigFile::getString(const wchar_t *name, wchar_t *buf, int buf_len, const wchar_t *def_str) +{ + INCRITICALSECTION(cs); + if (name == NULL || buf == NULL) return -1; + if (def_str == NULL) + def_str = L""; + StringPair *p = getPair(name); + if (p == NULL) + WCSCPYN(buf, def_str, buf_len); + else + WCSCPYN(buf, p->b.getValueSafe(), buf_len); + return 1; +} + +int ConfigFile::getStringLen(const wchar_t *name) +{ + INCRITICALSECTION(cs); + if (name == NULL) return -1; + StringPair *p = getPair(name); + if (p == NULL) return -1; + return wcslen(p->b.getValue()); +} |