+/* Internal function: Read one UTF-8 character, which may be more than one byte,
+from a memory stream @str, and return it as a Unicode code point. */
+static glsi32
+read_utf8_char_from_buffer(strid_t str)
+{
+ size_t foo;
+ gunichar charresult = (gunichar)-2;
+ char *buffer = str->buffer + str->mark;
+ size_t maxlen = str->buflen - str->mark;
+
+ if(maxlen == 0)
+ return -1;
+
+ for(foo = 1; foo <= maxlen; foo++)
+ {
+ charresult = g_utf8_get_char_validated(buffer, foo);
+ /* charresult is -1 if invalid, -2 if incomplete, and the
+ Unicode code point otherwise */
+ if(charresult != (gunichar)-2)
+ break;
+ }
+ str->mark += foo;
+ str->read_count++;
+
+ /* Return -1 on EOS */
+ if(charresult == (gunichar)-2)
+ return -1;
+ /* Silently return unknown characters as 0xFFFD, Replacement Character */
+ if(charresult == (gunichar)-1)
+ return 0xFFFD;
+ return charresult;
+}
+
+/* Internal function: Read one big-endian four-byte character from memory and
+return it as a Unicode code point, or -1 on EOF */
+static glsi32
+read_ucs4be_char_from_buffer(strid_t str)
+{
+ glui32 ch = str->buffer[str->mark++];
+ if(str->mark >= str->buflen)
+ return -1;
+ ch = (ch << 8) | (str->buffer[str->mark++] & 0xFF);
+ if(str->mark >= str->buflen)
+ return -1;
+ ch = (ch << 8) | (str->buffer[str->mark++] & 0xFF);
+ if(str->mark >= str->buflen)
+ return -1;
+ ch = (ch << 8) | (str->buffer[str->mark++] & 0xFF);
+ str->read_count++;
+ return ch;
+}
+