Serialized Data Functions

#include <keychain/keychain_headers.h>

Overview

Serialized data functions provide type-safe data serialization and deserialization. Serialized data objects are the fundamental data containers used throughout the Keychain API for transmitting and storing typed data.

Object Lifecycle Functions

kc_serialized_data_construct()

int kc_serialized_data_construct(
    kc_serialized_data_t** out_serialized_data_ptr,
    const char* data,
    const unsigned int data_size,
    const tkc_data_type data_type,
    const tkc_character_encoding encoding
)

Constructs a serialized data object from raw data with specified type and encoding.

Parameters:

  • out_serialized_data_ptr - Pointer to serialized data pointer (output, caller must free)

  • data - Raw data to serialize

  • data_size - Size of the data

  • data_type - Type of the data (see tkc_data_type enum)

  • encoding - Character encoding (for string types)

Returns: Error code (0 = success)

Example:

kc_serialized_data_t* data = NULL;
const char* message = "Hello, Keychain!";
int result = kc_serialized_data_construct(&data, message, strlen(message),
                                         TKC_DATA_TYPE_UTF8_STRING,
                                         TKC_CHARACTER_ENCODING_UTF8);
if (result == 0) {
    // Use serialized data...
    kc_serialized_data_destruct(&data);
}

kc_serialized_data_construct_from_string()

int kc_serialized_data_construct_from_string(
    kc_serialized_data_t** out_serialized_data_ptr,
    const char* string,
    const unsigned int string_size,
    const tkc_data_type data_type
)

Constructs a serialized data object from a string with automatic UTF-8 encoding.

Parameters:

  • out_serialized_data_ptr - Pointer to serialized data pointer (output, caller must free)

  • string - String data to serialize

  • string_size - Length of the string

  • data_type - Type of the data (typically TKC_DATA_TYPE_UTF8_STRING)

Returns: Error code (0 = success)

Example:

kc_serialized_data_t* data = NULL;
const char* json = "{\"name\":\"Alice\",\"age\":30}";
int result = kc_serialized_data_construct_from_string(&data, json, strlen(json),
                                                     TKC_DATA_TYPE_UTF8_STRING);
if (result == 0) {
    // Use serialized data...
    kc_serialized_data_destruct(&data);
}

kc_serialized_data_destruct()

int kc_serialized_data_destruct(kc_serialized_data_t** serialized_data_ptr)

Destructs a serialized data object and frees its resources.

Parameters:

  • serialized_data_ptr - Pointer to serialized data pointer (set to NULL on success)

Returns: Error code (0 = success)

Content Access Functions

kc_serialized_data_content()

int kc_serialized_data_content(
    const kc_serialized_data_t* serialized_data_ptr,
    char** out_content,
    unsigned int* out_size
)

Gets the raw content of the serialized data.

Parameters:

  • serialized_data_ptr - Serialized data to query

  • out_content - Pointer to content pointer (output, caller must free)

  • out_size - Pointer to content size (output)

Returns: Error code (0 = success)

Example:

char* content = NULL;
unsigned int content_size = 0;
int result = kc_serialized_data_content(data, &content, &content_size);
if (result == 0) {
    printf("Content (%u bytes): %.*s\n", content_size, content_size, content);
    kc_common_delete_buffer(&content);
}

kc_serialized_data_data_type()

int kc_serialized_data_data_type(
    const kc_serialized_data_t* serialized_data_ptr,
    tkc_data_type* out_data_type
)

Gets the data type of the serialized data.

Parameters:

  • serialized_data_ptr - Serialized data to query

  • out_data_type - Pointer to data type (output)

Returns: Error code (0 = success)

kc_serialized_data_encoding()

int kc_serialized_data_encoding(
    const kc_serialized_data_t* serialized_data_ptr,
    tkc_character_encoding* out_encoding
)

Gets the character encoding of the serialized data.

Parameters:

  • serialized_data_ptr - Serialized data to query

  • out_encoding - Pointer to character encoding (output)

Returns: Error code (0 = success)

Example:

