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
25 #include "wine/debug.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(winstring
);
29 #define HSTRING_REFERENCE_FLAG 1
40 struct hstring_private
42 struct hstring_header header
;
47 static const WCHAR empty
[1];
49 C_ASSERT(sizeof(struct hstring_header
) <= sizeof(HSTRING_HEADER
));
51 static inline struct hstring_private
*impl_from_HSTRING(HSTRING string
)
53 return (struct hstring_private
*)string
;
56 static inline struct hstring_private
*impl_from_HSTRING_HEADER(HSTRING_HEADER
*header
)
58 return CONTAINING_RECORD(header
, struct hstring_private
, header
);
61 static inline struct hstring_private
*impl_from_HSTRING_BUFFER(HSTRING_BUFFER buffer
)
63 return CONTAINING_RECORD(buffer
, struct hstring_private
, buffer
);
66 static BOOL
alloc_string(UINT32 len
, HSTRING
*out
)
68 struct hstring_private
*priv
;
69 priv
= malloc(offsetof(struct hstring_private
, buffer
[len
+1]));
73 priv
->header
.flags
= 0;
74 priv
->header
.length
= len
;
75 priv
->header
.str
= priv
->buffer
;
78 priv
->buffer
[len
] = '\0';
84 /***********************************************************************
85 * WindowsCreateString (combase.@)
87 HRESULT WINAPI
WindowsCreateString(LPCWSTR ptr
, UINT32 len
,
90 struct hstring_private
*priv
;
92 TRACE("(%s, %u, %p)\n", debugstr_wn(ptr
, len
), len
, out
);
103 if (!alloc_string(len
, out
))
104 return E_OUTOFMEMORY
;
105 priv
= impl_from_HSTRING(*out
);
106 memcpy(priv
->buffer
, ptr
, len
* sizeof(*priv
->buffer
));
110 /***********************************************************************
111 * WindowsCreateStringReference (combase.@)
113 HRESULT WINAPI
WindowsCreateStringReference(LPCWSTR ptr
, UINT32 len
,
114 HSTRING_HEADER
*header
, HSTRING
*out
)
116 struct hstring_private
*priv
= impl_from_HSTRING_HEADER(header
);
118 TRACE("(%s, %u, %p, %p)\n", debugstr_wn(ptr
, len
), len
, header
, out
);
120 if (out
== NULL
|| header
== NULL
)
122 if (ptr
!= NULL
&& ptr
[len
] != '\0')
132 priv
->header
.str
= ptr
;
133 priv
->header
.length
= len
;
134 priv
->header
.flags
= HSTRING_REFERENCE_FLAG
;
136 *out
= (HSTRING
)priv
;
140 /***********************************************************************
141 * WindowsDeleteString (combase.@)
143 HRESULT WINAPI
WindowsDeleteString(HSTRING str
)
145 struct hstring_private
*priv
= impl_from_HSTRING(str
);
147 TRACE("(%p)\n", str
);
151 if (priv
->header
.flags
& HSTRING_REFERENCE_FLAG
)
153 if (InterlockedDecrement(&priv
->refcount
) == 0)
158 /***********************************************************************
159 * WindowsDuplicateString (combase.@)
161 HRESULT WINAPI
WindowsDuplicateString(HSTRING str
, HSTRING
*out
)
163 struct hstring_private
*priv
= impl_from_HSTRING(str
);
165 TRACE("(%p, %p)\n", str
, out
);
174 if (priv
->header
.flags
& HSTRING_REFERENCE_FLAG
)
175 return WindowsCreateString(priv
->header
.str
, priv
->header
.length
, out
);
176 InterlockedIncrement(&priv
->refcount
);
181 /***********************************************************************
182 * WindowsPreallocateStringBuffer (combase.@)
184 HRESULT WINAPI
WindowsPreallocateStringBuffer(UINT32 len
, WCHAR
**outptr
,
187 struct hstring_private
*priv
;
190 TRACE("(%u, %p, %p)\n", len
, outptr
, out
);
192 if (outptr
== NULL
|| out
== NULL
)
196 *outptr
= (LPWSTR
)empty
;
201 if (!alloc_string(len
, &str
))
202 return E_OUTOFMEMORY
;
203 priv
= impl_from_HSTRING(str
);
204 *outptr
= priv
->buffer
;
205 *out
= (HSTRING_BUFFER
)&priv
->buffer
;
209 /***********************************************************************
210 * WindowsDeleteStringBuffer (combase.@)
212 HRESULT WINAPI
WindowsDeleteStringBuffer(HSTRING_BUFFER buf
)
214 struct hstring_private
*priv
= NULL
;
216 TRACE("(%p)\n", buf
);
219 priv
= impl_from_HSTRING_BUFFER(buf
);
221 return WindowsDeleteString((HSTRING
)priv
);
224 /***********************************************************************
225 * WindowsPromoteStringBuffer (combase.@)
227 HRESULT WINAPI
WindowsPromoteStringBuffer(HSTRING_BUFFER buf
, HSTRING
*out
)
229 struct hstring_private
*priv
= impl_from_HSTRING_BUFFER(buf
);
231 TRACE("(%p, %p)\n", buf
, out
);
240 if (priv
->buffer
[priv
->header
.length
] != 0 || priv
->header
.flags
& HSTRING_REFERENCE_FLAG
|| priv
->refcount
!= 1)
242 *out
= (HSTRING
)priv
;
246 /***********************************************************************
247 * WindowsGetStringLen (combase.@)
249 UINT32 WINAPI
WindowsGetStringLen(HSTRING str
)
251 struct hstring_private
*priv
= impl_from_HSTRING(str
);
253 TRACE("(%p)\n", str
);
257 return priv
->header
.length
;
260 /***********************************************************************
261 * WindowsGetStringRawBuffer (combase.@)
263 LPCWSTR WINAPI
WindowsGetStringRawBuffer(HSTRING str
, UINT32
*len
)
265 struct hstring_private
*priv
= impl_from_HSTRING(str
);
267 TRACE("(%p, %p)\n", str
, len
);
276 *len
= priv
->header
.length
;
277 return priv
->header
.str
;
280 /***********************************************************************
281 * WindowsStringHasEmbeddedNull (combase.@)
283 HRESULT WINAPI
WindowsStringHasEmbeddedNull(HSTRING str
, BOOL
*out
)
286 struct hstring_private
*priv
= impl_from_HSTRING(str
);
288 TRACE("(%p, %p)\n", str
, out
);
297 for (i
= 0; i
< priv
->header
.length
; i
++)
299 if (priv
->header
.str
[i
] == '\0')
309 /***********************************************************************
310 * WindowsSubstring (combase.@)
312 HRESULT WINAPI
WindowsSubstring(HSTRING str
, UINT32 start
, HSTRING
*out
)
314 struct hstring_private
*priv
= impl_from_HSTRING(str
);
315 UINT32 len
= WindowsGetStringLen(str
);
317 TRACE("(%p, %u, %p)\n", str
, start
, out
);
328 return WindowsCreateString(&priv
->header
.str
[start
], len
- start
, out
);
331 /***********************************************************************
332 * WindowsSubstringWithSpecifiedLength (combase.@)
334 HRESULT WINAPI
WindowsSubstringWithSpecifiedLength(HSTRING str
, UINT32 start
, UINT32 len
, HSTRING
*out
)
336 struct hstring_private
*priv
= impl_from_HSTRING(str
);
338 TRACE("(%p, %u, %u, %p)\n", str
, start
, len
, out
);
342 if (start
+ len
< start
||
343 start
+ len
> WindowsGetStringLen(str
))
350 return WindowsCreateString(&priv
->header
.str
[start
], len
, out
);
353 /***********************************************************************
354 * WindowsConcatString (combase.@)
356 HRESULT WINAPI
WindowsConcatString(HSTRING str1
, HSTRING str2
, HSTRING
*out
)
358 struct hstring_private
*priv1
= impl_from_HSTRING(str1
);
359 struct hstring_private
*priv2
= impl_from_HSTRING(str2
);
360 struct hstring_private
*priv
;
362 TRACE("(%p, %p, %p)\n", str1
, str2
, out
);
367 return WindowsDuplicateString(str2
, out
);
369 return WindowsDuplicateString(str1
, out
);
370 if (!priv1
->header
.length
&& !priv2
->header
.length
)
375 if (!alloc_string(priv1
->header
.length
+ priv2
->header
.length
, out
))
376 return E_OUTOFMEMORY
;
377 priv
= impl_from_HSTRING(*out
);
378 memcpy(priv
->buffer
, priv1
->header
.str
, priv1
->header
.length
* sizeof(*priv1
->buffer
));
379 memcpy(priv
->buffer
+ priv1
->header
.length
, priv2
->header
.str
, priv2
->header
.length
* sizeof(*priv2
->buffer
));
383 /***********************************************************************
384 * WindowsIsStringEmpty (combase.@)
386 BOOL WINAPI
WindowsIsStringEmpty(HSTRING str
)
388 struct hstring_private
*priv
= impl_from_HSTRING(str
);
390 TRACE("(%p)\n", str
);
394 return priv
->header
.length
== 0;
397 /***********************************************************************
398 * WindowsCompareStringOrdinal (combase.@)
400 HRESULT WINAPI
WindowsCompareStringOrdinal(HSTRING str1
, HSTRING str2
, INT32
*res
)
402 struct hstring_private
*priv1
= impl_from_HSTRING(str1
);
403 struct hstring_private
*priv2
= impl_from_HSTRING(str2
);
404 const WCHAR
*buf1
= empty
, *buf2
= empty
;
405 UINT32 len1
= 0, len2
= 0;
407 TRACE("(%p, %p, %p)\n", str1
, str2
, res
);
418 buf1
= priv1
->header
.str
;
419 len1
= priv1
->header
.length
;
423 buf2
= priv2
->header
.str
;
424 len2
= priv2
->header
.length
;
426 *res
= CompareStringOrdinal(buf1
, len1
, buf2
, len2
, FALSE
) - CSTR_EQUAL
;
430 /***********************************************************************
431 * WindowsTrimStringStart (combase.@)
433 HRESULT WINAPI
WindowsTrimStringStart(HSTRING str1
, HSTRING str2
, HSTRING
*out
)
435 struct hstring_private
*priv1
= impl_from_HSTRING(str1
);
436 struct hstring_private
*priv2
= impl_from_HSTRING(str2
);
439 TRACE("(%p, %p, %p)\n", str1
, str2
, out
);
441 if (!out
|| !str2
|| !priv2
->header
.length
)
448 for (start
= 0; start
< priv1
->header
.length
; start
++)
450 if (!wmemchr(priv2
->header
.str
, priv1
->header
.str
[start
], priv2
->header
.length
))
453 return start
? WindowsCreateString(&priv1
->header
.str
[start
], priv1
->header
.length
- start
, out
) :
454 WindowsDuplicateString(str1
, out
);
457 /***********************************************************************
458 * WindowsTrimStringEnd (combase.@)
460 HRESULT WINAPI
WindowsTrimStringEnd(HSTRING str1
, HSTRING str2
, HSTRING
*out
)
462 struct hstring_private
*priv1
= impl_from_HSTRING(str1
);
463 struct hstring_private
*priv2
= impl_from_HSTRING(str2
);
466 TRACE("(%p, %p, %p)\n", str1
, str2
, out
);
468 if (!out
|| !str2
|| !priv2
->header
.length
)
475 for (len
= priv1
->header
.length
; len
> 0; len
--)
477 if (!wmemchr(priv2
->header
.str
, priv1
->header
.str
[len
- 1], priv2
->header
.length
))
480 return (len
< priv1
->header
.length
) ? WindowsCreateString(priv1
->header
.str
, len
, out
) :
481 WindowsDuplicateString(str1
, out
);