int fb_DevFileReadLineEncodWstr( FB_FILE *handle, FB_WCHAR *dst, ssize_t max_chars ) { int res; FB_LOCK(); FILE* fp = (FILE *)handle->opaque; if( fp == stdout || fp == stderr ) fp = stdin; if( fp == NULL ) { FB_UNLOCK(); return fb_ErrorSetNum( FB_RTERROR_ILLEGALFUNCTIONCALL ); } /* Clear string first, we're only using += concat assign below... */ dst[0] = _LC('\0'); /* Read one byte at a time until CR and/or LF is found. The fb_FileGetDataEx() will handle the decoding. The length to read is specified in wchars, not bytes, because we're passing TRUE for is_unicode. */ while( TRUE ) { FB_WCHAR c[2]; size_t len; res = fb_FileGetDataEx( handle, 0, c, 1, &len, FALSE, TRUE ); if( (res != FB_RTERROR_OK) || (len == 0) ) break; /* CR? Check for following LF too, and skip it if it's there */ if( c[0] == _LC('\r') ) { res = fb_FileGetDataEx( handle, 0, c, 1, &len, FALSE, TRUE ); if( (res != FB_RTERROR_OK) || (len == 0) ) break; /* No LF? Ok then, don't skip it yet */ if( c[0] != _LC('\n') ) fb_FilePutBackEx( handle, c, 1 ); break; } /* LF? */ if( c[0] == _LC('\n') ) { break; } /* Any other char? Append to string, and continue... */ c[1] = _LC('\0'); fb_WstrConcatAssign( dst, max_chars, c ); } FB_UNLOCK(); return res; }
/*:::::*/ static FB_WCHAR hReadChar( FB_INPUTCTX *ctx ) { /* device? */ if( FB_HANDLE_USED(ctx->handle) ) { int res; FB_WCHAR c; size_t len; res = fb_FileGetDataEx( ctx->handle, 0, &c, 1, &len, FALSE, TRUE ); if( (res != FB_RTERROR_OK) || (len == 0) ) return WEOF; return c; } /* console.. */ else { if( ctx->index >= FB_STRSIZE( &ctx->str.len ) ) return WEOF; else return (unsigned char)ctx->str.data[ctx->index++]; } }
/*:::::*/ int fb_FileGetWstrEx( FB_FILE *handle, fb_off_t pos, FB_WCHAR *dst, int dst_chars, size_t *bytesread ) { int res; if( bytesread ) *bytesread = 0; if( !FB_HANDLE_USED(handle) ) return fb_ErrorSetNum( FB_RTERROR_ILLEGALFUNCTIONCALL ); /* perform call ... but only if there's data ... */ if( (dst != NULL) && (dst_chars > 0) ) { size_t chars; res = fb_FileGetDataEx( handle, pos, (void *)dst, dst_chars, &chars, TRUE, TRUE ); /* add the null-term */ if( res == FB_RTERROR_OK ) dst[chars] = _LC('\0'); if( bytesread ) *bytesread = chars; } else res = fb_ErrorSetNum( FB_RTERROR_ILLEGALFUNCTIONCALL ); return res; }
/*:::::*/ static int hReadChar ( FB_INPUTCTX *ctx ) { /* device? */ if( FB_HANDLE_USED(ctx->handle) ) { int res; int c; size_t len; res = fb_FileGetDataEx( ctx->handle, 0, &c, 1, &len, FALSE, FALSE ); if( (res != FB_RTERROR_OK) || (len == 0) ) return EOF; return c & 0x000000FF; } /* console.. */ else { if( ctx->index >= FB_STRSIZE( &ctx->str ) ) return EOF; else return ctx->str.data[ctx->index++]; } }
/*:::::*/ FBCALL int fb_FileGetLargeIOB( int fnum, long long pos, void *dst, unsigned int chars, unsigned int *bytesread ) { return fb_FileGetDataEx( FB_FILE_TO_HANDLE(fnum), pos, dst, chars, bytesread, TRUE, FALSE ); }
/*:::::*/ FBCALL int fb_FileGetLarge( int fnum, long long pos, void *dst, unsigned int chars ) { return fb_FileGetDataEx( FB_FILE_TO_HANDLE(fnum), pos, dst, chars, NULL, TRUE, FALSE ); }
/* Can fb_FileGetData() be removed? it's not used by the rtlib * nor is it referenced by fbc? Compatibility with old libs? [jeffm] */ int fb_FileGetData( int fnum, fb_off_t pos, void *dst, size_t chars, int adjust_rec_pos ) { return fb_FileGetDataEx( FB_FILE_TO_HANDLE(fnum), pos, dst, chars, NULL, adjust_rec_pos, FALSE ); }
static int fb_hFileLineInputEx ( FB_FILE *handle, void *dst, ssize_t dst_len, int fillrem ) { ssize_t len, readlen; char buffer[BUFFER_LEN]; eInputMode mode = eIM_Invalid; if( !FB_HANDLE_USED(handle) ) return fb_ErrorSetNum( FB_RTERROR_ILLEGALFUNCTIONCALL ); FB_LOCK(); if( handle->hooks->pfnReadLine != NULL ) { mode = eIM_ReadLine; } else if( handle->hooks->pfnRead != NULL && handle->hooks->pfnEof != NULL ) { mode = eIM_Read; } if( mode==eIM_Invalid ) { FB_UNLOCK(); return fb_ErrorSetNum( FB_RTERROR_ILLEGALFUNCTIONCALL ); } switch( mode ) { case eIM_Read: /* This is the VFS-compatible way to read a line ... but it's slow */ len = readlen = 0; while (!handle->hooks->pfnEof(handle)) { int do_add = FALSE, do_break = FALSE; size_t read_len; int res = fb_FileGetDataEx( handle, 0, buffer+len, 1, &read_len, FALSE, FALSE ); if( res==FB_RTERROR_OK && read_len==1) { char ch = buffer[len]; if( ch==13 ) { res = fb_FileGetDataEx( handle, 0, &ch, 1, &read_len, FALSE, FALSE ); if( res==FB_RTERROR_OK && ch!=10 && read_len==1) { fb_FilePutBackEx( handle, &ch, 1 ); } ch = 10; } if( ch==10 ) { do_add = do_break = TRUE; } else { do_add = len==(sizeof(buffer)-1); } } else { do_add = len!=0; } if( do_add || handle->hooks->pfnEof( handle ) ) { /* create temporary string to ensure that NUL's are preserved ... * this function wants the length WITH the NUL character!!! */ buffer[len] = 0; FBSTRING *src = fb_StrAllocTempDescF( buffer, len + 1); if( readlen==0 ) { fb_StrAssign( dst, dst_len, src, -1, fillrem ); } else { fb_StrConcatAssign ( dst, dst_len, src, -1, fillrem ); } readlen += len; len = 0; } else { ++len; } if( res!=FB_RTERROR_OK || do_break ) break; } if( readlen == 0 ) { /* del destine string */ if( dst_len == -1 ) fb_StrDelete( (FBSTRING *)dst ); else *(char *)dst = '\0'; } break; case eIM_ReadLine: /* The read line mode is the most comfortable ... but IMHO it's * only useful for special devices (like SCRN:) */ { /* destine is a var-len string? read directly */ if( dst_len == -1 ) { handle->hooks->pfnReadLine( handle, dst ); } /* fixed-len or unknown size (ie: pointers)? use a temp var-len */ else { FBSTRING str_result = { 0, 0, 0 }; /* read complete line (may include NULs) */ handle->hooks->pfnReadLine( handle, &str_result ); /* add contents of tempporary string to result buffer */ fb_StrAssign( dst, dst_len, (void *)&str_result, -1, fillrem ); /* delete result */ fb_StrDelete( &str_result ); } } break; case eIM_Invalid: /* the "invalid" mode was already handled above ... so we don't * need to do anything here ... */ break; } FB_UNLOCK(); return fb_ErrorSetNum( FB_RTERROR_OK ); }
FBCALL FB_WCHAR *fb_FileWstrInput( ssize_t chars, int fnum ) { FB_FILE *handle; FB_WCHAR *dst; size_t len; int res = FB_RTERROR_OK; fb_DevScrnInit_ReadWstr( ); FB_LOCK(); handle = FB_FILE_TO_HANDLE(fnum); if( !FB_HANDLE_USED(handle) ) { FB_UNLOCK(); return NULL; } dst = fb_wstr_AllocTemp( chars ); if( dst != NULL ) { ssize_t read_chars = 0; if( FB_HANDLE_IS_SCREEN(handle) ) { while( read_chars != chars ) { res = fb_FileGetDataEx( handle, 0, (void *)&dst[read_chars], chars - read_chars, &len, TRUE, TRUE ); if( res != FB_RTERROR_OK ) break; read_chars += len; } } else { res = fb_FileGetDataEx( handle, 0, (void *)dst, chars, &len, TRUE, TRUE ); read_chars = chars; } if( res == FB_RTERROR_OK ) { dst[read_chars] = _LC('\0'); } else { fb_wstr_Del( dst ); dst = NULL; } } else res = FB_RTERROR_OUTOFMEM; FB_UNLOCK(); return dst; }