/** * mio_write: * @mio: A #MIO object * @ptr: Pointer to the memory to write on the stream * @size: Size of each block to write * @nmemb: Number of block to write * * Writes raw data to a #MIO stream. This function behaves the same as fwrite(). * * Returns: The number of blocks actually written to the stream. This might be * smaller than the requested count if a write error occurs. */ size_t mio_write (MIO *mio, const void *ptr, size_t size, size_t nmemb) { if (mio->type == MIO_TYPE_FILE) return fwrite (ptr, size, nmemb, mio->impl.file.fp); else if (mio->type == MIO_TYPE_MEMORY) { size_t n_written = 0; if (size != 0 && nmemb != 0) { if (mem_try_ensure_space (mio, size * nmemb)) { memcpy (&mio->impl.mem.buf[mio->impl.mem.pos], ptr, size * nmemb); mio->impl.mem.pos += size * nmemb; n_written = nmemb; } } return n_written; } else { AssertNotReached (); return 0; } }
/** * mio_puts: * @mio: A #MIO object * @s: The string to write * * Writes a string to a #MIO object. This function behaves the same as fputs(). * * Returns: A non-negative integer on success or %EOF on failure. */ int mio_puts (MIO *mio, const char *s) { if (mio->type == MIO_TYPE_FILE) return fputs (s, mio->impl.file.fp); else if (mio->type == MIO_TYPE_MEMORY) { int rv = EOF; size_t len; len = strlen (s); if (mem_try_ensure_space (mio, len)) { memcpy (&mio->impl.mem.buf[mio->impl.mem.pos], s, len); mio->impl.mem.pos += len; rv = 1; } return rv; } else { AssertNotReached (); return 0; } }
/** * mio_vprintf: * @mio: A #MIO object * @format: A printf fomrat string * @ap: The variadic argument list for the format * * Writes a formatted string into a #MIO stream. This function behaves the same * as vfprintf(). * * Returns: The number of bytes written in the stream, or a negative value on * failure. */ int mio_vprintf (MIO *mio, const char *format, va_list ap) { if (mio->type == MIO_TYPE_FILE) return vfprintf (mio->impl.file.fp, format, ap); else if (mio->type == MIO_TYPE_MEMORY) { int rv = -1; size_t n; size_t old_pos; size_t old_size; va_list ap_copy; char c; old_pos = mio->impl.mem.pos; old_size = mio->impl.mem.size; va_copy (ap_copy, ap); /* compute the size we will need into the buffer */ n = vsnprintf (&c, 1, format, ap_copy); va_end (ap_copy); if (mem_try_ensure_space (mio, n)) { unsigned char c; /* backup character at n+1 that will be overwritten by a \0 ... */ c = mio->impl.mem.buf[mio->impl.mem.pos + (n - 1)]; rv = vsprintf ((char *)&mio->impl.mem.buf[mio->impl.mem.pos], format, ap); /* ...and restore it */ mio->impl.mem.buf[mio->impl.mem.pos + (n - 1)] = c; if (rv >= 0 && (size_t)rv == (n - 1)) { /* re-compute the actual size since we might have allocated one byte * more than needed */ mio->impl.mem.size = MAX (old_size, old_pos + (unsigned int)rv); mio->impl.mem.pos += (unsigned int)rv; } else { mio->impl.mem.size = old_size; rv = -1; } } return rv; } else { AssertNotReached (); return 0; } }
static gint mem_putc (MIO *mio, gint c) { gint rv = EOF; if (mem_try_ensure_space (mio, 1)) { mio->impl.mem.buf[mio->impl.mem.pos] = (guchar)c; mio->impl.mem.pos++; rv = (gint)((guchar)c); } return rv; }
static gint mem_puts (MIO *mio, const gchar *s) { gint rv = EOF; gsize len; len = strlen (s); if (mem_try_ensure_space (mio, len)) { memcpy (&mio->impl.mem.buf[mio->impl.mem.pos], s, len); mio->impl.mem.pos += len; rv = 1; } return rv; }
/** * mio_putc: * @mio: A #MIO object * @c: The character to write * * Writes a character to a #MIO stream. This function behaves the same as * fputc(). * * Returns: The written wharacter, or %EOF on error. */ int mio_putc (MIO *mio, int c) { if (mio->type == MIO_TYPE_FILE) return fputc (c, mio->impl.file.fp); else { int rv = EOF; if (mem_try_ensure_space (mio, 1)) { mio->impl.mem.buf[mio->impl.mem.pos] = (unsigned char)c; mio->impl.mem.pos++; rv = (int)((unsigned char)c); } return rv; } }
static gsize mem_write (MIO *mio, const void *ptr, gsize size, gsize nmemb) { gsize n_written = 0; if (size != 0 && nmemb != 0) { if (mem_try_ensure_space (mio, size * nmemb)) { memcpy (&mio->impl.mem.buf[mio->impl.mem.pos], ptr, size * nmemb); mio->impl.mem.pos += size * nmemb; n_written = nmemb; } } return n_written; }
static gint mem_vprintf (MIO *mio, const gchar *format, va_list ap) { gint rv = -1; gsize n; gsize old_pos; gsize old_size; va_list ap_copy; old_pos = mio->impl.mem.pos; old_size = mio->impl.mem.size; G_VA_COPY (ap_copy, ap); /* compute the size we will need into the buffer */ n = g_printf_string_upper_bound (format, ap_copy); va_end (ap_copy); if (mem_try_ensure_space (mio, n)) { guchar c; /* backup character at n+1 that will be overwritten by a \0 ... */ c = mio->impl.mem.buf[mio->impl.mem.pos + (n - 1)]; rv = vsprintf ((gchar *)&mio->impl.mem.buf[mio->impl.mem.pos], format, ap); /* ...and restore it */ mio->impl.mem.buf[mio->impl.mem.pos + (n - 1)] = c; if (G_LIKELY (rv >= 0 && (gsize)rv == (n - 1))) { /* re-compute the actual size since we might have allocated one byte * more than needed */ mio->impl.mem.size = MAX (old_size, old_pos + (guint)rv); mio->impl.mem.pos += (guint)rv; } else { mio->impl.mem.size = old_size; rv = -1; } } return rv; }