3static const uint8_t empty_source[] =
"";
10pm_string_sizeof(
void) {
18pm_string_shared_init(
pm_string_t *
string,
const uint8_t *start,
const uint8_t *end) {
22 .type = PM_STRING_SHARED,
24 .length = (size_t) (end - start)
32pm_string_owned_init(
pm_string_t *
string, uint8_t *source,
size_t length) {
34 .type = PM_STRING_OWNED,
44pm_string_constant_init(
pm_string_t *
string,
const char *source,
size_t length) {
46 .type = PM_STRING_CONSTANT,
47 .source = (
const uint8_t *) source,
63} pm_string_file_handle_t;
70pm_string_file_handle_open(pm_string_file_handle_t *handle,
const char *filepath) {
71 int length = MultiByteToWideChar(CP_UTF8, 0, filepath, -1, NULL, 0);
74 const size_t path_size =
sizeof(WCHAR) * ((
size_t) length);
75 handle->path =
xmalloc(path_size);
76 if ((handle->path == NULL) || (MultiByteToWideChar(CP_UTF8, 0, filepath, -1, handle->path, length) == 0)) {
77 xfree_sized(handle->path, path_size);
81 handle->file = CreateFileW(handle->path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL);
82 if (handle->file == INVALID_HANDLE_VALUE) {
85 if (GetLastError() == ERROR_ACCESS_DENIED) {
86 DWORD attributes = GetFileAttributesW(handle->path);
87 if ((attributes != INVALID_FILE_ATTRIBUTES) && (attributes & FILE_ATTRIBUTE_DIRECTORY)) {
92 xfree_sized(handle->path, path_size);
103pm_string_file_handle_close(pm_string_file_handle_t *handle) {
105 CloseHandle(handle->file);
124 pm_string_file_handle_t handle;
129 DWORD file_size = GetFileSize(handle.file, NULL);
130 if (file_size == INVALID_FILE_SIZE) {
131 pm_string_file_handle_close(&handle);
137 if (file_size == 0) {
138 pm_string_file_handle_close(&handle);
139 *
string = (
pm_string_t) { .type = PM_STRING_CONSTANT, .source = empty_source, .length = 0 };
144 HANDLE mapping = CreateFileMapping(handle.file, NULL, PAGE_READONLY, 0, 0, NULL);
145 if (mapping == NULL) {
146 pm_string_file_handle_close(&handle);
151 uint8_t *source = (uint8_t *) MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, 0);
152 CloseHandle(mapping);
153 pm_string_file_handle_close(&handle);
155 if (source == NULL) {
159 *
string = (
pm_string_t) { .type = PM_STRING_MAPPED, .source = source, .length = (size_t) file_size };
161#elif defined(_POSIX_MAPPED_FILES)
163 int fd = open(filepath, O_RDONLY);
170 if (fstat(fd, &sb) == -1) {
176 if (S_ISDIR(sb.st_mode)) {
182 size_t size = (size_t) sb.st_size;
183 uint8_t *source = NULL;
187 *
string = (
pm_string_t) { .type = PM_STRING_CONSTANT, .source = empty_source, .length = 0 };
191 source = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
192 if (source == MAP_FAILED) {
198 *
string = (
pm_string_t) { .type = PM_STRING_MAPPED, .source = source, .length = size };
214 pm_string_file_handle_t handle;
219 const DWORD file_size = GetFileSize(handle.file, NULL);
220 if (file_size == INVALID_FILE_SIZE) {
221 pm_string_file_handle_close(&handle);
227 if (file_size == 0) {
228 pm_string_file_handle_close(&handle);
229 *
string = (
pm_string_t) { .type = PM_STRING_CONSTANT, .source = empty_source, .length = 0 };
234 uint8_t *source =
xmalloc(file_size);
235 if (source == NULL) {
236 pm_string_file_handle_close(&handle);
242 if (!ReadFile(handle.file, source, file_size, &bytes_read, NULL)) {
243 pm_string_file_handle_close(&handle);
248 if (bytes_read != file_size) {
249 xfree_sized(source, file_size);
250 pm_string_file_handle_close(&handle);
254 pm_string_file_handle_close(&handle);
255 *
string = (
pm_string_t) { .type = PM_STRING_OWNED, .source = source, .length = (size_t) file_size };
257#elif defined(PRISM_HAS_FILESYSTEM)
259 int fd = open(filepath, O_RDONLY);
266 if (fstat(fd, &sb) == -1) {
272 if (S_ISDIR(sb.st_mode)) {
278 size_t size = (size_t) sb.st_size;
281 *
string = (
pm_string_t) { .type = PM_STRING_CONSTANT, .source = empty_source, .length = 0 };
285 const size_t length = (size_t) size;
286 uint8_t *source =
xmalloc(length);
287 if (source == NULL) {
292 long bytes_read = (long) read(fd, source, length);
295 if (bytes_read == -1) {
296 xfree_sized(source, length);
300 *
string = (
pm_string_t) { .type = PM_STRING_OWNED, .source = source, .length = length };
305 perror(
"pm_string_file_init is not implemented for this platform");
316 if (string->
type == PM_STRING_OWNED)
return;
321 uint8_t *memory =
xmalloc(length);
324 pm_string_owned_init(
string, memory, length);
325 memcpy((
void *) string->
source, source, length);
339 if (left_length < right_length) {
341 }
else if (left_length > right_length) {
353 return string->length;
361 return string->source;
369 void *memory = (
void *) string->
source;
371 if (string->
type == PM_STRING_OWNED) {
374 }
else if (string->
type == PM_STRING_MAPPED && string->
length) {
376 UnmapViewOfFile(memory);
377#elif defined(_POSIX_MAPPED_FILES)
378 munmap(memory, string->
length);
#define xfree
Old name of ruby_xfree.
#define xmalloc
Old name of ruby_xmalloc.
PRISM_EXPORTED_FUNCTION size_t pm_string_length(const pm_string_t *string)
Returns the length associated with the string.
PRISM_EXPORTED_FUNCTION const uint8_t * pm_string_source(const pm_string_t *string)
Returns the start pointer associated with the string.
PRISM_EXPORTED_FUNCTION pm_string_init_result_t pm_string_mapped_init(pm_string_t *string, const char *filepath)
Read the file indicated by the filepath parameter into source and load its contents and size into the...
PRISM_EXPORTED_FUNCTION void pm_string_free(pm_string_t *string)
Free the associated memory of the given string.
PRISM_EXPORTED_FUNCTION pm_string_init_result_t pm_string_file_init(pm_string_t *string, const char *filepath)
Read the file indicated by the filepath parameter into source and load its contents and size into the...
A generic string type that can have various ownership semantics.
pm_string_init_result_t
Represents the result of calling pm_string_mapped_init or pm_string_file_init.
@ PM_STRING_INIT_SUCCESS
Indicates that the string was successfully initialized.
@ PM_STRING_INIT_ERROR_GENERIC
Indicates a generic error from a string_*_init function, where the type of error should be read from ...
@ PM_STRING_INIT_ERROR_DIRECTORY
Indicates that the file that was attempted to be opened was a directory.
#define PRISM_EXPORTED_FUNCTION
By default, we compile with -fvisibility=hidden.
A generic string type that can have various ownership semantics.
const uint8_t * source
A pointer to the start of the string.
size_t length
The length of the string in bytes of memory.
enum pm_string_t::@105 type
The type of the string.