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 }