ported PrtView plugin
[xonotic/netradiant.git] / libs / profile / profile.cpp
1 /*
2 Copyright (c) 2001, Loki software, inc.
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without modification, 
6 are permitted provided that the following conditions are met:
7
8 Redistributions of source code must retain the above copyright notice, this list 
9 of conditions and the following disclaimer.
10
11 Redistributions in binary form must reproduce the above copyright notice, this
12 list of conditions and the following disclaimer in the documentation and/or
13 other materials provided with the distribution.
14
15 Neither the name of Loki software nor the names of its contributors may be used 
16 to endorse or promote products derived from this software without specific prior 
17 written permission. 
18
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' 
20 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
21 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
22 DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 
23 DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
24 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
25 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
26 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
27 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
28 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
29 */
30
31 //
32 // Application settings load/save
33 //
34 // Leonardo Zide (leo@lokigames.com)
35 //
36
37 #include "profile.h"
38
39 #include <string.h>
40 #include <stdio.h>
41 #include <math.h>
42
43 #include "file.h"
44
45 #include <stdlib.h>
46
47 #include "str.h"
48
49
50 // =============================================================================
51 // Static functions
52
53 bool read_var (const char *filename, const char *section, const char *key, char *value)
54 {
55   char line[1024], *ptr;
56   FILE *rc;
57   
58   rc = fopen (filename, "rt");
59   
60   if (rc == NULL)
61     return false;
62   
63   while (fgets (line, 1024, rc) != 0)
64   {
65     // First we find the section
66     if (line[0] != '[')
67       continue;
68     
69     ptr = strchr (line, ']');
70     *ptr = '\0';
71     
72     if (strcmp (&line[1], section) == 0)
73     {
74       while (fgets (line, 1024, rc) != 0)
75       {
76         ptr = strchr (line, '=');
77
78         if (ptr == NULL)
79         {
80           // reached the end of the section
81           fclose (rc);
82           return false;
83         }
84         *ptr = '\0';
85
86         // remove spaces
87         while (line[strlen(line)-1] == ' ')
88           line[strlen(line)-1] = '\0';
89
90         if (strcmp (line, key) == 0)
91         {
92           strcpy (value, ptr+1);
93           fclose (rc);
94           
95           if (value[strlen (value)-1] == 10 || value[strlen (value)-1] == 13 || value[strlen (value)-1] == 32)
96             value[strlen (value)-1] = 0;
97
98           return true;
99         }
100       }
101     }
102   }
103
104   fclose (rc);
105   return false;
106 }
107
108 bool save_var (const char *filename, const char *section, const char *key, const char *value)
109 {
110   char line[1024], *ptr;
111   MemStream old_rc;
112   bool found;
113   FILE *rc;
114
115   rc = fopen (filename, "rb");
116
117   if (rc != NULL)
118   {
119     unsigned int len;
120     void *buf;
121
122     fseek (rc, 0, SEEK_END);
123     len = ftell (rc);
124     rewind (rc);
125     buf = malloc (len);
126     fread (buf, len, 1, rc);
127     old_rc.write (reinterpret_cast<MemStream::byte_type*>(buf), len);
128     free (buf);
129     fclose (rc);
130     old_rc.Seek (0, SEEK_SET);
131   }
132
133   // TTimo: changed to binary writing. It doesn't seem to affect linux version, and win32 version was happending a lot of '\n'
134   rc = fopen (filename, "wb");
135
136   if (rc == NULL)
137     return false;
138
139   // First we need to find the section
140   found = false;
141   while (old_rc.ReadString (line, 1024) != NULL)
142   {
143     fputs (line, rc);
144
145     if (line[0] == '[')
146     {
147       ptr = strchr (line, ']');
148       *ptr = '\0';
149
150       if (strcmp (&line[1], section) == 0)
151       {
152         found = true;
153         break;
154       }
155     }
156   } 
157
158   if (!found)
159   {
160     fputs ("\n", rc);
161     fprintf (rc, "[%s]\n", section);
162   }
163
164   fprintf (rc, "%s=%s\n", key, value);
165
166   while (old_rc.ReadString (line, 1024) != NULL)
167   {
168     ptr = strchr (line, '=');
169
170     if (ptr != NULL)
171     {
172       *ptr = '\0';
173
174       if (strcmp (line, key) == 0)
175         break;
176  
177       *ptr = '=';
178       fputs (line, rc);
179     }
180     else
181     {
182       fputs (line, rc);
183       break;
184     }
185   }
186
187   while (old_rc.ReadString (line, 1024) != NULL)
188     fputs (line, rc);
189
190   fclose (rc);
191   return true;
192 }
193
194 // =============================================================================
195 // Global functions
196
197 bool profile_save_int (const char *filename, const char *section, const char *key, int value)
198 {
199   char buf[16];
200   sprintf (buf, "%d", value);
201   return save_var (filename, section, key, buf);
202 }
203
204 bool profile_save_float (const char *filename, const char *section, const char *key, float value)
205 {
206   char buf[16];
207   sprintf (buf, "%f", value);
208   return save_var (filename, section, key, buf);
209 }
210
211 bool profile_save_string (const char * filename, const char *section, const char *key, const char *value)
212 {
213   return save_var (filename, section, key, value);
214 }
215
216 bool profile_save_buffer (const char * rc_path, const char *name, void *buffer, unsigned int size)
217 {
218   bool ret = false;
219   char filename[1024];
220   sprintf (filename, "%s/%s.bin", rc_path, name);
221   FILE *f;
222
223   f = fopen (filename, "wb");
224
225   if (f != NULL)
226   {
227     if (fwrite (buffer, size, 1, f) == 1)
228       ret = true;
229
230     fclose (f);
231   }
232
233   return ret;
234 }
235
236 bool profile_load_buffer (const char * rc_path, const char *name, void *buffer, unsigned int *plSize)
237 {
238   char filename[1024];
239   sprintf (filename, "%s/%s.bin", rc_path, name);
240   bool ret = false;
241   unsigned int len;
242   FILE *f;
243
244   f = fopen (filename, "rb");
245
246   if (f != NULL)
247   {
248     fseek (f, 0, SEEK_END);
249     len = ftell (f);
250     rewind (f);
251
252     if (len > *plSize)
253       len = *plSize;
254     else
255       *plSize = len;
256
257     if (fread (buffer, len, 1, f) == 1)
258       ret = true;
259
260     fclose (f);
261   }
262
263   return true;
264 }
265
266 int profile_load_int (const char *filename, const char *section, const char *key, int default_value)
267 {
268   char value[1024];
269
270   if (read_var (filename, section, key, value))
271     return atoi (value);
272   else
273     return default_value;
274 }
275
276 float profile_load_float (const char *filename, const char *section, const char *key, float default_value)
277 {
278   char value[1024];
279
280   if (read_var (filename, section, key, value))
281     return static_cast<float>(atof(value));
282   else
283     return default_value;
284 }
285
286 char* profile_load_string (const char *filename, const char *section, const char *key, const char *default_value)
287 {
288   static Str ret;
289   char value[1024];
290
291   if (read_var (filename, section, key, value))
292     ret = value;
293   else
294     ret = default_value;
295
296   return (char*)ret.GetBuffer();
297 }