aboutsummaryrefslogtreecommitdiff
path: root/Src/Wasabi/api/config/config.cpp
diff options
context:
space:
mode:
authorJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
committerJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
commit20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch)
tree12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/Wasabi/api/config/config.cpp
parent537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff)
downloadwinamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz
Initial community commit
Diffstat (limited to 'Src/Wasabi/api/config/config.cpp')
-rw-r--r--Src/Wasabi/api/config/config.cpp329
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());
+}