blob: c36979c91c460734e5eee095f316c1889781bf26 [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);
34 return namebuf;
Harald Welted284cd92010-03-01 21:58:31 +010035}
36
Harald Welte8598f182011-08-17 14:19:27 +020037/*! \brief get numeric value for given human-readable string
38 * \param[in] vs Array of value_string tuples
39 * \param[in] str human-readable string
40 * \returns numeric value (>0) or negative numer in case of error
41 */
Harald Welted284cd92010-03-01 21:58:31 +010042int get_string_value(const struct value_string *vs, const char *str)
43{
44 int i;
45
46 for (i = 0;; i++) {
47 if (vs[i].value == 0 && vs[i].str == NULL)
48 break;
49 if (!strcasecmp(vs[i].str, str))
50 return vs[i].value;
51 }
52 return -EINVAL;
53}
Harald Weltea73e2f92010-03-04 10:50:32 +010054
Harald Welte8598f182011-08-17 14:19:27 +020055/*! \brief Convert BCD-encoded digit into printable character
56 * \param[in] bcd A single BCD-encoded digit
57 * \returns single printable character
58 */
Pablo Neira Ayuso87f7b252011-05-07 12:43:08 +020059char osmo_bcd2char(uint8_t bcd)
Harald Weltea73e2f92010-03-04 10:50:32 +010060{
61 if (bcd < 0xa)
62 return '0' + bcd;
63 else
64 return 'A' + (bcd - 0xa);
65}
66
Harald Weltede6e4982012-12-06 21:25:27 +010067/*! \brief Convert number in ASCII to BCD value
68 * \param[in] c ASCII character
69 * \returns BCD encoded value of character
70 */
Pablo Neira Ayuso87f7b252011-05-07 12:43:08 +020071uint8_t osmo_char2bcd(char c)
Harald Weltea73e2f92010-03-04 10:50:32 +010072{
73 return c - 0x30;
74}
Harald Welte3eba9912010-07-30 10:37:29 +020075
Harald Weltede6e4982012-12-06 21:25:27 +010076/*! \brief Parse a string ocntaining hexadecimal digits
77 * \param[in] str string containing ASCII encoded hexadecimal digits
78 * \param[out] b output buffer
79 * \param[in] max_len maximum space in output buffer
80 */
Pablo Neira Ayuso87f7b252011-05-07 12:43:08 +020081int osmo_hexparse(const char *str, uint8_t *b, int max_len)
Harald Welte3eba9912010-07-30 10:37:29 +020082
83{
84 int i, l, v;
85
86 l = strlen(str);
87 if ((l&1) || ((l>>1) > max_len))
88 return -1;
89
90 memset(b, 0x00, max_len);
91
92 for (i=0; i<l; i++) {
93 char c = str[i];
94 if (c >= '0' && c <= '9')
95 v = c - '0';
96 else if (c >= 'a' && c <= 'f')
97 v = 10 + (c - 'a');
98 else if (c >= 'A' && c <= 'F')
99 v = 10 + (c - 'A');
100 else
101 return -1;
102 b[i>>1] |= v << (i&1 ? 0 : 4);
103 }
104
105 return i>>1;
106}
Harald Welte40481e82010-07-30 11:40:32 +0200107
108static char hexd_buff[4096];
109
Pablo Neira Ayuso87f7b252011-05-07 12:43:08 +0200110static char *_osmo_hexdump(const unsigned char *buf, int len, char *delim)
Harald Welte40481e82010-07-30 11:40:32 +0200111{
112 int i;
113 char *cur = hexd_buff;
114
115 hexd_buff[0] = 0;
116 for (i = 0; i < len; i++) {
117 int len_remain = sizeof(hexd_buff) - (cur - hexd_buff);
Holger Hans Peter Freyther128d9e22011-07-15 16:07:23 +0200118 if (len_remain <= 0)
119 break;
Harald Weltedee47cd2010-07-30 11:43:30 +0200120 int rc = snprintf(cur, len_remain, "%02x%s", buf[i], delim);
Harald Welte40481e82010-07-30 11:40:32 +0200121 if (rc <= 0)
122 break;
123 cur += rc;
124 }
125 hexd_buff[sizeof(hexd_buff)-1] = 0;
126 return hexd_buff;
127}
Harald Weltedee47cd2010-07-30 11:43:30 +0200128
Harald Welte8598f182011-08-17 14:19:27 +0200129/*! \brief Convert a sequence of unpacked bits to ASCII string
130 * \param[in] bits A sequence of unpacked bits
131 * \param[in] len Length of bits
132 */
Pablo Neira Ayuso87f7b252011-05-07 12:43:08 +0200133char *osmo_ubit_dump(const uint8_t *bits, unsigned int len)
Harald Welte3d0ac5e2011-02-08 16:55:03 +0100134{
135 int i;
136
137 if (len > sizeof(hexd_buff)-1)
138 len = sizeof(hexd_buff)-1;
139 memset(hexd_buff, 0, sizeof(hexd_buff));
140
141 for (i = 0; i < len; i++) {
142 char outch;
143 switch (bits[i]) {
144 case 0:
145 outch = '0';
146 break;
147 case 0xff:
148 outch = '?';
149 break;
150 case 1:
151 outch = '1';
152 break;
153 default:
154 outch = 'E';
155 break;
156 }
157 hexd_buff[i] = outch;
158 }
159 hexd_buff[sizeof(hexd_buff)-1] = 0;
160 return hexd_buff;
161}
162
Harald Welte8598f182011-08-17 14:19:27 +0200163/*! \brief Convert binary sequence to hexadecimal ASCII string
164 * \param[in] buf pointer to sequence of bytes
165 * \param[in] len length of buf in number of bytes
166 * \returns pointer to zero-terminated string
167 *
168 * This function will print a sequence of bytes as hexadecimal numbers,
169 * adding one space character between each byte (e.g. "1a ef d9")
170 */
Pablo Neira Ayuso87f7b252011-05-07 12:43:08 +0200171char *osmo_hexdump(const unsigned char *buf, int len)
Harald Weltedee47cd2010-07-30 11:43:30 +0200172{
Pablo Neira Ayuso87f7b252011-05-07 12:43:08 +0200173 return _osmo_hexdump(buf, len, " ");
Harald Weltedee47cd2010-07-30 11:43:30 +0200174}
175
Harald Welte8598f182011-08-17 14:19:27 +0200176/*! \brief Convert binary sequence to hexadecimal ASCII string
177 * \param[in] buf pointer to sequence of bytes
178 * \param[in] len length of buf in number of bytes
179 * \returns pointer to zero-terminated string
180 *
181 * This function will print a sequence of bytes as hexadecimal numbers,
182 * without any space character between each byte (e.g. "1aefd9")
183 */
Sylvain Munautff23d242011-11-10 23:03:18 +0100184char *osmo_hexdump_nospc(const unsigned char *buf, int len)
Harald Weltedee47cd2010-07-30 11:43:30 +0200185{
Pablo Neira Ayuso87f7b252011-05-07 12:43:08 +0200186 return _osmo_hexdump(buf, len, "");
Harald Weltedee47cd2010-07-30 11:43:30 +0200187}
Harald Welte28222962011-02-18 20:37:04 +0100188
Sylvain Munaute55ae3a2011-11-11 23:06:55 +0100189 /* Compat with previous typo to preserve abi */
190char *osmo_osmo_hexdump_nospc(const unsigned char *buf, int len)
Sylvain Munaut17af41d2011-11-19 22:30:39 +0100191 __attribute__((weak, alias("osmo_hexdump_nospc")));
Sylvain Munaute55ae3a2011-11-11 23:06:55 +0100192
Harald Welte28222962011-02-18 20:37:04 +0100193#include "../config.h"
194#ifdef HAVE_CTYPE_H
195#include <ctype.h>
Harald Welte8598f182011-08-17 14:19:27 +0200196/*! \brief Convert an entire string to lower case
197 * \param[out] out output string, caller-allocated
198 * \param[in] in input string
199 */
Harald Welte28222962011-02-18 20:37:04 +0100200void osmo_str2lower(char *out, const char *in)
201{
202 unsigned int i;
203
204 for (i = 0; i < strlen(in); i++)
205 out[i] = tolower(in[i]);
206 out[strlen(in)] = '\0';
207}
208
Harald Welte8598f182011-08-17 14:19:27 +0200209/*! \brief Convert an entire string to upper case
210 * \param[out] out output string, caller-allocated
211 * \param[in] in input string
212 */
Harald Welte28222962011-02-18 20:37:04 +0100213void osmo_str2upper(char *out, const char *in)
214{
215 unsigned int i;
216
217 for (i = 0; i < strlen(in); i++)
218 out[i] = toupper(in[i]);
219 out[strlen(in)] = '\0';
220}
221#endif /* HAVE_CTYPE_H */
Harald Welte8598f182011-08-17 14:19:27 +0200222
Sylvain Munautdca7d2c2012-04-18 21:53:23 +0200223/*! @} */