Loading backends/yaml/yamlconf.cpp +96 −70 Original line number Diff line number Diff line Loading @@ -26,6 +26,9 @@ *******************************************************************************/ #include <iostream> #include <algorithm> #include <memory> #include <vector> #include <string> #include <yaml.h> Loading @@ -35,7 +38,7 @@ namespace confplus { struct YamlStack { std::string anchor; YamlStack *prevel; std::unique_ptr<YamlStack> prevel; }; }; Loading Loading @@ -64,53 +67,64 @@ void confplus::Yaml::saveConfig(const char *path,const Config *conf){ void confplus::Yaml::loadConfig(const char* path, Config* conf) { FILE *fh = fopen(path,"rb"); yaml_event_type_t type; FILE* fh = nullptr; yaml_event_type_t type = YAML_NO_EVENT; yaml_parser_t parse; bool parser_initialized = false; std::string key, value; // FIX C2362: ystack muss vor dem ersten goto initialisiert werden. std::unique_ptr<YamlStack> ystack = nullptr; /* Initialize parser */ if (!yaml_parser_initialize(&parse)) throw "Failed to initialize parser!"; parser_initialized = true; fh = fopen(path, "rb"); if (fh == nullptr) throw "Failed to open file!"; goto cleanup; // Springt bei Fehler zum Cleanup /* Set input file */ yaml_parser_set_input_file(&parse, fh); YamlStack *ystack=nullptr; bool seq = false; std::string key,value; int pos = 0; do { yaml_event_t event; if (!yaml_parser_parse(&parse, &event)) break; goto cleanup; // Springt bei Parser-Fehler zum Cleanup switch (event.type) { case YAML_MAPPING_START_EVENT: { YamlStack *cystack=new YamlStack; cystack->prevel=ystack; ystack=cystack; std::unique_ptr<YamlStack> cystack = std::make_unique<YamlStack>(); cystack->prevel = std::move(ystack); ystack = std::move(cystack); ystack->anchor = key; key = value; value.clear(); value = ""; // FIX: Explizite Zuweisung }break; case YAML_MAPPING_END_EVENT: { if(ystack->prevel){ YamlStack *pystack=ystack->prevel; delete ystack; ystack=pystack; if (ystack) { ystack = std::move(ystack->prevel); } }break; case YAML_SCALAR_EVENT: { if(key.empty()) std::copy(event.data.scalar.value,event.data.scalar.value+event.data.scalar.length,std::inserter<std::string>(key,std::begin(key))); else std::copy(event.data.scalar.value,event.data.scalar.value+event.data.scalar.length,std::inserter<std::string>(value,std::begin(value))); // FIX: Sichere String-Extraktion durch direkte Konstruktion. std::string temp_data( (const char*)event.data.scalar.value, event.data.scalar.length ); if (key.empty()) { key = temp_data; } else { value = temp_data; } }break; case YAML_SEQUENCE_START_EVENT: { Loading @@ -121,7 +135,7 @@ void confplus::Yaml::loadConfig(const char *path,Config *conf){ seq = false; key = value; pos = 0; value.clear(); value = ""; // FIX: Explizite Zuweisung }break; default: Loading @@ -129,18 +143,29 @@ void confplus::Yaml::loadConfig(const char *path,Config *conf){ } if (!key.empty() && !value.empty()) { std::vector<std::string> path_segments; for (YamlStack* curst = ystack.get(); curst; curst = curst->prevel.get()) { path_segments.push_back(curst->anchor); } // FIX: Korrekte Pfadkonstruktion (Root zu Leaf) std::string cname; for(YamlStack *curst=ystack; curst; curst=curst->prevel){ std::string pp=curst->anchor; pp+='/'; std::copy(pp.begin(),pp.end(),std::inserter<std::string>(cname,std::begin(cname))); for (auto it = path_segments.rbegin(); it != path_segments.rend(); ++it) { if (!it->empty()) { cname += "/"; cname += *it; } } cname += "/"; cname += key; Config::ConfigData* ckey = conf->setKey(cname); conf->setValue(ckey, pos, value); value.clear(); value = ""; // FIX: Explizite Zuweisung if (!seq) { key.clear(); }else{ key = ""; // FIX: Explizite Zuweisung } else { ++pos; } } Loading @@ -148,16 +173,17 @@ void confplus::Yaml::loadConfig(const char *path,Config *conf){ yaml_event_delete(&event); } while (type != YAML_STREAM_END_EVENT); cleanup: // Garantiertes Cleanup der C-Ressourcen if (parser_initialized) { yaml_parser_delete(&parse); } if (fh != nullptr) { fclose(fh); while(ystack){ YamlStack *prev=ystack->prevel; ystack->prevel=nullptr; delete ystack; ystack=prev; } delete ystack; // Fehler werfen nur, wenn das ffnen der Datei nach der Parser-Initialisierung fehlschlug if (fh == nullptr && parser_initialized) { throw "Failed to open file!"; } } No newline at end of file src/conf.cpp +35 −27 Original line number Diff line number Diff line Loading @@ -120,19 +120,22 @@ confplus::Config::ConfigData *confplus::Config::setKey(const std::string &key){ if(key[pos]=='/' || key[pos]=='\0'){ std::string childkey; std::copy(&key[start],&key[pos],std::inserter<std::string>(childkey,childkey.begin())); std::copy(&key[start], &key[pos], std::back_inserter(childkey)); start=(pos+1); find = existsdat(root_ptr->get(), childkey); if (!find) { find = createdat(*root_ptr); find->Key=childkey; if(key.empty()){ find->Value=std::make_unique<ConfigValue>(key,pos); find->haveChild=true; std::unique_ptr<ConfigData>* current_ptr = root_ptr; while (current_ptr->get()) { current_ptr = ¤t_ptr->get()->nextData; } ++find->Elements; *current_ptr = std::unique_ptr<ConfigData>(new ConfigData); // Konstruktor mit Key/Daten find = current_ptr->get(); } root_ptr = &find->Child; } Loading Loading @@ -170,8 +173,6 @@ size_t confplus::Config::ConfigData::getElements() const{ #ifdef Windows confplus::Config::Config(const std::string &path) { firstData = nullptr; std::string mpath = CONFIGPATH; size_t deli = path.find(':'); Loading @@ -184,7 +185,7 @@ confplus::Config::Config(const std::string &path) { std::string confpath = path.substr(deli, path.length() - deli); std::cout << "Loading backend: " << mpath << std::endl; std::cout << "Loading backend: " << mpath << "Config:" << confpath << std::endl; _BackendData = LoadLibrary(TEXT(mpath.c_str())); if (!_BackendData) { Loading Loading @@ -338,36 +339,43 @@ int confplus::Config::getIntValue(confplus::Config::ConfigData* key, size_t pos) throw err; } // In conf.cpp, replace the entire implementation of confplus::Config::setValue(): void confplus::Config::setValue(confplus::Config::ConfigData* key, size_t pos, const std::string& value) { // 1. Check if key is a path (correct) // 1. Prfen, ob es sich um einen Pfad handelt if (key->haveChild) { ConfException err; err[ConfException::Error] << "setValue it is a path not key"; throw err; } // 2. Bestehenden Wert an 'pos' suchen und aktualisieren for (ConfigValue* cur = key->Value.get(); cur; cur = cur->_nextValue.get()) { if (cur->_Pos == pos) { cur->_Value = value; return; // Found and updated existing value return; // Gefunden und aktualisiert } } // 3. Wenn der Wert nicht existiert, ihn am Ende anfgen. // Fall A: Die Liste ist leer (Kopf ist null). if (!key->Value) { // Set the head pointer directly // Setze den Kopfzeiger direkt key->Value = std::make_unique<ConfigValue>(value, pos); } else { // If the head is not null, traverse the linked list to find the last element std::unique_ptr<ConfigValue> *current_ptr = &key->Value->_nextValue; } else { // Fall B: Die Liste ist nicht leer. Finde das letzte Element. while (current_ptr->get()) { current_ptr = ¤t_ptr->get()->_nextValue; // Verwende einen Raw-Pointer zur Traversierung. ConfigValue* last = key->Value.get(); // Durchlaufe die Kette, solange _nextValue existiert. while (last->_nextValue) { last = last->_nextValue.get(); } // Set the final unique_ptr<ConfigValue>* in the chain *current_ptr = std::make_unique<ConfigValue>(value, pos); // Hnge das neue Objekt an den _nextValue-Smart Pointer des letzten Elements an. // Der Compiler verwendet hier std::move fr eine sichere Zuweisung. last->_nextValue = std::make_unique<ConfigValue>(value, pos); } } Loading Loading
backends/yaml/yamlconf.cpp +96 −70 Original line number Diff line number Diff line Loading @@ -26,6 +26,9 @@ *******************************************************************************/ #include <iostream> #include <algorithm> #include <memory> #include <vector> #include <string> #include <yaml.h> Loading @@ -35,7 +38,7 @@ namespace confplus { struct YamlStack { std::string anchor; YamlStack *prevel; std::unique_ptr<YamlStack> prevel; }; }; Loading Loading @@ -64,53 +67,64 @@ void confplus::Yaml::saveConfig(const char *path,const Config *conf){ void confplus::Yaml::loadConfig(const char* path, Config* conf) { FILE *fh = fopen(path,"rb"); yaml_event_type_t type; FILE* fh = nullptr; yaml_event_type_t type = YAML_NO_EVENT; yaml_parser_t parse; bool parser_initialized = false; std::string key, value; // FIX C2362: ystack muss vor dem ersten goto initialisiert werden. std::unique_ptr<YamlStack> ystack = nullptr; /* Initialize parser */ if (!yaml_parser_initialize(&parse)) throw "Failed to initialize parser!"; parser_initialized = true; fh = fopen(path, "rb"); if (fh == nullptr) throw "Failed to open file!"; goto cleanup; // Springt bei Fehler zum Cleanup /* Set input file */ yaml_parser_set_input_file(&parse, fh); YamlStack *ystack=nullptr; bool seq = false; std::string key,value; int pos = 0; do { yaml_event_t event; if (!yaml_parser_parse(&parse, &event)) break; goto cleanup; // Springt bei Parser-Fehler zum Cleanup switch (event.type) { case YAML_MAPPING_START_EVENT: { YamlStack *cystack=new YamlStack; cystack->prevel=ystack; ystack=cystack; std::unique_ptr<YamlStack> cystack = std::make_unique<YamlStack>(); cystack->prevel = std::move(ystack); ystack = std::move(cystack); ystack->anchor = key; key = value; value.clear(); value = ""; // FIX: Explizite Zuweisung }break; case YAML_MAPPING_END_EVENT: { if(ystack->prevel){ YamlStack *pystack=ystack->prevel; delete ystack; ystack=pystack; if (ystack) { ystack = std::move(ystack->prevel); } }break; case YAML_SCALAR_EVENT: { if(key.empty()) std::copy(event.data.scalar.value,event.data.scalar.value+event.data.scalar.length,std::inserter<std::string>(key,std::begin(key))); else std::copy(event.data.scalar.value,event.data.scalar.value+event.data.scalar.length,std::inserter<std::string>(value,std::begin(value))); // FIX: Sichere String-Extraktion durch direkte Konstruktion. std::string temp_data( (const char*)event.data.scalar.value, event.data.scalar.length ); if (key.empty()) { key = temp_data; } else { value = temp_data; } }break; case YAML_SEQUENCE_START_EVENT: { Loading @@ -121,7 +135,7 @@ void confplus::Yaml::loadConfig(const char *path,Config *conf){ seq = false; key = value; pos = 0; value.clear(); value = ""; // FIX: Explizite Zuweisung }break; default: Loading @@ -129,18 +143,29 @@ void confplus::Yaml::loadConfig(const char *path,Config *conf){ } if (!key.empty() && !value.empty()) { std::vector<std::string> path_segments; for (YamlStack* curst = ystack.get(); curst; curst = curst->prevel.get()) { path_segments.push_back(curst->anchor); } // FIX: Korrekte Pfadkonstruktion (Root zu Leaf) std::string cname; for(YamlStack *curst=ystack; curst; curst=curst->prevel){ std::string pp=curst->anchor; pp+='/'; std::copy(pp.begin(),pp.end(),std::inserter<std::string>(cname,std::begin(cname))); for (auto it = path_segments.rbegin(); it != path_segments.rend(); ++it) { if (!it->empty()) { cname += "/"; cname += *it; } } cname += "/"; cname += key; Config::ConfigData* ckey = conf->setKey(cname); conf->setValue(ckey, pos, value); value.clear(); value = ""; // FIX: Explizite Zuweisung if (!seq) { key.clear(); }else{ key = ""; // FIX: Explizite Zuweisung } else { ++pos; } } Loading @@ -148,16 +173,17 @@ void confplus::Yaml::loadConfig(const char *path,Config *conf){ yaml_event_delete(&event); } while (type != YAML_STREAM_END_EVENT); cleanup: // Garantiertes Cleanup der C-Ressourcen if (parser_initialized) { yaml_parser_delete(&parse); } if (fh != nullptr) { fclose(fh); while(ystack){ YamlStack *prev=ystack->prevel; ystack->prevel=nullptr; delete ystack; ystack=prev; } delete ystack; // Fehler werfen nur, wenn das ffnen der Datei nach der Parser-Initialisierung fehlschlug if (fh == nullptr && parser_initialized) { throw "Failed to open file!"; } } No newline at end of file
src/conf.cpp +35 −27 Original line number Diff line number Diff line Loading @@ -120,19 +120,22 @@ confplus::Config::ConfigData *confplus::Config::setKey(const std::string &key){ if(key[pos]=='/' || key[pos]=='\0'){ std::string childkey; std::copy(&key[start],&key[pos],std::inserter<std::string>(childkey,childkey.begin())); std::copy(&key[start], &key[pos], std::back_inserter(childkey)); start=(pos+1); find = existsdat(root_ptr->get(), childkey); if (!find) { find = createdat(*root_ptr); find->Key=childkey; if(key.empty()){ find->Value=std::make_unique<ConfigValue>(key,pos); find->haveChild=true; std::unique_ptr<ConfigData>* current_ptr = root_ptr; while (current_ptr->get()) { current_ptr = ¤t_ptr->get()->nextData; } ++find->Elements; *current_ptr = std::unique_ptr<ConfigData>(new ConfigData); // Konstruktor mit Key/Daten find = current_ptr->get(); } root_ptr = &find->Child; } Loading Loading @@ -170,8 +173,6 @@ size_t confplus::Config::ConfigData::getElements() const{ #ifdef Windows confplus::Config::Config(const std::string &path) { firstData = nullptr; std::string mpath = CONFIGPATH; size_t deli = path.find(':'); Loading @@ -184,7 +185,7 @@ confplus::Config::Config(const std::string &path) { std::string confpath = path.substr(deli, path.length() - deli); std::cout << "Loading backend: " << mpath << std::endl; std::cout << "Loading backend: " << mpath << "Config:" << confpath << std::endl; _BackendData = LoadLibrary(TEXT(mpath.c_str())); if (!_BackendData) { Loading Loading @@ -338,36 +339,43 @@ int confplus::Config::getIntValue(confplus::Config::ConfigData* key, size_t pos) throw err; } // In conf.cpp, replace the entire implementation of confplus::Config::setValue(): void confplus::Config::setValue(confplus::Config::ConfigData* key, size_t pos, const std::string& value) { // 1. Check if key is a path (correct) // 1. Prfen, ob es sich um einen Pfad handelt if (key->haveChild) { ConfException err; err[ConfException::Error] << "setValue it is a path not key"; throw err; } // 2. Bestehenden Wert an 'pos' suchen und aktualisieren for (ConfigValue* cur = key->Value.get(); cur; cur = cur->_nextValue.get()) { if (cur->_Pos == pos) { cur->_Value = value; return; // Found and updated existing value return; // Gefunden und aktualisiert } } // 3. Wenn der Wert nicht existiert, ihn am Ende anfgen. // Fall A: Die Liste ist leer (Kopf ist null). if (!key->Value) { // Set the head pointer directly // Setze den Kopfzeiger direkt key->Value = std::make_unique<ConfigValue>(value, pos); } else { // If the head is not null, traverse the linked list to find the last element std::unique_ptr<ConfigValue> *current_ptr = &key->Value->_nextValue; } else { // Fall B: Die Liste ist nicht leer. Finde das letzte Element. while (current_ptr->get()) { current_ptr = ¤t_ptr->get()->_nextValue; // Verwende einen Raw-Pointer zur Traversierung. ConfigValue* last = key->Value.get(); // Durchlaufe die Kette, solange _nextValue existiert. while (last->_nextValue) { last = last->_nextValue.get(); } // Set the final unique_ptr<ConfigValue>* in the chain *current_ptr = std::make_unique<ConfigValue>(value, pos); // Hnge das neue Objekt an den _nextValue-Smart Pointer des letzten Elements an. // Der Compiler verwendet hier std::move fr eine sichere Zuweisung. last->_nextValue = std::make_unique<ConfigValue>(value, pos); } } Loading