sg-dumper.c

来自「linux下网络收音机的源码」· C语言 代码 · 共 365 行

C
365
字号
/* * Copyright (c) 2002, 2003, 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 <stdarg.h>#include <stdio.h>#include <unistd.h>#include <errno.h>#include <glib-object.h>#include <glib/gi18n.h>#include "sg-dumper.h"/*** type definitions ********************************************************/struct _SGDumper{  char		*filename;	/* the file to write */  char		*tmpfile;	/* the temporary file we write into */  GIOChannel	*io_channel;    int		depth;		/* the current tab depth */  gboolean	ok;		/* is everything ok so far? */};/*** function declarations ***************************************************/static gboolean sg_dumper_write_indent	(SGDumper	*dumper,					 GError		**err);static gboolean sg_dumper_printf	(SGDumper	*dumper,					 GError		**err,					 const char	*format,					 ...) G_GNUC_PRINTF(3, 4);static gboolean sg_dumper_write_str	(SGDumper	*dumper,					 const char	*str,					 GError		**err);static gboolean sg_dumper_write_value	(SGDumper	*dumper,					 const GValue	*value,					 GError		**err);/*** implementation **********************************************************/SGDumper *sg_dumper_new (const char *filename, GError **err){  SGDumper *dumper;  int fd;    g_return_val_if_fail(filename != NULL, NULL);  dumper = g_new0(SGDumper, 1);  dumper->filename = g_strdup(filename);  dumper->tmpfile = g_strconcat(dumper->filename, ".XXXXXX", NULL);  fd = g_mkstemp(dumper->tmpfile);  if (fd < 0)    {      g_set_error(err, 0, 0, _("unable to create a temporary file: %s"), g_strerror(errno));      sg_dumper_free(dumper, NULL); /* ignore further errors */      return NULL;    }    /* fine */  dumper->io_channel = g_io_channel_unix_new(fd);  dumper->ok = TRUE;  return dumper;}gbooleansg_dumper_free (SGDumper *dumper, GError **err){  gboolean status = TRUE;  g_return_val_if_fail(dumper != NULL, FALSE);  if (dumper->io_channel)    {      GError *tmp_err = NULL;            status = g_io_channel_shutdown(dumper->io_channel, TRUE, &tmp_err) == G_IO_STATUS_NORMAL;      g_io_channel_unref(dumper->io_channel);            if (! status)	{	  g_set_error(err, 0, 0, _("unable to close %s: %s"),		      dumper->tmpfile, tmp_err->message);	  g_error_free(tmp_err);	  	  goto end;	}    }    if (dumper->ok)    {      if (g_file_test(dumper->filename, G_FILE_TEST_EXISTS))	{	  status = unlink(dumper->filename) >= 0;	  if (! status)	    {	      g_set_error(err, 0, 0, _("unable to unlink %s: %s"),			  dumper->filename, g_strerror(errno));	      goto end;	    }	}      status = rename(dumper->tmpfile, dumper->filename) >= 0;      if (! status)	{	  g_set_error(err, 0, 0, _("unable to rename %s to %s: %s"),		      dumper->tmpfile, dumper->filename, g_strerror(errno));	  goto end;	}    }   end:  g_free(dumper->filename);  g_free(dumper->tmpfile);  g_free(dumper);  return status;}gbooleansg_dumper_write (SGDumper *dumper, GError **err, ...){  va_list args;  char *format;  g_return_val_if_fail(dumper != NULL, FALSE);  va_start(args, err);  while ((format = va_arg(args, char *)))    {      int i;      const char *terminator = ";";            if (! format[0])	terminator = NULL;      else if (format[0] == '}')	{	  dumper->depth--;	  terminator = "}";	}            if (! sg_dumper_write_indent(dumper, err))	return FALSE;      for (i = 0; format[i]; i++)	{	  switch (format[i])	    {	    case 'k':	      {		const char *key;		key = va_arg(args, const char *);		g_return_val_if_fail(key != NULL, FALSE);		if (! sg_dumper_write_str(dumper, key, err))		  return FALSE;		break;	      }#define CASE_VALUE(letter, ctype, gtype, setter)			\	      case letter:						\		{							\		  GValue _value =	{ 0, };				\		  gboolean _status;					\									\		  g_value_init(&_value, gtype);				\		  setter(&_value, va_arg(args, ctype));			\		  _status = sg_dumper_write_value(dumper, &_value, err); \		  g_value_unset(&_value);				\		  							\		  if (! _status)					\		    return FALSE;					\		  							\		  break;						\		}	      CASE_VALUE('b', gboolean, G_TYPE_BOOLEAN, g_value_set_boolean);	      CASE_VALUE('i', int, G_TYPE_INT, g_value_set_int);	      CASE_VALUE('u', unsigned int, G_TYPE_UINT, g_value_set_uint);	      CASE_VALUE('d', double, G_TYPE_DOUBLE, g_value_set_double);	      CASE_VALUE('s', const char *, G_TYPE_STRING, g_value_set_string);#undef CASE_VALUE	    case 'v':	      {		const GValue *value;		value = va_arg(args, const GValue *);		g_return_val_if_fail(value != NULL, FALSE);		if (! sg_dumper_write_value(dumper, value, err))		  return FALSE;		break;	      }	      	    case '{':	      dumper->depth++;	      terminator = "{";	      break;	    case '#':	      {		const char *comment;				comment = va_arg(args, const char *);		g_return_val_if_fail(comment != NULL, FALSE);				terminator = NULL;		if (! sg_dumper_printf(dumper, err, "# %s", comment))		  return FALSE;		break;	      }	    case '}':	    case 0:	      break;	    default:	      g_return_val_if_reached(FALSE);	    }	  	  if (format[i + 1] != 0) /* not the last item */	    {	      if (! sg_dumper_write_str(dumper, " ", err))		return FALSE;	    }	}      if (terminator)	{	  if (! sg_dumper_write_str(dumper, terminator, err))	    return FALSE;	}      if (! sg_dumper_write_str(dumper, "\n", err))	return FALSE;    }  va_end(args);    return TRUE;}static gbooleansg_dumper_write_indent (SGDumper *dumper, GError **err){  char *indent;  gboolean status;  indent = g_strnfill(dumper->depth, '\t');  status = sg_dumper_write_str(dumper, indent, err);  g_free(indent);  return status;}static gbooleansg_dumper_printf (SGDumper *dumper,		  GError **err,		  const char *format,		  ...){  va_list args;  char *str;  gboolean status;  va_start(args, format);  str = g_strdup_vprintf(format, args);  va_end(args);  status = sg_dumper_write_str(dumper, str, err);  g_free(str);    return status;}static gbooleansg_dumper_write_str (SGDumper *dumper,		     const char *str,		     GError **err){  dumper->ok = g_io_channel_write_chars(dumper->io_channel,					str,					-1,					NULL,					err) == G_IO_STATUS_NORMAL;  return dumper->ok;}static gbooleansg_dumper_write_value (SGDumper *dumper,		       const GValue *value,		       GError **err){  g_return_val_if_fail(dumper != NULL, FALSE);  g_return_val_if_fail(value != NULL, FALSE);  if (G_VALUE_HOLDS_BOOLEAN(value))    {      gboolean val = g_value_get_boolean(value);      return sg_dumper_write_str(dumper, val ? "yes" : "no", err);    }  else if (G_VALUE_HOLDS_INT(value))    return sg_dumper_printf(dumper, err, "%i", g_value_get_int(value));  else if (G_VALUE_HOLDS_UINT(value))    return sg_dumper_printf(dumper, err, "%u", g_value_get_uint(value));  else if (G_VALUE_HOLDS_DOUBLE(value))    return sg_dumper_printf(dumper, err, "%f", g_value_get_double(value));  else if (G_VALUE_HOLDS_STRING(value))    {      const char *val;      char *escaped;      gboolean status;      val = g_value_get_string(value);      escaped = g_strescape(val ? val : "", NULL);      status = sg_dumper_printf(dumper, err, "\"%s\"", escaped);      g_free(escaped);      return status;    }  else    g_return_val_if_reached(FALSE);}

⌨️ 快捷键说明

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