common: preserve order of key/value pairs

This commit is contained in:
Eric Wasylishen 2021-02-10 00:05:53 -07:00
parent c8b2f6f8e6
commit fea7849315
4 changed files with 109 additions and 28 deletions

View File

@ -28,6 +28,71 @@
#include <light/ltface.hh>
#include <common/bsputils.hh>
const std::string& entdict_t::get(const std::string& key) const {
if (auto it = find(key); it != keyvalues.end()) {
return it->second;
}
static std::string empty;
return empty;
}
void entdict_t::set(const std::string& key, const std::string& value) {
// search for existing key to update
if (auto it = find(key); it != keyvalues.end()) {
// found existing key
it->second = value;
return;
}
// no existing key; add new
keyvalues.push_back(std::make_pair(key, value));
}
void entdict_t::remove(const std::string& key) {
if (auto it = find(key); it != keyvalues.end()) {
keyvalues.erase(it);
}
}
keyvalues_t::iterator entdict_t::find(std::string_view key) {
auto existingIt = keyvalues.end();
for (auto it = keyvalues.begin(); it != keyvalues.end(); ++it) {
if (key == it->first) {
existingIt = it;
break;
}
}
return existingIt;
}
keyvalues_t::const_iterator entdict_t::find(std::string_view key) const {
auto existingIt = keyvalues.end();
for (auto it = keyvalues.begin(); it != keyvalues.end(); ++it) {
if (key == it->first) {
existingIt = it;
break;
}
}
return existingIt;
}
keyvalues_t::const_iterator entdict_t::begin() const {
return keyvalues.begin();
}
keyvalues_t::const_iterator entdict_t::end() const {
return keyvalues.end();
}
keyvalues_t::iterator entdict_t::begin() {
return keyvalues.begin();
}
keyvalues_t::iterator entdict_t::end() {
return keyvalues.end();
}
/*
* ==================
* EntData_Parse
@ -77,7 +142,7 @@ EntData_Parse(const char *entdata)
if (valstring.length() > MAX_ENT_VALUE - 1)
Error("%s: Value length > %i", __func__, MAX_ENT_VALUE - 1);
entity[keystr] = valstring;
entity.set(keystr, valstring);
}
result.push_back(entity);
@ -108,17 +173,13 @@ EntData_Write(const std::vector<entdict_t> &ents)
std::string
EntDict_StringForKey(const entdict_t &dict, const std::string key)
{
auto it = dict.find(key);
if (it != dict.end()) {
return it->second;
}
return "";
return dict.get(key);
}
float
EntDict_FloatForKey(const entdict_t &dict, const std::string key)
{
auto s = EntDict_StringForKey(dict, key);
auto s = dict.get(key);
if (s.empty())
return 0;
@ -132,11 +193,7 @@ EntDict_FloatForKey(const entdict_t &dict, const std::string key)
void
EntDict_RemoveValueForKey(entdict_t &dict, const std::string &key)
{
const auto it = dict.find(key);
if (it != dict.end()) {
dict.erase(it);
}
Q_assert(dict.find(key) == dict.end());
dict.remove(key);
}
void //mxd
@ -144,7 +201,9 @@ EntDict_RenameKey(entdict_t &dict, const std::string &from, const std::string &t
{
const auto it = dict.find(from);
if (it != dict.end()) {
swap(dict[to], it->second);
dict.erase(it);
const auto oldValue = it->second;
dict.remove(from);
dict.set(to, oldValue);
}
}

View File

@ -17,11 +17,32 @@
See file, 'COPYING', for details.
*/
#pragma once
#include <map>
#include <string>
#include <utility>
#include <vector>
using entdict_t = std::map<std::string, std::string>;
using keyvalue_t = std::pair<std::string, std::string>;
using keyvalues_t = std::vector<keyvalue_t>;
class entdict_t {
keyvalues_t keyvalues;
public:
const std::string& get(const std::string& key) const;
void set(const std::string& key, const std::string& value);
void remove(const std::string& key);
keyvalues_t::iterator find(std::string_view key);
keyvalues_t::const_iterator find(std::string_view key) const;
keyvalues_t::const_iterator begin() const;
keyvalues_t::const_iterator end() const;
keyvalues_t::iterator begin();
keyvalues_t::iterator end();
};
std::vector<entdict_t> EntData_Parse(const char *entdata);
std::string EntData_Write(const std::vector<entdict_t> &ents);

