2022-02-18 18:11:04 +00:00
|
|
|
/**
|
|
|
|
* Furnace Tracker - multi-system chiptune tracker
|
2023-01-20 00:18:40 +00:00
|
|
|
* Copyright (C) 2021-2023 tildearrow and contributors
|
2022-02-18 18:11:04 +00:00
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License along
|
|
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
|
|
*/
|
|
|
|
|
2022-09-29 06:24:26 +00:00
|
|
|
#include "config.h"
|
2022-02-18 18:11:04 +00:00
|
|
|
#include "../ta-log.h"
|
2022-11-13 21:25:50 +00:00
|
|
|
#include "../baseutils.h"
|
2022-02-18 18:11:04 +00:00
|
|
|
#include "../fileutils.h"
|
|
|
|
#include <fmt/printf.h>
|
|
|
|
|
2022-09-29 06:24:26 +00:00
|
|
|
bool DivConfig::save(const char* path) {
|
|
|
|
FILE* f=ps_fopen(path,"wb");
|
2022-02-18 18:11:04 +00:00
|
|
|
if (f==NULL) {
|
2022-04-11 03:12:02 +00:00
|
|
|
logW("could not write config file! %s",strerror(errno));
|
2022-02-18 18:11:04 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
for (auto& i: conf) {
|
|
|
|
String toWrite=fmt::sprintf("%s=%s\n",i.first,i.second);
|
|
|
|
if (fwrite(toWrite.c_str(),1,toWrite.size(),f)!=toWrite.size()) {
|
2022-04-11 03:12:02 +00:00
|
|
|
logW("could not write config file! %s",strerror(errno));
|
2022-02-18 18:11:04 +00:00
|
|
|
fclose(f);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fclose(f);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2022-09-29 08:19:48 +00:00
|
|
|
String DivConfig::toString() {
|
|
|
|
String ret;
|
|
|
|
for (auto& i: conf) {
|
|
|
|
ret+=fmt::sprintf("%s=%s\n",i.first,i.second);
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2022-09-30 01:13:40 +00:00
|
|
|
String DivConfig::toBase64() {
|
|
|
|
String data=toString();
|
2022-11-13 21:25:50 +00:00
|
|
|
return taEncodeBase64(data);
|
2022-09-30 01:13:40 +00:00
|
|
|
}
|
|
|
|
|
2022-12-22 18:10:08 +00:00
|
|
|
const std::map<String,String>& DivConfig::configMap() {
|
|
|
|
return conf;
|
|
|
|
}
|
|
|
|
|
2022-09-29 08:19:48 +00:00
|
|
|
void DivConfig::parseLine(const char* line) {
|
|
|
|
String key="";
|
|
|
|
String value="";
|
|
|
|
bool keyOrValue=false;
|
|
|
|
for (const char* i=line; *i; i++) {
|
|
|
|
if (*i=='\n') continue;
|
|
|
|
if (keyOrValue) {
|
|
|
|
value+=*i;
|
|
|
|
} else {
|
|
|
|
if (*i=='=') {
|
|
|
|
keyOrValue=true;
|
|
|
|
} else {
|
|
|
|
key+=*i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (keyOrValue) {
|
|
|
|
conf[key]=value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-29 06:24:26 +00:00
|
|
|
bool DivConfig::loadFromFile(const char* path, bool createOnFail) {
|
2022-02-18 18:11:04 +00:00
|
|
|
char line[4096];
|
2022-09-29 06:24:26 +00:00
|
|
|
FILE* f=ps_fopen(path,"rb");
|
2022-02-18 18:11:04 +00:00
|
|
|
if (f==NULL) {
|
2022-09-29 08:19:48 +00:00
|
|
|
if (createOnFail) {
|
|
|
|
logI("creating default config.");
|
|
|
|
return save(path);
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
2022-02-18 18:11:04 +00:00
|
|
|
}
|
2022-04-11 03:12:02 +00:00
|
|
|
logI("loading config.");
|
2022-02-18 18:11:04 +00:00
|
|
|
while (!feof(f)) {
|
|
|
|
if (fgets(line,4095,f)==NULL) {
|
|
|
|
break;
|
|
|
|
}
|
2022-09-29 08:19:48 +00:00
|
|
|
parseLine(line);
|
2022-02-18 18:11:04 +00:00
|
|
|
}
|
|
|
|
fclose(f);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2022-09-29 08:19:48 +00:00
|
|
|
bool DivConfig::loadFromMemory(const char* buf) {
|
|
|
|
String line;
|
|
|
|
const char* readPos=buf;
|
|
|
|
while (*readPos) {
|
|
|
|
line+=*readPos;
|
|
|
|
readPos++;
|
|
|
|
if ((*readPos)=='\n' || (*readPos)==0) {
|
|
|
|
parseLine(line.c_str());
|
|
|
|
line="";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2022-09-30 01:13:40 +00:00
|
|
|
bool DivConfig::loadFromBase64(const char* buf) {
|
2022-11-13 21:25:50 +00:00
|
|
|
String data=taDecodeBase64(buf);
|
2022-09-30 01:13:40 +00:00
|
|
|
return loadFromMemory(data.c_str());
|
|
|
|
}
|
|
|
|
|
|
|
|
bool DivConfig::getBool(String key, bool fallback) const {
|
2022-02-18 18:11:04 +00:00
|
|
|
try {
|
|
|
|
String val=conf.at(key);
|
|
|
|
if (val=="true") {
|
|
|
|
return true;
|
|
|
|
} else if (val=="false") {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
} catch (std::out_of_range& e) {
|
|
|
|
}
|
|
|
|
return fallback;
|
|
|
|
}
|
|
|
|
|
2022-09-30 01:13:40 +00:00
|
|
|
int DivConfig::getInt(String key, int fallback) const {
|
2022-02-18 18:11:04 +00:00
|
|
|
try {
|
|
|
|
String val=conf.at(key);
|
|
|
|
int ret=std::stoi(val);
|
|
|
|
return ret;
|
|
|
|
} catch (std::out_of_range& e) {
|
|
|
|
} catch (std::invalid_argument& e) {
|
|
|
|
}
|
|
|
|
return fallback;
|
|
|
|
}
|
|
|
|
|
2022-09-30 01:13:40 +00:00
|
|
|
float DivConfig::getFloat(String key, float fallback) const {
|
2022-02-18 18:11:04 +00:00
|
|
|
try {
|
|
|
|
String val=conf.at(key);
|
|
|
|
float ret=std::stof(val);
|
|
|
|
return ret;
|
|
|
|
} catch (std::out_of_range& e) {
|
|
|
|
} catch (std::invalid_argument& e) {
|
|
|
|
}
|
|
|
|
return fallback;
|
|
|
|
}
|
|
|
|
|
2022-09-30 01:13:40 +00:00
|
|
|
double DivConfig::getDouble(String key, double fallback) const {
|
2022-02-18 18:11:04 +00:00
|
|
|
try {
|
|
|
|
String val=conf.at(key);
|
|
|
|
double ret=std::stod(val);
|
|
|
|
return ret;
|
|
|
|
} catch (std::out_of_range& e) {
|
|
|
|
} catch (std::invalid_argument& e) {
|
|
|
|
}
|
|
|
|
return fallback;
|
|
|
|
}
|
|
|
|
|
2022-09-30 01:13:40 +00:00
|
|
|
String DivConfig::getString(String key, String fallback) const {
|
2022-02-18 18:11:04 +00:00
|
|
|
try {
|
|
|
|
String val=conf.at(key);
|
|
|
|
return val;
|
|
|
|
} catch (std::out_of_range& e) {
|
|
|
|
}
|
|
|
|
return fallback;
|
|
|
|
}
|
|
|
|
|
2023-02-10 22:55:44 +00:00
|
|
|
bool DivConfig::has(String key) const {
|
2022-12-22 18:10:08 +00:00
|
|
|
try {
|
2022-12-22 20:40:10 +00:00
|
|
|
String test=conf.at(key);
|
2022-12-22 18:10:08 +00:00
|
|
|
} catch (std::out_of_range& e) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2022-09-29 23:03:39 +00:00
|
|
|
void DivConfig::set(String key, bool value) {
|
2022-02-18 18:11:04 +00:00
|
|
|
if (value) {
|
|
|
|
conf[key]="true";
|
|
|
|
} else {
|
|
|
|
conf[key]="false";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-29 23:03:39 +00:00
|
|
|
void DivConfig::set(String key, int value) {
|
2022-02-18 18:11:04 +00:00
|
|
|
conf[key]=fmt::sprintf("%d",value);
|
|
|
|
}
|
|
|
|
|
2022-09-29 23:03:39 +00:00
|
|
|
void DivConfig::set(String key, float value) {
|
2022-02-18 18:11:04 +00:00
|
|
|
conf[key]=fmt::sprintf("%f",value);
|
|
|
|
}
|
|
|
|
|
2022-09-29 23:03:39 +00:00
|
|
|
void DivConfig::set(String key, double value) {
|
2022-02-18 18:11:04 +00:00
|
|
|
conf[key]=fmt::sprintf("%f",value);
|
|
|
|
}
|
|
|
|
|
2022-09-29 23:03:39 +00:00
|
|
|
void DivConfig::set(String key, const char* value) {
|
2022-09-10 23:53:27 +00:00
|
|
|
conf[key]=String(value);
|
|
|
|
}
|
|
|
|
|
2022-09-29 23:03:39 +00:00
|
|
|
void DivConfig::set(String key, String value) {
|
2022-02-18 18:11:04 +00:00
|
|
|
conf[key]=value;
|
|
|
|
}
|
2022-09-29 23:03:39 +00:00
|
|
|
|
|
|
|
bool DivConfig::remove(String key) {
|
|
|
|
return conf.erase(key);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DivConfig::clear() {
|
|
|
|
conf.clear();
|
|
|
|
}
|