CvString.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589
  1. /*
  2. * CDE - Common Desktop Environment
  3. *
  4. * Copyright (c) 1993-2012, The Open Group. All rights reserved.
  5. *
  6. * These libraries and programs are free software; you can
  7. * redistribute them and/or modify them under the terms of the GNU
  8. * Lesser General Public License as published by the Free Software
  9. * Foundation; either version 2 of the License, or (at your option)
  10. * any later version.
  11. *
  12. * These libraries and programs are distributed in the hope that
  13. * they will be useful, but WITHOUT ANY WARRANTY; without even the
  14. * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  15. * PURPOSE. See the GNU Lesser General Public License for more
  16. * details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with these libraries and programs; if not, write
  20. * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
  21. * Floor, Boston, MA 02110-1301 USA
  22. */
  23. /* $XConsortium: CvString.c /main/4 1996/08/30 15:28:00 cde-hp $ */
  24. /************************************<+>*************************************
  25. ****************************************************************************
  26. **
  27. ** File: CvString.c
  28. **
  29. ** Project: Cde DtHelp
  30. **
  31. ** Description: Semi private string functions - can be platform dependent.
  32. ** These routines are straight C code. They do not require
  33. ** includes to know about the Canvas Engine, the Help
  34. ** dialogs or anything else.
  35. **
  36. **
  37. ** (c) Copyright 1987, 1988, 1989, 1990, 1991, 1992 Hewlett-Packard Company
  38. **
  39. ** (c) Copyright 1993, 1994 Hewlett-Packard Company
  40. ** (c) Copyright 1993, 1994 International Business Machines Corp.
  41. ** (c) Copyright 1993, 1994 Sun Microsystems, Inc.
  42. ** (c) Copyright 1993, 1994 Novell, Inc.
  43. **
  44. **
  45. **
  46. ****************************************************************************
  47. ************************************<+>*************************************/
  48. /*
  49. * system includes
  50. */
  51. #include <stdlib.h>
  52. #include <string.h>
  53. /*
  54. * private includes
  55. */
  56. #include "CvStringI.h"
  57. /******************************************************************************
  58. *
  59. * Private variables and defines.
  60. *
  61. *****************************************************************************/
  62. #define REALLOC_INCR 10
  63. /******************************************************************************
  64. *
  65. * Semi Public Functions
  66. *
  67. *****************************************************************************/
  68. /******************************************************************************
  69. * Function: _DtCvStrLen (const void *p1, int type)
  70. *
  71. * Paramenters:
  72. * p1 Specifies the string or wide char array to process.
  73. * type Specifies the type p1 is. 0 indicaates a string.
  74. * non-zero indicates a wide char array.
  75. * Returns:
  76. * >= 0 If p1 is non-null.
  77. * -1 If p1 is null.
  78. *
  79. * Purpose:
  80. * Returns in number of characters in p1.
  81. *
  82. *****************************************************************************/
  83. int
  84. _DtCvStrLen (
  85. const void *p1,
  86. int type )
  87. {
  88. int len = 0;
  89. const wchar_t *wcs;
  90. if (0 == type)
  91. return (strlen((const char *) p1));
  92. wcs = (wchar_t *) p1;
  93. while (0 != *wcs)
  94. {
  95. wcs++;
  96. len++;
  97. }
  98. return len;
  99. }
  100. /******************************************************************************
  101. * Function: _DtCvStrPtr (const void *p1, int type, int count)
  102. *
  103. * Paramenters:
  104. * p1 Specifies the string or wide char array to process.
  105. * type Specifies the type p1 is. 0 indicaates a string.
  106. * non-zero indicates a wide char array.
  107. * count Specifies an index into p1.
  108. * Returns:
  109. * ptr If everything works okay.
  110. * NULL If problems.
  111. *
  112. * Purpose:
  113. * Get to a point in the wide character or char string.
  114. *
  115. *****************************************************************************/
  116. void *
  117. _DtCvStrPtr (
  118. const void *p1,
  119. int type,
  120. int count)
  121. {
  122. if (0 == type)
  123. return ((void *) (((char *) p1) + count));
  124. return ((void *) (((wchar_t *) p1) + count));
  125. }
  126. /******************************************************************************
  127. * Function: _DtCvChar (const void *p1, int type, int count)
  128. *
  129. * Paramenters:
  130. * p1 Specifies the string or wide char array to process.
  131. * type Specifies the type p1 is. 0 indicaates a string.
  132. * non-zero indicates a wide char array.
  133. * count Specifies an index into p1.
  134. * Returns:
  135. * value If everything works okay.
  136. * (wchar_t) -1 If problems.
  137. *
  138. * Purpose:
  139. * Get a character value.
  140. *
  141. *****************************************************************************/
  142. wchar_t
  143. _DtCvChar (
  144. const void *p1,
  145. int type,
  146. int count)
  147. {
  148. int i, len;
  149. char *ptr;
  150. char str[MB_CUR_MAX];
  151. wchar_t value;
  152. if (0 == type) {
  153. ptr = (char *) p1 + count;
  154. if (MB_CUR_MAX > 1) {
  155. len = mbtowc(&value, ptr, MB_CUR_MAX);
  156. if (len == -1) {
  157. for (i = 1; i < MB_CUR_MAX; ++i) {
  158. ptr -= i;
  159. if (ptr < (char *) p1) {
  160. len = -1;
  161. break;
  162. }
  163. len = mbtowc(&value, ptr, MB_CUR_MAX);
  164. if (len == -1) continue;
  165. }
  166. if (len == -1) value = (wchar_t) -1;
  167. }
  168. }
  169. else value = *ptr;
  170. }
  171. else value = *(((wchar_t *) p1) + count);
  172. return (value);
  173. }
  174. /******************************************************************************
  175. * Function: _DtCvStrcspn (const void *s1, const char *s2, type, &ret_len)
  176. *
  177. * Returns in 'ret_len' the length of the initial segment of string
  178. * s1 which consists entirely of characters not found in string s2.
  179. *
  180. * if type is 0, then s1 is a char* string.
  181. * if type is not 0, then s1 is a wchar_t* string.
  182. *
  183. * s2 cannot be more than 15 characters if looking a wide character
  184. * string in s1.
  185. *
  186. * Returns:
  187. * -1 If found an invalid character.
  188. * 0 If found a character in string s2
  189. * 1 If found the null byte character.
  190. * 2 s2 contained more than 15 characters, but found one of the
  191. * first fifteen characters in string s2.
  192. * 3 s2 contained more than 15 characters, and didn't find any
  193. * of the first fifteen characters in string s2.
  194. *****************************************************************************/
  195. int
  196. _DtCvStrcspn (
  197. const void *s1,
  198. const char *s2,
  199. int type,
  200. int *ret_len )
  201. {
  202. int i, len1, len2;
  203. char *p1, *p2;
  204. size_t num;
  205. wchar_t widec[16];
  206. const wchar_t *wcp;
  207. const wchar_t *wcp2;
  208. if (NULL == s1)
  209. {
  210. *ret_len = 0;
  211. return 0;
  212. }
  213. if ((0 == type && '\0' == *((char *) s1)) ||
  214. (0 != type && 0 == *((wchar_t *) s1)))
  215. {
  216. *ret_len = 0;
  217. return 1;
  218. }
  219. if (NULL == s2 || '\0' == *s2)
  220. {
  221. *ret_len = _DtCvStrLen (s1, type);
  222. return 1;
  223. }
  224. if (0 == type)
  225. {
  226. if (MB_CUR_MAX > 1) {
  227. p1 = (char *) s1;
  228. while (*p1) {
  229. len1 = mblen(p1, MB_CUR_MAX);
  230. if (len1 == -1) {
  231. ++p1;
  232. continue;
  233. }
  234. p2 = (char *) s2;
  235. while (*p2) {
  236. len2 = mblen(p2, MB_CUR_MAX);
  237. if (len2 == -1) {
  238. ++p2;
  239. continue;
  240. }
  241. if (len1 == len2) {
  242. for (i = 0; i < len2; ++i) if (p1[i] != p2[i]) break;
  243. if (i == len2) {
  244. *ret_len = p1 - (char *) s1;
  245. return 0;
  246. }
  247. }
  248. p2 += len2;
  249. }
  250. p1 += len1;
  251. }
  252. *ret_len = p1 - (char *) s1;
  253. return 1;
  254. }
  255. else {
  256. /*
  257. * no need to go through any hassle, just use the 3C function
  258. */
  259. *ret_len = strcspn ((char *) s1, s2);
  260. if ('\0' == ((char *) s1)[*ret_len])
  261. return 1;
  262. return 0;
  263. }
  264. }
  265. /*
  266. * convert the test string into a wide char array
  267. */
  268. num = mbstowcs(widec, s2, 16);
  269. if ((size_t) -1 == num)
  270. return -1;
  271. /*
  272. * force a null termination of the array
  273. */
  274. widec[15] = 0;
  275. /*
  276. * if greater than 15 characters were converted, set the flag to 2
  277. */
  278. num = ((num > 15) ? 2 : 0);
  279. wcp = s1;
  280. while (0 != *wcp)
  281. {
  282. wcp2 = widec;
  283. while (0 != *wcp2)
  284. {
  285. if (*wcp2 == *wcp)
  286. {
  287. *ret_len = wcp - (wchar_t *) s1;
  288. return 0 + num;
  289. }
  290. wcp2++;
  291. }
  292. wcp++;
  293. }
  294. *ret_len = wcp - (wchar_t *) s1;
  295. return 1 + num;
  296. }
  297. /****************************************************************************
  298. * Function: void **_DtCvAddPtrToArray (void **array, void *ptr)
  299. *
  300. * Parameters: array A pointer to a NULL-terminated array
  301. * of pointers.
  302. * ptr The pointer which is to be added to
  303. * the end of the array.
  304. *
  305. * Returns: A pointer to the NULL-terminated array created
  306. * by adding 'ptr' to the end of 'array'.
  307. *
  308. * Purpose: Add a new element to a NULL-terminated array of pointers.
  309. * These are typed as "void *" so that they can be used with
  310. * pointers to any type of data.
  311. *
  312. ****************************************************************************/
  313. void **
  314. _DtCvAddPtrToArray (
  315. void **array,
  316. void *ptr)
  317. {
  318. void **nextP = NULL;
  319. int numElements;
  320. /* If this is the first item for the array, malloc the array and set
  321. nextP to point to the first element. */
  322. if (array == NULL || *array == NULL) {
  323. array = (void **) malloc (REALLOC_INCR * sizeof (void *));
  324. nextP = array;
  325. }
  326. else {
  327. /* Find the NULL pointer at the end of the array. */
  328. numElements = 0;
  329. for (nextP = array; *nextP != NULL; nextP++)
  330. numElements++;
  331. /* The array always grows by chunks of size REALLOC_INCR. So see if
  332. it currently is an exact multiple of REALLOC_INCR size (remember to
  333. count the NULL pointer). If it is then it must be full, so realloc
  334. another chunk. Also remember to move 'nextP' because the array
  335. will probably move in memory. */
  336. if ((numElements + 1) % REALLOC_INCR == 0) {
  337. array = (void **) realloc (array,
  338. (numElements + 1 + REALLOC_INCR) * sizeof (void *));
  339. if (array)
  340. nextP = array + numElements;
  341. else
  342. nextP = NULL;
  343. }
  344. }
  345. if (nextP)
  346. {
  347. *nextP++ = ptr;
  348. *nextP = NULL;
  349. }
  350. return (array);
  351. }
  352. /******************************************************************************
  353. * Function: int _DtCvFreeArray (void **array)
  354. *
  355. * Parameters: array A pointer to the NULL-terminated
  356. * string array which is to be freed.
  357. *
  358. * Return Value: 0 if successful, -1 if a failure occurs
  359. *
  360. * Purpose: Free the memory used for a NULL-terminated string array.
  361. *
  362. ******************************************************************************/
  363. int
  364. _DtCvFreeArray (void **array)
  365. {
  366. void **next;
  367. if (array == NULL)
  368. return -1;
  369. for (next = array; *next != NULL; next++)
  370. free (*next);
  371. free (array);
  372. return (0);
  373. }
  374. #if defined(_AIX)
  375. /*****************************************************************************
  376. * Function: _DtCvStrCaseCmp
  377. *
  378. * Parameters:
  379. *
  380. * Return Value:
  381. *
  382. * Purpose: IBM does not support the 'strcasecmp' routine. This takes it's
  383. * place.
  384. *****************************************************************************/
  385. int
  386. _DtCvStrCaseCmp (
  387. const char *s1,
  388. const char *s2)
  389. {
  390. int c1;
  391. int c2;
  392. int result = 0;
  393. if (s1 == s2) return 0;
  394. if (NULL == s1) return -1;
  395. if (NULL == s2) return 1;
  396. while (result == 0 && *s1 != '\0' && *s2 != '\0')
  397. {
  398. c1 = (unsigned char) *s1;
  399. c2 = (unsigned char) *s2;
  400. if (isupper(c1))
  401. c1 = _tolower(c1);
  402. if (isupper(c2))
  403. c2 = _tolower(c2);
  404. result = c1 - c2;
  405. s1++;
  406. s2++;
  407. }
  408. if (result == 0 && (*s1 != '\0' || *s2 != '\0'))
  409. {
  410. c1 = (unsigned char) *s1;
  411. c2 = (unsigned char) *s2;
  412. if (isupper(c1))
  413. c1 = _tolower(c1);
  414. if (isupper(c2))
  415. c2 = _tolower(c2);
  416. result = c1 - c2;
  417. }
  418. return result;
  419. }
  420. #endif /* _AIX */
  421. /*****************************************************************************
  422. * Function: _DtCvStrNCaseCmpLatin1()
  423. *
  424. * Purpose: Does not use the tolower() functions to determine the lower
  425. * case of a character. On some platforms, using tolower() on
  426. * the upper case of a typical Latin1 character does not match
  427. * it's Latin1 one lower case.
  428. *
  429. * This routine is to be used only when we want to map strict
  430. * Latin1 characters to it's lower case. I.e. when we -know-
  431. * the data is in English.
  432. *****************************************************************************/
  433. int
  434. _DtCvStrNCaseCmpLatin1 (
  435. const char *s1,
  436. const char *s2,
  437. size_t n)
  438. {
  439. int c1;
  440. int c2;
  441. int result = 0;
  442. if (s1 == s2 || n < 1) return 0;
  443. if (NULL == s1) return -1;
  444. if (NULL == s2) return 1;
  445. while (result == 0 && *s1 != '\0' && *s2 != '\0' && n > 0)
  446. {
  447. c1 = (unsigned char) *s1;
  448. c2 = (unsigned char) *s2;
  449. c1 = _DtCvToLower(c1);
  450. c2 = _DtCvToLower(c2);
  451. result = c1 - c2;
  452. s1++;
  453. s2++;
  454. n--;
  455. }
  456. if (result == 0 && n > 0 && (*s1 != '\0' || *s2 != '\0'))
  457. {
  458. c1 = (unsigned char) *s1;
  459. c2 = (unsigned char) *s2;
  460. c1 = _DtCvToLower(c1);
  461. c2 = _DtCvToLower(c2);
  462. result = c1 - c2;
  463. }
  464. return result;
  465. }
  466. /*****************************************************************************
  467. * Function: _DtCvStrCaseCmpLatin1
  468. *
  469. * Purpose: Does not use the tolower() functions to determine the lower
  470. * case of a character. On some platforms, using tolower() on
  471. * the upper case of a typical Latin1 character does not match
  472. * it's Latin1 one lower case.
  473. *
  474. * This routine is to be used only when we want to map strict
  475. * Latin1 characters to it's lower case. I.e. when we -know-
  476. * the data is in English.
  477. *****************************************************************************/
  478. int
  479. _DtCvStrCaseCmpLatin1 (
  480. const char *s1,
  481. const char *s2)
  482. {
  483. int c1;
  484. int c2;
  485. int result = 0;
  486. if (s1 == s2) return 0;
  487. if (NULL == s1) return -1;
  488. if (NULL == s2) return 1;
  489. while (result == 0 && *s1 != '\0' && *s2 != '\0')
  490. {
  491. c1 = (unsigned char) *s1;
  492. c2 = (unsigned char) *s2;
  493. c1 = _DtCvToLower(c1);
  494. c2 = _DtCvToLower(c2);
  495. result = c1 - c2;
  496. s1++;
  497. s2++;
  498. }
  499. if (result == 0 && (*s1 != '\0' || *s2 != '\0'))
  500. {
  501. c1 = (unsigned char) *s1;
  502. c2 = (unsigned char) *s2;
  503. c1 = _DtCvToLower(c1);
  504. c2 = _DtCvToLower(c2);
  505. result = c1 - c2;
  506. }
  507. return result;
  508. }