gimpconfig-iface.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539
  1. /* LIBGIMP - The GIMP Library
  2. * Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis
  3. *
  4. * Config file serialization and deserialization interface
  5. * Copyright (C) 2001-2002 Sven Neumann <sven@gimp.org>
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  20. */
  21. #include "config.h"
  22. #include <string.h>
  23. #include <glib-object.h>
  24. #include "libgimpbase/gimpbase.h"
  25. #include "gimpconfigtypes.h"
  26. #include "gimpconfigwriter.h"
  27. #include "gimpconfig-iface.h"
  28. #include "gimpconfig-deserialize.h"
  29. #include "gimpconfig-serialize.h"
  30. #include "gimpconfig-params.h"
  31. #include "gimpconfig-utils.h"
  32. #include "gimpscanner.h"
  33. #include "libgimp/libgimp-intl.h"
  34. /*
  35. * The GimpConfig serialization and deserialization interface.
  36. */
  37. static void gimp_config_iface_base_init (GimpConfigInterface *config_iface);
  38. static gboolean gimp_config_iface_serialize (GimpConfig *config,
  39. GimpConfigWriter *writer,
  40. gpointer data);
  41. static gboolean gimp_config_iface_deserialize (GimpConfig *config,
  42. GScanner *scanner,
  43. gint nest_level,
  44. gpointer data);
  45. static GimpConfig * gimp_config_iface_duplicate (GimpConfig *config);
  46. static gboolean gimp_config_iface_equal (GimpConfig *a,
  47. GimpConfig *b);
  48. static void gimp_config_iface_reset (GimpConfig *config);
  49. GType
  50. gimp_config_interface_get_type (void)
  51. {
  52. static GType config_iface_type = 0;
  53. if (!config_iface_type)
  54. {
  55. static const GTypeInfo config_iface_info =
  56. {
  57. sizeof (GimpConfigInterface),
  58. (GBaseInitFunc) gimp_config_iface_base_init,
  59. (GBaseFinalizeFunc) NULL,
  60. };
  61. config_iface_type = g_type_register_static (G_TYPE_INTERFACE,
  62. "GimpConfigInterface",
  63. &config_iface_info,
  64. 0);
  65. g_type_interface_add_prerequisite (config_iface_type, G_TYPE_OBJECT);
  66. }
  67. return config_iface_type;
  68. }
  69. static void
  70. gimp_config_iface_base_init (GimpConfigInterface *config_iface)
  71. {
  72. if (! config_iface->serialize)
  73. {
  74. config_iface->serialize = gimp_config_iface_serialize;
  75. config_iface->deserialize = gimp_config_iface_deserialize;
  76. config_iface->duplicate = gimp_config_iface_duplicate;
  77. config_iface->equal = gimp_config_iface_equal;
  78. config_iface->reset = gimp_config_iface_reset;
  79. }
  80. /* always set these to NULL since we don't want to inherit them
  81. * from parent classes
  82. */
  83. config_iface->serialize_property = NULL;
  84. config_iface->deserialize_property = NULL;
  85. }
  86. static gboolean
  87. gimp_config_iface_serialize (GimpConfig *config,
  88. GimpConfigWriter *writer,
  89. gpointer data)
  90. {
  91. return gimp_config_serialize_properties (config, writer);
  92. }
  93. static gboolean
  94. gimp_config_iface_deserialize (GimpConfig *config,
  95. GScanner *scanner,
  96. gint nest_level,
  97. gpointer data)
  98. {
  99. return gimp_config_deserialize_properties (config, scanner, nest_level);
  100. }
  101. static GimpConfig *
  102. gimp_config_iface_duplicate (GimpConfig *config)
  103. {
  104. GObject *object = G_OBJECT (config);
  105. GObjectClass *klass = G_OBJECT_GET_CLASS (object);
  106. GParamSpec **property_specs;
  107. guint n_property_specs;
  108. GParameter *construct_params = NULL;
  109. gint n_construct_params = 0;
  110. guint i;
  111. GObject *dup;
  112. property_specs = g_object_class_list_properties (klass, &n_property_specs);
  113. construct_params = g_new0 (GParameter, n_property_specs);
  114. for (i = 0; i < n_property_specs; i++)
  115. {
  116. GParamSpec *prop_spec = property_specs[i];
  117. if ((prop_spec->flags & G_PARAM_READABLE) &&
  118. (prop_spec->flags & G_PARAM_WRITABLE) &&
  119. (prop_spec->flags & G_PARAM_CONSTRUCT_ONLY))
  120. {
  121. GParameter *construct_param;
  122. construct_param = &construct_params[n_construct_params++];
  123. construct_param->name = prop_spec->name;
  124. g_value_init (&construct_param->value, prop_spec->value_type);
  125. g_object_get_property (object,
  126. prop_spec->name, &construct_param->value);
  127. }
  128. }
  129. g_free (property_specs);
  130. dup = g_object_newv (G_TYPE_FROM_INSTANCE (object),
  131. n_construct_params, construct_params);
  132. for (i = 0; i < n_construct_params; i++)
  133. g_value_unset (&construct_params[i].value);
  134. g_free (construct_params);
  135. gimp_config_sync (object, dup, 0);
  136. return GIMP_CONFIG (dup);
  137. }
  138. static gboolean
  139. gimp_config_iface_equal (GimpConfig *a,
  140. GimpConfig *b)
  141. {
  142. GObjectClass *klass;
  143. GParamSpec **property_specs;
  144. guint n_property_specs;
  145. guint i;
  146. gboolean equal = TRUE;
  147. klass = G_OBJECT_GET_CLASS (a);
  148. property_specs = g_object_class_list_properties (klass, &n_property_specs);
  149. for (i = 0; equal && i < n_property_specs; i++)
  150. {
  151. GParamSpec *prop_spec;
  152. GValue a_value = { 0, };
  153. GValue b_value = { 0, };
  154. prop_spec = property_specs[i];
  155. if (! (prop_spec->flags & G_PARAM_READABLE))
  156. continue;
  157. g_value_init (&a_value, prop_spec->value_type);
  158. g_value_init (&b_value, prop_spec->value_type);
  159. g_object_get_property (G_OBJECT (a), prop_spec->name, &a_value);
  160. g_object_get_property (G_OBJECT (b), prop_spec->name, &b_value);
  161. if (g_param_values_cmp (prop_spec, &a_value, &b_value))
  162. {
  163. if ((prop_spec->flags & GIMP_CONFIG_PARAM_AGGREGATE) &&
  164. G_IS_PARAM_SPEC_OBJECT (prop_spec) &&
  165. g_type_interface_peek (g_type_class_peek (prop_spec->value_type),
  166. GIMP_TYPE_CONFIG))
  167. {
  168. if (! gimp_config_is_equal_to (g_value_get_object (&a_value),
  169. g_value_get_object (&b_value)))
  170. {
  171. equal = FALSE;
  172. }
  173. }
  174. else
  175. {
  176. equal = FALSE;
  177. }
  178. }
  179. g_value_unset (&a_value);
  180. g_value_unset (&b_value);
  181. }
  182. g_free (property_specs);
  183. return equal;
  184. }
  185. static void
  186. gimp_config_iface_reset (GimpConfig *config)
  187. {
  188. gimp_config_reset_properties (G_OBJECT (config));
  189. }
  190. /**
  191. * gimp_config_serialize_to_file:
  192. * @config: a #GObject that implements the #GimpConfigInterface.
  193. * @filename: the name of the file to write the configuration to.
  194. * @header: optional file header (must be ASCII only)
  195. * @footer: optional file footer (must be ASCII only)
  196. * @data: user data passed to the serialize implementation.
  197. * @error:
  198. *
  199. * Serializes the object properties of @config to the file specified
  200. * by @filename. If a file with that name already exists, it is
  201. * overwritten. Basically this function opens @filename for you and
  202. * calls the serialize function of the @config's #GimpConfigInterface.
  203. *
  204. * Return value: %TRUE if serialization succeeded, %FALSE otherwise.
  205. *
  206. * Since: GIMP 2.4
  207. **/
  208. gboolean
  209. gimp_config_serialize_to_file (GimpConfig *config,
  210. const gchar *filename,
  211. const gchar *header,
  212. const gchar *footer,
  213. gpointer data,
  214. GError **error)
  215. {
  216. GimpConfigWriter *writer;
  217. g_return_val_if_fail (GIMP_IS_CONFIG (config), FALSE);
  218. g_return_val_if_fail (filename != NULL, FALSE);
  219. g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
  220. writer = gimp_config_writer_new_file (filename, TRUE, header, error);
  221. if (!writer)
  222. return FALSE;
  223. GIMP_CONFIG_GET_INTERFACE (config)->serialize (config, writer, data);
  224. return gimp_config_writer_finish (writer, footer, error);
  225. }
  226. /**
  227. * gimp_config_serialize_to_fd:
  228. * @config: a #GObject that implements the #GimpConfigInterface.
  229. * @fd: a file descriptor, opened for writing
  230. * @data: user data passed to the serialize implementation.
  231. *
  232. * Serializes the object properties of @config to the given file
  233. * descriptor.
  234. *
  235. * Return value: %TRUE if serialization succeeded, %FALSE otherwise.
  236. *
  237. * Since: GIMP 2.4
  238. **/
  239. gboolean
  240. gimp_config_serialize_to_fd (GimpConfig *config,
  241. gint fd,
  242. gpointer data)
  243. {
  244. GimpConfigWriter *writer;
  245. g_return_val_if_fail (GIMP_IS_CONFIG (config), FALSE);
  246. g_return_val_if_fail (fd > 0, FALSE);
  247. writer = gimp_config_writer_new_fd (fd);
  248. if (!writer)
  249. return FALSE;
  250. GIMP_CONFIG_GET_INTERFACE (config)->serialize (config, writer, data);
  251. return gimp_config_writer_finish (writer, NULL, NULL);
  252. }
  253. /**
  254. * gimp_config_serialize_to_string:
  255. * @config: a #GObject that implements the #GimpConfigInterface.
  256. * @data: user data passed to the serialize implementation.
  257. *
  258. * Serializes the object properties of @config to a string.
  259. *
  260. * Return value: a newly allocated %NUL-terminated string.
  261. *
  262. * Since: GIMP 2.4
  263. **/
  264. gchar *
  265. gimp_config_serialize_to_string (GimpConfig *config,
  266. gpointer data)
  267. {
  268. GimpConfigWriter *writer;
  269. GString *str;
  270. g_return_val_if_fail (GIMP_IS_CONFIG (config), NULL);
  271. str = g_string_new (NULL);
  272. writer = gimp_config_writer_new_string (str);
  273. GIMP_CONFIG_GET_INTERFACE (config)->serialize (config, writer, data);
  274. gimp_config_writer_finish (writer, NULL, NULL);
  275. return g_string_free (str, FALSE);
  276. }
  277. /**
  278. * gimp_config_deserialize:
  279. * @config: a #GObject that implements the #GimpConfigInterface.
  280. * @filename: the name of the file to read configuration from.
  281. * @data: user data passed to the deserialize implementation.
  282. * @error:
  283. *
  284. * Opens the file specified by @filename, reads configuration data
  285. * from it and configures @config accordingly. Basically this function
  286. * creates a properly configured #GScanner for you and calls the
  287. * deserialize function of the @config's #GimpConfigInterface.
  288. *
  289. * Return value: %TRUE if deserialization succeeded, %FALSE otherwise.
  290. *
  291. * Since: GIMP 2.4
  292. **/
  293. gboolean
  294. gimp_config_deserialize_file (GimpConfig *config,
  295. const gchar *filename,
  296. gpointer data,
  297. GError **error)
  298. {
  299. GScanner *scanner;
  300. gboolean success;
  301. g_return_val_if_fail (GIMP_IS_CONFIG (config), FALSE);
  302. g_return_val_if_fail (filename != NULL, FALSE);
  303. g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
  304. scanner = gimp_scanner_new_file (filename, error);
  305. if (! scanner)
  306. return FALSE;
  307. success = GIMP_CONFIG_GET_INTERFACE (config)->deserialize (config,
  308. scanner, 0, data);
  309. gimp_scanner_destroy (scanner);
  310. if (! success)
  311. g_assert (error == NULL || *error != NULL);
  312. return success;
  313. }
  314. /**
  315. * gimp_config_deserialize_string:
  316. * @config: a #GObject that implements the #GimpConfigInterface.
  317. * @text: string to deserialize (in UTF-8 encoding)
  318. * @text_len: length of @text in bytes or -1
  319. * @data:
  320. * @error:
  321. *
  322. * Configures @config from @text. Basically this function creates a
  323. * properly configured #GScanner for you and calls the deserialize
  324. * function of the @config's #GimpConfigInterface.
  325. *
  326. * Returns: %TRUE if deserialization succeeded, %FALSE otherwise.
  327. *
  328. * Since: GIMP 2.4
  329. **/
  330. gboolean
  331. gimp_config_deserialize_string (GimpConfig *config,
  332. const gchar *text,
  333. gint text_len,
  334. gpointer data,
  335. GError **error)
  336. {
  337. GScanner *scanner;
  338. gboolean success;
  339. g_return_val_if_fail (GIMP_IS_CONFIG (config), FALSE);
  340. g_return_val_if_fail (text != NULL || text_len == 0, FALSE);
  341. g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
  342. scanner = gimp_scanner_new_string (text, text_len, error);
  343. success = GIMP_CONFIG_GET_INTERFACE (config)->deserialize (config,
  344. scanner, 0, data);
  345. gimp_scanner_destroy (scanner);
  346. if (! success)
  347. g_assert (error == NULL || *error != NULL);
  348. return success;
  349. }
  350. /**
  351. * gimp_config_deserialize_return:
  352. * @scanner:
  353. * @expected_token:
  354. * @nest_level:
  355. *
  356. * Returns:
  357. *
  358. * Since: GIMP 2.4
  359. **/
  360. gboolean
  361. gimp_config_deserialize_return (GScanner *scanner,
  362. GTokenType expected_token,
  363. gint nest_level)
  364. {
  365. GTokenType next_token;
  366. g_return_val_if_fail (scanner != NULL, FALSE);
  367. next_token = g_scanner_peek_next_token (scanner);
  368. if (expected_token != G_TOKEN_LEFT_PAREN)
  369. {
  370. g_scanner_get_next_token (scanner);
  371. g_scanner_unexp_token (scanner, expected_token, NULL, NULL, NULL,
  372. _("fatal parse error"), TRUE);
  373. return FALSE;
  374. }
  375. else
  376. {
  377. if (nest_level > 0 && next_token == G_TOKEN_RIGHT_PAREN)
  378. {
  379. return TRUE;
  380. }
  381. else if (next_token != G_TOKEN_EOF)
  382. {
  383. g_scanner_get_next_token (scanner);
  384. g_scanner_unexp_token (scanner, expected_token, NULL, NULL, NULL,
  385. _("fatal parse error"), TRUE);
  386. return FALSE;
  387. }
  388. }
  389. return TRUE;
  390. }
  391. /**
  392. * gimp_config_duplicate:
  393. * @config: a #GObject that implements the #GimpConfigInterface.
  394. *
  395. * Creates a copy of the passed object by copying all object
  396. * properties. The default implementation of the #GimpConfigInterface
  397. * only works for objects that are completely defined by their
  398. * properties.
  399. *
  400. * Return value: the duplicated #GimpConfig object
  401. *
  402. * Since: GIMP 2.4
  403. **/
  404. gpointer
  405. gimp_config_duplicate (GimpConfig *config)
  406. {
  407. g_return_val_if_fail (GIMP_IS_CONFIG (config), NULL);
  408. return GIMP_CONFIG_GET_INTERFACE (config)->duplicate (config);
  409. }
  410. /**
  411. * gimp_config_is_equal_to:
  412. * @a: a #GObject that implements the #GimpConfigInterface.
  413. * @b: another #GObject of the same type as @a.
  414. *
  415. * Compares the two objects. The default implementation of the
  416. * #GimpConfigInterface compares the object properties and thus only
  417. * works for objects that are completely defined by their
  418. * properties.
  419. *
  420. * Return value: %TRUE if the two objects are equal.
  421. *
  422. * Since: GIMP 2.4
  423. **/
  424. gboolean
  425. gimp_config_is_equal_to (GimpConfig *a,
  426. GimpConfig *b)
  427. {
  428. g_return_val_if_fail (GIMP_IS_CONFIG (a), FALSE);
  429. g_return_val_if_fail (GIMP_IS_CONFIG (b), FALSE);
  430. g_return_val_if_fail (G_TYPE_FROM_INSTANCE (a) == G_TYPE_FROM_INSTANCE (b),
  431. FALSE);
  432. return GIMP_CONFIG_GET_INTERFACE (a)->equal (a, b);
  433. }
  434. /**
  435. * gimp_config_reset:
  436. * @config: a #GObject that implements the #GimpConfigInterface.
  437. *
  438. * Resets the object to its default state. The default implementation of the
  439. * #GimpConfigInterface only works for objects that are completely defined by
  440. * their properties.
  441. *
  442. * Since: GIMP 2.4
  443. **/
  444. void
  445. gimp_config_reset (GimpConfig *config)
  446. {
  447. g_return_if_fail (GIMP_IS_CONFIG (config));
  448. GIMP_CONFIG_GET_INTERFACE (config)->reset (config);
  449. }