tkc_data_type type;
tkc_character_encoding encoding;

int result = kc_serialized_data_data_type(data, &type);
if (result == 0) {
    kc_serialized_data_encoding(data, &encoding);

    printf("Data type: %d\n", type);
    printf("Encoding: %d\n", encoding);

    if (type == TKC_DATA_TYPE_UTF8_STRING && encoding == TKC_CHARACTER_ENCODING_UTF8) {
        printf("Data is a UTF-8 encoded string\n");
    }
}

Serialization Functions

kc_serialized_data_serialize_to_string()

int kc_serialized_data_serialize_to_string(
    const kc_serialized_data_t* serialized_data_ptr,
    char** out_content,
    unsigned int* out_size,
    const tkc_serialization_format serialization_format
)

Serializes the data to a string in the specified format.

Parameters:

  • serialized_data_ptr - Serialized data to convert

  • out_content - Pointer to string pointer (output, caller must free)

  • out_size - Pointer to string size (output)

  • serialization_format - Format for serialization (JSON, XML, or PROTOBUF)

Returns: Error code (0 = success)

Example:

char* json_output = NULL;
unsigned int json_size = 0;
int result = kc_serialized_data_serialize_to_string(data, &json_output, &json_size,
                                                   TKC_SERIALIZATION_FORMAT_JSON);
if (result == 0) {
    printf("As JSON: %.*s\n", json_size, json_output);
    kc_common_delete_buffer(&json_output);
}

Query Functions

kc_serialized_data_equals()

int kc_serialized_data_equals(
    const kc_serialized_data_t* lhs_ptr,
    bool* out_is_equal,
    const kc_serialized_data_t* rhs_ptr
)

Tests equality of two serialized data objects.

Parameters:

  • lhs_ptr - First serialized data to compare

  • out_is_equal - Pointer to equality result (output)

  • rhs_ptr - Second serialized data to compare

Returns: Error code (0 = success)

kc_serialized_data_is_null()

int kc_serialized_data_is_null(
    const kc_serialized_data_t* serialized_data_ptr,
    bool* out_is_null
)

Checks whether the serialized data is null.

Parameters:

  • serialized_data_ptr - Serialized data to check

  • out_is_null - Pointer to null status (output)

Returns: Error code (0 = success)

Type Conversion Functions

kc_serialized_data_to_int32()

int kc_serialized_data_to_int32(
    const kc_serialized_data_t* serialized_data_ptr,
    int32_t* out_value
)

Converts serialized data to a 32-bit integer.

Parameters:

  • serialized_data_ptr - Serialized data containing integer

  • out_value - Pointer to integer value (output)

Returns: Error code (0 = success)

kc_serialized_data_to_int64()

int kc_serialized_data_to_int64(
    const kc_serialized_data_t* serialized_data_ptr,
    int64_t* out_value
)

Converts serialized data to a 64-bit integer.

Parameters:

  • serialized_data_ptr - Serialized data containing integer

  • out_value - Pointer to integer value (output)

Returns: Error code (0 = success)

kc_serialized_data_to_bool()

int kc_serialized_data_to_bool(
    const kc_serialized_data_t* serialized_data_ptr,
    bool* out_value
)

Converts serialized data to a boolean value.

Parameters:

  • serialized_data_ptr - Serialized data containing boolean

  • out_value - Pointer to boolean value (output)

Returns: Error code (0 = success)

Example: Working with Different Data Types

