mirror of
https://github.com/vlang/v.git
synced 2025-09-10 07:47:20 -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.
|
// decode_value decodes a value from the JSON nodes.
|
||||||
fn (mut decoder Decoder) decode_value[T](mut val T) ! {
|
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 string {
|
||||||
} $else $if T is $sumtype {
|
} $else $if T is $sumtype {
|
||||||
$for v in val.variants {
|
$for v in val.variants {
|
||||||
if val is v {
|
if val is v {
|
||||||
decoder.decode_value(nodes, val)
|
decoder.decode_value(val)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} $else $if T is $alias {
|
} $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.fulfill_nodes(mut nodes)
|
||||||
|
|
||||||
decoder.decode_struct(nodes, val)
|
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 {
|
} $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 {
|
} $else {
|
||||||
return error('cannot encode value with ${typeof(val).name} type')
|
return error('cannot encode value with ${typeof(val).name} type')
|
||||||
}
|
}
|
||||||
|
decoder.value_info_idx++
|
||||||
}
|
}
|
||||||
|
|
||||||
// get_value_kind returns the kind of a JSON value.
|
// 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++
|
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() {
|
fn main() {
|
||||||
json_data := '{"val": 1, "val2": "lala", "val3": {"a": 2, "churrasco": "leleu"}}'
|
json_data := '{"val": 1, "val2": "lala", "val3": {"a": 2, "churrasco": "leleu"}}'
|
||||||
json_data1 := '{"val": "2"}'
|
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()
|
mut b := benchmark.start()
|
||||||
|
|
||||||
@ -85,6 +89,19 @@ fn main() {
|
|||||||
|
|
||||||
b.measure('old_json.decode(StructTypeOption[string], json_data1)!\n')
|
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 **********************************************************
|
// map[string]string **********************************************************
|
||||||
for i := 0; i < max_iterations; i++ {
|
for i := 0; i < max_iterations; i++ {
|
||||||
_ := decoder2.decode[map[string]string](json_data1)!
|
_ := decoder2.decode[map[string]string](json_data1)!
|
||||||
@ -97,4 +114,20 @@ fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
b.measure('old_json.decode(map[string]string, json_data1)!\n')
|
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