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

📄 st-cache.c

📁 linux下网络收音机的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (c) 2004 Jean-Yves Lefort * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. Neither the name of Jean-Yves Lefort nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */#include "config.h"#include <string.h>#include <sys/types.h>#include <sys/stat.h>#include <stdarg.h>#include <errno.h>#include <glib.h>#include <glib/gi18n.h>#include "sg-util.h"#include "sgtk-util.h"#include "st-handler.h"#include "st-handler-field.h"#include "st-handlers.h"#include "st-settings.h"#include "st-cache.h"/*** cpp *********************************************************************/#define CATEGORIES_MAGIC		0x43435453	/* STCC (little endian integer) */#define CATEGORIES_VERSION		0#define STREAMS_MAGIC			0x43535453	/* STSC (little endian integer) */#define STREAMS_VERSION			0#define st_cache_read_int(channel, int_ptr, err) \  st_cache_read_any((channel), (int_ptr), sizeof(int), (err))#define st_cache_read_double(channel, double_ptr, err) \  st_cache_read_any((channel), (double_ptr), sizeof(double), (err))/*** type definitions ********************************************************/typedef enum{  ATOM_CATEGORY_NAME,  ATOM_CATEGORY_FLAGS,  ATOM_CATEGORY_PARENT,  ATOM_CATEGORY_LABEL,  ATOM_CATEGORY_URL_POSTFIX} CategoryAtom;typedef enum{  ATOM_STREAM_NAME,  ATOM_STREAM_FIELDS} StreamAtom;typedef enum{  VALUE_TYPE_BOOLEAN,  VALUE_TYPE_INT,  VALUE_TYPE_UINT,  VALUE_TYPE_DOUBLE,  VALUE_TYPE_STRING,  VALUE_TYPE_VALUE_ARRAY,  VALUE_TYPE_PIXBUF} ValueType;typedef struct{  GIOChannel	*channel;  gboolean	status;  GError	**err;} SaveInfo;typedef enum{  OPEN_MODE_READ,  OPEN_MODE_WRITE} OpenMode;/*** function declarations ***************************************************/static gboolean st_cache_save_handler (STHandler *handler, GError **err);static gboolean st_cache_save_category_cb (STCategoryStore *store,					   STCategoryBag *bag,					   STCategoryBag *parent,					   gpointer data);static gboolean st_cache_save_category (GIOChannel *channel,					STCategoryBag *category_bag,					STCategoryBag *parent_bag,					GError **err);static gboolean st_cache_save_streams (STCategoryBag *category_bag,				       STStreamStore *streams,				       GError **err);static gboolean st_cache_save_stream_cb (STStreamStore *store,					 STStreamBag *bag,					 gpointer data);static gboolean st_cache_save_stream (GIOChannel *channel,				      STStreamBag *stream_bag,				      GError **err);static gboolean st_cache_save_value (GIOChannel *channel,				     const GValue *value,				     GError **err);static char *st_cache_get_filename (const char *str);static char *st_cache_get_handler_directory (STHandler *handler);static char *st_cache_get_categories_filename (STHandler *handler);static char *st_cache_get_streams_filename (STHandler *handler,					    const char *category_name);static GIOChannel *st_cache_io_channel_new_file (const char *filename,						 OpenMode mode,						 int magic,						 int version,						 int subversion,						 GError **err);static GIOChannel *st_cache_io_channel_new_categories (const char *filename,						       OpenMode mode,						       GError **err);static GIOChannel *st_cache_io_channel_new_streams (STHandler *handler,						    const char *filename,						    OpenMode mode,						    GError **err);static gboolean st_cache_write (GIOChannel *channel,				const char *format,				...);static gboolean st_cache_write_int (GIOChannel *channel, int i, GError **err);static gboolean st_cache_write_double (GIOChannel *channel, double d, GError **err);static gboolean st_cache_write_buffer (GIOChannel *channel,				       const char *buf,				       int len,				       GError **err);static gboolean st_cache_write_string (GIOChannel *channel,				       const char *str,				       GError **err);static void st_cache_append_category (STHandler *handler,				      GHashTable *parents,				      GNode *categories,				      STCategoryBag *category_bag,				      const char *parent_name);static gboolean st_cache_load_value (GIOChannel *channel,				     GValue *value,				     GError **err);static gboolean st_cache_read_any (GIOChannel *channel,				   gpointer ptr,				   int len,				   GError **err);static gboolean st_cache_read_buffer (GIOChannel *channel,				      char **buf,				      int *len,				      GError **err);static gboolean st_cache_read_string (GIOChannel *channel,				      char **str,				      GError **err);/*** implementation **********************************************************/gbooleanst_cache_save (GError **err){  GSList *l;  SG_LIST_FOREACH(l, st_handlers_list)    if (! st_cache_save_handler(l->data, err))      return FALSE;  return TRUE;}static gbooleanst_cache_save_handler (STHandler *handler, GError **err){  char *dirname;  SaveInfo info;  STCategoryStore *categories;  g_return_val_if_fail(ST_IS_HANDLER(handler), FALSE);  dirname = st_cache_get_handler_directory(handler);  if (! g_file_test(dirname, G_FILE_TEST_IS_DIR) && (mkdir(dirname, 0755) < 0))    {      g_set_error(err, 0, 0, _("unable to create directory %s: %s"), dirname, g_strerror(errno));      g_free(dirname);      return FALSE;    }  g_free(dirname);    if (ST_HANDLER_HAS_CATEGORIES(handler))    {      char *filename;            filename = st_cache_get_categories_filename(handler);      info.channel = st_cache_io_channel_new_categories(filename, OPEN_MODE_WRITE, err);      g_free(filename);      if (! info.channel)	return FALSE;    }  else    info.channel = NULL;  info.status = TRUE;  info.err = err;    categories = st_handler_get_categories(handler);  st_category_store_foreach(categories, st_cache_save_category_cb, &info);  g_object_unref(categories);  if (info.channel)    {      if (info.status)	{	  if (g_io_channel_shutdown(info.channel, TRUE, err) != G_IO_STATUS_NORMAL)	    info.status = FALSE;	}      else	g_io_channel_shutdown(info.channel, FALSE, NULL);        g_io_channel_unref(info.channel);    }  return info.status;}static gbooleanst_cache_save_category_cb (STCategoryStore *store,			   STCategoryBag *bag,			   STCategoryBag *parent,			   gpointer data){  SaveInfo *info = data;  info->status = st_cache_save_category(info->channel, bag, parent, info->err);  return ! info->status;}static gbooleanst_cache_save_category (GIOChannel *channel,			STCategoryBag *category_bag,			STCategoryBag *parent_bag,			GError **err){  STStreamStore *streams;  g_return_val_if_fail(ST_IS_CATEGORY_BAG(category_bag), FALSE);  if (channel)    {      if (! st_cache_write(channel, "isii",			   ATOM_CATEGORY_NAME, ST_CATEGORY(category_bag)->name,			   ATOM_CATEGORY_FLAGS, category_bag->flags,			   err))	return FALSE;            if (parent_bag)	{	  if (! st_cache_write(channel, "is",			       ATOM_CATEGORY_PARENT, ST_CATEGORY(parent_bag)->name,			       err))	    return FALSE;	}      if (! ST_CATEGORY_BAG_IS_STOCK(category_bag))	{	  if (! st_cache_write(channel, "isis",			       ATOM_CATEGORY_LABEL, ST_CATEGORY(category_bag)->label,			       ATOM_CATEGORY_URL_POSTFIX, ST_CATEGORY(category_bag)->url_postfix,			       err))	    return FALSE;	}    }        streams = st_handler_get_streams(category_bag->handler, ST_CATEGORY(category_bag)->name);  if (streams)    {      gboolean status;      status = st_stream_store_is_touched(streams)	? st_cache_save_streams(category_bag, streams, err)	: TRUE;      g_object_unref(streams);	        if (! status)	return FALSE;    }  return TRUE;}static gbooleanst_cache_save_streams (STCategoryBag *category_bag,		       STStreamStore *streams,		       GError **err){  char *filename;  SaveInfo info;  g_return_val_if_fail(ST_IS_CATEGORY_BAG(category_bag), FALSE);  g_return_val_if_fail(ST_IS_STREAM_STORE(streams), FALSE);    filename = st_cache_get_streams_filename(category_bag->handler, ST_CATEGORY(category_bag)->name);  info.channel = st_cache_io_channel_new_streams(category_bag->handler, filename, OPEN_MODE_WRITE, err);  g_free(filename);  if (! info.channel)    return FALSE;  info.status = st_cache_write_int(info.channel, sgtk_tree_model_get_count(GTK_TREE_MODEL(streams)), err);  if (info.status)    {      info.err = err;      st_stream_store_foreach(streams, st_cache_save_stream_cb, &info);    }    if (info.status)    {      if (g_io_channel_shutdown(info.channel, TRUE, err) != G_IO_STATUS_NORMAL)	info.status = FALSE;    }  else    g_io_channel_shutdown(info.channel, FALSE, NULL);    g_io_channel_unref(info.channel);  return info.status;}static gbooleanst_cache_save_stream_cb (STStreamStore *store,			 STStreamBag *bag,			 gpointer data){  SaveInfo *info = data;  info->status = st_cache_save_stream(info->channel, bag, info->err);  return ! info->status;}static gbooleanst_cache_save_stream (GIOChannel *channel,		      STStreamBag *stream_bag,		      GError **err){  GSList *fields;  GSList *l;    g_return_val_if_fail(channel != NULL, FALSE);  g_return_val_if_fail(ST_IS_STREAM_BAG(stream_bag), FALSE);  fields = st_handler_get_fields(stream_bag->handler);  if (! st_cache_write(channel, "isii",		       ATOM_STREAM_NAME, ST_STREAM(stream_bag)->name,		       ATOM_STREAM_FIELDS, g_slist_length(fields) - st_handler_count_fields(stream_bag->handler, ST_HANDLER_FIELD_VOLATILE),		       err))    return FALSE;    SG_LIST_FOREACH(l, fields)    {      STHandlerField *field = l->data;      if (! ST_HANDLER_FIELD_IS_VOLATILE(field))	{	  GValue value = { 0, };	  gboolean status;	  st_stream_bag_get_field(stream_bag, field, &value);	  status = st_cache_save_value(channel, &value, err);	  g_value_unset(&value);	  if (! status)	    return FALSE;	}    }  return TRUE;}static gbooleanst_cache_save_value (GIOChannel *channel, const GValue *value, GError **err){  ValueType type;  g_return_val_if_fail(channel != NULL, FALSE);  g_return_val_if_fail(G_IS_VALUE(value), FALSE);  if (G_VALUE_HOLDS_BOOLEAN(value))    type = VALUE_TYPE_BOOLEAN;  else if (G_VALUE_HOLDS_INT(value))    type = VALUE_TYPE_INT;  else if (G_VALUE_HOLDS_UINT(value))    type = VALUE_TYPE_UINT;  else if (G_VALUE_HOLDS_DOUBLE(value))    type = VALUE_TYPE_DOUBLE;  else if (G_VALUE_HOLDS_STRING(value))    type = VALUE_TYPE_STRING;  else if (G_VALUE_HOLDS(value, G_TYPE_VALUE_ARRAY))    type = VALUE_TYPE_VALUE_ARRAY;  else if (G_VALUE_HOLDS(value, GDK_TYPE_PIXBUF))    type = VALUE_TYPE_PIXBUF;  else    g_return_val_if_reached(FALSE);    if (! st_cache_write_int(channel, type, err))    return FALSE;  switch (type)    {    case VALUE_TYPE_BOOLEAN:      if (! st_cache_write_int(channel, g_value_get_boolean(value), err))	return FALSE;      break;    case VALUE_TYPE_INT:      if (! st_cache_write_int(channel, g_value_get_int(value), err))	return FALSE;      break;    case VALUE_TYPE_UINT:      if (! st_cache_write_int(channel, g_value_get_uint(value), err))	return FALSE;      break;    case VALUE_TYPE_DOUBLE:      if (! st_cache_write_double(channel, g_value_get_double(value), err))	return FALSE;      break;    case VALUE_TYPE_STRING:      if (! st_cache_write_string(channel, g_value_get_string(value), err))	return FALSE;      break;    case VALUE_TYPE_VALUE_ARRAY:      {	GValueArray *value_array = g_value_get_boxed(value);	int i;	if (! st_cache_write_int(channel, value_array->n_values, err))	  return FALSE;	for (i = 0; i < value_array->n_values; i++)	  if (! st_cache_save_value(channel, g_value_array_get_nth(value_array, i), err))	    return FALSE;		break;      }    case VALUE_TYPE_PIXBUF:      {	GdkPixbuf *pixbuf;

⌨️ 快捷键说明

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