| 
									
										
										
										
											2022-02-18 13:11:04 -05:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * Furnace Tracker - multi-system chiptune tracker | 
					
						
							| 
									
										
										
										
											2024-01-16 21:26:57 -05:00
										 |  |  |  * Copyright (C) 2021-2024 tildearrow and contributors | 
					
						
							| 
									
										
										
										
											2022-02-18 13:11:04 -05: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 02:24:26 -04:00
										 |  |  | #include "config.h"
 | 
					
						
							| 
									
										
										
										
											2022-02-18 13:11:04 -05:00
										 |  |  | #include "../ta-log.h"
 | 
					
						
							| 
									
										
										
										
											2022-11-13 16:25:50 -05:00
										 |  |  | #include "../baseutils.h"
 | 
					
						
							| 
									
										
										
										
											2022-02-18 13:11:04 -05:00
										 |  |  | #include "../fileutils.h"
 | 
					
						
							|  |  |  | #include <fmt/printf.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-05 05:44:21 -04:00
										 |  |  | #define REDUNDANCY_NUM_ATTEMPTS 5
 | 
					
						
							|  |  |  | #define CHECK_BUF_SIZE 8192
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool DivConfig::save(const char* path, bool redundancy) { | 
					
						
							| 
									
										
										
										
											2023-04-05 18:35:01 -04:00
										 |  |  |   if (redundancy) { | 
					
						
							|  |  |  |     char oldPath[4096]; | 
					
						
							|  |  |  |     char newPath[4096]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (fileExists(path)==1) { | 
					
						
							|  |  |  |       logD("rotating config files..."); | 
					
						
							|  |  |  |       for (int i=4; i>=0; i--) { | 
					
						
							|  |  |  |         if (i>0) { | 
					
						
							|  |  |  |           snprintf(oldPath,4095,"%s.%d",path,i); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |           strncpy(oldPath,path,4095); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         snprintf(newPath,4095,"%s.%d",path,i+1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (i>=4) { | 
					
						
							|  |  |  |           logV("remove %s",oldPath); | 
					
						
							|  |  |  |           deleteFile(oldPath); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |           logV("move %s to %s",oldPath,newPath); | 
					
						
							|  |  |  |           moveFiles(oldPath,newPath); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2023-04-04 16:27:36 -04:00
										 |  |  |   logD("opening config for write: %s",path); | 
					
						
							| 
									
										
										
										
											2022-09-29 02:24:26 -04:00
										 |  |  |   FILE* f=ps_fopen(path,"wb"); | 
					
						
							| 
									
										
										
										
											2022-02-18 13:11:04 -05:00
										 |  |  |   if (f==NULL) { | 
					
						
							| 
									
										
										
										
											2022-04-10 23:12:02 -04:00
										 |  |  |     logW("could not write config file! %s",strerror(errno)); | 
					
						
							| 
									
										
										
										
											2023-04-04 16:27:36 -04:00
										 |  |  |     reportError(fmt::sprintf("could not write config file! %s",strerror(errno))); | 
					
						
							| 
									
										
										
										
											2022-02-18 13:11:04 -05: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-10 23:12:02 -04:00
										 |  |  |       logW("could not write config file! %s",strerror(errno)); | 
					
						
							| 
									
										
										
										
											2023-04-04 16:27:36 -04:00
										 |  |  |       reportError(fmt::sprintf("could not write config file! %s",strerror(errno))); | 
					
						
							| 
									
										
										
										
											2023-04-05 18:35:01 -04:00
										 |  |  |       logV("removing config file"); | 
					
						
							| 
									
										
										
										
											2022-02-18 13:11:04 -05:00
										 |  |  |       fclose(f); | 
					
						
							| 
									
										
										
										
											2023-04-05 18:35:01 -04:00
										 |  |  |       deleteFile(path); | 
					
						
							| 
									
										
										
										
											2022-02-18 13:11:04 -05:00
										 |  |  |       return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   fclose(f); | 
					
						
							| 
									
										
										
										
											2023-04-04 16:27:36 -04:00
										 |  |  |   logD("config file written successfully."); | 
					
						
							| 
									
										
										
										
											2022-02-18 13:11:04 -05:00
										 |  |  |   return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-29 04:19:48 -04:00
										 |  |  | String DivConfig::toString() { | 
					
						
							|  |  |  |   String ret; | 
					
						
							|  |  |  |   for (auto& i: conf) { | 
					
						
							|  |  |  |     ret+=fmt::sprintf("%s=%s\n",i.first,i.second); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-29 21:13:40 -04:00
										 |  |  | String DivConfig::toBase64() { | 
					
						
							|  |  |  |   String data=toString(); | 
					
						
							| 
									
										
										
										
											2022-11-13 16:25:50 -05:00
										 |  |  |   return taEncodeBase64(data); | 
					
						
							| 
									
										
										
										
											2022-09-29 21:13:40 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-22 13:10:08 -05:00
										 |  |  | const std::map<String,String>& DivConfig::configMap() { | 
					
						
							|  |  |  |   return conf; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-29 04:19:48 -04:00
										 |  |  | void DivConfig::parseLine(const char* line) { | 
					
						
							|  |  |  |   String key=""; | 
					
						
							|  |  |  |   String value=""; | 
					
						
							|  |  |  |   bool keyOrValue=false; | 
					
						
							|  |  |  |   for (const char* i=line; *i; i++) { | 
					
						
							| 
									
										
										
										
											2023-04-04 16:40:01 -04:00
										 |  |  |     if (*i=='\r') continue; | 
					
						
							| 
									
										
										
										
											2023-04-04 17:24:08 -04:00
										 |  |  |     if (*i=='\n') continue; | 
					
						
							| 
									
										
										
										
											2022-09-29 04:19:48 -04:00
										 |  |  |     if (keyOrValue) { | 
					
						
							|  |  |  |       value+=*i; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       if (*i=='=') { | 
					
						
							|  |  |  |         keyOrValue=true; | 
					
						
							|  |  |  |       } else { | 
					
						
							|  |  |  |         key+=*i; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   if (keyOrValue) { | 
					
						
							|  |  |  |     conf[key]=value; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-05 05:44:21 -04:00
										 |  |  | bool DivConfig::loadFromFile(const char* path, bool createOnFail, bool redundancy) { | 
					
						
							| 
									
										
										
										
											2022-02-18 13:11:04 -05:00
										 |  |  |   char line[4096]; | 
					
						
							| 
									
										
										
										
											2023-04-04 16:27:36 -04:00
										 |  |  |   logD("opening config for read: %s",path); | 
					
						
							| 
									
										
										
										
											2023-04-05 05:44:21 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |   FILE* f=NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (redundancy) { | 
					
						
							|  |  |  |     unsigned char* readBuf=new unsigned char[CHECK_BUF_SIZE]; | 
					
						
							|  |  |  |     size_t readBufLen=0; | 
					
						
							|  |  |  |     for (int i=0; i<REDUNDANCY_NUM_ATTEMPTS; i++) { | 
					
						
							|  |  |  |       bool viable=false; | 
					
						
							|  |  |  |       if (i>0) { | 
					
						
							|  |  |  |         snprintf(line,4095,"%s.%d",path,i); | 
					
						
							|  |  |  |       } else { | 
					
						
							|  |  |  |         strncpy(line,path,4095); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       logV("trying: %s",line); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // try to open config
 | 
					
						
							|  |  |  |       f=ps_fopen(line,"rb"); | 
					
						
							|  |  |  |       // check whether we could open it
 | 
					
						
							|  |  |  |       if (f==NULL) { | 
					
						
							|  |  |  |         logV("fopen(): %s",strerror(errno)); | 
					
						
							|  |  |  |         continue; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // check whether there's something
 | 
					
						
							|  |  |  |       while (!feof(f)) { | 
					
						
							|  |  |  |         readBufLen=fread(readBuf,1,CHECK_BUF_SIZE,f); | 
					
						
							|  |  |  |         if (ferror(f)) { | 
					
						
							|  |  |  |           logV("fread(): %s",strerror(errno)); | 
					
						
							|  |  |  |           break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for (size_t j=0; j<readBufLen; j++) { | 
					
						
							| 
									
										
										
										
											2023-05-24 23:14:36 -04:00
										 |  |  |           if (readBuf[j]==0) { | 
					
						
							|  |  |  |             viable=false; | 
					
						
							|  |  |  |             logW("a zero?"); | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |           } | 
					
						
							| 
									
										
										
										
											2023-04-05 05:44:21 -04:00
										 |  |  |           if (readBuf[j]!='\r' && readBuf[j]!='\n' && readBuf[j]!=' ') { | 
					
						
							|  |  |  |             viable=true; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (viable) break; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // there's something
 | 
					
						
							|  |  |  |       if (viable) { | 
					
						
							|  |  |  |         if (fseek(f,0,SEEK_SET)==-1) { | 
					
						
							|  |  |  |           logV("fseek(): %s",strerror(errno)); | 
					
						
							|  |  |  |           viable=false; | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |           break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |        | 
					
						
							|  |  |  |       // close it (because there's nothing)
 | 
					
						
							|  |  |  |       fclose(f); | 
					
						
							|  |  |  |       f=NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     delete[] readBuf; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // we couldn't read at all
 | 
					
						
							|  |  |  |     if (f==NULL) { | 
					
						
							|  |  |  |       logD("config does not exist"); | 
					
						
							|  |  |  |       if (createOnFail) { | 
					
						
							|  |  |  |         logI("creating default config."); | 
					
						
							| 
									
										
										
										
											2023-04-30 20:45:54 -04:00
										 |  |  |         //reportError(fmt::sprintf("Creating default config: %s",strerror(errno)));
 | 
					
						
							| 
									
										
										
										
											2023-04-05 05:44:21 -04:00
										 |  |  |         return save(path,redundancy); | 
					
						
							|  |  |  |       } else { | 
					
						
							|  |  |  |         reportError(fmt::sprintf("COULD NOT LOAD CONFIG %s",strerror(errno))); | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } else { | 
					
						
							|  |  |  |     f=ps_fopen(path,"rb"); | 
					
						
							|  |  |  |     if (f==NULL) { | 
					
						
							|  |  |  |       logD("config does not exist"); | 
					
						
							|  |  |  |       if (createOnFail) { | 
					
						
							|  |  |  |         logI("creating default config."); | 
					
						
							| 
									
										
										
										
											2023-04-30 20:45:54 -04:00
										 |  |  |         //reportError(fmt::sprintf("Creating default config: %s",strerror(errno)));
 | 
					
						
							| 
									
										
										
										
											2023-04-05 05:44:21 -04:00
										 |  |  |         return save(path); | 
					
						
							|  |  |  |       } else { | 
					
						
							|  |  |  |         reportError(fmt::sprintf("COULD NOT LOAD CONFIG %s",strerror(errno))); | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2022-09-29 04:19:48 -04:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-02-18 13:11:04 -05:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2023-04-05 05:44:21 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-10 23:12:02 -04:00
										 |  |  |   logI("loading config."); | 
					
						
							| 
									
										
										
										
											2022-02-18 13:11:04 -05:00
										 |  |  |   while (!feof(f)) { | 
					
						
							|  |  |  |     if (fgets(line,4095,f)==NULL) { | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-09-29 04:19:48 -04:00
										 |  |  |     parseLine(line); | 
					
						
							| 
									
										
										
										
											2022-02-18 13:11:04 -05:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2023-04-04 16:40:01 -04:00
										 |  |  |   logD("end of file (%s)",strerror(errno)); | 
					
						
							| 
									
										
										
										
											2022-02-18 13:11:04 -05:00
										 |  |  |   fclose(f); | 
					
						
							|  |  |  |   return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-29 04:19:48 -04: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-29 21:13:40 -04:00
										 |  |  | bool DivConfig::loadFromBase64(const char* buf) { | 
					
						
							| 
									
										
										
										
											2022-11-13 16:25:50 -05:00
										 |  |  |   String data=taDecodeBase64(buf); | 
					
						
							| 
									
										
										
										
											2022-09-29 21:13:40 -04:00
										 |  |  |   return loadFromMemory(data.c_str()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool DivConfig::getBool(String key, bool fallback) const { | 
					
						
							| 
									
										
										
										
											2023-07-24 18:39:09 -04:00
										 |  |  |   auto val=conf.find(key); | 
					
						
							|  |  |  |   if (val!=conf.cend()) { | 
					
						
							|  |  |  |     if (val->second=="true") { | 
					
						
							| 
									
										
										
										
											2022-02-18 13:11:04 -05:00
										 |  |  |       return true; | 
					
						
							| 
									
										
										
										
											2023-07-24 18:39:09 -04:00
										 |  |  |     } else if (val->second=="false") { | 
					
						
							| 
									
										
										
										
											2022-02-18 13:11:04 -05:00
										 |  |  |       return false; | 
					
						
							| 
									
										
										
										
											2024-02-25 16:57:18 -05:00
										 |  |  |     } else { | 
					
						
							|  |  |  |       try { | 
					
						
							|  |  |  |         int ret=std::stoi(val->second); | 
					
						
							|  |  |  |         return (ret!=0); | 
					
						
							|  |  |  |       } catch (std::out_of_range& e) { | 
					
						
							|  |  |  |       } catch (std::invalid_argument& e) { | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2022-02-18 13:11:04 -05:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return fallback; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-29 21:13:40 -04:00
										 |  |  | int DivConfig::getInt(String key, int fallback) const { | 
					
						
							| 
									
										
										
										
											2023-07-24 18:39:09 -04:00
										 |  |  |   auto val=conf.find(key); | 
					
						
							|  |  |  |   if (val!=conf.cend()) { | 
					
						
							|  |  |  |     try { | 
					
						
							|  |  |  |       int ret=std::stoi(val->second); | 
					
						
							|  |  |  |       return ret; | 
					
						
							|  |  |  |     } catch (std::out_of_range& e) { | 
					
						
							|  |  |  |     } catch (std::invalid_argument& e) { | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-02-18 13:11:04 -05:00
										 |  |  |   } | 
					
						
							|  |  |  |   return fallback; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-29 21:13:40 -04:00
										 |  |  | float DivConfig::getFloat(String key, float fallback) const { | 
					
						
							| 
									
										
										
										
											2023-07-24 18:39:09 -04:00
										 |  |  |   auto val=conf.find(key); | 
					
						
							|  |  |  |   if (val!=conf.cend()) { | 
					
						
							|  |  |  |     try { | 
					
						
							|  |  |  |       float ret=std::stof(val->second); | 
					
						
							|  |  |  |       return ret; | 
					
						
							|  |  |  |     } catch (std::out_of_range& e) { | 
					
						
							|  |  |  |     } catch (std::invalid_argument& e) { | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-02-18 13:11:04 -05:00
										 |  |  |   } | 
					
						
							|  |  |  |   return fallback; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-29 21:13:40 -04:00
										 |  |  | double DivConfig::getDouble(String key, double fallback) const { | 
					
						
							| 
									
										
										
										
											2023-07-24 18:39:09 -04:00
										 |  |  |   auto val=conf.find(key); | 
					
						
							|  |  |  |   if (val!=conf.cend()) { | 
					
						
							|  |  |  |     try { | 
					
						
							|  |  |  |       double ret=std::stod(val->second); | 
					
						
							|  |  |  |       return ret; | 
					
						
							|  |  |  |     } catch (std::out_of_range& e) { | 
					
						
							|  |  |  |     } catch (std::invalid_argument& e) { | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-02-18 13:11:04 -05:00
										 |  |  |   } | 
					
						
							|  |  |  |   return fallback; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-29 21:13:40 -04:00
										 |  |  | String DivConfig::getString(String key, String fallback) const { | 
					
						
							| 
									
										
										
										
											2023-07-24 18:39:09 -04:00
										 |  |  |   auto val=conf.find(key); | 
					
						
							|  |  |  |   if (val!=conf.cend()) { | 
					
						
							|  |  |  |     return val->second; | 
					
						
							| 
									
										
										
										
											2022-02-18 13:11:04 -05:00
										 |  |  |   } | 
					
						
							|  |  |  |   return fallback; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-02 18:32:21 -04:00
										 |  |  | std::vector<int> DivConfig::getIntList(String key, std::initializer_list<int> fallback) const { | 
					
						
							|  |  |  |   String next; | 
					
						
							|  |  |  |   std::vector<int> ret; | 
					
						
							| 
									
										
										
										
											2023-07-24 18:39:09 -04:00
										 |  |  |   auto val=conf.find(key); | 
					
						
							|  |  |  |   if (val!=conf.cend()) { | 
					
						
							|  |  |  |     try { | 
					
						
							|  |  |  |       for (char i: val->second) { | 
					
						
							|  |  |  |         if (i==',') { | 
					
						
							|  |  |  |           int num=std::stoi(next); | 
					
						
							|  |  |  |           ret.push_back(num); | 
					
						
							|  |  |  |           next=""; | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |           next+=i; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       if (!next.empty()) { | 
					
						
							| 
									
										
										
										
											2023-04-02 18:32:21 -04:00
										 |  |  |         int num=std::stoi(next); | 
					
						
							|  |  |  |         ret.push_back(num); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-24 18:39:09 -04:00
										 |  |  |       return ret; | 
					
						
							|  |  |  |     } catch (std::out_of_range& e) { | 
					
						
							|  |  |  |     } catch (std::invalid_argument& e) { | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-04-02 18:32:21 -04:00
										 |  |  |   } | 
					
						
							|  |  |  |   return fallback; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-10 17:55:44 -05:00
										 |  |  | bool DivConfig::has(String key) const { | 
					
						
							| 
									
										
										
										
											2023-07-24 18:39:09 -04:00
										 |  |  |   auto val=conf.find(key); | 
					
						
							|  |  |  |   return (val!=conf.cend()); | 
					
						
							| 
									
										
										
										
											2022-12-22 13:10:08 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-29 19:03:39 -04:00
										 |  |  | void DivConfig::set(String key, bool value) { | 
					
						
							| 
									
										
										
										
											2022-02-18 13:11:04 -05:00
										 |  |  |   if (value) { | 
					
						
							|  |  |  |     conf[key]="true"; | 
					
						
							|  |  |  |   } else { | 
					
						
							|  |  |  |     conf[key]="false"; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-29 19:03:39 -04:00
										 |  |  | void DivConfig::set(String key, int value) { | 
					
						
							| 
									
										
										
										
											2022-02-18 13:11:04 -05:00
										 |  |  |   conf[key]=fmt::sprintf("%d",value); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-29 19:03:39 -04:00
										 |  |  | void DivConfig::set(String key, float value) { | 
					
						
							| 
									
										
										
										
											2022-02-18 13:11:04 -05:00
										 |  |  |   conf[key]=fmt::sprintf("%f",value); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-29 19:03:39 -04:00
										 |  |  | void DivConfig::set(String key, double value) { | 
					
						
							| 
									
										
										
										
											2022-02-18 13:11:04 -05:00
										 |  |  |   conf[key]=fmt::sprintf("%f",value); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-29 19:03:39 -04:00
										 |  |  | void DivConfig::set(String key, const char* value) { | 
					
						
							| 
									
										
										
										
											2022-09-10 19:53:27 -04:00
										 |  |  |   conf[key]=String(value); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-29 19:03:39 -04:00
										 |  |  | void DivConfig::set(String key, String value) { | 
					
						
							| 
									
										
										
										
											2022-02-18 13:11:04 -05:00
										 |  |  |   conf[key]=value; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2022-09-29 19:03:39 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-02 18:32:21 -04:00
										 |  |  | void DivConfig::set(String key, const std::vector<int>& value) { | 
					
						
							|  |  |  |   String val; | 
					
						
							|  |  |  |   bool comma=false; | 
					
						
							|  |  |  |   for (int i: value) { | 
					
						
							|  |  |  |     if (comma) val+=','; | 
					
						
							|  |  |  |     val+=fmt::sprintf("%d",i); | 
					
						
							|  |  |  |     comma=true; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   conf[key]=val; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-29 19:03:39 -04:00
										 |  |  | bool DivConfig::remove(String key) { | 
					
						
							|  |  |  |   return conf.erase(key); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void DivConfig::clear() { | 
					
						
							|  |  |  |   conf.clear(); | 
					
						
							|  |  |  | } |