Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

477 lines
12 KiB

  1. /*
  2. *
  3. * Copyright (c) 1985-1996, Microsoft Corporation. All Rights Reserved.
  4. *
  5. * Character functions (to and from wide characters)
  6. *
  7. ******************************************************************************
  8. */
  9. #include "h/wchar.h"
  10. #include <errno.h>
  11. #ifndef _tbstowcs
  12. #ifndef _WIN32 /* others */
  13. #define _tbstowcs sbstowcs
  14. #define _wcstotbs wcstosbs
  15. #else /* _WIN32 */
  16. #define _tbstowcs mbstowcs
  17. #define _wcstotbs wcstombs
  18. #endif /* _WIN32 */
  19. #endif
  20. #define ERROR_INVALID_PARAMETER 87L
  21. /*
  22. ** Converts a single byte i.e. ascii string to the wide char format
  23. **
  24. ** NOTE: This function does NOT handle multibyte characters!
  25. ** It should be used only when wchar_t is not 2 bytes and
  26. ** we cannot use the standard functions
  27. **
  28. */
  29. #ifndef _MSC_VER
  30. size_t sbstowcs(WCHAR *pwcs, const char *s, size_t n )
  31. {
  32. size_t count=0;
  33. /* if destintation string exists, fill it in */
  34. if (pwcs)
  35. {
  36. while (count < n)
  37. {
  38. *pwcs = (WCHAR) ( (unsigned char)s[count]);
  39. if (!s[count])
  40. return count;
  41. count++;
  42. pwcs++;
  43. }
  44. return count;
  45. }
  46. else { /* pwcs == NULL, get size only, s must be NUL-terminated */
  47. return strlen(s);
  48. }
  49. }
  50. #endif
  51. /***
  52. *size_t wcstosbs() - Convert wide char string to single byte char string.
  53. *
  54. *Purpose:
  55. * Convert a wide char string into the equivalent multibyte char string
  56. * [ANSI].
  57. *
  58. *Entry:
  59. * char *s = pointer to destination char string
  60. * const WCHAR *pwc = pointer to source wide character string
  61. * size_t n = maximum number of bytes to store in s
  62. *
  63. *Exit:
  64. * If s != NULL, returns (size_t)-1 (if a wchar cannot be converted)
  65. * Otherwise: Number of bytes modified (<=n), not including
  66. * the terminating NUL, if any.
  67. *
  68. *Exceptions
  69. * Returns (size_t)-1 if s is NULL or invalid mb character encountered.
  70. *
  71. *******************************************************************************/
  72. size_t __cdecl wcstosbs( char * s, const WCHAR * pwcs, size_t n)
  73. {
  74. size_t count=0;
  75. /* if destination string exists, fill it in */
  76. if (s)
  77. {
  78. while(count < n)
  79. {
  80. if (*pwcs > 255) /* validate high byte */
  81. {
  82. errno = EILSEQ;
  83. return (size_t)-1; /* error */
  84. }
  85. s[count] = (char) *pwcs;
  86. if (!(*pwcs++))
  87. return count;
  88. count++;
  89. }
  90. return count;
  91. } else { /* s == NULL, get size only, pwcs must be NUL-terminated */
  92. const WCHAR *eos = pwcs;
  93. while (*eos++);
  94. return ( (size_t) (eos - pwcs -1));
  95. }
  96. }
  97. /******
  98. * WCHAR *wcscat(dst, src) - concatenate (append) one wide character string
  99. * to another
  100. *
  101. *Purpose:
  102. * Concatenates src onto the end of dest. Assumes enough
  103. * space in dest.
  104. *
  105. *Entry:
  106. * WCHAR *dst - wide character string to which "src" is to be appended
  107. * const WCHAR *src - wide character string to append to end of "dst"
  108. *
  109. *Exit:
  110. * The address of "dst"
  111. *
  112. *Exceptions:
  113. *
  114. *******************************************************************************/
  115. WCHAR * __cdecl wcscat(WCHAR * dst, const WCHAR * src)
  116. {
  117. WCHAR * cp = dst;
  118. while( *cp )
  119. ++cp; /* Find end of dst */
  120. wcscpy(cp,src); /* Copy src to end of dst */
  121. return dst; /* return dst */
  122. }
  123. /***
  124. *WCHAR *wcscpy(dst, src) - copy one wide character string over another
  125. *
  126. *Purpose:
  127. * Copies the wide character string src into the spot specified by
  128. * dest; assumes enough room.
  129. *
  130. *Entry:
  131. * WCHAR * dst - wide character string over which "src" is to be copied
  132. * const WCHAR * src - string to be copied over "dst"
  133. *
  134. *Exit:
  135. * The address of "dst"
  136. *
  137. *Exceptions:
  138. *******************************************************************************/
  139. WCHAR * __cdecl wcscpy(WCHAR * dst, const WCHAR * src)
  140. {
  141. WCHAR * cp = dst;
  142. #ifdef _MSC_VER
  143. #pragma warning(disable:4706) // assignment within conditional expression
  144. #endif //_MSC_VER
  145. while( *cp++ = *src++ )
  146. ; /* Copy src over dst */
  147. #ifdef _MSC_VER
  148. #pragma warning(default:4706)
  149. #endif //_MSC_VER
  150. return dst;
  151. }
  152. /***
  153. *wcslen - return the length of a null-terminated string
  154. *
  155. *Purpose:
  156. * Finds the number of wide characters in the given wide character
  157. * string, not including the final null character.
  158. *
  159. *Entry:
  160. * const wchat_t * str - string whose length is to be computed
  161. *
  162. *Exit:
  163. * length of the string "str", exclusive of the final null wide character
  164. *
  165. *Exceptions:
  166. *
  167. *******************************************************************************/
  168. size_t __cdecl wcslen(const WCHAR * str)
  169. {
  170. WCHAR *string = (WCHAR *) str;
  171. while( *string )
  172. string++;
  173. return string - str;
  174. }
  175. /***
  176. *wcsnicmp.c - compare first n characters of two wide character strings with
  177. * case insensitivity
  178. *
  179. * Copyright (c) 1985-1988, Microsoft Corporation. All rights reserved.
  180. *
  181. *Purpose:
  182. * defines wcsnicmp() - compare first n characters of two wide character
  183. * strings for lexical order with case insensitivity.
  184. *
  185. *Revision History:
  186. *
  187. *******************************************************************************/
  188. /***
  189. *WCHAR wcUp(wc) - upper case wide character
  190. *
  191. */
  192. static WCHAR wcUp(WCHAR wc)
  193. {
  194. if ('a' <= wc && wc <= 'z')
  195. wc += (WCHAR)('A' - 'a');
  196. return(wc);
  197. }
  198. /***
  199. *int wcsnicmp(first, last, count) - compare first count wide characters of wide
  200. * character strings with case insensitivity.
  201. *
  202. *Purpose:
  203. * Compares two wide character strings for lexical order. The comparison
  204. * stops after: (1) a difference between the strings is found, (2) the end
  205. * of the strings is reached, or (3) count characters have been
  206. * compared.
  207. *
  208. *Entry:
  209. * char *first, *last - wide character strings to compare
  210. * unsigned count - maximum number of wide characters to compare
  211. *
  212. *Exit:
  213. * returns <0 if first < last
  214. * returns 0 if first == last
  215. * returns >0 if first > last
  216. *
  217. *Exceptions:
  218. *
  219. *******************************************************************************/
  220. int __cdecl wcsnicmp(const WCHAR * first, const WCHAR * last, size_t count)
  221. {
  222. if (!count)
  223. return 0;
  224. while (--count && *first && wcUp(*first) == wcUp(*last))
  225. {
  226. first++;
  227. last++;
  228. }
  229. return wcUp(*first) - wcUp(*last);
  230. }
  231. /***
  232. *wcscmp - compare two WCHAR string
  233. * returning less than, equal to, or greater than
  234. *
  235. *Purpose:
  236. * wcscmp compares two wide-character strings and returns an integer
  237. * to indicate whether the first is less than the second, the two are
  238. * equal, or whether the first is greater than the second.
  239. *
  240. * Comparison is done wchar_t by wchar_t on an UNSIGNED basis, which is to
  241. * say that Null wchar_t(0) is less than any other character.
  242. *
  243. *Entry:
  244. * const WCHAR * src - string for left-hand side of comparison
  245. * const WCHAR * dst - string for right-hand side of comparison
  246. *
  247. *Exit:
  248. * returns -1 if src < dst
  249. * returns 0 if src == dst
  250. * returns +1 if src > dst
  251. *
  252. *Exceptions:
  253. *
  254. ******************************************************************************/
  255. int __cdecl wcscmp ( const WCHAR * src, const WCHAR * dst )
  256. {
  257. int ret = 0 ;
  258. while( ! (ret = (int)(*src - *dst)) && *dst)
  259. ++src, ++dst;
  260. if ( ret < 0 )
  261. ret = -1 ;
  262. else if ( ret > 0 )
  263. ret = 1 ;
  264. return( ret );
  265. }
  266. /***
  267. *WCHAR *wcschr(string, c) - search a string for a WCHAR character
  268. *
  269. *Purpose:
  270. * Searches a WCHAR string for a given WCHAR character,
  271. * which may be the null character L'\0'.
  272. *
  273. *Entry:
  274. * WCHAR *string - WCHAR string to search in
  275. * WCHAR c - WCHAR character to search for
  276. *
  277. *Exit:
  278. * returns pointer to the first occurence of c in string
  279. * returns NULL if c does not occur in string
  280. *
  281. *Exceptions:
  282. *
  283. ******************************************************************************/
  284. WCHAR * __cdecl wcschr ( const WCHAR * string, WCHAR ch )
  285. {
  286. while (*string && *string != (WCHAR)ch)
  287. string++;
  288. if (*string == (WCHAR)ch)
  289. return((WCHAR *)string);
  290. return(NULL);
  291. }
  292. /***
  293. *WCHAR *wcsncpy(dest, source, count) - copy at most n wide characters
  294. *
  295. *Purpose:
  296. * Copies count characters from the source string to the
  297. * destination. If count is less than the length of source,
  298. * NO NULL CHARACTER is put onto the end of the copied string.
  299. * If count is greater than the length of sources, dest is padded
  300. * with null characters to length count (wide-characters).
  301. *
  302. *
  303. *Entry:
  304. * WCHAR *dest - pointer to destination
  305. * WCHAR *source - source string for copy
  306. * size_t count - max number of characters to copy
  307. *
  308. *Exit:
  309. * returns dest
  310. *
  311. *Exceptions:
  312. *
  313. *******************************************************************************/
  314. WCHAR* __cdecl wcsncpy ( WCHAR * dest, const WCHAR * source, size_t count )
  315. {
  316. WCHAR *start = dest;
  317. while (count && (*dest++ = *source++)) /* copy string */
  318. count--;
  319. if (count) /* pad out with zeroes */
  320. while (--count)
  321. *dest++ = (WCHAR)'\0';
  322. return(start);
  323. }
  324. #include <assert.h>
  325. /* NOTE: this function is really only converting to US ansi (i.e.
  326. single byte!)
  327. Note that the returned values are slightly different,
  328. but that does not matter in the reference implementation */
  329. int STDCALL WideCharToMultiByte(
  330. unsigned int CodePage, /* code page */
  331. unsigned long dwFlags, /* performance and mapping flags */
  332. const WCHAR* lpWideCharStr, /* address of wide-character string */
  333. int cchWideChar, /* number of characters in string */
  334. char* lpMultiByteStr, /* address of buffer for new string */
  335. int cchMultiByte, /* size of buffer */
  336. const char* lpDefaultChar, /* addr of default for unmappable chars */
  337. int* lpUsedDefaultChar /* addr of flag set when default char. used */
  338. )
  339. {
  340. /* only support UNICODE or US ANSI */
  341. if ((CodePage!=0) && (CodePage!=1252))
  342. {
  343. /* assert(0); */
  344. return 0;
  345. }
  346. /* the following 2 parameters are not used */
  347. dwFlags;
  348. lpDefaultChar;
  349. if (lpUsedDefaultChar)
  350. *lpUsedDefaultChar=0;
  351. if (cchMultiByte)
  352. {
  353. /* copy upto the smaller of the 2 strings */
  354. int nConvert = cchMultiByte;
  355. int nConverted;
  356. if (cchWideChar!=-1 && nConvert>cchWideChar)
  357. nConvert = cchWideChar;
  358. nConverted = _wcstotbs(lpMultiByteStr, lpWideCharStr, nConvert);
  359. if ( (nConverted < cchMultiByte) && (!lpMultiByteStr[nConverted]))
  360. nConverted++;
  361. return nConverted;
  362. }
  363. else /* calculate length */
  364. {
  365. if (cchWideChar!=-1)
  366. return (cchWideChar);
  367. return (_wcstotbs(NULL, lpWideCharStr, 0)+1);
  368. }
  369. }
  370. /*
  371. NOTE: This function is really only converting from US ansi (i.e.
  372. single byte!) It might not work with other locale
  373. Note that the returned values are slightly different,
  374. but that does not matter in the reference implementation
  375. */
  376. int STDCALL MultiByteToWideChar(
  377. unsigned int CodePage, /* code page */
  378. unsigned long dwFlags, /* character-type options */
  379. const char * lpMultiByteStr, /* address of string to map */
  380. int cchMultiByte, /* number of characters in string */
  381. WCHAR* lpWideCharStr, /* address of wide-character buffer */
  382. int cchWideChar /* size of buffer */
  383. )
  384. {
  385. /* only support UNICODE or US ANSI */
  386. if ((CodePage!=0) && (CodePage!=1252))
  387. {
  388. /*assert(0); */
  389. return 0;
  390. }
  391. dwFlags; /* we are not using this parameter */
  392. if (!cchWideChar) /* return size required */
  393. {
  394. if (cchMultiByte != -1)
  395. return cchMultiByte;
  396. else
  397. /* plus one to include null character */
  398. return (_tbstowcs(NULL, lpMultiByteStr, cchWideChar)+1);
  399. }
  400. else
  401. {
  402. /* nConvert is the smaller size of the two strings */
  403. int nConvert=cchWideChar;
  404. int nConverted;
  405. if (cchMultiByte!=-1 && nConvert>cchMultiByte)
  406. nConvert = cchMultiByte; /* prevent copying too much */
  407. nConverted = _tbstowcs(lpWideCharStr, lpMultiByteStr, nConvert);
  408. if ((nConverted < cchWideChar) && (!lpWideCharStr[nConverted]))
  409. nConverted++; /* include null character */
  410. return nConverted;
  411. }
  412. }