#include #include #include "gm-mcp-icecrew-playerdb.h" #include "gm-mcp.h" #include "gm-marshal.h" #include "gm-debug.h" #include "gm-support.h" #include "gm-string.h" #define GM_MCP_ICECREW_PLAYERDB_GET_PRIVATE(object)( \ G_TYPE_INSTANCE_GET_PRIVATE((object), \ GM_TYPE_MCP_ICECREW_PLAYERDB, GmMcpIcecrewPlayerdbPrivate)) struct _GmMcpIcecrewPlayerdbPrivate { gint self; GList *db; GList *last_init_keys; }; /* Signals */ enum { ADD, SET, DELETE, NUM_SIGNALS }; static guint gm_mcp_icecrew_playerdb_signals[NUM_SIGNALS] = {0}; G_DEFINE_TYPE(GmMcpIcecrewPlayerdb, gm_mcp_icecrew_playerdb, GM_TYPE_MCP_PACKAGE) void gm_mcp_icecrew_playerdb_handle_simple(GmMcpPackage *package, gchar *suffix, GList *fields); gboolean gm_mcp_icecrew_playerdb_handle_multi(GmMcpPackage *package, gchar const *data_tag, gchar const *key, gchar const *value, GList *all_values); static void gm_mcp_icecrew_playerdb_finalize(GObject *object) { GmMcpIcecrewPlayerdb *obj = GM_MCP_ICECREW_PLAYERDB(object); GmPlayerdbPlayerInfo *ppi; GList *f; for (f = obj->priv->db; f; f = f->next) { ppi = (GmPlayerdbPlayerInfo *)(f->data); g_hash_table_destroy(ppi->values); g_free(ppi); } g_list_free(obj->priv->db); gm_mcp_list_free(obj->priv->last_init_keys); G_OBJECT_CLASS(gm_mcp_icecrew_playerdb_parent_class)->finalize(object); } static void gm_mcp_icecrew_playerdb_class_init(GmMcpIcecrewPlayerdbClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS(klass); GmMcpPackageClass *pklass = GM_MCP_PACKAGE_CLASS(klass); object_class->finalize = gm_mcp_icecrew_playerdb_finalize; gm_mcp_icecrew_playerdb_signals[ADD] = g_signal_new("add", G_OBJECT_CLASS_TYPE(object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(GmMcpIcecrewPlayerdbClass, add), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); gm_mcp_icecrew_playerdb_signals[SET] = g_signal_new("set", G_OBJECT_CLASS_TYPE(object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(GmMcpIcecrewPlayerdbClass, set), NULL, NULL, gm_marshal_VOID__POINTER_STRING_STRING_STRING, G_TYPE_NONE, 4, G_TYPE_POINTER, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING); gm_mcp_icecrew_playerdb_signals[DELETE] = g_signal_new("delete", G_OBJECT_CLASS_TYPE(object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(GmMcpIcecrewPlayerdbClass, delete), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); pklass->name = "dns-nl-icecrew-playerdb"; pklass->handle_simple = &gm_mcp_icecrew_playerdb_handle_simple; pklass->handle_multi = &gm_mcp_icecrew_playerdb_handle_multi; pklass->min_version = 1.0; pklass->max_version = 1.1; g_type_class_add_private(object_class, sizeof(GmMcpIcecrewPlayerdbPrivate)); } static void gm_mcp_icecrew_playerdb_init(GmMcpIcecrewPlayerdb *obj) { obj->priv = GM_MCP_ICECREW_PLAYERDB_GET_PRIVATE(obj); obj->priv->self = 0; obj->priv->db = NULL; obj->priv->last_init_keys = NULL; } GmMcpIcecrewPlayerdb * gm_mcp_icecrew_playerdb_new() { GmMcpIcecrewPlayerdb *obj = GM_MCP_ICECREW_PLAYERDB(g_object_new( GM_TYPE_MCP_ICECREW_PLAYERDB, NULL)); return obj; } GmPlayerdbPlayerInfo * gm_mcp_icecrew_playerdb_find(GmMcpIcecrewPlayerdb *package, gint id) { GmPlayerdbPlayerInfo *ppi; GList *item; for (item = package->priv->db; item; item = item->next) { ppi = (GmPlayerdbPlayerInfo *)(item->data); if (ppi->id == id) { return ppi; } } return NULL; } gchar const * gm_playerdb_player_info_get_prop(GmPlayerdbPlayerInfo *ppi, gchar const *key) { return g_hash_table_lookup(ppi->values, key); } gboolean gm_mcp_icecrew_playerdb_initializing(GmMcpIcecrewPlayerdb *package) { return package->priv->last_init_keys != NULL; } void gm_mcp_icecrew_playerdb_find_players_with(GmMcpIcecrewPlayerdb *package, gchar const *key, gchar const *value, PlayerdbFindFunc func, gpointer user_data) { GmPlayerdbPlayerInfo *ppi; gchar const *v; GList *db; for (db = package->priv->db; db; db = db->next) { ppi = (GmPlayerdbPlayerInfo *)(db->data); v = gm_playerdb_player_info_get_prop(ppi, key); if (v != NULL && (value == NULL || strcmp(v, value) == 0)) { func(ppi, user_data); } } } void gm_mcp_icecrew_playerdb_set_prop(GmMcpIcecrewPlayerdb *package, GmPlayerdbPlayerInfo *ppi, gchar const *key, gchar const *value, gboolean add) { gchar *old; if (strcmp(key, "id") == 0) { return; } gm_debug_msg(DEBUG_MCP, "GmMcpIcecrewPlayerdb.SetProp: key: %s, value: %s", key, value); old = g_strdup(gm_playerdb_player_info_get_prop(ppi, key)); if (old && strcmp(old, value) == 0) { gm_debug_msg(DEBUG_MCP, "GmMcpIcecrewPlayerdb.SetProp: new value is " "the same as old value, no changes made"); g_free(old); return; } g_hash_table_insert(ppi->values, g_strdup(key), g_strdup(value)); if (!add) { g_signal_emit(package, gm_mcp_icecrew_playerdb_signals[SET], 0, ppi, key, value, old); } g_free(old); } void gm_mcp_icecrew_playerdb_modify_prop(GmMcpIcecrewPlayerdb *package, GmPlayerdbPlayerInfo *ppi, gchar const *key, gchar const *value, gboolean add) { if (ppi) { gm_mcp_icecrew_playerdb_set_prop(package, ppi, key, value, add); } } void gm_mcp_icecrew_playerdb_modify_prop_list(GmMcpIcecrewPlayerdb *package, GmPlayerdbPlayerInfo *ppi, GList *fields, gboolean add) { GmKeyValuePair *data; if (ppi) { for (; fields; fields = fields->next) { data = (GmKeyValuePair *)(fields->data); gm_mcp_icecrew_playerdb_set_prop(package, ppi, data->key, data->value, add); } } } void gm_mcp_icecrew_playerdb_remove_player(GmMcpIcecrewPlayerdb *package, gint id) { GmPlayerdbPlayerInfo *ppi; if ((ppi = gm_mcp_icecrew_playerdb_find(package, id))) { g_signal_emit(package, gm_mcp_icecrew_playerdb_signals[DELETE], 0, ppi); package->priv->db = g_list_remove(package->priv->db, ppi); g_hash_table_destroy(ppi->values); } } GmPlayerdbPlayerInfo * gm_mcp_icecrew_playerdb_add_player(GmMcpIcecrewPlayerdb *package, gint id) { GmPlayerdbPlayerInfo *ppi = g_new(GmPlayerdbPlayerInfo, 1); ppi->values = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); ppi->id = id; package->priv->db = g_list_append(package->priv->db, ppi); gm_debug_msg(DEBUG_MCP, "GmMcpIcecrewPlayerdb.AddPlayer: adding id %d", id); return ppi; } void gm_mcp_icecrew_playerdb_handle_simple(GmMcpPackage *package, gchar *suffix, GList *fields) { GmMcpIcecrewPlayerdb *playerdb = GM_MCP_ICECREW_PLAYERDB(package); gchar const *value; GmPlayerdbPlayerInfo *ppi; gint id, add; if (strcasecmp(suffix, "self") == 0) { if ((value = gm_mcp_find_value(fields, "id"))) { playerdb->priv->self = atoi(value); } } else if ((add = strcasecmp(suffix, "add")) == 0 || strcasecmp(suffix, "set") == 0) { if ((value = gm_mcp_find_value(fields, "id"))) { id = atoi(value); ppi = gm_mcp_icecrew_playerdb_find(playerdb, id); if (add == 0 && !ppi) { ppi = gm_mcp_icecrew_playerdb_add_player(playerdb, id); gm_mcp_icecrew_playerdb_modify_prop_list(playerdb, ppi, fields, TRUE); g_signal_emit(playerdb, gm_mcp_icecrew_playerdb_signals[ADD], 0, ppi); } else if (add != 0 && ppi) { gm_mcp_icecrew_playerdb_modify_prop_list(playerdb, ppi, fields, FALSE); } } } else if (strcasecmp(suffix, "del") == 0) { if ((value = gm_mcp_find_value(fields, "id"))) { id = atoi(value); gm_mcp_icecrew_playerdb_remove_player(playerdb, id); } } else if (strcasecmp(suffix, "init") == 0) { if ((value = gm_mcp_find_value(fields, "keys"))) { if (playerdb->priv->last_init_keys) { gm_mcp_list_free(playerdb->priv->last_init_keys); } playerdb->priv->last_init_keys = gm_mcp_parse_list(value); } } } gboolean gm_mcp_icecrew_playerdb_handle_multi(GmMcpPackage *package, gchar const *data_tag, gchar const *key, gchar const *value, GList *all_values) { GmMcpIcecrewPlayerdb *playerdb = GM_MCP_ICECREW_PLAYERDB(package); gint i; guint counter; gchar *id, *list; gchar const *ptr = value; GList *l; GmPlayerdbPlayerInfo *ppi; gunichar uc; if (key != NULL) { /* We should have a value something like */ gm_string_skip_space(&value); ptr = value; gm_string_skip_nonspace(&ptr); if (*ptr == '\0') { return TRUE; } id = g_strndup(value, ptr - value); gm_string_skip_space(&ptr); value = ptr; if (g_utf8_get_char(ptr) == '"') { ptr = g_utf8_next_char(ptr); value = ptr; i = 0; while (*ptr != '\0' && (uc = g_utf8_get_char(ptr)) != '"') { ptr = g_utf8_next_char(ptr); if (uc == '\\' && g_utf8_get_char(ptr) != '\0') { ptr = g_utf8_next_char(ptr); } } list = g_strndup(value, ptr - value); l = gm_mcp_parse_list(list); if (g_list_length(l) == g_list_length(playerdb->priv->last_init_keys)) { i = atoi(id); if ((ppi = gm_mcp_icecrew_playerdb_find(playerdb, i))) { gm_mcp_icecrew_playerdb_remove_player(playerdb, i); } ppi = gm_mcp_icecrew_playerdb_add_player(playerdb, i); for (counter = 0; counter < g_list_length(l); ++counter) { gm_mcp_icecrew_playerdb_modify_prop(playerdb, ppi, g_list_nth_data(playerdb->priv->last_init_keys, counter), g_list_nth_data(l, counter), TRUE); } g_signal_emit(playerdb, gm_mcp_icecrew_playerdb_signals[ADD], 0, ppi); } g_free(list); gm_mcp_list_free(l); } g_free(id); } else { gm_mcp_list_free(playerdb->priv->last_init_keys); playerdb->priv->last_init_keys = NULL; } return TRUE; }