PageRenderTime 25ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/spicebird-0.7.1/mozilla/collab/external/telepathy-glib/telepathy-glib/handle-repo-static.c

#
C | 338 lines | 240 code | 54 blank | 44 comment | 23 complexity | 2778eba8fd4de7ff578a8f2a7a435295 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, GPL-2.0, LGPL-2.1, LGPL-3.0, MIT, BSD-3-Clause
  1. /*
  2. * handle-repo-static.c - mechanism to store and retrieve handles on a
  3. * connection (implementation for handle types with a fixed list of possible
  4. * handles)
  5. *
  6. * Copyright (C) 2007 Collabora Ltd. <http://www.collabora.co.uk/>
  7. * Copyright (C) 2007 Nokia Corporation
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation; either
  12. * version 2.1 of the License, or (at your option) any later version.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  22. */
  23. /**
  24. * SECTION:handle-repo-static
  25. * @title: TpStaticHandleRepo
  26. * @short_description: handle repository implementation with a fixed, static
  27. * set of handle names
  28. * @see_also: TpHandleRepoIface, TpDynamicHandleRepo
  29. *
  30. * A static handle repository has a fixed, static set of allowed names;
  31. * these handles can never be destroyed, and no more can be created, so
  32. * no reference counting is performed.
  33. *
  34. * The #TpHandleRepoIface:handle-type property must be set at construction
  35. * time.
  36. *
  37. * Most connection managers will use this for handles of type
  38. * %TP_HANDLE_TYPE_CONTACT_LIST.
  39. */
  40. #include <telepathy-glib/handle-repo-static.h>
  41. #include <string.h>
  42. #include <telepathy-glib/handle-repo-internal.h>
  43. enum
  44. {
  45. PROP_HANDLE_TYPE = 1,
  46. PROP_HANDLE_NAMES,
  47. };
  48. struct _TpStaticHandleRepoClass {
  49. GObjectClass parent_class;
  50. };
  51. struct _TpStaticHandleRepo {
  52. GObject parent;
  53. TpHandleType handle_type;
  54. TpHandle last_handle;
  55. gchar **handle_names;
  56. GData **datalists;
  57. };
  58. static void static_repo_iface_init (gpointer g_iface,
  59. gpointer iface_data);
  60. G_DEFINE_TYPE_WITH_CODE (TpStaticHandleRepo, tp_static_handle_repo,
  61. G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (TP_TYPE_HANDLE_REPO_IFACE,
  62. static_repo_iface_init));
  63. static void
  64. tp_static_handle_repo_init (TpStaticHandleRepo *self)
  65. {
  66. self->handle_type = 0;
  67. self->last_handle = 0;
  68. self->handle_names = NULL;
  69. self->datalists = NULL;
  70. }
  71. static void
  72. static_finalize (GObject *object)
  73. {
  74. TpStaticHandleRepo *self = TP_STATIC_HANDLE_REPO (object);
  75. guint i;
  76. if (self->datalists)
  77. {
  78. for (i = 0; i < self->last_handle; i++)
  79. {
  80. g_datalist_clear (self->datalists + i);
  81. }
  82. }
  83. g_strfreev (self->handle_names);
  84. G_OBJECT_CLASS (tp_static_handle_repo_parent_class)->finalize (object);
  85. }
  86. static void
  87. static_get_property (GObject *object,
  88. guint property_id,
  89. GValue *value,
  90. GParamSpec *pspec)
  91. {
  92. TpStaticHandleRepo *self = TP_STATIC_HANDLE_REPO (object);
  93. switch (property_id)
  94. {
  95. case PROP_HANDLE_TYPE:
  96. g_value_set_uint (value, self->handle_type);
  97. break;
  98. case PROP_HANDLE_NAMES:
  99. g_value_set_boxed (value, g_strdupv (self->handle_names));
  100. break;
  101. default:
  102. G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
  103. break;
  104. }
  105. }
  106. static void
  107. static_set_property (GObject *object,
  108. guint property_id,
  109. const GValue *value,
  110. GParamSpec *pspec)
  111. {
  112. TpStaticHandleRepo *self = TP_STATIC_HANDLE_REPO (object);
  113. TpHandle i;
  114. switch (property_id)
  115. {
  116. case PROP_HANDLE_TYPE:
  117. self->handle_type = g_value_get_uint (value);
  118. break;
  119. case PROP_HANDLE_NAMES:
  120. if (self->datalists)
  121. {
  122. for (i = 0; i < self->last_handle; i++)
  123. {
  124. g_datalist_clear (self->datalists + i);
  125. }
  126. }
  127. g_strfreev (self->handle_names);
  128. self->handle_names = g_strdupv (g_value_get_boxed (value));
  129. i = 0;
  130. while (self->handle_names[i] != NULL)
  131. {
  132. i++;
  133. }
  134. self->last_handle = i;
  135. g_free (self->datalists);
  136. self->datalists = NULL;
  137. break;
  138. default:
  139. G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
  140. break;
  141. }
  142. }
  143. static void
  144. tp_static_handle_repo_class_init (TpStaticHandleRepoClass *klass)
  145. {
  146. GObjectClass *object_class = G_OBJECT_CLASS (klass);
  147. GParamSpec *param_spec;
  148. object_class->get_property = static_get_property;
  149. object_class->set_property = static_set_property;
  150. object_class->finalize = static_finalize;
  151. g_object_class_override_property (object_class, PROP_HANDLE_TYPE,
  152. "handle-type");
  153. param_spec = g_param_spec_boxed ("handle-names", "Handle names",
  154. "The static set of handle names supported by this repo.",
  155. G_TYPE_STRV,
  156. G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE |
  157. G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NICK);
  158. g_object_class_install_property (object_class, PROP_HANDLE_NAMES,
  159. param_spec);
  160. }
  161. static gboolean
  162. static_handle_is_valid (TpHandleRepoIface *irepo,
  163. TpHandle handle,
  164. GError **error)
  165. {
  166. TpStaticHandleRepo *self = TP_STATIC_HANDLE_REPO (irepo);
  167. if (handle <= 0 || handle > self->last_handle)
  168. {
  169. g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
  170. "handle %u is not a valid %s handle (type %u)",
  171. handle, tp_handle_type_to_string (self->handle_type),
  172. self->handle_type);
  173. return FALSE;
  174. }
  175. else
  176. {
  177. return TRUE;
  178. }
  179. }
  180. static gboolean
  181. static_handles_are_valid (TpHandleRepoIface *irepo, const GArray *handles,
  182. gboolean allow_zero, GError **error)
  183. {
  184. guint i;
  185. g_return_val_if_fail (handles != NULL, FALSE);
  186. for (i = 0; i < handles->len; i++)
  187. {
  188. TpHandle handle = g_array_index (handles, TpHandle, i);
  189. if (handle == 0 && allow_zero)
  190. continue;
  191. if (!static_handle_is_valid (irepo, handle, error))
  192. return FALSE;
  193. }
  194. return TRUE;
  195. }
  196. static void
  197. static_ref_or_unref_handle (TpHandleRepoIface *self, TpHandle handle)
  198. {
  199. /* nothing to do, handles in this repo are permanent */
  200. }
  201. static gboolean
  202. static_client_hold_or_release_handle (TpHandleRepoIface *self,
  203. const gchar *client_name,
  204. TpHandle handle,
  205. GError **error)
  206. {
  207. /* nothing to do, handles in this repo are permanent */
  208. return TRUE;
  209. }
  210. static const char *
  211. static_inspect_handle (TpHandleRepoIface *irepo, TpHandle handle)
  212. {
  213. TpStaticHandleRepo *self = TP_STATIC_HANDLE_REPO (irepo);
  214. if (handle <= 0 || handle > self->last_handle)
  215. return NULL;
  216. return self->handle_names[handle-1];
  217. }
  218. static TpHandle
  219. static_lookup_handle (TpHandleRepoIface *irepo,
  220. const char *id,
  221. gpointer context,
  222. GError **error)
  223. {
  224. TpStaticHandleRepo *self = TP_STATIC_HANDLE_REPO (irepo);
  225. guint i;
  226. for (i = 0; i < self->last_handle; i++)
  227. {
  228. if (!strcmp (self->handle_names[i], id))
  229. return (TpHandle) i + 1;
  230. }
  231. g_set_error (error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
  232. "'%s' is not one of the valid handles", id);
  233. return 0;
  234. }
  235. static void
  236. static_set_qdata (TpHandleRepoIface *repo, TpHandle handle,
  237. GQuark key_id, gpointer data, GDestroyNotify destroy)
  238. {
  239. TpStaticHandleRepo *self = TP_STATIC_HANDLE_REPO (repo);
  240. guint i;
  241. g_return_if_fail (handle > 0);
  242. g_return_if_fail (handle <= self->last_handle);
  243. if (!self->datalists)
  244. {
  245. self->datalists = g_new (GData *, self->last_handle);
  246. for (i = 0; i < self->last_handle; i++)
  247. {
  248. g_datalist_init (self->datalists + i);
  249. }
  250. }
  251. g_datalist_id_set_data_full (self->datalists + handle - 1, key_id, data,
  252. destroy);
  253. }
  254. static gpointer
  255. static_get_qdata (TpHandleRepoIface *repo, TpHandle handle,
  256. GQuark key_id)
  257. {
  258. TpStaticHandleRepo *self = TP_STATIC_HANDLE_REPO (repo);
  259. g_return_val_if_fail (handle > 0, NULL);
  260. g_return_val_if_fail (handle <= self->last_handle, NULL);
  261. /* if we have no datalists that's not a bug - it means nobody has called
  262. * static_set_qdata yet */
  263. if (!self->datalists)
  264. return NULL;
  265. return g_datalist_id_get_data (self->datalists + handle - 1, key_id);
  266. }
  267. static void
  268. static_repo_iface_init (gpointer g_iface,
  269. gpointer iface_data)
  270. {
  271. TpHandleRepoIfaceClass *klass = (TpHandleRepoIfaceClass *) g_iface;
  272. klass->handle_is_valid = static_handle_is_valid;
  273. klass->handles_are_valid = static_handles_are_valid;
  274. klass->ref_handle = static_ref_or_unref_handle;
  275. klass->unref_handle = static_ref_or_unref_handle;
  276. klass->client_hold_handle = static_client_hold_or_release_handle;
  277. klass->client_release_handle = static_client_hold_or_release_handle;
  278. klass->inspect_handle = static_inspect_handle;
  279. /* this repo is static, so lookup and ensure are identical */
  280. klass->lookup_handle = static_lookup_handle;
  281. klass->ensure_handle = static_lookup_handle;
  282. klass->set_qdata = static_set_qdata;
  283. klass->get_qdata = static_get_qdata;
  284. }