void demonstrate_serialized_data_types() {
    kc_serialized_data_t* string_data = NULL;
    kc_serialized_data_t* int_data = NULL;
    kc_serialized_data_t* bool_data = NULL;
    kc_serialized_data_t* binary_data = NULL;

    // Create string data
    const char* message = "Hello, World!";
    int result = kc_serialized_data_construct_from_string(&string_data,
        message, strlen(message), TKC_DATA_TYPE_UTF8_STRING);
    if (result == 0) {
        printf("Created string data\n");
    }

    // Create integer data
    int32_t number = 42;
    result = kc_serialized_data_construct(&int_data,
        (const char*)&number, sizeof(number),
        TKC_DATA_TYPE_INT32, TKC_CHARACTER_ENCODING_BINARY);
    if (result == 0) {
        printf("Created integer data\n");

        // Read it back
        int32_t read_number = 0;
        if (kc_serialized_data_to_int32(int_data, &read_number) == 0) {
            printf("Integer value: %d\n", read_number);
        }
    }

    // Create boolean data
    bool flag = true;
    result = kc_serialized_data_construct(&bool_data,
        (const char*)&flag, sizeof(flag),
        TKC_DATA_TYPE_BOOLEAN, TKC_CHARACTER_ENCODING_BINARY);
    if (result == 0) {
        printf("Created boolean data\n");

        // Read it back
        bool read_flag = false;
        if (kc_serialized_data_to_bool(bool_data, &read_flag) == 0) {
            printf("Boolean value: %s\n", read_flag ? "true" : "false");
        }
    }

    // Create binary data
    unsigned char binary[] = {0xDE, 0xAD, 0xBE, 0xEF};
    result = kc_serialized_data_construct(&binary_data,
        (const char*)binary, sizeof(binary),
        TKC_DATA_TYPE_BINARY, TKC_CHARACTER_ENCODING_BINARY);
    if (result == 0) {
        printf("Created binary data\n");

        // Get content
        char* content = NULL;
        unsigned int size = 0;
        if (kc_serialized_data_content(binary_data, &content, &size) == 0) {
            printf("Binary data (%u bytes): ", size);
            for (unsigned int i = 0; i < size; i++) {
                printf("%02X ", (unsigned char)content[i]);
            }
            printf("\n");
            kc_common_delete_buffer(&content);
        }
    }

    // Compare data objects
    bool are_equal = false;
    kc_serialized_data_equals(string_data, &are_equal, string_data);
    printf("String data equals itself: %s\n", are_equal ? "yes" : "no");

    kc_serialized_data_equals(string_data, &are_equal, int_data);
    printf("String data equals int data: %s\n", are_equal ? "yes" : "no");

    // Cleanup
    if (string_data) kc_serialized_data_destruct(&string_data);
    if (int_data) kc_serialized_data_destruct(&int_data);
    if (bool_data) kc_serialized_data_destruct(&bool_data);
    if (binary_data) kc_serialized_data_destruct(&binary_data);
}

Example: Serialization Formats

void demonstrate_serialization_formats(kc_serialized_data_t* data) {
    char* output = NULL;
    unsigned int output_size = 0;
    int result;

    // Serialize to JSON
    result = kc_serialized_data_serialize_to_string(data, &output, &output_size,
                                                   TKC_SERIALIZATION_FORMAT_JSON);
    if (result == 0) {
        printf("JSON format (%u bytes):\n%.*s\n", output_size, output_size, output);
        kc_common_delete_buffer(&output);
    }

    // Serialize to XML
    result = kc_serialized_data_serialize_to_string(data, &output, &output_size,
                                                   TKC_SERIALIZATION_FORMAT_XML);
    if (result == 0) {
        printf("\nXML format (%u bytes):\n%.*s\n", output_size, output_size, output);
        kc_common_delete_buffer(&output);
    }

    // Serialize to Protocol Buffers (binary format)
    result = kc_serialized_data_serialize_to_string(data, &output, &output_size,
                                                   TKC_SERIALIZATION_FORMAT_PROTOBUF);
    if (result == 0) {
        printf("\nProtobuf format (%u bytes, binary)\n", output_size);
        kc_common_delete_buffer(&output);
    }
}

Memory Management

  • Use kc_serialized_data_destruct() to free serialized data objects

  • Use kc_common_delete_buffer() for content and string outputs

  • Always check return codes before using output parameters

  • Remember that content retrieved is a copy and must be freed

Best Practices

  • Always specify the correct data type when creating serialized data

  • Use appropriate character encoding for string data (UTF-8 recommended)

  • Validate data types before performing conversions

  • Use serialized data as the common format for all Keychain operations

See Also