1 /*
2  * e-poolv.c
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU Lesser General Public License as published by
6  * the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
11  * for more details.
12  *
13  * You should have received a copy of the GNU Lesser General Public License
14  * along with this program; if not, see <http://www.gnu.org/licenses/>.
15  *
16  */
17 
18 #include "evolution-config.h"
19 
20 #include "e-poolv.h"
21 
22 #include <string.h>
23 #include <camel/camel.h>
24 
25 struct _EPoolv {
26 	guchar length;
27 	const gchar *s[1];
28 };
29 
30 /**
31  * e_poolv_new:
32  * @size: The number of elements in the poolv, maximum of 254 elements.
33  *
34  * Create a new #EPoolv: a string vector which shares a global string
35  * pool.  An #EPoolv can be used to work with arrays of strings which
36  * save memory by eliminating duplicated allocations of the same string.
37  *
38  * This is useful when you have a log of read-only strings that do not
39  * go away and are duplicated a lot, such as email headers.
40  *
41  * Returns: a new #EPoolv
42  **/
43 EPoolv *
e_poolv_new(guint size)44 e_poolv_new (guint size)
45 {
46 	EPoolv *poolv;
47 
48 	g_return_val_if_fail (size < 255, NULL);
49 
50 	poolv = g_malloc0 (sizeof (*poolv) + (size - 1) * sizeof (gchar *));
51 	poolv->length = size;
52 
53 	return poolv;
54 }
55 
56 /**
57  * e_poolv_set:
58  * @poolv: pooled string vector
59  * @index: index in vector of string
60  * @str: string to set
61  * @freeit: whether the caller is releasing its reference to the
62  * string
63  *
64  * Set a string vector reference.  If the caller will no longer be
65  * referencing the string, freeit should be TRUE.  Otherwise, this
66  * will duplicate the string if it is not found in the pool.
67  *
68  * Returns: @poolv
69  **/
70 EPoolv *
e_poolv_set(EPoolv * poolv,gint index,gchar * str,gint freeit)71 e_poolv_set (EPoolv *poolv,
72              gint index,
73              gchar *str,
74              gint freeit)
75 {
76 	const gchar *old_str;
77 
78 	g_return_val_if_fail (poolv != NULL, NULL);
79 	g_return_val_if_fail (index >= 0 && index < poolv->length, NULL);
80 
81 	if (!str) {
82 		camel_pstring_free (poolv->s[index]);
83 		poolv->s[index] = NULL;
84 		return poolv;
85 	}
86 
87 	old_str = poolv->s[index];
88 	poolv->s[index] = (gchar *) camel_pstring_add (str, freeit);
89 
90 	camel_pstring_free (old_str);
91 
92 	return poolv;
93 }
94 
95 /**
96  * e_poolv_get:
97  * @poolv: pooled string vector
98  * @index: index in vector of string
99  *
100  * Retrieve a string by index.  This could possibly just be a macro.
101  *
102  * Since the pool is never freed, this string does not need to be
103  * duplicated, but should not be modified.
104  *
105  * Returns: string at that index.
106  **/
107 const gchar *
e_poolv_get(EPoolv * poolv,gint index)108 e_poolv_get (EPoolv *poolv,
109              gint index)
110 {
111 	g_return_val_if_fail (poolv != NULL, NULL);
112 	g_return_val_if_fail (index >= 0 && index < poolv->length, NULL);
113 
114 	return poolv->s[index] ? poolv->s[index] : "";
115 }
116 
117 /**
118  * e_poolv_destroy:
119  * @poolv: pooled string vector to free
120  *
121  * Free a pooled string vector.  This doesn't free the strings from
122  * the vector, however.
123  **/
124 void
e_poolv_destroy(EPoolv * poolv)125 e_poolv_destroy (EPoolv *poolv)
126 {
127 	gint ii;
128 
129 	g_return_if_fail (poolv != NULL);
130 
131 	for (ii = 0; ii < poolv->length; ii++) {
132 		camel_pstring_free (poolv->s[ii]);
133 	}
134 
135 	g_free (poolv);
136 }
137