From 367a367ff969a111a215f71c2cb3e3ef8057af8b Mon Sep 17 00:00:00 2001 From: nirenjan Date: Thu, 10 Dec 2015 09:56:15 -0800 Subject: [PATCH] Add table walker to libx52util This file walks the generated table to find the corresponding character map values for the given UTF-8 string. --- util/libx52util.h | 43 +++++++++++++++++++ util/x52_char_map.h | 2 + util/x52_char_map_lookup.c | 86 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 131 insertions(+) create mode 100644 util/libx52util.h create mode 100644 util/x52_char_map_lookup.c diff --git a/util/libx52util.h b/util/libx52util.h new file mode 100644 index 0000000..1ff27a2 --- /dev/null +++ b/util/libx52util.h @@ -0,0 +1,43 @@ +/* + * Saitek X52 Pro Utility Library + * + * Copyright (C) 2015 Nirenjan Krishnan (nirenjan@nirenjan.org) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2. + * + */ + +#ifndef LIBX52UTIL_H +#define LIBX52UTIL_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Convert UTF8 string to X52 character map. + * + * This function takes in a UTF-8 string and converts it to the character + * map used by the X52Pro MFD. Unrecognized characters are silently dropped. + * + * @param[in] input Input string in UTF-8. Must be NUL-terminated + * @param[out] output Output buffer + * @param[inout] len Length of output buffer + * + * @returns 0 on success, -EINVAL on invalid parameters, -E2BIG if the buffer + * filled up before converting the entire string. + */ +int libx52util_convert_utf8_string(const uint8_t *input, + uint8_t *output, size_t *len); + +#ifdef __cplusplus +} +#endif + +#endif /* !defined LIBX52UTIL_H */ + diff --git a/util/x52_char_map.h b/util/x52_char_map.h index b5892a3..eba2ae2 100644 --- a/util/x52_char_map.h +++ b/util/x52_char_map.h @@ -29,4 +29,6 @@ struct map_entry { uint8_t value; /* Value is valid if this is of TYPE_ENTRY */ }; +extern struct map_entry map_root[]; + #endif /* !defined X52_CHAR_MAP_H */ diff --git a/util/x52_char_map_lookup.c b/util/x52_char_map_lookup.c new file mode 100644 index 0000000..267d740 --- /dev/null +++ b/util/x52_char_map_lookup.c @@ -0,0 +1,86 @@ +/* + * Saitek X52 Pro Character Map Lookup + * + * This file implements functions to perform a lookup of a UTF-8 character + * in the generated lookup table. + * + * Copyright (C) 2015 Nirenjan Krishnan (nirenjan@nirenjan.org) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2. + * + */ + +#include +#include + +#include "libx52util.h" +#include "x52_char_map.h" + +/** + * @brief Convert UTF8 string to X52 character map. + * + * This function takes in a UTF-8 string and converts it to the character + * map used by the X52Pro MFD. Unrecognized characters are silently dropped. + * + * @param[in] input Input string in UTF-8. Must be NUL-terminated + * @param[out] output Output buffer + * @param[inout] len Length of output buffer + * + * @returns 0 on success, -EINVAL on invalid parameters, -E2BIG if the buffer + * filled up before converting the entire string. + */ +int libx52util_convert_utf8_string(const uint8_t *input, + uint8_t *output, size_t *len) +{ + struct map_entry *entry; + size_t index; + int retval = 0; + unsigned char local_index; + + if (!input || !output || !len || !*len) { + return -EINVAL; + } + + index = 0; + entry = &map_root[*input]; + while (*input) { + input++; + if (entry->type == TYPE_ENTRY) { + output[index] = entry->value; + index++; + if (index >= *len) { + retval = -E2BIG; + break; + } + entry = &map_root[*input]; + } else if (entry->type == TYPE_POINTER) { + local_index = *input; + if (local_index < 0x80 || local_index >= 0xC0) { + /* Invalid input, skip till we find the start of another + * valid UTF-8 character + */ + while (*input >= 0x80 && *input < 0xC0) { + input++; /* Skip invalid characters */ + } + + /* New UTF-8 character, reset the entry pointer */ + entry = &map_root[*input]; + } else { + /* Mask off the upper bits, we only care about the lower 6 bits */ + local_index &= 0x3F; + entry = &(entry->next[local_index]); + } + } else { + /* Invalid value, skip */ + while (*input >= 0x80 && *input < 0xC0) { + input++; /* Skip invalid characters */ + } + } + } + + *len = index; + return retval; +} +