/*- * $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 * Copyright (c) 2002 Daniel Lundin * Copyright (c) 2002 CodeFactory AB. All rights reserved. */ #include #include #include 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; }