Mercurial > pidgin
comparison src/stringref.c @ 7786:203a18e56dc6
[gaim-migrate @ 8431]
* Documentation is good. Not that I have any idea if any of my
documentation works, because I haven't checked... I totally made up
@note, but it sure seems reasonable to me.
* A couple of stringref utility functions which seem useful in any
case, like len and cmp.
* I'm going ahead and pushing a stringref creation function which
creates a zero-refcount stringref into CVS... Nothing uses it yet,
but I think that it is useful even in the absence of major stringref
conversion ... because it's garbage collected! If no one refs it
before the next iteration of the mainloop, it will be freed ... if
it is ref'd, of course, it will have to be freed normally by an
unref at some later point.
committer: Tailor Script <tailor@pidgin.im>
author | Ethan Blanton <elb@pidgin.im> |
---|---|
date | Sun, 07 Dec 2003 16:28:34 +0000 |
parents | 136c65e68fb1 |
children | 6741cac0bf52 |
comparison
equal
deleted
inserted
replaced
7785:d5ee9c6da122 | 7786:203a18e56dc6 |
---|---|
1 /** | 1 /** |
2 * @file stringref.c Reference-counted strings | 2 * @file stringref.c Reference-counted immutable strings |
3 * @ingroup core | 3 * @ingroup core |
4 * | 4 * |
5 * gaim | 5 * gaim |
6 * | 6 * |
7 * Copyright (C) 2003 Ethan Blanton <elb@elitists.net> | 7 * Copyright (C) 2003 Ethan Blanton <elb@elitists.net> |
27 #include <string.h> | 27 #include <string.h> |
28 #include <stdarg.h> | 28 #include <stdarg.h> |
29 | 29 |
30 #include "stringref.h" | 30 #include "stringref.h" |
31 | 31 |
32 static GList *gclist = NULL; | |
33 | |
34 static void stringref_free(GaimStringref *stringref); | |
35 static gboolean gs_idle_cb(gpointer data); | |
36 | |
32 GaimStringref *gaim_stringref_new(const char *value) | 37 GaimStringref *gaim_stringref_new(const char *value) |
33 { | 38 { |
34 GaimStringref *newref; | 39 GaimStringref *newref; |
35 | 40 |
36 if (value == NULL) | 41 if (value == NULL) |
37 return NULL; | 42 return NULL; |
38 | 43 |
39 newref = g_malloc(sizeof(GaimStringref) + strlen(value) + 1); | 44 newref = g_malloc(sizeof(GaimStringref) + strlen(value) + 1); |
40 strcpy(newref->value, value); | 45 strcpy(newref->value, value); |
41 newref->ref = 1; | 46 newref->ref = 1; |
47 | |
48 return newref; | |
49 } | |
50 | |
51 GaimStringref *gaim_stringref_new_noref(const char *value) | |
52 { | |
53 GaimStringref *newref; | |
54 | |
55 if (value == NULL) | |
56 return NULL; | |
57 | |
58 newref = g_malloc(sizeof(GaimStringref) + strlen(value) + 1); | |
59 strcpy(newref->value, value); | |
60 newref->ref = 0x80000000; | |
61 | |
62 if (gclist == NULL) | |
63 g_idle_add(gs_idle_cb, NULL); | |
64 gclist = g_list_prepend(gclist, newref); | |
42 | 65 |
43 return newref; | 66 return newref; |
44 } | 67 } |
45 | 68 |
46 GaimStringref *gaim_stringref_printf(const char *format, ...) | 69 GaimStringref *gaim_stringref_printf(const char *format, ...) |
69 } | 92 } |
70 | 93 |
71 void gaim_stringref_unref(GaimStringref *stringref) | 94 void gaim_stringref_unref(GaimStringref *stringref) |
72 { | 95 { |
73 g_return_if_fail(stringref != NULL); | 96 g_return_if_fail(stringref != NULL); |
74 if (--stringref->ref == 0) | 97 if ((--(stringref->ref) & 0x7fffffff) == 0) { |
98 if (stringref->ref & 0x80000000) | |
99 gclist = g_list_remove(gclist, stringref); | |
75 g_free(stringref); | 100 g_free(stringref); |
101 } | |
76 } | 102 } |
77 | 103 |
78 const char *gaim_stringref_value(const GaimStringref *stringref) | 104 const char *gaim_stringref_value(const GaimStringref *stringref) |
79 { | 105 { |
80 return (stringref == NULL ? NULL : stringref->value); | 106 return (stringref == NULL ? NULL : stringref->value); |
81 } | 107 } |
108 | |
109 int gaim_stringref_cmp(const GaimStringref *s1, const GaimStringref *s2) | |
110 { | |
111 return (s1 == s2 ? 0 : strcmp(gaim_stringref_value(s1), gaim_stringref_value(s2))); | |
112 } | |
113 | |
114 size_t gaim_stringref_len(const GaimStringref *stringref) | |
115 { | |
116 return strlen(gaim_stringref_value(stringref)); | |
117 } | |
118 | |
119 static void stringref_free(GaimStringref *stringref) | |
120 { | |
121 #ifdef DEBUG | |
122 if (stringref->ref != 0) { | |
123 gaim_debug(GAIM_DEBUG_ERROR, "stringref", "Free of nonzero (%d) ref stringref!\n", stringref->ref); | |
124 return; | |
125 } | |
126 #endif /* DEBUG */ | |
127 g_free(stringref); | |
128 } | |
129 | |
130 static gboolean gs_idle_cb(gpointer data) | |
131 { | |
132 GaimStringref *ref; | |
133 GList *del; | |
134 | |
135 while (gclist != NULL) { | |
136 ref = gclist->data; | |
137 ref->ref &= 0x7fffffff; | |
138 if (ref->ref == 0) { | |
139 stringref_free(ref); | |
140 } | |
141 del = gclist; | |
142 gclist = gclist->next; | |
143 g_list_free_1(del); | |
144 } | |
145 | |
146 return FALSE; | |
147 } |