1 /*
2  * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 /**
17  * @file picopal.c
18  *
19  * pico platform abstraction layer
20  *
21  * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland
22  * All rights reserved.
23  *
24  * History:
25  * - 2009-04-20 -- initial version
26  *
27  */
28 
29 /* GCC does not supporte #pragma message */
30 #if !defined(__GNUC__)
31 #define PRAGMA_MESSAGE
32 #endif
33 
34 #if defined(PRAGMA_MESSAGE) && defined(PICO_PLATFORM)
35 #pragma message("PICO_PLATFORM       : is defined externally")
36 #endif
37 
38 #if defined(PRAGMA_MESSAGE) && defined(_WIN32)
39 #pragma message("_WIN32              : is defined")
40 #endif
41 
42 #if defined(PRAGMA_MESSAGE) && defined(__APPLE__)
43 #pragma message("__APPLE__           : is defined")
44 #endif
45 
46 #if defined(PRAGMA_MESSAGE) && defined(__MACH__)
47 #pragma message("__MACH__            : is defined")
48 #endif
49 
50 #if defined(PRAGMA_MESSAGE) && defined(macintosh)
51 #pragma message("macintosh           : is defined")
52 #endif
53 
54 #if defined(PRAGMA_MESSAGE) && defined(linux)
55 #pragma message("linux               : is defined")
56 #endif
57 #if defined(PRAGMA_MESSAGE) && defined(__linux__)
58 #pragma message("__linux__           : is defined")
59 #endif
60 #if defined(PRAGMA_MESSAGE) && defined(__linux)
61 #pragma message("__linux             : is defined")
62 #endif
63 
64 
65 #include <stdlib.h>
66 #include <string.h>
67 #include <stdio.h>
68 #include <stdarg.h>
69 
70 #include "picodefs.h"
71 #include "picopal.h"
72 
73 #ifdef __cplusplus
74 extern "C" {
75 #endif
76 #if 0
77 }
78 #endif
79 
80 #if PICO_PLATFORM == PICO_Windows
81 /* use high-resolution timer functions on Windows platform */
82 #define USE_CLOCK 0
83 #else
84 /* use clock() function instead of high-resolution timer on
85    non-Windows platforms */
86 #define USE_CLOCK 1
87 #endif
88 
89 #include <time.h>
90 #if PICO_PLATFORM == PICO_Windows
91 #include <windows.h>
92 #endif
93 
94 #if defined(PRAGMA_MESSAGE)
95 #pragma message("PICO_PLATFORM       : " PICO_PLATFORM_STRING)
96 #endif
97 
98 
picopal_atoi(const picopal_char * s)99 picopal_int32 picopal_atoi(const picopal_char *s) {
100   return (picopal_int32)atoi((const char *)s);
101 }
102 
picopal_strcmp(const picopal_char * a,const picopal_char * b)103 picopal_int32 picopal_strcmp(const picopal_char *a, const picopal_char *b) {
104   return (picopal_int32)strcmp((const char *)a, (const char *)b);
105 }
106 
picopal_strncmp(const picopal_char * a,const picopal_char * b,picopal_objsize_t siz)107 picopal_int32 picopal_strncmp(const picopal_char *a, const picopal_char *b, picopal_objsize_t siz) {
108   return (picopal_int32)strncmp((const char *)a, (const char *)b, (size_t) siz);
109 }
110 
picopal_strlen(const picopal_char * s)111 picopal_objsize_t picopal_strlen(const picopal_char *s) {
112   return (picopal_objsize_t)strlen((const char *)s);
113 }
114 
picopal_strchr(const picopal_char * s,picopal_char c)115 picopal_char *picopal_strchr(const picopal_char *s, picopal_char c) {
116   return (picopal_char *)strchr((const char *)s, (int)c);
117 }
118 
picopal_strstr(const picopal_char * s,const picopal_char * substr)119 picopal_char *picopal_strstr(const picopal_char *s, const picopal_char *substr) {
120   return (picopal_char *)strstr((const char *)s, (const char *)substr);
121 }
122 
picopal_strcpy(picopal_char * d,const picopal_char * s)123 picopal_char *picopal_strcpy(picopal_char *d, const picopal_char *s) {
124   return (picopal_char *)strcpy((char *)d, (const char *)s);
125 }
126 
picopal_strcat(picopal_char * dest,const picopal_char * src)127 picopal_char *picopal_strcat(picopal_char *dest, const picopal_char *src) {
128   return (picopal_char *)strcat((char *)dest, (const char *)src);
129 }
130 
131 
132 /* copy src into dst, but make sure that dst is not accessed beyond its size 'siz' and is allways NULLC-terminated.
133  * 'siz' is the number of bytes of the destination, including one byte for NULLC!
134  * returns the full length of the input string, not including termination NULLC (strlen(src)).
135  * the copy is successfull without truncation if picopal_strlcpy(dst,src,siz) < siz */
picopal_strlcpy(picopal_char * dst,const picopal_char * src,picopal_objsize_t siz)136 picopal_objsize_t picopal_strlcpy(picopal_char *dst, const picopal_char *src, picopal_objsize_t siz)
137 {
138         picopal_char *d = dst;
139         const picopal_char *s = src;
140         picopal_objsize_t n = siz;
141 
142         /* Copy as many bytes as will fit */
143         if (n != 0) {
144                 while (--n != 0) {
145                         if ((*(d++) = *(s++)) == NULLC) {
146                                 break;
147                         }
148                 }
149         }
150 
151         /* Not enough room in dst, add NULLC and traverse rest of src */
152         if (n == 0) {
153                 if (siz != 0) {
154                         *d = NULLC;                /* NULLC-terminate dst */
155                 }
156                 while (*(s++)) {}
157                         ;
158         }
159 
160         return(s - src - 1);        /* count does not include NULLC */
161 }
162 
163 
picopal_sprintf(picopal_char * dst,const picopal_char * fmt,...)164 picopal_int16 picopal_sprintf(picopal_char * dst, const picopal_char *fmt, ...)
165 {
166     picopal_int16 i;
167     va_list args;
168 
169     va_start(args, (char *)fmt);
170     i = (picopal_int16)vsprintf((char *) dst, (const char *)fmt, args);
171     va_end(args);
172     return i;
173 }
174 
175 
picopal_vslprintf(picopal_char * dst,picopal_objsize_t siz,const picopal_char * fmt,va_list args)176 picopal_objsize_t picopal_vslprintf(picopal_char * dst, picopal_objsize_t siz, const picopal_char *fmt, va_list args) {
177     picopal_char buf[21];
178     picopal_char *d = dst;
179     const picopal_char *f = fmt;
180     picopal_char * b;
181     picopal_objsize_t len, nnew, n = siz;
182     picopal_int32 ival;
183     picopal_char cval;
184     picopal_objsize_t i = 0;
185 
186     if (!f) {
187         f = (picopal_char *) "";
188     }
189     while (*f) {
190         if (*f == '%') {
191             switch (*(++f)) {
192                 case 'i':
193                     f++;
194                     ival = va_arg(args,int);
195                     picopal_sprintf(buf,(picopal_char *)"%i",ival);
196                     b = buf;
197                     break;
198                 case 'c':
199                     f++;
200                     cval = va_arg(args,int);
201                     picopal_sprintf(buf,(picopal_char *)"%c",cval);
202                     b = buf;
203                     break;
204                 case 's':
205                     f++;
206                     b = (picopal_char *) va_arg(args, char*);
207                     break;
208                 default:
209                     if (n > 0) {
210                         (*d++) = '%';
211                         n--;
212                     }
213                     i++;
214                     b = NULL;
215                     break;
216             }
217             if (b) {
218                 len = picopal_strlcpy(d,b,n); /* n1 is the actual length of sval */
219                 i += len;
220                 nnew = (n > len) ? n-len : 0; /* nnew is the new value of n */
221                 d += (n - nnew);
222                 n = nnew;
223             }
224         } else {
225             if (n) {
226                 (*d++) = (*f);
227                 n--;
228             }
229             i++;
230             f++;
231         }
232     }
233 
234     return i;
235 }
236 
picopal_slprintf(picopal_char * dst,picopal_objsize_t siz,const picopal_char * fmt,...)237 picopal_objsize_t picopal_slprintf(picopal_char * dst, picopal_objsize_t siz, const picopal_char *fmt, /*args*/ ...) {
238     picopal_objsize_t i;
239     va_list args;
240 
241     va_start(args, (char *)fmt);
242     i = picopal_vslprintf(dst, siz, fmt, args);
243     va_end(args);
244     return i;
245 
246 }
247 
248 
249 /* copies 'length' bytes from 'src' to 'dest'. (regions may be overlapping) no error checks! */
picopal_mem_copy(const void * src,void * dst,picopal_objsize_t length)250 void * picopal_mem_copy(const void * src, void * dst, picopal_objsize_t length)
251 {
252     return memmove(dst, src, (size_t) length);
253 }
254 
255 /* sets 'length' bytes starting at dest[0] to 'byte_val' */
picopal_mem_set(void * dest,picopal_uint8 byte_val,picopal_objsize_t length)256 void * picopal_mem_set(void * dest, picopal_uint8 byte_val, picopal_objsize_t length)
257 {
258     return memset(dest, (int) byte_val, (size_t) length);
259 }
260 
261 /* *************************************************/
262 /* fixed-point math                                */
263 /* *************************************************/
264 
265 /* *************************************************/
266 /* transcendent math                                */
267 /* *************************************************/
268 
269 
picopal_cos(const picopal_double cos_arg)270 picopal_double picopal_cos(const picopal_double cos_arg)
271 {
272     return (picopal_double) cos((double)cos_arg);
273 }
picopal_sin(const picopal_double sin_arg)274 picopal_double picopal_sin(const picopal_double sin_arg)
275 {
276     return (picopal_double) sin((double) sin_arg);
277 }
picopal_fabs(const picopal_double fabs_arg)278 picopal_double picopal_fabs(const picopal_double fabs_arg)
279 {
280     return (picopal_double) fabs((double) fabs_arg);
281 }
282 
283 
284 /* *************************************************/
285 /* file access                                     */
286 /* *************************************************/
287 #define PICOPAL_EOL '\n'
288 
picopal_eol(void)289 picopal_char picopal_eol(void)
290 {
291     return PICOPAL_EOL;
292 }
293 
294 /* 'fopen' opens the file with name 'filename'. Depending on
295    'mode' :
296       'PICOPAL_TEXT_READ'    : Opens an existing text file for reading.
297                       The file is positioned at the beginning of the file.
298       'PICOPAL_TEXT_WRITE'   : Opens and truncates an existing file or creates a new
299                       text file for writing. The file is positioned at the
300                       beginning.
301       'PICOPAL_BIN_READ'  : Opens an existing binary file for reading.
302                       The file is positioned at the beginning of the file.
303       'PICOPAL_BIN_WRITE' : Opens and truncates an existing file or creates a new
304                       binary file for writing. The file is positioned at the
305                       beginning.
306     If the opening of the file is successful a file pointer is given
307     back. Otherwise a NIL-File is given back.
308 */
picopal_fopen(picopal_char filename[],picopal_access_mode mode)309 picopal_File picopal_fopen (picopal_char filename[], picopal_access_mode mode)
310 {
311     picopal_File res;
312 
313      switch (mode) {
314      case PICOPAL_TEXT_READ :
315          res = (picopal_File) fopen((char *)filename, (char *)"r");
316          break;
317      case PICOPAL_TEXT_WRITE :
318          res = (picopal_File) fopen((char *)filename, (char *)"w");
319          break;
320      case PICOPAL_BINARY_READ :
321          res = (picopal_File) fopen((char *)filename, (char *)"rb");
322          break;
323      case PICOPAL_BINARY_WRITE :
324          res = (picopal_File) fopen((char *)filename, (char *)"wb");
325          break;
326      default :
327          res = (picopal_File) NULL;
328      }
329      return res;
330 
331 }
332 
333 
picopal_get_fnil(void)334 picopal_File picopal_get_fnil (void)
335 {
336     return (picopal_File) NULL;
337 }
338 
339 
picopal_is_fnil(picopal_File f)340 picopal_int8 picopal_is_fnil (picopal_File f)
341 {
342     return (NULL == f);
343 }
344 
picopal_fflush(picopal_File f)345 pico_status_t picopal_fflush (picopal_File f)
346 {
347     return (0 == fflush((FILE *)f)) ? PICO_OK : PICO_EOF;
348 }
349 
350 
picopal_fclose(picopal_File f)351 pico_status_t picopal_fclose (picopal_File f)
352 {
353     return (0 == fclose((FILE *)f)) ? PICO_OK : PICO_EOF;
354 }
355 
356 
357 
picopal_flength(picopal_File stream)358 picopal_uint32 picopal_flength (picopal_File stream)
359 {
360     fpos_t fpos;
361     picopal_int32 len;
362 
363     fgetpos((FILE *)stream,&fpos);
364     picopal_fseek(stream,0,SEEK_END);
365     len = ftell((FILE *)stream);
366     fsetpos((FILE *)stream,&fpos);
367     clearerr((FILE *)stream);
368     return len;
369 
370 }
371 
picopal_feof(picopal_File stream)372 picopal_uint8 picopal_feof (picopal_File stream)
373 {
374     return (0 != feof((FILE *)stream));
375 
376 }
377 
picopal_fseek(picopal_File f,picopal_uint32 offset,picopal_int8 seekmode)378 pico_status_t picopal_fseek (picopal_File f, picopal_uint32 offset, picopal_int8 seekmode)
379 {
380     return (0 == fseek((FILE *)f, offset, seekmode)) ? PICO_OK : PICO_EOF;
381 }
382 
picopal_fget_char(picopal_File f,picopal_char * ch)383 pico_status_t picopal_fget_char (picopal_File f, picopal_char * ch)
384 {
385     picopal_int16 res;
386 
387     res = fgetc((FILE *)f);
388     if (res >= 0) {
389       *ch = (picopal_char) res;
390     }
391     else {
392       *ch = '\0';
393     }
394     return (res >= 0) ? PICO_OK : PICO_EOF;
395 }
396 
picopal_fread_bytes(picopal_File f,void * ptr,picopal_objsize_t objsize,picopal_uint32 nobj)397 picopal_objsize_t picopal_fread_bytes (picopal_File f, void * ptr, picopal_objsize_t objsize, picopal_uint32 nobj)
398 {
399     return (picopal_objsize_t) fread(ptr, objsize, nobj, (FILE *)f);
400 }
401 
picopal_fwrite_bytes(picopal_File f,void * ptr,picopal_objsize_t objsize,picopal_uint32 nobj)402 picopal_objsize_t picopal_fwrite_bytes (picopal_File f, void * ptr, picopal_objsize_t objsize, picopal_uint32 nobj){    return (picopal_objsize_t) fwrite(ptr, objsize, nobj, (FILE *)f);}
403 /* *************************************************/
404 /* functions for debugging/testing purposes only   */
405 /* *************************************************/
406 
picopal_mpr_alloc(picopal_objsize_t size)407 void *picopal_mpr_alloc(picopal_objsize_t size)
408 {
409 #if PICO_PLATFORM == PICO_Windows
410     return VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE);
411 #else
412     /* not yet implemented for other platforms;  corresponding
413        function on UNIX systems is pvalloc */
414     return NULL;
415 #endif
416     size = size;        /* avoid warning "var not used in this function"*/
417 
418 }
419 
picopal_mpr_free(void ** p)420 void picopal_mpr_free(void **p)
421 {
422 #if PICO_PLATFORM == PICO_Windows
423     VirtualFree(*p, 0, MEM_RELEASE);
424 #else
425     /* not yet implemented for other platforms */
426 #endif
427     *p = NULL;
428 }
429 
picopal_mpr_protect(void * addr,picopal_objsize_t len,picopal_int16 prot)430 pico_status_t picopal_mpr_protect(void *addr, picopal_objsize_t len, picopal_int16 prot)
431 {
432     pico_status_t status = PICO_OK;
433 
434 #if PICO_PLATFORM == PICO_Windows
435     DWORD dwNewProtect, dwOldProtect;
436     dwNewProtect = PICOPAL_PROT_NONE;
437     if (prot & PICOPAL_PROT_READ) {
438         if (prot & PICOPAL_PROT_WRITE) {
439             dwNewProtect = PAGE_READWRITE;
440         } else {
441             dwNewProtect = PAGE_READONLY;
442         }
443     } else if (prot & PICOPAL_PROT_WRITE) {
444         /* under Windows write-only is not possible */
445         dwNewProtect = PAGE_READWRITE;
446     }
447     if (!VirtualProtect(addr, len, dwNewProtect, &dwOldProtect)) {
448         status = PICO_ERR_OTHER;
449     }
450 #else
451     /* not yet implemented for other platforms */
452     addr = addr;        /* avoid warning "var not used in this function"*/
453     len = len;            /* avoid warning "var not used in this function"*/
454     prot = prot;        /* avoid warning "var not used in this function"*/
455 
456 #endif
457     return status;
458 }
459 /*
460  *  Reference:
461  * A Fast, Compact Approximation of the Exponential Function by Nicol N. Schraudolph in Neural Computation, 11,853-862 (1999)
462  * See also: http://www-h.eng.cam.ac.uk/help/tpl/programs/Matlab/mex.html
463  *
464  */
picopal_quick_exp(const picopal_double y)465 picopal_double picopal_quick_exp(const picopal_double y) {
466     union {
467         picopal_double d;
468           struct {
469             #if PICO_ENDIANNESS == ENDIANNESS_LITTLE /* little endian */
470               picopal_int32 j,i;
471             #else
472               picopal_int32 i,j;
473             #endif
474           } n;
475 
476     } _eco;
477     _eco.n.i = (picopal_int32)(1512775.3951951856938297995605697f * y) + 1072632447;
478     return _eco.d;
479 }
480 
481 
482 /* *************************************************/
483 /* timer                                           */
484 /* *************************************************/
485 
486 #if IMPLEMENT_TIMER
487 
488 #define USEC_PER_SEC 1000000
489 
490 typedef clock_t picopal_clock_t;
491 
492 
493 #if USE_CLOCK
494 picopal_clock_t startTime;
495 #else
496 int timerInit = 0;
497 LARGE_INTEGER startTime;
498 LARGE_INTEGER timerFreq;
499 #endif
500 
501 
picopal_clock(void)502 picopal_clock_t picopal_clock(void)
503 {
504     return (picopal_clock_t)clock();
505 }
506 
507 #endif /* IMPLEMENT_TIMER */
508 
picopal_get_timer(picopal_uint32 * sec,picopal_uint32 * usec)509 void picopal_get_timer(picopal_uint32 * sec, picopal_uint32 * usec)
510 {
511 #if IMPLEMENT_TIMER
512 #if USE_CLOCK
513     picopal_clock_t dt;
514     dt = picopal_clock() - startTime;
515     *sec = dt / CLOCKS_PER_SEC;
516     *usec = USEC_PER_SEC * (dt % CLOCKS_PER_SEC) / CLOCKS_PER_SEC;
517 #else
518     LARGE_INTEGER now;
519     if (!timerInit) {
520       QueryPerformanceFrequency(&timerFreq);
521       timerInit = 1;
522     }
523     if (QueryPerformanceCounter(&now) && 0) {
524 /*
525         LONGLONG dt, tf;
526         dt = now.QuadPart - GLOB(startTime).QuadPart;
527         tf = GLOB(timerFreq).QuadPart;
528         *sec = (unsigned int) (dt / tf);
529         *usec = (unsigned int) (USEC_PER_SEC * (dt % tf) / tf);
530 */
531         double dt, tf;
532         dt = (double)(now.QuadPart - startTime.QuadPart);
533         tf = (double)(timerFreq.QuadPart);
534         *sec = (unsigned int) (dt /tf);
535         *usec = (unsigned int) ((double)USEC_PER_SEC * (dt / tf)) % USEC_PER_SEC;
536     } else {
537         /* high freq counter not supported by system */
538         DWORD dt;
539         dt = GetTickCount() - startTime.LowPart;
540         *sec = dt / 1000;
541         *usec = 1000 * (dt % 1000);
542     }
543 #endif /* USE_CLOCK */
544 #else
545     *sec = 0;
546     *usec = 0;
547 #endif /* IMPLEMENT_TIMER */
548 }
549 
550 #ifdef __cplusplus
551 }
552 #endif
553 
554 /* End picopal.c */
555