From: Olivia Ryan <olivia.r.dev@gmail.com> --- dlls/windows.web/json_value.c | 88 +++++++++++++++++++++++------------ dlls/windows.web/tests/web.c | 5 +- 2 files changed, 60 insertions(+), 33 deletions(-) diff --git a/dlls/windows.web/json_value.c b/dlls/windows.web/json_value.c index 7470d60ff81..fcca2334aac 100644 --- a/dlls/windows.web/json_value.c +++ b/dlls/windows.web/json_value.c @@ -1,6 +1,7 @@ /* WinRT Windows.Data.Json.JsonValue Implementation * * Copyright (C) 2024 Mohamad Al-Jaf + * Copyright (C) 2026 Olivia Ryan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -314,60 +315,81 @@ static HRESULT unescape_string( const WCHAR *src, HSTRING *output ) return WindowsPromoteStringBuffer( buf, output ); } -static HRESULT trim_string( HSTRING input, HSTRING *output ) +struct json_buffer +{ + const WCHAR *str; + UINT32 len; +}; + +static void json_buffer_trim( struct json_buffer *json ) { static const WCHAR valid_whitespace[] = L" \t\n\r"; - UINT32 len, start = 0, end; - const WCHAR *json = WindowsGetStringRawBuffer( input, &len ); + UINT32 start = 0, end = json->len; - end = len; - while (start < end && wcschr( valid_whitespace, json[start] )) start++; - while (end > start && wcschr( valid_whitespace, json[end - 1] )) end--; + while (start < end && wcschr( valid_whitespace, json->str[start] )) start++; + while (end > start && wcschr( valid_whitespace, json->str[end - 1] )) end--; - return WindowsCreateString( json + start, end - start, output ); + json->str += start; + json->len = end - start; } -static HRESULT parse_json_value( HSTRING input, IJsonValue **value ) +static BOOL json_buffer_take( struct json_buffer *json, const WCHAR *str ) +{ + UINT32 len = wcslen( str ); + + if (json->len < len || wcsncmp( json->str, str, len )) return FALSE; + json->str += len; + json->len -= len; + + return TRUE; +} + +static HRESULT parse_json_value( struct json_buffer *json, IJsonValue **value ) { - UINT32 len; - const WCHAR *json = WindowsGetStringRawBuffer( input, &len ); struct json_value *impl; HRESULT hr = S_OK; /* FIXME: Handle all JSON edge cases */ - if (!len) return WEB_E_INVALID_JSON_STRING; + if (!json->len) return WEB_E_INVALID_JSON_STRING; if (!(impl = calloc( 1, sizeof( *impl ) ))) return E_OUTOFMEMORY; impl->IJsonValue_iface.lpVtbl = &json_value_vtbl; impl->ref = 1; - if (len == 4 && !wcsncmp( L"null", json, 4 )) + if (json_buffer_take( json, L"null" )) { impl->json_value_type = JsonValueType_Null; } - else if ((len == 4 && !wcsncmp( L"true", json, 4 )) || (len == 5 && !wcsncmp( L"false", json, 5 ))) + else if (json_buffer_take( json, L"true" )) { - impl->boolean_value = len == 4; + impl->boolean_value = TRUE; impl->json_value_type = JsonValueType_Boolean; } - else if (json[0] == '\"' && json[len - 1] == '\"') + else if (json_buffer_take( json, L"false" )) { - json++; - len -= 2; + impl->boolean_value = FALSE; + impl->json_value_type = JsonValueType_Boolean; + } + else if (*json->str == '"' && json->str[json->len - 1] == '"') + { + json->str++; + json->len -= 2; - if (len <= 2) hr = WEB_E_INVALID_JSON_STRING; - else hr = unescape_string( json, &impl->string_value ); + if (json->len <= 2) hr = WEB_E_INVALID_JSON_STRING; + else hr = unescape_string( json->str, &impl->string_value ); impl->json_value_type = JsonValueType_String; } - else if (json[0] == '[' && json[len - 1] == ']') + else if (*json->str == '[') { FIXME( "Array parsing not implemented!\n" ); impl->json_value_type = JsonValueType_Array; + hr = WEB_E_INVALID_JSON_STRING; } - else if (json[0] == '{' && json[len - 1] == '}') + else if (*json->str == '{') { FIXME( "Object parsing not implemented!\n" ); impl->json_value_type = JsonValueType_Object; + hr = WEB_E_INVALID_JSON_STRING; } else { @@ -375,9 +397,12 @@ static HRESULT parse_json_value( HSTRING input, IJsonValue **value ) WCHAR *end; errno = 0; - result = wcstold( json, &end ); + result = wcstold( json->str, &end ); + + json->len -= end - json->str; + json->str = end; - if (errno || errno == ERANGE || end != json + len) hr = WEB_E_INVALID_JSON_NUMBER; + if (errno || errno == ERANGE) hr = WEB_E_INVALID_JSON_NUMBER; impl->number_value = result; impl->json_value_type = JsonValueType_Number; @@ -388,16 +413,17 @@ static HRESULT parse_json_value( HSTRING input, IJsonValue **value ) return hr; } -static HRESULT parse_json( HSTRING json, IJsonValue **value ) +static HRESULT parse_json( HSTRING string, IJsonValue **value ) { - HSTRING trimmed_json = NULL; - HRESULT hr = trim_string( json, &trimmed_json ); - - if (SUCCEEDED(hr) && WindowsIsStringEmpty( trimmed_json )) hr = WEB_E_INVALID_JSON_STRING; - if (SUCCEEDED(hr)) hr = parse_json_value( trimmed_json, value ); + HRESULT hr; + struct json_buffer json; + json.str = WindowsGetStringRawBuffer( string, &json.len ); - WindowsDeleteString( trimmed_json ); - return hr; + json_buffer_trim( &json ); + if (!json.len) return WEB_E_INVALID_JSON_STRING; + if (FAILED(hr = parse_json_value( &json, value ))) return hr; + if (json.len) return WEB_E_INVALID_JSON_STRING; + return S_OK; } static HRESULT WINAPI json_value_statics_Parse( IJsonValueStatics *iface, HSTRING input, IJsonValue **value ) diff --git a/dlls/windows.web/tests/web.c b/dlls/windows.web/tests/web.c index b0f38edfb3b..9af1b872846 100644 --- a/dlls/windows.web/tests/web.c +++ b/dlls/windows.web/tests/web.c @@ -112,13 +112,15 @@ static void check_json_( unsigned int line, IJsonValueStatics *json_value_static if (expected_json_value_type == JsonValueType_Number) ok_(__FILE__, line)( hr == WEB_E_INVALID_JSON_NUMBER, "got hr %#lx.\n", hr ); else - todo_wine ok_(__FILE__, line)( hr == WEB_E_INVALID_JSON_STRING, "got hr %#lx.\n", hr ); WindowsDeleteString( str ); return; } + + todo_wine_if(expected_json_value_type == JsonValueType_Array || expected_json_value_type == JsonValueType_Object) ok_(__FILE__, line)( hr == S_OK, "got hr %#lx.\n", hr ); + if (FAILED(hr)) return; hr = IJsonValue_get_ValueType( json_value, &json_value_type ); ok_(__FILE__, line)( hr == S_OK, "got hr %#lx.\n", hr ); ok_(__FILE__, line)( json_value_type == expected_json_value_type, "got json_value_type %d.\n", json_value_type ); @@ -289,7 +291,6 @@ static void test_JsonValueStatics(void) hr = IJsonValueStatics_Parse( json_value_statics, str, NULL ); ok( hr == E_POINTER, "got hr %#lx.\n", hr ); hr = IJsonValueStatics_Parse( json_value_statics, str, &json_value ); - todo_wine ok( hr == WEB_E_INVALID_JSON_STRING, "got hr %#lx.\n", hr ); WindowsDeleteString( str ); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10443