-
Notifications
You must be signed in to change notification settings - Fork 14
/
Copy pathx52_char_map_lookup.c
84 lines (76 loc) · 2.46 KB
/
x52_char_map_lookup.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
/*
* 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 ([email protected])
*
* SPDX-License-Identifier: GPL-2.0-only WITH Classpath-exception-2.0
*/
#include "config.h"
#include <stdint.h>
#include <errno.h>
#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;
}