Update stdlib with new syntax for short function decl.

This commit is contained in:
Christoffer Lerno
2025-02-08 23:04:59 +01:00
parent c4f9efc8f5
commit e1d546225f
16 changed files with 335 additions and 417 deletions

View File

@@ -71,24 +71,21 @@ import std::io;
@param [in] input `The raw RGB or RGBA pixels to encode`
@param [&in] desc `The descriptor of the image`
*>
fn usz! write(String filename, char[] input, QOIDesc* desc)
fn usz! write(String filename, char[] input, QOIDesc* desc) => @pool()
{
@pool()
{
// encode data
char[] output = new_encode(input, desc)!;
// encode data
char[] output = new_encode(input, desc)!;
// open file
File! f = file::open(filename, "wb");
if (catch f) return QOIError.FILE_OPEN_FAILED?;
// open file
File! f = file::open(filename, "wb");
if (catch f) return QOIError.FILE_OPEN_FAILED?;
// write data to file and close it
usz! written = f.write(output);
if (catch written) return QOIError.FILE_WRITE_FAILED?;
if (catch f.close()) return QOIError.FILE_WRITE_FAILED?;
// write data to file and close it
usz! written = f.write(output);
if (catch written) return QOIError.FILE_WRITE_FAILED?;
if (catch f.close()) return QOIError.FILE_WRITE_FAILED?;
return written;
};
return written;
}
@@ -113,16 +110,12 @@ fn usz! write(String filename, char[] input, QOIDesc* desc)
@param [&out] desc `The descriptor to fill with the image's info`
@param channels `The channels to be used`
*>
fn char[]! new_read(String filename, QOIDesc* desc, QOIChannels channels = AUTO, Allocator allocator = allocator::heap())
fn char[]! new_read(String filename, QOIDesc* desc, QOIChannels channels = AUTO, Allocator allocator = allocator::heap()) => @pool(allocator)
{
@pool(allocator)
{
// read file
char[] data = file::load_temp(filename) ?? QOIError.FILE_OPEN_FAILED?!;
// pass data to decode function
return new_decode(data, desc, channels, allocator);
};
// read file
char[] data = file::load_temp(filename) ?? QOIError.FILE_OPEN_FAILED?!;
// pass data to decode function
return new_decode(data, desc, channels, allocator);
}
fn char[]! read(String filename, QOIDesc* desc, QOIChannels channels = AUTO, Allocator allocator = allocator::heap()) @deprecated("Use new_read")

View File

