static char stream_get(stream_t *stream, json_error_t *error) { char c; if(!stream->buffer[stream->buffer_pos]) { stream->buffer[0] = stream->get(stream->data); stream->buffer_pos = 0; c = stream->buffer[0]; if((unsigned char)c >= 0x80 && c != (char)EOF) { /* multi-byte UTF-8 sequence */ int i, count; count = utf8_check_first(c); if(!count) goto out; assert(count >= 2); for(i = 1; i < count; i++) stream->buffer[i] = stream->get(stream->data); if(!utf8_check_full(stream->buffer, count, NULL)) goto out; stream->stream_pos += count; stream->buffer[count] = '\0'; } else { stream->buffer[1] = '\0'; stream->stream_pos++; } } return stream->buffer[stream->buffer_pos++]; out: error_set(error, NULL, "unable to decode byte 0x%x at position %d", (unsigned char)c, stream->stream_pos); stream->buffer[0] = EOF; stream->buffer[1] = '\0'; stream->buffer_pos = 1; return EOF; }
static void stream_unget(stream_t *stream, int c) { if(c == STREAM_STATE_EOF || c == STREAM_STATE_ERROR) return; stream->position--; if(c == '\n') { stream->line--; stream->column = stream->last_column; } else if(utf8_check_first(c)) stream->column--; assert(stream->buffer_pos > 0); stream->buffer_pos--; assert(stream->buffer[stream->buffer_pos] == c); }
static int stream_get(stream_t *stream, json_error_t *error) { int c; if(stream->state != STREAM_STATE_OK) return stream->state; if(!stream->buffer[stream->buffer_pos]) { c = stream->get(stream->data); if(c == EOF) { stream->state = STREAM_STATE_EOF; return STREAM_STATE_EOF; } stream->buffer[0] = c; stream->buffer_pos = 0; if(0x80 <= c && c <= 0xFF) { /* multi-byte UTF-8 sequence */ int i, count; count = utf8_check_first(c); if(!count) goto out; assert(count >= 2); for(i = 1; i < count; i++) stream->buffer[i] = stream->get(stream->data); if(!utf8_check_full(stream->buffer, count, NULL)) goto out; stream->buffer[count] = '\0'; } else stream->buffer[1] = '\0'; } c = stream->buffer[stream->buffer_pos++]; stream->position++; if(c == '\n') { stream->line++; stream->last_column = stream->column; stream->column = 0; } else if(utf8_check_first(c)) { /* track the Unicode character column, so increment only if this is the first character of a UTF-8 sequence */ stream->column++; } return c; out: stream->state = STREAM_STATE_ERROR; error_set(error, stream_to_lex(stream), "unable to decode byte 0x%x", c); return STREAM_STATE_ERROR; }