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