rllib  1
rlinifile.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  rlinifile.cpp - description
3  -------------------
4  begin : Tue Jan 02 2001
5  copyright : (C) 2001 by R. Lehrig
6  email : lehrig@t-online.de
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This library is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE as *
13  * published by the Free Software Foundation *
14  * *
15  ***************************************************************************/
16 #include "rldefine.h"
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <stdarg.h>
20 #include <string.h>
21 #ifdef RLWIN32
22 #include <windows.h>
23 #endif
24 #include "rlinifile.h"
25 #include "rlcutil.h"
26 
27 static const char null_string[] = "";
28 
30 {
31  _firstSection = new rlSection; // first section holds names with section name = null_string
32  _firstSection->nextSection = NULL;
33  _firstSection->firstName = NULL;
34  _firstSection->name = new char[1];
35  _firstSection->name[0] = '\0';
37 }
38 
40 {
41  rlSection *section, *last_section;
42 
43  section = _firstSection;
44  while(section != NULL)
45  {
46  deleteSectionNames(section);
47  last_section = section;
48  section = section->nextSection;
49  delete last_section;
50  }
51 }
52 
54 {
55  rlSectionName *name, *last_name;
56 
57  if(section == NULL) return;
58  name = section->firstName;
59  while(name != NULL)
60  {
61  if(name->name != NULL) delete [] name->name;
62  if(name->param != NULL) delete [] name->param;
63  last_name = name;
64  name = name->nextName;
65  delete [] last_name;
66  }
67  if(section->name != NULL) delete [] section->name;
68 }
69 
70 void rlIniFile::copyIdentifier(char *buf, const char *line)
71 {
72  int i = 1;
73  buf[0] = '\0';
74  if(line[0] != '[') return;
75  while(line[i] != ']' && line[i] != '\0')
76  {
77  *buf++ = line[i++];
78  }
79  *buf = '\0';
80 }
81 
82 void rlIniFile::copyName(char *buf, const char *line)
83 {
84  int i = 0;
85  buf[0] = '\0';
86  //while(line[i] > ' ' && line[i] != '=')
87  while(line[i] != '\0' && (line[i] != '=' || (line[i] == '=' && line[i-1] == '\\')))
88  {
89  *buf++ = line[i++];
90  }
91  *buf = '\0';
92  i--; // eventually delete spaces
93  while(i>=0 && (buf[i] == ' ' || buf[i] == '\t'))
94  {
95  buf[i--] = '\0';
96  }
97 }
98 
99 void rlIniFile::copyParam(char *buf, const char *line)
100 {
101  const char *cptr = line;
102  buf[0] = '\0';
103  while(1)
104  {
105  cptr = strchr(cptr,'=');
106  if(cptr == NULL) return;
107  cptr++;
108  if(cptr[-2] != '\\') break;
109  }
110  while((*cptr == ' ' || *cptr == '\t') && *cptr != '\0') cptr++;
111  if(*cptr == '\0') return;
112  while(*cptr != '\0' && *cptr != '\n') *buf++ = *cptr++;
113  *buf = '\0';
114 }
115 
116 int rlIniFile::read(const char *filename)
117 {
118  FILE *fp;
119  char line[rl_PRINTF_LENGTH],
120  name_section[rl_PRINTF_LENGTH],
121  name_name[rl_PRINTF_LENGTH],
122  name_param[rl_PRINTF_LENGTH],
123  *cptr;
124  rlSection *s, *s_old;
125 
126  // delete old content
127  s = _firstSection;
128  while(s != NULL)
129  {
131  s_old = s;
132  s = s->nextSection;
133  delete s_old;
134  }
135 
136  // read the file
138  _firstSection = new rlSection; // first section holds names with section name = null_string
139  _firstSection->nextSection = NULL;
140  _firstSection->firstName = NULL;
141  _firstSection->name = new char[1];
142  _firstSection->name[0] = '\0';
143  fp = fopen(filename,"r");
144  if(fp == NULL) return -1;
145  name_section[0] = name_name[0] = name_param[0] = '\0';
146  while(fgets(line,sizeof(line)-1,fp) != NULL)
147  {
148  cptr = strchr(line,0x0d);
149  if(cptr != NULL) *cptr = '\0';
150  cptr = strchr(line,0x0a);
151  if(cptr != NULL) *cptr = '\0';
152  if(line[0] == '[') // section identifier
153  {
154  copyIdentifier(name_section,line);
155  setText(name_section, NULL, NULL);
156  }
157  else if(line[0] > ' ' && line[0] != '\t' && line[0] != '#') // name identifier
158  {
159  copyName(name_name,line);
160  copyParam(name_param,line);
161  setText(name_section, name_name, name_param);
162  }
163  else // it must be a comment line
164  {
165  setText(name_section, line, NULL);
166  }
167  }
168  fclose(fp);
169  return 0;
170 }
171 
172 int rlIniFile::write(const char *filename)
173 {
174  FILE *fp;
175  rlSection *s;
176  rlSectionName *n;
177 
178  fp = fopen(filename,"w");
179  if(fp == NULL) return -1;
180 
181  s = _firstSection;
182  while(s != NULL)
183  {
184  if (s->name[0] == '#') fprintf(fp,"%s\n",s->name);
185  else if(s->name[0] == '\0') ;
186  else fprintf(fp,"[%s]\n",s->name);
187  n = s->firstName;
188  while(n != NULL)
189  {
190  if (n->name[0] == '#') fprintf(fp,"%s\n",n->name);
191  else if(n->name[0] == '\0') fprintf(fp,"\n");
192  else if(n->param[0] == '\0') fprintf(fp,"\n");
193  else fprintf(fp,"%s=%s\n",n->name,n->param);
194  n = n->nextName;
195  }
196  s = s->nextSection;
197  }
198 
199  fclose(fp);
200  return 0;
201 }
202 
203 const char *rlIniFile::filename()
204 {
205  return fname.text();
206 }
207 
208 const char *rlIniFile::text(const char *section, const char *name)
209 {
210  rlSection *s;
211  rlSectionName *n;
212 
213  s = _firstSection;
214  while(s != NULL)
215  {
216  if(strcmp(section,s->name) == 0)
217  {
218  n = s->firstName;
219  while(n != NULL)
220  {
221  if(n->name != NULL && strcmp(name,n->name) == 0)
222  {
223  return n->param;
224  }
225  n = n->nextName;
226  }
227  return null_string;
228  }
229  s = s->nextSection;
230  }
231  return null_string;
232 }
233 
234 void rlIniFile::setText(const char *section, const char *name, const char *text)
235 {
236  rlSection *s, *last_section;
237  rlSectionName *n, *last_name;
238 
239  if(section == NULL) return;
240  last_section = NULL;
241  last_name = NULL;
242  s = _firstSection;
243  while(s != NULL)
244  {
245  if(strcmp(section,s->name) == 0)
246  {
247  last_name = NULL;
248  n = s->firstName;
249  while(n != NULL)
250  {
251  if(name != NULL && name[0] != '#' && name[0] != '\0' && strcmp(name,n->name) == 0)
252  {
253  if(n->param != NULL) delete [] n->param;
254  if(text == NULL)
255  {
256  n->param = new char[1];
257  n->param[0] = '\0';
258  }
259  else
260  {
261  n->param = new char[strlen(text)+1];
262  strcpy(n->param,text);
263  }
264  return;
265  }
266  last_name = n;
267  n = n->nextName;
268  }
269  if(last_name == NULL)
270  {
271  s->firstName = new rlSectionName;
272  n = s->firstName;
273  }
274  else
275  {
276  last_name->nextName = new rlSectionName;
277  n = last_name->nextName;
278  }
279  if(name == NULL)
280  {
281  n->name = new char[1];
282  n->name[0] = '\0';
283  }
284  else
285  {
286  n->name = new char[strlen(name)+1];
287  strcpy(n->name,name);
288  }
289  if(text == NULL)
290  {
291  n->param = new char[1];
292  n->param[0] = '\0';
293  }
294  else
295  {
296  n->param = new char[strlen(text)+1];
297  strcpy(n->param,text);
298  }
299  n->nextName = NULL;
300  return;
301  }
302  last_section = s;
303  s = s->nextSection;
304  }
305  if(last_section == NULL)
306  {
307  _firstSection = new rlSection;
308  last_section = _firstSection;
309  }
310  else
311  {
312  last_section->nextSection = new rlSection;
313  last_section = last_section->nextSection;
314  }
315  last_section->name = new char[strlen(section)+1];
316  strcpy(last_section->name,section);
317  last_section->nextSection = NULL;
318  if(name == NULL)
319  {
320  last_section->firstName = NULL;
321  }
322  else
323  {
324  last_section->firstName = new rlSectionName;
325  n = last_section->firstName;
326  n->name = new char[strlen(name)+1];
327  strcpy(n->name,name);
328  if(text == NULL)
329  {
330  n->param = new char[1];
331  n->param[0] = '\0';
332  }
333  else
334  {
335  n->param = new char[strlen(text)+1];
336  strcpy(n->param,text);
337  }
338  n->nextName = NULL;
339  }
340  return;
341 }
342 
343 int rlIniFile::printf(const char *section, const char *name, const char *format, ...)
344 {
345  int ret;
346  char buf[rl_PRINTF_LENGTH]; // should be big enough
347 
348  va_list ap;
349  va_start(ap,format);
350  ret = rlvsnprintf(buf, rl_PRINTF_LENGTH - 1, format, ap);
351  va_end(ap);
352  if(ret > 0) setText(section, name, buf);
353  return ret;
354 }
355 
356 void rlIniFile::remove(const char *section)
357 {
358  rlSection *s, *last;
359 
360  last = NULL;
361  s = _firstSection;
362  while(s != NULL)
363  {
364  if(strcmp(section,s->name) == 0)
365  {
367  if(last != NULL) last->nextSection = s->nextSection;
368  if (s == _firstSection)
369  _firstSection = NULL;
370  delete s;
371  return;
372  }
373  last = s;
374  s = s->nextSection;
375  }
376 }
377 
378 void rlIniFile::remove(const char *section, const char *name)
379 {
380  rlSection *s;
381  rlSectionName *n, *last;
382 
383  s = _firstSection;
384  while(s != NULL)
385  {
386  if(strcmp(section,s->name) == 0)
387  {
388  last = NULL;
389  n = s->firstName;
390  while(n != NULL)
391  {
392  if(strcmp(name,n->name) == 0)
393  {
394  if(n->name != NULL) delete [] n->name;
395  if(n->param != NULL) delete [] n->param;
396  if(last != NULL) last->nextName = n->nextName;
397  if (n == s->firstName)
398  s->firstName = NULL;
399  delete n;
400  return;
401  }
402  last = n;
403  n = n->nextName;
404  }
405  return;
406  }
407  s = s->nextSection;
408  }
409 }
410 
412 {
413  currentSection = 0;
414  return _firstSection->name;
415 }
416 
418 {
419  rlSection *s;
420  int i;
421 
422  if(currentSection < 0) return NULL;
423  currentSection++;
424  i = 0;
425  s = _firstSection;
426  while(s != NULL)
427  {
428  if(i == currentSection) return s->name;
429  s = s->nextSection;
430  i++;
431  }
432  currentSection = -1;
433  return NULL;
434 }
435 
436 const char *rlIniFile::firstName(const char *section)
437 {
438  rlSection *s;
439  rlSectionName *n;
440 
441  s = _firstSection;
442  while(s != NULL)
443  {
444  if(strcmp(section,s->name) == 0)
445  {
446  n = s->firstName;
447  currentName = 0;
448  return n->name;
449  }
450  s = s->nextSection;
451  }
452  return NULL;
453 }
454 
455 const char *rlIniFile::nextName(const char *section)
456 {
457  rlSection *s;
458  rlSectionName *n;
459  int i;
460 
461  if(currentName < 0) return NULL;
462  currentName++;
463  i = 0;
464  s = _firstSection;
465  while(s != NULL)
466  {
467  if(strcmp(section,s->name) == 0)
468  {
469  n = s->firstName;
470  while(n != NULL)
471  {
472  if(i == currentName) return n->name;
473  i++;
474  n = n->nextName;
475  }
476  return NULL;
477  }
478  s = s->nextSection;
479  }
480  return NULL;
481 }
482 
483 void rlIniFile::setDefaultSection(const char *section)
484 {
485  default_section.setText(section);
486 }
487 
489 {
490  return default_section.text();
491 }
492 
493 const char *rlIniFile::i18n(const char *tag, const char *default_text)
494 {
495  const char *cptr = text(default_section.text(), tag);
496  if(strcmp(cptr,null_string) == 0) return default_text;
497  else return cptr;
498 }
499 
500 const char *rlIniFile::tr(const char *txt)
501 {
502  if(txt == NULL) return "ERROR:txt=NULL";
503  char default_text[1024];
504  if(strlen(txt) < (sizeof(default_text) - 40)) sprintf(default_text,"tr_error:%s", txt);
505  else strcpy(default_text,"tr_error:text too long");
506  return i18n(txt,default_text);
507 }
508 
509 // Translator
510 static rlIniFile *trIniFile = NULL;
511 
512 int rlSetTranslator(const char *language, const char *inifile)
513 {
514  if(inifile != NULL)
515  {
516  if(trIniFile == NULL) trIniFile = new rlIniFile();
517  if(trIniFile->read(inifile) < 0) return -1;
518  }
519  trIniFile->setDefaultSection(language);
520  return 0;
521 }
522 
523 static const char *fixquote(const char *text, char **mytext)
524 {
525  if(strchr(text,'\\') == NULL) return text;
526  int len = strlen(text);
527  if(*mytext != NULL) delete [] *mytext;
528  *mytext = new char[len+1];
529  char *temp = *mytext;
530  int i2 = 0;
531  for(int i=0; i<len; i++)
532  {
533  if (text[i] == '\\' && text[i+1] == '=') { temp[i2] = '='; i++; }
534  else if(text[i] == '\\' && text[i+1] == 'n') { temp[i2] = '\n'; i++; }
535  else if(text[i] == '\\' && text[i+1] == 't') { temp[i2] = '\t'; i++; }
536  else if(text[i] == '\\' && text[i+1] == '\\') { temp[i2] = '\\'; i++; }
537  else { temp[i2] = text[i]; }
538  i2++;
539  }
540  temp[i2] = '\0';
541  //printf("fixquote(%s) return=%s\n", text, temp);
542  return temp;
543 }
544 
545 const char *rltranslate(const char *txt, char **mytext)
546 {
547  if(trIniFile == NULL) return fixquote(txt,mytext); // use original language because translator is not initalized
548  const char *text = trIniFile->i18n(txt,"@"); // translate
549  if(strcmp(text,"@") == 0) return fixquote(txt,mytext); // use original language because there is no tranlation available
550  return fixquote(text,mytext); // return the translated text
551 }
552 
553 const char *rltranslate2(const char *section, const char *txt, char **mytext)
554 {
555  //printf("rltranslate2(%s,%s) mytext=%s\n", section, txt, *mytext);
556  if(trIniFile == NULL) return fixquote(txt,mytext); // use original language because translator is not initalized
557  if(*section == '\0') return rltranslate(txt,mytext); // user did not call pvSelectLanguage()
558  const char *text = trIniFile->text(section,txt); // translate
559  if(text[0] == '\0') return fixquote(txt,mytext); // use original language because there is no tranlation available
560  return fixquote(text,mytext); // return the translated text
561 }
562 
563 
virtual ~rlIniFile()
Definition: rlinifile.cpp:39
void copyName(char *buf, const char *line)
Definition: rlinifile.cpp:82
static rlIniFile * trIniFile
Definition: rlinifile.cpp:510
const char * nextSection()
Definition: rlinifile.cpp:417
const char * tr(const char *txt)
Definition: rlinifile.cpp:500
const char * i18n(const char *tag, const char *default_text="")
Definition: rlinifile.cpp:493
const char * text(const char *section, const char *name)
Definition: rlinifile.cpp:208
void copyIdentifier(char *buf, const char *line)
Definition: rlinifile.cpp:70
struct rlIniFile::_rlSectionName_ rlSectionName
int read(const char *filename)
Definition: rlinifile.cpp:116
const char * rltranslate(const char *txt, char **mytext)
Definition: rlinifile.cpp:545
#define rl_PRINTF_LENGTH
Definition: rldefine.h:71
int currentSection
Definition: rlinifile.h:109
char * text()
Definition: rlstring.cpp:126
int rlSetTranslator(const char *language, const char *inifile)
Definition: rlinifile.cpp:512
void deleteSectionNames(rlSection *section)
Definition: rlinifile.cpp:53
void setText(const char *section, const char *name, const char *text)
Definition: rlinifile.cpp:234
int currentName
Definition: rlinifile.h:109
int rlvsnprintf(char *text, int len, const char *format, va_list ap)
Definition: rlcutil.cpp:197
void copyParam(char *buf, const char *line)
Definition: rlinifile.cpp:99
int setText(const char *text)
Definition: rlstring.cpp:136
const char * firstSection()
Definition: rlinifile.cpp:411
rlString fname
Definition: rlinifile.h:110
rlSectionName * firstName
Definition: rlinifile.h:100
const char * defaultSection()
Definition: rlinifile.cpp:488
static const char * fixquote(const char *text, char **mytext)
Definition: rlinifile.cpp:523
static const char null_string[]
Definition: rlinifile.cpp:27
const char * filename()
Definition: rlinifile.cpp:203
void setDefaultSection(const char *section)
Definition: rlinifile.cpp:483
_rlSection_ * nextSection
Definition: rlinifile.h:99
_rlSectionName_ * nextName
Definition: rlinifile.h:92
const char * rltranslate2(const char *section, const char *txt, char **mytext)
Definition: rlinifile.cpp:553
rlSection * _firstSection
Definition: rlinifile.h:108
int printf(const char *section, const char *name, const char *format,...)
Definition: rlinifile.cpp:343
struct rlIniFile::_rlSection_ rlSection
const char * nextName(const char *section)
Definition: rlinifile.cpp:455
const char * firstName(const char *section)
Definition: rlinifile.cpp:436
rlString default_section
Definition: rlinifile.h:111
void remove(const char *section)
Definition: rlinifile.cpp:356
int write(const char *filename)
Definition: rlinifile.cpp:172