reactos/rosapps/smartpdf/baseutils/wstr_util.c
Klemens Friedl 435a566751 SmartPDF - lightweight pdf viewer app for rosapps
* sumatrapdf - vendor import
* everything compiles (libjpeg, poppler, fitz, sumatrapdf)
* does NOT link

(remove the comment tags in the parent directory.rbuild file (rosapps dir) to build it)

svn path=/trunk/; revision=29295
2007-09-29 08:39:35 +00:00

286 lines
6.2 KiB
C

/* Written by Krzysztof Kowalczyk (http://blog.kowalczyk.info)
The author disclaims copyright to this source code. */
/* The most basic things, including string handling functions */
#include "base_util.h"
#include "wstr_util.h"
#include <strsafe.h>
WCHAR *wstr_cat4(const WCHAR *str1, const WCHAR *str2, const WCHAR *str3, const WCHAR *str4)
{
WCHAR *str;
WCHAR *tmp;
size_t str1_len = 0;
size_t str2_len = 0;
size_t str3_len = 0;
size_t str4_len = 0;
if (str1)
str1_len = wstrlen(str1);
if (str2)
str2_len = wstrlen(str2);
if (str3)
str3_len = wstrlen(str3);
if (str4)
str4_len = wstrlen(str4);
str = (WCHAR*)zmalloc((str1_len + str2_len + str3_len + str4_len + 1)*sizeof(WCHAR));
if (!str)
return NULL;
tmp = str;
if (str1) {
memcpy(tmp, str1, str1_len*sizeof(WCHAR));
tmp += str1_len;
}
if (str2) {
memcpy(tmp, str2, str2_len*sizeof(WCHAR));
tmp += str2_len;
}
if (str3) {
memcpy(tmp, str3, str3_len*sizeof(WCHAR));
tmp += str3_len;
}
if (str4) {
memcpy(tmp, str4, str1_len*sizeof(WCHAR));
}
return str;
}
WCHAR *wstr_cat3(const WCHAR *str1, const WCHAR *str2, const WCHAR *str3)
{
return wstr_cat4(str1, str2, str3, NULL);
}
WCHAR *wstr_cat(const WCHAR *str1, const WCHAR *str2)
{
return wstr_cat4(str1, str2, NULL, NULL);
}
WCHAR *wstr_dupn(const WCHAR *str, int str_len_cch)
{
WCHAR *copy;
if (!str)
return NULL;
copy = (WCHAR*)malloc((str_len_cch+1)*sizeof(WCHAR));
if (!copy)
return NULL;
memcpy(copy, str, str_len_cch*sizeof(WCHAR));
copy[str_len_cch] = 0;
return copy;
}
WCHAR *wstr_dup(const WCHAR *str)
{
return wstr_cat4(str, NULL, NULL, NULL);
}
int wstr_copyn(WCHAR *dst, int dst_cch_size, const WCHAR *src, int src_cch_size)
{
WCHAR *end = dst + dst_cch_size - 1;
if (0 == dst_cch_size) {
if (0 == src_cch_size)
return TRUE;
else
return FALSE;
}
while ((dst < end) && (src_cch_size > 0)) {
*dst++ = *src++;
--src_cch_size;
}
*dst = 0;
if (0 == src_cch_size)
return TRUE;
else
return FALSE;
}
int wstr_copy(WCHAR *dst, int dst_cch_size, const WCHAR *src)
{
WCHAR *end = dst + dst_cch_size - 1;
if (0 == dst_cch_size)
return FALSE;
while ((dst < end) && *src) {
*dst++ = *src++;
}
*dst = 0;
if (0 == *src)
return TRUE;
else
return FALSE;
}
int wstr_ieq(const WCHAR *str1, const WCHAR *str2)
{
if (!str1 && !str2)
return TRUE;
if (!str1 || !str2)
return FALSE;
if (0 == _wcsicmp(str1, str2))
return TRUE;
return FALSE;
}
/* return true if 'str' starts with 'txt', case-sensitive */
int wstr_startswith(const WCHAR *str, const WCHAR *txt)
{
if (!str && !txt)
return TRUE;
if (!str || !txt)
return FALSE;
if (0 == wcsncmp(str, txt, wcslen(txt)))
return TRUE;
return FALSE;
}
/* return true if 'str' starts with 'txt', NOT case-sensitive */
int wstr_startswithi(const WCHAR *str, const WCHAR *txt)
{
if (!str && !txt)
return TRUE;
if (!str || !txt)
return FALSE;
if (0 == _wcsnicmp(str, txt, wcslen(txt)))
return TRUE;
return FALSE;
}
int wstr_empty(const WCHAR *str)
{
if (!str)
return TRUE;
if (0 == *str)
return TRUE;
return FALSE;
}
static void wchar_to_hex(WCHAR c, WCHAR* buffer)
{
const WCHAR* numbers = L"0123456789ABCDEF";
buffer[0]=numbers[c / 16];
buffer[1]=numbers[c % 16];
}
int wstr_contains(const WCHAR *str, WCHAR c)
{
while (*str) {
if (c == *str++)
return TRUE;
}
return FALSE;
}
#define WCHAR_URL_DONT_ENCODE L"-_.!~*'()"
int wchar_needs_url_encode(WCHAR c)
{
if ((c >= L'a') && (c <= L'z'))
return FALSE;
if ((c >= L'A') && (c <= L'Z'))
return FALSE;
if ((c >= L'0') && (c <= L'9'))
return FALSE;
if (wstr_contains(WCHAR_URL_DONT_ENCODE, c))
return FALSE;
return TRUE;
}
WCHAR *wstr_url_encode(const WCHAR *str)
{
WCHAR * encoded;
WCHAR * result;
int res_len = 0;
const WCHAR * tmp = str;
while (*tmp) {
if (wchar_needs_url_encode(*tmp))
res_len += 3;
else
++res_len;
tmp++;
}
if (0 == res_len)
return NULL;
encoded = (WCHAR*)malloc((res_len+1)*sizeof(WCHAR));
if (!encoded)
return NULL;
result = encoded;
tmp = str;
while (*tmp) {
if (wchar_needs_url_encode(*tmp)) {
*encoded++ = L'%';
wchar_to_hex(*tmp, encoded);
encoded += 2;
} else {
if (L' ' == *tmp)
*encoded++ = L'+';
else
*encoded++ = *tmp;
}
tmp++;
}
*encoded = 0;
return result;
}
WCHAR *wstr_printf(const WCHAR *format, ...)
{
HRESULT hr;
va_list args;
WCHAR message[256];
WCHAR * buf;
size_t bufCchSize;
buf = &(message[0]);
bufCchSize = sizeof(message)/sizeof(message[0]);
va_start(args, format);
for (;;)
{
hr = StringCchVPrintfW(buf, bufCchSize, format, args);
if (S_OK == hr)
break;
if (STRSAFE_E_INSUFFICIENT_BUFFER != hr)
{
/* any error other than buffer not big enough:
a) should not happen
b) means we give up */
assert(FALSE);
goto Error;
}
/* we have to make the buffer bigger. The algorithm used to calculate
the new size is arbitrary (aka. educated guess) */
if (buf != &(message[0]))
free(buf);
if (bufCchSize < 4*1024)
bufCchSize += bufCchSize;
else
bufCchSize += 1024;
buf = (WCHAR *)malloc(bufCchSize*sizeof(WCHAR));
if (NULL == buf)
goto Error;
}
va_end(args);
/* free the buffer if it was dynamically allocated */
if (buf == &(message[0]))
return wstr_dup(buf);
return buf;
Error:
if (buf != &(message[0]))
free((void*)buf);
return NULL;
}