Commit 53d9610a authored by Matthias Clasen's avatar Matthias Clasen
Browse files

serializer: Replace json-glib

Replace json-glib by a homegrown json parser/printer.
parent f15cf8af
......@@ -232,7 +232,6 @@ harfbuzz_req_version = '>= 2.6.0'
fontconfig_req_version = '>= 2.13.0'
xft_req_version = '>= 2.0.0'
cairo_req_version = '>= 1.12.10'
json_glib_version = '>= 1.6.0'
# libm
mathlib_dep = cc.find_library('m', required: false)
......@@ -252,10 +251,6 @@ fribidi_dep = dependency('fribidi', version: fribidi_req_version,
default_options: ['docs=false'])
pango_deps += fribidi_dep
json_glib_dep = dependency('json-glib-1.0', version: json_glib_version,
fallback: ['json-glib', 'json_glib_dep'])
pango_deps += json_glib_dep
thai_dep = dependency('libthai', version: libthai_req_version, required: get_option('libthai'))
if thai_dep.found()
pango_conf.set('HAVE_LIBTHAI', 1)
......
This diff is collapsed.
/*
* Copyright © 2021 Benjamin Otte
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Benjamin Otte <otte@gnome.org>
*/
#ifndef __GTK_JSON_PARSER_H__
#define __GTK_JSON_PARSER_H__
#include <glib.h>
G_BEGIN_DECLS
typedef enum {
GTK_JSON_NONE,
GTK_JSON_NULL,
GTK_JSON_BOOLEAN,
GTK_JSON_NUMBER,
GTK_JSON_STRING,
GTK_JSON_OBJECT,
GTK_JSON_ARRAY
} GtkJsonNode;
typedef struct _GtkJsonParser GtkJsonParser;
GtkJsonParser * gtk_json_parser_new_for_bytes (GBytes *bytes);
GtkJsonParser * gtk_json_parser_new_for_string (const char *string,
gssize size);
void gtk_json_parser_free (GtkJsonParser *self);
gboolean gtk_json_parser_next (GtkJsonParser *self);
GtkJsonNode gtk_json_parser_get_node (GtkJsonParser *self);
const GError * gtk_json_parser_get_error (GtkJsonParser *self) G_GNUC_PURE;
char * gtk_json_parser_get_member_name (GtkJsonParser *self);
gssize gtk_json_parser_select_member (GtkJsonParser *self,
const char * const *options);
gboolean gtk_json_parser_get_boolean (GtkJsonParser *self);
double gtk_json_parser_get_number (GtkJsonParser *self);
int gtk_json_parser_get_int (GtkJsonParser *self);
guint gtk_json_parser_get_uint (GtkJsonParser *self);
char * gtk_json_parser_get_string (GtkJsonParser *self);
gboolean gtk_json_parser_start_object (GtkJsonParser *self);
gboolean gtk_json_parser_start_array (GtkJsonParser *self);
gboolean gtk_json_parser_end (GtkJsonParser *self);
G_END_DECLS
#endif /* __GTK_JSON_PARSER_H__ */
/*
* Copyright © 2021 Benjamin Otte
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Benjamin Otte <otte@gnome.org>
*/
#include "config.h"
#include "gtkjsonprinterprivate.h"
typedef struct _GtkJsonBlock GtkJsonBlock;
typedef enum {
GTK_JSON_BLOCK_TOPLEVEL,
GTK_JSON_BLOCK_OBJECT,
GTK_JSON_BLOCK_ARRAY,
} GtkJsonBlockType;
struct _GtkJsonBlock
{
GtkJsonBlockType type;
gsize n_elements; /* number of elements already written */
};
struct _GtkJsonPrinter
{
GtkJsonPrinterFlags flags;
char *indentation;
GtkJsonPrinterWriteFunc write_func;
gpointer user_data;
GDestroyNotify user_destroy;
GtkJsonBlock *block; /* current block */
GtkJsonBlock *blocks; /* blocks array */
GtkJsonBlock *blocks_end; /* blocks array */
GtkJsonBlock blocks_preallocated[128]; /* preallocated */
};
static void
gtk_json_printer_push_block (GtkJsonPrinter *self,
GtkJsonBlockType type)
{
self->block++;
if (self->block == self->blocks_end)
{
gsize old_size = self->blocks_end - self->blocks;
gsize new_size = old_size + 128;
if (self->blocks == self->blocks_preallocated)
{
self->blocks = g_new (GtkJsonBlock, new_size);
memcpy (self->blocks, self->blocks_preallocated, sizeof (GtkJsonBlock) * G_N_ELEMENTS (self->blocks_preallocated));
}
else
{
self->blocks = g_renew (GtkJsonBlock, self->blocks, new_size);
}
self->blocks_end = self->blocks + new_size;
self->block = self->blocks + old_size;
}
self->block->type = type;
self->block->n_elements = 0;
}
static void
gtk_json_printer_pop_block (GtkJsonPrinter *self)
{
g_assert (self->block > self->blocks);
self->block--;
}
GtkJsonPrinter *
gtk_json_printer_new (GtkJsonPrinterWriteFunc write_func,
gpointer data,
GDestroyNotify destroy)
{
GtkJsonPrinter *self;
g_return_val_if_fail (write_func, NULL);
self = g_slice_new0 (GtkJsonPrinter);
self->flags = 0;
self->indentation = g_strdup (" ");
self->write_func = write_func;
self->user_data = data;
self->user_destroy = destroy;
self->blocks = self->blocks_preallocated;
self->blocks_end = self->blocks + G_N_ELEMENTS (self->blocks_preallocated);
self->block = self->blocks;
self->block->type = GTK_JSON_BLOCK_TOPLEVEL;
return self;
}
void
gtk_json_printer_free (GtkJsonPrinter *self)
{
g_return_if_fail (self != NULL);
g_free (self->indentation);
if (self->user_destroy)
self->user_destroy (self->user_data);
if (self->blocks != self->blocks_preallocated)
g_free (self->blocks);
g_slice_free (GtkJsonPrinter, self);
}
static gboolean
gtk_json_printer_has_flag (GtkJsonPrinter *self,
GtkJsonPrinterFlags flag)
{
return (self->flags & flag) ? TRUE : FALSE;
}
gsize
gtk_json_printer_get_depth (GtkJsonPrinter *self)
{
return self->block - self->blocks;
}
gsize
gtk_json_printer_get_n_elements (GtkJsonPrinter *self)
{
return self->block->n_elements;
}
void
gtk_json_printer_set_flags (GtkJsonPrinter *self,
GtkJsonPrinterFlags flags)
{
g_return_if_fail (self != NULL);
self->flags = flags;
}
GtkJsonPrinterFlags
gtk_json_printer_get_flags (GtkJsonPrinter *self)
{
g_return_val_if_fail (self != NULL, 0);
return self->flags;
}
void
gtk_json_printer_set_indentation (GtkJsonPrinter *self,
gsize amount)
{
g_return_if_fail (self != NULL);
g_free (self->indentation);
self->indentation = g_malloc (amount + 1);
memset (self->indentation, ' ', amount);
self->indentation[amount] = 0;
}
gsize
gtk_json_printer_get_indentation (GtkJsonPrinter *self)
{
g_return_val_if_fail (self != NULL, 2);
return strlen (self->indentation);
}
static void
gtk_json_printer_write (GtkJsonPrinter *self,
const char *s)
{
self->write_func (self, s, self->user_data);
}
static char *
gtk_json_printer_escape_string (GtkJsonPrinter *self,
const char *str)
{
GString *string;
string = g_string_new (NULL);
string = g_string_append_c (string, '"');
for (; *str != '\0'; str = g_utf8_next_char (str))
{
switch (*str)
{
case '"':
g_string_append (string, "\\\"");
break;
case '\\':
g_string_append (string, "\\\\");
break;
case '\b':
g_string_append (string, "\\b");
break;
case '\f':
g_string_append (string, "\\f");
break;
case '\n':
g_string_append (string, "\\n");
break;
case '\r':
g_string_append (string, "\\r");
break;
case '\t':
g_string_append (string, "\\t");
break;
default:
if ((int) *str < 0x20)
{
if ((guint) *str < 0x20 || gtk_json_printer_has_flag (self, GTK_JSON_PRINTER_ASCII))
g_string_append_printf (string, "\\u%04x", g_utf8_get_char (str));
else
g_string_append_unichar (string, g_utf8_get_char (str));
}
else
g_string_append_c (string, *str);
}
}
string = g_string_append_c (string, '"');
return g_string_free (string, FALSE);
}
static void
gtk_json_printer_newline (GtkJsonPrinter *self)
{
gsize depth;
if (!gtk_json_printer_has_flag (self, GTK_JSON_PRINTER_PRETTY))
return;
gtk_json_printer_write (self, "\n");
for (depth = gtk_json_printer_get_depth (self); depth-->0;)
gtk_json_printer_write (self, self->indentation);
}
static void
gtk_json_printer_begin_member (GtkJsonPrinter *self,
const char *name)
{
if (gtk_json_printer_get_n_elements (self) > 0)
gtk_json_printer_write (self, ",");
if (self->block->type != GTK_JSON_BLOCK_TOPLEVEL || gtk_json_printer_get_n_elements (self) > 0)
gtk_json_printer_newline (self);
self->block->n_elements++;
if (name)
{
char *escaped = gtk_json_printer_escape_string (self, name);
gtk_json_printer_write (self, escaped);
g_free (escaped);
if (gtk_json_printer_has_flag (self, GTK_JSON_PRINTER_PRETTY))
gtk_json_printer_write (self, " : ");
else
gtk_json_printer_write (self, ":");
}
}
void
gtk_json_printer_add_boolean (GtkJsonPrinter *self,
const char *name,
gboolean value)
{
g_return_if_fail (self != NULL);
g_return_if_fail ((self->block->type == GTK_JSON_BLOCK_OBJECT) == (name != NULL));
gtk_json_printer_begin_member (self, name);
gtk_json_printer_write (self, value ? "true" : "false");
}
void
gtk_json_printer_add_number (GtkJsonPrinter *self,
const char *name,
double value)
{
char buf[G_ASCII_DTOSTR_BUF_SIZE];
g_return_if_fail (self != NULL);
g_return_if_fail ((self->block->type == GTK_JSON_BLOCK_OBJECT) == (name != NULL));
gtk_json_printer_begin_member (self, name);
g_ascii_dtostr (buf, G_ASCII_DTOSTR_BUF_SIZE, value);
gtk_json_printer_write (self, buf);
}
void
gtk_json_printer_add_integer (GtkJsonPrinter *self,
const char *name,
int value)
{
char buf[128];
g_return_if_fail (self != NULL);
g_return_if_fail ((self->block->type == GTK_JSON_BLOCK_OBJECT) == (name != NULL));
gtk_json_printer_begin_member (self, name);
g_snprintf (buf, sizeof (buf), "%d", value);
gtk_json_printer_write (self, buf);
}
void
gtk_json_printer_add_string (GtkJsonPrinter *self,
const char *name,
const char *s)
{
char *escaped;
g_return_if_fail (self != NULL);
g_return_if_fail ((self->block->type == GTK_JSON_BLOCK_OBJECT) == (name != NULL));
g_return_if_fail (s != NULL);
gtk_json_printer_begin_member (self, name);
escaped = gtk_json_printer_escape_string (self, s);
gtk_json_printer_write (self, escaped);
g_free (escaped);
}
void
gtk_json_printer_add_null (GtkJsonPrinter *self,
const char *name)
{
g_return_if_fail (self != NULL);
g_return_if_fail ((self->block->type == GTK_JSON_BLOCK_OBJECT) == (name != NULL));
gtk_json_printer_begin_member (self, name);
gtk_json_printer_write (self, "null");
}
void
gtk_json_printer_start_object (GtkJsonPrinter *self,
const char *name)
{
g_return_if_fail (self != NULL);
g_return_if_fail ((self->block->type == GTK_JSON_BLOCK_OBJECT) == (name != NULL));
gtk_json_printer_begin_member (self, name);
gtk_json_printer_write (self, "{");
gtk_json_printer_push_block (self, GTK_JSON_BLOCK_OBJECT);
}
void
gtk_json_printer_start_array (GtkJsonPrinter *self,
const char *name)
{
g_return_if_fail (self != NULL);
g_return_if_fail ((self->block->type == GTK_JSON_BLOCK_OBJECT) == (name != NULL));
gtk_json_printer_begin_member (self, name);
gtk_json_printer_write (self, "[");
gtk_json_printer_push_block (self, GTK_JSON_BLOCK_ARRAY);
}
void
gtk_json_printer_end (GtkJsonPrinter *self)
{
const char *bracket;
gboolean empty;
g_return_if_fail (self != NULL);
switch (self->block->type)
{
case GTK_JSON_BLOCK_OBJECT:
bracket = "}";
break;
case GTK_JSON_BLOCK_ARRAY:
bracket = "]";
break;
case GTK_JSON_BLOCK_TOPLEVEL:
default:
g_return_if_reached ();
}
empty = gtk_json_printer_get_n_elements (self) == 0;
gtk_json_printer_pop_block (self);
if (!empty)
{
gtk_json_printer_newline (self);
}
gtk_json_printer_write (self, bracket);
}
/*
* Copyright © 2021 Benjamin Otte
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Benjamin Otte <otte@gnome.org>
*/
#ifndef __GTK_JSON_PRINTER_H__
#define __GTK_JSON_PRINTER_H__
#include <glib.h>
G_BEGIN_DECLS
typedef struct _GtkJsonPrinter GtkJsonPrinter;
typedef enum {
GTK_JSON_PRINTER_PRETTY = (1 << 0),
GTK_JSON_PRINTER_ASCII = (1 << 1),
} GtkJsonPrinterFlags;
typedef void (* GtkJsonPrinterWriteFunc) (GtkJsonPrinter *printer,
const char *s,
gpointer user_data);
GtkJsonPrinter * gtk_json_printer_new (GtkJsonPrinterWriteFunc write_func,
gpointer data,
GDestroyNotify destroy);
void gtk_json_printer_free (GtkJsonPrinter *self);
void gtk_json_printer_set_flags (GtkJsonPrinter *self,
GtkJsonPrinterFlags flags);
GtkJsonPrinterFlags gtk_json_printer_get_flags (GtkJsonPrinter *self);
void gtk_json_printer_set_indentation (GtkJsonPrinter *self,
gsize amount);
gsize gtk_json_printer_get_indentation (GtkJsonPrinter *self);
gsize gtk_json_printer_get_depth (GtkJsonPrinter *self);
gsize gtk_json_printer_get_n_elements (GtkJsonPrinter *self);
void gtk_json_printer_add_boolean (GtkJsonPrinter *self,
const char *name,
gboolean value);
void gtk_json_printer_add_number (GtkJsonPrinter *self,
const char *name,
double value);
void gtk_json_printer_add_integer (GtkJsonPrinter *self,
const char *name,
int value);
void gtk_json_printer_add_string (GtkJsonPrinter *self,
const char *name,
const char *s);
void gtk_json_printer_add_null (GtkJsonPrinter *self,
const char *name);
void gtk_json_printer_start_object (GtkJsonPrinter *self,
const char *name);
void gtk_json_printer_start_array (GtkJsonPrinter *self,
const char *name);
void gtk_json_printer_end (GtkJsonPrinter *self);
G_END_DECLS
#endif /* __GTK_JSON_PRINTER_H__ */
......@@ -28,6 +28,8 @@ pango_sources = [
'reorder-items.c',
'shape.c',
'serializer.c',
'json/gtkjsonparser.c',
'json/gtkjsonprinter.c',
]
pango_headers = [
......
This diff is collapsed.
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment