]> git.mxchange.org Git - flightgear.git/blob - utils/fgcom/utils.cxx
fgcom-sa: remove plib, zlib, win dependencies
[flightgear.git] / utils / fgcom / utils.cxx
1 /*
2  * fgcom - VoIP-Client for the FlightGear-Radio-Infrastructure
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or (at your option) any later version.
8  * 
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  * 
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17  * MA  02110-1301, USA.
18  *
19  */
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #ifdef _MSC_VER
26 #include <WinSock2.h> // which included <Windows.h>
27 #else
28 #include <unistd.h>
29 #endif
30
31 #ifdef __APPLE__
32 #include <CoreFoundation/CoreFoundation.h>
33 #include <mach-o/dyld.h> /* for _NSGetExecutablePath() */
34 #endif
35
36 #include <fcntl.h>
37 #include <sys/stat.h>
38
39 #include <simgear/debug/logstream.hxx>
40 #include "fgcom.hxx"
41
42 #ifndef bcopy
43 #define bcopy(from, to, n) memcpy(to, from, n)
44 #endif
45
46 static int s_index;
47 static int s_file_handle;
48 static char *s_content;
49 static int s_size;
50
51 /**
52  *
53  * \fn void parser_init(void)
54  *
55  * \brief Starts parser initialization.
56  *
57  */
58 int parser_init(const char *filename)
59 {
60         struct stat l_stat;
61         ssize_t l_nbytes;
62         int l_status;
63     int oflag = O_RDONLY;
64 #ifdef _MSC_VER
65     oflag |= _O_BINARY; /* if comparing to stat size then must be binary */
66 #endif
67
68         s_index = 0;
69
70         if((s_file_handle = open(filename, oflag)) < 0)
71                 return (s_file_handle);
72
73         fstat(s_file_handle, &l_stat);
74
75         l_status = -1;
76         if((s_content = (char *)malloc((l_stat.st_size + 1) * sizeof(char))) != NULL)
77         {
78                 if((l_nbytes = read(s_file_handle, s_content, l_stat.st_size)) == l_stat.st_size)
79                 {
80                         l_status = 0;
81                         s_size = l_stat.st_size;
82                 }
83         }
84         close(s_file_handle);
85
86         return(l_status);
87 }
88
89 /**
90  *
91  * \fn void parser_exit(void)
92  *
93  * \brief Exits parser.
94  *
95  */
96 void parser_exit(void)
97 {
98         free(s_content);
99 }
100
101 /**
102  *
103  * \fn int parser_get_next_value(const char *line, float *value)
104  *
105  * \brief Extract a numeric value.
106  *
107  * \param line  pointer on the line extracted from the input file.
108  * \param value pointer on the returned value.
109  *
110  * \return Returns 0 if value successfully extracted. Otherwhise, returns
111  * a negative value meaning that an error occured.
112  *
113  */
114 int parser_get_next_value(double *value)
115 {
116         int l_status = 0;
117         unsigned int l_j;
118         unsigned int l_size;
119         char *l_buf;
120
121         /* Check if we are already at the end of the string. */
122         if(s_index >= s_size)
123                 return(-1);
124
125         /* Enter main parser loop. */
126         while((s_index < s_size) && (l_status == 0))
127         {
128                 /* Search for something different than an espace or tab. */
129                 while(  (s_content[s_index] == ' ' || s_content[s_index] == '\t') &&
130                                 (s_index < s_size) )
131                         s_index++;
132
133                 /* If we have reached end of file, we exit now. */
134                 if (s_index >= s_size)
135                         return(-1);
136
137                 /* If character is a CR, we restart for next line. */
138                 if(s_content[s_index] == '\n')
139                 {
140                         s_index++;
141                         continue;
142                 }
143
144                 /* Is it a comment ? */
145                 if(s_content[s_index] == '#')
146                 {
147                         /* Yes, go until end of line. */
148                         while((s_content[s_index] != '\n') && (s_index < s_size))
149                                 s_index++;
150                 }
151                 else
152                 {
153                         /* We have found something that is not a comment. */
154                         while((s_content[s_index] < '0' || s_content[s_index] > '9') && (s_index < s_size))
155                                 s_index++;
156
157                         if(s_index < s_size)
158                         {
159                                 l_j = s_index + 1;
160                                 while(  ((s_content[l_j] >= '0' && s_content[l_j] <= '9') ||
161                                                  (s_content[l_j] == '.' || s_content[l_j] == ',')) &&
162                                                 ((s_content[l_j] != '\n') && (l_j < (unsigned int)s_size)) )
163                                         l_j++;
164
165                                 l_size = l_j - s_index + 1;
166                                 if((l_buf = (char *)malloc(l_size * sizeof(char))) != NULL)
167                                 {
168                                         /* Initialize buffer with O. */
169                                         memset((void *)l_buf, 0, l_size);
170                                         bcopy((const void *)(s_content + s_index), (void *)l_buf, l_size - 1);
171                                         /* Convert string into double. */
172                                         *value = atof(l_buf);
173                                         /* Buffer is not needed any longer. */
174                                         free(l_buf);
175                                         /* Prepare for next value. */
176                                         s_index = l_j + 1;
177                                         break;
178                                 }
179                         }
180                 }
181         } /* while((s_index < s_size) && (l_status == 0)) */
182
183         return(0);
184 }
185
186 /* cross-platform stat and check if directory or file
187  * return 2 == directory
188  * return 1 == file
189  * return 0 == neither
190  * NOTE: Think this fails in Windows if 
191  *       the path has a trailing path separator
192  *       and in some cases even if the path contains a forward (unix) separator
193  * TODO: Should copy the path, and fix it for stat
194  */
195
196 #ifdef _MSC_VER
197 #define M_ISDIR(a) (a & _S_IFDIR)
198 #else
199 #define M_ISDIR S_ISDIR
200 #endif
201
202 int is_file_or_directory( const char * path )
203 {
204     struct stat buf;
205     if ( stat(path,&buf) == 0 ) {
206         if (M_ISDIR(buf.st_mode))
207             return 2;
208         return 1;
209     }
210     return 0;
211 }
212
213 /* trim to base binary path IN BUFFER,
214  * essentially removing the executable name
215  */
216 void trim_base_path_ib( char *path )
217 {
218     size_t len = strlen(path);
219     size_t i, off;
220     int c;
221     off = 0;
222     for (i = 0; i < len; i++) {
223         c = path[i];
224         if (( c == '/' ) || ( c == '\\')) {
225             off = i + 1;    // get after separator
226 #ifdef _MSC_VER
227             if ( c == '/' )
228                 path[i] = '\\';
229 #endif // _MSC_VER
230         }
231     }
232     path[off] = 0;
233 }
234
235 /*
236  * get data path per OS 
237  * In Windows and OSX the compiler only supplies a partial data file path,
238  *  so this is to get the current binary installed path.
239  * In *nix the full path is supplied, so this does nothing, except zero the path
240  *
241  */
242 int get_data_path_per_os( char *path, size_t len )
243 {
244 #if defined(MACOSX)
245 // if we're running as part of an application bundle, return the bundle's
246 // resources directory
247 // The following code looks for the base package inside the application
248 // bundle, in the standard Contents/Resources location.
249     
250   CFURLRef resourcesUrl = CFBundleCopyResourcesDirectoryURL(CFBundleGetMainBundle());
251   if (resourcesUrl) {
252       CFURLGetFileSystemRepresentation(resourcesUrl, true, (UInt8*) path, len);
253       CFRelease(resourcesUrl);
254       // append trailing seperator since CF doesn't
255       len = strlen(path);
256       path[len] = '/';
257       path[len+1] = 0;
258       return 0;
259   }
260   
261 // we're unbundled, simply return the executable path
262     unsigned int size = (unsigned int) len;
263     if (_NSGetExecutablePath(path, &size) == 0)  {
264         // success
265         trim_base_path_ib(path);
266     } else {
267         SG_LOG( SG_GENERAL, SG_ALERT, "ERROR: path buffer too small; need size " << size );
268         return 1;
269     }
270 #elif defined(_MSC_VER)
271     unsigned int size = GetModuleFileName(NULL,path, len);
272     if (size && (size != len)) {
273         // success
274         trim_base_path_ib(path);
275     } else {
276         if (size) {
277             SG_LOG( SG_GENERAL, SG_ALERT, "ERROR: GetModuleFileName: path buffer too small; need size more than " << len );
278         } else {
279             SG_LOG( SG_GENERAL, SG_ALERT, "ERROR: GetModuleFileName FAILED!" );
280         }
281         return 1;
282     }
283 #else
284     path[0] = 0;
285 #endif // MACOSX | _MSC_VER | others   
286     return 0;
287 }
288
289 /* eof - utils.cpp */