xref: /aosp_15_r20/external/cpu_features/src/stack_line_reader.c (revision eca53ba6d2e951e174b64682eaf56a36b8204c89)
1*eca53ba6SRoland Levillain // Copyright 2017 Google LLC
2*eca53ba6SRoland Levillain //
3*eca53ba6SRoland Levillain // Licensed under the Apache License, Version 2.0 (the "License");
4*eca53ba6SRoland Levillain // you may not use this file except in compliance with the License.
5*eca53ba6SRoland Levillain // You may obtain a copy of the License at
6*eca53ba6SRoland Levillain //
7*eca53ba6SRoland Levillain //    http://www.apache.org/licenses/LICENSE-2.0
8*eca53ba6SRoland Levillain //
9*eca53ba6SRoland Levillain // Unless required by applicable law or agreed to in writing, software
10*eca53ba6SRoland Levillain // distributed under the License is distributed on an "AS IS" BASIS,
11*eca53ba6SRoland Levillain // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*eca53ba6SRoland Levillain // See the License for the specific language governing permissions and
13*eca53ba6SRoland Levillain // limitations under the License.
14*eca53ba6SRoland Levillain 
15*eca53ba6SRoland Levillain #include "internal/stack_line_reader.h"
16*eca53ba6SRoland Levillain 
17*eca53ba6SRoland Levillain #include <assert.h>
18*eca53ba6SRoland Levillain #include <errno.h>
19*eca53ba6SRoland Levillain #include <stdio.h>
20*eca53ba6SRoland Levillain 
21*eca53ba6SRoland Levillain #include "internal/filesystem.h"
22*eca53ba6SRoland Levillain 
StackLineReader_Initialize(StackLineReader * reader,int fd)23*eca53ba6SRoland Levillain void StackLineReader_Initialize(StackLineReader* reader, int fd) {
24*eca53ba6SRoland Levillain   reader->view.ptr = reader->buffer;
25*eca53ba6SRoland Levillain   reader->view.size = 0;
26*eca53ba6SRoland Levillain   reader->skip_mode = false;
27*eca53ba6SRoland Levillain   reader->fd = fd;
28*eca53ba6SRoland Levillain }
29*eca53ba6SRoland Levillain 
30*eca53ba6SRoland Levillain // Replaces the content of buffer with bytes from the file.
LoadFullBuffer(StackLineReader * reader)31*eca53ba6SRoland Levillain static int LoadFullBuffer(StackLineReader* reader) {
32*eca53ba6SRoland Levillain   const int read = CpuFeatures_ReadFile(reader->fd, reader->buffer,
33*eca53ba6SRoland Levillain                                         STACK_LINE_READER_BUFFER_SIZE);
34*eca53ba6SRoland Levillain   assert(read >= 0);
35*eca53ba6SRoland Levillain   reader->view.ptr = reader->buffer;
36*eca53ba6SRoland Levillain   reader->view.size = read;
37*eca53ba6SRoland Levillain   return read;
38*eca53ba6SRoland Levillain }
39*eca53ba6SRoland Levillain 
40*eca53ba6SRoland Levillain // Appends with bytes from the file to buffer, filling the remaining space.
LoadMore(StackLineReader * reader)41*eca53ba6SRoland Levillain static int LoadMore(StackLineReader* reader) {
42*eca53ba6SRoland Levillain   char* const ptr = reader->buffer + reader->view.size;
43*eca53ba6SRoland Levillain   const size_t size_to_read = STACK_LINE_READER_BUFFER_SIZE - reader->view.size;
44*eca53ba6SRoland Levillain   const int read = CpuFeatures_ReadFile(reader->fd, ptr, size_to_read);
45*eca53ba6SRoland Levillain   assert(read >= 0);
46*eca53ba6SRoland Levillain   assert(read <= (int)size_to_read);
47*eca53ba6SRoland Levillain   reader->view.size += read;
48*eca53ba6SRoland Levillain   return read;
49*eca53ba6SRoland Levillain }
50*eca53ba6SRoland Levillain 
IndexOfEol(StackLineReader * reader)51*eca53ba6SRoland Levillain static int IndexOfEol(StackLineReader* reader) {
52*eca53ba6SRoland Levillain   return CpuFeatures_StringView_IndexOfChar(reader->view, '\n');
53*eca53ba6SRoland Levillain }
54*eca53ba6SRoland Levillain 
55*eca53ba6SRoland Levillain // Relocate buffer's pending bytes at the beginning of the array and fills the
56*eca53ba6SRoland Levillain // remaining space with bytes from the file.
BringToFrontAndLoadMore(StackLineReader * reader)57*eca53ba6SRoland Levillain static int BringToFrontAndLoadMore(StackLineReader* reader) {
58*eca53ba6SRoland Levillain   if (reader->view.size && reader->view.ptr != reader->buffer) {
59*eca53ba6SRoland Levillain     memmove(reader->buffer, reader->view.ptr, reader->view.size);
60*eca53ba6SRoland Levillain   }
61*eca53ba6SRoland Levillain   reader->view.ptr = reader->buffer;
62*eca53ba6SRoland Levillain   return LoadMore(reader);
63*eca53ba6SRoland Levillain }
64*eca53ba6SRoland Levillain 
65*eca53ba6SRoland Levillain // Loads chunks of buffer size from disks until it contains a newline character
66*eca53ba6SRoland Levillain // or end of file.
SkipToNextLine(StackLineReader * reader)67*eca53ba6SRoland Levillain static void SkipToNextLine(StackLineReader* reader) {
68*eca53ba6SRoland Levillain   for (;;) {
69*eca53ba6SRoland Levillain     const int read = LoadFullBuffer(reader);
70*eca53ba6SRoland Levillain     if (read == 0) {
71*eca53ba6SRoland Levillain       break;
72*eca53ba6SRoland Levillain     } else {
73*eca53ba6SRoland Levillain       const int eol_index = IndexOfEol(reader);
74*eca53ba6SRoland Levillain       if (eol_index >= 0) {
75*eca53ba6SRoland Levillain         reader->view =
76*eca53ba6SRoland Levillain             CpuFeatures_StringView_PopFront(reader->view, eol_index + 1);
77*eca53ba6SRoland Levillain         break;
78*eca53ba6SRoland Levillain       }
79*eca53ba6SRoland Levillain     }
80*eca53ba6SRoland Levillain   }
81*eca53ba6SRoland Levillain }
82*eca53ba6SRoland Levillain 
CreateLineResult(bool eof,bool full_line,StringView view)83*eca53ba6SRoland Levillain static LineResult CreateLineResult(bool eof, bool full_line, StringView view) {
84*eca53ba6SRoland Levillain   LineResult result;
85*eca53ba6SRoland Levillain   result.eof = eof;
86*eca53ba6SRoland Levillain   result.full_line = full_line;
87*eca53ba6SRoland Levillain   result.line = view;
88*eca53ba6SRoland Levillain   return result;
89*eca53ba6SRoland Levillain }
90*eca53ba6SRoland Levillain 
91*eca53ba6SRoland Levillain // Helper methods to provide clearer semantic in StackLineReader_NextLine.
CreateEOFLineResult(StringView view)92*eca53ba6SRoland Levillain static LineResult CreateEOFLineResult(StringView view) {
93*eca53ba6SRoland Levillain   return CreateLineResult(true, true, view);
94*eca53ba6SRoland Levillain }
95*eca53ba6SRoland Levillain 
CreateTruncatedLineResult(StringView view)96*eca53ba6SRoland Levillain static LineResult CreateTruncatedLineResult(StringView view) {
97*eca53ba6SRoland Levillain   return CreateLineResult(false, false, view);
98*eca53ba6SRoland Levillain }
99*eca53ba6SRoland Levillain 
CreateValidLineResult(StringView view)100*eca53ba6SRoland Levillain static LineResult CreateValidLineResult(StringView view) {
101*eca53ba6SRoland Levillain   return CreateLineResult(false, true, view);
102*eca53ba6SRoland Levillain }
103*eca53ba6SRoland Levillain 
StackLineReader_NextLine(StackLineReader * reader)104*eca53ba6SRoland Levillain LineResult StackLineReader_NextLine(StackLineReader* reader) {
105*eca53ba6SRoland Levillain   if (reader->skip_mode) {
106*eca53ba6SRoland Levillain     SkipToNextLine(reader);
107*eca53ba6SRoland Levillain     reader->skip_mode = false;
108*eca53ba6SRoland Levillain   }
109*eca53ba6SRoland Levillain   {
110*eca53ba6SRoland Levillain     const bool can_load_more =
111*eca53ba6SRoland Levillain         reader->view.size < STACK_LINE_READER_BUFFER_SIZE;
112*eca53ba6SRoland Levillain     int eol_index = IndexOfEol(reader);
113*eca53ba6SRoland Levillain     if (eol_index < 0 && can_load_more) {
114*eca53ba6SRoland Levillain       const int read = BringToFrontAndLoadMore(reader);
115*eca53ba6SRoland Levillain       if (read == 0) {
116*eca53ba6SRoland Levillain         return CreateEOFLineResult(reader->view);
117*eca53ba6SRoland Levillain       }
118*eca53ba6SRoland Levillain       eol_index = IndexOfEol(reader);
119*eca53ba6SRoland Levillain     }
120*eca53ba6SRoland Levillain     if (eol_index < 0) {
121*eca53ba6SRoland Levillain       reader->skip_mode = true;
122*eca53ba6SRoland Levillain       return CreateTruncatedLineResult(reader->view);
123*eca53ba6SRoland Levillain     }
124*eca53ba6SRoland Levillain     {
125*eca53ba6SRoland Levillain       StringView line =
126*eca53ba6SRoland Levillain           CpuFeatures_StringView_KeepFront(reader->view, eol_index);
127*eca53ba6SRoland Levillain       reader->view =
128*eca53ba6SRoland Levillain           CpuFeatures_StringView_PopFront(reader->view, eol_index + 1);
129*eca53ba6SRoland Levillain       return CreateValidLineResult(line);
130*eca53ba6SRoland Levillain     }
131*eca53ba6SRoland Levillain   }
132*eca53ba6SRoland Levillain }
133