maintainers: Update winemaker section.
[wine.git] / dlls / combase / string.c
blobdd7c8e9fa4980e61d873994c965f27d45db1aa9f
1 /*
2 * Copyright 2014 Martin Storsjo
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.1 of the License, or (at your option) any later version.
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.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include <string.h>
21 #include "windows.h"
22 #include "winerror.h"
23 #include "hstring.h"
24 #include "wine/debug.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(winstring);
28 struct hstring_private
30 LPWSTR buffer;
31 UINT32 length;
32 BOOL reference;
33 LONG refcount;
36 static const WCHAR empty[1];
38 C_ASSERT(sizeof(struct hstring_private) <= sizeof(HSTRING_HEADER));
40 static inline struct hstring_private *impl_from_HSTRING(HSTRING string)
42 return (struct hstring_private *)string;
45 static inline struct hstring_private *impl_from_HSTRING_HEADER(HSTRING_HEADER *header)
47 return (struct hstring_private *)header;
50 static inline struct hstring_private *impl_from_HSTRING_BUFFER(HSTRING_BUFFER buffer)
52 return (struct hstring_private *)buffer;
55 static BOOL alloc_string(UINT32 len, HSTRING *out)
57 struct hstring_private *priv;
58 priv = HeapAlloc(GetProcessHeap(), 0, sizeof(*priv) + (len + 1) * sizeof(*priv->buffer));
59 if (!priv)
60 return FALSE;
61 priv->buffer = (LPWSTR)(priv + 1);
62 priv->length = len;
63 priv->reference = FALSE;
64 priv->refcount = 1;
65 priv->buffer[len] = '\0';
66 *out = (HSTRING)priv;
67 return TRUE;
70 /***********************************************************************
71 * WindowsCreateString (combase.@)
73 HRESULT WINAPI WindowsCreateString(LPCWSTR ptr, UINT32 len,
74 HSTRING *out)
76 struct hstring_private *priv;
78 TRACE("(%s, %u, %p)\n", debugstr_wn(ptr, len), len, out);
80 if (out == NULL)
81 return E_INVALIDARG;
82 if (len == 0)
84 *out = NULL;
85 return S_OK;
87 if (ptr == NULL)
88 return E_POINTER;
89 if (!alloc_string(len, out))
90 return E_OUTOFMEMORY;
91 priv = impl_from_HSTRING(*out);
92 memcpy(priv->buffer, ptr, len * sizeof(*priv->buffer));
93 return S_OK;
96 /***********************************************************************
97 * WindowsCreateStringReference (combase.@)
99 HRESULT WINAPI WindowsCreateStringReference(LPCWSTR ptr, UINT32 len,
100 HSTRING_HEADER *header, HSTRING *out)
102 struct hstring_private *priv = impl_from_HSTRING_HEADER(header);
104 TRACE("(%s, %u, %p, %p)\n", debugstr_wn(ptr, len), len, header, out);
106 if (out == NULL || header == NULL)
107 return E_INVALIDARG;
108 if (ptr != NULL && ptr[len] != '\0')
109 return E_INVALIDARG;
110 if (len == 0)
112 *out = NULL;
113 return S_OK;
115 if (ptr == NULL)
116 return E_POINTER;
117 priv->buffer = (LPWSTR)ptr;
118 priv->length = len;
119 priv->reference = TRUE;
120 *out = (HSTRING)header;
121 return S_OK;
124 /***********************************************************************
125 * WindowsDeleteString (combase.@)
127 HRESULT WINAPI WindowsDeleteString(HSTRING str)
129 struct hstring_private *priv = impl_from_HSTRING(str);
131 TRACE("(%p)\n", str);
133 if (str == NULL)
134 return S_OK;
135 if (priv->reference)
136 return S_OK;
137 if (InterlockedDecrement(&priv->refcount) == 0)
138 HeapFree(GetProcessHeap(), 0, priv);
139 return S_OK;
142 /***********************************************************************
143 * WindowsDuplicateString (combase.@)
145 HRESULT WINAPI WindowsDuplicateString(HSTRING str, HSTRING *out)
147 struct hstring_private *priv = impl_from_HSTRING(str);
149 TRACE("(%p, %p)\n", str, out);
151 if (out == NULL)
152 return E_INVALIDARG;
153 if (str == NULL)
155 *out = NULL;
156 return S_OK;
158 if (priv->reference)
159 return WindowsCreateString(priv->buffer, priv->length, out);
160 InterlockedIncrement(&priv->refcount);
161 *out = str;
162 return S_OK;
165 /***********************************************************************
166 * WindowsPreallocateStringBuffer (combase.@)
168 HRESULT WINAPI WindowsPreallocateStringBuffer(UINT32 len, WCHAR **outptr,
169 HSTRING_BUFFER *out)
171 struct hstring_private *priv;
172 HSTRING str;
174 TRACE("(%u, %p, %p)\n", len, outptr, out);
176 if (outptr == NULL || out == NULL)
177 return E_POINTER;
178 if (len == 0)
180 *outptr = (LPWSTR)empty;
181 *out = NULL;
182 return S_OK;
185 if (!alloc_string(len, &str))
186 return E_OUTOFMEMORY;
187 priv = impl_from_HSTRING(str);
188 *outptr = priv->buffer;
189 *out = (HSTRING_BUFFER)str;
190 return S_OK;
193 /***********************************************************************
194 * WindowsDeleteStringBuffer (combase.@)
196 HRESULT WINAPI WindowsDeleteStringBuffer(HSTRING_BUFFER buf)
198 TRACE("(%p)\n", buf);
200 return WindowsDeleteString((HSTRING)buf);
203 /***********************************************************************
204 * WindowsPromoteStringBuffer (combase.@)
206 HRESULT WINAPI WindowsPromoteStringBuffer(HSTRING_BUFFER buf, HSTRING *out)
208 struct hstring_private *priv = impl_from_HSTRING_BUFFER(buf);
210 TRACE("(%p, %p)\n", buf, out);
212 if (out == NULL)
213 return E_POINTER;
214 if (buf == NULL)
216 *out = NULL;
217 return S_OK;
219 if (priv->buffer[priv->length] != 0 || priv->reference || priv->refcount != 1)
220 return E_INVALIDARG;
221 *out = (HSTRING)buf;
222 return S_OK;
225 /***********************************************************************
226 * WindowsGetStringLen (combase.@)
228 UINT32 WINAPI WindowsGetStringLen(HSTRING str)
230 struct hstring_private *priv = impl_from_HSTRING(str);
232 TRACE("(%p)\n", str);
234 if (str == NULL)
235 return 0;
236 return priv->length;
239 /***********************************************************************
240 * WindowsGetStringRawBuffer (combase.@)
242 LPCWSTR WINAPI WindowsGetStringRawBuffer(HSTRING str, UINT32 *len)
244 struct hstring_private *priv = impl_from_HSTRING(str);
246 TRACE("(%p, %p)\n", str, len);
248 if (str == NULL)
250 if (len)
251 *len = 0;
252 return empty;
254 if (len)
255 *len = priv->length;
256 return priv->buffer;
259 /***********************************************************************
260 * WindowsStringHasEmbeddedNull (combase.@)
262 HRESULT WINAPI WindowsStringHasEmbeddedNull(HSTRING str, BOOL *out)
264 UINT32 i;
265 struct hstring_private *priv = impl_from_HSTRING(str);
267 TRACE("(%p, %p)\n", str, out);
269 if (out == NULL)
270 return E_INVALIDARG;
271 if (str == NULL)
273 *out = FALSE;
274 return S_OK;
276 for (i = 0; i < priv->length; i++)
278 if (priv->buffer[i] == '\0')
280 *out = TRUE;
281 return S_OK;
284 *out = FALSE;
285 return S_OK;
288 /***********************************************************************
289 * WindowsSubstring (combase.@)
291 HRESULT WINAPI WindowsSubstring(HSTRING str, UINT32 start, HSTRING *out)
293 struct hstring_private *priv = impl_from_HSTRING(str);
294 UINT32 len = WindowsGetStringLen(str);
296 TRACE("(%p, %u, %p)\n", str, start, out);
298 if (out == NULL)
299 return E_INVALIDARG;
300 if (start > len)
301 return E_BOUNDS;
302 if (start == len)
304 *out = NULL;
305 return S_OK;
307 return WindowsCreateString(&priv->buffer[start], len - start, out);
310 /***********************************************************************
311 * WindowsSubstringWithSpecifiedLength (combase.@)
313 HRESULT WINAPI WindowsSubstringWithSpecifiedLength(HSTRING str, UINT32 start, UINT32 len, HSTRING *out)
315 struct hstring_private *priv = impl_from_HSTRING(str);
317 TRACE("(%p, %u, %u, %p)\n", str, start, len, out);
319 if (out == NULL)
320 return E_INVALIDARG;
321 if (start + len < start ||
322 start + len > WindowsGetStringLen(str))
323 return E_BOUNDS;
324 if (len == 0)
326 *out = NULL;
327 return S_OK;
329 return WindowsCreateString(&priv->buffer[start], len, out);
332 /***********************************************************************
333 * WindowsConcatString (combase.@)
335 HRESULT WINAPI WindowsConcatString(HSTRING str1, HSTRING str2, HSTRING *out)
337 struct hstring_private *priv1 = impl_from_HSTRING(str1);
338 struct hstring_private *priv2 = impl_from_HSTRING(str2);
339 struct hstring_private *priv;
341 TRACE("(%p, %p, %p)\n", str1, str2, out);
343 if (out == NULL)
344 return E_INVALIDARG;
345 if (str1 == NULL)
346 return WindowsDuplicateString(str2, out);
347 if (str2 == NULL)
348 return WindowsDuplicateString(str1, out);
349 if (!priv1->length && !priv2->length)
351 *out = NULL;
352 return S_OK;
354 if (!alloc_string(priv1->length + priv2->length, out))
355 return E_OUTOFMEMORY;
356 priv = impl_from_HSTRING(*out);
357 memcpy(priv->buffer, priv1->buffer, priv1->length * sizeof(*priv1->buffer));
358 memcpy(priv->buffer + priv1->length, priv2->buffer, priv2->length * sizeof(*priv2->buffer));
359 return S_OK;
362 /***********************************************************************
363 * WindowsIsStringEmpty (combase.@)
365 BOOL WINAPI WindowsIsStringEmpty(HSTRING str)
367 struct hstring_private *priv = impl_from_HSTRING(str);
369 TRACE("(%p)\n", str);
371 if (str == NULL)
372 return TRUE;
373 return priv->length == 0;