Blame egg/egg-hex.c

Packit b00eeb
/*
Packit b00eeb
 * gnome-keyring
Packit b00eeb
 *
Packit b00eeb
 * Copyright (C) 2008 Stefan Walter
Packit b00eeb
 *
Packit b00eeb
 * This program is free software; you can redistribute it and/or modify
Packit b00eeb
 * it under the terms of the GNU Lesser General Public License as
Packit b00eeb
 * published by the Free Software Foundation; either version 2.1 of
Packit b00eeb
 * the License, or (at your option) any later version.
Packit b00eeb
 *
Packit b00eeb
 * This program is distributed in the hope that it will be useful, but
Packit b00eeb
 * WITHOUT ANY WARRANTY; without even the implied warranty of
Packit b00eeb
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit b00eeb
 * Lesser General Public License for more details.
Packit b00eeb
 *
Packit b00eeb
 * You should have received a copy of the GNU Lesser General Public
Packit b00eeb
 * License along with this program; if not, see <http://www.gnu.org/licenses/>.
Packit b00eeb
 */
Packit b00eeb
Packit b00eeb
#include "config.h"
Packit b00eeb
Packit b00eeb
#include "egg-hex.h"
Packit b00eeb
Packit b00eeb
#include <string.h>
Packit b00eeb
Packit b00eeb
static const char HEXC_UPPER[] = "0123456789ABCDEF";
Packit b00eeb
static const char HEXC_LOWER[] = "0123456789abcdef";
Packit b00eeb
Packit b00eeb
gpointer
Packit b00eeb
egg_hex_decode (const gchar *data, gssize n_data, gsize *n_decoded)
Packit b00eeb
{
Packit b00eeb
	return egg_hex_decode_full (data, n_data, 0, 1, n_decoded);
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
gpointer
Packit b00eeb
egg_hex_decode_full (const gchar *data,
Packit b00eeb
                     gssize n_data,
Packit b00eeb
                     const gchar *delim,
Packit b00eeb
                     guint group,
Packit b00eeb
                     gsize *n_decoded)
Packit b00eeb
{
Packit b00eeb
	guchar *result;
Packit b00eeb
	guchar *decoded;
Packit b00eeb
	gsize n_delim;
Packit b00eeb
	gushort j;
Packit b00eeb
	gint state = 0;
Packit b00eeb
	gint part = 0;
Packit b00eeb
	const gchar* pos;
Packit b00eeb
Packit b00eeb
	g_return_val_if_fail (data || !n_data, NULL);
Packit b00eeb
	g_return_val_if_fail (n_decoded, NULL);
Packit b00eeb
	g_return_val_if_fail (group >= 1, NULL);
Packit b00eeb
Packit b00eeb
	if (n_data == -1)
Packit b00eeb
		n_data = strlen (data);
Packit b00eeb
	n_delim = delim ? strlen (delim) : 0;
Packit b00eeb
	decoded = result = g_malloc0 ((n_data / 2) + 1);
Packit b00eeb
	*n_decoded = 0;
Packit b00eeb
Packit b00eeb
	while (n_data > 0 && state == 0) {
Packit b00eeb
Packit b00eeb
		if (decoded != result && delim) {
Packit b00eeb
			if (n_data < n_delim || memcmp (data, delim, n_delim) != 0) {
Packit b00eeb
				state = -1;
Packit b00eeb
				break;
Packit b00eeb
			}
Packit b00eeb
Packit b00eeb
			data += n_delim;
Packit b00eeb
			n_data -= n_delim;
Packit b00eeb
		}
Packit b00eeb
Packit b00eeb
		while (part < group && n_data > 0) {
Packit b00eeb
Packit b00eeb
			/* Find the position */
Packit b00eeb
			pos = strchr (HEXC_UPPER, g_ascii_toupper (*data));
Packit b00eeb
			if (pos == 0) {
Packit b00eeb
				if (n_data > 0)
Packit b00eeb
					state = -1;
Packit b00eeb
				break;
Packit b00eeb
			}
Packit b00eeb
Packit b00eeb
			j = pos - HEXC_UPPER;
Packit b00eeb
			if(!state) {
Packit b00eeb
				*decoded = (j & 0xf) << 4;
Packit b00eeb
				state = 1;
Packit b00eeb
			} else {
Packit b00eeb
				*decoded |= (j & 0xf);
Packit b00eeb
				(*n_decoded)++;
Packit b00eeb
				decoded++;
Packit b00eeb
				state = 0;
Packit b00eeb
				part++;
Packit b00eeb
			}
Packit b00eeb
Packit b00eeb
			++data;
Packit b00eeb
			--n_data;
Packit b00eeb
		}
Packit b00eeb
Packit b00eeb
		part = 0;
Packit b00eeb
	}
Packit b00eeb
Packit b00eeb
	/* Parsing error */
Packit b00eeb
	if (state != 0) {
Packit b00eeb
		g_free (result);
Packit b00eeb
		result = NULL;
Packit b00eeb
	}
Packit b00eeb
Packit b00eeb
	return result;
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
gchar*
Packit b00eeb
egg_hex_encode (gconstpointer data, gsize n_data)
Packit b00eeb
{
Packit b00eeb
	return egg_hex_encode_full (data, n_data, TRUE, NULL, 0);
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
gchar*
Packit b00eeb
egg_hex_encode_full (gconstpointer data,
Packit b00eeb
                     gsize n_data,
Packit b00eeb
                     gboolean upper_case,
Packit b00eeb
                     const gchar *delim,
Packit b00eeb
                     guint group)
Packit b00eeb
{
Packit b00eeb
	GString *result;
Packit b00eeb
	const gchar *input;
Packit b00eeb
	const char *hexc;
Packit b00eeb
	gsize bytes;
Packit b00eeb
	guchar j;
Packit b00eeb
Packit b00eeb
	g_return_val_if_fail (data || !n_data, NULL);
Packit b00eeb
Packit b00eeb
	input = data;
Packit b00eeb
	hexc = upper_case ? HEXC_UPPER : HEXC_LOWER;
Packit b00eeb
Packit b00eeb
	result = g_string_sized_new (n_data * 2 + 1);
Packit b00eeb
	bytes = 0;
Packit b00eeb
Packit b00eeb
	while (n_data > 0) {
Packit b00eeb
Packit b00eeb
		if (delim && group && bytes && (bytes % group) == 0)
Packit b00eeb
			g_string_append (result, delim);
Packit b00eeb
Packit b00eeb
		j = *(input) >> 4 & 0xf;
Packit b00eeb
		g_string_append_c (result, hexc[j]);
Packit b00eeb
Packit b00eeb
		j = *(input++) & 0xf;
Packit b00eeb
		g_string_append_c (result, hexc[j]);
Packit b00eeb
Packit b00eeb
		++bytes;
Packit b00eeb
		--n_data;
Packit b00eeb
	}
Packit b00eeb
Packit b00eeb
	/* Make sure still null terminated */
Packit b00eeb
	return g_string_free (result, FALSE);
Packit b00eeb
}
Packit b00eeb