⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 attrgroup.c

📁 打魔兽战网的都知道他是什么
💻 C
字号:
/* * Copyright (C) 2004 Dizzy  * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. */#include "common/setup_before.h"#ifdef HAVE_ASSERT_H# include <assert.h>#endif#ifdef HAVE_STRING_H# include <string.h>#else# ifdef HAVE_STRINGS_H#  include <strings.h># endif#endif#include "common/eventlog.h"#include "common/flags.h"#include "common/xalloc.h"#include "compat/strcasecmp.h"#include "compat/strncasecmp.h"#define ATTRGROUP_INTERNAL_ACCESS#include "attr.h"#include "attrgroup.h"#include "attrlayer.h"#include "storage.h"#include "prefs.h"#include "server.h"#include "common/setup_after.h"static inline void attrgroup_set_accessed(t_attrgroup *attrgroup){    FLAG_SET(&attrgroup->flags, ATTRGROUP_FLAG_ACCESSED);    attrgroup->lastaccess = now;}static inline void attrgroup_clear_accessed(t_attrgroup *attrgroup){    FLAG_CLEAR(&attrgroup->flags, ATTRGROUP_FLAG_ACCESSED);}static inline void attrgroup_set_dirty(t_attrgroup *attrgroup){    if (FLAG_ISSET(attrgroup->flags, ATTRGROUP_FLAG_DIRTY)) return;    attrgroup->dirtytime = now;    FLAG_SET(&attrgroup->flags, ATTRGROUP_FLAG_DIRTY);    attrlayer_add_dirtylist(&attrgroup->dirtylist);}static inline void attrgroup_clear_dirty(t_attrgroup *attrgroup){    if (!FLAG_ISSET(attrgroup->flags, ATTRGROUP_FLAG_DIRTY)) return;    FLAG_CLEAR(&attrgroup->flags, ATTRGROUP_FLAG_DIRTY);    attrlayer_del_dirtylist(&attrgroup->dirtylist);}static inline void attrgroup_set_loaded(t_attrgroup *attrgroup){    if (FLAG_ISSET(attrgroup->flags, ATTRGROUP_FLAG_LOADED)) return;    FLAG_SET(&attrgroup->flags, ATTRGROUP_FLAG_LOADED);    attrlayer_add_loadedlist(&attrgroup->loadedlist);}static inline void attrgroup_clear_loaded(t_attrgroup *attrgroup){    if (!FLAG_ISSET(attrgroup->flags, ATTRGROUP_FLAG_LOADED)) return;    /* clear this because they are not valid if attrgroup is unloaded */    attrgroup_clear_dirty(attrgroup);    attrgroup_clear_accessed(attrgroup);    FLAG_CLEAR(&attrgroup->flags, ATTRGROUP_FLAG_LOADED);    attrlayer_del_loadedlist(&attrgroup->loadedlist);}static t_attrgroup * attrgroup_create(void){    t_attrgroup *attrgroup;    attrgroup = xmalloc(sizeof(t_attrgroup));    hlist_init(&attrgroup->list);    attrgroup->storage = NULL;    attrgroup->flags = ATTRGROUP_FLAG_NONE;    attrgroup->lastaccess = 0;    attrgroup->dirtytime = 0;    elist_init(&attrgroup->loadedlist);    elist_init(&attrgroup->dirtylist);    return attrgroup;}extern t_attrgroup * attrgroup_create_storage(t_storage_info *storage){    t_attrgroup *attrgroup;    attrgroup = attrgroup_create();    attrgroup->storage = storage;    return attrgroup;}extern t_attrgroup * attrgroup_create_newuser(const char *name){    t_attrgroup *attrgroup;    t_storage_info *stmp;    stmp = storage->create_account(name);    if (!stmp) {	eventlog(eventlog_level_error,__FUNCTION__,"failed to add user '%s' to storage", name);	return NULL;    }    attrgroup = attrgroup_create_storage(stmp);    /* new accounts are born loaded */    attrgroup_set_loaded(attrgroup);    return attrgroup;}extern t_attrgroup * attrgroup_create_nameuid(const char *name, unsigned uid){    t_storage_info *info;    t_attrgroup *attrgroup;    info = storage->read_account(name,uid);    if (!info) return NULL;    attrgroup = attrgroup_create_storage(info);    return attrgroup;}extern int attrgroup_destroy(t_attrgroup *attrgroup){    if (!attrgroup) {	eventlog(eventlog_level_error, __FUNCTION__, "got NULL attrgroup");	return -1;    }    attrgroup_unload(attrgroup);    if (attrgroup->storage) storage->free_info(attrgroup->storage);    xfree(attrgroup);    return 0;}extern int attrgroup_save(t_attrgroup *attrgroup, int flags){    if (!attrgroup) {	eventlog(eventlog_level_error, __FUNCTION__, "got NULL attrgroup");	return -1;    }    if (!FLAG_ISSET(attrgroup->flags, ATTRGROUP_FLAG_LOADED))	return 0;    if (!FLAG_ISSET(attrgroup->flags, ATTRGROUP_FLAG_DIRTY))	return 0;    if (!FLAG_ISSET(flags, FS_FORCE) && now - attrgroup->dirtytime < prefs_get_user_sync_timer())	return 0;    assert(attrgroup->storage);    storage->write_attrs(attrgroup->storage, &attrgroup->list);    attrgroup_clear_dirty(attrgroup);    return 1;}extern int attrgroup_flush(t_attrgroup *attrgroup, int flags){    t_attr *attr;    t_hlist *curr, *save;    if (!attrgroup) {	eventlog(eventlog_level_error, __FUNCTION__, "got NULL attrgroup");	return -1;    }    if (!FLAG_ISSET(attrgroup->flags, ATTRGROUP_FLAG_LOADED))	return 0;    if (!FLAG_ISSET(flags, FS_FORCE) &&	FLAG_ISSET(attrgroup->flags, ATTRGROUP_FLAG_ACCESSED) &&	now - attrgroup->lastaccess < prefs_get_user_flush_timer())	return 0;    /* sync data to disk if dirty */    attrgroup_save(attrgroup,FS_FORCE);    hlist_for_each_safe(curr,&attrgroup->list,save) {	attr = hlist_entry(curr,t_attr,link);	attr_destroy(attr);    }    hlist_init(&attrgroup->list);	/* reset list */    attrgroup_clear_loaded(attrgroup);    return 1;}static int _cb_load_attr(const char *key, const char *val, void *data){    t_attrgroup *attrgroup = (t_attrgroup *)data;    return attrgroup_set_attr(attrgroup, key, val);}extern int attrgroup_load(t_attrgroup *attrgroup){    assert(attrgroup);    assert(attrgroup->storage);    if (FLAG_ISSET(attrgroup->flags, ATTRGROUP_FLAG_LOADED))	/* already done */	return 0;    if (FLAG_ISSET(attrgroup->flags, ATTRGROUP_FLAG_DIRTY)) { /* if not loaded, how dirty ? */	eventlog(eventlog_level_error, __FUNCTION__, "can't load modified account");	return -1;    }    attrgroup_set_loaded(attrgroup);    if (storage->read_attrs(attrgroup->storage, _cb_load_attr, attrgroup)) {	eventlog(eventlog_level_error, __FUNCTION__, "got error loading attributes");	return -1;    }    attrgroup_clear_dirty(attrgroup);    return 0;}extern int attrgroup_unload(t_attrgroup *attrgroup){    attrgroup_flush(attrgroup,FS_FORCE);    return 0;}typedef struct {    void *data;    t_attr_cb cb;} t_attr_cb_data;static int _cb_read_accounts(t_storage_info *info, void *data){    t_attrgroup *attrgroup;    t_attr_cb_data *cbdata = (t_attr_cb_data*)data;    attrgroup = attrgroup_create_storage(info);    return cbdata->cb(attrgroup,cbdata->data);}extern int attrgroup_read_accounts(int flag, t_attr_cb cb, void *data){    t_attr_cb_data cbdata;    cbdata.cb = cb;    cbdata.data = data;    return storage->read_accounts(flag, _cb_read_accounts, &cbdata);}static const char *attrgroup_escape_key(const char *key){    const char *newkey, *newkey2;    char *tmp;    newkey = key;    if (!strncasecmp(key,"DynKey",6)) {	/* OLD COMMENT, MIGHT NOT BE VALID ANYMORE	 * Recent Starcraft clients seems to query DynKey\*\1\rank instead of 	 * Record\*\1\rank. So replace Dynkey with Record for key lookup.	 */	tmp = xstrdup(key);	strncpy(tmp,"Record",6);	newkey = tmp;    } else if (!strncmp(key,"Star",4)) {	/* OLD COMMENT	 * Starcraft clients query Star instead of STAR on logon screen.	 */	tmp = xstrdup(key);	strncpy(tmp,"STAR",4);	newkey = tmp;    }    if (newkey != key) {	newkey2 = storage->escape_key(newkey);	if (newkey2 != newkey) {	    xfree((void*)newkey);	    newkey = newkey2;	}    } else newkey = storage->escape_key(key);    return newkey;}static t_attr *attrgroup_find_attr(t_attrgroup *attrgroup, const char *pkey[], int escape){    const char *val;    t_hlist *curr, *last, *last2;    t_attr *attr;    assert(attrgroup);    assert(pkey);    assert(*pkey);    /* trigger loading of attributes if not loaded already */    if (attrgroup_load(attrgroup)) return NULL;	/* eventlog happens earlier */    /* only if the callers tell us to */    if (escape) *pkey = attrgroup_escape_key(*pkey);    /* we are doing attribute lookup so we are accessing it */    attrgroup_set_accessed(attrgroup);    last = &attrgroup->list;    last2 = NULL;    hlist_for_each(curr,&attrgroup->list) {	attr = hlist_entry(curr, t_attr, link);	if (!strcasecmp(attr_get_key(attr),*pkey)) {	    val = attr_get_val(attr);	    /* key found, promote it so it's found faster next time */	    hlist_promote(curr, last, last2);	    break;	}	last2 = last; last = curr;    }    if (curr == &attrgroup->list) {	/* no key found in cached list */	attr = (t_attr*)storage->read_attr(attrgroup->storage, *pkey);	if (attr) hlist_add(&attrgroup->list, &attr->link);    }    /* "attr" here can either have a proper value found in the cached list, or     * a value returned by storage->read_attr, or NULL */    return attr;}/* low-level get attr, receives a flag to tell if it needs to escape key */static const char *attrgroup_get_attrlow(t_attrgroup *attrgroup, const char *key, int escape){    const char *val = NULL;    const char *newkey = key;    t_attr *attr;    /* no need to check for attrgroup, key */    attr = attrgroup_find_attr(attrgroup, &newkey, escape);    if (attr) val = attr_get_val(attr);    if (!val && attrgroup != attrlayer_get_defattrgroup()) 	val = attrgroup_get_attrlow(attrlayer_get_defattrgroup(), newkey, 0);    if (newkey != key) xfree((void*)newkey);    return val;}extern const char *attrgroup_get_attr(t_attrgroup *attrgroup, const char *key){    if (!attrgroup) {	eventlog(eventlog_level_error, __FUNCTION__, "got NULL attrgroup");	return NULL;    }    if (!key) {	eventlog(eventlog_level_error, __FUNCTION__, "got NULL key");	return NULL;    }    return attrgroup_get_attrlow(attrgroup, key, 1);}extern int attrgroup_set_attr(t_attrgroup *attrgroup, const char *key, const char *val){    t_attr *attr;    const char *newkey = key;    if (!attrgroup) {	eventlog(eventlog_level_error, __FUNCTION__, "got NULL attrgroup");	return -1;    }    if (!key) {	eventlog(eventlog_level_error, __FUNCTION__, "got NULL key");	return -1;    }    attr = attrgroup_find_attr(attrgroup, &newkey, 1);    if (attr) {	if (attr_get_val(attr) == val ||	    (attr_get_val(attr) && val && !strcmp(attr_get_val(attr), val)))	    goto out;	/* no need to modify anything, values are the same */	/* new value for existent key, replace the old one */	attr_set_val(attr, val);    } else {	/* unknown key so add new attr */	attr = attr_create(newkey, val);	hlist_add(&attrgroup->list, &attr->link);    }    /* we have modified this attr and attrgroup */    attr_set_dirty(attr);    attrgroup_set_dirty(attrgroup);out:    if (newkey != key) xfree((void*)newkey);    return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -