Repository navigation
Expand file tree
/
Copy pathsource-line-reader.cpp
More file actions
105 lines (84 loc) · 3.1 KB
/
Copy pathsource-line-reader.cpp
File metadata and controls
105 lines (84 loc) · 3.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
/*
* Copyright (C) 2026 Clownacy
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "source-line-reader.h"
#include <iostream>
#include <optional>
#include <string_view>
bool SourceLineReader::ReadRaw(std::size_t &line_buffer_write_position)
{
if (input_stream.eof())
return false;
for (;;)
{
input_stream.getline(&line_buffer[line_buffer_write_position], line_buffer.size() - line_buffer_write_position);
line_buffer_write_position += input_stream.gcount();
if (input_stream.eof())
break;
/* Do not count the newline. */
--line_buffer_write_position;
/* Failure indicates the buffer was not big enough; if it
is not set, then we have read a full line and can exit. */
if (!input_stream.fail())
break;
/* Make more room for the line. */
line_buffer.resize(line_buffer.size() * 2);
/* Now loop back around and read more of the line! */
}
return true;
}
std::optional<std::string_view> SourceLineReader::Read()
{
bool data_read = false;
std::size_t line_buffer_read_position = 0, line_buffer_write_position = 0;
while (ReadRaw(line_buffer_write_position))
{
char quote_character;
data_read = true;
/* Find where the code ends and a comment begins.
Note that terminating at ';' prevents a trailing '&' from being recognised
and causing a line to be continued on the next line.
This is needed for compatibility with S.N. 68k (asm68k). */
/* TODO: Does S.N. 68k actually concatenate when a '&' occurs before a comment? */
quote_character = '\0';
for (; line_buffer_read_position < line_buffer_write_position; ++line_buffer_read_position)
{
const char character = line_buffer[line_buffer_read_position];
if (quote_character == '\0')
{
if (character == '"' || character == '\'')
quote_character = character;
else if (character == ';')
break;
}
else if (character == quote_character)
{
quote_character = '\0';
}
}
/* An '&' at the end of a line is like a '\' at the end of a line in C:
it signals that the current line is continued on the next line. */
if (line_buffer_read_position == 0 || line_buffer[line_buffer_read_position - 1] != '&')
break;
/* Discard the '&'. */
--line_buffer_read_position;
--line_buffer_write_position;
/* Go back and get another line. */
}
if (!data_read)
return std::nullopt;
return std::string_view{line_buffer.data(), line_buffer_read_position};
}