mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Fix to simple a += b overload fallback. Renaming and reordering in the stdlib.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2023 Eduardo José Gómez Hernández. All rights reserved.
|
||||
// Copyright (c) 2023-2025 Eduardo José Gómez Hernández. All rights reserved.
|
||||
// Use of this source code is governed by the MIT license
|
||||
// a copy of which can be found in the LICENSE_STDLIB file.
|
||||
module std::atomic::types{Type};
|
||||
|
||||
@@ -32,9 +32,11 @@ const Complex IDENTITY = { 1, 0 };
|
||||
const Complex IMAGINARY = { 0, 1 };
|
||||
|
||||
macro Complex Complex.add(self, Complex b) @operator(+) => { .v = self.v + b.v };
|
||||
macro Complex Complex.add_this(&self, Complex b) @operator(+=) => { .v = self.v += b.v };
|
||||
macro Complex Complex.add_real(self, Real r) @operator_s(+) => { .v = self.v + (Real[<2>]) { r, 0 } };
|
||||
macro Complex Complex.add_each(self, Real b) => { .v = self.v + b };
|
||||
macro Complex Complex.sub(self, Complex b) @operator(-) => { .v = self.v - b.v };
|
||||
macro Complex Complex.sub_this(&self, Complex b) @operator(-=) => { .v = self.v -= b.v };
|
||||
macro Complex Complex.sub_real(self, Real r) @operator(-) => { .v = self.v - (Real[<2>]) { r, 0 } };
|
||||
macro Complex Complex.sub_real_inverse(self, Real r) @operator_r(-) => { .v = (Real[<2>]) { r, 0 } - self.v };
|
||||
macro Complex Complex.sub_each(self, Real b) => { .v = self.v - b };
|
||||
@@ -1,4 +1,4 @@
|
||||
module std::math;
|
||||
module std::math::math_rt;
|
||||
|
||||
fn int128 __divti3(int128 a, int128 b) @extern("__divti3") @weak @nostrip
|
||||
{
|
||||
@@ -312,21 +312,21 @@ macro float_from_i128($Type, a) @private
|
||||
$switch $Type:
|
||||
$case double:
|
||||
$Rep = ulong;
|
||||
const MANT_DIG = DOUBLE_MANT_DIG;
|
||||
const MANT_DIG = math::DOUBLE_MANT_DIG;
|
||||
const SIGNIFICANT_BITS = 52;
|
||||
const EXP_BIAS = 1023;
|
||||
const MANTISSA_MASK = 0xFFFFF_FFFF_FFFFu64;
|
||||
const SIGN_BIT = 1u64 << 63;
|
||||
$case float:
|
||||
$Rep = uint;
|
||||
const MANT_DIG = FLOAT_MANT_DIG;
|
||||
const MANT_DIG = math::FLOAT_MANT_DIG;
|
||||
const EXP_BIAS = 127;
|
||||
const SIGNIFICANT_BITS = 23;
|
||||
const MANTISSA_MASK = 0x7F_FFFFu32;
|
||||
const SIGN_BIT = 1u32 << 31;
|
||||
$case float16:
|
||||
$Rep = ushort;
|
||||
const MANT_DIG = HALF_MANT_DIG;
|
||||
const MANT_DIG = math::HALF_MANT_DIG;
|
||||
$case float128:
|
||||
$Rep = uint128;
|
||||
const MANT_DIG = QUAD_MANT_DIG;
|
||||
@@ -371,22 +371,22 @@ macro float_from_u128($Type, a) @private
|
||||
$switch $Type:
|
||||
$case double:
|
||||
$Rep = ulong;
|
||||
const MANT_DIG = DOUBLE_MANT_DIG;
|
||||
const MANT_DIG = math::DOUBLE_MANT_DIG;
|
||||
const SIGNIFICANT_BITS = 52;
|
||||
const EXP_BIAS = 1023;
|
||||
const MANTISSA_MASK = 0xFFFFF_FFFF_FFFFu64;
|
||||
$case float:
|
||||
$Rep = uint;
|
||||
const MANT_DIG = FLOAT_MANT_DIG;
|
||||
const MANT_DIG = math::FLOAT_MANT_DIG;
|
||||
const EXP_BIAS = 127;
|
||||
const SIGNIFICANT_BITS = 23;
|
||||
const MANTISSA_MASK = 0x7F_FFFFu32;
|
||||
$case float16:
|
||||
$Rep = ushort;
|
||||
const MANT_DIG = HALF_MANT_DIG;
|
||||
const MANT_DIG = math::HALF_MANT_DIG;
|
||||
$case float128:
|
||||
$Rep = uint128;
|
||||
const MANT_DIG = QUAD_MANT_DIG;
|
||||
const MANT_DIG = math::QUAD_MANT_DIG;
|
||||
$endswitch
|
||||
if (a == 0) return ($Type)0;
|
||||
int sd = 128 - (int)$$clz(a); // digits
|
||||
@@ -1,15 +1,15 @@
|
||||
module std::math;
|
||||
module std::math::math_rt;
|
||||
|
||||
fn float __roundevenf(float f) @extern("roundevenf") @weak @nostrip
|
||||
{
|
||||
// Slow implementation
|
||||
return round(f / 2) * 2;
|
||||
return math::round(f / 2) * 2;
|
||||
}
|
||||
|
||||
fn double __roundeven(double d) @extern("roundeven") @weak @nostrip
|
||||
{
|
||||
// Slow implementation
|
||||
return round(d / 2) * 2;
|
||||
return math::round(d / 2) * 2;
|
||||
}
|
||||
|
||||
fn double __powidf2(double a, int b) @extern("__powidf2") @weak @nostrip
|
||||
|
||||
@@ -1,406 +0,0 @@
|
||||
module std::net::http;
|
||||
/*
|
||||
enum HttpStatus
|
||||
{
|
||||
PENDING,
|
||||
COMPLETED,
|
||||
FAILED
|
||||
}
|
||||
|
||||
struct Http
|
||||
{
|
||||
HttpStatus status;
|
||||
int status_code;
|
||||
String reason;
|
||||
String content_type;
|
||||
String response_data;
|
||||
}
|
||||
|
||||
fn Http* http_get(String url, Allocator using = allocator::temp())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
fn Http* http_post(String url, Allocator using = allocator::temp())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
fn void Http.destroy(Http* this)
|
||||
{
|
||||
}
|
||||
|
||||
fn HttpStatus Http.process(Http* this)
|
||||
{
|
||||
unreachable();
|
||||
}
|
||||
|
||||
// Common across implementations
|
||||
|
||||
struct HttpInternal @private
|
||||
{
|
||||
inline Http http;
|
||||
Allocator allocator;
|
||||
int connect_pending;
|
||||
int request_sent;
|
||||
char[256] address;
|
||||
char[256] request_header;
|
||||
char* request_header_large;
|
||||
String request_data;
|
||||
char[1024] reason_phrase;
|
||||
char[256] content_type;
|
||||
|
||||
usz data_size;
|
||||
usz data_capacity;
|
||||
void* data;
|
||||
}
|
||||
|
||||
fn String? parse_url(String url, String* port, String* resource) @private
|
||||
{
|
||||
if (url[:7] != "http://") return NetError.INVALID_URL?;
|
||||
url = url[7..];
|
||||
|
||||
usz end_index = url.index_of(":") ?? url.index_of("/") ?? url.len;
|
||||
String address = url[:end_index];
|
||||
String end_part = url[end_index..];
|
||||
if (!end_part.len)
|
||||
{
|
||||
*port = "80";
|
||||
*resource = {};
|
||||
return address;
|
||||
}
|
||||
switch (end_part[0])
|
||||
{
|
||||
case ':':
|
||||
end_index = end_part.index_of("/") ?? end_part.len;
|
||||
end_part[:end_index].to_uint() ?? NetError.INVALID_URL?!;
|
||||
*port = end_part[:end_index];
|
||||
*resource = url[end_index..];
|
||||
case '/':
|
||||
*port = "80";
|
||||
*resource = end_part;
|
||||
default:
|
||||
unreachable();
|
||||
}
|
||||
return address;
|
||||
}
|
||||
|
||||
fn Socket? http_internal_connect(String address, uint port) @private
|
||||
{
|
||||
return tcp::connect_async(address, port)!;
|
||||
}
|
||||
|
||||
fn HttpInternal* http_internal_create(usz request_data_size, Allocator allocator) @private
|
||||
{
|
||||
HttpInternal* internal = allocator.alloc(HttpInternal.sizeof + request_data_size)!!;
|
||||
internal.status = PENDING;
|
||||
internal.status_code = 0;
|
||||
internal.response_data = {};
|
||||
internal.allocator = allocator;
|
||||
internal.connect_pending = 1;
|
||||
internal.request_sent = 0;
|
||||
// internal.reason = "";
|
||||
// internal.content_type = "";
|
||||
internal.data_size = 0;
|
||||
internal.data_capacity = 64 * 1024;
|
||||
internal.data = allocator.alloc(internal.data_capacity)!!;
|
||||
internal.request_data = {};
|
||||
return internal;
|
||||
}
|
||||
|
||||
fn Http*? http_get(String url, Allocator allocator = allocator::temp())
|
||||
{
|
||||
$if env::WIN32:
|
||||
int[1024] wsa_data;
|
||||
if (_wsa_startup(1, &wsa_data) != 0) return NetError.GENERAL_ERROR?;
|
||||
$endif
|
||||
uint port;
|
||||
String resource;
|
||||
String address = parse_url(url, &port, &resource)?;
|
||||
Socket socket = tcp::connect(address, port)?;
|
||||
HttpInternal* internal = http_internal_create(0, allocator);
|
||||
internal.socket = socket;
|
||||
|
||||
char* request_header;
|
||||
usz request_header_len = 64 + resource.len + address.len + port.len;
|
||||
if (request_header_len < sizeof(internal.request_header))
|
||||
{
|
||||
internal.request_header_large = null;
|
||||
request_header = internal.request_header;
|
||||
}
|
||||
else
|
||||
{
|
||||
internal.request_header_large = (char*)allocator.malloc(request_header_len + 1);
|
||||
request_header = internal.request_header_large;
|
||||
}
|
||||
int default_http_port = port == "80";
|
||||
sprintf( request_header, "GET %s HTTP/1.0\r\nHost: %s%s%s\r\n\r\n", resource, address, default_http_port ? "" : ":", default_http_port ? "" : port );
|
||||
|
||||
return internal;
|
||||
}
|
||||
|
||||
fn Http*? http_post(String url, Allocator allocator = allocator::temp())
|
||||
{
|
||||
$if env::OS_TYPE == OsType::WIN32:
|
||||
int[1024] wsa_data;
|
||||
if (_wsa_startup(1, &wsa_data) != 0) return NetError.GENERAL_ERROR?;
|
||||
$endif
|
||||
String port;
|
||||
String resource;
|
||||
String address = parse_url(url, &port, &resource)?;
|
||||
Socket socket = http_internal_connect(address, port)?;
|
||||
HttpInternal* internal = http_internal_create(0, allocator);
|
||||
internal.socket = socket;
|
||||
|
||||
char* request_header;
|
||||
uz request_header_len = 64 + resource.len + address.len + port.len;
|
||||
if (request_header_len < sizeof(internal.request_header))
|
||||
{
|
||||
internal.request_header_large = null;
|
||||
request_header = internal.request_header;
|
||||
}
|
||||
else
|
||||
{
|
||||
internal.request_header_large = (char*)allocator.malloc(request_header_len + 1);
|
||||
request_header = internal.request_header_large;
|
||||
}
|
||||
int default_http_port = port == "80";
|
||||
sprintf( request_header, "POST %s HTTP/1.0\r\nHost: %s%s%s\r\nContent-Length: %d\r\n\r\n", resource, address, default_http_port ? "" : ":", default_http_port ? "" : port,
|
||||
(int) size );
|
||||
|
||||
internal->request_data_size = size;
|
||||
internal->request_data = ( internal + 1 );
|
||||
memcpy( internal->request_data, data, size );
|
||||
|
||||
return internal;
|
||||
}
|
||||
|
||||
fn HttpStatus Http.process(Http* http)
|
||||
{
|
||||
HttpInternal* internal = (HttpInternal*)http;
|
||||
if (http.status == HttpStatus.FAILED) return http.status;
|
||||
if (internal.connect_pending)
|
||||
{
|
||||
fd_set sockets_to_check;
|
||||
FD_ZERO(&sockets_to_check);
|
||||
FD_SET( internal->socket, &sockets_to_check );
|
||||
struct timeval timeout; timeout.tv_sec = 0; timeout.tv_usec = 0;
|
||||
// check if socket is ready for send
|
||||
if( select( (int)( internal->socket + 1 ), NULL, &sockets_to_check, NULL, &timeout ) == 1 )
|
||||
{
|
||||
int opt = -1;
|
||||
socklen_t len = sizeof( opt );
|
||||
if( getsockopt( internal->socket, SOL_SOCKET, SO_ERROR, (char*)( &opt ), &len) >= 0 && opt == 0 )
|
||||
{
|
||||
internal->connect_pending = 0; // if it is, we're connected
|
||||
}
|
||||
}
|
||||
}
|
||||
if (internal.connect_pending) retur http.status;
|
||||
if (!internal.request_sent)
|
||||
{
|
||||
char* request_header = internal->request_header_large ?
|
||||
internal.request_header_large : internal.request_header;
|
||||
if (send(internal.socket, request_header, (int) strlen( request_header ), 0) == -1)
|
||||
{
|
||||
return http.status = FAILED;
|
||||
}
|
||||
if (internal.request_data_size)
|
||||
{
|
||||
int res = send(internal.socket, (char const*)internal->request_data, (int) internal->request_data_size, 0 );
|
||||
if (res == -1)
|
||||
{
|
||||
http.status = HTTP_STATUS_FAILED;
|
||||
return http.status;
|
||||
}
|
||||
}
|
||||
internal.request_sent = 1;
|
||||
return http.status;
|
||||
}
|
||||
// check if socket is ready for recv
|
||||
fd_set sockets_to_check;
|
||||
FD_ZERO( &sockets_to_check );
|
||||
#pragma warning( push )
|
||||
#pragma warning( disable: 4548 ) // expression before comma has no effect; expected expression with side-effect
|
||||
FD_SET( internal->socket, &sockets_to_check );
|
||||
#pragma warning( pop )
|
||||
struct timeval timeout; timeout.tv_sec = 0; timeout.tv_usec = 0;
|
||||
}
|
||||
http_status_t http_process( http_t* http )
|
||||
{
|
||||
|
||||
|
||||
while( select( (int)( internal->socket + 1 ), &sockets_to_check, NULL, NULL, &timeout ) == 1 )
|
||||
{
|
||||
char buffer[ 4096 ];
|
||||
int size = recv( internal->socket, buffer, sizeof( buffer ), 0 );
|
||||
if( size == -1 )
|
||||
{
|
||||
http->status = HTTP_STATUS_FAILED;
|
||||
return http->status;
|
||||
}
|
||||
else if( size > 0 )
|
||||
{
|
||||
size_t min_size = internal->data_size + size + 1;
|
||||
if( internal->data_capacity < min_size )
|
||||
{
|
||||
internal->data_capacity *= 2;
|
||||
if( internal->data_capacity < min_size ) internal->data_capacity = min_size;
|
||||
void* new_data = HTTP_MALLOC( memctx, internal->data_capacity );
|
||||
memcpy( new_data, internal->data, internal->data_size );
|
||||
HTTP_FREE( memctx, internal->data );
|
||||
internal->data = new_data;
|
||||
}
|
||||
memcpy( (void*)( ( (uintptr_t) internal->data ) + internal->data_size ), buffer, (size_t) size );
|
||||
internal->data_size += size;
|
||||
}
|
||||
else if( size == 0 )
|
||||
{
|
||||
char const* status_line = (char const*) internal->data;
|
||||
|
||||
int header_size = 0;
|
||||
char const* header_end = strstr( status_line, "\r\n\r\n" );
|
||||
if( header_end )
|
||||
{
|
||||
header_end += 4;
|
||||
header_size = (int)( header_end - status_line );
|
||||
}
|
||||
else
|
||||
{
|
||||
http->status = HTTP_STATUS_FAILED;
|
||||
return http->status;
|
||||
}
|
||||
|
||||
// skip http version
|
||||
status_line = strchr( status_line, ' ' );
|
||||
if( !status_line )
|
||||
{
|
||||
http->status = HTTP_STATUS_FAILED;
|
||||
return http->status;
|
||||
}
|
||||
++status_line;
|
||||
|
||||
// extract status code
|
||||
char status_code[ 16 ];
|
||||
char const* status_code_end = strchr( status_line, ' ' );
|
||||
if( !status_code_end )
|
||||
{
|
||||
http->status = HTTP_STATUS_FAILED;
|
||||
return http->status;
|
||||
}
|
||||
memcpy( status_code, status_line, (size_t)( status_code_end - status_line ) );
|
||||
status_code[ status_code_end - status_line ] = 0;
|
||||
status_line = status_code_end + 1;
|
||||
http->status_code = atoi( status_code );
|
||||
|
||||
// extract reason phrase
|
||||
char const* reason_phrase_end = strstr( status_line, "\r\n" );
|
||||
if( !reason_phrase_end )
|
||||
{
|
||||
http->status = HTTP_STATUS_FAILED;
|
||||
return http->status;
|
||||
}
|
||||
size_t reason_phrase_len = (size_t)( reason_phrase_end - status_line );
|
||||
if( reason_phrase_len >= sizeof( internal->reason_phrase ) )
|
||||
reason_phrase_len = sizeof( internal->reason_phrase ) - 1;
|
||||
memcpy( internal->reason_phrase, status_line, reason_phrase_len );
|
||||
internal->reason_phrase[ reason_phrase_len ] = 0;
|
||||
status_line = reason_phrase_end + 1;
|
||||
|
||||
// extract content type
|
||||
char const* content_type_start = strstr( status_line, "Content-Type: " );
|
||||
if( content_type_start )
|
||||
{
|
||||
content_type_start += strlen( "Content-Type: " );
|
||||
char const* content_type_end = strstr( content_type_start, "\r\n" );
|
||||
if( content_type_end )
|
||||
{
|
||||
size_t content_type_len = (size_t)( content_type_end - content_type_start );
|
||||
if( content_type_len >= sizeof( internal->content_type ) )
|
||||
content_type_len = sizeof( internal->content_type ) - 1;
|
||||
memcpy( internal->content_type, content_type_start, content_type_len );
|
||||
internal->content_type[ content_type_len ] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
http->status = http->status_code < 300 ? HTTP_STATUS_COMPLETED : HTTP_STATUS_FAILED;
|
||||
http->response_data = (void*)( ( (uintptr_t) internal->data ) + header_size );
|
||||
http->response_size = internal->data_size - header_size;
|
||||
|
||||
// add an extra zero after the received data, but don't modify the size, so ascii results can be used as
|
||||
// a zero terminated string. the size returned will be the string without this extra zero terminator.
|
||||
( (char*)http->response_data )[ http->response_size ] = 0;
|
||||
return http->status;
|
||||
}
|
||||
}
|
||||
|
||||
return http->status;
|
||||
}
|
||||
|
||||
|
||||
void http_release( http_t* http )
|
||||
{
|
||||
http_internal_t* internal = (http_internal_t*) http;
|
||||
#ifdef _WIN32
|
||||
closesocket( internal->socket );
|
||||
#else
|
||||
close( internal->socket );
|
||||
#endif
|
||||
|
||||
if( internal->request_header_large) HTTP_FREE( memctx, internal->request_header_large );
|
||||
HTTP_FREE( memctx, internal->data );
|
||||
HTTP_FREE( memctx, internal );
|
||||
#ifdef _WIN32
|
||||
WSACleanup();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#endif /* HTTP_IMPLEMENTATION */
|
||||
|
||||
/*
|
||||
revision history:
|
||||
1.0 first released version
|
||||
*/
|
||||
|
||||
/*
|
||||
------------------------------------------------------------------------------
|
||||
This software is available under 2 licenses - you may choose the one you like.
|
||||
------------------------------------------------------------------------------
|
||||
ALTERNATIVE A - MIT License
|
||||
Copyright (c) 2016 Mattias Gustavsson
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
------------------------------------------------------------------------------
|
||||
ALTERNATIVE B - Public Domain (www.unlicense.org)
|
||||
This is free and unencumbered software released into the public domain.
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
|
||||
software, either in source code form or as a compiled binary, for any purpose,
|
||||
commercial or non-commercial, and by any means.
|
||||
In jurisdictions that recognize copyright laws, the author or authors of this
|
||||
software dedicate any and all copyright interest in the software to the public
|
||||
domain. We make this dedication for the benefit of the public at large and to
|
||||
the detriment of our heirs and successors. We intend this dedication to be an
|
||||
overt act of relinquishment in perpetuity of all present and future rights to
|
||||
this software under copyright law.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
------------------------------------------------------------------------------
|
||||
*/*/
|
||||
@@ -88,7 +88,7 @@ fn fault convert_error(WSAError error)
|
||||
|
||||
fn fault socket_error()
|
||||
{
|
||||
return convert_error(win32_WSAGetLastError());
|
||||
return convert_error(win32::wsaGetLastError());
|
||||
}
|
||||
|
||||
const CUShort POLLIN = win32::POLLIN;
|
||||
|
||||
@@ -69,7 +69,7 @@ fn ulong? poll_ms(Poll[] polls, long timeout_ms)
|
||||
{
|
||||
if (timeout_ms > CInt.max) timeout_ms = CInt.max;
|
||||
$if env::WIN32:
|
||||
CInt result = win32_WSAPoll((Win32_LPWSAPOLLFD)polls.ptr, (Win32_ULONG)polls.len, (CInt)timeout_ms);
|
||||
CInt result = win32::wsaPoll((Win32_LPWSAPOLLFD)polls.ptr, (Win32_ULONG)polls.len, (CInt)timeout_ms);
|
||||
$else
|
||||
CInt result = os::poll((Posix_pollfd*)polls.ptr, (Posix_nfds_t)polls.len, (CInt)timeout_ms);
|
||||
$endif
|
||||
|
||||
@@ -23,7 +23,7 @@ fn bool last_error_is_delayed_connect()
|
||||
{
|
||||
$switch:
|
||||
$case env::WIN32:
|
||||
switch (win32_WSAGetLastError())
|
||||
switch (win32::wsaGetLastError())
|
||||
{
|
||||
case wsa::EWOULDBLOCK:
|
||||
case wsa::EINPROGRESS: return true;
|
||||
|
||||
2
lib/std/os/freebsd/general.c3
Normal file
2
lib/std/os/freebsd/general.c3
Normal file
@@ -0,0 +1,2 @@
|
||||
module std::os::freebsd @if(env::FREEBSD);
|
||||
|
||||
@@ -67,6 +67,17 @@ struct Darwin_segment_command_64
|
||||
uint flags; /* flags */
|
||||
}
|
||||
|
||||
struct Darwin_mach_timebase_info
|
||||
{
|
||||
uint numer;
|
||||
uint denom;
|
||||
}
|
||||
|
||||
alias Darwin_mach_timebase_info_t = Darwin_mach_timebase_info;
|
||||
alias Darwin_mach_timebase_info_data_t = Darwin_mach_timebase_info;
|
||||
|
||||
extern fn void mach_timebase_info(Darwin_mach_timebase_info_data_t* timebase);
|
||||
extern fn ulong mach_absolute_time();
|
||||
|
||||
fn String? executable_path(Allocator allocator)
|
||||
{
|
||||
@@ -155,3 +166,4 @@ fn BacktraceList? symbolize_backtrace(Allocator allocator, void*[] backtrace)
|
||||
};
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
2
lib/std/os/macos/general.c3
Normal file
2
lib/std/os/macos/general.c3
Normal file
@@ -0,0 +1,2 @@
|
||||
module std::os::darwin @if(env::DARWIN);
|
||||
|
||||
1
lib/std/os/netbsd/general.c3
Normal file
1
lib/std/os/netbsd/general.c3
Normal file
@@ -0,0 +1 @@
|
||||
module std::os::netbsd @if(env::NETBSD);
|
||||
2
lib/std/os/openbsd/general.c3
Normal file
2
lib/std/os/openbsd/general.c3
Normal file
@@ -0,0 +1,2 @@
|
||||
module std::os::openbsd @if(env::OPENBSD);
|
||||
|
||||
68
lib/std/os/posix/clock.c3
Normal file
68
lib/std/os/posix/clock.c3
Normal file
@@ -0,0 +1,68 @@
|
||||
module std::os::posix @if(env::POSIX);
|
||||
import libc;
|
||||
|
||||
extern fn CInt clock_gettime(int type, TimeSpec *time);
|
||||
|
||||
module std::os::posix @if(env::OPENBSD);
|
||||
const CLOCK_REALTIME = 0;
|
||||
const CLOCK_PROCESS_CPUTIME_ID = 2;
|
||||
const CLOCK_MONOTONIC = 3;
|
||||
const CLOCK_THREAD_CPUTIME_ID = 4;
|
||||
const CLOCK_UPTIME = 5;
|
||||
const CLOCK_BOOTTIME = 6;
|
||||
|
||||
module std::os::posix @if(env::FREEBSD);
|
||||
const CLOCK_REALTIME = 0;
|
||||
const CLOCK_VIRTUAL = 1;
|
||||
const CLOCK_PROF = 2;
|
||||
const CLOCK_MONOTONIC = 4;
|
||||
const CLOCK_UPTIME = 5;
|
||||
const CLOCK_UPTIME_PRECISE = 7;
|
||||
const CLOCK_UPTIME_FAST = 8;
|
||||
const CLOCK_REALTIME_PRECISE = 9;
|
||||
const CLOCK_REALTIME_FAST = 10;
|
||||
const CLOCK_MONOTONIC_PRECISE = 11;
|
||||
const CLOCK_MONOTONIC_FAST = 12;
|
||||
const CLOCK_SECOND = 13;
|
||||
const CLOCK_THREAD_CPUTIME_ID = 14;
|
||||
const CLOCK_PROCESS_CPUTIME_ID = 15;
|
||||
const CLOCK_BOOTTIME = CLOCK_UPTIME;
|
||||
const CLOCK_REALTIME_COARSE = CLOCK_REALTIME_FAST;
|
||||
const CLOCK_MONOTONIC_COARSE = CLOCK_MONOTONIC_FAST;
|
||||
|
||||
module std::os::posix @if(env::NETBSD);
|
||||
const CLOCK_REALTIME = 0;
|
||||
const CLOCK_VIRTUAL = 1;
|
||||
const CLOCK_PROF = 2;
|
||||
const CLOCK_MONOTONIC = 3;
|
||||
const CLOCK_THREAD_CPUTIME_ID = 0x20000000;
|
||||
const CLOCK_PROCESS_CPUTIME_ID = 0x40000000;
|
||||
|
||||
module std::os::posix @if(env::WASI);
|
||||
// Not implemented
|
||||
const CLOCK_REALTIME = 0;
|
||||
const CLOCK_MONOTONIC = 0;
|
||||
|
||||
module std::os::posix @if(env::DARWIN);
|
||||
const CLOCK_REALTIME = 0;
|
||||
const CLOCK_MONOTONIC = 6;
|
||||
const CLOCK_MONOTONIC_RAW = 4;
|
||||
const CLOCK_MONOTONIC_RAW_APPROX = 5;
|
||||
const CLOCK_UPTIME_RAW = 8;
|
||||
const CLOCK_UPTIME_RAW_APPROX = 9;
|
||||
const CLOCK_PROCESS_CPUTIME_ID = 12;
|
||||
const CLOCK_THREAD_CPUTIME_ID = 16;
|
||||
|
||||
module std::os::posix @if(env::LINUX || env::ANDROID);
|
||||
const CLOCK_REALTIME = 0;
|
||||
const CLOCK_MONOTONIC = 1;
|
||||
const CLOCK_PROCESS_CPUTIME_ID = 2;
|
||||
const CLOCK_THREAD_CPUTIME_ID = 3;
|
||||
const CLOCK_MONOTONIC_RAW = 4;
|
||||
const CLOCK_REALTIME_COARSE = 5;
|
||||
const CLOCK_MONOTONIC_COARSE = 6;
|
||||
const CLOCK_BOOTTIME = 7;
|
||||
const CLOCK_REALTIME_ALARM = 8;
|
||||
const CLOCK_BOOTTIME_ALARM = 9;
|
||||
const CLOCK_TAI = 11;
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
module std::os::posix;
|
||||
module std::os::posix @if(env::POSIX);
|
||||
|
||||
extern ZString* environ;
|
||||
|
||||
|
||||
1
lib/std/os/posix/net.c3
Normal file
1
lib/std/os/posix/net.c3
Normal file
@@ -0,0 +1 @@
|
||||
module std::os::posix @if(env::POSIX);
|
||||
6
lib/std/os/win32/clock.c3
Normal file
6
lib/std/os/win32/clock.c3
Normal file
@@ -0,0 +1,6 @@
|
||||
module std::os::win32 @if(env::WIN32);
|
||||
import std::math;
|
||||
|
||||
extern fn void getSystemTimeAsFileTime(Win32_FILETIME* time) @extern("GetSystemTimeAsFileTime");
|
||||
extern fn Win32_BOOL queryPerformanceFrequency(Win32_LARGE_INTEGER* lpFrequency) @extern("QueryPerformanceFrequency");
|
||||
extern fn Win32_BOOL queryPerformanceCounter(Win32_LARGE_INTEGER* lpPerformanceCount) @extern("QueryPerformanceCounter");
|
||||
@@ -1,5 +1,6 @@
|
||||
module std::os::win32 @if(env::WIN32);
|
||||
import libc;
|
||||
|
||||
enum Win32_GET_FILEEX_INFO_LEVELS
|
||||
{
|
||||
STANDARD,
|
||||
|
||||
@@ -122,11 +122,11 @@ const SD_RECEIVE = 0x00;
|
||||
const SD_SEND = 0x01;
|
||||
const SD_BOTH = 0x02;
|
||||
|
||||
extern fn CInt win32_WSAPoll(Win32_LPWSAPOLLFD fdArray, Win32_ULONG fds, Win32_INT timeout) @extern("WSAPoll") @builtin;
|
||||
extern fn WSAError win32_WSAGetLastError() @extern("WSAGetLastError") @builtin;
|
||||
extern fn void win32_WSASetLastError(WSAError error) @extern("WSASetLastError") @builtin;
|
||||
extern fn CInt win32_WSAStartup(Win32_WORD, void*) @extern("WSAStartup") @builtin;
|
||||
extern fn CInt win32_WSACleanup() @extern("WSACleanup") @builtin;
|
||||
extern fn CInt wsaPoll(Win32_LPWSAPOLLFD fdArray, Win32_ULONG fds, Win32_INT timeout) @extern("WSAPoll");
|
||||
extern fn WSAError wsaGetLastError() @extern("WSAGetLastError");
|
||||
extern fn void wsaSetLastError(WSAError error) @extern("WSASetLastError");
|
||||
extern fn CInt wsaStartup(Win32_WORD, void*) @extern("WSAStartup");
|
||||
extern fn CInt wsaCleanup() @extern("WSACleanup");
|
||||
|
||||
const int FIONBIO = -2147195266;
|
||||
const int FIONREAD = 1074030207;
|
||||
@@ -230,3 +230,4 @@ const WSAError QOS_EPSFILTERSPEC = 11028;
|
||||
const WSAError QOS_ESDMODEOBJ = 11029;
|
||||
const WSAError QOS_ESHAPERATEOBJ = 11030;
|
||||
const WSAError QOS_RESERVED_PETYPE = 11031;
|
||||
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
/*module std::text::i18n;
|
||||
import std::collections::map;
|
||||
import std::hash::fnv32a;
|
||||
typedef Language = char[];
|
||||
|
||||
const Language EN = "en";
|
||||
|
||||
alias TranslationMap = HashMap{String, String};
|
||||
fn uint Language.hash(self) => fnv32a::encode((char[])self);
|
||||
HashMap{Language, TranslationMap*} language_map @private;
|
||||
TranslationMap? current_map;
|
||||
|
||||
macro String @localized(String string) @builtin
|
||||
{
|
||||
return current_map[string] ?? string;
|
||||
}
|
||||
|
||||
@@ -1,23 +1,12 @@
|
||||
module std::time::os @if(env::DARWIN);
|
||||
|
||||
struct Darwin_mach_timebase_info
|
||||
{
|
||||
uint numer;
|
||||
uint denom;
|
||||
}
|
||||
|
||||
alias Darwin_mach_timebase_info_t = Darwin_mach_timebase_info;
|
||||
alias Darwin_mach_timebase_info_data_t = Darwin_mach_timebase_info;
|
||||
|
||||
extern fn void mach_timebase_info(Darwin_mach_timebase_info_data_t* timebase);
|
||||
extern fn ulong mach_absolute_time();
|
||||
import std::os::darwin;
|
||||
|
||||
fn Clock native_clock()
|
||||
{
|
||||
static Darwin_mach_timebase_info_data_t timebase;
|
||||
if (!timebase.denom)
|
||||
{
|
||||
mach_timebase_info(&timebase);
|
||||
darwin::mach_timebase_info(&timebase);
|
||||
}
|
||||
return (Clock)(mach_absolute_time() * timebase.numer / timebase.denom);
|
||||
return (Clock)(darwin::mach_absolute_time() * timebase.numer / timebase.denom);
|
||||
}
|
||||
|
||||
@@ -1,82 +1,17 @@
|
||||
module std::time::os @if(env::POSIX);
|
||||
import libc;
|
||||
|
||||
extern fn CInt clock_gettime(int type, TimeSpec *time);
|
||||
import libc, std::os::posix;
|
||||
|
||||
fn Time native_timestamp()
|
||||
{
|
||||
TimeSpec ts;
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
posix::clock_gettime(posix::CLOCK_REALTIME, &ts);
|
||||
return (Time)(ts.s * 1_000_000i64 + ts.ns / 1_000i64);
|
||||
}
|
||||
|
||||
fn Clock native_clock() @if(!env::DARWIN)
|
||||
{
|
||||
TimeSpec ts;
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
posix::clock_gettime(posix::CLOCK_MONOTONIC, &ts);
|
||||
return (Clock)((ulong)ts.s * 1_000_000_000u64 + (ulong)ts.ns);
|
||||
}
|
||||
|
||||
module std::time::os @if(env::OPENBSD);
|
||||
const CLOCK_REALTIME = 0;
|
||||
const CLOCK_PROCESS_CPUTIME_ID = 2;
|
||||
const CLOCK_MONOTONIC = 3;
|
||||
const CLOCK_THREAD_CPUTIME_ID = 4;
|
||||
const CLOCK_UPTIME = 5;
|
||||
const CLOCK_BOOTTIME = 6;
|
||||
|
||||
module std::time::os @if(env::FREEBSD);
|
||||
const CLOCK_REALTIME = 0;
|
||||
const CLOCK_VIRTUAL = 1;
|
||||
const CLOCK_PROF = 2;
|
||||
const CLOCK_MONOTONIC = 4;
|
||||
const CLOCK_UPTIME = 5;
|
||||
const CLOCK_UPTIME_PRECISE = 7;
|
||||
const CLOCK_UPTIME_FAST = 8;
|
||||
const CLOCK_REALTIME_PRECISE = 9;
|
||||
const CLOCK_REALTIME_FAST = 10;
|
||||
const CLOCK_MONOTONIC_PRECISE = 11;
|
||||
const CLOCK_MONOTONIC_FAST = 12;
|
||||
const CLOCK_SECOND = 13;
|
||||
const CLOCK_THREAD_CPUTIME_ID = 14;
|
||||
const CLOCK_PROCESS_CPUTIME_ID = 15;
|
||||
const CLOCK_BOOTTIME = CLOCK_UPTIME;
|
||||
const CLOCK_REALTIME_COARSE = CLOCK_REALTIME_FAST;
|
||||
const CLOCK_MONOTONIC_COARSE = CLOCK_MONOTONIC_FAST;
|
||||
|
||||
module std::time::os @if(env::NETBSD);
|
||||
const CLOCK_REALTIME = 0;
|
||||
const CLOCK_VIRTUAL = 1;
|
||||
const CLOCK_PROF = 2;
|
||||
const CLOCK_MONOTONIC = 3;
|
||||
const CLOCK_THREAD_CPUTIME_ID = 0x20000000;
|
||||
const CLOCK_PROCESS_CPUTIME_ID = 0x40000000;
|
||||
|
||||
module std::time::os @if(env::WASI);
|
||||
// Not implemented
|
||||
const CLOCK_REALTIME = 0;
|
||||
const CLOCK_MONOTONIC = 0;
|
||||
|
||||
module std::time::os @if(env::DARWIN);
|
||||
const CLOCK_REALTIME = 0;
|
||||
const CLOCK_MONOTONIC = 6;
|
||||
const CLOCK_MONOTONIC_RAW = 4;
|
||||
const CLOCK_MONOTONIC_RAW_APPROX = 5;
|
||||
const CLOCK_UPTIME_RAW = 8;
|
||||
const CLOCK_UPTIME_RAW_APPROX = 9;
|
||||
const CLOCK_PROCESS_CPUTIME_ID = 12;
|
||||
const CLOCK_THREAD_CPUTIME_ID = 16;
|
||||
|
||||
module std::time::os @if(env::LINUX || env::ANDROID);
|
||||
const CLOCK_REALTIME = 0;
|
||||
const CLOCK_MONOTONIC = 1;
|
||||
const CLOCK_PROCESS_CPUTIME_ID = 2;
|
||||
const CLOCK_THREAD_CPUTIME_ID = 3;
|
||||
const CLOCK_MONOTONIC_RAW = 4;
|
||||
const CLOCK_REALTIME_COARSE = 5;
|
||||
const CLOCK_MONOTONIC_COARSE = 6;
|
||||
const CLOCK_BOOTTIME = 7;
|
||||
const CLOCK_REALTIME_ALARM = 8;
|
||||
const CLOCK_BOOTTIME_ALARM = 9;
|
||||
const CLOCK_TAI = 11;
|
||||
|
||||
|
||||
@@ -2,14 +2,9 @@ module std::time::os @if(env::WIN32);
|
||||
import std::os::win32;
|
||||
import std::math;
|
||||
|
||||
extern fn void win32_GetSystemTimeAsFileTime(Win32_FILETIME* time) @extern("GetSystemTimeAsFileTime");
|
||||
extern fn Win32_BOOL win32_QueryPerformanceFrequency(Win32_LARGE_INTEGER* lpFrequency) @extern("QueryPerformanceFrequency");
|
||||
extern fn Win32_BOOL win32_QueryPerformanceCounter(Win32_LARGE_INTEGER* lpPerformanceCount) @extern("QueryPerformanceCounter");
|
||||
|
||||
const ulong WINDOWS_TICK_US @local = 10;
|
||||
const ulong WIN_TO_UNIX_EPOCH_US @local = 116444736000000000u64 / WINDOWS_TICK_US;
|
||||
|
||||
|
||||
fn Clock native_clock()
|
||||
{
|
||||
static Win32_LARGE_INTEGER freq;
|
||||
@@ -17,17 +12,17 @@ fn Clock native_clock()
|
||||
ulong mult = 0;
|
||||
if (!freq.quadPart)
|
||||
{
|
||||
if (!win32_QueryPerformanceFrequency(&freq)) return 0;
|
||||
if (!win32::queryPerformanceFrequency(&freq)) return 0;
|
||||
}
|
||||
Win32_LARGE_INTEGER counter @noinit;
|
||||
if (!win32_QueryPerformanceCounter(&counter)) return 0;
|
||||
if (!win32::queryPerformanceCounter(&counter)) return 0;
|
||||
return (Clock)counter.quadPart.muldiv(1_000_000_000, freq.quadPart);
|
||||
}
|
||||
|
||||
fn Time native_timestamp()
|
||||
{
|
||||
Win32_FILETIME ft @noinit;
|
||||
win32_GetSystemTimeAsFileTime(&ft);
|
||||
win32::getSystemTimeAsFileTime(&ft);
|
||||
ulong result = (ulong)ft.dwHighDateTime << 32 | ft.dwLowDateTime;
|
||||
return (Time)(result / WINDOWS_TICK_US - WIN_TO_UNIX_EPOCH_US);
|
||||
}
|
||||
Reference in New Issue
Block a user