@@ -49,13 +49,10 @@ fn void TrackingAllocator.free(&self)
<*
@return "the total allocated memory not yet freed."
*>
fn usz TrackingAllocator.allocated(&self)
fn usz TrackingAllocator.allocated(&self) => @pool()
{
usz allocated = 0;
@pool()
{
foreach (&allocation : self.map.value_tlist()) allocated += allocation.size;
};
foreach (&allocation : self.map.value_tlist()) allocated += allocation.size;
return allocated;
}
@@ -118,99 +115,95 @@ fn void TrackingAllocator.clear(&self)
fn void TrackingAllocator.print_report(&self) => self.fprint_report(io::stdout())!!;
fn void! TrackingAllocator.fprint_report(&self, OutStream out)
fn void! TrackingAllocator.fprint_report(&self, OutStream out) => @pool()
{
usz total = 0;
usz entries = 0;
bool leaks = false;
@pool()
{
Allocation[] allocs = self.map.value_tlist();
if (allocs.len)
{
if (!allocs[0].backtrace[0])
{
io::fprintn(out, "======== Memory Report ========")!;
io::fprintn(out, "Size in bytes Address")!;
foreach (i, &allocation : allocs)
{
entries++;
total += allocation.size;
io::fprintfn(out, "%13s %p", allocation.size, allocation.ptr)!;
}
io::fprintn(out, "===============================")!;
}
else
Allocation[] allocs = self.map.value_tlist();
if (allocs.len)
{
if (!allocs[0].backtrace[0])
{
io::fprintn(out, "======== Memory Report ========")!;
io::fprintn(out, "Size in bytes Address")!;
foreach (i, &allocation : allocs)
{
io::fprintn(out, "================================== Memory Report ==================================")!;
io::fprintn(out, "Size in bytes Address Function ")!;
foreach (i, &allocation : allocs)
{
entries++;
total += allocation.size;
BacktraceList backtraces = {};
Backtrace trace = backtrace::BACKTRACE_UNKNOWN;
if (allocation.backtrace[3])
{
trace = backtrace::symbolize_backtrace(allocation.backtrace[3:1], allocator::temp()).get(0) ?? backtrace::BACKTRACE_UNKNOWN;
}
if (trace.function.len) leaks = true;
io::fprintfn(out, "%13s %p %s:%d", allocation.size,
allocation.ptr, trace.function.len ? trace.function : "???",
trace.line ? trace.line : 0)!;
}
io::fprintn(out, "===================================================================================")!;
entries++;
total += allocation.size;
io::fprintfn(out, "%13s %p", allocation.size, allocation.ptr)!;
}
io::fprintn(out, "===============================")!;
}
else
{
io::fprintn(out, "* NO ALLOCATIONS FOUND *")!;
}
io::fprintfn(out, "- Total currently allocated memory: %d", total)!;
io::fprintfn(out, "- Total current allocations: %d", entries)!;
io::fprintfn(out, "- Total allocations (freed and retained): %d", self.allocs_total)!;
io::fprintfn(out, "- Total allocated memory (freed and retained): %d", self.mem_total)!;
if (leaks)
{
io::fprintn(out)!;
io::fprintn(out, "Full leak report:")!;
io::fprintn(out, "================================== Memory Report ==================================")!;
io::fprintn(out, "Size in bytes Address Function ")!;
foreach (i, &allocation : allocs)
{
if (!allocation.backtrace[3])
{
io::fprintfn(out, "Allocation %d (%d bytes) - no backtrace available.", i + 1, allocation.size)!;
continue;
}
entries++;
total += allocation.size;
BacktraceList backtraces = {};
usz end = MAX_BACKTRACE;
foreach (j, val : allocation.backtrace)
Backtrace trace = backtrace::BACKTRACE_UNKNOWN;
if (allocation.backtrace[3])
{
if (!val)
{
end = j;
break;
}
trace = backtrace::symbolize_backtrace(allocation.backtrace[3:1], allocator::temp()).get(0) ?? backtrace::BACKTRACE_UNKNOWN;
}
BacktraceList list = backtrace::symbolize_backtrace(allocation.backtrace[3..(end - 1)], allocator::temp())!;
io::fprintfn(out, "Allocation %d (%d bytes): ", i + 1, allocation.size)!;
foreach (trace : list)
if (trace.function.len) leaks = true;
io::fprintfn(out, "%13s %p %s:%d", allocation.size,
allocation.ptr, trace.function.len ? trace.function : "???",
trace.line ? trace.line : 0)!;
}
io::fprintn(out, "===================================================================================")!;
}
}
else
{
io::fprintn(out, "* NO ALLOCATIONS FOUND *")!;
}
io::fprintfn(out, "- Total currently allocated memory: %d", total)!;
io::fprintfn(out, "- Total current allocations: %d", entries)!;
io::fprintfn(out, "- Total allocations (freed and retained): %d", self.allocs_total)!;
io::fprintfn(out, "- Total allocated memory (freed and retained): %d", self.mem_total)!;
if (leaks)
{
io::fprintn(out)!;
io::fprintn(out, "Full leak report:")!;
foreach (i, &allocation : allocs)
{
if (!allocation.backtrace[3])
{
io::fprintfn(out, "Allocation %d (%d bytes) - no backtrace available.", i + 1, allocation.size)!;
continue;
}
BacktraceList backtraces = {};
usz end = MAX_BACKTRACE;
foreach (j, val : allocation.backtrace)
{
if (!val)
{
if (trace.has_file())
{
io::fprintfn(out, " %s (in %s:%d)", trace.function, trace.file, trace.line);
continue;
}
if (trace.is_unknown())
{
io::fprintfn(out, " ??? (in unknown)");
continue;
}
io::fprintfn(out, " %s (source unavailable)", trace.function);
end = j;
break;
}
}
BacktraceList list = backtrace::symbolize_backtrace(allocation.backtrace[3..(end - 1)], allocator::temp())!;
io::fprintfn(out, "Allocation %d (%d bytes): ", i + 1, allocation.size)!;
foreach (trace : list)
{
if (trace.has_file())
{
io::fprintfn(out, " %s (in %s:%d)", trace.function, trace.file, trace.line);
continue;
}
if (trace.is_unknown())
{
io::fprintfn(out, " ??? (in unknown)");
continue;
}
io::fprintfn(out, " %s (source unavailable)", trace.function);
}
}
};
}
}

View File

@@ -62,38 +62,37 @@ macro anycast(any v, $Type) @builtin
return ($Type*)v.ptr;
}
fn bool print_backtrace(String message, int backtraces_to_ignore) @if(env::NATIVE_STACKTRACE)
fn bool print_backtrace(String message, int backtraces_to_ignore) @if(env::NATIVE_STACKTRACE) => @pool()
{
@pool()
void*[256] buffer;
void*[] backtraces = backtrace::capture_current(&buffer);
backtraces_to_ignore++;
BacktraceList! backtrace = backtrace::symbolize_backtrace(backtraces, allocator::temp());
if (catch backtrace) return false;
if (backtrace.len() <= backtraces_to_ignore) return false;
io::eprint("\nERROR: '");
io::eprint(message);
io::eprintn("'");
foreach (i, &trace : backtrace)
{
void*[256] buffer;
void*[] backtraces = backtrace::capture_current(&buffer);
backtraces_to_ignore++;
BacktraceList! backtrace = backtrace::symbolize_backtrace(backtraces, allocator::temp());
if (catch backtrace) return false;
if (backtrace.len() <= backtraces_to_ignore) return false;
io::eprint("\nERROR: '");
io::eprint(message);
io::eprintn("'");
foreach (i, &trace : backtrace)
if (i < backtraces_to_ignore) continue;
String inline_suffix = trace.is_inline ? " [inline]" : "";
if (trace.is_unknown())
{
if (i < backtraces_to_ignore) continue;
String inline_suffix = trace.is_inline ? " [inline]" : "";
if (trace.is_unknown())
{
io::eprintfn(" in ???%s", inline_suffix);
continue;
}
if (trace.has_file())
{
io::eprintfn(" in %s (%s:%d) [%s]%s", trace.function, trace.file, trace.line, trace.object_file, inline_suffix);
continue;
}
io::eprintfn(" in %s (source unavailable) [%s]%s", trace.function, trace.object_file, inline_suffix);
io::eprintfn(" in ???%s", inline_suffix);
continue;
}
return true;
};
if (trace.has_file())
{
io::eprintfn(" in %s (%s:%d) [%s]%s", trace.function, trace.file, trace.line, trace.object_file, inline_suffix);
continue;
}
io::eprintfn(" in %s (source unavailable) [%s]%s", trace.function, trace.object_file, inline_suffix);
}
return true;
}
fn void default_panic(String message, String file, String function, uint line) @if(env::NATIVE_STACKTRACE)
{
$if $defined(io::stderr):

View File

@@ -168,10 +168,7 @@ fn bool run_benchmarks(BenchmarkUnit[] benchmarks) @if(!$$OLD_TEST)
return true;
}
fn bool default_benchmark_runner(String[] args)
fn bool default_benchmark_runner(String[] args) => @pool()
{
@pool()
{
return run_benchmarks(benchmark_collection_create(allocator::temp()));
};
return run_benchmarks(benchmark_collection_create(allocator::temp()));
}

