Gammu internals  1.38.0
INI files

Data Structures

struct  _INI_Entry
 
struct  _INI_Section
 

Typedefs

typedef struct _INI_Entry INI_Entry
 
typedef struct _INI_Section INI_Section
 

Functions

void INI_Free (INI_Section *head)
 
GSM_Error INI_ReadFile (const char *FileName, gboolean Unicode, INI_Section **result)
 
INI_EntryINI_FindLastSectionEntry (INI_Section *file_info, const unsigned char *section, const gboolean Unicode)
 
unsigned char * INI_GetValue (INI_Section *file_info, const unsigned char *section, const unsigned char *key, const gboolean Unicode)
 
gboolean GSM_StringToBool (const char *value)
 

Detailed Description

These functions parse ini file and make them available in easily accessable manner.

File format is standard ini file, comments are both # and ;.

Typedef Documentation

§ INI_Entry

typedef struct _INI_Entry INI_Entry

Private structure holding information INI entry.

Definition at line 28 of file gammu-inifile.h.

§ INI_Section

typedef struct _INI_Section INI_Section

Private structure holding information INI section.

Definition at line 34 of file gammu-inifile.h.

Function Documentation

§ GSM_StringToBool()

gboolean GSM_StringToBool ( const char *  value)

Converts value to boolean.

It just takes the string and checks whether there is true/yes/t/y/1 or false/no/f/n/0.

Parameters
valueString to parse.
Returns
Boolean value, -1 on failure.

Definition at line 470 of file cfg.c.

References FALSE, and TRUE.

Referenced by INI_GetBool().

471 {
472  if (strcasecmp(value, "true") == 0) return TRUE;
473  if (strcasecmp(value, "yes") == 0) return TRUE;
474  if (strcasecmp(value, "y") == 0) return TRUE;
475  if (strcasecmp(value, "t") == 0) return TRUE;
476  if (strcasecmp(value, "1") == 0) return TRUE;
477  if (strcasecmp(value, "false") == 0) return FALSE;
478  if (strcasecmp(value, "no") == 0) return FALSE;
479  if (strcasecmp(value, "f") == 0) return FALSE;
480  if (strcasecmp(value, "n") == 0) return FALSE;
481  if (strcasecmp(value, "0") == 0) return FALSE;
482  return -1;
483 }
#define FALSE
Definition: gammu-types.h:25
#define TRUE
Definition: gammu-types.h:28

§ INI_FindLastSectionEntry()

INI_Entry* INI_FindLastSectionEntry ( INI_Section file_info,
const unsigned char *  section,
const gboolean  Unicode 
)

Returns pointer to last INI entry of given section.

Parameters
file_infoFile data as returned by INI_ReadFile.
sectionSection to scan.
UnicodeWhether file is unicode.
Returns
Last entry in section.
Bug:
Unicode should be part of file_info.

Definition at line 409 of file cfg.c.

References mywstrncasecmp(), _INI_Entry::Next, _INI_Section::Next, _INI_Section::SectionName, and _INI_Section::SubEntries.

410 {
411  INI_Section *h;
412  INI_Entry *e;
413 
414  e = NULL;
415  /* First find our section */
416  for (h = file_info; h != NULL; h = h->Next) {
417  if (Unicode) {
418  if (mywstrncasecmp(section, h->SectionName, 0)) {
419  e = h->SubEntries;
420  break;
421  }
422  } else {
423  if (strcasecmp(section, h->SectionName) == 0) {
424  e = h->SubEntries;
425  break;
426  }
427  }
428  }
429 
430  if (e == NULL) return NULL;
431 
432  /* Goes into last value in section */
433  while (e->Next != NULL) e = e->Next;
434  return e;
435 }
gboolean mywstrncasecmp(unsigned const char *a, unsigned const char *b, int num)
Definition: coding.c:1437
INI_Entry * SubEntries
Definition: gammu-inifile.h:54
Definition: gammu-inifile.h:41
unsigned char * SectionName
Definition: gammu-inifile.h:55
INI_Section * Next
Definition: gammu-inifile.h:53
INI_Entry * Next
Definition: gammu-inifile.h:42

§ INI_Free()

void INI_Free ( INI_Section head)

Free INI data.

Parameters
headINI section data.

Definition at line 454 of file cfg.c.

References INI_Free_Entries(), _INI_Section::Next, _INI_Section::SectionName, and _INI_Section::SubEntries.

455 {
456  INI_Section *cur = head, *next;
457 
458  if (cur == NULL) return;
459  while (cur != NULL) {
460  next = cur->Next;
461  free(cur->SectionName);
462  cur->SectionName=NULL;
464  free(cur);
465  cur=NULL;
466  cur=next;
467  }
468 }
void INI_Free_Entries(INI_Entry *entry)
Definition: cfg.c:437
INI_Entry * SubEntries
Definition: gammu-inifile.h:54
unsigned char * SectionName
Definition: gammu-inifile.h:55
INI_Section * Next
Definition: gammu-inifile.h:53

