1 /*
2  * Copyright © 2020 Canonical Ltd.
3  * Copyright © 2021 Alexandros Theodotou
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 3 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #include "utils/strv_builder.h"
20 
21 /**
22  * SECTION:gstrvbuilder
23  * @title: GStrvBuilder
24  * @short_description: Helper to create NULL-terminated string arrays.
25  *
26  * #GStrvBuilder is a method of easily building dynamically sized
27  * NULL-terminated string arrays.
28  *
29  * The following example shows how to build a two element array:
30  *
31  * |[<!-- language="C" -->
32  *   g_autoptr(GStrvBuilder) builder = strv_builder_new ();
33  *   strv_builder_add (builder, "hello");
34  *   strv_builder_add (builder, "world");
35  *   g_auto(GStrv) array = strv_builder_end (builder);
36  * ]|
37  *
38  * Since: 2.68
39  */
40 
41 struct _StrvBuilder
42 {
43   GPtrArray array;
44 };
45 
46 /**
47  * strv_builder_new:
48  *
49  * Creates a new #GStrvBuilder with a reference count of 1.
50  * Use strv_builder_unref() on the returned value when no longer needed.
51  *
52  * Returns: (transfer full): the new #GStrvBuilder
53  *
54  * Since: 2.68
55  */
56 StrvBuilder *
strv_builder_new(void)57 strv_builder_new (void)
58 {
59   return (StrvBuilder *) g_ptr_array_new_with_free_func (g_free);
60 }
61 
62 /**
63  * strv_builder_unref:
64  * @builder: (transfer full): a #GStrvBuilder allocated by strv_builder_new()
65  *
66  * Decreases the reference count on @builder.
67  *
68  * In the event that there are no more references, releases all memory
69  * associated with the #GStrvBuilder.
70  *
71  * Since: 2.68
72  **/
73 void
strv_builder_unref(StrvBuilder * builder)74 strv_builder_unref (StrvBuilder *builder)
75 {
76   g_ptr_array_unref (&builder->array);
77 }
78 
79 /**
80  * strv_builder_ref:
81  * @builder: (transfer none): a #GStrvBuilder
82  *
83  * Atomically increments the reference count of @builder by one.
84  * This function is thread-safe and may be called from any thread.
85  *
86  * Returns: (transfer full): The passed in #GStrvBuilder
87  *
88  * Since: 2.68
89  */
90 StrvBuilder *
strv_builder_ref(StrvBuilder * builder)91 strv_builder_ref (StrvBuilder *builder)
92 {
93   return (StrvBuilder *) g_ptr_array_ref (&builder->array);
94 }
95 
96 /**
97  * strv_builder_add:
98  * @builder: a #GStrvBuilder
99  * @value: a string.
100  *
101  * Add a string to the end of the array.
102  *
103  * Since 2.68
104  */
105 void
strv_builder_add(StrvBuilder * builder,const char * value)106 strv_builder_add (StrvBuilder *builder,
107                     const char   *value)
108 {
109   g_ptr_array_add (&builder->array, g_strdup (value));
110 }
111 
112 /**
113  * strv_builder_addv:
114  * @builder: a #GStrvBuilder
115  * @value: (array zero-terminated=1): the vector of strings to add
116  *
117  * Appends all the strings in the given vector to the builder.
118  *
119  * Since 2.70
120  */
121 void
strv_builder_addv(StrvBuilder * builder,const char ** value)122 strv_builder_addv (StrvBuilder *builder,
123                      const char **value)
124 {
125   gsize i = 0;
126   g_return_if_fail (builder != NULL);
127   g_return_if_fail (value != NULL);
128   for (i = 0; value[i] != NULL; i++)
129     strv_builder_add (builder, value[i]);
130 }
131 
132 /**
133  * strv_builder_add_many:
134  * @builder: a #GStrvBuilder
135  * @...: one or more strings followed by %NULL
136  *
137  * Appends all the given strings to the builder.
138  *
139  * Since 2.70
140  */
141 void
strv_builder_add_many(StrvBuilder * builder,...)142 strv_builder_add_many (StrvBuilder *builder,
143                          ...)
144 {
145   va_list var_args;
146   const gchar *str;
147   g_return_if_fail (builder != NULL);
148   va_start (var_args, builder);
149   while ((str = va_arg (var_args, gchar *)) != NULL)
150     strv_builder_add (builder, str);
151   va_end (var_args);
152 }
153 
154 /**
155  * strv_builder_end:
156  * @builder: a #GStrvBuilder
157  *
158  * Ends the builder process and returns the constructed NULL-terminated string
159  * array. The returned value should be freed with g_strfreev() when no longer
160  * needed.
161  *
162  * Returns: (transfer full): the constructed string array.
163  *
164  * Since 2.68
165  */
166 char **
strv_builder_end(StrvBuilder * builder)167 strv_builder_end (StrvBuilder *builder)
168 {
169   /* Add NULL terminator */
170   g_ptr_array_add (&builder->array, NULL);
171   return
172     (char **)
173     g_ptr_array_steal (&builder->array, NULL);
174 }
175