mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
fix Object.free (#982)
* lib/std/collections: add HashMap.@each_entry()
* lib/std/json: fix Object.free() when object is a map
* lib/std/collections: fix allocator use in Object.{set,set_at,append}
* lib/std: add char.from_hex
* lib/std/collections: print arrays and objects compactly
* lib/std/io: fix Formatter.vprintf result
* lib/std/io/stream: rename module for ByteBuffer
* lib/std/io/stream: make Scanner a Stream reader
* lib/std/io: make std{in,err,out} return File* if no libc
This commit is contained in:
@@ -30,9 +30,19 @@ fn ByteBuffer*! ByteBuffer.tinit(&self, usz max_read, usz initial_capacity = 16)
|
||||
return self.init(max_read, initial_capacity, mem::temp())!;
|
||||
}
|
||||
|
||||
/**
|
||||
* @require buf.len > 0
|
||||
* @require self.bytes.len == 0 "Buffer already initialized."
|
||||
**/
|
||||
fn ByteBuffer*! ByteBuffer.init_with_buffer(&self, char[] buf)
|
||||
{
|
||||
*self = { .stream.fns = &BYTEBUFFER_INTERFACE, .max_read = buf.len, .bytes = buf };
|
||||
return self;
|
||||
}
|
||||
|
||||
fn void! ByteBuffer.free(&self)
|
||||
{
|
||||
self.allocator.free(self.bytes)!;
|
||||
if (self.allocator) self.allocator.free(self.bytes)!;
|
||||
*self = {};
|
||||
}
|
||||
|
||||
@@ -104,6 +114,23 @@ fn void! ByteBuffer.pushback_byte(&self)
|
||||
self.has_last = false;
|
||||
}
|
||||
|
||||
fn void! ByteBuffer.seek(&self, isz offset, Seek seek)
|
||||
{
|
||||
switch (seek)
|
||||
{
|
||||
case SET:
|
||||
if (offset < 0 || offset > self.write_idx) return IoError.INVALID_POSITION?;
|
||||
self.read_idx = offset;
|
||||
case CURSOR:
|
||||
if ((offset < 0 && self.read_idx < -offset) ||
|
||||
(offset > 0 && self.read_idx + offset > self.write_idx)) return IoError.INVALID_POSITION?;
|
||||
self.read_idx += offset;
|
||||
case END:
|
||||
if (offset < 0 || offset > self.write_idx) return IoError.INVALID_POSITION?;
|
||||
self.read_idx = self.write_idx - offset;
|
||||
}
|
||||
}
|
||||
|
||||
fn usz! ByteBuffer.available(&self) @inline
|
||||
{
|
||||
return self.write_idx - self.read_idx;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
module std::io::stream;
|
||||
module std::io;
|
||||
|
||||
struct LimitReader
|
||||
{
|
||||
|
||||
@@ -2,7 +2,8 @@ module std::io;
|
||||
|
||||
struct Scanner
|
||||
{
|
||||
Stream* stream;
|
||||
inline Stream stream;
|
||||
Stream* wrapped_stream;
|
||||
char[] buf;
|
||||
usz pattern_idx;
|
||||
usz read_idx;
|
||||
@@ -20,9 +21,14 @@ struct Scanner
|
||||
**/
|
||||
fn void Scanner.init(&self, Stream* stream, char[] buffer)
|
||||
{
|
||||
*self = { .stream = stream, .buf = buffer };
|
||||
*self = { .stream.fns = &SCANNER_INTERFACE, .wrapped_stream = stream, .buf = buffer };
|
||||
}
|
||||
|
||||
const StreamInterface SCANNER_INTERFACE = {
|
||||
.read_fn = (ReadStreamFn)&Scanner.read,
|
||||
.read_byte_fn = (ReadByteStreamFn)&Scanner.read_byte,
|
||||
};
|
||||
|
||||
/**
|
||||
* Return and clear any remaining unscanned data.
|
||||
**/
|
||||
@@ -85,7 +91,7 @@ macro usz! Scanner.find(&self, buf, pattern) @private
|
||||
|
||||
macro usz! Scanner.refill(&self, buf) @private
|
||||
{
|
||||
usz! n = self.stream.read(buf);
|
||||
usz! n = self.wrapped_stream.read(buf);
|
||||
if (catch err = n)
|
||||
{
|
||||
case IoError.EOF:
|
||||
@@ -94,4 +100,27 @@ macro usz! Scanner.refill(&self, buf) @private
|
||||
return err?;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
fn usz! Scanner.read(&self, char[] bytes)
|
||||
{
|
||||
usz n;
|
||||
if (self.pattern_idx < self.read_idx)
|
||||
{
|
||||
n = min(bytes.len, self.read_idx - self.pattern_idx);
|
||||
bytes[:n] = self.buf[self.pattern_idx:n];
|
||||
self.pattern_idx += n;
|
||||
bytes = bytes[n..];
|
||||
}
|
||||
n += self.wrapped_stream.read(bytes)!;
|
||||
return n;
|
||||
}
|
||||
|
||||
fn char! Scanner.read_byte(&self)
|
||||
{
|
||||
if (self.pattern_idx < self.read_idx)
|
||||
{
|
||||
return self.buf[self.pattern_idx++];
|
||||
}
|
||||
return self.wrapped_stream.read_byte();
|
||||
}
|
||||
Reference in New Issue
Block a user