Freeciv21
Develop your civilization from humble roots to a global empire
fcdb.cpp
Go to the documentation of this file.
1 /*
2 _ ._ Copyright (c) 1996-2021 Freeciv21 and Freeciv contributors.
3  \ | This file is part of Freeciv21. Freeciv21 is free software: you
4  \_| can redistribute it and/or modify it under the terms of the
5  .' '. GNU General Public License as published by the Free
6  :O O: Software Foundation, either version 3 of the License,
7  '/ \' or (at your option) any later version. You should have
8  :X: received a copy of the GNU General Public License along with
9  :X: Freeciv21. If not, see https://www.gnu.org/licenses/.
10  */
11 
12 // Qt
13 #include <QHash>
14 #include <QString>
15 
16 // utility
17 #include "fcintl.h"
18 #include "log.h"
19 #include "registry.h"
20 #include "section_file.h"
21 #include "support.h"
22 
23 /* server/scripting */
24 #include "script_fcdb.h"
25 
26 #include "fcdb.h"
27 
28 struct fcdb_option {
29  char *value;
30 };
31 
32 QHash<QString, fcdb_option *> fcdb_config;
33 
34 static bool fcdb_set_option(const char *key, const char *value);
35 static bool fcdb_load_config(const char *filename);
36 
41 static bool fcdb_set_option(const char *key, const char *value)
42 {
43  struct fcdb_option *oldopt = nullptr;
44  bool removed;
45 
46  if (value != nullptr) {
47  auto newopt = new fcdb_option;
48 
49  newopt->value = fc_strdup(value);
50 
51  removed = fcdb_config.contains(key);
52  if (removed) {
53  oldopt = fcdb_config.value(key);
54  }
55  fcdb_config[key] = newopt;
56  } else {
57  removed = fcdb_config.contains(key);
58  if (removed) {
59  oldopt = fcdb_config.take(key);
60  }
61  }
62 
63  if (removed) {
64  /* Overwritten/removed an existing value */
65  fc_assert_ret_val(oldopt != nullptr, false);
66  delete[] oldopt->value;
67  delete oldopt;
68  oldopt = nullptr;
69  }
70 
71  return true;
72 }
73 
79 static bool fcdb_load_config(const char *filename)
80 {
81  struct section_file *secfile;
82 
83  fc_assert_ret_val(nullptr != filename, false);
84 
85  if (!(secfile = secfile_load(filename, false))) {
86  qCritical(_("Cannot load fcdb config file '%s':\n%s"), filename,
87  secfile_error());
88  return false;
89  }
90 
92  section_entries(secfile_section_by_name(secfile, "fcdb")), pentry)
93  {
94  if (entry_type_get(pentry) == ENTRY_STR) {
95  const char *value;
96  bool entry_str_get_success = entry_str_get(pentry, &value);
97 
98  fc_assert(entry_str_get_success);
99  fcdb_set_option(entry_name(pentry), value);
100  } else {
101  qCritical("Value for '%s' in '%s' is not of string type, ignoring",
102  entry_name(pentry), filename);
103  }
104  }
106 
107  /* FIXME: we could arrange to call secfile_check_unused() and have it
108  * complain about unused entries (e.g. those not in [fcdb]). */
109  secfile_destroy(secfile);
110 
111  return true;
112 }
113 
117 bool fcdb_init(const char *conf_file)
118 {
119  if (conf_file && strcmp(conf_file, "-")) {
120  if (!fcdb_load_config(conf_file)) {
121  return false;
122  }
123  } else {
124  log_debug("No fcdb config file.");
125  }
126 
127  return script_fcdb_init(nullptr);
128 }
129 
133 const char *fcdb_option_get(const char *type)
134 {
135  if (fcdb_config.contains(type)) {
136  return fcdb_config[type]->value;
137  } else {
138  return nullptr;
139  }
140 }
141 
145 void fcdb_free(void)
146 {
148 
149  for (auto popt : qAsConst(fcdb_config)) {
150  // Dangling pointers freed below
151  delete[] popt->value;
152  delete popt;
153  popt = nullptr;
154  }
155  fcdb_config.clear();
156 }
void fcdb_free(void)
Free resources allocated by fcdb system.
Definition: fcdb.cpp:145
bool fcdb_init(const char *conf_file)
Initialize freeciv database system.
Definition: fcdb.cpp:117
static bool fcdb_load_config(const char *filename)
Load fcdb configuration from file.
Definition: fcdb.cpp:79
static bool fcdb_set_option(const char *key, const char *value)
Set one fcdb option (or delete it if value == nullptr).
Definition: fcdb.cpp:41
QHash< QString, fcdb_option * > fcdb_config
Definition: fcdb.cpp:32
const char * fcdb_option_get(const char *type)
Return the selected fcdb config value.
Definition: fcdb.cpp:133
#define _(String)
Definition: fcintl.h:50
#define fc_assert(condition)
Definition: log.h:89
#define fc_assert_ret_val(condition, val)
Definition: log.h:114
#define log_debug(message,...)
Definition: log.h:65
struct section_file * secfile_load(const QString &filename, bool allow_duplicates)
Create a section file from a file.
Definition: registry.cpp:21
const char * secfile_error()
Returns the last error which occurred in a string.
void secfile_destroy(struct section_file *secfile)
Free a section file.
const char * entry_name(const struct entry *pentry)
Returns the name of this entry.
bool entry_str_get(const struct entry *pentry, const char **value)
Gets an string value.
struct section * secfile_section_by_name(const struct section_file *secfile, const QString &name)
Returns the first section matching the name.
const struct entry_list * section_entries(const struct section *psection)
Returns a list containing all the entries.
enum entry_type entry_type_get(const struct entry *pentry)
Returns the type of this entry or ENTRY_ILLEGAL or error.
@ ENTRY_STR
Definition: registry_ini.h:537
#define entry_list_iterate_end
Definition: registry_ini.h:58
#define entry_list_iterate(entlist, pentry)
Definition: registry_ini.h:56
bool script_fcdb_init(const QString &fcdb_luafile)
Initialize the scripting state.
void script_fcdb_free()
Free the scripting data.
char * value
Definition: fcdb.cpp:29
#define fc_strdup(str)
Definition: support.h:111