/*-
* $Id: rr-framefactory.c,v 1.11 2002/05/11 17:54:01 jonas Exp $
*
* See the file LICENSE for redistribution information.
* If you have not received a copy of the license, please contact CodeFactory
* by email at info@codefactory.se, or on the web at http://www.codefactory.se/
* You may also write to: CodeFactory AB, SE-903 47, Umeå, Sweden.
*
* Copyright (c) 2002 Jonas Borgström <jonas@codefactory.se>
* Copyright (c) 2002 Daniel Lundin <daniel@codefactory.se>
* Copyright (c) 2002 CodeFactory AB. All rights reserved.
*/
#include <librr/rr.h>
#include <stdio.h>
#include <string.h>
static GStaticRWLock rwlock = G_STATIC_RW_LOCK_INIT;
static GSList *frame_types = NULL; /* Protected by the rwlock above */
typedef struct {
const gchar *header_id;
GType type;
} FrameTypeInfo;
static GType
get_frame_type (const guint8 *buffer)
{
char str[4];
GSList *list;
FrameTypeInfo *info;
GType type = G_TYPE_INVALID;
g_return_val_if_fail (buffer != NULL, type);
if (sscanf (buffer, "%3s", str) != 1) {
return G_TYPE_INVALID;
}
g_static_rw_lock_reader_lock (&rwlock);
list = frame_types;
while (list) {
info = list->data;
if (strcmp (info->header_id, str) == 0) {
type = info->type;
break;
}
list = list->next;
}
g_static_rw_lock_reader_unlock (&rwlock);
return type;
}
void
rr_framefactory_register_type (const gchar *header_id, GType type)
{
FrameTypeInfo *info;
info = g_new (FrameTypeInfo, 1);
g_return_if_fail (info != NULL);
info->header_id = header_id;
info->type = type;
g_static_rw_lock_writer_lock (&rwlock);
frame_types = g_slist_append (frame_types, info);
g_static_rw_lock_writer_unlock (&rwlock);
}
static const gchar *
find_body (const gchar *str, gint len)
{
const gchar *end = str + len;
while (str < end) {
if (*str == '\n')
return str + 1;
if (*str == 0)
return NULL;
str++;
}
return 0;
}
gint
rr_framefactory_parse_frame (RRConnection *conn, const gchar *buffer,
gint len, RRFrame **frame, GError **error)
{
GType type;
const gchar *body;
gint header_len;
gint bytes;
g_return_val_if_fail (RR_IS_CONNECTION (conn), 0);
g_return_val_if_fail (buffer != 0, 0);
g_return_val_if_fail (len > 0, 0);
g_return_val_if_fail (frame != NULL, 0);
*frame = NULL;
body = find_body (buffer, len);
/* Not enough data for a complete header */
if (body == NULL)
return 0;
header_len = body - buffer;
type = get_frame_type (buffer);
if (type == G_TYPE_INVALID) {
g_set_error (error, RR_BEEP_ERROR, RR_BEEP_CODE_SYNTAX_ERROR,
"Frame header parse error");
return -1;
}
g_return_val_if_fail (type != G_TYPE_INVALID, 0);
*frame = g_object_new (type, NULL);
g_return_val_if_fail (RR_IS_FRAME (*frame), 0);
bytes = rr_frame_parse (*frame, buffer, body, len, error);
if (bytes <= 0) {
g_object_unref (G_OBJECT (*frame));
*frame = NULL;
return bytes;
}
return bytes;
}
syntax highlighted by Code2HTML, v. 0.9.1