gnss-sdr/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/stack_line_reader.c

141 lines
4.1 KiB
C

// SPDX-FileCopyrightText: 2017 Google Inc.
// SPDX-License-Identifier: Apache-2.0
#include "internal/stack_line_reader.h"
#include "internal/filesystem.h"
#include <assert.h>
#include <errno.h>
#include <stdio.h>
void StackLineReader_Initialize(StackLineReader* reader, int fd)
{
reader->view.ptr = reader->buffer;
reader->view.size = 0;
reader->skip_mode = false;
reader->fd = fd;
}
// Replaces the content of buffer with bytes from the file.
static int LoadFullBuffer(StackLineReader* reader)
{
const int read = CpuFeatures_ReadFile(reader->fd, reader->buffer,
STACK_LINE_READER_BUFFER_SIZE);
assert(read >= 0);
reader->view.ptr = reader->buffer;
reader->view.size = read;
return read;
}
// Appends with bytes from the file to buffer, filling the remaining space.
static int LoadMore(StackLineReader* reader)
{
char* const ptr = reader->buffer + reader->view.size;
const size_t size_to_read = STACK_LINE_READER_BUFFER_SIZE - reader->view.size;
const int read = CpuFeatures_ReadFile(reader->fd, ptr, size_to_read);
assert(read >= 0);
assert(read <= (int)size_to_read);
reader->view.size += read;
return read;
}
static int IndexOfEol(StackLineReader* reader)
{
return CpuFeatures_StringView_IndexOfChar(reader->view, '\n');
}
// Relocate buffer's pending bytes at the beginning of the array and fills the
// remaining space with bytes from the file.
static int BringToFrontAndLoadMore(StackLineReader* reader)
{
if (reader->view.size && reader->view.ptr != reader->buffer)
{
memmove(reader->buffer, reader->view.ptr, reader->view.size);
}
reader->view.ptr = reader->buffer;
return LoadMore(reader);
}
// Loads chunks of buffer size from disks until it contains a newline character
// or end of file.
static void SkipToNextLine(StackLineReader* reader)
{
for (;;)
{
const int read = LoadFullBuffer(reader);
if (read == 0)
{
break;
}
else
{
const int eol_index = IndexOfEol(reader);
if (eol_index >= 0)
{
reader->view =
CpuFeatures_StringView_PopFront(reader->view, eol_index + 1);
break;
}
}
}
}
static LineResult CreateLineResult(bool eof, bool full_line, StringView view)
{
LineResult result;
result.eof = eof;
result.full_line = full_line;
result.line = view;
return result;
}
// Helper methods to provide clearer semantic in StackLineReader_NextLine.
static LineResult CreateEOFLineResult(StringView view)
{
return CreateLineResult(true, true, view);
}
static LineResult CreateTruncatedLineResult(StringView view)
{
return CreateLineResult(false, false, view);
}
static LineResult CreateValidLineResult(StringView view)
{
return CreateLineResult(false, true, view);
}
LineResult StackLineReader_NextLine(StackLineReader* reader)
{
if (reader->skip_mode)
{
SkipToNextLine(reader);
reader->skip_mode = false;
}
{
const bool can_load_more =
reader->view.size < STACK_LINE_READER_BUFFER_SIZE;
int eol_index = IndexOfEol(reader);
if (eol_index < 0 && can_load_more)
{
const int read = BringToFrontAndLoadMore(reader);
if (read == 0)
{
return CreateEOFLineResult(reader->view);
}
eol_index = IndexOfEol(reader);
}
if (eol_index < 0)
{
reader->skip_mode = true;
return CreateTruncatedLineResult(reader->view);
}
{
StringView line =
CpuFeatures_StringView_KeepFront(reader->view, eol_index);
reader->view =
CpuFeatures_StringView_PopFront(reader->view, eol_index + 1);
return CreateValidLineResult(line);
}
}
}