}
#endif // _di_f_conversion_character_is_decimal_
+#ifndef _di_f_conversion_character_is_duodecimal_
+ f_return_status f_conversion_character_is_duodecimal(const int8_t character) {
+
+ if (character > 0x29 && character < 0x40) {
+ return f_true;
+ }
+
+ if (character == 0x41 || character == 0x42) {
+ return f_true;
+ }
+
+ if (character == 0x61 || character == 0x62) {
+ return f_true;
+ }
+
+ return f_false;
+ }
+#endif // _di_f_conversion_character_is_duodecimal_
+
#ifndef _di_f_conversion_character_is_hexidecimal_
f_return_status f_conversion_character_is_hexidecimal(const int8_t character) {
}
#endif // _di_f_conversion_character_to_decimal_
+#ifndef _di_f_conversion_character_to_duodecimal_
+ f_return_status f_conversion_character_to_duodecimal(const int8_t character, uint64_t *decimal) {
+ #ifndef _di_level_0_parameter_checking_
+ if (decimal == 0) return f_status_set_error(f_invalid_parameter);
+ #endif // _di_level_0_parameter_checking_
+
+ switch (character) {
+ case 0x30: *decimal = 0; break;
+ case 0x31: *decimal = 1; break;
+ case 0x32: *decimal = 2; break;
+ case 0x33: *decimal = 3; break;
+ case 0x34: *decimal = 4; break;
+ case 0x35: *decimal = 5; break;
+ case 0x36: *decimal = 6; break;
+ case 0x37: *decimal = 7; break;
+ case 0x38: *decimal = 8; break;
+ case 0x39: *decimal = 9; break;
+ case 0x41: *decimal = 10; break;
+ case 0x42: *decimal = 11; break;
+ case 0x61: *decimal = 10; break;
+ case 0x62: *decimal = 11; break;
+ default:
+ return f_status_set_error(f_invalid_number);
+ }
+
+ return f_none;
+ }
+#endif // _di_f_conversion_character_to_duodecimal_
+
#ifndef _di_f_conversion_character_to_hexidecimal_
f_return_status f_conversion_character_to_hexidecimal(const int8_t character, uint64_t *decimal) {
#ifndef _di_level_0_parameter_checking_
}
#endif // _di_f_conversion_character_to_octal_
+#ifndef _di_f_conversion_string_to_binary_signed_
+ f_return_status f_conversion_string_to_binary_signed(const f_string string, int64_t *number, const f_string_location location, const bool negative) {
+ #ifndef _di_level_0_parameter_checking_
+ if (string == 0) return f_status_set_error(f_invalid_parameter);
+ if (number == 0) return f_status_set_error(f_invalid_parameter);
+ if (location.start < 0) return f_status_set_error(f_invalid_parameter);
+ if (location.stop < location.start) return f_status_set_error(f_invalid_parameter);
+ #endif // _di_level_0_parameter_checking_
+
+ uint8_t scale = 0;
+ uint64_t digit = 0;
+ uint64_t converted = 0;
+
+ for (f_string_length i = location.start; i <= location.stop; i++) {
+ if (f_conversion_character_to_binary(string[i], &digit) == f_none) {
+ if (scale) {
+ scale++;
+
+ if (scale > 63) {
+ return f_status_set_error(f_overflow);
+ }
+
+ if (negative) {
+ if (scale > 63) {
+ return f_status_set_error(f_underflow);
+ }
+
+ converted <<= 1;
+ converted -= digit;
+ }
+ else {
+ if (scale > 63) {
+ return f_status_set_error(f_overflow);
+ }
+
+ converted <<= 1;
+ converted += digit;
+ }
+ }
+ else if (digit != 0) {
+ scale = 1;
+
+ if (negative) {
+ converted = 0 - digit;
+ }
+ else {
+ converted = digit;
+ }
+ }
+ }
+ else if (string[i] != '\0') {
+ return f_status_set_error(f_invalid_number);
+ }
+ } // for
+
+ *number = converted;
+ return f_none;
+ }
+#endif // _di_f_conversion_string_to_binary_signed_
+
#ifndef _di_f_conversion_string_to_binary_unsigned_
f_return_status f_conversion_string_to_binary_unsigned(const f_string string, uint64_t *number, const f_string_location location) {
#ifndef _di_level_0_parameter_checking_
if (location.stop < location.start) return f_status_set_error(f_invalid_parameter);
#endif // _di_level_0_parameter_checking_
- bool scale = 0;
+ uint8_t scale = 0;
uint64_t digit = 0;
uint64_t converted = 0;
- // @todo: needs overflow/underflow detection.
for (f_string_length i = location.start; i <= location.stop; i++) {
if (f_conversion_character_to_binary(string[i], &digit) == f_none) {
if (scale) {
+ scale++;
+
+ if (scale > 64) {
+ return f_status_set_error(f_overflow);
+ }
+
converted <<= 1;
converted += digit;
}
converted = digit;
}
}
- else {
+ else if (string[i] != '\0') {
return f_status_set_error(f_invalid_number);
}
} // for
}
#endif // _di_f_conversion_string_to_binary_unsigned_
+#ifndef _di_f_conversion_string_to_decimal_signed_
+ f_return_status f_conversion_string_to_decimal_signed(const f_string string, int64_t *number, const f_string_location location, const bool negative) {
+ #ifndef _di_level_0_parameter_checking_
+ if (string == 0) return f_status_set_error(f_invalid_parameter);
+ if (number == 0) return f_status_set_error(f_invalid_parameter);
+ if (location.start < 0) return f_status_set_error(f_invalid_parameter);
+ if (location.stop < location.start) return f_status_set_error(f_invalid_parameter);
+ #endif // _di_level_0_parameter_checking_
+
+ uint8_t scale = 0;
+ uint64_t digit = 0;
+ uint64_t converted = 0;
+
+ for (f_string_length i = location.start; i <= location.stop; i++) {
+ if (f_conversion_character_to_decimal(string[i], &digit) == f_none) {
+
+ if (scale) {
+ scale++;
+
+ if (negative) {
+ if (scale > 18) {
+ if ((converted * 10) - digit < LLONG_MIN || (converted * 10) - digit > converted) {
+ return f_status_set_error(f_underflow);
+ }
+ }
+
+ converted *= 10;
+ converted -= digit;
+ }
+ else {
+ if (scale > 18) {
+ if ((converted * 10) + digit > LLONG_MAX || (converted * 10) + digit < converted) {
+ return f_status_set_error(f_overflow);
+ }
+ }
+
+ converted *= 10;
+ converted += digit;
+ }
+ }
+ else if (digit != 0) {
+ scale = 1;
+
+ if (negative) {
+ converted = 0 - digit;
+ }
+ else {
+ converted = digit;
+ }
+ }
+ }
+ else if (string[i] != '\0') {
+ return f_status_set_error(f_invalid_number);
+ }
+ } // for
+
+ *number = converted;
+ return f_none;
+ }
+#endif // _di_f_conversion_string_to_decimal_signed_
+
#ifndef _di_f_conversion_string_to_decimal_unsigned_
f_return_status f_conversion_string_to_decimal_unsigned(const f_string string, uint64_t *number, const f_string_location location) {
#ifndef _di_level_0_parameter_checking_
if (location.stop < location.start) return f_status_set_error(f_invalid_parameter);
#endif // _di_level_0_parameter_checking_
- bool scale = 0;
+ uint8_t scale = 0;
uint64_t digit = 0;
uint64_t converted = 0;
- // @todo: needs overflow/underflow detection.
for (f_string_length i = location.start; i <= location.stop; i++) {
if (f_conversion_character_to_decimal(string[i], &digit) == f_none) {
if (scale) {
+ scale++;
+
+ if (scale > 18) {
+ if ((converted * 10) + digit > ULLONG_MAX || (converted * 10) + digit < converted) {
+ return f_status_set_error(f_overflow);
+ }
+ }
+
converted *= 10;
converted += digit;
}
converted = digit;
}
}
- else {
+ else if (string[i] != '\0') {
return f_status_set_error(f_invalid_number);
}
} // for
}
#endif // _di_f_conversion_string_to_decimal_unsigned_
+#ifndef _di_f_conversion_string_to_duodecimal_signed_
+ f_return_status f_conversion_string_to_duodecimal_signed(const f_string string, int64_t *number, const f_string_location location, const bool negative) {
+ #ifndef _di_level_0_parameter_checking_
+ if (string == 0) return f_status_set_error(f_invalid_parameter);
+ if (number == 0) return f_status_set_error(f_invalid_parameter);
+ if (location.start < 0) return f_status_set_error(f_invalid_parameter);
+ if (location.stop < location.start) return f_status_set_error(f_invalid_parameter);
+ #endif // _di_level_0_parameter_checking_
+
+ uint8_t scale = 0;
+ uint64_t digit = 0;
+ uint64_t converted = 0;
+
+ for (f_string_length i = location.start; i <= location.stop; i++) {
+ if (f_conversion_character_to_duodecimal(string[i], &digit) == f_none) {
+
+ if (scale) {
+ scale++;
+
+ if (negative) {
+ if (scale > 15) {
+ if ((converted * 12) - digit < LLONG_MIN || (converted * 12) - digit > converted) {
+ return f_status_set_error(f_underflow);
+ }
+ }
+
+ converted *= 12;
+ converted -= digit;
+ }
+ else {
+ if (scale > 15) {
+ if ((converted * 12) + digit > LLONG_MAX || (converted * 12) + digit < converted) {
+ return f_status_set_error(f_overflow);
+ }
+ }
+
+ converted *= 12;
+ converted += digit;
+ }
+ }
+ else if (digit != 0) {
+ scale = 1;
+
+ if (negative) {
+ converted = 0 - digit;
+ }
+ else {
+ converted = digit;
+ }
+ }
+ }
+ else if (string[i] != '\0') {
+ return f_status_set_error(f_invalid_number);
+ }
+ } // for
+
+ *number = converted;
+ return f_none;
+ }
+#endif // _di_f_conversion_string_to_duodecimal_signed_
+
+#ifndef _di_f_conversion_string_to_duodecimal_unsigned_
+ f_return_status f_conversion_string_to_duodecimal_unsigned(const f_string string, uint64_t *number, const f_string_location location) {
+ #ifndef _di_level_0_parameter_checking_
+ if (string == 0) return f_status_set_error(f_invalid_parameter);
+ if (number == 0) return f_status_set_error(f_invalid_parameter);
+ if (location.start < 0) return f_status_set_error(f_invalid_parameter);
+ if (location.stop < location.start) return f_status_set_error(f_invalid_parameter);
+ #endif // _di_level_0_parameter_checking_
+
+ uint8_t scale = 0;
+ uint64_t digit = 0;
+ uint64_t converted = 0;
+
+ for (f_string_length i = location.start; i <= location.stop; i++) {
+ if (f_conversion_character_to_duodecimal(string[i], &digit) == f_none) {
+
+ if (scale) {
+ scale++;
+
+ if (scale > 16) {
+ if ((converted * 12) + digit > ULLONG_MAX || (converted * 12) + digit < converted) {
+ return f_status_set_error(f_overflow);
+ }
+ }
+
+ converted *= 12;
+ converted += digit;
+ }
+ else if (digit != 0) {
+ scale = 1;
+ converted = digit;
+ }
+ }
+ else if (string[i] != '\0') {
+ return f_status_set_error(f_invalid_number);
+ }
+ } // for
+
+ *number = converted;
+ return f_none;
+ }
+#endif // _di_f_conversion_string_to_duodecimal_unsigned_
+
+#ifndef _di_f_conversion_string_to_hexidecimal_signed_
+ f_return_status f_conversion_string_to_hexidecimal_signed(const f_string string, int64_t *number, const f_string_location location, const bool negative) {
+ #ifndef _di_level_0_parameter_checking_
+ if (string == 0) return f_status_set_error(f_invalid_parameter);
+ if (number == 0) return f_status_set_error(f_invalid_parameter);
+ if (location.start < 0) return f_status_set_error(f_invalid_parameter);
+ if (location.stop < location.start) return f_status_set_error(f_invalid_parameter);
+ #endif // _di_level_0_parameter_checking_
+
+ uint8_t scale = 0;
+ uint64_t digit = 0;
+ uint64_t converted = 0;
+
+ for (f_string_length i = location.start; i <= location.stop; i++) {
+ if (f_conversion_character_to_hexidecimal(string[i], &digit) == f_none) {
+
+ if (scale) {
+ scale++;
+
+ if (negative) {
+ if (scale > 15) {
+ if ((converted << 4) - digit < LLONG_MIN || (converted << 4) - digit > converted) {
+ return f_status_set_error(f_underflow);
+ }
+ }
+
+ converted <<= 4;
+ converted -= digit;
+ }
+ else {
+ if (scale > 15) {
+ if ((converted << 4) + digit > LLONG_MAX || (converted << 4) + digit < converted) {
+ return f_status_set_error(f_overflow);
+ }
+ }
+
+ converted <<= 4;
+ converted += digit;
+ }
+ }
+ else if (digit != 0) {
+ scale = 1;
+
+ if (negative) {
+ converted = 0 - digit;
+ }
+ else {
+ converted = digit;
+ }
+ }
+ }
+ else if (string[i] != '\0') {
+ return f_status_set_error(f_invalid_number);
+ }
+ } // for
+
+ *number = converted;
+ return f_none;
+ }
+#endif // _di_f_conversion_string_to_hexidecimal_signed_
+
#ifndef _di_f_conversion_string_to_hexidecimal_unsigned_
f_return_status f_conversion_string_to_hexidecimal_unsigned(const f_string string, uint64_t *number, const f_string_location location) {
#ifndef _di_level_0_parameter_checking_
if (location.stop < location.start) return f_status_set_error(f_invalid_parameter);
#endif // _di_level_0_parameter_checking_
- bool scale = 0;
+ uint8_t scale = 0;
uint64_t digit = 0;
uint64_t converted = 0;
- // @todo: needs overflow/underflow detection.
for (f_string_length i = location.start; i <= location.stop; i++) {
if (f_conversion_character_to_hexidecimal(string[i], &digit) == f_none) {
if (scale) {
+ scale++;
+
+ if (scale > 16) {
+ return f_status_set_error(f_overflow);
+ }
+
converted <<= 4;
converted += digit;
}
converted = digit;
}
}
- else {
+ else if (string[i] != '\0') {
return f_status_set_error(f_invalid_number);
}
} // for
}
#endif // _di_f_conversion_string_to_hexidecimal_unsigned_
+#ifndef _di_f_conversion_string_to_octal_signed_
+ f_return_status f_conversion_string_to_octal_signed(const f_string string, int64_t *number, const f_string_location location, const bool negative) {
+ #ifndef _di_level_0_parameter_checking_
+ if (string == 0) return f_status_set_error(f_invalid_parameter);
+ if (number == 0) return f_status_set_error(f_invalid_parameter);
+ if (location.start < 0) return f_status_set_error(f_invalid_parameter);
+ if (location.stop < location.start) return f_status_set_error(f_invalid_parameter);
+ #endif // _di_level_0_parameter_checking_
+
+ uint8_t scale = 0;
+ uint64_t digit = 0;
+ uint64_t converted = 0;
+
+ for (f_string_length i = location.start; i <= location.stop; i++) {
+ if (f_conversion_character_to_octal(string[i], &digit) == f_none) {
+
+ if (scale) {
+ scale++;
+
+ if (negative) {
+ if (scale > 19) {
+ if ((converted << 3) - digit < LLONG_MIN || (converted << 3) - digit > converted) {
+ return f_status_set_error(f_underflow);
+ }
+ }
+
+ converted <<= 3;
+ converted -= digit;
+ }
+ else {
+ if (scale > 19) {
+ if ((converted << 3) + digit > LLONG_MAX || (converted << 3) + digit < converted) {
+ return f_status_set_error(f_overflow);
+ }
+ }
+
+ converted <<= 3;
+ converted += digit;
+ }
+ }
+ else if (digit != 0) {
+ scale = 1;
+
+ if (negative) {
+ converted = 0 - digit;
+ }
+ else {
+ converted = digit;
+ }
+ }
+ }
+ else if (string[i] != '\0') {
+ return f_status_set_error(f_invalid_number);
+ }
+ } // for
+
+ *number = converted;
+ return f_none;
+ }
+#endif // _di_f_conversion_string_to_octal_signed_
+
#ifndef _di_f_conversion_string_to_octal_unsigned_
f_return_status f_conversion_string_to_octal_unsigned(const f_string string, uint64_t *number, const f_string_location location) {
#ifndef _di_level_0_parameter_checking_
if (location.stop < location.start) return f_status_set_error(f_invalid_parameter);
#endif // _di_level_0_parameter_checking_
- bool scale = 0;
+ uint8_t scale = 0;
uint64_t digit = 0;
uint64_t converted = 0;
- // @todo: needs overflow/underflow detection.
for (f_string_length i = location.start; i <= location.stop; i++) {
if (f_conversion_character_to_octal(string[i], &digit) == f_none) {
- // when the scale exists, then we need to make the number larger, for this function the scale is base 8.
if (scale) {
- converted *= 8;
+ scale++;
+
+ if (scale > 20) {
+ if ((converted << 3) + digit > ULLONG_MAX || (converted << 3) + digit < converted) {
+ return f_status_set_error(f_overflow);
+ }
+ }
+
+ converted <<= 3;
converted += digit;
}
else if (digit != 0) {
converted = digit;
}
}
- else {
+ else if (string[i] != '\0') {
return f_status_set_error(f_invalid_number);
}
} // for
}
#endif // _di_f_conversion_string_to_octal_unsigned_
+#ifndef _di_f_conversion_string_to_number_signed_
+ f_return_status f_conversion_string_to_number_signed(const f_string string, int64_t *number, const f_string_location location) {
+ #ifndef _di_level_0_parameter_checking_
+ if (string == 0) return f_status_set_error(f_invalid_parameter);
+ if (number == 0) return f_status_set_error(f_invalid_parameter);
+ if (location.start < 0) return f_status_set_error(f_invalid_parameter);
+ if (location.stop < location.start) return f_status_set_error(f_invalid_parameter);
+ #endif // _di_level_0_parameter_checking_
+
+ uint8_t width = 0;
+ uint8_t width_max = 0;
+ uint8_t mode = 0;
+ int8_t vector = 0; // 0 for assumed positive, 1 for explicit positive, -1 for negative.
+ f_string_length j = 0;
+ f_string_length offset = 0;
+ f_status status = f_none;
+
+ for (f_string_length i = location.start; i <= location.stop; i++) {
+ width = f_macro_utf_byte_width_is(string[i]);
+
+ if (width == 0) {
+ if (isspace(string[i])) {
+ if (mode == 0 && vector == 0) {
+ offset++;
+ continue;
+ }
+
+ return f_status_set_error(f_invalid_number);
+ }
+ }
+ else {
+ if (mode == 0 && vector == 0) {
+ width_max = (location.stop - i) + 1;
+
+ status = f_utf_is_whitespace(string + i, width_max);
+
+ if (status == f_true) {
+ offset = i + 1;
+ continue;
+ }
+
+ if (f_status_is_error(status)) {
+ if (status == f_status_set_error(f_maybe)) {
+ status = f_status_set_error(f_incomplete_utf);
+ }
+
+ return status;
+ }
+ }
+
+ return f_status_set_error(f_invalid_number);
+ }
+
+ if (string[i] == 0x30) {
+ j = i + 1;
+
+ // immediate next value must be either '0', 'x', 'X', 'd', 'D', 'o', 'O', 'b', or 'B'.
+ if (j > location.stop) {
+ *number = 0;
+ return f_none;
+ }
+ else if (string[j] == 0x30) {
+ mode = 10;
+ }
+ else if (string[j] == 0x78 || string[j] == 0x58) {
+ mode = 16;
+ offset += 2;
+ }
+ else if (string[j] == 0x44 || string[j] == 0x64) {
+ mode = 12;
+ offset += 2;
+ }
+ else if (string[j] == 0x6f || string[j] == 0x4f) {
+ mode = 8;
+ offset += 2;
+ }
+ else if (string[j] == 0x62 || string[j] == 0x42) {
+ mode = 2;
+ offset += 2;
+ }
+ else {
+ return f_status_set_error(f_invalid_number);
+ }
+
+ break;
+ }
+
+ // plus sign is only allowed as the first non-whitespace character.
+ if (string[i] == 0x2b) {
+ if (mode == 0 && vector == 0) {
+ vector = 1;
+ offset++;
+ }
+ else {
+ return f_status_set_error(f_invalid_number);
+ }
+ }
+
+ // negative sign is not allowed.
+ if (string[i] == 0x2d) {
+ if (mode == 0 && vector == 0) {
+ vector = -1;
+ offset++;
+ }
+ else {
+ return f_status_set_error(f_invalid_number);
+ }
+ }
+
+ if (f_conversion_character_is_decimal(string[i]) == f_true) {
+ mode = 10;
+ break;
+ }
+
+ return f_status_set_error(f_negative_number);
+ } // for
+
+ if (mode == 0) {
+ return f_no_data;
+ }
+
+ f_string_location location_offset = f_string_location_initialize;
+ location_offset.start = location.start + offset;
+ location_offset.stop = location.stop;
+
+ if (mode == 10) {
+ return f_conversion_string_to_decimal_signed(string, number, location_offset, vector == -1);
+ }
+
+ if (mode == 16) {
+ return f_conversion_string_to_hexidecimal_signed(string, number, location_offset, vector == -1);
+ }
+
+ if (mode == 12) {
+ return f_conversion_string_to_duodecimal_signed(string, number, location_offset, vector == -1);
+ }
+
+ if (mode == 8) {
+ return f_conversion_string_to_octal_signed(string, number, location_offset, vector == -1);
+ }
+
+ return f_conversion_string_to_binary_signed(string, number, location_offset, vector == -1);
+ }
+#endif // _di_f_conversion_string_to_number_signed_
+
#ifndef _di_f_conversion_string_to_number_unsigned_
f_return_status f_conversion_string_to_number_unsigned(const f_string string, uint64_t *number, const f_string_location location) {
#ifndef _di_level_0_parameter_checking_
if (location.stop < location.start) return f_status_set_error(f_invalid_parameter);
#endif // _di_level_0_parameter_checking_
- bool scale = 0;
- uint64_t digit = 0;
- uint64_t converted = 0;
uint8_t width = 0;
uint8_t width_max = 0;
uint8_t mode = 0;
if (string[i] == 0x30) {
j = i + 1;
- // immediate next value must be either '0', 'x', 'X', 'o', 'O', 'b', or 'B'.
+ // immediate next value must be either '0', 'x', 'X', 'd', 'D', 'o', 'O', 'b', or 'B'.
if (j > location.stop) {
*number = 0;
return f_none;
mode = 16;
offset += 2;
}
+ else if (string[j] == 0x44 || string[j] == 0x64) {
+ mode = 12;
+ offset += 2;
+ }
else if (string[j] == 0x6f || string[j] == 0x4f) {
mode = 8;
offset += 2;
return f_conversion_string_to_hexidecimal_unsigned(string, number, location_offset);
}
+ if (mode == 12) {
+ return f_conversion_string_to_duodecimal_unsigned(string, number, location_offset);
+ }
+
if (mode == 8) {
return f_conversion_string_to_octal_unsigned(string, number, location_offset);
}
// libc includes
#include <ctype.h>
+#include <limits.h>
#include <stdlib.h>
// fll-0 includes
#endif // _di_f_conversion_character_is_decimal_
/**
+ * Convert a single character into the duodecimal digit that it represents.
+ *
+ * @param character
+ * The character to validate.
+ *
+ * @return
+ * f_true if character is a duodecimal.
+ * f_false if character is not a duodecimal.
+ */
+#ifndef _di_f_conversion_character_is_duodecimal_
+ extern f_return_status f_conversion_character_is_duodecimal(const int8_t character);
+#endif // _di_f_conversion_character_is_duodecimal_
+
+/**
* Convert a single character into the hexidecimal digit that it represents.
*
* @param character
#endif // _di_f_conversion_character_is_octal_
/**
- * Convert a single character into the digit that it represents.
+ * Convert a single character into the binary digit that it represents.
+ *
+ * @param character
+ * The character to convert.
+ * @param number
+ * This will store the value of the converted character.
+ * This value is only changed on success.
+ *
+ * @return
+ * f_none if character was converted to a binary.
+ * f_invalid_number (with error bit) if no conversion was made due to non-binary values being found.
+ * f_invalid_parameter (with error bit) if a parameter is invalid.
+ */
+#ifndef _di_f_conversion_character_to_binary_
+ extern f_return_status f_conversion_character_to_binary(const int8_t character, uint64_t *number);
+#endif // _di_f_conversion_character_to_binary_
+
+/**
+ * Convert a single character into the decimal digit that it represents.
*
* @param character
* The character to convert.
#endif // _di_f_conversion_character_to_decimal_
/**
+ * Convert a single character into the duodecimal digit that it represents.
+ *
+ * @param character
+ * The character to convert.
+ * @param number
+ * This will store the value of the converted character.
+ * This value is only changed on success.
+ *
+ * @return
+ * f_none if character was converted to a duodecimal.
+ * f_invalid_number (with error bit) if no conversion was made due to non-duodecimal values being found.
+ * f_invalid_parameter (with error bit) if a parameter is invalid.
+ */
+#ifndef _di_f_conversion_character_to_duodecimal_
+ extern f_return_status f_conversion_character_to_duodecimal(const int8_t character, uint64_t *number);
+#endif // _di_f_conversion_character_to_duodecimal_
+
+/**
* Convert a single character into the hexidecimal digit that it represents.
*
* @param character
#endif // _di_f_conversion_character_to_octal_
/**
+ * Convert a series of positive or negative binary number characters into a int64_t.
+ *
+ * This will stop at one of the following: location.stop or a non-digit.
+ * This will ignore NULL values.
+ * This will not process signed statuses (+/-).
+ *
+ * @param string
+ * The string to convert.
+ * @param number
+ * This will store the value of the converted string.
+ * This value is only changed on success.
+ * @param location
+ * The start/stop range to convert.
+ * @param negative
+ * Set to 0 to treat string as a positive number, 1 for as a negative number.
+ *
+ * @return
+ * f_none if the binary string was converted to an signed long.
+ * f_invalid_number (with error bit) if no conversion was made due to non-binary values being found.
+ * f_invalid_parameter (with error bit) if a parameter is invalid.
+ * f_overflow (with error bit) on integer overflow.
+ * f_underflow (with error bit) on integer underflow.
+ */
+#ifndef _di_f_conversion_string_to_binary_signed_
+ extern f_return_status f_conversion_string_to_binary_signed(const f_string string, int64_t *number, const f_string_location location, const bool negative);
+#endif // _di_f_conversion_string_to_binary_signed_
+
+/**
* Convert a series of positive binary number characters into a uint64_t.
*
- * This will stop at one of the following: EOS, location.stop, or a non-digit.
- * This works like atoi, except there is a start/stop range.
+ * This will stop at one of the following: location.stop or a non-digit.
+ * This will ignore NULL values.
* This will not process signed statuses (+/-).
*
* @param string
* f_none if the binary string was converted to an unsigned long.
* f_invalid_number (with error bit) if no conversion was made due to non-binary values being found.
* f_invalid_parameter (with error bit) if a parameter is invalid.
+ * f_overflow (with error bit) on integer overflow.
*/
#ifndef _di_f_conversion_string_to_binary_unsigned_
extern f_return_status f_conversion_string_to_binary_unsigned(const f_string string, uint64_t *number, const f_string_location location);
#endif // _di_f_conversion_string_to_binary_unsigned_
/**
+ * Convert a series of positive or negative decimal number characters into an int64_t.
+ *
+ * This will stop at one of the following: location.stop or a non-digit.
+ * This will ignore NULL values.
+ * This will not process signed statuses (+/-).
+ *
+ * @param string
+ * The string to convert.
+ * @param number
+ * This will store the value of the converted string.
+ * This value is only changed on success.
+ * @param location
+ * The start/stop range to convert.
+ * @param negative
+ * Set to 0 to treat string as a positive number, 1 for as a negative number.
+ *
+ * @return
+ * f_none if the decimal string was converted to an signed long.
+ * f_invalid_number (with error bit) if no conversion was made due to non-decimal values being found.
+ * f_invalid_parameter (with error bit) if a parameter is invalid.
+ * f_overflow (with error bit) on integer overflow.
+ * f_underflow (with error bit) on integer underflow.
+ */
+#ifndef _di_f_conversion_string_to_decimal_signed_
+ extern f_return_status f_conversion_string_to_decimal_signed(const f_string string, int64_t *number, const f_string_location location, const bool negative);
+#endif // _di_f_conversion_string_to_decimal_signed_
+
+/**
* Convert a series of positive decimal number characters into an uint64_t.
*
- * This will stop at one of the following: EOS, location.stop, or a non-digit.
- * This works like atoi, except there is a start/stop range.
+ * This will stop at one of the following: location.stop or a non-digit.
+ * This will ignore NULL values.
* This will not process signed statuses (+/-).
*
* @param string
* f_none if the decimal string was converted to an unsigned long.
* f_invalid_number (with error bit) if no conversion was made due to non-decimal values being found.
* f_invalid_parameter (with error bit) if a parameter is invalid.
+ * f_overflow (with error bit) on integer overflow.
*/
#ifndef _di_f_conversion_string_to_decimal_unsigned_
extern f_return_status f_conversion_string_to_decimal_unsigned(const f_string string, uint64_t *number, const f_string_location location);
#endif // _di_f_conversion_string_to_decimal_unsigned_
/**
+ * Convert a series of positive or negative duodecimal number characters into an int64_t.
+ *
+ * This will stop at one of the following: location.stop or a non-digit.
+ * This will ignore NULL values.
+ * This will not process signed statuses (+/-).
+ *
+ * @param string
+ * The string to convert.
+ * @param number
+ * This will store the value of the converted string.
+ * This value is only changed on success.
+ * @param location
+ * The start/stop range to convert.
+ * @param negative
+ * Set to 0 to treat string as a positive number, 1 for as a negative number.
+ *
+ * @return
+ * f_none if the duodecimal string was converted to an signed long.
+ * f_invalid_number (with error bit) if no conversion was made due to non-duodecimal values being found.
+ * f_invalid_parameter (with error bit) if a parameter is invalid.
+ * f_overflow (with error bit) on integer overflow.
+ * f_underflow (with error bit) on integer underflow.
+ */
+#ifndef _di_f_conversion_string_to_duodecimal_signed_
+ extern f_return_status f_conversion_string_to_duodecimal_signed(const f_string string, int64_t *number, const f_string_location location, const bool negative);
+#endif // _di_f_conversion_string_to_duodecimal_signed_
+
+/**
+ * Convert a series of positive duodecimal number characters into an uint64_t.
+ *
+ * This will stop at one of the following: location.stop or a non-digit.
+ * This will ignore NULL values.
+ * This will not process signed statuses (+/-).
+ *
+ * @param string
+ * The string to convert.
+ * @param number
+ * This will store the value of the converted string.
+ * This value is only changed on success.
+ * @param location
+ * The start/stop range to convert.
+ *
+ * @return
+ * f_none if the duodecimal string was converted to an unsigned long.
+ * f_invalid_number (with error bit) if no conversion was made due to non-duodecimal values being found.
+ * f_invalid_parameter (with error bit) if a parameter is invalid.
+ * f_overflow (with error bit) on integer overflow.
+ */
+#ifndef _di_f_conversion_string_to_duodecimal_unsigned_
+ extern f_return_status f_conversion_string_to_duodecimal_unsigned(const f_string string, uint64_t *number, const f_string_location location);
+#endif // _di_f_conversion_string_to_duodecimal_unsigned_
+
+/**
+ * Convert a series of positive or negative hexidecimal number characters into an int64_t.
+ *
+ * This will stop at one of the following: location.stop or a non-digit.
+ * This will ignore NULL values.
+ * This will not process signed statuses (+/-).
+ *
+ * @param string
+ * The string to convert.
+ * @param number
+ * This will store the value of the converted string.
+ * This value is only changed on success.
+ * @param location
+ * The start/stop range to convert.
+ * @param negative
+ * Set to 0 to treat string as a positive number, 1 for as a negative number.
+ *
+ * @return
+ * f_none if the hexidecimal string was converted to an signed long.
+ * f_invalid_number (with error bit) if no conversion was made due to non-hexidecimal values being found.
+ * f_invalid_parameter (with error bit) if a parameter is invalid.
+ * f_overflow (with error bit) on integer overflow.
+ * f_underflow (with error bit) on integer underflow.
+ */
+#ifndef _di_f_conversion_string_to_hexidecimal_signed_
+ extern f_return_status f_conversion_string_to_hexidecimal_signed(const f_string string, int64_t *number, const f_string_location location, const bool negative);
+#endif // _di_f_conversion_string_to_hexidecimal_signed_
+
+/**
* Convert a series of positive hexidecimal number characters into an uint64_t.
*
- * This will stop at one of the following: EOS, location.stop, or a non-digit.
- * This works like atoi, except there is a start/stop range.
+ * This will stop at one of the following: location.stop or a non-digit.
+ * This will ignore NULL values.
* This will not process signed statuses (+/-).
*
* @param string
* f_none if the hexidecimal string was converted to an unsigned long.
* f_invalid_number (with error bit) if no conversion was made due to non-hexidecimal values being found.
* f_invalid_parameter (with error bit) if a parameter is invalid.
+ * f_overflow (with error bit) on integer overflow.
*/
#ifndef _di_f_conversion_string_to_hexidecimal_unsigned_
extern f_return_status f_conversion_string_to_hexidecimal_unsigned(const f_string string, uint64_t *number, const f_string_location location);
#endif // _di_f_conversion_string_to_hexidecimal_unsigned_
/**
+ * Convert a series of positive or negative octal number characters into an int64_t.
+ *
+ * This will stop at one of the following: location.stop or a non-digit.
+ * This will ignore NULL values.
+ * This will not process signed statuses (+/-).
+ *
+ * @param string
+ * The string to convert.
+ * @param number
+ * This will store the value of the converted string.
+ * This value is only changed on success.
+ * @param location
+ * The start/stop range to convert.
+ * @param negative
+ * Set to 0 to treat string as a positive number, 1 for as a negative number.
+ *
+ * @return
+ * f_none if the octal string was converted to an signed long.
+ * f_invalid_number (with error bit) if no conversion was made due to non-octal values being found.
+ * f_invalid_parameter (with error bit) if a parameter is invalid.
+ * f_overflow (with error bit) on integer overflow.
+ */
+#ifndef _di_f_conversion_string_to_octal_signed_
+ extern f_return_status f_conversion_string_to_octal_signed(const f_string string, int64_t *number, const f_string_location location, const bool negative);
+#endif // _di_f_conversion_string_to_octal_signed_
+
+/**
* Convert a series of positive octal number characters into an uint64_t.
*
- * This will stop at one of the following: EOS, location.stop, or a non-digit.
- * This works like atoi, except there is a start/stop range.
+ * This will stop at one of the following: location.stop or a non-digit.
+ * This will ignore NULL values.
* This will not process signed statuses (+/-).
*
* @param string
* f_none if the octal string was converted to an unsigned long.
* f_invalid_number (with error bit) if no conversion was made due to non-octal values being found.
* f_invalid_parameter (with error bit) if a parameter is invalid.
+ * f_overflow (with error bit) on integer overflow.
*/
#ifndef _di_f_conversion_string_to_octal_unsigned_
extern f_return_status f_conversion_string_to_octal_unsigned(const f_string string, uint64_t *number, const f_string_location location);
#endif // _di_f_conversion_string_to_octal_unsigned_
/**
- * Convert a series of positive number characters into an uint64_t.
+ * Convert a series of positive or negative number characters into an int64_t.
*
- * This will stop at one of the following: EOS, location.stop, or a non-digit.
- * This works like atoi, except there is a start/stop range.
+ * This will stop at one of the following: location.stop or a non-digit.
+ * This will ignore NULL values.
* This will process signed statuses (+/-).
* This will detect based types as follows:
* - hexidecimals begin with either '0x' or '0X'.
+ * - duodecimals begin with either '0d' or '0D'.
+ * - octals begin with either '0o' or '0O'.
+ * - binaries begin with either '0b' or '0B'.
+ * - decimal is used for all other cases.
+ *
+ * Leading 0's and whitespace are ignored.
+ * Whitespace after the first digit is considered invalid.
+ *
+ * This function is similar to strtoll(), but the behavior of error handling and special bases are different.
+ * In particular, octals are specified here with '0b' prefix or '0B' prefix instead of the ridiculous '0' prefix.
+ *
+ * @param string
+ * The string to convert.
+ * @param number
+ * This will store the value of the converted string.
+ * This value is only changed on success.
+ * @param location
+ * The start/stop range to convert.
+ *
+ * @return
+ * f_none on success.
+ * f_no_data is returned if string only contains valid whitespace.
+ * f_invalid_parameter (with error bit) if a parameter is invalid.
+ * f_invalid_number (with error bit) if parameter is not a number.
+ * f_overflow (with error bit) on integer overflow.
+ * f_underflow (with error bit) on integer underflow.
+ * f_incomplete_utf (with error bit) if an incomplete UTF-8 fragment is found.
+ *
+ * @see strtoll()
+ */
+#ifndef _di_f_conversion_string_to_number_signed_
+ extern f_return_status f_conversion_string_to_number_signed(const f_string string, int64_t *number, const f_string_location location);
+#endif // _di_f_conversion_string_to_number_signed_
+
+/**
+ * Convert a series of positive number characters into an uint64_t.
+ *
+ * This will stop at one of the following: location.stop or a non-digit.
+ * This will ignore NULL values.
+ * This will not process signed statuses (+/-).
+ * This will detect based types as follows:
+ * - hexidecimals begin with either '0x' or '0X'.
+ * - duodecimals begin with either '0d' or '0D'.
* - octals begin with either '0o' or '0O'.
* - binaries begin with either '0b' or '0B'.
* - decimal is used for all other cases.
* Leading 0's and whitespace are ignored.
* Whitespace after the first digit is considered invalid.
*
+ * This function is similar to strtoull(), but the behavior of error handling and special bases are different.
+ * In particular, octals are specified here with '0b' prefix or '0B' prefix instead of the ridiculous '0' prefix.
+ * Negative values are reported as such instead of being converted into the unsigned equivalent.
+ *
* @param string
* The string to convert.
* @param number
* f_invalid_parameter (with error bit) if a parameter is invalid.
* f_invalid_number (with error bit) if parameter is not a number.
* f_negative_number (with error bit) on negative value.
- * f_underflow (with error bit) on underflow.
- * f_overflow (with error bit) on overflow.
+ * f_overflow (with error bit) on integer overflow.
* f_incomplete_utf (with error bit) if an incomplete UTF-8 fragment is found.
+ *
+ * @see strtoull()
*/
#ifndef _di_f_conversion_string_to_number_unsigned_
extern f_return_status f_conversion_string_to_number_unsigned(const f_string string, uint64_t *number, const f_string_location location);
extern "C" {
#endif
+#ifndef _fl_console_parameter_to_number_signed_
+ f_return_status fl_console_parameter_to_number_signed(const f_string argument, int64_t *number) {
+ #ifndef _di_level_0_parameter_checking_
+ if (argument == 0) return f_status_set_error(f_invalid_parameter);
+ #endif // _di_level_0_parameter_checking_f
+
+ if (argument[0] == '\0') {
+ return f_no_data;
+ }
+
+ f_string_location location = f_string_location_initialize;
+ location.start = 0;
+ location.stop = strlen(argument) - 1;
+
+ return f_conversion_string_to_number_signed(argument, number, location);
+ }
+#endif // _fl_console_parameter_to_number_signed_
+
+#ifndef _fl_console_parameter_to_number_unsigned_
+ f_return_status fl_console_parameter_to_number_unsigned(const f_string argument, uint64_t *number) {
+ #ifndef _di_level_0_parameter_checking_
+ if (argument == 0) return f_status_set_error(f_invalid_parameter);
+ #endif // _di_level_0_parameter_checking_f
+
+ if (argument[0] == '\0') {
+ return f_no_data;
+ }
+
+ f_string_location location = f_string_location_initialize;
+ location.start = 0;
+ location.stop = strlen(argument) - 1;
+
+ return f_conversion_string_to_number_unsigned(argument, number, location);
+ }
+#endif // _fl_console_parameter_to_number_unsigned_
+
#ifndef _di_fl_console_parameter_process_
f_return_status fl_console_parameter_process(const f_console_arguments arguments, f_console_parameters parameters, f_string_lengths *remaining) {
#ifndef _di_level_1_parameter_checking_
}
#endif // _di_fl_console_parameter_prioritize_
-#ifndef _fl_console_parameter_to_number_unsigned_
- f_return_status fl_console_parameter_to_number_unsigned(const f_string argument, uint64_t *number) {
- #ifndef _di_level_0_parameter_checking_
- if (argument == 0) return f_status_set_error(f_invalid_parameter);
- #endif // _di_level_0_parameter_checking_f
-
- if (argument[0] == '\0') {
- return f_no_data;
- }
-
- f_string_location location = f_string_location_initialize;
- location.start = 0;
- location.stop = strlen(argument) - 1;
-
- f_status status = f_conversion_string_to_number_unsigned(argument, number, location);
-
- return status;
-/*
- errno = 0;
-
- f_string end = 0;
- uint64_t converted = (uint64_t) strtoull(argument, &end, 0);
-
- if (errno == ERANGE) {
- if (converted == LLONG_MAX) {
- return f_status_set_error(f_overflow);
- }
-
- return f_status_set_error(f_invalid_number);
- }
-
- if (*end == '\0') {
- *number = converted;
- return f_none;
- }
-
- return f_status_set_error(f_invalid_number);
-*/
- }
-#endif // _fl_console_parameter_to_number_unsigned_
-
-#ifndef _fl_console_parameter_to_number_signed_
- f_return_status fl_console_parameter_to_number_signed(const f_string argument, int64_t *number) {
- #ifndef _di_level_0_parameter_checking_
- if (argument == 0) return f_status_set_error(f_invalid_parameter);
- #endif // _di_level_0_parameter_checking_f
-
- if (argument[0] == '\0') {
- return f_no_data;
- }
-
- errno = 0;
-
- f_string end = 0;
- int64_t converted = (int64_t) strtoull(argument, &end, 0);
-
- if (errno == ERANGE) {
- if (converted == LLONG_MAX) {
- return f_status_set_error(f_overflow);
- }
-
- if (converted == LLONG_MIN) {
- return f_status_set_error(f_underflow);
- }
-
- return f_status_set_error(f_invalid_number);
- }
-
- if (*end == '\0') {
- *number = converted;
- return f_none;
- }
-
- return f_status_set_error(f_invalid_number);
- }
-#endif // _fl_console_parameter_to_number_signed_
-
#ifdef __cplusplus
} // extern "C"
#endif
#endif
/**
+ * Convert a console parameter additional argument to a signed 64-bit integer.
+ *
+ * This will detect based types as follows:
+ * - hexidecimals begin with either '0x' or '0X'.
+ * - duodecimals begin with either '0d' or '0D'.
+ * - octals begin with either '0o' or '0O'.
+ * - binaries begin with either '0b' or '0B'.
+ * - decimal is used for all other cases.
+ *
+ * Leading 0's and whitespace are ignored.
+ * Whitespace after the first digit is considered invalid.
+ *
+ * @param argv
+ * The argument string expected to be a number.
+ * This is generally passed from the argv[].
+ * @param number
+ * The converted number is stored here.
+ * This only gets modified on success.
+ *
+ * @return
+ * f_none on success.
+ * f_no_data the argument is empty or only contains valid whitespace.
+ * f_invalid_parameter (with error bit) if a parameter is invalid.
+ * f_invalid_number (with error bit) if parameter is not a number.
+ * f_overflow (with error bit) on integer overflow.
+ * f_underflow (with error bit) on integer underflow.
+ * f_incomplete_utf (with error bit) if an incomplete UTF-8 fragment is found.
+ *
+ * @see f_conversion_string_to_number_signed()
+ */
+#ifndef _fl_console_parameter_to_number_signed_
+ f_return_status fl_console_parameter_to_number_signed(const f_string argument, int64_t *number);
+#endif // _fl_console_parameter_to_number_signed_
+
+/**
+ * Convert a console parameter additional argument to an unsigned 64-bit integer.
+ *
+ * This will detect based types as follows:
+ * - hexidecimals begin with either '0x' or '0X'.
+ * - duodecimals begin with either '0d' or '0D'.
+ * - octals begin with either '0o' or '0O'.
+ * - binaries begin with either '0b' or '0B'.
+ * - decimal is used for all other cases.
+ *
+ * Leading 0's and whitespace are ignored.
+ * Whitespace after the first digit is considered invalid.
+ *
+ * @param argv
+ * The argument string expected to be a number.
+ * This is generally passed from the argv[].
+ * @param number
+ * The converted number is stored here.
+ * This only gets modified on success.
+ *
+ * @return
+ * f_none on success.
+ * f_no_data the argument is empty or only contains valid whitespace.
+ * f_invalid_parameter (with error bit) if a parameter is invalid.
+ * f_invalid_number (with error bit) if parameter is not a number.
+ * f_negative_number (with error bit) on negative value.
+ * f_overflow (with error bit) on integer overflow.
+ * f_incomplete_utf (with error bit) if an incomplete UTF-8 fragment is found.
+ *
+ * @see f_conversion_string_to_number_unsigned()
+ */
+#ifndef _fl_console_parameter_to_number_unsigned_
+ f_return_status fl_console_parameter_to_number_unsigned(const f_string argument, uint64_t *number);
+#endif // _fl_console_parameter_to_number_unsigned_
+
+/**
* Process console parameters.
*
* Short parameters are processed as follows:
extern f_return_status fl_console_parameter_prioritize(const f_console_parameters parameters, const f_console_parameter_ids choices, f_console_parameter_id *decision);
#endif // _di_fl_console_parameter_prioritize__
-/**
- * Convert a console parameter additional argument to an unsigned integer.
- *
- * Unlike strtoull(), this only accepts complete numbers.
- * If the argument has anything else, such as "123abc", this will consider the number to be "123".
- *
- * This accepts base-16, base-10, and base-8.
- * - Base-16 is prefixed with '0x' or '0X'.
- * - Base-10 is not prefixed.
- * - Base-8 is prefixed with '0'.
- *
- * Note: The idea of an octal (base-8) being prefixed with '0' is a horrible mistake.
- * This is done by strtoull().
- * In the future, custom code may be used in place of strtoull() to use '0o' for octal.
- * Furthermore, '0b' for binary should be supported as well.
- *
- * @param argv
- * The argument string expected to be a number.
- * This is generally passed from the argv[].
- * @param number
- * The converted number is stored here.
- * This only gets modified on success.
- *
- * @return
- * f_none on success.
- * f_no_data the argument is empty.
- * f_invalid_parameter (with error bit) if a parameter is invalid.
- * f_invalid_number (with error bit) if parameter is not a number.
- * f_negative_number (with error bit) on negative value.
- * f_overflow (with error bit) on overflow.
- *
- * @see strtoull()
- */
-#ifndef _fl_console_parameter_to_number_unsigned_
- f_return_status fl_console_parameter_to_number_unsigned(const f_string argument, uint64_t *number);
-#endif // _fl_console_parameter_to_number_unsigned_
-
-/**
- * Convert a console parameter additional argument to a signed integer.
- *
- * Unlike strtoll(), this only accepts complete numbers.
- * If the argument has anything else, such as "123abc", this will consider the number to be "123".
- *
- * This accepts base-16, base-10, and base-8.
- * - Base-16 is prefixed with '0x' or '0X'.
- * - Base-10 is not prefixed.
- * - Base-8 is prefixed with '0'.
- *
- * Note: The idea of an octal (base-8) being prefixed with '0' is a horrible mistake.
- * This is done by strtoull().
- * In the future, custom code may be used in place of strtoull() to use '0o'/'0O' for octal.
- * Furthermore, '0b'/'0B' for binary should be supported as well.
- *
- * @param argv
- * The argument string expected to be a number.
- * This is generally passed from the argv[].
- * @param number
- * The converted number is stored here.
- * This only gets modified on success.
- *
- * @return
- * f_none on success.
- * f_no_data the argument is empty.
- * f_invalid_parameter (with error bit) if a parameter is invalid.
- * f_invalid_number (with error bit) if parameter is not a number.
- * f_underflow (with error bit) on underflow.
- * f_overflow (with error bit) on overflow.
- *
- * @see strtoll()
- */
-#ifndef _fl_console_parameter_to_number_signed_
- f_return_status fl_console_parameter_to_number_signed(const f_string argument, int64_t *number);
-#endif // _fl_console_parameter_to_number_signed_
-
#ifdef __cplusplus
} // extern "C"
#endif