mirror of
https://github.com/vlang/v.git
synced 2025-09-08 14:51:53 -04:00
x.json2.decoder2: decode bool and numbers (#22550)
This commit is contained in:
parent
7da79fd221
commit
7c1cde0396
@ -494,12 +494,12 @@ pub fn decode[T](val string) !T {
|
||||
|
||||
// decode_value decodes a value from the JSON nodes.
|
||||
fn (mut decoder Decoder) decode_value[T](mut val T) ! {
|
||||
$if val is $option {
|
||||
$if T is $option {
|
||||
} $else $if T is string {
|
||||
} $else $if T is $sumtype {
|
||||
$for v in val.variants {
|
||||
if val is v {
|
||||
decoder.decode_value(nodes, val)
|
||||
decoder.decode_value(val)
|
||||
}
|
||||
}
|
||||
} $else $if T is $alias {
|
||||
@ -512,13 +512,26 @@ fn (mut decoder Decoder) decode_value[T](mut val T) ! {
|
||||
decoder.fulfill_nodes(mut nodes)
|
||||
|
||||
decoder.decode_struct(nodes, val)
|
||||
} $else $if T is $enum {
|
||||
} $else $if T is $int {
|
||||
} $else $if T is $float {
|
||||
} $else $if T is bool {
|
||||
value_info := decoder.values_info[decoder.value_info_idx]
|
||||
|
||||
unsafe {
|
||||
val = vmemcmp(decoder.json.str + value_info.position, 'true'.str, 4) == 0
|
||||
}
|
||||
} $else $if T in [$int, $float, $enum] {
|
||||
value_info := decoder.values_info[decoder.value_info_idx]
|
||||
|
||||
if value_info.value_kind == .number {
|
||||
bytes := unsafe { (decoder.json.str + value_info.position).vbytes(value_info.length) }
|
||||
|
||||
unsafe {
|
||||
string_buffer_to_generic_number(val, bytes)
|
||||
}
|
||||
}
|
||||
} $else {
|
||||
return error('cannot encode value with ${typeof(val).name} type')
|
||||
}
|
||||
decoder.value_info_idx++
|
||||
}
|
||||
|
||||
// get_value_kind returns the kind of a JSON value.
|
||||
@ -866,3 +879,74 @@ fn (mut decoder Decoder) fulfill_nodes(mut nodes []Node) {
|
||||
decoder.idx++
|
||||
}
|
||||
}
|
||||
|
||||
// string_buffer_to_generic_number converts a buffer of bytes (data) into a generic type T and
|
||||
// stores the result in the provided result pointer.
|
||||
// The function supports conversion to the following types:
|
||||
// - Signed integers: i8, i16, int, i64
|
||||
// - Unsigned integers: u8, u16, u32, u64
|
||||
// - Floating-point numbers: f32, f64
|
||||
//
|
||||
// For signed integers, the function handles negative numbers by checking for a '-' character.
|
||||
// For floating-point numbers, the function handles decimal points and adjusts the result
|
||||
// accordingly.
|
||||
//
|
||||
// If the type T is not supported, the function will panic with an appropriate error message.
|
||||
//
|
||||
// Parameters:
|
||||
// - data []u8: The buffer of bytes to be converted.
|
||||
// - result &T: A pointer to the variable where the converted result will be stored.
|
||||
//
|
||||
// NOTE: This aims works with not new memory allocated data, to more efficient use `vbytes` before
|
||||
@[direct_array_access; unsafe]
|
||||
pub fn string_buffer_to_generic_number[T](result &T, data []u8) {
|
||||
mut is_negative := false
|
||||
|
||||
$if T is $int {
|
||||
for ch in data {
|
||||
if ch == `-` {
|
||||
is_negative = true
|
||||
continue
|
||||
}
|
||||
digit := T(ch - `0`)
|
||||
*result = T(*result * 10 + digit)
|
||||
}
|
||||
} $else $if T is $float {
|
||||
mut decimal_seen := false
|
||||
mut decimal_divider := int(1)
|
||||
|
||||
for ch in data {
|
||||
if ch == `-` {
|
||||
is_negative = true
|
||||
continue
|
||||
}
|
||||
if ch == `.` {
|
||||
decimal_seen = true
|
||||
continue
|
||||
}
|
||||
|
||||
digit := T(ch - `0`)
|
||||
|
||||
if decimal_seen {
|
||||
decimal_divider *= 10
|
||||
*result += T(digit / decimal_divider)
|
||||
} else {
|
||||
*result = *result * 10 + digit
|
||||
}
|
||||
}
|
||||
} $else $if T is $enum {
|
||||
// Convert the string to an integer
|
||||
enumeration := 0
|
||||
for ch in data {
|
||||
digit := int(ch - `0`)
|
||||
enumeration = enumeration * 10 + digit
|
||||
}
|
||||
*result = T(enumeration)
|
||||
} $else {
|
||||
panic('unsupported type ${typeof[T]().name}')
|
||||
}
|
||||
|
||||
if is_negative {
|
||||
*result = -*result
|
||||
}
|
||||
}
|
||||
|
@ -47,7 +47,11 @@ mut:
|
||||
fn main() {
|
||||
json_data := '{"val": 1, "val2": "lala", "val3": {"a": 2, "churrasco": "leleu"}}'
|
||||
json_data1 := '{"val": "2"}'
|
||||
// json_data2 := '{"val": 2}'
|
||||
json_data2 := '{"val": 2}'
|
||||
|
||||
println('Starting benchmark...')
|
||||
println('max_iterations: ${max_iterations}')
|
||||
println('\n***Structure and maps***')
|
||||
|
||||
mut b := benchmark.start()
|
||||
|
||||
@ -85,6 +89,19 @@ fn main() {
|
||||
|
||||
b.measure('old_json.decode(StructTypeOption[string], json_data1)!\n')
|
||||
|
||||
// StructType[int] **********************************************************
|
||||
for i := 0; i < max_iterations; i++ {
|
||||
_ := decoder2.decode[StructType[int]](json_data2)!
|
||||
}
|
||||
|
||||
b.measure('decoder2.decode[StructType[int]](json_data2)!')
|
||||
|
||||
for i := 0; i < max_iterations; i++ {
|
||||
_ := old_json.decode(StructType[int], json_data2)!
|
||||
}
|
||||
|
||||
b.measure('old_json.decode(StructType[int], json_data2)!\n')
|
||||
|
||||
// map[string]string **********************************************************
|
||||
for i := 0; i < max_iterations; i++ {
|
||||
_ := decoder2.decode[map[string]string](json_data1)!
|
||||
@ -97,4 +114,20 @@ fn main() {
|
||||
}
|
||||
|
||||
b.measure('old_json.decode(map[string]string, json_data1)!\n')
|
||||
|
||||
println('\n***simple types***')
|
||||
|
||||
// int **********************************************************
|
||||
for i := 0; i < max_iterations; i++ {
|
||||
_ := decoder2.decode[int]('2')!
|
||||
}
|
||||
|
||||
b.measure("decoder2.decode[int]('2')!")
|
||||
|
||||
// bool **********************************************************
|
||||
for i := 0; i < max_iterations; i++ {
|
||||
_ := decoder2.decode[bool]('true')!
|
||||
}
|
||||
|
||||
b.measure("decoder2.decode[bool]('true')!")
|
||||
}
|
||||
|
94
vlib/x/json2/decoder2/tests/decode_number_and_boolean_test.v
Normal file
94
vlib/x/json2/decoder2/tests/decode_number_and_boolean_test.v
Normal file
@ -0,0 +1,94 @@
|
||||
import x.json2.decoder2 as json
|
||||
|
||||
fn test_number() {
|
||||
// Test u8
|
||||
assert json.decode[u8]('0')! == 0
|
||||
assert json.decode[u8]('1')! == 1
|
||||
assert json.decode[u8]('201')! == 201
|
||||
|
||||
assert json.decode[u8]('-1')! == u8(-1)
|
||||
assert json.decode[u8]('-127')! == u8(-127)
|
||||
|
||||
// Test u16
|
||||
assert json.decode[u16]('0')! == 0
|
||||
assert json.decode[u16]('1')! == 1
|
||||
assert json.decode[u16]('201')! == 201
|
||||
|
||||
assert json.decode[u16]('-1')! == u16(-1)
|
||||
assert json.decode[u16]('-201')! == u16(-201)
|
||||
|
||||
// Test u32
|
||||
assert json.decode[u32]('0')! == 0
|
||||
assert json.decode[u32]('1')! == 1
|
||||
assert json.decode[u32]('201')! == 201
|
||||
|
||||
// Test u64
|
||||
assert json.decode[u64]('0')! == 0
|
||||
assert json.decode[u64]('1')! == 1
|
||||
assert json.decode[u64]('201')! == 201
|
||||
|
||||
// Test i8
|
||||
assert json.decode[i8]('0')! == 0
|
||||
assert json.decode[i8]('1')! == 1
|
||||
assert json.decode[i8]('127')! == 127
|
||||
|
||||
assert json.decode[i8]('-1')! == -1
|
||||
assert json.decode[i8]('-127')! == -127
|
||||
|
||||
// Test i16
|
||||
assert json.decode[i16]('0')! == 0
|
||||
assert json.decode[i16]('1')! == 1
|
||||
assert json.decode[i16]('201')! == 201
|
||||
|
||||
assert json.decode[i16]('-1')! == -1
|
||||
assert json.decode[i16]('-201')! == -201
|
||||
|
||||
// Test int
|
||||
assert json.decode[int]('0')! == 0
|
||||
assert json.decode[int]('1')! == 1
|
||||
assert json.decode[int]('201')! == 201
|
||||
|
||||
assert json.decode[int]('-1')! == -1
|
||||
assert json.decode[int]('-201')! == -201
|
||||
|
||||
assert json.decode[int]('1234567890')! == 1234567890
|
||||
assert json.decode[int]('-1234567890')! == -1234567890
|
||||
|
||||
// Test i64
|
||||
assert json.decode[i64]('0')! == 0
|
||||
assert json.decode[i64]('1')! == 1
|
||||
assert json.decode[i64]('201')! == 201
|
||||
|
||||
assert json.decode[i64]('-1')! == -1
|
||||
assert json.decode[i64]('-201')! == -201
|
||||
|
||||
assert json.decode[i64]('1234567890')! == 1234567890
|
||||
assert json.decode[i64]('-1234567890')! == -1234567890
|
||||
|
||||
// Test f32
|
||||
assert json.decode[f32]('0')! == 0.0
|
||||
assert json.decode[f32]('1')! == 1.0
|
||||
assert json.decode[f32]('201')! == 201.0
|
||||
|
||||
assert json.decode[f32]('-1')! == -1.0
|
||||
assert json.decode[f32]('-201')! == -201.0
|
||||
|
||||
assert json.decode[f32]('1234567890')! == 1234567890.0
|
||||
assert json.decode[f32]('-1234567890')! == -1234567890.0
|
||||
|
||||
// Test f64
|
||||
assert json.decode[f64]('0')! == 0.0
|
||||
assert json.decode[f64]('1')! == 1.0
|
||||
assert json.decode[f64]('201')! == 201.0
|
||||
|
||||
assert json.decode[f64]('-1')! == -1.0
|
||||
assert json.decode[f64]('-201')! == -201.0
|
||||
|
||||
assert json.decode[f64]('1234567890')! == 1234567890.0
|
||||
assert json.decode[f64]('-1234567890')! == -1234567890.0
|
||||
}
|
||||
|
||||
fn test_boolean() {
|
||||
assert json.decode[bool]('false')! == false
|
||||
assert json.decode[bool]('true')! == true
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user