§ INI_GetValue()

unsigned char* INI_GetValue ( INI_Section cfg,
const unsigned char *  section,
const unsigned char *  key,
const gboolean  Unicode 
)

Returns value of INI file entry.

Parameters
file_infoFile data as returned by INI_ReadFile.
sectionSection to scan.
keyName of key to read.
UnicodeWhether file is unicode.
Returns
Entry value.
Bug:
Unicode should be part of file_info.

Search for key value in file in Windows INI format style Returns found value or NULL

Definition at line 365 of file cfg.c.

References _INI_Entry::EntryName, _INI_Entry::EntryValue, mywstrncasecmp(), _INI_Entry::Next, _INI_Section::Next, _INI_Section::SectionName, and _INI_Section::SubEntries.

Referenced by GSM_ReadConfig(), INI_GetBool(), and INI_GetInt().

366 {
367  INI_Section *sec;
368  INI_Entry *ent;
369 
370  if (cfg == NULL || section == NULL || key == NULL) return NULL;
371 
372  if (Unicode) {
373  /* Search for section */
374  sec = cfg;
375  while (sec != NULL) {
376  if (mywstrncasecmp(section, sec->SectionName, 0)) {
377  /* Search for key inside section */
378  ent = sec->SubEntries;
379  while (ent != NULL) {
380  if (mywstrncasecmp(key,ent->EntryName,0)) {
381  return ent->EntryValue;
382  }
383  ent = ent->Next;
384  }
385  }
386  sec = sec->Next;
387  }
388  } else {
389  /* Search for section */
390  sec = cfg;
391  while (sec != NULL) {
392  if (strcasecmp(section, sec->SectionName) == 0) {
393  /* Search for key inside section */
394  ent = sec->SubEntries;
395  while (ent != NULL) {
396  if (strcasecmp(key,ent->EntryName) == 0) {
397  return ent->EntryValue;
398  }
399  ent = ent->Next;
400  }
401  }
402  sec = sec->Next;
403  }
404  }
405  return NULL;
406 }
gboolean mywstrncasecmp(unsigned const char *a, unsigned const char *b, int num)
Definition: coding.c:1437
INI_Entry * SubEntries
Definition: gammu-inifile.h:54
unsigned char * EntryValue
Definition: gammu-inifile.h:44
Definition: gammu-inifile.h:41
unsigned char * SectionName
Definition: gammu-inifile.h:55
unsigned char * EntryName
Definition: gammu-inifile.h:43
INI_Section * Next
Definition: gammu-inifile.h:53
INI_Entry * Next
Definition: gammu-inifile.h:42

§ INI_ReadFile()

GSM_Error INI_ReadFile ( const char *  FileName,
gboolean  Unicode,
INI_Section **  result 
)

Reads INI data.

Parameters
FileNameFile to read.
UnicodeWhether file shoul be treated like unicode.
resultPointer where file will be read.
Returns
Error code

Read information from file in Windows INI format style

Definition at line 24 of file cfg.c.

References _INI_Entry::EntryName, _INI_Entry::EntryValue, ERR_CANTOPENFILE, ERR_FILENOTSUPPORTED, ERR_MOREMEMORY, ERR_NONE, FALSE, myiswspace(), _INI_Entry::Next, _INI_Section::Next, _INI_Entry::Prev, _INI_Section::SubEntries, and TRUE.

Referenced by GSM_TryReadGammuRC().

