DSL
ini-reader.cpp
1 //@AUTOHEADER@BEGIN@
2 /***********************************************************************\
3 | Drift Standard Libraries v1.01 |
4 | Copyright 2010-2023 Drift Solutions / Indy Sams |
5 | Docs and more information available at https://www.driftsolutions.dev |
6 | This file released under the 3-clause BSD license, |
7 | see included DSL.LICENSE.TXT file for details. |
8 \***********************************************************************/
9 //@AUTOHEADER@END@
10 
11 #include <drift/dslcore.h>
12 #include <drift/ini-reader.h>
13 #include <drift/Mutex.h>
14 #include <drift/GenLib.h>
15 
16 DSL_Mutex * iniMutex()
17 {
18  static DSL_Mutex actualMutex;
19  return &actualMutex;
20 }
21 
22 char * DSL_CC Get_INI_String(const char * pszFilename, const char *pszSection, const char *pszItem, char *pszValue, size_t lValueBufferSize, const char * pszDefault) {
23  AutoMutexPtr(iniMutex());
24 
25  char * ret = NULL;
26  *pszValue = 0;
27 
28  FILE * hFile = fopen(pszFilename, "rb");
29  if (hFile != NULL) {
30  fseek(hFile, 0, SEEK_END);
31  long lFileSize = ftell(hFile);
32  char * cINIFile = (char *)dsl_malloc(lFileSize + 1);
33  cINIFile[lFileSize] = 0;
34  if (lFileSize > 0) {
35  fseek(hFile, 0, SEEK_SET);
36  if (fread(cINIFile, lFileSize, 1, hFile) == 1) {
37  ret = Get_INI_String_Memory(cINIFile, pszSection, pszItem, pszValue, lValueBufferSize, pszDefault);
38  }
39  }
40  fclose(hFile);
41  dsl_free(cINIFile);
42  }
43 
44  if (ret == NULL && pszDefault) {
45  strlcpy(pszValue, pszDefault, lValueBufferSize);
46  return pszValue;
47  }
48 
49  return ret;
50 }
51 
52 char * DSL_CC Get_INI_String_Memory(const char * data, const char *pszSection, const char *pszItem, char *pszValue, size_t lValueBufferSize, const char * pszDefault) {
53  AutoMutexPtr(iniMutex());
54 
55  memset(pszValue, 0, lValueBufferSize);
56 
57  char * cfile = dsl_strdup(data);
58  size_t len = strlen(cfile);
59  str_replaceA(cfile, len+1, "\r", "");
60  str_replaceA(cfile, len+1, "\t", " ");
61  while (strstr(cfile, " ")) {
62  str_replaceA(cfile, len+1, " ", " ");
63  }
64  len = strlen(cfile);
65 
66  bool insec = false;
67  char * line2 = NULL;
68  char * line = strtok_r(cfile, "\n", &line2);
69  while (line) {
70  if (insec) {
71  if (*line == '[' && strchr(line, ']')) {
72  //a new section has opened, so stop looking for the correct item
73  insec = false;
74  } else {
75  char * p = strchr(line, '=');
76  if (p) {
77  //trim up the item name and value for bad INI writers
78  char * item = dsl_strdup(line);
79  strchr(item, '=')[0] = 0;
80  while (item[0] == ' ') {
81  memmove(item, item+1, strlen(item));
82  }
83  while (item[strlen(item)-1] == ' ') {
84  item[strlen(item)-1] = 0;
85  }
86  char * value = dsl_strdup(p+1);
87  while (value[0] == ' ') {
88  memmove(value, value+1, strlen(value));
89  }
90  while (value[strlen(value)-1] == ' ') {
91  value[strlen(value)-1] = 0;
92  }
93 
94  //is this my item?
95  if (!stricmp(item, pszItem)) {
96  strlcpy(pszValue, value, lValueBufferSize);
97  dsl_free(item);
98  dsl_free(value);
99  dsl_free(cfile);
100  return pszValue;
101  }
102  dsl_free(item);
103  dsl_free(value);
104  }
105  }
106  } else {
107  if (*line == '[' && !strnicmp(line+1, pszSection, strlen(pszSection)) && line[strlen(pszSection)+1] == ']') {
108  insec = true;
109  }
110  }
111  line = strtok_r(NULL, "\n", &line2);
112  }
113 
114  if (pszDefault) {
115  strlcpy(pszValue, pszDefault, lValueBufferSize);
116  } else {
117  pszValue = NULL;
118  }
119 
120  dsl_free(cfile);
121  return pszValue;
122 
123 }
124 
125 int64 DSL_CC Get_INI_Int(const char *path, const char *section, const char *item, int64 iDefault) {
126  AutoMutexPtr(iniMutex());
127 
128  char ivalue[64];
129  char * ret = Get_INI_String(path, section, item, ivalue, sizeof(ivalue), NULL);
130  if (ret) {
131  return atoi64(ret);
132  }
133  return iDefault;
134 }
135 
136 DSL_API int64 DSL_CC Get_INI_Int_Memory(const char * cINIFile, const char *section, const char *item, int64 iDefault) {
137  AutoMutexPtr(iniMutex());
138 
139  char ivalue[64];
140  char * ret = Get_INI_String_Memory(cINIFile, section, item, ivalue, sizeof(ivalue), NULL);
141  if (ret) {
142  return atoi64(ret);
143  }
144  return iDefault;
145 }
146 
147 double DSL_CC Get_INI_Float(const char *path, const char *section, const char *item, double iDefault) {
148  AutoMutexPtr(iniMutex());
149 
150  char ivalue[64];
151  char * ret = Get_INI_String(path, section, item, ivalue, sizeof(ivalue), NULL);
152  if (ret) {
153  return atof(ret);
154  }
155  return iDefault;
156 }
157 
158 DSL_API double DSL_CC Get_INI_Float_Memory(const char * cINIFile, const char *section, const char *item, double iDefault) {
159  AutoMutexPtr(iniMutex());
160 
161  char ivalue[64];
162  char * ret = Get_INI_String_Memory(cINIFile, section, item, ivalue, sizeof(ivalue), NULL);
163  if (ret) {
164  return atof(ret);
165  }
166  return iDefault;
167 }
168 
169 int DSL_CC Write_INI_String(const char *pszPath, const char *pszSection, const char *pszItem, const char *pszValue) {
170  FILE * hFile = fopen(pszPath, "rb");
171  if (hFile == NULL) {
172  //can't open, may not exist
173  hFile = fopen(pszPath, "wb");
174  if (hFile == NULL) {
175  //nope, just an error in general
176  return -1;
177  }
178  fprintf(hFile, "[%s]\r\n%s=%s\r\n", pszSection, pszItem, pszValue);
179  fclose(hFile);
180  return 0;
181  }
182  fseek(hFile, 0, SEEK_END);
183  size_t len = (size_t)ftell(hFile);
184  fseek(hFile, 0, SEEK_SET);
185  char * cfile = (char *)dsl_malloc(len+1);
186  cfile[len] = 0;
187  if (fread(cfile, len, 1, hFile) != 1) {
188  dsl_free(cfile);
189  fclose(hFile);
190  return -1;
191  }
192  fclose(hFile);
193  hFile = fopen(pszPath, "wb");
194  if (hFile == NULL) {
195  dsl_free(cfile);
196  return -1;
197  }
198  str_replaceA(cfile, len+1, "\r", "");
199  str_replaceA(cfile, len+1, "\t", " ");
200  while (strstr(cfile, " ")) {
201  str_replaceA(cfile, len+1, " ", " ");
202  }
203  len = strlen(cfile);
204 
205  bool written = false;
206  bool insec = false;
207  char * line2 = NULL;
208  char * line = strtok_r(cfile, "\n", &line2);
209  while (line) {
210  if (insec) {
211  if (*line == '[' && strchr(line, ']')) {
212  //a new section has opened, so stop looking for the correct item
213  if (!written) {
214  //just append the value here before the new section opens
215  fprintf(hFile, "%s=%s\r\n\r\n", pszItem, pszValue);
216  written = true;
217  }
218  insec = false;
219  } else {
220  char * p = strchr(line, '=');
221  if (p) {
222  //trim up the item name and value for bad INI writers
223  char * item = dsl_strdup(line);
224  strchr(item, '=')[0] = 0;
225  while (item[0] == ' ') {
226  memmove(item, item+1, strlen(item));
227  }
228  while (item[strlen(item)-1] == ' ') {
229  item[strlen(item)-1] = 0;
230  }
231  char * value = dsl_strdup(p+1);
232  while (value[0] == ' ') {
233  memmove(value, value+1, strlen(value));
234  }
235  while (value[strlen(value)-1] == ' ') {
236  value[strlen(value)-1] = 0;
237  }
238 
239  //is this my item?
240  if (!stricmp(item, pszItem)) {
241  fprintf(hFile, "%s=%s\r\n", pszItem, pszValue);
242  written = true;
243  dsl_free(item);
244  dsl_free(value);
245  line = strtok_r(NULL, "\n", &line2);
246  continue;
247  }
248  dsl_free(item);
249  dsl_free(value);
250  }
251  }
252  } else {
253  if (*line == '[' && !strnicmp(line+1, pszSection, strlen(pszSection)) && line[strlen(pszSection)+1] == ']') {
254  insec = true;
255  }
256  }
257 
258  //printf("out: %s\r\n", line);
259  fprintf(hFile, "%s\r\n", line);
260  line = strtok_r(NULL, "\n", &line2);
261  }
262 
263  if (written == false) {
264  if (insec) {
265  //EOF, but I am still in the correct section, no need to open a new one
266  fprintf(hFile, "%s=%s\r\n", pszItem, pszValue);
267  } else {
268  // Section not found, create it add the section and write the value
269  fprintf(hFile, "[%s]\r\n%s=%s\r\n", pszSection, pszItem, pszValue);
270  }
271  }
272 
273  fclose(hFile);
274  dsl_free(cfile);
275  return 0;
276 }
277 
278 int DSL_CC Write_INI_Int(const char *pszPath, const char *pszSection, const char *pszItem, int64 iValue) {
279  char value[64];
280  sprintf(value, I64FMT, iValue);
281  return Write_INI_String(pszPath, pszSection, pszItem, value);
282 }
DSL_API void DSL_CC dsl_free(void *ptr)
Definition: dsl.cpp:345
DSL_API size_t DSL_CC strlcpy(char *dst, const char *src, size_t siz)
Definition: GenLib.cpp:905
DSL_API_CLASS int DSL_CC str_replaceA(char *Str, size_t BufSize, const char *FindStr, const char *ReplStr)
Simple string replacement.
Definition: GenLib.cpp:592