nexmon – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | /* source: xio-ascii.c */ |
2 | /* Copyright Gerhard Rieger */ |
||
3 | /* Published under the GNU General Public License V.2, see file COPYING */ |
||
4 | |||
5 | /* this file contains functions for text encoding, decoding, and conversions */ |
||
6 | |||
7 | |||
8 | #include <stddef.h> |
||
9 | #include <ctype.h> |
||
10 | #include <stdio.h> |
||
11 | |||
12 | #include "xio-ascii.h" |
||
13 | |||
14 | /* for each 6 bit pattern we have an ASCII character in the arry */ |
||
15 | const static int base64chars[] = { |
||
16 | 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', |
||
17 | 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', |
||
18 | 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', |
||
19 | 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', |
||
20 | 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', |
||
21 | 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', |
||
22 | 'w', 'x', 'y', 'z', '0', '1', '2', '3', |
||
23 | '4', '5', '6', '7', '8', '9', '+', '/', |
||
24 | } ; |
||
25 | |||
26 | #define CHAR64(c) (base64chars[c]) |
||
27 | |||
28 | char * |
||
29 | xiob64encodeline(const char *data, /* input data */ |
||
30 | size_t bytes, /* length of input data, >=0 */ |
||
31 | char *coded /* output buffer, must be long enough */ |
||
32 | ) { |
||
33 | int c1, c2, c3; |
||
34 | |||
35 | while (bytes > 0) { |
||
36 | c1 = *data++; |
||
37 | *coded++ = CHAR64(c1>>2); |
||
38 | if (--bytes == 0) { |
||
39 | *coded++ = CHAR64((c1&0x03)<<4); |
||
40 | *coded++ = '='; |
||
41 | *coded++ = '='; |
||
42 | } else { |
||
43 | c2 = *data++; |
||
44 | *coded++ = CHAR64(((c1&0x03)<<4)|(c2>>4)); |
||
45 | if (--bytes == 0) { |
||
46 | *coded++ = CHAR64((c2&0x0f)<<2); |
||
47 | *coded++ = '='; |
||
48 | } else { |
||
49 | c3 = *data++; --bytes; |
||
50 | *coded++ = CHAR64(((c2&0x0f)<<2)|(c3>>6)); |
||
51 | *coded++ = CHAR64(c3&0x3f); |
||
52 | } |
||
53 | } |
||
54 | } |
||
55 | return coded; |
||
56 | } |
||
57 | |||
58 | |||
59 | |||
60 | /* sanitize "untrusted" text, replacing special control characters with the C |
||
61 | string version ("\x"), and replacing unprintable chars with ".". |
||
62 | text can grow to double size, so keep output buffer long enough! |
||
63 | returns a pointer to the first untouched byte of the output buffer. |
||
64 | */ |
||
65 | char *xiosanitize(const char *data, /* input data */ |
||
66 | size_t bytes, /* length of input data, >=0 */ |
||
67 | char *coded /* output buffer, must be long enough */ |
||
68 | ) { |
||
69 | int c; |
||
70 | |||
71 | while (bytes > 0) { |
||
72 | c = *(unsigned char *)data++; |
||
73 | switch (c) { |
||
74 | case '\0' : *coded++ = '\\'; *coded++ = '0'; break; |
||
75 | case '\a' : *coded++ = '\\'; *coded++ = 'a'; break; |
||
76 | case '\b' : *coded++ = '\\'; *coded++ = 'b'; break; |
||
77 | case '\t' : *coded++ = '\\'; *coded++ = 't'; break; |
||
78 | case '\n' : *coded++ = '\\'; *coded++ = 'n'; break; |
||
79 | case '\v' : *coded++ = '\\'; *coded++ = 'v'; break; |
||
80 | case '\f' : *coded++ = '\\'; *coded++ = 'f'; break; |
||
81 | case '\r' : *coded++ = '\\'; *coded++ = 'r'; break; |
||
82 | case '\'' : *coded++ = '\\'; *coded++ = '\''; break; |
||
83 | case '\"' : *coded++ = '\\'; *coded++ = '"'; break; |
||
84 | case '\\' : *coded++ = '\\'; *coded++ = '\\'; break; |
||
85 | default: |
||
86 | if (!isprint(c)) |
||
87 | c = '.'; |
||
88 | *coded++ = c; |
||
89 | break; |
||
90 | } |
||
91 | --bytes; |
||
92 | } |
||
93 | return coded; |
||
94 | } |
||
95 | |||
96 | |||
97 | /* print the bytes in hex */ |
||
98 | char * |
||
99 | xiohexdump(const unsigned char *data, size_t bytes, char *coded) { |
||
100 | int space = 0; |
||
101 | while (bytes-- > 0) { |
||
102 | if (space) { *coded++ = ' '; } |
||
103 | coded += sprintf(coded, "%02x", *data++); |
||
104 | space = 1; |
||
105 | } |
||
106 | return coded; |
||
107 | } |
||
108 | |||
109 | /* write the binary data to output buffer codbuff in human readable form. |
||
110 | bytes gives the length of the data, codlen the available space in codbuff. |
||
111 | coding specifies how the data is to be presented. Not much to select now. |
||
112 | returns a pointer to the first char in codbuff that has not been overwritten; |
||
113 | it might also point to the first char after the buffer! |
||
114 | this function does not write a terminating \0 |
||
115 | */ |
||
116 | static char * |
||
117 | _xiodump(const unsigned char *data, size_t bytes, char *codbuff, size_t codlen, |
||
118 | int coding) { |
||
119 | int start = 1; |
||
120 | int space = coding & 0xff; |
||
121 | |||
122 | if (bytes <= 0) { return codbuff; } |
||
123 | if (codlen < 1) { return codbuff; } |
||
124 | if (space == 0) space = -1; |
||
125 | if (0) { |
||
126 | ; /* for canonical reasons */ |
||
127 | } else if (1) { |
||
128 | /* simple hexadecimal output */ |
||
129 | if (3*bytes+1 > codlen) { |
||
130 | bytes = (codlen-1)/3; /* "truncate" data so generated text fits */ |
||
131 | } |
||
132 | *codbuff++ = 'x'; |
||
133 | while (bytes-- > 0) { |
||
134 | if (start == 0 && space == 0) { |
||
135 | *codbuff++ = ' '; |
||
136 | space = (coding & 0xff); |
||
137 | } |
||
138 | codbuff += sprintf(codbuff, "%02x", *data++); |
||
139 | start = 0; |
||
140 | } |
||
141 | } |
||
142 | return codbuff; |
||
143 | } |
||
144 | |||
145 | /* write the binary data to codbuff in human readable form. |
||
146 | bytes gives the length of the data, codlen the available space in codbuff. |
||
147 | coding specifies how the data is to be presented. Not much to select now. |
||
148 | null terminates the output. returns a pointer to the output string. |
||
149 | */ |
||
150 | char * |
||
151 | xiodump(const unsigned char *data, size_t bytes, char *codbuff, size_t codlen, |
||
152 | int coding) { |
||
153 | char *result; |
||
154 | |||
155 | result = _xiodump(data, bytes, codbuff, codlen-1, coding); |
||
156 | *result = '\0'; |
||
157 | return codbuff; |
||
158 | } |