/* convert-emoji.c: A tool to create an Emoji data GVariant
* Copyright 2017 , Red Hat , Inc .
*
* 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 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/>.
*/
/* Build with gcc -o convert-emoji convert-emoji.c `pkg-config --cflags --libs json-glib-1.0`
*/
/* Reads data from the json files in emojibase, expecting
* language - specific data . raw . json as input
*/
/* The format of the generated data is: a(aussasasu).
* Each member of the array has the following fields :
* au - sequence of unicode codepoints , including the emoji presentation
* selector ( FE0F ) where necessary . skin tone variations are represented
* with either the first tone code point ( 1 F3FB ) or 0 . the choice indicates
* the handling of the generic sequence ( i . e . , no tone ) , which may have a
* default text presentation and thus require the emoji presentation
* selector ( unlike sequences with a tone , which are always presented as
* emojis ) . 0 indicates the text case , that is , replace this code point
* with FE0F , while 1 F3FB indicates this code point should be omitted .
* s - name in english , e . g . " man worker "
* s - name in locale
* as - keywords in english , e . g . " man " , " worker "
* as - keywords in locale
* u - the group that this item belongs to :
* 0 : smileys - emotion
* 1 : people - body
* 2 : component
* 3 : animals - nature
* 4 : food - drink
* 5 : travel - places
* 6 : activities
* 7 : objects
* 8 : symbols
* 9 : flags
*/
#include <json-glib/json-glib.h>
#include <string.h>
gboolean
parse_code (GVariantBuilder *b,
const char *code,
gboolean needs_presentation_selector)
{
char **strv;
int j;
strv = g_strsplit (code, "-" , -1 );
for (j = 0 ; strv[j]; j++)
{
guint32 u;
char *end;
u = (guint32) g_ascii_strtoull (strv[j], &end, 16 );
if (*end != '\0' )
{
g_error ("failed to parse code: %s\n" , strv[j]);
g_strfreev (strv);
return FALSE ;
}
if (0 x1f3fb <= u && u <= 0 x1f3ff)
{
if (needs_presentation_selector)
{
if (strv[j+1 ])
{
g_error ("unexpected inner skin tone in default-text generic sequence: %s\n" , code);
g_strfreev (strv);
return FALSE ;
}
g_variant_builder_add (b, "u" , 0 );
needs_presentation_selector = FALSE ;
}
else
{
g_variant_builder_add (b, "u" , 0 x1f3fb);
}
}
else
{
g_variant_builder_add (b, "u" , u);
}
}
if (needs_presentation_selector)
g_variant_builder_add (b, "u" , 0 xfe0f);
g_strfreev (strv);
return TRUE ;
}
int
main (int argc, char *argv[])
{
JsonParser *parser;
JsonNode *root;
JsonParser *parser_en;
JsonNode *root_en;
JsonObject *ro;
JsonArray *array;
JsonArray *array_en;
JsonNode *node;
const char *unicode;
JsonObjectIter iter;
GError *error = NULL;
guint length, length_en, i;
GVariantBuilder builder;
GVariant *v;
GString *s;
GHashTable *names;
if (argc != 4 ) //0 -> compiled file, 1 -> en/data.raw.json, 2 -> de/data.raw.json, 3 -> de.data
{
g_print ("Usage: emoji-convert INPUT1 INPUT2 OUTPUT\nINPUT1 should be raw json data for English\nINPUT2 should be raw json data for the locale\n" );
return 1 ;
}
parser = json_parser_new ();
parser_en = json_parser_new ();
if (!json_parser_load_from_file (parser_en, argv[1 ], &error))
{
g_error ("%s" , error->message);
return 1 ;
}
if (!json_parser_load_from_file (parser, argv[2 ], &error))
{
g_error ("%s" , error->message);
return 1 ;
}
root = json_parser_get_root (parser);
array = json_node_get_array (root);
length = json_array_get_length (array);
root_en = json_parser_get_root (parser_en);
array_en = json_node_get_array (root_en);
length_en = json_array_get_length (array_en);
g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(aussasasu)" ));
for (i = 0 ; i < length; i++)
{
JsonObject *obj = json_array_get_object_element (array, i);
JsonObject *obj_en = json_array_get_object_element (array_en, i);
GVariantBuilder b1;
GVariantBuilder b2;
GVariantBuilder b3;
guint group;
const char *name;
const char *name_en;
char *code;
const char *text;
gboolean needs_presentation_selector;
if (!json_object_has_member (obj, "group" ))
continue ;
if (!json_object_has_member (obj_en, "group" ))
continue ;
group = json_object_get_int_member (obj, "group" );
name = json_object_get_string_member (obj, "label" );
name_en = json_object_get_string_member (obj_en, "label" );
if (g_str_has_suffix (name_en, "skin tone" ))
continue ;
if (json_object_has_member (obj, "skins" ) && json_object_has_member (obj_en, "skins" ))
{
JsonArray *a2 = json_object_get_array_member (obj, "skins" );
JsonNode *n2 = json_array_get_element (a2, 0 );
JsonObject *o2 = json_node_get_object (n2);
code = g_strdup (json_object_get_string_member (o2, "hexcode" ));
}
else
{
code = g_strdup (json_object_get_string_member (obj, "hexcode" ));
}
text = json_object_get_string_member (obj, "text" );
needs_presentation_selector = *text != '\0' && json_object_get_int_member (obj, "type" ) == 0 ;
g_variant_builder_init (&b1, G_VARIANT_TYPE ("au" ));
if (!parse_code (&b1, code, needs_presentation_selector))
return 1 ;
g_variant_builder_init (&b2, G_VARIANT_TYPE ("as" ));
if (json_object_has_member (obj_en, "tags" ))
{
JsonArray *tags_en = json_object_get_array_member (obj_en, "tags" );
for (int j = 0 ; j < json_array_get_length (tags_en); j++)
{
g_variant_builder_add (&b2, "s" , json_array_get_string_element (tags_en, j));
}
}
g_variant_builder_init (&b3, G_VARIANT_TYPE ("as" ));
if (json_object_has_member (obj, "tags" ))
{
JsonArray *tags = json_object_get_array_member (obj, "tags" );
for (int j = 0 ; j < json_array_get_length (tags); j++)
{
g_variant_builder_add (&b3, "s" , json_array_get_string_element (tags, j));
}
}
g_variant_builder_add (&builder, "(aussasasu)" , &b1, name_en, name, &b2, &b3, group);
}
v = g_variant_builder_end (&builder);
if (g_str_has_suffix (argv[3 ], ".json" ))
{
JsonNode *node;
char *out;
node = json_gvariant_serialize (v);
out = json_to_string (node, TRUE );
if (!g_file_set_contents (argv[3 ], out, -1 , &error))
{
g_error ("%s" , error->message);
return 1 ;
}
}
else
{
GBytes *bytes;
bytes = g_variant_get_data_as_bytes (v);
if (!g_file_set_contents (argv[3 ], g_bytes_get_data (bytes, NULL), g_bytes_get_size (bytes), &error))
{
g_error ("%s" , error->message);
return 1 ;
}
}
return 0 ;
}
Messung V0.5 in Prozent C=98 H=96 G=96
¤ Dauer der Verarbeitung: 0.14 Sekunden
(vorverarbeitet am 2026-07-02)
¤
*© Formatika GbR, Deutschland