/* sp-line-reader.c * * Copyright (C) 2015 Christian Hergert * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include "sp-line-reader.h" struct _SpLineReader { const gchar *contents; gsize length; gsize pos; }; void sp_line_reader_free (SpLineReader *self) { g_slice_free (SpLineReader, self); } /** * sp_line_reader_new: * @contents: The buffer to read lines from * @length: the length of @buffer in bytes * * Creates a new #SpLineReader for the contents provided. @contents are not * copied and therefore it is a programming error to free contents before * freeing the #SpLineReader structure. * * Use sp_line_reader_next() to read through the lines of the buffer. * * Returns: (transfer full): A new #SpLineReader that should be freed with * sp_line_reader_free() when no longer in use. */ SpLineReader * sp_line_reader_new (const gchar *contents, gssize length) { SpLineReader *self = g_slice_new (SpLineReader); if (contents == NULL) { contents = ""; length = 0; } else if (length < 0) { length = strlen (contents); } self->contents = contents; self->length = length; self->pos = 0; return self; } /** * sp_line_reader_next: * @self: the #SpLineReader * @length: a location for the length of the line in bytes * * Moves forward to the beginning of the next line in the buffer. No changes to * the buffer are made, and the result is a pointer within the string passed as * @contents in sp_line_reader_init(). Since the line most likely will not be * terminated with a NULL byte, you must provide @length to determine the * length of the line. * * Using "line[length]" will place you on the \n that was found for the line. * However, to perform this safely, you need to know that your string was * either \0 terminated to begin with, or that your buffer provides enough space * to guarantee you can dereference past the last "textual content" of the * buffer. * * Returns: (nullable) (transfer none): The beginning of the line within the buffer */ const gchar * sp_line_reader_next (SpLineReader *self, gsize *length) { const gchar *ret; const gchar *endptr; g_return_val_if_fail (self != NULL, NULL); g_return_val_if_fail (length != NULL, NULL); if ((self->contents == NULL) || (self->pos >= self->length)) { *length = 0; return NULL; } ret = &self->contents [self->pos]; endptr = memchr (ret, '\n', self->length - self->pos); if (G_UNLIKELY (endptr == NULL)) endptr = &self->contents [self->length]; *length = (endptr - ret); self->pos += *length + 1; return ret; }