diff options
| author | Charlie Stanton <charlie@shtanton.xyz> | 2022-01-09 15:10:21 +0000 | 
|---|---|---|
| committer | Charlie Stanton <charlie@shtanton.xyz> | 2022-01-09 15:10:21 +0000 | 
| commit | e5d44899cffd80653da9e0336af36230c4e992a0 (patch) | |
| tree | 07587e6b88b5d7d5c41f222a567a7b783fa35c80 | |
| parent | fbcba2f689348fb723f8d33f3d8e2010e4864e85 (diff) | |
| download | cudl-main.tar | |
| -rw-r--r-- | cudl.c | 69 | ||||
| -rw-r--r-- | cudl.h | 1 | ||||
| -rw-r--r-- | test.cudl | 5 | 
3 files changed, 73 insertions, 2 deletions
| @@ -5,6 +5,7 @@  #include "cudl.h"  #define STRIP_WHITESPACE(text) while (isspace(*(text))) (text)++ +  #define IS_KEY_CHAR(c) (\  	'a' <= (c) && (c) <= 'z' ||\  	'A' <= (c) && (c) <= 'Z' ||\ @@ -12,6 +13,10 @@  	(c) == '_' || (c) == '-'\  ) +#define IS_DIGIT(c) (\ +	'0' <= (c) && (c) <= '9'\ +) +  int cudl_err = CUDL_OK;  static char *fread_all(FILE *file) { @@ -43,18 +48,26 @@ void cudl_debug(struct cudl_value value) {  			else  				printf("%%false");  			break; +		case CUDL_TAG_NUMBER: +			printf("%lf", value.data.number); +			break;  		case CUDL_TAG_STRING:  			printf("\"%s\"", value.data.string);  			break;;  		case CUDL_TAG_ARRAY:  			printf("["); -			for (i = 0; i < value.data.array.length; i++) +			for (i = 0; i < value.data.array.length; i++) { +				if (i != 0) +					printf(" ");  				cudl_debug(value.data.array.values[i]); +			}  			printf("]");  			break;  		case CUDL_TAG_MAP:  			printf("{");  			for (i = 0; i < value.data.map.length; i++) { +				if (i != 0) +					printf(" ");  				printf("\"%s\": ", value.data.map.fields[i].key);  				cudl_debug(value.data.map.fields[i].value);  			} @@ -106,11 +119,61 @@ static size_t parse_bool_or_null(char *input, struct cudl_value *value) {  	return 0;  } +static size_t parse_number(char *input, struct cudl_value *value) { +	double number; +	size_t i, exponentStart; +	int exponent, otherExponent; +	int exponentUsed; +	exponentUsed = 0; +	number = 0; +	i = input[0] == '-'; +	for (;; i++) { +		if (IS_DIGIT(input[i])) { +			number = number * 10 + (input[i] - '0'); +			exponent++; +			continue; +		} else if (input[i] == '.') { +			exponent = 0; +			exponentUsed = 1; +			continue; +		} +		break; +	} +	if (input[0] == '-') +		number = 0 - number; +	if (!exponentUsed) +		exponent = 0; +	otherExponent = 0; +	if (input[i] == 'e' && (IS_DIGIT(input[i+1]) || (input[i+1] == '-' && IS_DIGIT(input[i+2])))) { +		i++; +		exponentStart = i; +		i += input[i] == '-'; +		for (;; i++) { +			if (IS_DIGIT(input[i])) +				otherExponent = otherExponent * 10 + (input[i] - '0'); +			else +				break; +		} +		if (input[exponentStart] == '-') +			otherExponent = 0 - otherExponent; +	} +	exponent = exponent - otherExponent; +	for (; exponent > 0; exponent--) { +		number /= 10; +	} +	for (; exponent < 0; exponent++) { +		number *= 10; +	} +	value->tag = CUDL_TAG_NUMBER; +	value->data.number = number; +	return i; +} +  /* Convert UCS character to utf-8 bytes.   * Return number of bytes generated.   * Sets cudl_error on error.   * Shamelessly lifted from https://github.com/cktan/tomc99 */ -size_t cudl_ucs_to_utf8(int64_t ucs, char utf8[6]) { +static size_t cudl_ucs_to_utf8(int64_t ucs, char utf8[6]) {  	if (  		0xd800 <= ucs && ucs <= 0xdfff ||  		0xfffe <= ucs && ucs <= 0xffff || @@ -482,6 +545,8 @@ static size_t _parse_value(char *input, struct cudl_value *value) {  		value->tag = CUDL_TAG_STRING;  		return parse_quoted_string(++input, &value->data.string) + 1;  	} +	if (IS_DIGIT(*input) || *input == '-') +		return parse_number(input, value);  	cudl_err = CUDL_ERR_UNRECOGNISED_VALUE;  	return 0;  } @@ -33,6 +33,7 @@ struct cudl_map_field {  enum {  	CUDL_TAG_NULL,  	CUDL_TAG_BOOL, +	CUDL_TAG_NUMBER,  	CUDL_TAG_ARRAY,  	CUDL_TAG_MAP,  	CUDL_TAG_STRING, @@ -4,6 +4,11 @@  	[%null %null %false]  	["hello\nfriend\t\tstuff\"" "world"]  	"\U0001f600" +	12 +	12.4 +	13.456 +	123.345e4 +	123456789e-8  	{  		testing: "this is a test map"  		i_hope_it_works: {nesting: "nested maps!!!"} | 