View File

@@ -66,20 +66,18 @@ fn int cmp_test_unit(TestUnit a, TestUnit b)
return (int)(an - bn);
}
fn bool terminal_has_ansi_codes() @local
fn bool terminal_has_ansi_codes() @local => @pool()
{
@pool()
if (try v = env::get_var_temp("TERM"))
{
if (try v = env::get_var_temp("TERM"))
{
if (v.contains("xterm") || v.contains("vt100") || v.contains("screen")) return true;
}
$if env::WIN32 || env::NO_LIBC:
return false;
$else
return io::stdout().isatty();
$endif
};
if (v.contains("xterm") || v.contains("vt100") || v.contains("screen")) return true;
}
$if env::WIN32 || env::NO_LIBC:
return false;
$else
return io::stdout().isatty();
$endif
}
fn void test_panic(String message, String file, String function, uint line) @local
@@ -304,12 +302,9 @@ fn bool run_tests(String[] args, TestUnit[] tests) @private
return n_failed == 0;
}
fn bool default_test_runner(String[] args)
fn bool default_test_runner(String[] args) => @pool()
{
@pool()
{
assert(test_context == null, "test suite is already running");
return run_tests(args, test_collection_create(allocator::temp()));
};
assert(test_context == null, "test suite is already running");
return run_tests(args, test_collection_create(allocator::temp()));
}

