blob: cc339941f44b8c3514130efe7233b0602ce087c6 [file] [log] [blame]
Harald Welted284cd92010-03-01 21:58:31 +01001
2#include <string.h>
3#include <stdint.h>
4#include <errno.h>
Harald Welteb59f9352010-03-25 11:37:04 +08005#include <stdio.h>
Harald Welted284cd92010-03-01 21:58:31 +01006
Pablo Neira Ayuso83419342011-03-22 16:36:13 +01007#include <osmocom/core/utils.h>
Harald Welted284cd92010-03-01 21:58:31 +01008
Harald Welte8598f182011-08-17 14:19:27 +02009/*! \addtogroup utils
10 * @{
11 */
12
13/*! \file utils.c */
14
Harald Welteb59f9352010-03-25 11:37:04 +080015static char namebuf[255];
Harald Welte8598f182011-08-17 14:19:27 +020016
17/*! \brief get human-readable string for given value
18 * \param[in] vs Array of value_string tuples
19 * \param[in] val Value to be converted
20 * \returns pointer to human-readable string
21 */
Harald Welted284cd92010-03-01 21:58:31 +010022const char *get_value_string(const struct value_string *vs, uint32_t val)
23{
24 int i;
25
26 for (i = 0;; i++) {
27 if (vs[i].value == 0 && vs[i].str == NULL)
28 break;
29 if (vs[i].value == val)
30 return vs[i].str;
31 }
Harald Welteb59f9352010-03-25 11:37:04 +080032
33 snprintf(namebuf, sizeof(namebuf), "unknown 0x%x", val);
Holger Hans Peter Freyther8d506002013-07-04 20:14:10 +020034 namebuf[sizeof(namebuf) - 1] = '\0';
Harald Welteb59f9352010-03-25 11:37:04 +080035 return namebuf;
Harald Welted284cd92010-03-01 21:58:31 +010036}
37
Harald Welte8598f182011-08-17 14:19:27 +020038/*! \brief get numeric value for given human-readable string
39 * \param[in] vs Array of value_string tuples
40 * \param[in] str human-readable string
41 * \returns numeric value (>0) or negative numer in case of error
42 */
Harald Welted284cd92010-03-01 21:58:31 +010043int get_string_value(const struct value_string *vs, const char *str)
44{
45 int i;
46
47 for (i = 0;; i++) {
48 if (vs[i].value == 0 && vs[i].str == NULL)
49 break;
50 if (!strcasecmp(vs[i].str, str))
51 return vs[i].value;
52 }
53 return -EINVAL;
54}
Harald Weltea73e2f92010-03-04 10:50:32 +010055
Harald Welte8598f182011-08-17 14:19:27 +020056/*! \brief Convert BCD-encoded digit into printable character
57 * \param[in] bcd A single BCD-encoded digit
58 * \returns single printable character
59 */
Pablo Neira Ayuso87f7b252011-05-07 12:43:08 +020060char osmo_bcd2char(uint8_t bcd)
Harald Weltea73e2f92010-03-04 10:50:32 +010061{
62 if (bcd < 0xa)
63 return '0' + bcd;
64 else
65 return 'A' + (bcd - 0xa);
66}
67
Harald Weltede6e4982012-12-06 21:25:27 +010068/*! \brief Convert number in ASCII to BCD value
69 * \param[in] c ASCII character
70 * \returns BCD encoded value of character
71 */
Pablo Neira Ayuso87f7b252011-05-07 12:43:08 +020072uint8_t osmo_char2bcd(char c)
Harald Weltea73e2f92010-03-04 10:50:32 +010073{
74 return c - 0x30;
75}
Harald Welte3eba9912010-07-30 10:37:29 +020076
Harald Weltede6e4982012-12-06 21:25:27 +010077/*! \brief Parse a string ocntaining hexadecimal digits
78 * \param[in] str string containing ASCII encoded hexadecimal digits
79 * \param[out] b output buffer
80 * \param[in] max_len maximum space in output buffer
81 */
Pablo Neira Ayuso87f7b252011-05-07 12:43:08 +020082int osmo_hexparse(const char *str, uint8_t *b, int max_len)
Harald Welte3eba9912010-07-30 10:37:29 +020083
84{
85 int i, l, v;
86
87 l = strlen(str);
88 if ((l&1) || ((l>>1) > max_len))
89 return -1;
90
91 memset(b, 0x00, max_len);
92
93 for (i=0; i<l; i++) {
94 char c = str[i];
95 if (c >= '0' && c <= '9')
96 v = c - '0';
97 else if (c >= 'a' && c <= 'f')
98 v = 10 + (c - 'a');
99 else if (c >= 'A' && c <= 'F')
100 v = 10 + (c - 'A');
101 else
102 return -1;
103 b[i>>1] |= v << (i&1 ? 0 : 4);
104 }
105
106 return i>>1;
107}
Harald Welte40481e82010-07-30 11:40:32 +0200108
109static char hexd_buff[4096];
Nils O. Selåsdal32447022014-01-02 14:04:43 +0100110static const char hex_chars[] = "0123456789abcdef";
Harald Welte40481e82010-07-30 11:40:32 +0200111
Pablo Neira Ayuso87f7b252011-05-07 12:43:08 +0200112static char *_osmo_hexdump(const unsigned char *buf, int len, char *delim)
Harald Welte40481e82010-07-30 11:40:32 +0200113{
114 int i;
115 char *cur = hexd_buff;
116
117 hexd_buff[0] = 0;
118 for (i = 0; i < len; i++) {
Nils O. Selåsdal32447022014-01-02 14:04:43 +0100119 const char *delimp = delim;
Harald Welte40481e82010-07-30 11:40:32 +0200120 int len_remain = sizeof(hexd_buff) - (cur - hexd_buff);
Nils O. Selåsdal32447022014-01-02 14:04:43 +0100121 if (len_remain < 3)
Holger Hans Peter Freyther128d9e22011-07-15 16:07:23 +0200122 break;
Nils O. Selåsdal32447022014-01-02 14:04:43 +0100123
124 *cur++ = hex_chars[buf[i] >> 4];
125 *cur++ = hex_chars[buf[i] & 0xf];
126
127 while (len_remain > 1 && *delimp) {
128 *cur++ = *delimp++;
129 len_remain--;
130 }
131
132 *cur = 0;
Harald Welte40481e82010-07-30 11:40:32 +0200133 }
134 hexd_buff[sizeof(hexd_buff)-1] = 0;
135 return hexd_buff;
136}
Harald Weltedee47cd2010-07-30 11:43:30 +0200137
Harald Welte8598f182011-08-17 14:19:27 +0200138/*! \brief Convert a sequence of unpacked bits to ASCII string
139 * \param[in] bits A sequence of unpacked bits
140 * \param[in] len Length of bits
141 */
Pablo Neira Ayuso87f7b252011-05-07 12:43:08 +0200142char *osmo_ubit_dump(const uint8_t *bits, unsigned int len)
Harald Welte3d0ac5e2011-02-08 16:55:03 +0100143{
144 int i;
145
146 if (len > sizeof(hexd_buff)-1)
147 len = sizeof(hexd_buff)-1;
148 memset(hexd_buff, 0, sizeof(hexd_buff));
149
150 for (i = 0; i < len; i++) {
151 char outch;
152 switch (bits[i]) {
153 case 0:
154 outch = '0';
155 break;
156 case 0xff:
157 outch = '?';
158 break;
159 case 1:
160 outch = '1';
161 break;
162 default:
163 outch = 'E';
164 break;
165 }
166 hexd_buff[i] = outch;
167 }
168 hexd_buff[sizeof(hexd_buff)-1] = 0;
169 return hexd_buff;
170}
171
Harald Welte8598f182011-08-17 14:19:27 +0200172/*! \brief Convert binary sequence to hexadecimal ASCII string
173 * \param[in] buf pointer to sequence of bytes
174 * \param[in] len length of buf in number of bytes
175 * \returns pointer to zero-terminated string
176 *
177 * This function will print a sequence of bytes as hexadecimal numbers,
178 * adding one space character between each byte (e.g. "1a ef d9")
179 */
Pablo Neira Ayuso87f7b252011-05-07 12:43:08 +0200180char *osmo_hexdump(const unsigned char *buf, int len)
Harald Weltedee47cd2010-07-30 11:43:30 +0200181{
Pablo Neira Ayuso87f7b252011-05-07 12:43:08 +0200182 return _osmo_hexdump(buf, len, " ");
Harald Weltedee47cd2010-07-30 11:43:30 +0200183}
184
Harald Welte8598f182011-08-17 14:19:27 +0200185/*! \brief Convert binary sequence to hexadecimal ASCII string
186 * \param[in] buf pointer to sequence of bytes
187 * \param[in] len length of buf in number of bytes
188 * \returns pointer to zero-terminated string
189 *
190 * This function will print a sequence of bytes as hexadecimal numbers,
191 * without any space character between each byte (e.g. "1aefd9")
192 */
Sylvain Munautff23d242011-11-10 23:03:18 +0100193char *osmo_hexdump_nospc(const unsigned char *buf, int len)
Harald Weltedee47cd2010-07-30 11:43:30 +0200194{
Pablo Neira Ayuso87f7b252011-05-07 12:43:08 +0200195 return _osmo_hexdump(buf, len, "");
Harald Weltedee47cd2010-07-30 11:43:30 +0200196}
Harald Welte28222962011-02-18 20:37:04 +0100197
Sylvain Munaute55ae3a2011-11-11 23:06:55 +0100198 /* Compat with previous typo to preserve abi */
199char *osmo_osmo_hexdump_nospc(const unsigned char *buf, int len)
Sylvain Munaut17af41d2011-11-19 22:30:39 +0100200 __attribute__((weak, alias("osmo_hexdump_nospc")));
Sylvain Munaute55ae3a2011-11-11 23:06:55 +0100201
Harald Welte28222962011-02-18 20:37:04 +0100202#include "../config.h"
203#ifdef HAVE_CTYPE_H
204#include <ctype.h>
Harald Welte8598f182011-08-17 14:19:27 +0200205/*! \brief Convert an entire string to lower case
206 * \param[out] out output string, caller-allocated
207 * \param[in] in input string
208 */
Harald Welte28222962011-02-18 20:37:04 +0100209void osmo_str2lower(char *out, const char *in)
210{
211 unsigned int i;
212
213 for (i = 0; i < strlen(in); i++)
214 out[i] = tolower(in[i]);
215 out[strlen(in)] = '\0';
216}
217
Harald Welte8598f182011-08-17 14:19:27 +0200218/*! \brief Convert an entire string to upper case
219 * \param[out] out output string, caller-allocated
220 * \param[in] in input string
221 */
Harald Welte28222962011-02-18 20:37:04 +0100222void osmo_str2upper(char *out, const char *in)
223{
224 unsigned int i;
225
226 for (i = 0; i < strlen(in); i++)
227 out[i] = toupper(in[i]);
228 out[strlen(in)] = '\0';
229}
230#endif /* HAVE_CTYPE_H */
Harald Welte8598f182011-08-17 14:19:27 +0200231
Sylvain Munautdca7d2c2012-04-18 21:53:23 +0200232/*! @} */