/* reads a line from a filehandle. */ MVMString * MVM_file_readline_fh(MVMThreadContext *tc, MVMObject *oshandle) { MVMString *result; apr_status_t rv; MVMOSHandle *handle; char ch; char *buf; apr_off_t offset = 0; apr_off_t fetched = 0; apr_off_t bytes_read = 0; verify_filehandle_type(tc, oshandle, &handle, "readline from filehandle"); if ((rv = apr_file_seek(handle->body.file_handle, APR_CUR, &offset)) != APR_SUCCESS) { MVM_exception_throw_apr_error(tc, rv, "Failed to tell position of filehandle in readline(1): "); } while (apr_file_getc(&ch, handle->body.file_handle) == APR_SUCCESS && ch != 10 && ch != 13) { bytes_read++; } /* have a look if it is a windows newline, and step back if not. */ if (ch == 13 && apr_file_getc(&ch, handle->body.file_handle) == APR_SUCCESS && ch != 10) { fetched--; } if ((rv = apr_file_seek(handle->body.file_handle, APR_CUR, &fetched)) != APR_SUCCESS) { MVM_exception_throw_apr_error(tc, rv, "Failed to tell position of filehandle in readline(2): "); } if ((rv = apr_file_seek(handle->body.file_handle, APR_SET, &offset)) != APR_SUCCESS) { MVM_exception_throw_apr_error(tc, rv, "Failed to tell position of filehandle in readline(3)"); } buf = malloc((int)(bytes_read + 1)); if ((rv = apr_file_read(handle->body.file_handle, buf, &bytes_read)) != APR_SUCCESS) { free(buf); MVM_exception_throw_apr_error(tc, rv, "readline from filehandle failed: "); } if ((rv = apr_file_seek(handle->body.file_handle, APR_SET, &fetched)) != APR_SUCCESS) { MVM_exception_throw_apr_error(tc, rv, "Failed to tell position of filehandle in readline(4)"); } /* XXX should this take a type object? */ result = MVM_decode_C_buffer_to_string(tc, tc->instance->VMString, buf, bytes_read, handle->body.encoding_type); free(buf); return result; }
static void test_ungetc(abts_case *tc, void *data) { apr_file_t *f = NULL; apr_status_t rv; char ch; rv = apr_file_open(&f, FILENAME, APR_READ, 0, p); ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); apr_file_getc(&ch, f); ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); ABTS_INT_EQUAL(tc, (int)TESTSTR[0], (int)ch); apr_file_ungetc('X', f); ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); apr_file_getc(&ch, f); ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); ABTS_INT_EQUAL(tc, 'X', (int)ch); apr_file_close(f); }
static void test_ungetc(CuTest *tc) { apr_file_t *f = NULL; apr_status_t rv; char ch; rv = apr_file_open(&f, FILENAME, APR_READ, 0, p); CuAssertIntEquals(tc, APR_SUCCESS, rv); apr_file_getc(&ch, f); CuAssertIntEquals(tc, APR_SUCCESS, rv); CuAssertIntEquals(tc, (int)TESTSTR[0], (int)ch); apr_file_ungetc('X', f); CuAssertIntEquals(tc, APR_SUCCESS, rv); apr_file_getc(&ch, f); CuAssertIntEquals(tc, APR_SUCCESS, rv); CuAssertIntEquals(tc, 'X', (int)ch); apr_file_close(f); }
// get next place takes the request, a file pointing to the file named in the request // and a buffer which is used to pass back the place's name static int get_next_place(request_rec *r, apr_file_t *fd, char * buf) { // initialization int counter=0; apr_status_t rv; // loop and get characters from file until the // end of the file is reached or a newline is reached // increment the counter based on the character // and if the buffer capacity is reached then // return an error while(1) { rv = apr_file_getc(buf+counter,fd); if(APR_STATUS_IS_EOF(rv)) { return DONE; } if(buf[counter]=='\n') { buf[counter]='\0'; return OK; } // escapes spaces for URI if(buf[counter]==' ') { if(counter+3 < MAX_BUF_LENGTH) { buf[counter]='%'; buf[counter+1]='2'; buf[counter+2]='0'; } counter+=3; } else { counter++; } // check for exceeding the buffer length if(counter>=MAX_BUF_LENGTH) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0 , r, "Name in file:%s is longer than %d!", r->filename, MAX_BUF_LENGTH); return HTTP_INTERNAL_SERVER_ERROR; } } }
static int get_line(char *s, int n, apr_file_t *f) { register int i = 0; char ch; apr_status_t rv = APR_EINVAL; /* we need 2 remaining bytes in buffer */ while (i < (n - 2) && ((rv = apr_file_getc(&ch, f)) == APR_SUCCESS) && (ch != '\n')) { s[i++] = ch; } /* First remaining byte potentially used here */ if (ch == '\n') s[i++] = ch; /* Second remaining byte used here */ s[i] = '\0'; if (rv != APR_SUCCESS) return 1; return 0; }
static int apache_read_line_fn(lily_lex_entry *entry) { char ch; int bufsize, i, ok, utf8_check; lily_lex_state *lexer = entry->lexer; char *input_buffer = lexer->input_buffer; apr_file_t *input_file = (apr_file_t *)entry->source; apr_status_t result; bufsize = lexer->input_size; i = 0; utf8_check = 0; while (1) { result = apr_file_getc(&ch, input_file); if (result != APR_SUCCESS) { if ((i + 1) == bufsize) { lily_grow_lexer_buffers(lexer); input_buffer = lexer->input_buffer; } lexer->input_buffer[i] = '\n'; lexer->input_end = i + 1; /* If i is 0, then nothing is on this line except eof. Return 0 to let the caller know this is the end. * If it isn't, then there's stuff with an unexpected eof at the end. Return 1, then 0 the next time. */ ok = !!i; /* Make sure the second eof found does not increment the line number again. */ if (lexer->hit_eof == 0) { lexer->line_num++; lexer->hit_eof = 1; } break; } /* i + 2 is used so that when \r\n that the \n can be safely added to the buffer. Otherwise, it would be i + 1. */ if ((i + 2) == bufsize) { lily_grow_lexer_buffers(lexer); /* Do this in case the realloc decides to use a different block instead of growing what it had. */ input_buffer = lexer->input_buffer; } input_buffer[i] = ch; if (ch == '\r' || ch == '\n') { lexer->input_end = i; lexer->line_num++; ok = 1; if (ch == '\r') { apr_file_getc(&ch, input_file); if (ch != '\n') apr_file_ungetc(ch, input_file); else { /* This is safe: See i + 2 == size comment above. */ lexer->input_buffer[i+1] = ch; lexer->input_end++; } } break; } else if (((unsigned char)ch) > 127) utf8_check = 1; i++; } if (utf8_check) lily_lexer_utf8_check(lexer); return ok; }