View File

@@ -52,14 +52,11 @@ fn ZString tformat_zstr(String fmt, args...)
@param [inout] allocator `The allocator to use`
@param [in] fmt `The formatting string`
*>
fn String format(String fmt, args..., Allocator allocator)
fn String format(String fmt, args..., Allocator allocator) => @pool(allocator)
{
@pool(allocator)
{
DString str = dstring::temp_with_capacity(fmt.len + args.len * 8);
str.appendf(fmt, ...args);
return str.copy_str(allocator);
};
DString str = dstring::temp_with_capacity(fmt.len + args.len * 8);
str.appendf(fmt, ...args);
return str.copy_str(allocator);
}
<*
@@ -87,14 +84,11 @@ fn String tformat(String fmt, args...)
@param [in] fmt `The formatting string`
@param [inout] allocator `The allocator to use`
*>
fn ZString new_format_zstr(String fmt, args..., Allocator allocator = allocator::heap())
fn ZString new_format_zstr(String fmt, args..., Allocator allocator = allocator::heap()) => @pool(allocator)
{
@pool(allocator)
{
DString str = dstring::temp_with_capacity(fmt.len + args.len * 8);
str.appendf(fmt, ...args);
return str.copy_zstr(allocator);
};
DString str = dstring::temp_with_capacity(fmt.len + args.len * 8);
str.appendf(fmt, ...args);
return str.copy_zstr(allocator);
}
<*

View File

@@ -70,12 +70,9 @@ fn void CsvRow.free(&self)
self.allocator = null;
}
fn void! CsvReader.skip_row(self) @maydiscard
fn void! CsvReader.skip_row(self) @maydiscard => @pool()
{
@pool()
{
(void)io::treadline(self.stream);
};
(void)io::treadline(self.stream);
}
macro void! CsvReader.@each_row(self, int rows = int.max; @body(String[] row)) @maydiscard

View File

@@ -5,57 +5,48 @@ import libc;
@require mode.len > 0
@require filename.len > 0
*>
fn void*! native_fopen(String filename, String mode) @inline
fn void*! native_fopen(String filename, String mode) @inline => @pool()
{
@pool()
{
$if env::WIN32:
void* file = libc::_wfopen(filename.to_temp_wstring(), mode.to_temp_wstring())!;
$else
void* file = libc::fopen(filename.zstr_tcopy(), mode.zstr_tcopy());
$endif
return file ?: file_open_errno()?;
};
$if env::WIN32:
void* file = libc::_wfopen(filename.to_temp_wstring(), mode.to_temp_wstring())!;
$else
void* file = libc::fopen(filename.zstr_tcopy(), mode.zstr_tcopy());
$endif
return file ?: file_open_errno()?;
}
fn void! native_remove(String filename)
fn void! native_remove(String filename) => @pool()
{
@pool()
$if env::WIN32:
CInt result = libc::_wremove(filename.to_temp_wstring())!;
$else
CInt result = libc::remove(filename.zstr_tcopy());
$endif
if (result)
{
$if env::WIN32:
CInt result = libc::_wremove(filename.to_temp_wstring())!;
$else
CInt result = libc::remove(filename.zstr_tcopy());
$endif
if (result)
switch (libc::errno())
{
switch (libc::errno())
{
case errno::ENOENT:
return IoError.FILE_NOT_FOUND?;
case errno::EACCES:
default:
return IoError.FILE_CANNOT_DELETE?;
}
case errno::ENOENT:
return IoError.FILE_NOT_FOUND?;
case errno::EACCES:
default:
return IoError.FILE_CANNOT_DELETE?;
}
};
}
}
<*
@require mode.len > 0
@require filename.len > 0
*>
fn void*! native_freopen(void* file, String filename, String mode) @inline
fn void*! native_freopen(void* file, String filename, String mode) @inline => @pool()
{
@pool()
{
$if env::WIN32:
file = libc::_wfreopen(filename.to_temp_wstring(), mode.to_temp_wstring(), file)!;
$else
file = libc::freopen(filename.zstr_tcopy(), mode.zstr_tcopy(), file);
$endif
return file ?: file_open_errno()?;
};
$if env::WIN32:
file = libc::_wfreopen(filename.to_temp_wstring(), mode.to_temp_wstring(), file)!;
$else
file = libc::freopen(filename.zstr_tcopy(), mode.zstr_tcopy(), file);
$endif
return file ?: file_open_errno()?;
}
fn void! native_fseek(void* file, isz offset, Seek seek_mode) @inline

