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 struct hstring_private
37 static const WCHAR empty
[1];
39 C_ASSERT(sizeof(struct hstring_private
) <= sizeof(HSTRING_HEADER
));
41 static inline struct hstring_private
*impl_from_HSTRING(HSTRING string
)
43 return (struct hstring_private
*)string
;
46 static inline struct hstring_private
*impl_from_HSTRING_HEADER(HSTRING_HEADER
*header
)
48 return (struct hstring_private
*)header
;
51 static inline struct hstring_private
*impl_from_HSTRING_BUFFER(HSTRING_BUFFER buffer
)
53 return (struct hstring_private
*)buffer
;
56 static BOOL
alloc_string(UINT32 len
, HSTRING
*out
)
58 struct hstring_private
*priv
;
59 priv
= HeapAlloc(GetProcessHeap(), 0, sizeof(*priv
) + (len
+ 1) * sizeof(*priv
->buffer
));
62 priv
->buffer
= (LPWSTR
)(priv
+ 1);
64 priv
->reference
= FALSE
;
66 priv
->buffer
[len
] = '\0';
71 /***********************************************************************
72 * WindowsCreateString (combase.@)
74 HRESULT WINAPI
WindowsCreateString(LPCWSTR ptr
, UINT32 len
,
77 struct hstring_private
*priv
;
79 TRACE("(%s, %u, %p)\n", debugstr_wn(ptr
, len
), len
, out
);
90 if (!alloc_string(len
, out
))
92 priv
= impl_from_HSTRING(*out
);
93 memcpy(priv
->buffer
, ptr
, len
* sizeof(*priv
->buffer
));
97 /***********************************************************************
98 * WindowsCreateStringReference (combase.@)
100 HRESULT WINAPI
WindowsCreateStringReference(LPCWSTR ptr
, UINT32 len
,
101 HSTRING_HEADER
*header
, HSTRING
*out
)
103 struct hstring_private
*priv
= impl_from_HSTRING_HEADER(header
);
105 TRACE("(%s, %u, %p, %p)\n", debugstr_wn(ptr
, len
), len
, header
, out
);
107 if (out
== NULL
|| header
== NULL
)
109 if (ptr
!= NULL
&& ptr
[len
] != '\0')
118 priv
->buffer
= (LPWSTR
)ptr
;
120 priv
->reference
= TRUE
;
121 *out
= (HSTRING
)header
;
125 /***********************************************************************
126 * WindowsDeleteString (combase.@)
128 HRESULT WINAPI
WindowsDeleteString(HSTRING str
)
130 struct hstring_private
*priv
= impl_from_HSTRING(str
);
132 TRACE("(%p)\n", str
);
138 if (InterlockedDecrement(&priv
->refcount
) == 0)
139 HeapFree(GetProcessHeap(), 0, priv
);
143 /***********************************************************************
144 * WindowsDuplicateString (combase.@)
146 HRESULT WINAPI
WindowsDuplicateString(HSTRING str
, HSTRING
*out
)
148 struct hstring_private
*priv
= impl_from_HSTRING(str
);
150 TRACE("(%p, %p)\n", str
, out
);
160 return WindowsCreateString(priv
->buffer
, priv
->length
, out
);
161 InterlockedIncrement(&priv
->refcount
);
166 /***********************************************************************
167 * WindowsPreallocateStringBuffer (combase.@)
169 HRESULT WINAPI
WindowsPreallocateStringBuffer(UINT32 len
, WCHAR
**outptr
,
172 struct hstring_private
*priv
;
175 TRACE("(%u, %p, %p)\n", len
, outptr
, out
);
177 if (outptr
== NULL
|| out
== NULL
)
181 *outptr
= (LPWSTR
)empty
;
186 if (!alloc_string(len
, &str
))
187 return E_OUTOFMEMORY
;
188 priv
= impl_from_HSTRING(str
);
189 *outptr
= priv
->buffer
;
190 *out
= (HSTRING_BUFFER
)str
;
194 /***********************************************************************
195 * WindowsDeleteStringBuffer (combase.@)
197 HRESULT WINAPI
WindowsDeleteStringBuffer(HSTRING_BUFFER buf
)
199 TRACE("(%p)\n", buf
);
201 return WindowsDeleteString((HSTRING
)buf
);
204 /***********************************************************************
205 * WindowsPromoteStringBuffer (combase.@)
207 HRESULT WINAPI
WindowsPromoteStringBuffer(HSTRING_BUFFER buf
, HSTRING
*out
)
209 struct hstring_private
*priv
= impl_from_HSTRING_BUFFER(buf
);
211 TRACE("(%p, %p)\n", buf
, out
);
220 if (priv
->buffer
[priv
->length
] != 0 || priv
->reference
|| priv
->refcount
!= 1)
226 /***********************************************************************
227 * WindowsGetStringLen (combase.@)
229 UINT32 WINAPI
WindowsGetStringLen(HSTRING str
)
231 struct hstring_private
*priv
= impl_from_HSTRING(str
);
233 TRACE("(%p)\n", str
);
240 /***********************************************************************
241 * WindowsGetStringRawBuffer (combase.@)
243 LPCWSTR WINAPI
WindowsGetStringRawBuffer(HSTRING str
, UINT32
*len
)
245 struct hstring_private
*priv
= impl_from_HSTRING(str
);
247 TRACE("(%p, %p)\n", str
, len
);
260 /***********************************************************************
261 * WindowsStringHasEmbeddedNull (combase.@)
263 HRESULT WINAPI
WindowsStringHasEmbeddedNull(HSTRING str
, BOOL
*out
)
266 struct hstring_private
*priv
= impl_from_HSTRING(str
);
268 TRACE("(%p, %p)\n", str
, out
);
277 for (i
= 0; i
< priv
->length
; i
++)
279 if (priv
->buffer
[i
] == '\0')
289 /***********************************************************************
290 * WindowsSubstring (combase.@)
292 HRESULT WINAPI
WindowsSubstring(HSTRING str
, UINT32 start
, HSTRING
*out
)
294 struct hstring_private
*priv
= impl_from_HSTRING(str
);
295 UINT32 len
= WindowsGetStringLen(str
);
297 TRACE("(%p, %u, %p)\n", str
, start
, out
);
308 return WindowsCreateString(&priv
->buffer
[start
], len
- start
, out
);
311 /***********************************************************************
312 * WindowsSubstringWithSpecifiedLength (combase.@)
314 HRESULT WINAPI
WindowsSubstringWithSpecifiedLength(HSTRING str
, UINT32 start
, UINT32 len
, HSTRING
*out
)
316 struct hstring_private
*priv
= impl_from_HSTRING(str
);
318 TRACE("(%p, %u, %u, %p)\n", str
, start
, len
, out
);
322 if (start
+ len
< start
||
323 start
+ len
> WindowsGetStringLen(str
))
330 return WindowsCreateString(&priv
->buffer
[start
], len
, out
);
333 /***********************************************************************
334 * WindowsConcatString (combase.@)
336 HRESULT WINAPI
WindowsConcatString(HSTRING str1
, HSTRING str2
, HSTRING
*out
)
338 struct hstring_private
*priv1
= impl_from_HSTRING(str1
);
339 struct hstring_private
*priv2
= impl_from_HSTRING(str2
);
340 struct hstring_private
*priv
;
342 TRACE("(%p, %p, %p)\n", str1
, str2
, out
);
347 return WindowsDuplicateString(str2
, out
);
349 return WindowsDuplicateString(str1
, out
);
350 if (!priv1
->length
&& !priv2
->length
)
355 if (!alloc_string(priv1
->length
+ priv2
->length
, out
))
356 return E_OUTOFMEMORY
;
357 priv
= impl_from_HSTRING(*out
);
358 memcpy(priv
->buffer
, priv1
->buffer
, priv1
->length
* sizeof(*priv1
->buffer
));
359 memcpy(priv
->buffer
+ priv1
->length
, priv2
->buffer
, priv2
->length
* sizeof(*priv2
->buffer
));
363 /***********************************************************************
364 * WindowsIsStringEmpty (combase.@)
366 BOOL WINAPI
WindowsIsStringEmpty(HSTRING str
)
368 struct hstring_private
*priv
= impl_from_HSTRING(str
);
370 TRACE("(%p)\n", str
);
374 return priv
->length
== 0;
377 /***********************************************************************
378 * WindowsCompareStringOrdinal (combase.@)
380 HRESULT WINAPI
WindowsCompareStringOrdinal(HSTRING str1
, HSTRING str2
, INT32
*res
)
382 struct hstring_private
*priv1
= impl_from_HSTRING(str1
);
383 struct hstring_private
*priv2
= impl_from_HSTRING(str2
);
384 const WCHAR
*buf1
= empty
, *buf2
= empty
;
385 UINT32 len1
= 0, len2
= 0;
387 TRACE("(%p, %p, %p)\n", str1
, str2
, res
);
398 buf1
= priv1
->buffer
;
399 len1
= priv1
->length
;
403 buf2
= priv2
->buffer
;
404 len2
= priv2
->length
;
406 *res
= CompareStringOrdinal(buf1
, len1
, buf2
, len2
, FALSE
) - CSTR_EQUAL
;
410 /***********************************************************************
411 * WindowsTrimStringStart (combase.@)
413 HRESULT WINAPI
WindowsTrimStringStart(HSTRING str1
, HSTRING str2
, HSTRING
*out
)
415 struct hstring_private
*priv1
= impl_from_HSTRING(str1
);
416 struct hstring_private
*priv2
= impl_from_HSTRING(str2
);
419 TRACE("(%p, %p, %p)\n", str1
, str2
, out
);
421 if (!out
|| !str2
|| !priv2
->length
)
428 for (start
= 0; start
< priv1
->length
; start
++)
430 if (!wmemchr(priv2
->buffer
, priv1
->buffer
[start
], priv2
->length
))
433 return start
? WindowsCreateString(&priv1
->buffer
[start
], priv1
->length
- start
, out
) :
434 WindowsDuplicateString(str1
, out
);
437 /***********************************************************************
438 * WindowsTrimStringEnd (combase.@)
440 HRESULT WINAPI
WindowsTrimStringEnd(HSTRING str1
, HSTRING str2
, HSTRING
*out
)
442 struct hstring_private
*priv1
= impl_from_HSTRING(str1
);
443 struct hstring_private
*priv2
= impl_from_HSTRING(str2
);
446 TRACE("(%p, %p, %p)\n", str1
, str2
, out
);
448 if (!out
|| !str2
|| !priv2
->length
)
455 for (len
= priv1
->length
; len
> 0; len
--)
457 if (!wmemchr(priv2
->buffer
, priv1
->buffer
[len
- 1], priv2
->length
))
460 return (len
< priv1
->length
) ? WindowsCreateString(priv1
->buffer
, len
, out
) :
461 WindowsDuplicateString(str1
, out
);