25 {
26  FILE *f;
27  gboolean FFEEUnicode=FALSE;
28  int level = -1, buffer1used, buffer2used;
29  size_t bufferused, i, read_buffer_used=1000,read_buffer_pos=1000, num;
30  unsigned char ch[3], *buffer = NULL;
31  unsigned char *buffer2 = NULL, *buffer1 = NULL, read_buffer[1001];
32  INI_Section *INI_info = NULL, *INI_head = NULL, *heading;
33  INI_Entry *entry;
34  GSM_Error error = ERR_NONE;
35 
36  *result = NULL;
37 
38  if (FileName == NULL) {
39  return ERR_CANTOPENFILE;
40  }
41 
42  f = fopen(FileName,"rb");
43  if (f == NULL) {
44  return ERR_CANTOPENFILE;
45  }
46 
47  num = 0;
48  while(1) {
49  /* We read one line from file */
50  bufferused = 0;
51  while (1) {
52  if (read_buffer_used == read_buffer_pos) {
53  read_buffer_used = fread(read_buffer,1,1000,f);
54  read_buffer_pos = 0;
55  if (read_buffer_used == 0) {
56  error = ERR_NONE;
57  goto done;
58  }
59  }
60  if (Unicode) {
61  if (num == 0) {
62  if (read_buffer_used == read_buffer_pos) {
63  continue;
64  }
65  ch[0] = read_buffer[read_buffer_pos++];
66  num = 1;
67  }
68  if (num == 1) {
69  if (read_buffer_used == read_buffer_pos) {
70  continue;
71  }
72  ch[1] = read_buffer[read_buffer_pos++];
73  num = 0;
74  }
75  if (level == -1) {
76  if (ch[0] == 0xFF && ch[1] == 0xFE) FFEEUnicode = TRUE;
77  level = 0;
78  continue;
79  }
80  if (FFEEUnicode) {
81  ch[2] = ch[0]; ch[0] = ch[1]; ch[1] = ch[2];
82  }
83  } else {
84  if (read_buffer_used == read_buffer_pos) {
85  continue;
86  }
87  ch[0] = 0;
88  ch[1] = read_buffer[read_buffer_pos++];
89  if (level == -1) level = 0;
90  }
91  if ((ch[0] == 0 && ch[1] == 13) ||
92  (ch[0] == 0 && ch[1] == 10)) {
93  break;
94  }
95  buffer = (unsigned char *)realloc(buffer,bufferused+2);
96  if (buffer == NULL) {
97  error = ERR_MOREMEMORY;
98  goto done;
99  }
100  buffer[bufferused] = ch[0];
101  buffer[bufferused+1] = ch[1];
102  bufferused = bufferused + 2;
103  }
104 
105  buffer1used = 0;
106  buffer2used = 0;
107  if (level == 1) level = 0;
108  if (level == 3 || level == 4 || level == 5) level = 2;
109 
110  /* We parse read line */
111  for (i=0;i<bufferused/2;i++) {
112  ch[0] = buffer[i*2];
113  ch[1] = buffer[i*2+1];
114  if (level == 0) { /* search for name of section */
115  if (ch[0] == 0 && ch[1] == '[') level = 1;
116  if (ch[0] == 0 && ch[1] == ';') {
117  break;
118  }
119  if (ch[0] == 0 && ch[1] == '#') {
120  break;
121  }
122  continue;
123  }
124  if (level == 1) { /* section name */
125  if (ch[0] == 0 && ch[1] == ']') {
126  if (buffer1used == 0) {
127  break;
128  }
129  if (Unicode) {
130  buffer1 = (unsigned char *)realloc(buffer1,buffer1used+2);
131  buffer1[buffer1used] = 0;
132  buffer1[buffer1used+1] = 0;
133  buffer1used = buffer1used + 2;
134  } else {
135  buffer1 = (unsigned char *)realloc(buffer1,buffer1used+1);
136  buffer1[buffer1used] = 0x00;
137  buffer1used = buffer1used + 1;
138  }
139  heading = (INI_Section *)malloc(sizeof(*heading));
140  if (heading == NULL) {
141  error = ERR_MOREMEMORY;
142  goto done;
143  }
144  heading->SectionName = (char *)malloc(buffer1used);
145  memcpy(heading->SectionName,buffer1,buffer1used);
146  heading->Prev = INI_info;
147  heading->Next = NULL;
148  if (INI_info != NULL) {
149  INI_info->Next = heading;
150  } else {
151  INI_head = heading;
152  }
153  INI_info = heading;
154  INI_info->SubEntries = NULL;
155  level = 2;
156  break;
157  }
158  if (Unicode) {
159  buffer1 = (unsigned char *)realloc(buffer1,buffer1used+2);
160  buffer1[buffer1used] = ch[0];
161  buffer1[buffer1used+1] = ch[1];
162  buffer1used = buffer1used + 2;
163  } else {
164  buffer1 = (unsigned char *)realloc(buffer1,buffer1used+1);
165  buffer1[buffer1used] = ch[1];
166  buffer1used = buffer1used + 1;
167  }
168  continue;
169  }
170  if (level == 2) { /* search for key name */
171  if (ch[0] == 0 && ch[1] == ';') {
172  break;
173  }
174  if (ch[0] == 0 && ch[1] == '#') {
175  break;
176  }
177  if (ch[0] == 0 && ch[1] == '[') {
178  level = 1;
179  continue;
180  }
181  if (Unicode) {
182  if (myiswspace(ch)) {
183  continue;
184  }
185  } else {
186  if (isspace((int) ch[1])) {
187  continue;
188  }
189  }
190  level = 3;
191  }
192  if (level == 3) { /* key name */
193  if (ch[0] == 0 && ch[1] == '=') {
194  if (buffer1used == 0) {
195  break;
196  }
197  while(1) {
198  if (Unicode) {
199  if (!myiswspace(buffer1+(buffer1used-2))) {
200  break;
201  }
202  buffer1used = buffer1used - 2;
203  } else {
204  if (!isspace((int)buffer1[buffer1used-1])) {
205  break;
206  }
207  buffer1used = buffer1used - 1;
208  }
209  }
210  level = 4;
211  continue;
212  }
213  if (Unicode) {
214  buffer1 = (unsigned char *)realloc(buffer1,buffer1used+2);
215  buffer1[buffer1used] = ch[0];
216  buffer1[buffer1used+1] = ch[1];
217  buffer1used = buffer1used + 2;
218  } else {
219  buffer1 = (unsigned char *)realloc(buffer1,buffer1used+1);
220  buffer1[buffer1used] = ch[1];
221  buffer1used = buffer1used + 1;
222  }
223  }
224  if (level == 4) { /* search for key value */
225  if (Unicode) {
226  if (myiswspace(ch)) {
227  continue;
228  }
229  } else {
230  if (isspace((int) ch[1])) {
231  continue;
232  }
233  }
234  level = 5;
235  }
236  if (level == 5) { /* key value */
237  if (Unicode) {
238  buffer2 = (unsigned char *)realloc(buffer2,buffer2used+2);
239  buffer2[buffer2used] = ch[0];
240  buffer2[buffer2used+1] = ch[1];
241  buffer2used = buffer2used + 2;
242  } else {
243  buffer2 = (unsigned char *)realloc(buffer2,buffer2used+1);
244  buffer2[buffer2used] = ch[1];
245  buffer2used = buffer2used + 1;
246  }
247  }
248  }
249  if (level == 5) {
250  if (Unicode) {
251  while (myiswspace(buffer2 + buffer2used - 2) && buffer2used > 0) {
252  buffer2used -= 2;
253  }
254  } else {
255  while (isspace(buffer2[buffer2used - 1]) && buffer2used > 0) {
256  buffer2used -= 1;
257  }
258  }
259  if (buffer2used == 0) {
260  continue;
261  }
262 
263  entry = (INI_Entry *)malloc(sizeof(*entry));
264  if (entry == NULL) {
265  error = ERR_MOREMEMORY;
266  goto done;
267  }
268  if (Unicode) {
269  buffer1 = (unsigned char *)realloc(buffer1,buffer1used+2);
270  buffer1[buffer1used] = 0;
271  buffer1[buffer1used+1] = 0;
272  buffer1used = buffer1used + 2;
273  buffer2 = (unsigned char *)realloc(buffer2,buffer2used+2);
274  buffer2[buffer2used] = 0;
275  buffer2[buffer2used+1] = 0;
276  buffer2used = buffer2used + 2;
277  } else {
278  buffer1 = (unsigned char *)realloc(buffer1,buffer1used+1);
279  buffer1[buffer1used] = 0x00;
280  buffer1used = buffer1used + 1;
281  buffer2 = (unsigned char *)realloc(buffer2,buffer2used+1);
282  buffer2[buffer2used] = 0x00;
283  buffer2used = buffer2used + 1;
284  }
285 
286  entry->EntryName = (char *)malloc(buffer1used);
287  if (entry->EntryName == NULL) {
288  error = ERR_MOREMEMORY;
289  goto done;
290  }
291  memcpy(entry->EntryName,buffer1,buffer1used);
292 
293  entry->EntryValue = (char *)malloc(buffer2used);
294  if (entry->EntryValue == NULL) {
295  error = ERR_MOREMEMORY;
296  goto done;
297  }
298  memcpy(entry->EntryValue,buffer2,buffer2used);
299 
300  entry->Prev = NULL;
301  entry->Next = INI_info->SubEntries;
302  if (INI_info->SubEntries != NULL) {
303  INI_info->SubEntries->Prev = entry;
304  }
305  INI_info->SubEntries = entry;
306  }
307  }
308 done:
309  free(buffer);
310  buffer=NULL;
311  free(buffer1);
312  buffer1=NULL;
313  free(buffer2);
314  buffer2=NULL;
315  fclose(f);
316 
317  if (error == ERR_NONE) {
318  *result = INI_head;
319  if (INI_head == NULL) {
320  error = ERR_FILENOTSUPPORTED;
321  }
322  }
323  return error;
324 }
GSM_Error
Definition: gammu-error.h:23
INI_Entry * Prev
Definition: gammu-inifile.h:42
INI_Entry * SubEntries
Definition: gammu-inifile.h:54
int gboolean
Definition: gammu-types.h:23
#define FALSE
Definition: gammu-types.h:25
unsigned char * EntryValue
Definition: gammu-inifile.h:44
Definition: gammu-inifile.h:41
unsigned char * EntryName
Definition: gammu-inifile.h:43
#define TRUE
Definition: gammu-types.h:28
gboolean myiswspace(unsigned const char *src)
Definition: coding.c:1470
INI_Section * Next
Definition: gammu-inifile.h:53
INI_Entry * Next
Definition: gammu-inifile.h:42