71d2ae1b9c18b250cae0e987d042764a7c1f8d11
[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         char line[1024], *ptr;
55         FILE *rc;
56
57         rc = fopen( filename, "rt" );
58
59         if ( rc == NULL ) {
60                 return false;
61         }
62
63         while ( fgets( line, 1024, rc ) != 0 )
64         {
65                 // First we find the section
66                 if ( line[0] != '[' ) {
67                         continue;
68                 }
69
70                 ptr = strchr( line, ']' );
71                 *ptr = '\0';
72
73                 if ( strcmp( &line[1], section ) == 0 ) {
74                         while ( fgets( line, 1024, rc ) != 0 )
75                         {
76                                 ptr = strchr( line, '=' );
77
78                                 if ( ptr == NULL ) {
79                                         // reached the end of the section
80                                         fclose( rc );
81                                         return false;
82                                 }
83                                 *ptr = '\0';
84
85                                 // remove spaces
86                                 while ( line[strlen( line ) - 1] == ' ' )
87                                         line[strlen( line ) - 1] = '\0';
88
89                                 if ( strcmp( line, key ) == 0 ) {
90                                         strcpy( value, ptr + 1 );
91                                         fclose( rc );
92
93                                         if ( value[strlen( value ) - 1] == 10 || value[strlen( value ) - 1] == 13 || value[strlen( value ) - 1] == 32 ) {
94                                                 value[strlen( value ) - 1] = 0;
95                                         }
96
97                                         return true;
98                                 }
99                         }
100                 }
101         }
102
103         fclose( rc );
104         return false;
105 }
106
107 bool save_var( const char *filename, const char *section, const char *key, const char *value ){
108         char line[1024], *ptr;
109         MemStream old_rc;
110         bool found;
111         FILE *rc;
112
113         rc = fopen( filename, "rb" );
114
115         if ( rc != NULL ) {
116                 unsigned int len;
117                 void *buf;
118
119                 fseek( rc, 0, SEEK_END );
120                 len = ftell( rc );
121                 rewind( rc );
122                 buf = malloc( len );
123                 fread( buf, len, 1, rc );
124                 old_rc.write( reinterpret_cast<MemStream::byte_type*>( buf ), len );
125                 free( buf );
126                 fclose( rc );
127                 old_rc.Seek( 0, SEEK_SET );
128         }
129
130         // TTimo: changed to binary writing. It doesn't seem to affect linux version, and win32 version was happending a lot of '\n'
131         rc = fopen( filename, "wb" );
132
133         if ( rc == NULL ) {
134                 return false;
135         }
136
137         // First we need to find the section
138         found = false;
139         while ( old_rc.ReadString( line, 1024 ) != NULL )
140         {
141                 fputs( line, rc );
142
143                 if ( line[0] == '[' ) {
144                         ptr = strchr( line, ']' );
145                         *ptr = '\0';
146
147                         if ( strcmp( &line[1], section ) == 0 ) {
148                                 found = true;
149                                 break;
150                         }
151                 }
152         }
153
154         if ( !found ) {
155                 fputs( "\n", rc );
156                 fprintf( rc, "[%s]\n", section );
157         }
158
159         fprintf( rc, "%s=%s\n", key, value );
160
161         while ( old_rc.ReadString( line, 1024 ) != NULL )
162         {
163                 ptr = strchr( line, '=' );
164
165                 if ( ptr != NULL ) {
166                         *ptr = '\0';
167
168                         if ( strcmp( line, key ) == 0 ) {
169                                 break;
170                         }
171
172                         *ptr = '=';
173                         fputs( line, rc );
174                 }
175                 else
176                 {
177                         fputs( line, rc );
178                         break;
179                 }
180         }
181
182         while ( old_rc.ReadString( line, 1024 ) != NULL )
183                 fputs( line, rc );
184
185         fclose( rc );
186         return true;
187 }
188
189 // =============================================================================
190 // Global functions
191
192 bool profile_save_int( const char *filename, const char *section, const char *key, int value ){
193         char buf[16];
194         sprintf( buf, "%d", value );
195         return save_var( filename, section, key, buf );
196 }
197
198 bool profile_save_float( const char *filename, const char *section, const char *key, float value ){
199         char buf[16];
200         sprintf( buf, "%f", value );
201         return save_var( filename, section, key, buf );
202 }
203
204 bool profile_save_string( const char * filename, const char *section, const char *key, const char *value ){
205         return save_var( filename, section, key, value );
206 }
207
208 bool profile_save_buffer( const char * rc_path, const char *name, void *buffer, unsigned int size ){
209         bool ret = false;
210         char filename[1024];
211         sprintf( filename, "%s/%s.bin", rc_path, name );
212         FILE *f;
213
214         f = fopen( filename, "wb" );
215
216         if ( f != NULL ) {
217                 if ( fwrite( buffer, size, 1, f ) == 1 ) {
218                         ret = true;
219                 }
220
221                 fclose( f );
222         }
223
224         return ret;
225 }
226
227 bool profile_load_buffer( const char * rc_path, const char *name, void *buffer, unsigned int *plSize ){
228         char filename[1024];
229         sprintf( filename, "%s/%s.bin", rc_path, name );
230         bool ret = false;
231         unsigned int len;
232         FILE *f;
233
234         f = fopen( filename, "rb" );
235
236         if ( f != NULL ) {
237                 fseek( f, 0, SEEK_END );
238                 len = ftell( f );
239                 rewind( f );
240
241                 if ( len > *plSize ) {
242                         len = *plSize;
243                 }
244                 else{
245                         *plSize = len;
246                 }
247
248                 if ( fread( buffer, len, 1, f ) == 1 ) {
249                         ret = true;
250                 }
251
252                 fclose( f );
253         }
254
255         return true;
256 }
257
258 int profile_load_int( const char *filename, const char *section, const char *key, int default_value ){
259         char value[1024];
260
261         if ( read_var( filename, section, key, value ) ) {
262                 return atoi( value );
263         }
264         else{
265                 return default_value;
266         }
267 }
268
269 float profile_load_float( const char *filename, const char *section, const char *key, float default_value ){
270         char value[1024];
271
272         if ( read_var( filename, section, key, value ) ) {
273                 return static_cast<float>( atof( value ) );
274         }
275         else{
276                 return default_value;
277         }
278 }
279
280 char* profile_load_string( const char *filename, const char *section, const char *key, const char *default_value ){
281         static Str ret;
282         char value[1024];
283
284         if ( read_var( filename, section, key, value ) ) {
285                 ret = value;
286         }
287         else{
288                 ret = default_value;
289         }
290
291         return (char*)ret.GetBuffer();
292 }