chore: remove trailing whitespace from README.md line 42

This commit is contained in:
2025-12-07 15:31:49 +00:00
parent 8c0c82335e
commit 36f84fba17
51 changed files with 2606 additions and 562 deletions
+689 -559
View File
File diff suppressed because it is too large Load Diff
+66 -1
View File
@@ -32,7 +32,8 @@ typedef enum {
RAVA_VAL_HASHMAP,
RAVA_VAL_SOCKET,
RAVA_VAL_STREAM,
RAVA_VAL_METHOD_REF
RAVA_VAL_METHOD_REF,
RAVA_VAL_INETADDRESS
} RavaValueType_e;
typedef struct {
@@ -49,6 +50,7 @@ typedef struct RavaHashMap_t RavaHashMap_t;
typedef struct RavaSocket_t RavaSocket_t;
typedef struct RavaStream_t RavaStream_t;
typedef struct RavaMethodRef_t RavaMethodRef_t;
typedef struct RavaInetAddress_t RavaInetAddress_t;
#define RAVA_OBJECT_HASH_SIZE 32
@@ -79,6 +81,7 @@ struct RavaValue_t {
RavaSocket_t *socket_val;
RavaStream_t *stream_val;
RavaMethodRef_t *method_ref_val;
RavaInetAddress_t *inetaddress_val;
} data;
};
@@ -118,6 +121,9 @@ struct RavaSocket_t {
int fd;
bool connected;
bool closed;
bool bound;
bool input_shutdown;
bool output_shutdown;
};
#define RAVA_STREAM_TYPE_INPUT 1
@@ -140,6 +146,17 @@ struct RavaMethodRef_t {
bool has_target;
};
#define RAVA_INETADDRESS_IPV4 1
#define RAVA_INETADDRESS_IPV6 2
struct RavaInetAddress_t {
RavaGCHeader_t gc;
int address_type;
uint8_t address[16];
char *hostname;
char *hostaddress;
};
typedef struct {
RavaValue_t *values;
size_t capacity;
@@ -365,6 +382,53 @@ int rava_stream_read_byte(RavaStream_t *stream);
void rava_stream_write(RavaStream_t *stream, const char *data);
void rava_stream_write_byte(RavaStream_t *stream, int byte);
void rava_stream_close(RavaStream_t *stream);
int rava_stream_read_bytes(RavaStream_t *stream, RavaArray_t *arr, int off, int len);
int rava_stream_available(RavaStream_t *stream);
RavaInetAddress_t* rava_inetaddress_create(void);
RavaInetAddress_t* rava_inetaddress_get_by_name(const char *host);
RavaInetAddress_t* rava_inetaddress_get_local_host(void);
RavaInetAddress_t* rava_inetaddress_get_loopback(void);
char* rava_inetaddress_get_host_name(RavaInetAddress_t *addr);
char* rava_inetaddress_get_host_address(RavaInetAddress_t *addr);
bool rava_inetaddress_is_loopback(RavaInetAddress_t *addr);
bool rava_inetaddress_is_any_local(RavaInetAddress_t *addr);
int rava_socket_get_port(RavaSocket_t *socket);
int rava_socket_get_local_port(RavaSocket_t *socket);
RavaInetAddress_t* rava_socket_get_inet_address(RavaSocket_t *socket);
RavaInetAddress_t* rava_socket_get_local_address(RavaSocket_t *socket);
int rava_server_socket_get_local_port(RavaSocket_t *socket);
bool rava_server_socket_is_bound(RavaSocket_t *socket);
bool rava_server_socket_is_closed(RavaSocket_t *socket);
void rava_server_socket_set_so_timeout(RavaSocket_t *socket, int timeout);
int rava_server_socket_get_so_timeout(RavaSocket_t *socket);
void rava_socket_set_so_timeout(RavaSocket_t *socket, int timeout_ms);
int rava_socket_get_so_timeout(RavaSocket_t *socket);
void rava_socket_set_tcp_nodelay(RavaSocket_t *socket, bool nodelay);
bool rava_socket_get_tcp_nodelay(RavaSocket_t *socket);
void rava_socket_bind(RavaSocket_t *socket, const char *host, int port);
bool rava_socket_is_connected(RavaSocket_t *socket);
bool rava_socket_is_closed(RavaSocket_t *socket);
bool rava_socket_is_bound(RavaSocket_t *socket);
void rava_socket_shutdown_input(RavaSocket_t *socket);
void rava_socket_shutdown_output(RavaSocket_t *socket);
bool rava_socket_is_input_shutdown(RavaSocket_t *socket);
bool rava_socket_is_output_shutdown(RavaSocket_t *socket);
void rava_socket_set_send_buffer_size(RavaSocket_t *socket, int size);
int rava_socket_get_send_buffer_size(RavaSocket_t *socket);
void rava_socket_set_receive_buffer_size(RavaSocket_t *socket, int size);
int rava_socket_get_receive_buffer_size(RavaSocket_t *socket);
void rava_socket_set_keep_alive(RavaSocket_t *socket, bool keepalive);
bool rava_socket_get_keep_alive(RavaSocket_t *socket);
void rava_socket_set_reuse_address(RavaSocket_t *socket, bool reuse);
bool rava_socket_get_reuse_address(RavaSocket_t *socket);
static inline RavaValue_t rava_value_inetaddress(RavaInetAddress_t *addr) {
RavaValue_t val;
val.type = RAVA_VAL_INETADDRESS;
val.data.inetaddress_val = addr;
return val;
}
static inline RavaValue_t rava_value_socket(RavaSocket_t *socket) {
RavaValue_t val;
@@ -437,6 +501,7 @@ RavaValue_t rava_native_to_value(RavaNativeValue_t native);
#define RAVA_GC_TYPE_SOCKET 6
#define RAVA_GC_TYPE_STREAM 7
#define RAVA_GC_TYPE_METHODREF 8
#define RAVA_GC_TYPE_INETADDRESS 9
void rava_gc_init(void);
void rava_gc_shutdown(void);
+23
View File
@@ -0,0 +1,23 @@
#include "runtime_internal.h"
RavaExceptionStack_t* rava_exception_stack_create(void) {
RavaExceptionStack_t *stack = calloc(1, sizeof(RavaExceptionStack_t));
if (!stack) return NULL;
stack->count = 0;
return stack;
}
void rava_exception_stack_destroy(RavaExceptionStack_t *stack) {
free(stack);
}
void rava_exception_stack_push(RavaExceptionStack_t *stack, RavaExceptionHandler_t handler) {
if (stack->count >= RAVA_MAX_EXCEPTION_DEPTH) return;
stack->handlers[stack->count++] = handler;
}
bool rava_exception_stack_pop(RavaExceptionStack_t *stack, RavaExceptionHandler_t *handler) {
if (stack->count == 0) return false;
*handler = stack->handlers[--stack->count];
return true;
}
+25
View File
@@ -0,0 +1,25 @@
#include "runtime_internal.h"
const char* _rava_intern_string(RavaVM_t *vm, const char *str) {
uint32_t h = _intern_hash(str);
for (size_t i = 0; i < RAVA_INTERN_TABLE_SIZE; i++) {
size_t idx = (h + i) & (RAVA_INTERN_TABLE_SIZE - 1);
if (vm->intern_table.strings[idx] == NULL) {
if (vm->intern_table.count >= RAVA_INTERN_TABLE_SIZE - 1) {
static bool warned = false;
if (!warned) {
fprintf(stderr, "Warning: String intern table full (%d entries)\n",
RAVA_INTERN_TABLE_SIZE);
warned = true;
}
}
vm->intern_table.strings[idx] = strdup(str);
vm->intern_table.count++;
return vm->intern_table.strings[idx];
}
if (strcmp(vm->intern_table.strings[idx], str) == 0) {
return vm->intern_table.strings[idx];
}
}
return strdup(str);
}
+174
View File
@@ -0,0 +1,174 @@
#ifndef RAVA_RUNTIME_INTERNAL_H
#define RAVA_RUNTIME_INTERNAL_H
#define _POSIX_C_SOURCE 200809L
#include "runtime.h"
#include "labeltable.h"
#include "methodcache.h"
#include "nanbox.h"
#include "fastframe.h"
#include "superinst.h"
#include "../utils/safe_alloc.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <time.h>
#include <math.h>
#include <ctype.h>
#ifdef __GNUC__
#define LIKELY(x) __builtin_expect(!!(x), 1)
#define UNLIKELY(x) __builtin_expect(!!(x), 0)
#else
#define LIKELY(x) (x)
#define UNLIKELY(x) (x)
#endif
#define STACK_ENSURE_CAPACITY(stack) do { \
if ((stack)->top >= (stack)->capacity) { \
(stack)->capacity *= 2; \
RavaValue_t *_new_values = realloc((stack)->values, sizeof(RavaValue_t) * (stack)->capacity); \
if (_new_values) (stack)->values = _new_values; \
} \
} while(0)
#define STACK_PUSH(stack, val) do { \
STACK_ENSURE_CAPACITY(stack); \
(stack)->values[(stack)->top++] = (val); \
} while(0)
#define STACK_POP(stack) ((stack)->top > 0 ? (stack)->values[--(stack)->top] : (RavaValue_t){0})
#define STACK_PEEK(stack) ((stack)->top > 0 ? (stack)->values[(stack)->top - 1] : (RavaValue_t){0})
#define STACK_PUSH_INT(stack, v) do { \
STACK_ENSURE_CAPACITY(stack); \
RavaValue_t _v; _v.type = RAVA_VAL_INT; _v.data.int_val = (v); \
(stack)->values[(stack)->top++] = _v; \
} while(0)
#define STACK_PUSH_LONG(stack, v) do { \
STACK_ENSURE_CAPACITY(stack); \
RavaValue_t _v; _v.type = RAVA_VAL_LONG; _v.data.long_val = (v); \
(stack)->values[(stack)->top++] = _v; \
} while(0)
#define STACK_PUSH_BOOL(stack, v) do { \
STACK_ENSURE_CAPACITY(stack); \
RavaValue_t _v; _v.type = RAVA_VAL_BOOLEAN; _v.data.bool_val = (v); \
(stack)->values[(stack)->top++] = _v; \
} while(0)
#define VALUE_IS_INT(v) ((v).type == RAVA_VAL_INT)
#define VALUE_IS_LONG(v) ((v).type == RAVA_VAL_LONG)
#define VALUE_AS_INT_FAST(v) ((v).data.int_val)
#define VALUE_AS_LONG_FAST(v) ((v).data.long_val)
static inline RavaNanboxValue_t rava_value_to_nanbox(RavaValue_t val) {
switch (val.type) {
case RAVA_VAL_INT: return rava_nanbox_int(val.data.int_val);
case RAVA_VAL_LONG: return rava_nanbox_long(val.data.long_val);
case RAVA_VAL_DOUBLE: return rava_nanbox_double(val.data.double_val);
case RAVA_VAL_FLOAT: return rava_nanbox_double((double)val.data.float_val);
case RAVA_VAL_BOOLEAN: return rava_nanbox_bool(val.data.bool_val);
case RAVA_VAL_NULL: return rava_nanbox_null();
case RAVA_VAL_STRING: return rava_nanbox_string(val.data.string_val);
case RAVA_VAL_OBJECT: return rava_nanbox_object(val.data.object_val);
case RAVA_VAL_ARRAY: return rava_nanbox_array(val.data.array_val);
default: return rava_nanbox_null();
}
}
static inline RavaValue_t rava_nanbox_to_value(RavaNanboxValue_t nb) {
RavaValue_t val;
if (rava_nanbox_is_int(nb)) {
val.type = RAVA_VAL_INT;
val.data.int_val = rava_nanbox_as_int(nb);
} else if (rava_nanbox_is_long(nb)) {
val.type = RAVA_VAL_LONG;
val.data.long_val = rava_nanbox_as_long(nb);
} else if (rava_nanbox_is_double(nb)) {
val.type = RAVA_VAL_DOUBLE;
val.data.double_val = rava_nanbox_as_double(nb);
} else if (rava_nanbox_is_bool(nb)) {
val.type = RAVA_VAL_BOOLEAN;
val.data.bool_val = rava_nanbox_as_bool(nb);
} else if (rava_nanbox_is_null(nb)) {
val.type = RAVA_VAL_NULL;
val.data.object_val = NULL;
} else if (rava_nanbox_is_string(nb)) {
val.type = RAVA_VAL_STRING;
val.data.string_val = (char*)rava_nanbox_as_string(nb);
} else if (rava_nanbox_is_object(nb)) {
val.type = RAVA_VAL_OBJECT;
val.data.object_val = rava_nanbox_as_object(nb);
} else if (rava_nanbox_is_array(nb)) {
val.type = RAVA_VAL_ARRAY;
val.data.array_val = rava_nanbox_as_array(nb);
} else {
val.type = RAVA_VAL_NULL;
val.data.object_val = NULL;
}
return val;
}
static inline uint32_t _rava_field_hash(const char *name) {
uint32_t hash = 5381;
while (*name) {
hash = ((hash << 5) + hash) ^ (uint32_t)*name++;
}
return hash;
}
static inline uint32_t _rava_class_hash(const char *name) {
uint32_t hash = 5381;
while (*name) hash = ((hash << 5) + hash) ^ (uint32_t)*name++;
return hash & (RAVA_CLASS_HASH_SIZE - 1);
}
static inline uint32_t _rava_method_hash(const char *name) {
uint32_t hash = 5381;
while (*name) hash = ((hash << 5) + hash) ^ (uint32_t)*name++;
return hash & (RAVA_METHOD_HASH_SIZE - 1);
}
static inline uint32_t _rava_static_hash(const char *class_name, const char *field_name) {
uint32_t hash = 5381;
while (*class_name) hash = ((hash << 5) + hash) ^ (uint32_t)*class_name++;
hash = ((hash << 5) + hash) ^ (uint32_t)'.';
while (*field_name) hash = ((hash << 5) + hash) ^ (uint32_t)*field_name++;
return hash;
}
static inline uint32_t _intern_hash(const char *str) {
uint32_t hash = 5381;
while (*str) hash = ((hash << 5) + hash) ^ (uint32_t)*str++;
return hash;
}
char* _rava_get_string_buffer(RavaVM_t *vm, size_t needed);
const char* _rava_intern_string(RavaVM_t *vm, const char *str);
void _rava_object_set_field_vm(RavaObject_t *obj, const char *name, RavaValue_t value, RavaVM_t *vm);
RavaClass_t* _rava_vm_find_class(RavaVM_t *vm, const char *class_name);
RavaMethod_t* _rava_vm_find_method(RavaVM_t *vm, const char *class_name, const char *method_name);
RavaMethod_t* _rava_vm_find_method_cached(RavaVM_t *vm, const char *class_name, const char *method_name);
RavaStaticFieldTable_t* rava_static_field_table_create(void);
void rava_static_field_table_destroy(RavaStaticFieldTable_t *table);
RavaValue_t* rava_static_field_table_get(RavaStaticFieldTable_t *table, const char *class_name, const char *field_name);
void rava_static_field_table_set(RavaStaticFieldTable_t *table, const char *class_name, const char *field_name, RavaValue_t value);
RavaExceptionStack_t* rava_exception_stack_create(void);
void rava_exception_stack_destroy(RavaExceptionStack_t *stack);
void rava_exception_stack_push(RavaExceptionStack_t *stack, RavaExceptionHandler_t handler);
bool rava_exception_stack_pop(RavaExceptionStack_t *stack, RavaExceptionHandler_t *handler);
bool _rava_vm_execute_instruction(RavaVM_t *vm, RavaCallFrame_t *frame, RavaInstruction_t *instr);
bool _rava_vm_execute_fast(RavaVM_t *vm, RavaCallFrame_t *frame);
bool _rava_vm_execute_ultrafast(RavaVM_t *vm, RavaMethod_t *entry_method);
bool _rava_vm_run_static_initializers(RavaVM_t *vm);
extern bool g_gc_initialized;
#endif
+53
View File
@@ -0,0 +1,53 @@
#include "runtime_internal.h"
bool g_gc_initialized = false;
RavaClass_t* _rava_vm_find_class(RavaVM_t *vm, const char *class_name) {
uint32_t h = _rava_class_hash(class_name);
int idx = vm->class_hash[h];
if (idx >= 0 && (size_t)idx < vm->program->class_count &&
strcmp(vm->program->classes[idx]->name, class_name) == 0) {
return vm->program->classes[idx];
}
for (size_t i = 0; i < vm->program->class_count; i++) {
if (strcmp(vm->program->classes[i]->name, class_name) == 0) {
vm->class_hash[h] = (int)i;
return vm->program->classes[i];
}
}
return NULL;
}
RavaMethod_t* _rava_vm_find_method(RavaVM_t *vm, const char *class_name, const char *method_name) {
const char *current_class = class_name;
while (current_class) {
RavaClass_t *class = _rava_vm_find_class(vm, current_class);
if (!class) break;
uint32_t h = _rava_method_hash(method_name);
int idx = class->method_hash[h];
if (idx >= 0 && (size_t)idx < class->method_count &&
strcmp(class->methods[idx]->name, method_name) == 0) {
return class->methods[idx];
}
for (size_t j = 0; j < class->method_count; j++) {
if (strcmp(class->methods[j]->name, method_name) == 0) {
class->method_hash[h] = (int)j;
return class->methods[j];
}
}
current_class = class->superclass;
}
return NULL;
}
RavaMethod_t* _rava_vm_find_method_cached(RavaVM_t *vm, const char *class_name, const char *method_name) {
MethodCache_t *cache = (MethodCache_t*)vm->method_cache;
RavaMethod_t *cached = rava_methodcache_lookup(cache, class_name, method_name);
if (cached) return cached;
RavaMethod_t *method = _rava_vm_find_method(vm, class_name, method_name);
if (method) {
rava_methodcache_insert(cache, class_name, method_name, method);
}
return method;
}
+11
View File
@@ -178,6 +178,8 @@ int32_t rava_object_hashcode(RavaValue_t value) {
return (int32_t)((uintptr_t)value.data.socket_val >> 3);
case RAVA_VAL_STREAM:
return (int32_t)((uintptr_t)value.data.stream_val >> 3);
case RAVA_VAL_INETADDRESS:
return (int32_t)((uintptr_t)value.data.inetaddress_val >> 3);
case RAVA_VAL_METHOD_REF:
return (int32_t)((uintptr_t)value.data.method_ref_val >> 3);
}
@@ -287,6 +289,13 @@ char* rava_object_tostring(RavaValue_t value) {
snprintf(buffer, 128, "Stream@%x",
(unsigned int)((uintptr_t)value.data.stream_val >> 3));
break;
case RAVA_VAL_INETADDRESS:
if (value.data.inetaddress_val && value.data.inetaddress_val->hostaddress) {
snprintf(buffer, 128, "/%s", value.data.inetaddress_val->hostaddress);
} else {
strcpy(buffer, "/null");
}
break;
case RAVA_VAL_METHOD_REF:
if (value.data.method_ref_val) {
snprintf(buffer, 128, "%s::%s",
@@ -333,6 +342,8 @@ const char* rava_object_getclass(RavaValue_t value) {
return "Socket";
case RAVA_VAL_STREAM:
return "Stream";
case RAVA_VAL_INETADDRESS:
return "InetAddress";
case RAVA_VAL_METHOD_REF:
return "MethodReference";
}
+430
View File
@@ -9,6 +9,13 @@
#include <arpa/inet.h>
#include <netdb.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <netinet/tcp.h>
#ifndef NI_MAXHOST
#define NI_MAXHOST 1025
#endif
RavaSocket_t* rava_socket_create(void) {
RavaSocket_t *sock = rava_gc_alloc(sizeof(RavaSocket_t), RAVA_GC_TYPE_SOCKET);
@@ -62,6 +69,8 @@ RavaSocket_t* rava_server_socket_create(int port) {
return sock;
}
sock->bound = true;
if (listen(sock->fd, 10) < 0) {
close(sock->fd);
sock->fd = -1;
@@ -204,3 +213,424 @@ void rava_stream_close(RavaStream_t *stream) {
if (!stream) return;
stream->closed = true;
}
int rava_stream_read_bytes(RavaStream_t *stream, RavaArray_t *arr, int off, int len) {
if (!stream || stream->closed || stream->fd < 0) return -1;
if (stream->stream_type != RAVA_STREAM_TYPE_INPUT) return -1;
if (!arr || off < 0 || len <= 0) return -1;
if ((size_t)(off + len) > arr->length) return -1;
char *buffer = malloc(len);
if (!buffer) return -1;
ssize_t bytes_read = read(stream->fd, buffer, len);
if (bytes_read <= 0) {
free(buffer);
return -1;
}
for (ssize_t i = 0; i < bytes_read; i++) {
rava_array_set_value(arr, off + i, rava_value_int((unsigned char)buffer[i]));
}
free(buffer);
return (int)bytes_read;
}
int rava_stream_available(RavaStream_t *stream) {
if (!stream || stream->closed || stream->fd < 0) return 0;
if (stream->stream_type != RAVA_STREAM_TYPE_INPUT) return 0;
int available = 0;
if (ioctl(stream->fd, FIONREAD, &available) < 0) {
return 0;
}
return available;
}
RavaInetAddress_t* rava_inetaddress_create(void) {
RavaInetAddress_t *addr = rava_gc_alloc(sizeof(RavaInetAddress_t), RAVA_GC_TYPE_INETADDRESS);
if (!addr) return NULL;
memset((char*)addr + sizeof(RavaGCHeader_t), 0, sizeof(RavaInetAddress_t) - sizeof(RavaGCHeader_t));
addr->address_type = RAVA_INETADDRESS_IPV4;
return addr;
}
RavaInetAddress_t* rava_inetaddress_get_by_name(const char *host) {
if (!host) return NULL;
struct addrinfo hints, *res;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
int status = getaddrinfo(host, NULL, &hints, &res);
if (status != 0) return NULL;
RavaInetAddress_t *addr = rava_inetaddress_create();
if (!addr) {
freeaddrinfo(res);
return NULL;
}
addr->hostname = strdup(host);
if (res->ai_family == AF_INET) {
addr->address_type = RAVA_INETADDRESS_IPV4;
struct sockaddr_in *ipv4 = (struct sockaddr_in*)res->ai_addr;
memcpy(addr->address, &ipv4->sin_addr, 4);
char ip[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &ipv4->sin_addr, ip, sizeof(ip));
addr->hostaddress = strdup(ip);
} else if (res->ai_family == AF_INET6) {
addr->address_type = RAVA_INETADDRESS_IPV6;
struct sockaddr_in6 *ipv6 = (struct sockaddr_in6*)res->ai_addr;
memcpy(addr->address, &ipv6->sin6_addr, 16);
char ip[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, &ipv6->sin6_addr, ip, sizeof(ip));
addr->hostaddress = strdup(ip);
}
freeaddrinfo(res);
return addr;
}
RavaInetAddress_t* rava_inetaddress_get_local_host(void) {
char hostname[256];
if (gethostname(hostname, sizeof(hostname)) != 0) {
return rava_inetaddress_get_loopback();
}
RavaInetAddress_t *addr = rava_inetaddress_get_by_name(hostname);
if (!addr) {
return rava_inetaddress_get_loopback();
}
return addr;
}
RavaInetAddress_t* rava_inetaddress_get_loopback(void) {
RavaInetAddress_t *addr = rava_inetaddress_create();
if (!addr) return NULL;
addr->address_type = RAVA_INETADDRESS_IPV4;
addr->address[0] = 127;
addr->address[1] = 0;
addr->address[2] = 0;
addr->address[3] = 1;
addr->hostname = strdup("localhost");
addr->hostaddress = strdup("127.0.0.1");
return addr;
}
char* rava_inetaddress_get_host_name(RavaInetAddress_t *addr) {
if (!addr) return NULL;
if (addr->hostname) return addr->hostname;
char host[NI_MAXHOST];
struct sockaddr_in sa;
memset(&sa, 0, sizeof(sa));
sa.sin_family = AF_INET;
memcpy(&sa.sin_addr, addr->address, 4);
int result = getnameinfo((struct sockaddr*)&sa, sizeof(sa), host, sizeof(host), NULL, 0, 0);
if (result == 0) {
addr->hostname = strdup(host);
return addr->hostname;
}
return addr->hostaddress;
}
char* rava_inetaddress_get_host_address(RavaInetAddress_t *addr) {
if (!addr) return NULL;
if (addr->hostaddress) return addr->hostaddress;
char ip[INET6_ADDRSTRLEN];
if (addr->address_type == RAVA_INETADDRESS_IPV4) {
inet_ntop(AF_INET, addr->address, ip, sizeof(ip));
} else {
inet_ntop(AF_INET6, addr->address, ip, sizeof(ip));
}
addr->hostaddress = strdup(ip);
return addr->hostaddress;
}
bool rava_inetaddress_is_loopback(RavaInetAddress_t *addr) {
if (!addr) return false;
if (addr->address_type == RAVA_INETADDRESS_IPV4) {
return addr->address[0] == 127;
}
static const uint8_t ipv6_loopback[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1};
return memcmp(addr->address, ipv6_loopback, 16) == 0;
}
bool rava_inetaddress_is_any_local(RavaInetAddress_t *addr) {
if (!addr) return false;
if (addr->address_type == RAVA_INETADDRESS_IPV4) {
return addr->address[0] == 0 && addr->address[1] == 0 &&
addr->address[2] == 0 && addr->address[3] == 0;
}
static const uint8_t ipv6_any[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
return memcmp(addr->address, ipv6_any, 16) == 0;
}
int rava_socket_get_port(RavaSocket_t *socket) {
if (!socket || socket->fd < 0) return -1;
struct sockaddr_in addr;
socklen_t len = sizeof(addr);
if (getpeername(socket->fd, (struct sockaddr*)&addr, &len) < 0) {
return -1;
}
return ntohs(addr.sin_port);
}
int rava_socket_get_local_port(RavaSocket_t *socket) {
if (!socket || socket->fd < 0) return -1;
struct sockaddr_in addr;
socklen_t len = sizeof(addr);
if (getsockname(socket->fd, (struct sockaddr*)&addr, &len) < 0) {
return -1;
}
return ntohs(addr.sin_port);
}
RavaInetAddress_t* rava_socket_get_inet_address(RavaSocket_t *socket) {
if (!socket || socket->fd < 0) return NULL;
struct sockaddr_in addr;
socklen_t len = sizeof(addr);
if (getpeername(socket->fd, (struct sockaddr*)&addr, &len) < 0) {
return NULL;
}
RavaInetAddress_t *inet_addr = rava_inetaddress_create();
if (!inet_addr) return NULL;
inet_addr->address_type = RAVA_INETADDRESS_IPV4;
memcpy(inet_addr->address, &addr.sin_addr, 4);
char ip[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &addr.sin_addr, ip, sizeof(ip));
inet_addr->hostaddress = strdup(ip);
return inet_addr;
}
RavaInetAddress_t* rava_socket_get_local_address(RavaSocket_t *socket) {
if (!socket || socket->fd < 0) return NULL;
struct sockaddr_in addr;
socklen_t len = sizeof(addr);
if (getsockname(socket->fd, (struct sockaddr*)&addr, &len) < 0) {
return NULL;
}
RavaInetAddress_t *inet_addr = rava_inetaddress_create();
if (!inet_addr) return NULL;
inet_addr->address_type = RAVA_INETADDRESS_IPV4;
memcpy(inet_addr->address, &addr.sin_addr, 4);
char ip[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &addr.sin_addr, ip, sizeof(ip));
inet_addr->hostaddress = strdup(ip);
return inet_addr;
}
int rava_server_socket_get_local_port(RavaSocket_t *socket) {
return rava_socket_get_local_port(socket);
}
bool rava_server_socket_is_bound(RavaSocket_t *socket) {
if (!socket || socket->fd < 0) return false;
return socket->bound;
}
bool rava_server_socket_is_closed(RavaSocket_t *socket) {
if (!socket) return true;
return socket->closed;
}
void rava_server_socket_set_so_timeout(RavaSocket_t *socket, int timeout) {
if (!socket || socket->fd < 0) return;
struct timeval tv;
tv.tv_sec = timeout / 1000;
tv.tv_usec = (timeout % 1000) * 1000;
setsockopt(socket->fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
}
int rava_server_socket_get_so_timeout(RavaSocket_t *socket) {
if (!socket || socket->fd < 0) return 0;
struct timeval tv;
socklen_t len = sizeof(tv);
if (getsockopt(socket->fd, SOL_SOCKET, SO_RCVTIMEO, &tv, &len) < 0) {
return 0;
}
return (int)(tv.tv_sec * 1000 + tv.tv_usec / 1000);
}
void rava_socket_set_so_timeout(RavaSocket_t *socket, int timeout_ms) {
if (!socket || socket->fd < 0) return;
struct timeval tv;
tv.tv_sec = timeout_ms / 1000;
tv.tv_usec = (timeout_ms % 1000) * 1000;
setsockopt(socket->fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
setsockopt(socket->fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
}
int rava_socket_get_so_timeout(RavaSocket_t *socket) {
if (!socket || socket->fd < 0) return 0;
struct timeval tv;
socklen_t len = sizeof(tv);
if (getsockopt(socket->fd, SOL_SOCKET, SO_RCVTIMEO, &tv, &len) < 0) {
return 0;
}
return (int)(tv.tv_sec * 1000 + tv.tv_usec / 1000);
}
void rava_socket_set_tcp_nodelay(RavaSocket_t *socket, bool nodelay) {
if (!socket || socket->fd < 0) return;
int flag = nodelay ? 1 : 0;
setsockopt(socket->fd, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof(flag));
}
bool rava_socket_get_tcp_nodelay(RavaSocket_t *socket) {
if (!socket || socket->fd < 0) return false;
int flag = 0;
socklen_t len = sizeof(flag);
if (getsockopt(socket->fd, IPPROTO_TCP, TCP_NODELAY, &flag, &len) < 0) {
return false;
}
return flag != 0;
}
void rava_socket_bind(RavaSocket_t *socket, const char *host, int port) {
if (!socket || socket->fd < 0) return;
if (socket->bound) return;
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
if (host && strcmp(host, "0.0.0.0") != 0) {
if (inet_pton(AF_INET, host, &addr.sin_addr) <= 0) {
return;
}
} else {
addr.sin_addr.s_addr = INADDR_ANY;
}
if (bind(socket->fd, (struct sockaddr*)&addr, sizeof(addr)) == 0) {
socket->bound = true;
}
}
bool rava_socket_is_connected(RavaSocket_t *socket) {
if (!socket) return false;
return socket->connected && !socket->closed;
}
bool rava_socket_is_closed(RavaSocket_t *socket) {
if (!socket) return true;
return socket->closed;
}
bool rava_socket_is_bound(RavaSocket_t *socket) {
if (!socket) return false;
return socket->bound;
}
void rava_socket_shutdown_input(RavaSocket_t *socket) {
if (!socket || socket->fd < 0) return;
if (socket->input_shutdown) return;
shutdown(socket->fd, SHUT_RD);
socket->input_shutdown = true;
}
void rava_socket_shutdown_output(RavaSocket_t *socket) {
if (!socket || socket->fd < 0) return;
if (socket->output_shutdown) return;
shutdown(socket->fd, SHUT_WR);
socket->output_shutdown = true;
}
bool rava_socket_is_input_shutdown(RavaSocket_t *socket) {
if (!socket) return false;
return socket->input_shutdown;
}
bool rava_socket_is_output_shutdown(RavaSocket_t *socket) {
if (!socket) return false;
return socket->output_shutdown;
}
void rava_socket_set_send_buffer_size(RavaSocket_t *socket, int size) {
if (!socket || socket->fd < 0) return;
setsockopt(socket->fd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
}
int rava_socket_get_send_buffer_size(RavaSocket_t *socket) {
if (!socket || socket->fd < 0) return 0;
int size = 0;
socklen_t len = sizeof(size);
if (getsockopt(socket->fd, SOL_SOCKET, SO_SNDBUF, &size, &len) == 0) {
return size;
}
return 0;
}
void rava_socket_set_receive_buffer_size(RavaSocket_t *socket, int size) {
if (!socket || socket->fd < 0) return;
setsockopt(socket->fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
}
int rava_socket_get_receive_buffer_size(RavaSocket_t *socket) {
if (!socket || socket->fd < 0) return 0;
int size = 0;
socklen_t len = sizeof(size);
if (getsockopt(socket->fd, SOL_SOCKET, SO_RCVBUF, &size, &len) == 0) {
return size;
}
return 0;
}
void rava_socket_set_keep_alive(RavaSocket_t *socket, bool keepalive) {
if (!socket || socket->fd < 0) return;
int val = keepalive ? 1 : 0;
setsockopt(socket->fd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val));
}
bool rava_socket_get_keep_alive(RavaSocket_t *socket) {
if (!socket || socket->fd < 0) return false;
int val = 0;
socklen_t len = sizeof(val);
if (getsockopt(socket->fd, SOL_SOCKET, SO_KEEPALIVE, &val, &len) == 0) {
return val != 0;
}
return false;
}
void rava_socket_set_reuse_address(RavaSocket_t *socket, bool reuse) {
if (!socket || socket->fd < 0) return;
int val = reuse ? 1 : 0;
setsockopt(socket->fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
}
bool rava_socket_get_reuse_address(RavaSocket_t *socket) {
if (!socket || socket->fd < 0) return false;
int val = 0;
socklen_t len = sizeof(val);
if (getsockopt(socket->fd, SOL_SOCKET, SO_REUSEADDR, &val, &len) == 0) {
return val != 0;
}
return false;
}
+127
View File
@@ -0,0 +1,127 @@
#include "runtime_internal.h"
RavaStack_t* rava_stack_create(size_t capacity) {
RavaStack_t *stack = malloc(sizeof(RavaStack_t));
if (!stack) return NULL;
stack->capacity = capacity;
stack->values = malloc(sizeof(RavaValue_t) * capacity);
if (!stack->values) {
free(stack);
return NULL;
}
stack->top = 0;
return stack;
}
void rava_stack_destroy(RavaStack_t *stack) {
if (!stack) return;
free(stack->values);
free(stack);
}
void rava_stack_push(RavaStack_t *stack, RavaValue_t value) {
if (stack->top >= stack->capacity) {
stack->capacity *= 2;
RavaValue_t *new_values = rava_safe_realloc(stack->values, sizeof(RavaValue_t) * stack->capacity);
if (!new_values) return;
stack->values = new_values;
}
stack->values[stack->top++] = value;
}
RavaValue_t rava_stack_pop(RavaStack_t *stack) {
if (stack->top == 0) {
return rava_value_int(0);
}
return stack->values[--stack->top];
}
RavaValue_t rava_stack_peek(RavaStack_t *stack) {
if (stack->top == 0) {
return rava_value_int(0);
}
return stack->values[stack->top - 1];
}
bool rava_stack_is_empty(RavaStack_t *stack) {
return stack->top == 0;
}
RavaCallFrame_t* rava_call_frame_create(RavaMethod_t *method) {
RavaCallFrame_t *frame = calloc(1, sizeof(RavaCallFrame_t));
if (!frame) return NULL;
frame->method = method;
frame->local_count = method->local_count;
frame->locals = calloc(method->local_count, sizeof(RavaValue_t));
if (!frame->locals && method->local_count > 0) {
free(frame);
return NULL;
}
frame->pc = 0;
size_t stack_size = method->max_stack > 0 ? (size_t)method->max_stack : 64;
frame->operand_stack = rava_stack_create(stack_size);
if (!frame->operand_stack) {
free(frame->locals);
free(frame);
return NULL;
}
frame->has_this = false;
frame->this_ref = rava_value_null();
return frame;
}
void rava_call_frame_destroy(RavaCallFrame_t *frame) {
if (!frame) return;
free(frame->locals);
rava_stack_destroy(frame->operand_stack);
free(frame);
}
RavaCallStack_t* rava_call_stack_create(void) {
RavaCallStack_t *stack = malloc(sizeof(RavaCallStack_t));
if (!stack) return NULL;
stack->capacity = 256;
stack->frames = malloc(sizeof(RavaCallFrame_t*) * stack->capacity);
if (!stack->frames) {
free(stack);
return NULL;
}
stack->count = 0;
return stack;
}
void rava_call_stack_destroy(RavaCallStack_t *stack) {
if (!stack) return;
for (size_t i = 0; i < stack->count; i++) {
rava_call_frame_destroy(stack->frames[i]);
}
free(stack->frames);
free(stack);
}
#define RAVA_MAX_CALL_STACK_DEPTH 10000
bool rava_call_stack_push(RavaCallStack_t *stack, RavaCallFrame_t *frame) {
if (stack->count >= RAVA_MAX_CALL_STACK_DEPTH) {
return false;
}
if (stack->count >= stack->capacity) {
stack->capacity *= 2;
RavaCallFrame_t **new_frames = rava_safe_realloc(stack->frames, sizeof(RavaCallFrame_t*) * stack->capacity);
if (!new_frames) return false;
stack->frames = new_frames;
}
stack->frames[stack->count++] = frame;
return true;
}
RavaCallFrame_t* rava_call_stack_pop(RavaCallStack_t *stack) {
if (stack->count == 0) return NULL;
RavaCallFrame_t *frame = stack->frames[--stack->count];
return frame;
}
RavaCallFrame_t* rava_call_stack_current(RavaCallStack_t *stack) {
if (stack->count == 0) return NULL;
return stack->frames[stack->count - 1];
}
+85
View File
@@ -0,0 +1,85 @@
#include "runtime_internal.h"
RavaStaticFieldTable_t* rava_static_field_table_create(void) {
RavaStaticFieldTable_t *table = malloc(sizeof(RavaStaticFieldTable_t));
if (!table) return NULL;
table->capacity = 16;
table->fields = calloc(table->capacity, sizeof(RavaStaticField_t));
if (!table->fields) {
free(table);
return NULL;
}
table->count = 0;
for (int i = 0; i < RAVA_STATIC_HASH_SIZE; i++) {
table->hash_table[i] = -1;
}
return table;
}
void rava_static_field_table_destroy(RavaStaticFieldTable_t *table) {
if (!table) return;
for (size_t i = 0; i < table->count; i++) {
free(table->fields[i].class_name);
free(table->fields[i].field_name);
}
free(table->fields);
free(table);
}
RavaValue_t* rava_static_field_table_get(RavaStaticFieldTable_t *table,
const char *class_name,
const char *field_name) {
uint32_t hash = _rava_static_hash(class_name, field_name);
for (size_t probe = 0; probe < RAVA_STATIC_HASH_SIZE; probe++) {
uint32_t slot = (hash + probe) & (RAVA_STATIC_HASH_SIZE - 1);
int idx = table->hash_table[slot];
if (idx == -1) {
return NULL;
}
if ((size_t)idx < table->count &&
strcmp(table->fields[idx].class_name, class_name) == 0 &&
strcmp(table->fields[idx].field_name, field_name) == 0) {
return &table->fields[idx].value;
}
}
return NULL;
}
void rava_static_field_table_set(RavaStaticFieldTable_t *table,
const char *class_name,
const char *field_name,
RavaValue_t value) {
uint32_t hash = _rava_static_hash(class_name, field_name);
for (size_t probe = 0; probe < RAVA_STATIC_HASH_SIZE; probe++) {
uint32_t slot = (hash + probe) & (RAVA_STATIC_HASH_SIZE - 1);
int idx = table->hash_table[slot];
if (idx == -1) {
if (table->count >= table->capacity) {
size_t new_cap = table->capacity * 2;
RavaStaticField_t *new_fields = rava_safe_realloc(table->fields, sizeof(RavaStaticField_t) * new_cap);
if (!new_fields) return;
table->fields = new_fields;
table->capacity = new_cap;
}
table->fields[table->count].class_name = strdup(class_name);
table->fields[table->count].field_name = strdup(field_name);
table->fields[table->count].value = value;
table->hash_table[slot] = (int)table->count;
table->count++;
return;
}
if ((size_t)idx < table->count &&
strcmp(table->fields[idx].class_name, class_name) == 0 &&
strcmp(table->fields[idx].field_name, field_name) == 0) {
table->fields[idx].value = value;
return;
}
}
}
+97
View File
@@ -0,0 +1,97 @@
#include "runtime_internal.h"
RavaValue_t rava_value_string(const char *str) {
RavaValue_t val;
val.type = RAVA_VAL_STRING;
val.data.string_val = str ? strdup(str) : NULL;
return val;
}
const char* rava_value_as_string(RavaValue_t value) {
if (value.type == RAVA_VAL_STRING) {
return value.data.string_val ? value.data.string_val : "";
}
return "";
}
char* _rava_get_string_buffer(RavaVM_t *vm, size_t needed) {
if (needed >= RAVA_STRING_BUFFER_SIZE) {
return malloc(needed);
}
char *buf = vm->string_pool.buffers[vm->string_pool.current];
vm->string_pool.current = (vm->string_pool.current + 1) % RAVA_STRING_BUFFER_COUNT;
return buf;
}
void _rava_object_set_field_vm(RavaObject_t *obj, const char *name, RavaValue_t value, RavaVM_t *vm) {
if (!obj || !name) return;
uint32_t hash = _rava_field_hash(name);
for (size_t probe = 0; probe < RAVA_OBJECT_HASH_SIZE; probe++) {
uint32_t idx = (hash + probe) & (RAVA_OBJECT_HASH_SIZE - 1);
int field_idx = obj->field_hash[idx];
if (field_idx == -1) {
if (obj->field_count >= obj->field_capacity) {
size_t new_cap = obj->field_capacity * 2;
char **new_names = rava_safe_realloc(obj->field_names, new_cap * sizeof(char*));
RavaValue_t *new_values = rava_safe_realloc(obj->field_values, new_cap * sizeof(RavaValue_t));
if (!new_names || !new_values) return;
obj->field_names = new_names;
obj->field_values = new_values;
obj->field_capacity = new_cap;
}
obj->field_names[obj->field_count] = (char*)(vm ? _rava_intern_string(vm, name) : strdup(name));
obj->field_values[obj->field_count] = value;
obj->field_hash[idx] = (int)obj->field_count;
obj->field_count++;
return;
}
if ((size_t)field_idx < obj->field_count &&
strcmp(obj->field_names[field_idx], name) == 0) {
obj->field_values[field_idx] = value;
return;
}
}
}
int64_t rava_value_as_int(RavaValue_t value) {
switch (value.type) {
case RAVA_VAL_INT: return value.data.int_val;
case RAVA_VAL_LONG: return value.data.long_val;
case RAVA_VAL_FLOAT: return (int64_t)value.data.float_val;
case RAVA_VAL_DOUBLE: return (int64_t)value.data.double_val;
case RAVA_VAL_BOOLEAN: return value.data.bool_val ? 1 : 0;
case RAVA_VAL_CHAR: return value.data.char_val;
default: return 0;
}
}
int64_t rava_value_as_long(RavaValue_t value) {
switch (value.type) {
case RAVA_VAL_INT: return value.data.int_val;
case RAVA_VAL_LONG: return value.data.long_val;
case RAVA_VAL_FLOAT: return (int64_t)value.data.float_val;
case RAVA_VAL_DOUBLE: return (int64_t)value.data.double_val;
default: return 0;
}
}
double rava_value_as_double(RavaValue_t value) {
switch (value.type) {
case RAVA_VAL_INT: return value.data.int_val;
case RAVA_VAL_LONG: return (double)value.data.long_val;
case RAVA_VAL_FLOAT: return value.data.float_val;
case RAVA_VAL_DOUBLE: return value.data.double_val;
default: return 0.0;
}
}
bool rava_value_as_boolean(RavaValue_t value) {
if (value.type == RAVA_VAL_BOOLEAN) {
return value.data.bool_val;
}
return rava_value_as_int(value) != 0;
}