Freeciv21
Develop your civilization from humble roots to a global empire
section_file.cpp
Go to the documentation of this file.
1 /*__ ___ ***************************************
2 / \ / \ Copyright (c) 1996-2020 Freeciv21 and Freeciv
3 \_ \ / __/ contributors. This file is part of Freeciv21.
4  _\ \ / /__ Freeciv21 is free software: you can redistribute it
5  \___ \____/ __/ and/or modify it under the terms of the GNU General
6  \_ _/ Public License as published by the Free Software
7  | @ @ \_ Foundation, either version 3 of the License,
8  | or (at your option) any later version.
9  _/ /\ You should have received a copy of the GNU
10  /o) (o/\ \_ General Public License along with Freeciv21.
11  \_____/ / If not, see https://www.gnu.org/licenses/.
12  \____/ ********************************************************/
13 // utility
14 #include "registry.h"
15 
16 #include "section_file.h"
17 
18 #include <QMultiHash>
19 
20 #include "log.h"
21 
22 #define MAX_LEN_ERRORBUF 1024
23 
24 static char error_buffer[MAX_LEN_ERRORBUF] = "\0";
25 
26 // Debug function for every new entry.
27 #define DEBUG_ENTRIES(...) // log_debug(__VA_ARGS__);
28 
33 const char *secfile_error() { return error_buffer; }
34 
38 void secfile_log(const struct section_file *secfile,
39  const struct section *psection, const char *file,
40  const char *function, int line, const char *format, ...)
41 {
43  va_list args;
44 
45  va_start(args, format);
46  fc_vsnprintf(message, sizeof(message), format, args);
47  va_end(args);
48 
50  "In %s() [%s:%d]: secfile '%s' in section '%s': %s", function,
51  file, line, secfile_name(secfile),
52  psection != nullptr ? section_name(psection) : "nullptr",
53  message);
54 }
55 
59 const char *section_name(const struct section *psection)
60 {
61  return (nullptr != psection ? psection->name : nullptr);
62 }
63 
68 {
69  section_file *secfile = new section_file;
70 
71  secfile->name = nullptr;
72  secfile->num_entries = 0;
73  secfile->num_includes = 0;
74  secfile->num_long_comments = 0;
75  secfile->sections = section_list_new_full(section_destroy);
77  secfile->allow_digital_boolean = false; // Default
78 
80  // Maybe allocated later.
81  secfile->hash.entries = nullptr;
82 
83  return secfile;
84 }
85 
89 void secfile_destroy(struct section_file *secfile)
90 {
91  SECFILE_RETURN_IF_FAIL(secfile, nullptr, secfile != nullptr);
92 
93  delete secfile->hash.sections;
94  /* Mark it nullptr to be sure to don't try to make operations when
95  * deleting the entries. */
96  secfile->hash.sections = nullptr;
97  delete secfile->hash.entries;
98  secfile->hash.entries = nullptr;
99  section_list_destroy(secfile->sections);
100  delete[] secfile->name;
101  secfile->name = nullptr;
102  delete secfile;
103  secfile = nullptr;
104 }
105 
113 {
114  fc_assert_ret(nullptr != secfile);
116 }
117 
121 bool entry_from_token(struct section *psection, const QString &name,
122  const QString &tok)
123 {
124  if ('*' == tok[0]) {
125  auto buf = remove_escapes(tok.mid(1), false);
126  (void) section_entry_str_new(psection, name, buf, false);
127  DEBUG_ENTRIES("entry %s '%s'", name, qUtf8Printable(buf));
128  return true;
129  }
130 
131  if ('$' == tok[0] || '"' == tok[0]) {
132  bool escaped = ('"' == tok[0]);
133  auto buf = remove_escapes(tok.mid(1), escaped);
134  (void) section_entry_str_new(psection, name, buf, escaped);
135  DEBUG_ENTRIES("entry %s '%s'", name, qUtf8Printable(buf));
136  return true;
137  }
138 
139  if (tok[0].isDigit()
140  || (('-' == tok[0] || '+' == tok[0]) && tok[1].isDigit())) {
141  if (tok.contains('.')) {
142  bool ok;
143  auto fvalue = tok.toFloat(&ok);
144  if (ok) {
145  (void) section_entry_float_new(psection, name, fvalue);
146  DEBUG_ENTRIES("entry %s %d", name, fvalue);
147  return true;
148  }
149  } else {
150  bool ok;
151  auto ivalue = tok.toInt(&ok, 0);
152  if (ok) {
153  (void) section_entry_int_new(psection, name, ivalue);
154  DEBUG_ENTRIES("entry %s %d", name, ivalue);
155 
156  return true;
157  }
158  }
159  return false;
160  }
161 
162  if (tok.compare(QStringLiteral("FALSE"), Qt::CaseInsensitive) == 0
163  || tok.compare(QStringLiteral("TRUE"), Qt::CaseInsensitive) == 0) {
164  bool value =
165  (tok.compare(QStringLiteral("TRUE"), Qt::CaseInsensitive) == 0);
166 
167  (void) section_entry_bool_new(psection, name, value);
168  DEBUG_ENTRIES("entry %s %s", name, value ? "TRUE" : "FALSE");
169  return true;
170  }
171 
172  return false;
173 }
const char * name
Definition: inputfile.cpp:118
#define fc_assert_ret(condition)
Definition: log.h:112
void section_destroy(struct section *psection)
Remove this section from the secfile.
struct entry * section_entry_str_new(struct section *psection, const QString &name, const QString &value, bool escaped)
Returns a new entry of type ENTRY_STR.
const char * secfile_name(const struct section_file *secfile)
Return the filename the section file was loaded as, or "(anonymous)" if this sectionfile was created ...
struct entry * section_entry_int_new(struct section *psection, const QString &name, int value)
Returns a new entry of type ENTRY_INT.
struct entry * section_entry_bool_new(struct section *psection, const QString &name, bool value)
Returns a new entry of type ENTRY_BOOL.
struct entry * section_entry_float_new(struct section *psection, const QString &name, float value)
Returns a new entry of type ENTRY_FLOAT.
void secfile_log(const struct section_file *secfile, const struct section *psection, const char *file, const char *function, int line, const char *format,...)
Edit the error_buffer.
static char error_buffer[MAX_LEN_ERRORBUF]
#define MAX_LEN_ERRORBUF
const char * secfile_error()
Returns the last error which occurred in a string.
bool entry_from_token(struct section *psection, const QString &name, const QString &tok)
Add entry to section from token.
struct section_file * secfile_new(bool allow_duplicates)
Create a new empty section file.
void secfile_allow_digital_boolean(struct section_file *secfile, bool allow_digital_boolean)
Set if we could consider values 0 and 1 as boolean.
const char * section_name(const struct section *psection)
Returns the section name.
#define DEBUG_ENTRIES(...)
void secfile_destroy(struct section_file *secfile)
Free a section file.
#define SECFILE_RETURN_IF_FAIL(secfile, psection, condition)
Definition: section_file.h:61
struct section_file::@7 hash
QMultiHash< QString, struct entry * > * entries
Definition: section_file.h:49
struct section_list * sections
Definition: section_file.h:44
bool allow_digital_boolean
Definition: section_file.h:46
bool allow_duplicates
Definition: section_file.h:45
unsigned int num_includes
Definition: section_file.h:42
unsigned int num_long_comments
Definition: section_file.h:43
size_t num_entries
Definition: section_file.h:38
char * name
Definition: section_file.h:31
int fc_snprintf(char *str, size_t n, const char *format,...)
See also fc_utf8_snprintf_trunc(), fc_utf8_snprintf_rep().
Definition: support.cpp:537
int fc_vsnprintf(char *str, size_t n, const char *format, va_list ap)
Definition: support.cpp:512
QString remove_escapes(const QString &str, bool full_escapes)
Copies a string.
Definition: support.cpp:149