PageRenderTime 44ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/stores/server/CGI/src/cbtreeString.c

https://github.com/aramk/cbtree
C | 407 lines | 267 code | 26 blank | 114 comment | 89 complexity | 8f582fa97d35350fcd782f9573348ddd MD5 | raw file
Possible License(s): BSD-3-Clause
  1. /****************************************************************************************
  2. * Copyright (c) 2012, Peter Jekel
  3. * All rights reserved.
  4. *
  5. * The Checkbox Tree File Store CGI (cbtreeFileStore) is released under to following
  6. * license:
  7. *
  8. * BSD 2-Clause (http://thejekels.com/cbtree/LICENSE)
  9. *
  10. * @author Peter Jekel
  11. *
  12. ****************************************************************************************
  13. *
  14. * Description:
  15. *
  16. * This module provides some basic extensions to the standard C libraries.
  17. *
  18. ****************************************************************************************/
  19. #ifdef _MSC_VER
  20. #define _CRT_SECURE_NO_WARNINGS
  21. #endif /* _MSC_VER */
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <ctype.h>
  25. #include "cbtreeCommon.h"
  26. #include "cbtreeString.h"
  27. /**
  28. * _strpair
  29. *
  30. * Match a pair of left and right delimiters. The pair of delimiters can be
  31. * nested. However, the string of characters is NOT checked for any literals.
  32. * On success, piCount, if specified, returns the total number of characters
  33. * in between the two outer most delimiters.
  34. *
  35. * @param src Reference to a zero terminated string
  36. * @param iLvalue ASCII value of left delimiter
  37. * @param iRvalue ASCII value of right delimiter
  38. * @param piCount Address integer receiving the total number of characters
  39. * between the delimiters.
  40. *
  41. * @return Address right side delimiter.
  42. **/
  43. static char *_strpair( char *src, int iLvalue, int iRvalue, int *piCount )
  44. {
  45. int iLbr = 0,
  46. iCnt = 0;
  47. if( src && *src == iLvalue )
  48. {
  49. while( *src )
  50. {
  51. if( *src == iLvalue || *src == iRvalue )
  52. {
  53. if( *src == iLvalue )
  54. {
  55. if( !iLbr++ )
  56. {
  57. src++;
  58. continue;
  59. }
  60. if( iLvalue == iRvalue )
  61. {
  62. if( piCount ) *piCount = iCnt;
  63. return src;
  64. }
  65. }
  66. if( *src == iRvalue )
  67. {
  68. if( --iLbr == 0 )
  69. {
  70. if( piCount ) *piCount = iCnt;
  71. return src;
  72. }
  73. }
  74. }
  75. iCnt++;
  76. src++;
  77. }
  78. }
  79. if( piCount ) *piCount = 0;
  80. return NULL;
  81. }
  82. /**
  83. * isBoolean
  84. *
  85. **/
  86. bool isBoolean( char *pcSrc, bool *pbValue )
  87. {
  88. char cBuffer[MAX_BUF_SIZE];
  89. if( pcSrc && *pcSrc )
  90. {
  91. strncpyz( cBuffer, pcSrc, sizeof(cBuffer)-1 );
  92. strtrim( cBuffer, (TRIM_M_WSP | TRIM_M_QUOTES) );
  93. if( !strcmp(cBuffer,"true") )
  94. {
  95. if( pbValue )
  96. {
  97. *pbValue = true;
  98. }
  99. return true;
  100. }
  101. if( !strcmp(cBuffer,"false") )
  102. {
  103. if( pbValue )
  104. {
  105. *pbValue = false;
  106. }
  107. return true;
  108. }
  109. }
  110. return false;
  111. }
  112. /**
  113. * isNumeric
  114. *
  115. * @param pcSrc Pointer to a zero terminated string
  116. * @param plValue Numeric value
  117. *
  118. * @return False
  119. * True
  120. **/
  121. bool isNumeric( char *pcSrc, long *plValue )
  122. {
  123. char *nxt;
  124. double dValue;
  125. long lValue;
  126. if( plValue ) *plValue = 0; // Reset the output value.
  127. if( pcSrc && *pcSrc )
  128. {
  129. // Try integer first
  130. lValue = strtol( pcSrc, &nxt, 0 );
  131. if( !*nxt )
  132. {
  133. if( plValue ) *plValue = lValue;
  134. return true;
  135. }
  136. // Try double/float
  137. dValue = strtod( pcSrc, &nxt );
  138. if( !*nxt )
  139. {
  140. if( plValue ) *plValue = (long)dValue;
  141. return true;
  142. }
  143. }
  144. return false;
  145. }
  146. /**
  147. * isQuoted
  148. *
  149. **/
  150. bool isQuoted( char *s )
  151. {
  152. int i;
  153. if( s != NULL )
  154. {
  155. if( ( i = strlen(s) ) > 1) // We need at least 2 or more char.
  156. {
  157. if( (s[0] == '\'' && s[i-1] == '\'') ||
  158. (s[0] == '"' && s[i-1] == '"') )
  159. {
  160. return true;
  161. }
  162. }
  163. }
  164. return false;
  165. }
  166. /**
  167. * mstrncpy
  168. *
  169. **/
  170. char *mstrncpy( const char *src, size_t len )
  171. {
  172. const char *s = src;
  173. char *b = NULL,
  174. *d;
  175. size_t i;
  176. if( s != NULL && len >= 0 )
  177. {
  178. if( (b = (char *)malloc( len+1 )) )
  179. {
  180. d = b;
  181. for( i=0; i<len; i++ ) *d++ = *s++;
  182. *d = '\0';
  183. }
  184. }
  185. return b;
  186. }
  187. /**
  188. * mstrcpy
  189. *
  190. **/
  191. char *mstrcpy( const char *src )
  192. {
  193. return (src ? mstrncpy( src, strlen(src) ) : NULL );
  194. }
  195. /**
  196. * strcap
  197. *
  198. **/
  199. char *strcap( char *src )
  200. {
  201. char *s = src;
  202. while( *s )
  203. {
  204. *s = (char)tolower(*s);
  205. s++;
  206. }
  207. *src = (char)toupper( *src );
  208. return src;
  209. }
  210. /**
  211. * strcpair
  212. *
  213. * Match a pair of left and right delimiters. On success, returns the total
  214. * number of characters in between the two outer most delimiters.
  215. *
  216. * @param src Reference to a zero terminated string
  217. * @param iLvalue
  218. * @param iRvalue
  219. *
  220. * @return Character count between delimiters
  221. **/
  222. int strcpair( char *src, int iLvalue, int iRvalue )
  223. {
  224. int iLen;
  225. if( _strpair( src, iLvalue, iRvalue, &iLen ) )
  226. {
  227. return iLen;
  228. }
  229. return -1;
  230. }
  231. /**
  232. * strfchr
  233. *
  234. * Returns the address of the first non whitespace character following
  235. * 'src'
  236. *
  237. * @param src Reference to a zero terminated string
  238. *
  239. * @return Address first non whitespace.
  240. **/
  241. char *strfchr( char *src )
  242. {
  243. while( src && isspace( *src ) ) src++;
  244. return src;
  245. }
  246. /**
  247. * strncpyz
  248. *
  249. **/
  250. char *strncpyz( char *dst, const char *src, size_t len )
  251. {
  252. if( dst && len >= 0 )
  253. {
  254. if( src )
  255. {
  256. strncpy( dst, src, len );
  257. dst[len] = '\0';
  258. }
  259. else
  260. *dst = '\0';
  261. }
  262. return dst;
  263. }
  264. /**
  265. * strpair
  266. *
  267. * Match a pair of left and right delimiters. On success, returns address
  268. * of the right side delimiter.
  269. *
  270. * @param src Reference to a zero terminated string
  271. * @param iLvalue Left delimiter
  272. * @param iRvalue Right delimiter
  273. *
  274. * @return Address right side delimiter.
  275. **/
  276. char *strpair( char *src, int iLvalue, int iRvalue )
  277. {
  278. return _strpair( src, iLvalue, iRvalue, NULL );
  279. }
  280. /**
  281. * strtrim
  282. *
  283. **/
  284. char *strtrim( char *src, int flag )
  285. {
  286. char *s, *d;
  287. int len;
  288. if( src != NULL && strlen(src) )
  289. {
  290. // Substitute <CRLF> or <CR> or <NIL> to <LF>
  291. if( flag & TRIM_M_CRLF_TO_LF )
  292. {
  293. s = d = src;
  294. while( *s )
  295. {
  296. if( *s == 0x0D && *(s+1) == 0x0A )
  297. {
  298. *d++ = 0x0A;
  299. s += 2;
  300. continue;
  301. }
  302. if( *s == 0x0D || *s == 0x85 )
  303. {
  304. *d++ = 0x0A;
  305. s++;
  306. continue;
  307. }
  308. *d++ = *s++;
  309. }
  310. *d = '\0';
  311. }
  312. // Substitude the characters 0x09, 0x0A and 0xOD with a single space
  313. if( flag & TRIM_M_WSP_TO_SP )
  314. {
  315. s = src;
  316. while( *s )
  317. {
  318. if( (unsigned char)*s == 0x0A ||
  319. (unsigned char)*s == 0x0D ||
  320. (unsigned char)*s == 0x85 || // <NEL>
  321. (unsigned char)*s == 0x09 )
  322. {
  323. *s = 0x20;
  324. }
  325. s++;
  326. }
  327. }
  328. // Collapse a sequence of spaces into a single space
  329. if( flag & TRIM_M_COLLAPSE )
  330. {
  331. s = src;
  332. while( (s = strstr( s, " " )) ) // Find <space><space>
  333. {
  334. d = ++s;
  335. while( *d == ' ' ) d++;
  336. memmove( s, d, strlen(d)+1 ); // Move left
  337. }
  338. }
  339. // Strip leading whitespace
  340. if( flag & TRIM_M_LWSP )
  341. {
  342. s = d = src;
  343. while( isspace((unsigned char)*s) ) { s++; }
  344. if( s != d )
  345. while( (*d++ = *s++) );
  346. }
  347. // Strip trailing spaces
  348. d = src + strlen(src);
  349. if( flag == 0 || (flag & TRIM_M_RWSP) || (flag & TRIM_M_SLASH) )
  350. {
  351. while( d > src && isspace((unsigned char)*(d-1)) ) { d--; }
  352. *d = '\0';
  353. }
  354. // Strip trailing slash
  355. if( flag & TRIM_M_SLASH )
  356. {
  357. if( *(d-1) == '\\' || *(d-1) == '/' )
  358. {
  359. d--;
  360. }
  361. }
  362. *d = '\0';
  363. // Strip quotes
  364. if( flag & TRIM_M_QUOTES )
  365. {
  366. s = src;
  367. len = strlen( s );
  368. if( isQuoted( s ) ) // Is the string enclosed in quotes?
  369. {
  370. len = len - 2; // String length without the quotes.
  371. memcpy( s, &s[1], len ); // Shift string left.
  372. s[len]='\0'; // Zero terminate updated string.
  373. if( flag & TRIM_M_QUOTES_RECUR )
  374. {
  375. strtrim(s, flag); // Check for nested quotes
  376. }
  377. }
  378. }
  379. }
  380. return src;
  381. }