View File

@ -20,6 +20,7 @@
#ifndef __LIGHT_SETTINGS_H__
#define __LIGHT_SETTINGS_H__
#include <common/entdata.h>
#include <common/log.hh>
#include <common/mathlib.hh>
@ -352,7 +353,7 @@ public:
setting->setStringValue(value, cmdline);
}
void setSettings(const std::map<std::string, std::string> &epairs, bool cmdline) {
void setSettings(const entdict_t &epairs, bool cmdline) {
for (const auto &epair : epairs) {
setSetting(epair.first, epair.second, cmdline);
}

View File

@ -65,7 +65,7 @@ static std::vector<std::pair<std::string, int>> lightstyleForTargetname;
static entdict_t &WorldEnt()
{
if (entdicts.size() == 0
|| entdicts.at(0)["classname"] != "worldspawn") {
|| entdicts.at(0).get("classname") != "worldspawn") {
Error("WorldEnt() failed to get worldspawn");
}
return entdicts.at(0);
@ -73,7 +73,7 @@ static entdict_t &WorldEnt()
void SetWorldKeyValue(const std::string &key, const std::string &value)
{
WorldEnt()[key] = value;
WorldEnt().set(key, value);
}
std::string WorldValueForKey(const std::string &key)
{
@ -954,8 +954,8 @@ LoadEntities(const globalconfig_t &cfg, const mbsp_t *bsp)
if (!lmscale.empty()) {
logprint("lightmap_scale should be _lightmap_scale\n");
entdict.erase(entdict.find("lightmap_scale"));
entdict["_lightmap_scale"] = lmscale;
EntDict_RemoveValueForKey(entdict,"lightmap_scale");
entdict.set("_lightmap_scale", lmscale);
}
// setup light styles for switchable lights
@ -965,7 +965,7 @@ LoadEntities(const globalconfig_t &cfg, const mbsp_t *bsp)
const std::string targetname = EntDict_StringForKey(entdict, "targetname");
if (!targetname.empty()) {
const int style = LightStyleForTargetname(cfg, targetname);
entdict["style"] = std::to_string(style);
entdict.set("style", std::to_string(style));
}
}
@ -975,7 +975,7 @@ LoadEntities(const globalconfig_t &cfg, const mbsp_t *bsp)
// if targetname is "", generates a new unique lightstyle
const int style = LightStyleForTargetname(cfg, targetname);
// TODO: Configurable key?
entdict["switchshadstyle"] = std::to_string(style);
entdict.set("switchshadstyle", std::to_string(style));
}
// parse escape sequences
@ -1009,7 +1009,7 @@ LoadEntities(const globalconfig_t &cfg, const mbsp_t *bsp)
if(anglescale != entdict.end()) {
// Convert from 0..2 to 0..1 range...
const float val = qmin(1.0f, qmax(0.0f, EntDict_FloatForKey(entdict, "_anglescale") * 0.5f));
entdict["_anglescale"] = std::to_string(val);
entdict.set("_anglescale", std::to_string(val));
}
}
@ -1305,7 +1305,7 @@ SurfLights_WriteEntityToFile(FILE *f, light_t *entity, const vec3_t pos)
entdict_t epairs { *entity->epairs };
EntDict_RemoveValueForKey(epairs, "_surface");
epairs["origin"] = VecStr(pos);
epairs.set("origin", VecStr(pos));
std::string entstring = EntData_Write({ epairs });
fwrite(entstring.data(), 1, entstring.size(), f);
@ -1513,7 +1513,7 @@ bool ParseLightsFile(const char *fname)
if (!t)
continue;
entdict_t d = {};
d["_surface"] = std::string(com_token);
d.set("_surface", std::string(com_token));
t = COM_Parse(t);
r = atof(com_token);
t = COM_Parse(t);
@ -1521,9 +1521,9 @@ bool ParseLightsFile(const char *fname)
t = COM_Parse(t);
b = atof(com_token);
q_snprintf(gah, sizeof(gah), "%f %f %f", r,g,b);
d["_color"] = std::string(gah);
d.set("_color", std::string(gah));
t = COM_Parse(t);
d["light"] = std::string(com_token);
d.set("light", std::string(com_token));
//might be hdr rgbi values here
radlights.push_back(d);