Skip to content

Commit ea6fcd1

Browse files
committed
Address review comments
1 parent c806840 commit ea6fcd1

2 files changed

Lines changed: 55 additions & 39 deletions

File tree

src/runtime/modules/BuiltinsModule.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ PyResult<PyObject *> print(const PyTuple *args, const PyDict *kwargs, Interprete
114114
if (auto it = kwargs->map().find(file_keyword); it != kwargs->map().end()) {
115115
auto file_ = PyObject::from(it->second);
116116
if (file_.is_err()) { return file_; }
117-
file = file_.unwrap();
117+
if (file_.unwrap() != py_none()) { file = file_.unwrap(); }
118118
}
119119
if (auto it = kwargs->map().find(flush_keyword); it != kwargs->map().end()) {
120120
auto flush_ = PyObject::from(it->second);

src/runtime/modules/IOModule.cpp

Lines changed: 54 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -990,12 +990,17 @@ struct Buffered
990990
{
991991
if (auto err = check_initialized(); err.is_err()) return Err(err.unwrap_err());
992992

993-
if (n < -1) { return Err(value_error("read length must be non-negative or -1")); }
993+
if (n < 0) {
994+
// TODO: determine actual buffer size
995+
n = 4096;
996+
}
994997

995998
if (is_closed()) { return Err(value_error("read of closed file")); }
996999

1000+
if (n == 0) { return PyBytes::create(); }
1001+
9971002
const auto have = readahead();
998-
if (have > 0) { return static_cast<T *>(this)->readfast(n); }
1003+
if (have > 0) { return static_cast<T *>(this)->readfast(std::min<int64_t>(n, have)); }
9991004
Bytes b;
10001005
b.b.resize(n);
10011006
auto result = static_cast<T *>(this)->raw_read(std::span{ b.b.begin(), b.b.end() });
@@ -1150,8 +1155,8 @@ class BufferedReader
11501155
if (static_cast<int64_t>(n) <= current_size) {
11511156
ASSERT(buffer);
11521157
std::vector<std::byte> data;
1153-
data.resize(current_size);
1154-
buffer->sgetn(::bit_cast<char *>(data.begin().base()), current_size);
1158+
data.resize(n);
1159+
buffer->sgetn(::bit_cast<char *>(data.begin().base()), n);
11551160
return PyBytes::create(Bytes{ std::move(data) });
11561161
}
11571162
return Ok(py_none());
@@ -2207,16 +2212,14 @@ class FileIO : public RawIOBase
22072212
{
22082213
if (!m_filebuffer.is_open()) { return Err(value_error("I/O operation on closed file")); }
22092214

2210-
m_filebuffer.pubseekpos(0, std::ios::in);
2211-
22122215
// TODO: if (m_filestream.fail()) { TODO(); }
22132216
const auto initial_position = m_filebuffer.pubseekoff(0, std::ios::cur, std::ios::in);
22142217
if (initial_position == -1) { TODO(); }
22152218

22162219
const auto end_position = m_filebuffer.pubseekoff(0, std::ios::end, std::ios::in);
22172220
if (end_position == -1) { TODO(); }
22182221

2219-
m_filebuffer.pubseekpos(0, std::ios::in);
2222+
m_filebuffer.pubseekpos(initial_position, std::ios::in);
22202223
// TODO: if (m_filestream.fail()) { TODO(); }
22212224

22222225
const auto file_size = end_position - initial_position;
@@ -3118,45 +3121,58 @@ class TextIOWrapper : public TextIOBase
31183121
std::numeric_limits<size_t>::max());
31193122
if (result.is_err()) { return Err(result.unwrap_err()); }
31203123
auto [limit] = result.unwrap();
3124+
return readline_impl(limit);
3125+
}
31213126

3127+
PyResult<PyObject *> readline_impl(size_t limit)
3128+
{
31223129
if (auto result = writeflush(); result.is_err()) { return Err(result.unwrap_err()); }
31233130

31243131
// Lines in the input can end in \'\\n\', \'\\r\', or \'\\r\\n\'
31253132
auto is_line_end = [](std::string_view remaining) {
3126-
if (remaining.starts_with("\n") || remaining.starts_with("\r")) {
3127-
return 1;
3128-
} else if (remaining.starts_with("\r\n")) {
3129-
return 2;
3130-
}
3133+
if (remaining.starts_with("\r\n")) { return 2; }
3134+
if (remaining.starts_with("\n") || remaining.starts_with("\r")) { return 1; }
31313135
return 0;
31323136
};
3133-
while (!m_buffer_bytes.has_value() || m_buffer_bytes->b.empty()) {
3134-
auto chunk = read_chunk(0);
3135-
if (chunk.is_err()) { return Err(chunk.unwrap_err()); }
3136-
if (chunk.unwrap() == 0) { break; }
3137-
}
3138-
3139-
std::string_view remaining{ bit_cast<const char *>(m_buffer_bytes->b.data()) + m_position,
3140-
m_buffer_bytes->b.size() - m_position };
3141-
3142-
// TODO: use utf8 codepoints
3143-
const char *start = remaining.data();
3144-
size_t len = 0;
3145-
limit = std::min(limit, remaining.size());
3146-
for (; len < limit; ++len) {
3147-
if (auto chars = is_line_end(remaining)) {
3148-
// TODO: what if len becomes greater than limit due to \r\n?
3149-
len += chars;
3150-
break;
3137+
std::string line;
3138+
bool found_nl = false;
3139+
while (!found_nl && line.size() < limit) {
3140+
if (!m_buffer_bytes.has_value() || m_buffer_bytes->b.empty()) {
3141+
auto chunk = read_chunk(0);
3142+
if (chunk.is_err()) { return Err(chunk.unwrap_err()); }
3143+
if (!chunk.unwrap()) { break; }
3144+
}
3145+
3146+
// a trailing '\r' may be the first byte of a "\r\n" that straddles the
3147+
// chunk boundary; read ahead so is_line_end can see the full terminator
3148+
while (m_buffer_bytes->b.back() == std::byte{ '\r' }) {
3149+
auto chunk = read_chunk(0);
3150+
if (chunk.is_err()) { return Err(chunk.unwrap_err()); }
3151+
if (!chunk.unwrap()) { break; }
31513152
}
3152-
remaining = remaining.substr(1);
3153-
}
3154-
std::string line{ start, start + len };
3155-
std::rotate(
3156-
m_buffer_bytes->b.begin(), m_buffer_bytes->b.begin() + len, m_buffer_bytes->b.end());
3157-
m_position = 0;
3158-
m_buffer_bytes->b.resize(m_buffer_bytes->b.size() - line.size());
31593153

3154+
std::string_view remaining{ bit_cast<const char *>(m_buffer_bytes->b.data())
3155+
+ m_position,
3156+
m_buffer_bytes->b.size() - m_position };
3157+
3158+
// TODO: use utf8 codepoints
3159+
const char *start = remaining.data();
3160+
size_t len = 0;
3161+
const size_t scan_limit = std::min(limit - line.size(), remaining.size());
3162+
for (; len < scan_limit; ++len) {
3163+
if (auto chars = is_line_end(remaining)) {
3164+
// TODO: what if len becomes greater than limit due to \r\n?
3165+
len += chars;
3166+
found_nl = true;
3167+
break;
3168+
}
3169+
remaining = remaining.substr(1);
3170+
}
3171+
line.insert(line.end(), start, start + len);
3172+
m_buffer_bytes->b.erase(
3173+
m_buffer_bytes->b.begin(), m_buffer_bytes->b.begin() + m_position + len);
3174+
m_position = 0;
3175+
}
31603176
return PyString::create(std::move(line));
31613177
}
31623178

@@ -3167,7 +3183,7 @@ class TextIOWrapper : public TextIOBase
31673183
if (result_.is_err()) { return result_; }
31683184
auto *result = result_.unwrap();
31693185
while (m_position < m_buffer_bytes->b.size()) {
3170-
auto line = readline(nullptr, nullptr);
3186+
auto line = readline_impl(std::numeric_limits<size_t>::max());
31713187
if (line.is_err()) { return line; }
31723188
if (auto appended = result->append(line.unwrap()); appended.is_err()) {
31733189
return Err(appended.unwrap_err());

0 commit comments

Comments
 (0)