19#define PHAROS_SUPPORT_PATH_SEP '\\'
20#define pharos_support_getcwd _getcwd
21#define pharos_support_access _access
22#define pharos_support_stat _stat
23#define pharos_support_strdup _strdup
27#define PHAROS_SUPPORT_PATH_SEP '/'
28#define pharos_support_getcwd getcwd
29#define pharos_support_access access
30#define pharos_support_stat stat
31#define pharos_support_strdup strdup
49 size_t cap = buffer->
cap == 0 ? 4096 : buffer->
cap;
50 if (needed <= buffer->cap) {
53 while (cap < needed) {
54 if (cap > (SIZE_MAX / 2)) {
59 next = (
char *)realloc(buffer->
data, cap);
74 buffer->
data[buffer->
len] =
'\0';
79 char *copy = (
char *)malloc(
len + 1);
83 memcpy(copy, start,
len);
94 while (*start !=
'\0' && isspace((
unsigned char)*start)) {
98 memmove(text, start, strlen(start) + 1);
100 end = text + strlen(text);
101 while (end > text && isspace((
unsigned char)end[-1])) {
108 return strncmp(value, prefix, strlen(prefix)) == 0;
111int streq(
const char *a,
const char *b) {
112 return strcmp(a, b) == 0;
120 if (left == NULL || left[0] ==
'\0') {
123 if (right == NULL || right[0] ==
'\0') {
126 left_len = strlen(left);
127 right_len = strlen(right);
131 joined = (
char *)malloc(left_len + right_len + need_sep + 1);
132 if (joined == NULL) {
135 memcpy(joined, left, left_len);
138 memcpy(joined + left_len + 1, right, right_len + 1);
140 memcpy(joined + left_len, right, right_len + 1);
153 const char *alt = strrchr(path,
'/');
154 if (alt != NULL && (slash == NULL || alt > slash)) {
165 return dup_range(path, (
size_t)(slash - path));
185 return (st.st_mode & _S_IFDIR) != 0;
187 return S_ISDIR(st.st_mode);
199 if (path == NULL || path[0] ==
'\0') {
212 while (*cursor !=
'\0') {
213 const char *segment_start;
214 const char *segment_end;
220 if (*cursor ==
'\0') {
223 segment_start = cursor;
227 segment_end = cursor;
228 segment_len = (size_t)(segment_end - segment_start);
229 if (segment_len == 1 && segment_start[0] ==
'.') {
232 if (segment_len == 2 && segment_start[0] ==
'.' && segment_start[1] ==
'.') {
233 if (buffer.
len > 0) {
234 size_t trim_to = buffer.
len;
242 if (absolute && trim_to == 1) {
244 buffer.
data[1] =
'\0';
246 buffer.
len = trim_to > 0 ? trim_to - (absolute ? 0 : 1) : 0;
250 buffer.
data[buffer.
len] =
'\0';
256 if (buffer.
len > 0) {
263 if (
buffer_append(&buffer, segment_start, segment_len) != 0) {
277 if (
buffer_append(&buffer, segment_start, segment_len) != 0) {
281 previous = buffer.
data;
284 if (buffer.
data == NULL) {
287 if (buffer.
len == 0) {
295 if (value == NULL || value[0] ==
'\0') {
299 if ((strlen(value) > 2 && value[1] ==
':') || value[0] ==
'\\' || value[0] ==
'/') {
303 if (value[0] ==
'/') {
311 char stack_buf[PATH_MAX];
324 file = fopen(path,
"rb");
328 while ((bytes_read = fread(chunk, 1,
sizeof(chunk), file)) > 0) {
void buffer_init(Buffer *buffer)
Initializes a growable buffer to an empty state.
char * path_join(const char *left, const char *right)
Joins two path segments using the native path separator.
void trim_in_place(char *text)
Trims leading and trailing ASCII whitespace from a string in place.
char * dup_range(const char *start, size_t len)
Duplicates a byte range into a newly allocated NUL-terminated string.
char * path_canonicalize(const char *path)
Normalizes a path by collapsing redundant separators and dot segments.
void buffer_free(Buffer *buffer)
Releases memory owned by a growable buffer.
char * current_working_directory(void)
Returns the current working directory.
int streq(const char *a, const char *b)
Tests whether two strings are exactly equal.
int path_is_directory(const char *path)
Tests whether a filesystem path refers to a directory.
char * path_dirname(const char *path)
Returns the parent directory component of a path.
char * resolve_relative_to(const char *base_dir, const char *value)
Resolves a path value relative to a base directory when needed.
int buffer_append(Buffer *buffer, const void *data, size_t len)
Appends bytes to a growable buffer and maintains a trailing NUL byte.
#define pharos_support_access
int buffer_reserve(Buffer *buffer, size_t needed)
Ensures a buffer can hold at least a requested number of bytes.
int path_is_writable(const char *path)
Tests whether a filesystem path is writable by the current process.
#define pharos_support_getcwd
#define pharos_support_stat
#define PHAROS_SUPPORT_PATH_SEP
#define pharos_support_strdup
char * read_file_text(const char *path)
Reads an entire file into a newly allocated text buffer.
int starts_with(const char *value, const char *prefix)
Tests whether one string starts with another string.
int path_exists(const char *path)
Tests whether a filesystem path currently exists.
Declares shared low-level support helpers used across the Pharos native runtime.
Growable byte buffer used by parsing and string assembly helpers.