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