Files
sysprof/lib/sp-line-reader.c
Christian Hergert e4e1bf73b3 line-reader: handle invalid parameters more gracefully
This silences coverity which doesn't handle return_if_fail() macros
very well.
2016-08-22 11:02:03 -07:00

119 lines
3.3 KiB
C

/* sp-line-reader.c
*
* Copyright (C) 2015 Christian Hergert <christian@hergert.me>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#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;
}