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.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. /*
  2. * Copyright (C) 2015 Michael Brown <mbrown@fensystems.co.uk>.
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License as
  6. * published by the Free Software Foundation; either version 2 of the
  7. * License, or (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful, but
  10. * WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  17. * 02110-1301, USA.
  18. */
  19. FILE_LICENCE ( GPL2_OR_LATER );
  20. #include <stddef.h>
  21. #include <stdint.h>
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #include <ctype.h>
  25. /** @file
  26. *
  27. * String functions
  28. *
  29. */
  30. /**
  31. * Fill memory region
  32. *
  33. * @v dest Destination region
  34. * @v character Fill character
  35. * @v len Length
  36. * @ret dest Destination region
  37. */
  38. void * generic_memset ( void *dest, int character, size_t len ) {
  39. uint8_t *dest_bytes = dest;
  40. while ( len-- )
  41. *(dest_bytes++) = character;
  42. return dest;
  43. }
  44. /**
  45. * Copy memory region
  46. *
  47. * @v dest Destination region
  48. * @v src Source region
  49. * @v len Length
  50. * @ret dest Destination region
  51. */
  52. void * generic_memcpy ( void *dest, const void *src, size_t len ) {
  53. const uint8_t *src_bytes = src;
  54. uint8_t *dest_bytes = dest;
  55. while ( len-- )
  56. *(dest_bytes++) = *(src_bytes++);
  57. return dest;
  58. }
  59. /**
  60. * Copy (possibly overlapping) memory region
  61. *
  62. * @v dest Destination region
  63. * @v src Source region
  64. * @v len Length
  65. * @ret dest Destination region
  66. */
  67. void * generic_memmove ( void *dest, const void *src, size_t len ) {
  68. const uint8_t *src_bytes = ( src + len );
  69. uint8_t *dest_bytes = ( dest + len );
  70. if ( dest < src )
  71. return memcpy ( dest, src, len );
  72. while ( len-- )
  73. *(--dest_bytes) = *(--src_bytes);
  74. return dest;
  75. }
  76. /**
  77. * Compare memory regions
  78. *
  79. * @v first First region
  80. * @v second Second region
  81. * @v len Length
  82. * @ret diff Difference
  83. */
  84. int memcmp ( const void *first, const void *second, size_t len ) {
  85. const uint8_t *first_bytes = first;
  86. const uint8_t *second_bytes = second;
  87. int diff;
  88. while ( len-- ) {
  89. diff = ( *(second_bytes++) - *(first_bytes++) );
  90. if ( diff )
  91. return diff;
  92. }
  93. return 0;
  94. }
  95. /**
  96. * Find character within a memory region
  97. *
  98. * @v src Source region
  99. * @v character Character to find
  100. * @v len Length
  101. * @ret found Found character, or NULL if not found
  102. */
  103. void * memchr ( const void *src, int character, size_t len ) {
  104. const uint8_t *src_bytes = src;
  105. for ( ; len-- ; src_bytes++ ) {
  106. if ( *src_bytes == character )
  107. return ( ( void * ) src_bytes );
  108. }
  109. return NULL;
  110. }
  111. /**
  112. * Swap memory regions
  113. *
  114. * @v first First region
  115. * @v second Second region
  116. * @v len Length
  117. * @ret first First region
  118. */
  119. void * memswap ( void *first, void *second, size_t len ) {
  120. uint8_t *first_bytes = first;
  121. uint8_t *second_bytes = second;
  122. uint8_t temp;
  123. for ( ; len-- ; first_bytes++, second_bytes++ ) {
  124. temp = *first_bytes;
  125. *first_bytes = *second_bytes;
  126. *second_bytes = temp;
  127. }
  128. return first;
  129. }
  130. /**
  131. * Compare strings
  132. *
  133. * @v first First string
  134. * @v second Second string
  135. * @ret diff Difference
  136. */
  137. int strcmp ( const char *first, const char *second ) {
  138. return strncmp ( first, second, ~( ( size_t ) 0 ) );
  139. }
  140. /**
  141. * Compare strings
  142. *
  143. * @v first First string
  144. * @v second Second string
  145. * @v max Maximum length to compare
  146. * @ret diff Difference
  147. */
  148. int strncmp ( const char *first, const char *second, size_t max ) {
  149. const uint8_t *first_bytes = ( ( const uint8_t * ) first );
  150. const uint8_t *second_bytes = ( ( const uint8_t * ) second );
  151. int diff;
  152. for ( ; max-- ; first_bytes++, second_bytes++ ) {
  153. diff = ( *second_bytes - *first_bytes );
  154. if ( diff )
  155. return diff;
  156. if ( ! *first_bytes )
  157. return 0;
  158. }
  159. return 0;
  160. }
  161. /**
  162. * Compare case-insensitive strings
  163. *
  164. * @v first First string
  165. * @v second Second string
  166. * @ret diff Difference
  167. */
  168. int strcasecmp ( const char *first, const char *second ) {
  169. const uint8_t *first_bytes = ( ( const uint8_t * ) first );
  170. const uint8_t *second_bytes = ( ( const uint8_t * ) second );
  171. int diff;
  172. for ( ; ; first_bytes++, second_bytes++ ) {
  173. diff = ( toupper ( *second_bytes ) -
  174. toupper ( *first_bytes ) );
  175. if ( diff )
  176. return diff;
  177. if ( ! *first_bytes )
  178. return 0;
  179. }
  180. }
  181. /**
  182. * Get length of string
  183. *
  184. * @v src String
  185. * @ret len Length
  186. */
  187. size_t strlen ( const char *src ) {
  188. return strnlen ( src, ~( ( size_t ) 0 ) );
  189. }
  190. /**
  191. * Get length of string
  192. *
  193. * @v src String
  194. * @v max Maximum length
  195. * @ret len Length
  196. */
  197. size_t strnlen ( const char *src, size_t max ) {
  198. const uint8_t *src_bytes = ( ( const uint8_t * ) src );
  199. size_t len = 0;
  200. while ( max-- && *(src_bytes++) )
  201. len++;
  202. return len;
  203. }
  204. /**
  205. * Find character within a string
  206. *
  207. * @v src String
  208. * @v character Character to find
  209. * @ret found Found character, or NULL if not found
  210. */
  211. char * strchr ( const char *src, int character ) {
  212. const uint8_t *src_bytes = ( ( const uint8_t * ) src );
  213. for ( ; ; src_bytes++ ) {
  214. if ( *src_bytes == character )
  215. return ( ( char * ) src_bytes );
  216. if ( ! *src_bytes )
  217. return NULL;
  218. }
  219. }
  220. /**
  221. * Find rightmost character within a string
  222. *
  223. * @v src String
  224. * @v character Character to find
  225. * @ret found Found character, or NULL if not found
  226. */
  227. char * strrchr ( const char *src, int character ) {
  228. const uint8_t *src_bytes = ( ( const uint8_t * ) src );
  229. const uint8_t *start = src_bytes;
  230. while ( *src_bytes )
  231. src_bytes++;
  232. for ( src_bytes-- ; src_bytes >= start ; src_bytes-- ) {
  233. if ( *src_bytes == character )
  234. return ( ( char * ) src_bytes );
  235. }
  236. return NULL;
  237. }
  238. /**
  239. * Find substring
  240. *
  241. * @v haystack String
  242. * @v needle Substring
  243. * @ret found Found substring, or NULL if not found
  244. */
  245. char * strstr ( const char *haystack, const char *needle ) {
  246. size_t len = strlen ( needle );
  247. for ( ; *haystack ; haystack++ ) {
  248. if ( memcmp ( haystack, needle, len ) == 0 )
  249. return ( ( char * ) haystack );
  250. }
  251. return NULL;
  252. }
  253. /**
  254. * Copy string
  255. *
  256. * @v dest Destination string
  257. * @v src Source string
  258. * @ret dest Destination string
  259. */
  260. char * strcpy ( char *dest, const char *src ) {
  261. const uint8_t *src_bytes = ( ( const uint8_t * ) src );
  262. uint8_t *dest_bytes = ( ( uint8_t * ) dest );
  263. /* We cannot use strncpy(), since that would pad the destination */
  264. for ( ; ; src_bytes++, dest_bytes++ ) {
  265. *dest_bytes = *src_bytes;
  266. if ( ! *dest_bytes )
  267. break;
  268. }
  269. return dest;
  270. }
  271. /**
  272. * Copy string
  273. *
  274. * @v dest Destination string
  275. * @v src Source string
  276. * @v max Maximum length
  277. * @ret dest Destination string
  278. */
  279. char * strncpy ( char *dest, const char *src, size_t max ) {
  280. const uint8_t *src_bytes = ( ( const uint8_t * ) src );
  281. uint8_t *dest_bytes = ( ( uint8_t * ) dest );
  282. for ( ; max ; max--, src_bytes++, dest_bytes++ ) {
  283. *dest_bytes = *src_bytes;
  284. if ( ! *dest_bytes )
  285. break;
  286. }
  287. while ( max-- )
  288. *(dest_bytes++) = '\0';
  289. return dest;
  290. }
  291. /**
  292. * Concatenate string
  293. *
  294. * @v dest Destination string
  295. * @v src Source string
  296. * @ret dest Destination string
  297. */
  298. char * strcat ( char *dest, const char *src ) {
  299. strcpy ( ( dest + strlen ( dest ) ), src );
  300. return dest;
  301. }
  302. /**
  303. * Duplicate string
  304. *
  305. * @v src Source string
  306. * @ret dup Duplicated string, or NULL if allocation failed
  307. */
  308. char * strdup ( const char *src ) {
  309. return strndup ( src, ~( ( size_t ) 0 ) );
  310. }
  311. /**
  312. * Duplicate string
  313. *
  314. * @v src Source string
  315. * @v max Maximum length
  316. * @ret dup Duplicated string, or NULL if allocation failed
  317. */
  318. char * strndup ( const char *src, size_t max ) {
  319. size_t len = strnlen ( src, max );
  320. char *dup;
  321. dup = malloc ( len + 1 /* NUL */ );
  322. if ( dup ) {
  323. memcpy ( dup, src, len );
  324. dup[len] = '\0';
  325. }
  326. return dup;
  327. }