Home | History | Annotate | Download | only in lib
      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 
     99 picopal_int32 picopal_atoi(const picopal_char *s) {
    100   return (picopal_int32)atoi((const char *)s);
    101 }
    102 
    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 
    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 
    111 picopal_objsize_t picopal_strlen(const picopal_char *s) {
    112   return (picopal_objsize_t)strlen((const char *)s);
    113 }
    114 
    115 picopal_char *picopal_strchr(const picopal_char *s, picopal_char c) {
    116   return (picopal_char *)strchr((const char *)s, (int)c);
    117 }
    118 
    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 
    123 picopal_char *picopal_strcpy(picopal_char *d, const picopal_char *s) {
    124   return (picopal_char *)strcpy((char *)d, (const char *)s);
    125 }
    126 
    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 */
    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 
    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 
    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 
    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! */
    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' */
    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 
    270 picopal_double picopal_cos(const picopal_double cos_arg)
    271 {
    272     return (picopal_double) cos((double)cos_arg);
    273 }
    274 picopal_double picopal_sin(const picopal_double sin_arg)
    275 {
    276     return (picopal_double) sin((double) sin_arg);
    277 }
    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 
    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 */
    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 
    334 picopal_File picopal_get_fnil (void)
    335 {
    336     return (picopal_File) NULL;
    337 }
    338 
    339 
    340 picopal_int8 picopal_is_fnil (picopal_File f)
    341 {
    342     return (NULL == f);
    343 }
    344 
    345 pico_status_t picopal_fflush (picopal_File f)
    346 {
    347     return (0 == fflush((FILE *)f)) ? PICO_OK : PICO_EOF;
    348 }
    349 
    350 
    351 pico_status_t picopal_fclose (picopal_File f)
    352 {
    353     return (0 == fclose((FILE *)f)) ? PICO_OK : PICO_EOF;
    354 }
    355 
    356 
    357 
    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 
    372 picopal_uint8 picopal_feof (picopal_File stream)
    373 {
    374     return (0 != feof((FILE *)stream));
    375 
    376 }
    377 
    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 
    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 
    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 
    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 
    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 
    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 
    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  */
    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 
    502 picopal_clock_t picopal_clock(void)
    503 {
    504     return (picopal_clock_t)clock();
    505 }
    506 
    507 #endif /* IMPLEMENT_TIMER */
    508 
    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