View File

@@ -1,56 +1,50 @@
module std::io::os;
import libc, std::os, std::io;
fn void! native_stat(Stat* stat, String path) @if(env::DARWIN || env::LINUX || env::BSD_FAMILY)
fn void! native_stat(Stat* stat, String path) @if(env::DARWIN || env::LINUX || env::BSD_FAMILY) => @pool()
{
@pool()
$if env::DARWIN || env::LINUX || env::BSD_FAMILY:
int res = libc::stat(path.zstr_tcopy(), stat);
$else
unreachable("Stat unimplemented");
int res = 0;
$endif
if (res != 0)
{
$if env::DARWIN || env::LINUX || env::BSD_FAMILY:
int res = libc::stat(path.zstr_tcopy(), stat);
$else
unreachable("Stat unimplemented");
int res = 0;
$endif
if (res != 0)
switch (libc::errno())
{
switch (libc::errno())
{
case errno::EBADF:
return IoError.FILE_NOT_VALID?;
case errno::EFAULT:
unreachable("Invalid stat");
case errno::EIO:
return IoError.GENERAL_ERROR?;
case errno::EACCES:
return IoError.NO_PERMISSION?;
case errno::ELOOP:
return IoError.NO_PERMISSION?;
case errno::ENAMETOOLONG:
return IoError.NAME_TOO_LONG?;
case errno::ENOENT:
return IoError.FILE_NOT_FOUND?;
case errno::ENOTDIR:
return IoError.FILE_NOT_DIR?;
case errno::EOVERFLOW:
return IoError.GENERAL_ERROR?;
default:
return IoError.UNKNOWN_ERROR?;
}
case errno::EBADF:
return IoError.FILE_NOT_VALID?;
case errno::EFAULT:
unreachable("Invalid stat");
case errno::EIO:
return IoError.GENERAL_ERROR?;
case errno::EACCES:
return IoError.NO_PERMISSION?;
case errno::ELOOP:
return IoError.NO_PERMISSION?;
case errno::ENAMETOOLONG:
return IoError.NAME_TOO_LONG?;
case errno::ENOENT:
return IoError.FILE_NOT_FOUND?;
case errno::ENOTDIR:
return IoError.FILE_NOT_DIR?;
case errno::EOVERFLOW:
return IoError.GENERAL_ERROR?;
default:
return IoError.UNKNOWN_ERROR?;
}
};
}
}
fn usz! native_file_size(String path) @if(env::WIN32)
fn usz! native_file_size(String path) @if(env::WIN32) => @pool()
{
@pool()
{
Win32_FILE_ATTRIBUTE_DATA data;
win32::getFileAttributesExW(path.to_temp_wstring()!, Win32_GET_FILEEX_INFO_LEVELS.STANDARD, &data);
Win32_LARGE_INTEGER size;
size.lowPart = data.nFileSizeLow;
size.highPart = data.nFileSizeHigh;
return (usz)size.quadPart;
};
Win32_FILE_ATTRIBUTE_DATA data;
win32::getFileAttributesExW(path.to_temp_wstring()!, Win32_GET_FILEEX_INFO_LEVELS.STANDARD, &data);
Win32_LARGE_INTEGER size;
size.lowPart = data.nFileSizeLow;
size.highPart = data.nFileSizeHigh;
return (usz)size.quadPart;
}
fn usz! native_file_size(String path) @if(!env::WIN32 && !env::DARWIN)

View File

