-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* add .DS_Store to gitignore * add convert.h/c and impl str_frombuf * basic itoa/s impl * added some docs for new functions * add unit tests and fix bugs
- Loading branch information
1 parent
940d61b
commit 0b372db
Showing
10 changed files
with
187 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
target/ | ||
.DS_Store |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
#ifndef LFC_CONVERT_HEADER | ||
#define LFC_CONVERT_HEADER | ||
|
||
#include <stdint.h> | ||
#include "lfc/collections/str.h" | ||
|
||
// itoa and itos convert an integer to its string representation, storing it either in a null-terminated | ||
// character buffer or an lfc owned string | ||
char* itoa(int32_t n); | ||
str_t itos(int32_t n); | ||
|
||
// FUTURE: extend this for... | ||
// different bases | ||
// long integers | ||
// unsigned integers? | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
#include "lfc/utils/convert.h" | ||
|
||
#include <math.h> | ||
#include <stdint.h> | ||
|
||
#include "lfc/collections/str.h" | ||
#include "lfc/utils/mem.h" | ||
|
||
// Because the max number of digits in an int is 10, it can be stored in an unsigned char | ||
// This function also takes into account whether or not a negative sign is required | ||
uint8_t __n_chars_required(int32_t n) { | ||
uint8_t sign = 0; | ||
uint32_t magnitude = n; | ||
|
||
if (n < 0) { | ||
sign = 1; | ||
magnitude = (int64_t)n * -1; | ||
} else if (n == 0) { | ||
return 1; | ||
} | ||
|
||
return ceil(log10(magnitude)) + sign; | ||
} | ||
|
||
// NOTE: this function assumes the buffer has enough space to store the | ||
// contents of the number's string repr inside of it. Violating this assumption | ||
// leads to buffer overflow, which obviously is undefined behavior. | ||
void __fill_buf(int32_t n, char* buf) { | ||
uint8_t buflen = __n_chars_required(n); | ||
uint32_t magnitude = n; | ||
|
||
if (n < 0) { | ||
// If n is negative, add the sign at the front of the buffer and revert to positive | ||
buf[0] = '-'; | ||
magnitude = (int64_t)n * -1; | ||
} else if (n == 0) { | ||
buf[0] = '0'; | ||
return; | ||
} | ||
|
||
uint8_t i = 0; | ||
|
||
while (magnitude > 0) { | ||
// Grab each digit and insert it in the back of the buffer | ||
uint8_t digit = magnitude % 10; | ||
|
||
// NOTE: a bit of unsafety here: there's overflow if buflen is 0, but I think | ||
// that's not possible because of the range of log | ||
uint8_t index = buflen - 1 - i; | ||
buf[index] = '0' + digit; | ||
|
||
magnitude /= 10; | ||
i++; | ||
} | ||
} | ||
|
||
char* itoa(int32_t n) { | ||
// Allocate a buffer that can hold the number's string repr, | ||
// _and_ a null terminator | ||
uint8_t buflen = __n_chars_required(n) + 1; | ||
char* buf = malloc_unwrap(sizeof(char), buflen, "[itoa] failed to alloc buffer"); | ||
|
||
// Fill the buffer and add a null terminator | ||
__fill_buf(n, buf); | ||
buf[buflen - 1] = '\0'; | ||
|
||
return buf; | ||
} | ||
|
||
str_t itos(int32_t n) { | ||
// Allocate a buffer that can hold the number's string repr, | ||
// without a null terminator | ||
uint8_t buflen = __n_chars_required(n); | ||
char* buf = malloc_unwrap(sizeof(char), buflen, "[itoa] failed to alloc buffer"); | ||
|
||
// Fill the buffer | ||
__fill_buf(n, buf); | ||
|
||
// Initialize the string from the buffer | ||
str_t str; | ||
str_frombuf(&str, buf, buflen); | ||
return str; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
#include "lfc/utils/convert.h" | ||
|
||
#include <stdint.h> | ||
#include <string.h> | ||
|
||
#include "tests/assert.h" | ||
#include "tests/setup.h" | ||
|
||
#define RUN_ITOA_TEST(n) start_test(); itoa_test_body(n, #n); end_test(); | ||
|
||
#include <stdio.h> | ||
|
||
void itoa_test_body(int32_t n, char* exp_lit) { | ||
str_t exp_str; | ||
str_from(&exp_str, exp_lit); | ||
|
||
char* result_buf = itoa(n); | ||
assert(strcmp(exp_lit, result_buf) == 0); | ||
|
||
str_t result_str = itos(n); | ||
assert(str_eq(&exp_str, &result_str)); | ||
} | ||
|
||
void test_itoa_zero_converted_correctly() { | ||
RUN_ITOA_TEST(0); | ||
} | ||
|
||
void test_itoa_small_positive_converted_correctly() { | ||
RUN_ITOA_TEST(150); | ||
} | ||
|
||
void test_itoa_large_positive_converted_correctly() { | ||
RUN_ITOA_TEST(12500000); | ||
} | ||
|
||
void test_itoa_small_negative_converted_correctly() { | ||
RUN_ITOA_TEST(-225); | ||
} | ||
|
||
void test_itoa_large_negative_converted_correctly() { | ||
RUN_ITOA_TEST(-7500000); | ||
} | ||
|
||
void test_itoa_max_value_converted_correctly() { | ||
// hardcode INT32_MAX to get the test to run w/ the macro | ||
RUN_ITOA_TEST(2147483647); | ||
} | ||
|
||
void test_itoa_min_value_converted_correctly() { | ||
// hardcode INT32_MIN to get the test to run w/ the macro | ||
RUN_ITOA_TEST(-2147483648); | ||
} | ||
|
||
void run_convert_tests() { | ||
start_suite(); | ||
|
||
test_itoa_zero_converted_correctly(); | ||
test_itoa_small_positive_converted_correctly(); | ||
test_itoa_large_positive_converted_correctly(); | ||
test_itoa_small_negative_converted_correctly(); | ||
test_itoa_large_negative_converted_correctly(); | ||
test_itoa_max_value_converted_correctly(); | ||
test_itoa_min_value_converted_correctly(); | ||
|
||
end_suite(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters