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 + -
显示快捷键?