[gbinder] Added gbinder_reader_read_nullable_string8

The equivalent of Android's Parcel::readString8
This commit is contained in:
Slava Monich 2024-09-24 18:48:39 +03:00
parent 5cfe96b891
commit 3350f51a21
3 changed files with 186 additions and 11 deletions

View File

@ -1,6 +1,6 @@
/*
* Copyright (C) 2018-2022 Jolla Ltd.
* Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2018-2024 Slava Monich <slava@monich.com>
*
* You may use this file under the terms of BSD license as follows:
*
@ -196,6 +196,15 @@ const char*
gbinder_reader_read_string8(
GBinderReader* reader);
gboolean
gbinder_reader_read_nullable_string8(
GBinderReader* reader,
const char** out,
gsize* out_len); /* Since 1.1.41 */
#define gbinder_reader_skip_nullable_string8(reader) \
gbinder_reader_read_nullable_string8(reader, NULL, NULL)
char*
gbinder_reader_read_string16(
GBinderReader* reader)

View File

@ -617,6 +617,7 @@ gbinder_reader_read_hidl_string_vec(
return NULL;
}
/* The equivalent of Android's Parcel::readCString */
const char*
gbinder_reader_read_string8(
GBinderReader* reader)
@ -641,6 +642,49 @@ gbinder_reader_read_string8(
return NULL;
}
/* The equivalent of Android's Parcel::readString8 */
gboolean
gbinder_reader_read_nullable_string8(
GBinderReader* reader,
const char** out,
gsize* out_len) /* Since 1.1.41 */
{
GBinderReaderPriv* p = gbinder_reader_cast(reader);
if ((p->ptr + 4) <= p->end) {
const gint32* len_ptr = (gint32*)p->ptr;
const gint32 len = *len_ptr;
if (len == -1) {
/* NULL string */
p->ptr += 4;
if (out) {
*out = NULL;
}
if (out_len) {
*out_len = 0;
}
return TRUE;
} else if (len >= 0) {
const guint32 padded_len = G_ALIGN4(len + 1);
const char* str = (char*)(p->ptr + 4);
if ((p->ptr + padded_len + 4) <= p->end && !str[len]) {
p->ptr += padded_len + 4;
if (out) {
*out = str;
}
if (out_len) {
*out_len = len;
}
return TRUE;
}
}
}
return FALSE;
}
/* The equivalent of Android's Parcel::readString16 */
gboolean
gbinder_reader_read_nullable_string16(
GBinderReader* reader,

View File

@ -504,7 +504,7 @@ test_double(
}
/*==========================================================================*
* string8
* cstring
*==========================================================================*/
typedef struct test_string_data {
@ -515,28 +515,28 @@ typedef struct test_string_data {
gboolean remaining;
} TestStringData;
static const guint8 test_string8_in_short [] = {
static const guint8 test_cstring_in_short [] = {
't', 'e', 's', 't', 0, 0, 0
};
static const guint8 test_string8_in_basic1 [] = {
static const guint8 test_cstring_in_basic1 [] = {
't', 'e', 's', 't', 0, 0, 0, 0
};
static const guint8 test_string8_in_basic2 [] = {
static const guint8 test_cstring_in_basic2 [] = {
't', 'e', 's', 't', 0, 0, 0, 0, 0
};
static const TestStringData test_string8_tests [] = {
{ "short", TEST_ARRAY_AND_SIZE(test_string8_in_short), NULL,
sizeof(test_string8_in_short)},
{ "ok1", TEST_ARRAY_AND_SIZE(test_string8_in_basic1), "test", 0 },
{ "ok2", TEST_ARRAY_AND_SIZE(test_string8_in_basic2), "test", 1 }
static const TestStringData test_cstring_tests [] = {
{ "err", TEST_ARRAY_AND_SIZE(test_cstring_in_short), NULL,
sizeof(test_cstring_in_short)},
{ "ok1", TEST_ARRAY_AND_SIZE(test_cstring_in_basic1), "test", 0 },
{ "ok2", TEST_ARRAY_AND_SIZE(test_cstring_in_basic2), "test", 1 }
};
static
void
test_string8(
test_cstring(
gconstpointer test_data)
{
const TestStringData* test = test_data;
@ -560,6 +560,119 @@ test_string8(
gbinder_driver_unref(driver);
}
/*==========================================================================*
* string8
*==========================================================================*/
static const guint8 test_string8_in_null [] = {
TEST_INT32_BYTES(-1)
};
static const guint8 test_string8_in_invalid [] = {
TEST_INT32_BYTES(-2)
};
static const guint8 test_string8_in_short1 [] = {
0x00
};
static const guint8 test_string8_in_short2 [] = {
TEST_INT32_BYTES(3), 'f', 'o', 'o'
};
static const guint8 test_string8_in_noterm [] = {
TEST_INT32_BYTES(3), 'f', 'o', 'o', 'x' /* Missing terminator */
};
static const guint8 test_string8_in_basic1 [] = {
TEST_INT32_BYTES(3), 'f', 'o', 'o', 0x00
};
static const guint8 test_string8_in_basic2 [] = {
TEST_INT32_BYTES(3), 'f', 'o', 'o', 0x00, 0x00
};
static const TestStringData test_string8_tests [] = {
{ "invalid", TEST_ARRAY_AND_SIZE(test_string8_in_invalid), NULL,
sizeof(test_string8_in_invalid) },
{ "short1", TEST_ARRAY_AND_SIZE(test_string8_in_short1), NULL,
sizeof(test_string8_in_short1) },
{ "short2", TEST_ARRAY_AND_SIZE(test_string8_in_short2), NULL,
sizeof(test_string8_in_short2) },
{ "noterm", TEST_ARRAY_AND_SIZE(test_string8_in_noterm), NULL,
sizeof(test_string8_in_noterm) },
{ "ok1", TEST_ARRAY_AND_SIZE(test_string8_in_basic1), "foo", 0 },
{ "ok2", TEST_ARRAY_AND_SIZE(test_string8_in_basic2), "foo", 1 }
};
static
void
test_string8_null(
void)
{
GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
GBinderReader reader;
GBinderReaderData data;
gsize len = 1;
char dummy;
const char* out = &dummy;
g_assert(driver);
memset(&data, 0, sizeof(data));
data.buffer = gbinder_buffer_new(driver,
g_memdup(TEST_ARRAY_AND_SIZE(test_string8_in_null)),
sizeof(test_string8_in_null), NULL);
gbinder_reader_init(&reader, &data, 0, sizeof(test_string8_in_null));
g_assert(gbinder_reader_skip_nullable_string8(&reader));
g_assert(gbinder_reader_at_end(&reader));
gbinder_reader_init(&reader, &data, 0, sizeof(test_string8_in_null));
g_assert(gbinder_reader_read_nullable_string8(&reader, &out, &len));
g_assert(gbinder_reader_at_end(&reader));
g_assert(!out);
g_assert(!len);
gbinder_buffer_free(data.buffer);
gbinder_driver_unref(driver);
}
static
void
test_string8(
gconstpointer test_data)
{
const TestStringData* test = test_data;
GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
GBinderReader r;
GBinderReaderData data;
const gboolean valid = (test->out != NULL);
const char* out = NULL;
gsize len = 0;
g_assert(driver);
memset(&data, 0, sizeof(data));
data.buffer = gbinder_buffer_new(driver, g_memdup(test->in, test->in_size),
test->in_size, NULL);
gbinder_reader_init(&r, &data, 0, test->in_size);
g_assert(gbinder_reader_skip_nullable_string8(&r) == valid);
g_assert(gbinder_reader_at_end(&r) == (!test->remaining));
g_assert_cmpuint(gbinder_reader_bytes_remaining(&r), == ,test->remaining);
gbinder_reader_init(&r, &data, 0, test->in_size);
g_assert(gbinder_reader_read_nullable_string8(&r, &out, &len) == valid);
g_assert(gbinder_reader_at_end(&r) == (!test->remaining));
g_assert_cmpuint(gbinder_reader_bytes_remaining(&r), == ,test->remaining);
if (valid) {
g_assert_cmpstr(out, ==, test->out);
g_assert_cmpuint(len, == ,strlen(test->out));
}
gbinder_buffer_free(data.buffer);
gbinder_driver_unref(driver);
}
/*==========================================================================*
* string16
*==========================================================================*/
@ -2453,6 +2566,15 @@ int main(int argc, char* argv[])
g_test_add_func(TEST_("float"), test_float);
g_test_add_func(TEST_("double"), test_double);
for (i = 0; i < G_N_ELEMENTS(test_cstring_tests); i++) {
const TestStringData* test = test_cstring_tests + i;
char* path = g_strconcat(TEST_("cstring/"), test->name, NULL);
g_test_add_data_func(path, test, test_cstring);
g_free(path);
}
g_test_add_func(TEST_("string8/null"), test_string8_null);
for (i = 0; i < G_N_ELEMENTS(test_string8_tests); i++) {
const TestStringData* test = test_string8_tests + i;
char* path = g_strconcat(TEST_("string8/"), test->name, NULL);