@@ -11,16 +11,13 @@ fn Path! native_temp_directory(Allocator allocator = allocator::heap()) @if(!env
return path::new("/tmp", allocator);
}
fn Path! native_temp_directory(Allocator allocator = allocator::heap()) @if(env::WIN32)
fn Path! native_temp_directory(Allocator allocator = allocator::heap()) @if(env::WIN32) => @pool(allocator)
{
@pool(allocator)
{
Win32_DWORD len = win32::getTempPathW(0, null);
if (!len) return IoError.GENERAL_ERROR?;
Char16[] buff = mem::temp_alloc_array(Char16, len + (usz)1);
if (!win32::getTempPathW(len, buff)) return IoError.GENERAL_ERROR?;
return path::new(string::temp_from_utf16(buff[:len]), allocator);
};
Win32_DWORD len = win32::getTempPathW(0, null);
if (!len) return IoError.GENERAL_ERROR?;
Char16[] buff = mem::temp_alloc_array(Char16, len + (usz)1);
if (!win32::getTempPathW(len, buff)) return IoError.GENERAL_ERROR?;
return path::new(string::temp_from_utf16(buff[:len]), allocator);
}
module std::io::os @if(env::NO_LIBC);

View File

@@ -29,12 +29,9 @@ enum PathEnv
POSIX
}
fn Path! new_cwd(Allocator allocator = allocator::heap())
fn Path! new_cwd(Allocator allocator = allocator::heap()) => @pool(allocator)
{
@pool(allocator)
{
return new(os::getcwd(allocator::temp()), allocator);
};
return new(os::getcwd(allocator::temp()), allocator);
}
fn Path! getcwd(Allocator allocator = allocator::heap()) @deprecated("Use new_cwd()")
@@ -164,12 +161,9 @@ fn Path! temp_new(String path, PathEnv path_env = DEFAULT_PATH_ENV)
return new(path, allocator::temp(), path_env);
}
fn Path! new_win32_wstring(WString path, Allocator allocator = allocator::heap())
fn Path! new_win32_wstring(WString path, Allocator allocator = allocator::heap()) => @pool(allocator)
{
@pool(allocator)
{
return path::new(string::temp_from_wstring(path)!, allocator: allocator);
};
return path::new(string::temp_from_wstring(path)!, allocator: allocator);
}
fn Path! new_windows(String path, Allocator allocator = allocator::heap())

View File

@@ -257,16 +257,13 @@ fn bool InetAddress.is_multicast_link_local(InetAddress* addr)
return addr.ipv4.a == 224 && addr.ipv4.b == 0 && addr.ipv4.c == 0;
}
fn AddrInfo*! addrinfo(String host, uint port, AIFamily ai_family, AISockType ai_socktype) @if(os::SUPPORTS_INET)
fn AddrInfo*! addrinfo(String host, uint port, AIFamily ai_family, AISockType ai_socktype) @if(os::SUPPORTS_INET) => @pool()
{
@pool()
{
ZString zhost = host.zstr_tcopy();
DString str = dstring::temp_with_capacity(32);
str.appendf("%d", port);
AddrInfo hints = { .ai_family = ai_family, .ai_socktype = ai_socktype };
AddrInfo* ai;
if (os::getaddrinfo(zhost, str.zstr_view(), &hints, &ai)) return NetError.ADDRINFO_FAILED?;
return ai;
};
ZString zhost = host.zstr_tcopy();
DString str = dstring::temp_with_capacity(32);
str.appendf("%d", port);
AddrInfo hints = { .ai_family = ai_family, .ai_socktype = ai_socktype };
AddrInfo* ai;
if (os::getaddrinfo(zhost, str.zstr_view(), &hints, &ai)) return NetError.ADDRINFO_FAILED?;
return ai;
}

View File

