Wed, 13 May 2009 20:29:03 +0000
Support custom smileys in MUCs (when all participants support BoB and a maximum
of 10 participants are in the chat).
Always announce support for BoB, since disable custom smileys will still turn
off fetching them, and BoB can be used for other purposes further on.
| 7763 | 1 | /** |
| 7786 | 2 | * @file stringref.c Reference-counted immutable strings |
| 7763 | 3 | * @ingroup core |
|
20147
66f05a854eee
applied changes from 8a731bbd0197fbcc91a705c2d8f528154216defa
Richard Laager <rlaager@pidgin.im>
parents:
19859
diff
changeset
|
4 | */ |
|
66f05a854eee
applied changes from 8a731bbd0197fbcc91a705c2d8f528154216defa
Richard Laager <rlaager@pidgin.im>
parents:
19859
diff
changeset
|
5 | |
|
66f05a854eee
applied changes from 8a731bbd0197fbcc91a705c2d8f528154216defa
Richard Laager <rlaager@pidgin.im>
parents:
19859
diff
changeset
|
6 | /* purple |
| 7763 | 7 | * |
| 15884 | 8 | * Purple is the legal property of its developers, whose names are too numerous |
| 8046 | 9 | * to list here. Please refer to the COPYRIGHT file distributed with this |
| 10 | * source distribution. | |
| 7763 | 11 | * |
| 12 | * This program is free software; you can redistribute it and/or modify | |
| 13 | * it under the terms of the GNU General Public License as published by | |
| 14 | * the Free Software Foundation; either version 2 of the License, or | |
| 15 | * (at your option) any later version. | |
| 16 | * | |
| 17 | * This program is distributed in the hope that it will be useful, | |
| 18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 20 | * GNU General Public License for more details. | |
| 21 | * | |
| 22 | * You should have received a copy of the GNU General Public License | |
| 23 | * along with this program; if not, write to the Free Software | |
|
19859
71d37b57eff2
The FSF changed its address a while ago; our files were out of date.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
15884
diff
changeset
|
24 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA |
| 7763 | 25 | * |
| 26 | */ | |
| 27 | ||
| 28 | #include "internal.h" | |
| 29 | ||
| 30 | #include <string.h> | |
| 7767 | 31 | #include <stdarg.h> |
| 7763 | 32 | |
| 7789 | 33 | #include "debug.h" |
|
22351
6ca0640b3d31
Change some g_idle_add(...) calls in libpurple to purple_timeout_add(0, ...)
Mark Doliner <markdoliner@pidgin.im>
parents:
20147
diff
changeset
|
34 | #include "eventloop.h" |
| 7763 | 35 | #include "stringref.h" |
| 36 | ||
|
14988
66b34458d49e
[gaim-migrate @ 17698]
Richard Laager <rlaager@pidgin.im>
parents:
14254
diff
changeset
|
37 | /** |
|
66b34458d49e
[gaim-migrate @ 17698]
Richard Laager <rlaager@pidgin.im>
parents:
14254
diff
changeset
|
38 | * The internal representation of a stringref. |
|
66b34458d49e
[gaim-migrate @ 17698]
Richard Laager <rlaager@pidgin.im>
parents:
14254
diff
changeset
|
39 | * |
|
66b34458d49e
[gaim-migrate @ 17698]
Richard Laager <rlaager@pidgin.im>
parents:
14254
diff
changeset
|
40 | * @note For this structure to be useful, the string contained within |
|
66b34458d49e
[gaim-migrate @ 17698]
Richard Laager <rlaager@pidgin.im>
parents:
14254
diff
changeset
|
41 | * it must be immutable -- for this reason, do _not_ access it |
|
66b34458d49e
[gaim-migrate @ 17698]
Richard Laager <rlaager@pidgin.im>
parents:
14254
diff
changeset
|
42 | * directly! |
|
66b34458d49e
[gaim-migrate @ 17698]
Richard Laager <rlaager@pidgin.im>
parents:
14254
diff
changeset
|
43 | */ |
| 15884 | 44 | struct _PurpleStringref { |
|
14988
66b34458d49e
[gaim-migrate @ 17698]
Richard Laager <rlaager@pidgin.im>
parents:
14254
diff
changeset
|
45 | guint32 ref; /**< The reference count of this string. |
|
66b34458d49e
[gaim-migrate @ 17698]
Richard Laager <rlaager@pidgin.im>
parents:
14254
diff
changeset
|
46 | * Note that reference counts are only |
|
66b34458d49e
[gaim-migrate @ 17698]
Richard Laager <rlaager@pidgin.im>
parents:
14254
diff
changeset
|
47 | * 31 bits, and the high-order bit |
|
66b34458d49e
[gaim-migrate @ 17698]
Richard Laager <rlaager@pidgin.im>
parents:
14254
diff
changeset
|
48 | * indicates whether this string is up |
|
66b34458d49e
[gaim-migrate @ 17698]
Richard Laager <rlaager@pidgin.im>
parents:
14254
diff
changeset
|
49 | * for GC at the next idle handler... |
|
66b34458d49e
[gaim-migrate @ 17698]
Richard Laager <rlaager@pidgin.im>
parents:
14254
diff
changeset
|
50 | * But you aren't going to touch this |
|
66b34458d49e
[gaim-migrate @ 17698]
Richard Laager <rlaager@pidgin.im>
parents:
14254
diff
changeset
|
51 | * anyway, right? */ |
|
66b34458d49e
[gaim-migrate @ 17698]
Richard Laager <rlaager@pidgin.im>
parents:
14254
diff
changeset
|
52 | char value[1]; /**< The string contained in this ref. |
|
66b34458d49e
[gaim-migrate @ 17698]
Richard Laager <rlaager@pidgin.im>
parents:
14254
diff
changeset
|
53 | * Notice that it is simply "hanging |
|
66b34458d49e
[gaim-migrate @ 17698]
Richard Laager <rlaager@pidgin.im>
parents:
14254
diff
changeset
|
54 | * off the end" of the ref ... this |
|
66b34458d49e
[gaim-migrate @ 17698]
Richard Laager <rlaager@pidgin.im>
parents:
14254
diff
changeset
|
55 | * is to save an allocation. */ |
|
66b34458d49e
[gaim-migrate @ 17698]
Richard Laager <rlaager@pidgin.im>
parents:
14254
diff
changeset
|
56 | }; |
|
66b34458d49e
[gaim-migrate @ 17698]
Richard Laager <rlaager@pidgin.im>
parents:
14254
diff
changeset
|
57 | |
| 7795 | 58 | #define REFCOUNT(x) ((x) & 0x7fffffff) |
| 59 | ||
| 7786 | 60 | static GList *gclist = NULL; |
| 61 | ||
| 15884 | 62 | static void stringref_free(PurpleStringref *stringref); |
| 7786 | 63 | static gboolean gs_idle_cb(gpointer data); |
| 64 | ||
| 15884 | 65 | PurpleStringref *purple_stringref_new(const char *value) |
| 7763 | 66 | { |
| 15884 | 67 | PurpleStringref *newref; |
| 7763 | 68 | |
| 7772 | 69 | if (value == NULL) |
| 70 | return NULL; | |
| 71 | ||
| 15884 | 72 | newref = g_malloc(sizeof(PurpleStringref) + strlen(value)); |
| 7763 | 73 | strcpy(newref->value, value); |
| 74 | newref->ref = 1; | |
| 75 | ||
| 76 | return newref; | |
| 77 | } | |
| 78 | ||
| 15884 | 79 | PurpleStringref *purple_stringref_new_noref(const char *value) |
| 7786 | 80 | { |
| 15884 | 81 | PurpleStringref *newref; |
| 7786 | 82 | |
| 83 | if (value == NULL) | |
| 84 | return NULL; | |
| 85 | ||
| 15884 | 86 | newref = g_malloc(sizeof(PurpleStringref) + strlen(value)); |
| 7786 | 87 | strcpy(newref->value, value); |
| 88 | newref->ref = 0x80000000; | |
| 89 | ||
| 90 | if (gclist == NULL) | |
|
22351
6ca0640b3d31
Change some g_idle_add(...) calls in libpurple to purple_timeout_add(0, ...)
Mark Doliner <markdoliner@pidgin.im>
parents:
20147
diff
changeset
|
91 | purple_timeout_add(0, gs_idle_cb, NULL); |
| 7786 | 92 | gclist = g_list_prepend(gclist, newref); |
| 93 | ||
| 94 | return newref; | |
| 95 | } | |
| 96 | ||
| 15884 | 97 | PurpleStringref *purple_stringref_printf(const char *format, ...) |
| 7767 | 98 | { |
| 15884 | 99 | PurpleStringref *newref; |
| 7767 | 100 | va_list ap; |
| 101 | ||
| 102 | if (format == NULL) | |
| 103 | return NULL; | |
| 104 | ||
| 105 | va_start(ap, format); | |
| 15884 | 106 | newref = g_malloc(sizeof(PurpleStringref) + g_printf_string_upper_bound(format, ap)); |
| 7767 | 107 | vsprintf(newref->value, format, ap); |
| 108 | va_end(ap); | |
| 7784 | 109 | newref->ref = 1; |
| 7767 | 110 | |
| 111 | return newref; | |
| 112 | } | |
| 113 | ||
| 15884 | 114 | PurpleStringref *purple_stringref_ref(PurpleStringref *stringref) |
| 7763 | 115 | { |
| 116 | if (stringref == NULL) | |
| 117 | return NULL; | |
| 118 | stringref->ref++; | |
| 119 | return stringref; | |
| 120 | } | |
| 121 | ||
| 15884 | 122 | void purple_stringref_unref(PurpleStringref *stringref) |
| 7763 | 123 | { |
| 7790 | 124 | if (stringref == NULL) |
| 125 | return; | |
| 7795 | 126 | if (REFCOUNT(--(stringref->ref)) == 0) { |
| 7786 | 127 | if (stringref->ref & 0x80000000) |
| 128 | gclist = g_list_remove(gclist, stringref); | |
| 7788 | 129 | stringref_free(stringref); |
| 7786 | 130 | } |
| 7763 | 131 | } |
| 132 | ||
| 15884 | 133 | const char *purple_stringref_value(const PurpleStringref *stringref) |
| 7763 | 134 | { |
| 135 | return (stringref == NULL ? NULL : stringref->value); | |
| 136 | } | |
| 7786 | 137 | |
| 15884 | 138 | int purple_stringref_cmp(const PurpleStringref *s1, const PurpleStringref *s2) |
| 7786 | 139 | { |
| 15884 | 140 | return (s1 == s2 ? 0 : strcmp(purple_stringref_value(s1), purple_stringref_value(s2))); |
| 7786 | 141 | } |
| 142 | ||
| 15884 | 143 | size_t purple_stringref_len(const PurpleStringref *stringref) |
| 7786 | 144 | { |
| 15884 | 145 | return strlen(purple_stringref_value(stringref)); |
| 7786 | 146 | } |
| 147 | ||
| 15884 | 148 | static void stringref_free(PurpleStringref *stringref) |
| 7786 | 149 | { |
| 150 | #ifdef DEBUG | |
| 7795 | 151 | if (REFCOUNT(stringref->ref) != 0) { |
| 15884 | 152 | purple_debug(PURPLE_DEBUG_ERROR, "stringref", "Free of nonzero (%d) ref stringref!\n", REFCOUNT(stringref->ref)); |
| 7786 | 153 | return; |
| 154 | } | |
| 155 | #endif /* DEBUG */ | |
| 156 | g_free(stringref); | |
| 157 | } | |
| 158 | ||
| 159 | static gboolean gs_idle_cb(gpointer data) | |
| 160 | { | |
| 15884 | 161 | PurpleStringref *ref; |
| 7786 | 162 | GList *del; |
| 163 | ||
| 164 | while (gclist != NULL) { | |
| 165 | ref = gclist->data; | |
| 7795 | 166 | if (REFCOUNT(ref->ref) == 0) { |
| 7786 | 167 | stringref_free(ref); |
| 168 | } | |
| 169 | del = gclist; | |
| 170 | gclist = gclist->next; | |
| 171 | g_list_free_1(del); | |
| 172 | } | |
| 173 | ||
| 174 | return FALSE; | |
| 175 | } |