+ 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, char c)
+{
+ assert(stream->buffer_pos > 0);
+ stream->buffer_pos--;
+ assert(stream->buffer[stream->buffer_pos] == c);