@@ -177,70 +177,67 @@ fn Url! new_parse(String url_string, Allocator allocator = allocator::heap())
@param [inout] allocator
@return "Url as a string"
*>
fn String Url.to_string(&self, Allocator allocator = allocator::heap()) @dynamic
fn String Url.to_string(&self, Allocator allocator = allocator::heap()) @dynamic => @pool(allocator)
{
@pool(allocator)
DString builder = dstring::temp_new();
// Add scheme if it exists
if (self.scheme != "")
{
DString builder = dstring::temp_new();
builder.append_chars(self.scheme);
builder.append_char(':');
if (self.host.len > 0) builder.append_chars("//");
}
// Add scheme if it exists
if (self.scheme != "")
{
builder.append_chars(self.scheme);
builder.append_char(':');
if (self.host.len > 0) builder.append_chars("//");
}
// Add username and password if they exist
if (self.username != "")
{
String username = temp_encode(self.username, USERPASS);
builder.append_chars(username);
// Add username and password if they exist
if (self.username != "")
{
String username = temp_encode(self.username, USERPASS);
builder.append_chars(username);
if (self.password != "")
{
builder.append_char(':');
String password = temp_encode(self.password, USERPASS);
builder.append_chars(password);
}
builder.append_char('@');
}
// Add host
String host = temp_encode(self.host, HOST);
builder.append_chars(host);
// Add port
if (self.port != 0)
if (self.password != "")
{
builder.append_char(':');
builder.appendf("%d", self.port);
String password = temp_encode(self.password, USERPASS);
builder.append_chars(password);
}
builder.append_char('@');
}
// Add path
String path = temp_encode(self.path, PATH);
builder.append_chars(path);
// Add host
String host = temp_encode(self.host, HOST);
builder.append_chars(host);
// Add query if it exists (note that `query` is expected to
// be already properly encoded).
if (self.query != "")
{
builder.append_char('?');
builder.append_chars(self.query);
}
// Add port
if (self.port != 0)
{
builder.append_char(':');
builder.appendf("%d", self.port);
}
// Add fragment if it exists
if (self.fragment != "")
{
builder.append_char('#');
// Add path
String path = temp_encode(self.path, PATH);
builder.append_chars(path);
String fragment = temp_encode(self.fragment, FRAGMENT);
builder.append_chars(fragment);
}
// Add query if it exists (note that `query` is expected to
// be already properly encoded).
if (self.query != "")
{
builder.append_char('?');
builder.append_chars(self.query);
}
return builder.copy_str(allocator);
};
// Add fragment if it exists
if (self.fragment != "")
{
builder.append_char('#');
String fragment = temp_encode(self.fragment, FRAGMENT);
builder.append_chars(fragment);
}
return builder.copy_str(allocator);
}
def UrlQueryValueList = List<[String]>;
@@ -327,35 +324,32 @@ fn UrlQueryValues* UrlQueryValues.add(&self, String key, String value)
@param [inout] allocator
@return "a percent-encoded query string"
*>
fn String UrlQueryValues.to_string(&self, Allocator allocator = allocator::heap()) @dynamic
fn String UrlQueryValues.to_string(&self, Allocator allocator = allocator::heap()) @dynamic => @pool(allocator)
{
@pool(allocator)
DString builder = dstring::temp_new();
usz i;
foreach (key: self.key_order)
{
DString builder = dstring::temp_new();
String encoded_key = temp_encode(key, QUERY);
usz i;
foreach (key: self.key_order)
UrlQueryValueList! values = self.map.get(key);
if (catch values) continue;
foreach (value: values)
{
String encoded_key = temp_encode(key, QUERY);
if (i > 0) builder.append_char('&');
UrlQueryValueList! values = self.map.get(key);
if (catch values) continue;
builder.append_chars(encoded_key);
builder.append_char('=');
foreach (value: values)
{
if (i > 0) builder.append_char('&');
builder.append_chars(encoded_key);
builder.append_char('=');
String encoded_value = temp_encode(value, QUERY);
builder.append_chars(encoded_value);
i++;
}
};
return builder.copy_str(allocator);
String encoded_value = temp_encode(value, QUERY);
builder.append_chars(encoded_value);
i++;
}
};
return builder.copy_str(allocator);
}
fn void UrlQueryValues.free(&self)

View File

