Conversion functions

This commit is contained in:
2026-09-12 10:08:59 -05:00
parent fd010ec112
commit 838861aeea
3 changed files with 377 additions and 2 deletions
+135
View File
@@ -1,6 +1,47 @@
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include "malunal/strview.h"
#define STRVIEW_NUMBUF_SIZE 64
static
malunal_cstr_t
describe(malunal_int32_t code) {
switch (code) {
case STRVIEW_ERROR_NULL_INPUT:
return "String view input was null.";
case STRVIEW_ERROR_OUT_OF_RANGE:
return "Conversion of string view to value was out of range.";
case STRVIEW_ERROR_UNCONSUMED:
return "String view was not consumed fully during conversion.";
}
return "Unknown strview error";
}
const error_domain_t ERROR_DOMAIN_STRVIEW_T = {
.describe = &describe,
.name = "malunal.strview.error"
};
static malunal_size_t
strview__copy_to_buffer(
strview_iptr_t self,
malunal_char_t buffer[STRVIEW_NUMBUF_SIZE]
) {
malunal_size_t length = strview_length(self);
malunal_size_t copied =
length >= STRVIEW_NUMBUF_SIZE - 1
? STRVIEW_NUMBUF_SIZE - 1
: length;
if (copied > 0)
memcpy(buffer, self->beg, copied);
buffer[copied] = '\0';
return copied;
}
strview_t
strview(
@@ -178,3 +219,97 @@ strview_contains(
return false;
}
error_t
strview_to_int64(
strview_iptr_t self,
malunal_int64_t* out
) {
if (self == null) {
if (out != null)
*out = 0;
return (error_t) {
.domain = &ERROR_DOMAIN_STRVIEW_T,
.code = STRVIEW_ERROR_NULL_INPUT
};
}
malunal_char_t buffer[STRVIEW_NUMBUF_SIZE];
malunal_size_t copied = strview__copy_to_buffer(self, buffer);
if (copied == 0) {
if (out != null)
*out = 0;
return (error_t) {
.domain = &ERROR_DOMAIN_STRVIEW_T,
.code = STRVIEW_ERROR_UNCONSUMED
};
}
malunal_str_t endptr;
malunal_int64_t value;
errno = 0;
value = strtoll(buffer, &endptr, 10);
if (out != null)
*out = value;
if (errno == ERANGE)
return (error_t) {
.domain = &ERROR_DOMAIN_STRVIEW_T,
.code = STRVIEW_ERROR_OUT_OF_RANGE
};
return endptr != buffer + copied
? (error_t) {
.domain = &ERROR_DOMAIN_STRVIEW_T,
.code = STRVIEW_ERROR_UNCONSUMED
}
: NO_ERROR;
}
error_t
strview_to_double(
strview_iptr_t self,
malunal_double_t* out
) {
if (self == null) {
if (out != null)
*out = 0.0;
return (error_t) {
.domain = &ERROR_DOMAIN_STRVIEW_T,
.code = STRVIEW_ERROR_NULL_INPUT
};
}
malunal_char_t buffer[STRVIEW_NUMBUF_SIZE];
malunal_size_t copied = strview__copy_to_buffer(self, buffer);
if (copied == 0) {
if (out != null)
*out = 0.0;
return (error_t) {
.domain = &ERROR_DOMAIN_STRVIEW_T,
.code = STRVIEW_ERROR_UNCONSUMED
};
}
malunal_str_t endptr;
malunal_double_t value;
errno = 0;
value = strtod(buffer, &endptr);
if (out != null)
*out = value;
if (errno == ERANGE)
return (error_t) {
.domain = &ERROR_DOMAIN_STRVIEW_T,
.code = STRVIEW_ERROR_OUT_OF_RANGE
};
return endptr != buffer + copied
? (error_t) {
.domain = &ERROR_DOMAIN_STRVIEW_T,
.code = STRVIEW_ERROR_UNCONSUMED
}
: NO_ERROR;
}