1 /* GLIB - Library of useful routines for C programming
2  * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19 
20 /*
21  * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
22  * file for a list of people on the GLib Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GLib at ftp://ftp.gtk.org/pub/gtk/.
25  */
26 
27 #define _GNU_SOURCE
28 #include <stdio.h>
29 #include <string.h>
30 
31 #include <glib.h>
32 #include "gstring.h"
33 
34 #define MY_MAXSIZE ((gsize)-1)
35 
36 static inline gsize
nearest_power(gsize base,gsize num)37 nearest_power (gsize base, gsize num)
38 {
39   if (num > MY_MAXSIZE / 2)
40     {
41       return MY_MAXSIZE;
42     }
43   else
44     {
45       gsize n = base;
46 
47       while (n < num)
48 	n <<= 1;
49 
50       return n;
51     }
52 }
53 
54 static void
g_string_maybe_expand(GString * string,gsize len)55 g_string_maybe_expand (GString* string,
56 		       gsize    len)
57 {
58   if (string->len + len >= string->allocated_len)
59     {
60       string->allocated_len = nearest_power (1, string->len + len + 1);
61       string->str = g_realloc (string->str, string->allocated_len);
62     }
63 }
64 
65 /**
66  * g_string_overwrite:
67  * @string: a #GString
68  * @pos: the position at which to start overwriting
69  * @val: the string that will overwrite the @string starting at @pos
70  *
71  * Overwrites part of a string, lengthening it if necessary.
72  *
73  * Return value: @string
74  *
75  * Since: 2.14
76  **/
77 GString *
g_string_overwrite(GString * string,gsize pos,const gchar * val)78 g_string_overwrite (GString     *string,
79 		    gsize        pos,
80 		    const gchar *val)
81 {
82   g_return_val_if_fail (val != NULL, string);
83   return g_string_overwrite_len (string, pos, val, strlen (val));
84 }
85 
86 /**
87  * g_string_overwrite_len:
88  * @string: a #GString
89  * @pos: the position at which to start overwriting
90  * @val: the string that will overwrite the @string starting at @pos
91  * @len: the number of bytes to write from @val
92  *
93  * Overwrites part of a string, lengthening it if necessary.
94  * This function will work with embedded nuls.
95  *
96  * Return value: @string
97  *
98  * Since: 2.14
99  **/
100 GString *
g_string_overwrite_len(GString * string,gsize pos,const gchar * val,gssize len)101 g_string_overwrite_len (GString     *string,
102 			gsize        pos,
103 			const gchar *val,
104 			gssize       len)
105 {
106   gsize end;
107 
108   g_return_val_if_fail (string != NULL, NULL);
109 
110   if (!len)
111     return string;
112 
113   g_return_val_if_fail (val != NULL, string);
114   g_return_val_if_fail (pos <= string->len, string);
115 
116   if (len < 0)
117     len = strlen (val);
118 
119   end = pos + len;
120 
121   if (end > string->len)
122     g_string_maybe_expand (string, end - string->len);
123 
124   memcpy (string->str + pos, val, len);
125 
126   if (end > string->len)
127     {
128       string->str[end] = '\0';
129       string->len = end;
130     }
131 
132   return string;
133 }
134 
135 /**
136  * g_string_append_vprintf:
137  * @string: a #GString
138  * @format: the string format. See the printf() documentation
139  * @args: the list of arguments to insert in the output
140  *
141  * Appends a formatted string onto the end of a #GString.
142  * This function is is similar to g_string_append_printf()
143  * except that the arguments to the format string are passed
144  * as a va_list.
145  *
146  * Since: 2.14
147  */
148 void
g_string_append_vprintf(GString * string,const gchar * format,va_list args)149 g_string_append_vprintf (GString     *string,
150 			 const gchar *format,
151 			 va_list      args)
152 {
153   gchar *buf;
154   gint len;
155 
156   g_return_if_fail (string != NULL);
157   g_return_if_fail (format != NULL);
158 
159   len = vasprintf (&buf, format, args);
160 
161   if (len >= 0)
162     {
163       g_string_maybe_expand (string, len);
164       memcpy (string->str + string->len, buf, len + 1);
165       string->len += len;
166       g_free (buf);
167     }
168 }
169