@@ -67,35 +67,32 @@ fn usz encode_len(String s, UrlEncodingMode mode) @inline
@param [inout] allocator
@return "Percent-encoded String"
*>
fn String encode(String s, UrlEncodingMode mode, Allocator allocator)
fn String encode(String s, UrlEncodingMode mode, Allocator allocator) => @pool(allocator)
{
usz n = encode_len(s, mode);
@pool(allocator)
DString builder = dstring::temp_with_capacity(n);
foreach(i, c: s)
{
DString builder = dstring::temp_with_capacity(n);
foreach(i, c: s)
switch
{
switch
{
// encode spaces in queries
case c == ' ' && mode == QUERY:
builder.append_char('+');
// encode spaces in queries
case c == ' ' && mode == QUERY:
builder.append_char('+');
// add encoded char
case should_encode(c, mode):
builder.append_char('%');
String hex = hex::encode_temp(s[i:1]);
builder.append(hex.temp_ascii_to_upper());
// add encoded char
case should_encode(c, mode):
builder.append_char('%');
String hex = hex::encode_temp(s[i:1]);
builder.append(hex.temp_ascii_to_upper());
// use char, no encoding needed
default:
builder.append_char(c);
}
// use char, no encoding needed
default:
builder.append_char(c);
}
}
return builder.copy_str(allocator);
};
return builder.copy_str(allocator);
}
<*
@@ -146,35 +143,32 @@ fn usz! decode_len(String s, UrlEncodingMode mode) @inline
@param [inout] allocator
@return "Percent-decoded String"
*>
fn String! decode(String s, UrlEncodingMode mode, Allocator allocator)
fn String! decode(String s, UrlEncodingMode mode, Allocator allocator) => @pool(allocator)
{
usz n = decode_len(s, mode)!;
@pool(allocator)
DString builder = dstring::temp_with_capacity(n);
for (usz i = 0; i < s.len; i++)
{
DString builder = dstring::temp_with_capacity(n);
for (usz i = 0; i < s.len; i++)
switch (s[i])
{
switch (s[i])
{
// decode encoded char
case '%':
char[] hex = hex::decode_temp(s[i+1:2])!;
builder.append(hex);
i += 2;
// decode encoded char
case '%':
char[] hex = hex::decode_temp(s[i+1:2])!;
builder.append(hex);
i += 2;
// decode space when in queries
case '+':
builder.append_char((mode == QUERY) ? ' ' : '+');
// decode space when in queries
case '+':
builder.append_char((mode == QUERY) ? ' ' : '+');
// use char, no decoding needed
default:
builder.append_char(s[i]);
}
// use char, no decoding needed
default:
builder.append_char(s[i]);
}
}
return builder.copy_str(allocator);
};
return builder.copy_str(allocator);
}
<*

View File

@@ -9,10 +9,9 @@ import std::io::path, libc, std::os;
@require name.len > 0
@return! SearchResult.MISSING
*>
fn String! get_var(String name, Allocator allocator = allocator::heap())
fn String! get_var(String name, Allocator allocator = allocator::heap()) => @pool(allocator)
{
@pool(allocator)
{
$switch
$case env::LIBC && !env::WIN32:
ZString val = libc::getenv(name.zstr_tcopy());
@@ -33,7 +32,6 @@ fn String! get_var(String name, Allocator allocator = allocator::heap())
$default:
return "";
$endswitch
};
}
fn String! get_var_temp(String name)
@@ -46,10 +44,8 @@ fn String! get_var_temp(String name)
@param [in] value
@require name.len > 0
*>
fn bool set_var(String name, String value, bool overwrite = true)
fn bool set_var(String name, String value, bool overwrite = true) => @pool()
{
@pool()
{
$switch
$case env::WIN32:
WString wname = name.to_temp_wstring()!!;
@@ -65,8 +61,6 @@ fn bool set_var(String name, String value, bool overwrite = true)
$default:
return false;
$endswitch
};
}
<*
@@ -91,10 +85,8 @@ fn Path! get_config_dir(Allocator allocator = allocator::heap()) @deprecated("us
<*
Returns the current user's config directory.
*>
fn Path! new_get_config_dir(Allocator allocator = allocator::heap())
fn Path! new_get_config_dir(Allocator allocator = allocator::heap()) => @pool(allocator)
{
@pool(allocator)
{
$if env::WIN32:
return path::new(get_var_temp("AppData"), allocator);
$else
@@ -107,7 +99,6 @@ fn Path! new_get_config_dir(Allocator allocator = allocator::heap())
$endif
return path::temp_new(s).new_append(DIR, allocator: allocator);
$endif
};
}
@@ -115,10 +106,8 @@ fn Path! new_get_config_dir(Allocator allocator = allocator::heap())
@param [in] name
@require name.len > 0
*>
fn bool clear_var(String name)
fn bool clear_var(String name) => @pool()
{
@pool()
{
$switch
$case env::WIN32:
WString wname = name.to_temp_wstring()!!;
@@ -128,7 +117,6 @@ fn bool clear_var(String name)
$default:
return false;
$endswitch
};
}
fn String! executable_path(Allocator allocator = allocator::heap()) @deprecated("use new_executable_path()")

View File

@@ -204,7 +204,8 @@ fn void! backtrace_add_element(BacktraceList *list, void* addr, Allocator alloca
return;
}
@pool(allocator) {
@pool(allocator)
{
Linux_Dl_info info;
if (dladdr(addr, &info) == 0)
{