1/*---------------------------------------------------------------------------* 2 * PFile.c * 3 * * 4 * Copyright 2007, 2008 Nuance Communciations, Inc. * 5 * * 6 * Licensed under the Apache License, Version 2.0 (the 'License'); * 7 * you may not use this file except in compliance with the License. * 8 * * 9 * You may obtain a copy of the License at * 10 * http://www.apache.org/licenses/LICENSE-2.0 * 11 * * 12 * Unless required by applicable law or agreed to in writing, software * 13 * distributed under the License is distributed on an 'AS IS' BASIS, * 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * 15 * See the License for the specific language governing permissions and * 16 * limitations under the License. * 17 * * 18 *---------------------------------------------------------------------------*/ 19 20#include "LCHAR.h" 21#include "pendian.h" 22#include "PFile.h" 23#include "PFileSystem.h" 24#include "plog.h" 25#include "pstdio.h" 26 27 28ESR_ReturnCode PFileDestroy(PFile* self) 29{ 30 if (self == NULL) 31 { 32 PLogError(L("ESR_INVALID_ARGUMENT")); 33 return ESR_INVALID_ARGUMENT; 34 } 35 return self->destroy(self); 36} 37 38ESR_ReturnCode PFileOpen(PFile* self, const LCHAR* mode) 39{ 40 if (self == NULL) 41 { 42 PLogError(L("ESR_INVALID_ARGUMENT")); 43 return ESR_INVALID_ARGUMENT; 44 } 45 return self->open(self, mode); 46} 47 48ESR_ReturnCode PFileClose(PFile* self) 49{ 50 if (self == NULL) 51 { 52 PLogError(L("ESR_INVALID_ARGUMENT")); 53 return ESR_INVALID_ARGUMENT; 54 } 55 return self->close(self); 56} 57 58ESR_ReturnCode PFileRead(PFile* self, void* buffer, size_t size, size_t* count) 59{ 60 if (self == NULL) 61 { 62 PLogError(L("ESR_INVALID_ARGUMENT")); 63 return ESR_INVALID_ARGUMENT; 64 } 65 return self->read(self, buffer, size, count); 66} 67 68ESR_ReturnCode PFileWrite(PFile* self, void* buffer, size_t size, size_t* count) 69{ 70 if (self == NULL) 71 { 72 PLogError(L("ESR_INVALID_ARGUMENT")); 73 return ESR_INVALID_ARGUMENT; 74 } 75 return self->write(self, buffer, size, count); 76} 77 78ESR_ReturnCode PFileFlush(PFile* self) 79{ 80 if (self == NULL) 81 { 82 PLogError(L("ESR_INVALID_ARGUMENT")); 83 return ESR_INVALID_ARGUMENT; 84 } 85 return self->flush(self); 86} 87 88ESR_ReturnCode PFileSeek(PFile* self, long offset, int origin) 89{ 90 if (self == NULL) 91 { 92 PLogError(L("ESR_INVALID_ARGUMENT")); 93 return ESR_INVALID_ARGUMENT; 94 } 95 return self->seek(self, offset, origin); 96} 97 98 99ESR_ReturnCode PFileGetPosition(PFile* self, size_t* position) 100{ 101 if (self == NULL) 102 { 103 PLogError(L("ESR_INVALID_ARGUMENT")); 104 return ESR_INVALID_ARGUMENT; 105 } 106 return self->getPosition(self, position); 107} 108 109ESR_ReturnCode PFileIsOpen(PFile* self, ESR_BOOL* isOpen) 110{ 111 if (self == NULL) 112 { 113 PLogError(L("ESR_INVALID_ARGUMENT")); 114 return ESR_INVALID_ARGUMENT; 115 } 116 return self->isOpen(self, isOpen); 117} 118 119ESR_ReturnCode PFileIsEOF(PFile* self, ESR_BOOL* isEof) 120{ 121 if (self == NULL) 122 { 123 PLogError(L("ESR_INVALID_ARGUMENT")); 124 return ESR_INVALID_ARGUMENT; 125 } 126 return self->isEOF(self, isEof); 127} 128 129ESR_ReturnCode PFileGetFilename(PFile* self, LCHAR* filename, size_t* len) 130{ 131 ESR_ReturnCode rc; 132 133 if (self == NULL) 134 { 135 PLogError(L("ESR_INVALID_ARGUMENT")); 136 return ESR_INVALID_ARGUMENT; 137 } 138 rc = self->getFilename(self, filename, len); 139 return rc; 140} 141 142ESR_ReturnCode PFileIsErrorSet(PFile* self, ESR_BOOL* isError) 143{ 144 if (self == NULL) 145 { 146 PLogError(L("ESR_INVALID_ARGUMENT")); 147 return ESR_INVALID_ARGUMENT; 148 } 149 return self->isErrorSet(self, isError); 150} 151 152ESR_ReturnCode PFileClearError(PFile* self) 153{ 154 if (self == NULL) 155 { 156 PLogError(L("ESR_INVALID_ARGUMENT")); 157 return ESR_INVALID_ARGUMENT; 158 } 159 return self->clearError(self); 160} 161 162ESR_ReturnCode PFileVfprintf(PFile* self, int* result, const LCHAR* format, va_list args) 163{ 164 ESR_ReturnCode rc; 165 166 if (self == NULL) 167 { 168 PLogError(L("ESR_INVALID_ARGUMENT")); 169 return ESR_INVALID_ARGUMENT; 170 } 171 rc = self->vfprintf(self, result, format, args); 172 return rc; 173} 174 175ESR_ReturnCode PFileFgetc(PFile* self, LINT* result) 176{ 177 if (self == NULL) 178 { 179 PLogError(L("ESR_INVALID_ARGUMENT")); 180 return ESR_INVALID_ARGUMENT; 181 } 182 return self->fgetc(self, result); 183} 184 185ESR_ReturnCode PFileFgets(PFile* self, LCHAR* string, int n, LCHAR** result) 186{ 187 if (self == NULL) 188 { 189 PLogError(L("ESR_INVALID_ARGUMENT")); 190 return ESR_INVALID_ARGUMENT; 191 } 192 return self->fgets(self, string, n, result); 193} 194 195ESR_ReturnCode PFileReadInt(PFile* self, int* value) 196{ 197 LCHAR number[MAX_INT_DIGITS+1]; 198 size_t i, bufferSize, count, totalRead = 0; 199 ESR_ReturnCode rc; 200 201 /* Skip whitespace before token */ 202 do 203 { 204 count = pfread(number, sizeof(LCHAR), MAX_INT_DIGITS, self); 205 totalRead += count; 206 if (count < MAX_INT_DIGITS) 207 { 208 if (pferror(self)) 209 { 210 rc = ESR_READ_ERROR; 211 PLogError(ESR_rc2str(rc)); 212 goto CLEANUP; 213 } 214 else 215 { 216 rc = ESR_INVALID_STATE; 217 PLogError(L("%s: reached end of file before finding token"), ESR_rc2str(rc)); 218 goto CLEANUP; 219 } 220 } 221 /* locate first non-whitespace character */ 222 for (i = 0; i < count && LISSPACE(number[i]); ++i); 223 } 224 while (i == count); 225 bufferSize = count - i; 226 227 /* Fill remainder of buffer */ 228 if (bufferSize < MAX_INT_DIGITS) 229 { 230 count = pfread(number + bufferSize, sizeof(LCHAR), MAX_INT_DIGITS - bufferSize, self); 231 bufferSize += count; 232 totalRead += count; 233 if (count < MAX_INT_DIGITS - bufferSize && pferror(self)) 234 { 235 rc = ESR_READ_ERROR; 236 PLogError(ESR_rc2str(rc)); 237 goto CLEANUP; 238 } 239 } 240 241 /* locate first whitespace character */ 242 for (i = 0; i < bufferSize && !LISSPACE(number[i]); ++i); 243 if (i < bufferSize) 244 { 245 /* unread anything after the token */ 246 if (PFileSeek(self, - (int)(bufferSize - i), SEEK_CUR)) 247 { 248 rc = ESR_SEEK_ERROR; 249 PLogError(ESR_rc2str(rc)); 250 } 251 totalRead -= bufferSize - i; 252 number[i] = L('\0'); 253 } 254 255 if (number[0] != L('-') && !LISDIGIT(number[0])) 256 { 257 rc = ESR_INVALID_STATE; 258 PLogError(L("%s: token was not number (%s)"), ESR_rc2str(rc), number); 259 goto CLEANUP; 260 } 261 262 CHKLOG(rc, lstrtoi(number, value, 10)); 263 return rc; 264CLEANUP: 265 if (PFileSeek(self, - (int) count, SEEK_CUR)) 266 PLogError(L("ESR_SEEK_ERROR")); 267 return rc; 268} 269 270ESR_ReturnCode PFileReadLCHAR(PFile* self, LCHAR* value, size_t len) 271{ 272 size_t i, bufferSize, count, totalRead = 0; 273 ESR_ReturnCode rc = ESR_SUCCESS; 274 275 /* Skip whitespace before token */ 276 do 277 { 278 count = pfread(value, sizeof(LCHAR), len, self); 279 totalRead += count; 280 if (count < len) 281 { 282 if (pferror(self)) 283 { 284 rc = ESR_READ_ERROR; 285 PLogError(ESR_rc2str(rc)); 286 goto CLEANUP; 287 } 288 else 289 { 290 rc = ESR_INVALID_STATE; 291 PLogError(L("%s: reached end of file before finding token"), ESR_rc2str(rc)); 292 goto CLEANUP; 293 } 294 } 295 /* locate first non-whitespace character */ 296 for (i = 0; i < count && LISSPACE(value[i]); ++i); 297 } 298 while (i == count); 299 bufferSize = count - i; 300 301 /* Fill remainder of buffer */ 302 if (bufferSize < len) 303 { 304 count = pfread(value + bufferSize, sizeof(LCHAR), len - bufferSize, self); 305 bufferSize += count; 306 totalRead += count; 307 if (count < len - bufferSize && pferror(self)) 308 { 309 rc = ESR_READ_ERROR; 310 PLogError(ESR_rc2str(rc)); 311 goto CLEANUP; 312 } 313 } 314 315 /* locate first whitespace character */ 316 for (i = 0; i < bufferSize && !LISSPACE(value[i]); ++i); 317 if (i < bufferSize) 318 { 319 /* unread anything after the token */ 320 if (PFileSeek(self, -(int)(bufferSize - i), SEEK_CUR)) 321 { 322 rc = ESR_SEEK_ERROR; 323 PLogError(ESR_rc2str(rc)); 324 } 325 totalRead -= bufferSize - i; 326 value[i] = L('\0'); 327 } 328 return rc; 329CLEANUP: 330 if (PFileSeek(self, - (int) count, SEEK_CUR)) 331 PLogError(L("ESR_SEEK_ERROR")); 332 return rc; 333} 334 335PFile* pfopen(const LCHAR* filename, const LCHAR* mode) 336{ 337 PFile* result; 338 ESR_ReturnCode rc; 339 ESR_BOOL isLittleEndian; 340 341#if __BYTE_ORDER==__LITTLE_ENDIAN 342 isLittleEndian = ESR_TRUE; 343#else 344 isLittleEndian = ESR_FALSE; 345#endif 346 347 rc = PFileSystemCreatePFile(filename, isLittleEndian, &result); 348 if (rc != ESR_SUCCESS) 349 return NULL; 350 rc = result->open(result, mode); 351 if (rc != ESR_SUCCESS) 352 { 353 result->destroy(result); 354 return NULL; 355 } 356 return result; 357} 358 359size_t pfread(void* buffer, size_t size, size_t count, PFile* stream) 360{ 361 ESR_ReturnCode rc; 362 363 rc = PFileRead(stream, buffer, size, &count); 364 if (rc != ESR_SUCCESS) 365 return 0; 366 return count; 367} 368 369size_t pfwrite(const void* buffer, size_t size, size_t count, PFile* stream) 370{ 371 ESR_ReturnCode rc; 372 373 rc = PFileWrite(stream, buffer, size, &count); 374 if (rc != ESR_SUCCESS) 375 return 0; 376 return count; 377} 378 379int pfclose(PFile* stream) 380{ 381 ESR_ReturnCode rc; 382 383 rc = PFileDestroy(stream); 384 if (rc != ESR_SUCCESS) 385 return PEOF; 386 return 0; 387} 388 389void prewind(PFile* stream) 390{ 391 PFileSeek(stream, 0, SEEK_SET); 392} 393 394int pfseek(PFile* stream, long offset, int origin) 395{ 396 ESR_ReturnCode rc; 397 398 rc = PFileSeek(stream, offset, origin); 399 if (rc != ESR_SUCCESS) 400 return 1; 401 return 0; 402} 403 404long pftell(PFile* stream) 405{ 406 size_t result; 407 ESR_ReturnCode rc; 408 409 rc = PFileGetPosition(stream, &result); 410 if (rc != ESR_SUCCESS) 411 return -1; 412 return result; 413} 414 415int pfeof(PFile* stream) 416{ 417 ESR_BOOL eof; 418 419 PFileIsEOF(stream, &eof); 420 if (!eof) 421 return 0; 422 return 1; 423} 424 425int pferror(PFile* stream) 426{ 427 ESR_BOOL error; 428 429 PFileIsErrorSet(stream, &error); 430 if (!error) 431 return 0; 432 return 1; 433} 434 435void pclearerr(PFile* stream) 436{ 437 PFileClearError(stream); 438} 439 440int pfflush(PFile* stream) 441{ 442 ESR_ReturnCode rc; 443 444 rc = PFileFlush(stream); 445 if (rc != ESR_SUCCESS) 446 return PEOF; 447 return 0; 448} 449 450LCHAR* pfgets(LCHAR* string, int n, PFile* self) 451{ 452 LCHAR* result; 453 ESR_ReturnCode rc; 454 455 rc = PFileFgets(self, string, n, &result); 456 if (rc != ESR_SUCCESS) 457 return NULL; 458 return result; 459} 460 461LINT pfgetc(PFile* self) 462{ 463 LINT result; 464 ESR_ReturnCode rc; 465 466 rc = PFileFgetc(self, &result); 467 if (rc != ESR_SUCCESS) 468 return PEOF; 469 return result; 470} 471 472int pfprintf(PFile* stream, const LCHAR* format, ...) 473{ 474#ifdef FINAL_RELEASE 475 return 0; 476#else 477 va_list args; 478 int result; 479 ESR_ReturnCode rc; 480 481 va_start(args, format); 482 rc = PFileVfprintf(stream, &result, format, args); 483 va_end(args); 484 if (rc != ESR_SUCCESS) 485 return -1; 486 return result; 487#endif 488} 489 490int pvfprintf(PFile* stream, const LCHAR* format, va_list argptr) 491{ 492#ifdef FINAL_RELEASE 493 return 0; 494#else 495 int result; 496 ESR_ReturnCode rc; 497 498 rc = PFileVfprintf(stream, &result, format, argptr); 499 if (rc != ESR_SUCCESS) 500 return -1; 501 return result; 502#endif 503} 504 505int pprintf(const LCHAR* format, ...) 506{ 507#ifdef FINAL_RELEASE 508 return 0; 509#else 510 va_list args; 511 int result; 512 ESR_ReturnCode rc; 513 514 va_start(args, format); 515 rc = PFileVfprintf(PSTDOUT, &result, format, args); 516 va_end(args); 517 if (rc != ESR_SUCCESS) 518 return -1; 519 return result; 520#endif 521} 522