Inital Packaging on 0.10
[platform/upstream/libsecret.git] / egg / egg-hex.c
1 /*
2  * gnome-keyring
3  *
4  * Copyright (C) 2008 Stefan Walter
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as
8  * published by the Free Software Foundation; either version 2.1 of
9  * the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19  * MA 02110-1301 USA
20  *
21  * Author: Stef Walter <stefw@thewalter.net>
22  */
23
24 #include "config.h"
25
26 #include "egg-hex.h"
27
28 #include <string.h>
29
30 static const char HEXC_UPPER[] = "0123456789ABCDEF";
31 static const char HEXC_LOWER[] = "0123456789abcdef";
32
33 gpointer
34 egg_hex_decode (const gchar *data, gssize n_data, gsize *n_decoded)
35 {
36         return egg_hex_decode_full (data, n_data, 0, 1, n_decoded);
37 }
38
39 gpointer
40 egg_hex_decode_full (const gchar *data,
41                      gssize n_data,
42                      const gchar *delim,
43                      guint group,
44                      gsize *n_decoded)
45 {
46         guchar *result;
47         guchar *decoded;
48         gsize n_delim;
49         gushort j;
50         gint state = 0;
51         gint part = 0;
52         const gchar* pos;
53
54         g_return_val_if_fail (data || !n_data, NULL);
55         g_return_val_if_fail (n_decoded, NULL);
56         g_return_val_if_fail (group >= 1, NULL);
57
58         if (n_data == -1)
59                 n_data = strlen (data);
60         n_delim = delim ? strlen (delim) : 0;
61         decoded = result = g_malloc0 ((n_data / 2) + 1);
62         *n_decoded = 0;
63
64         while (n_data > 0 && state == 0) {
65
66                 if (decoded != result && delim) {
67                         if (n_data < n_delim || memcmp (data, delim, n_delim) != 0) {
68                                 state = -1;
69                                 break;
70                         }
71
72                         data += n_delim;
73                         n_data -= n_delim;
74                 }
75
76                 while (part < group && n_data > 0) {
77
78                         /* Find the position */
79                         pos = strchr (HEXC_UPPER, g_ascii_toupper (*data));
80                         if (pos == 0) {
81                                 if (n_data > 0)
82                                         state = -1;
83                                 break;
84                         }
85
86                         j = pos - HEXC_UPPER;
87                         if(!state) {
88                                 *decoded = (j & 0xf) << 4;
89                                 state = 1;
90                         } else {
91                                 *decoded |= (j & 0xf);
92                                 (*n_decoded)++;
93                                 decoded++;
94                                 state = 0;
95                                 part++;
96                         }
97
98                         ++data;
99                         --n_data;
100                 }
101
102                 part = 0;
103         }
104
105         /* Parsing error */
106         if (state != 0) {
107                 g_free (result);
108                 result = NULL;
109         }
110
111         return result;
112 }
113
114 gchar*
115 egg_hex_encode (gconstpointer data, gsize n_data)
116 {
117         return egg_hex_encode_full (data, n_data, TRUE, NULL, 0);
118 }
119
120 gchar*
121 egg_hex_encode_full (gconstpointer data,
122                      gsize n_data,
123                      gboolean upper_case,
124                      const gchar *delim,
125                      guint group)
126 {
127         GString *result;
128         const gchar *input;
129         const char *hexc;
130         gsize bytes;
131         guchar j;
132
133         g_return_val_if_fail (data || !n_data, NULL);
134
135         input = data;
136         hexc = upper_case ? HEXC_UPPER : HEXC_LOWER;
137
138         result = g_string_sized_new (n_data * 2 + 1);
139         bytes = 0;
140
141         while (n_data > 0) {
142
143                 if (delim && group && bytes && (bytes % group) == 0)
144                         g_string_append (result, delim);
145
146                 j = *(input) >> 4 & 0xf;
147                 g_string_append_c (result, hexc[j]);
148
149                 j = *(input++) & 0xf;
150                 g_string_append_c (result, hexc[j]);
151
152                 ++bytes;
153                 --n_data;
154         }
155
156         /* Make sure still null terminated */
157         return g_string_free (result, FALSE);
158 }
159