《操作系统》的实验代码。
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.

380 line
11 KiB

12 年之前
  1. #include <string.h>
  2. #include <x86.h>
  3. /* *
  4. * strlen - calculate the length of the string @s, not including
  5. * the terminating '\0' character.
  6. * @s: the input string
  7. *
  8. * The strlen() function returns the length of string @s.
  9. * */
  10. size_t
  11. strlen(const char *s) {
  12. size_t cnt = 0;
  13. while (*s ++ != '\0') {
  14. cnt ++;
  15. }
  16. return cnt;
  17. }
  18. /* *
  19. * strnlen - calculate the length of the string @s, not including
  20. * the terminating '\0' char acter, but at most @len.
  21. * @s: the input string
  22. * @len: the max-length that function will scan
  23. *
  24. * Note that, this function looks only at the first @len characters
  25. * at @s, and never beyond @s + @len.
  26. *
  27. * The return value is strlen(s), if that is less than @len, or
  28. * @len if there is no '\0' character among the first @len characters
  29. * pointed by @s.
  30. * */
  31. size_t
  32. strnlen(const char *s, size_t len) {
  33. size_t cnt = 0;
  34. while (cnt < len && *s ++ != '\0') {
  35. cnt ++;
  36. }
  37. return cnt;
  38. }
  39. /* *
  40. * strcat - appends a copy of the @src string to the @dst string. The terminating null
  41. * character in @dst is overwritten by the first character of @src, and a new null-character
  42. * is appended at the end of the new string formed by the concatenation of both in @dst.
  43. * @dst: pointer to the @dst array, which should be large enough to contain the concatenated
  44. * resulting string.
  45. * @src: string to be appended, this should not overlap @dst
  46. * */
  47. char *
  48. strcat(char *dst, const char *src) {
  49. return strcpy(dst + strlen(dst), src);
  50. }
  51. /* *
  52. * strcpy - copies the string pointed by @src into the array pointed by @dst,
  53. * including the terminating null character.
  54. * @dst: pointer to the destination array where the content is to be copied
  55. * @src: string to be copied
  56. *
  57. * The return value is @dst.
  58. *
  59. * To avoid overflows, the size of array pointed by @dst should be long enough to
  60. * contain the same string as @src (including the terminating null character), and
  61. * should not overlap in memory with @src.
  62. * */
  63. char *
  64. strcpy(char *dst, const char *src) {
  65. #ifdef __HAVE_ARCH_STRCPY
  66. return __strcpy(dst, src);
  67. #else
  68. char *p = dst;
  69. while ((*p ++ = *src ++) != '\0')
  70. /* nothing */;
  71. return dst;
  72. #endif /* __HAVE_ARCH_STRCPY */
  73. }
  74. /* *
  75. * strncpy - copies the first @len characters of @src to @dst. If the end of string @src
  76. * if found before @len characters have been copied, @dst is padded with '\0' until a
  77. * total of @len characters have been written to it.
  78. * @dst: pointer to the destination array where the content is to be copied
  79. * @src: string to be copied
  80. * @len: maximum number of characters to be copied from @src
  81. *
  82. * The return value is @dst
  83. * */
  84. char *
  85. strncpy(char *dst, const char *src, size_t len) {
  86. char *p = dst;
  87. while (len > 0) {
  88. if ((*p = *src) != '\0') {
  89. src ++;
  90. }
  91. p ++, len --;
  92. }
  93. return dst;
  94. }
  95. /* *
  96. * strcmp - compares the string @s1 and @s2
  97. * @s1: string to be compared
  98. * @s2: string to be compared
  99. *
  100. * This function starts comparing the first character of each string. If
  101. * they are equal to each other, it continues with the following pairs until
  102. * the characters differ or until a terminanting null-character is reached.
  103. *
  104. * Returns an integral value indicating the relationship between the strings:
  105. * - A zero value indicates that both strings are equal;
  106. * - A value greater than zero indicates that the first character that does
  107. * not match has a greater value in @s1 than in @s2;
  108. * - And a value less than zero indicates the opposite.
  109. * */
  110. int
  111. strcmp(const char *s1, const char *s2) {
  112. #ifdef __HAVE_ARCH_STRCMP
  113. return __strcmp(s1, s2);
  114. #else
  115. while (*s1 != '\0' && *s1 == *s2) {
  116. s1 ++, s2 ++;
  117. }
  118. return (int)((unsigned char)*s1 - (unsigned char)*s2);
  119. #endif /* __HAVE_ARCH_STRCMP */
  120. }
  121. /* *
  122. * strncmp - compares up to @n characters of the string @s1 to those of the string @s2
  123. * @s1: string to be compared
  124. * @s2: string to be compared
  125. * @n: maximum number of characters to compare
  126. *
  127. * This function starts comparing the first character of each string. If
  128. * they are equal to each other, it continues with the following pairs until
  129. * the characters differ, until a terminating null-character is reached, or
  130. * until @n characters match in both strings, whichever happens first.
  131. * */
  132. int
  133. strncmp(const char *s1, const char *s2, size_t n) {
  134. while (n > 0 && *s1 != '\0' && *s1 == *s2) {
  135. n --, s1 ++, s2 ++;
  136. }
  137. return (n == 0) ? 0 : (int)((unsigned char)*s1 - (unsigned char)*s2);
  138. }
  139. /* *
  140. * strchr - locates first occurrence of character in string
  141. * @s: the input string
  142. * @c: character to be located
  143. *
  144. * The strchr() function returns a pointer to the first occurrence of
  145. * character in @s. If the value is not found, the function returns 'NULL'.
  146. * */
  147. char *
  148. strchr(const char *s, char c) {
  149. while (*s != '\0') {
  150. if (*s == c) {
  151. return (char *)s;
  152. }
  153. s ++;
  154. }
  155. return NULL;
  156. }
  157. /* *
  158. * strfind - locates first occurrence of character in string
  159. * @s: the input string
  160. * @c: character to be located
  161. *
  162. * The strfind() function is like strchr() except that if @c is
  163. * not found in @s, then it returns a pointer to the null byte at the
  164. * end of @s, rather than 'NULL'.
  165. * */
  166. char *
  167. strfind(const char *s, char c) {
  168. while (*s != '\0') {
  169. if (*s == c) {
  170. break;
  171. }
  172. s ++;
  173. }
  174. return (char *)s;
  175. }
  176. /* *
  177. * strtol - converts string to long integer
  178. * @s: the input string that contains the representation of an integer number
  179. * @endptr: reference to an object of type char *, whose value is set by the
  180. * function to the next character in @s after the numerical value. This
  181. * parameter can also be a null pointer, in which case it is not used.
  182. * @base: x
  183. *
  184. * The function first discards as many whitespace characters as necessary until
  185. * the first non-whitespace character is found. Then, starting from this character,
  186. * takes as many characters as possible that are valid following a syntax that
  187. * depends on the base parameter, and interprets them as a numerical value. Finally,
  188. * a pointer to the first character following the integer representation in @s
  189. * is stored in the object pointed by @endptr.
  190. *
  191. * If the value of base is zero, the syntax expected is similar to that of
  192. * integer constants, which is formed by a succession of:
  193. * - An optional plus or minus sign;
  194. * - An optional prefix indicating octal or hexadecimal base ("0" or "0x" respectively)
  195. * - A sequence of decimal digits (if no base prefix was specified) or either octal
  196. * or hexadecimal digits if a specific prefix is present
  197. *
  198. * If the base value is between 2 and 36, the format expected for the integral number
  199. * is a succession of the valid digits and/or letters needed to represent integers of
  200. * the specified radix (starting from '0' and up to 'z'/'Z' for radix 36). The
  201. * sequence may optionally be preceded by a plus or minus sign and, if base is 16,
  202. * an optional "0x" or "0X" prefix.
  203. *
  204. * The strtol() function returns the converted integral number as a long int value.
  205. * */
  206. long
  207. strtol(const char *s, char **endptr, int base) {
  208. int neg = 0;
  209. long val = 0;
  210. // gobble initial whitespace
  211. while (*s == ' ' || *s == '\t') {
  212. s ++;
  213. }
  214. // plus/minus sign
  215. if (*s == '+') {
  216. s ++;
  217. }
  218. else if (*s == '-') {
  219. s ++, neg = 1;
  220. }
  221. // hex or octal base prefix
  222. if ((base == 0 || base == 16) && (s[0] == '0' && s[1] == 'x')) {
  223. s += 2, base = 16;
  224. }
  225. else if (base == 0 && s[0] == '0') {
  226. s ++, base = 8;
  227. }
  228. else if (base == 0) {
  229. base = 10;
  230. }
  231. // digits
  232. while (1) {
  233. int dig;
  234. if (*s >= '0' && *s <= '9') {
  235. dig = *s - '0';
  236. }
  237. else if (*s >= 'a' && *s <= 'z') {
  238. dig = *s - 'a' + 10;
  239. }
  240. else if (*s >= 'A' && *s <= 'Z') {
  241. dig = *s - 'A' + 10;
  242. }
  243. else {
  244. break;
  245. }
  246. if (dig >= base) {
  247. break;
  248. }
  249. s ++, val = (val * base) + dig;
  250. // we don't properly detect overflow!
  251. }
  252. if (endptr) {
  253. *endptr = (char *) s;
  254. }
  255. return (neg ? -val : val);
  256. }
  257. /* *
  258. * memset - sets the first @n bytes of the memory area pointed by @s
  259. * to the specified value @c.
  260. * @s: pointer the the memory area to fill
  261. * @c: value to set
  262. * @n: number of bytes to be set to the value
  263. *
  264. * The memset() function returns @s.
  265. * */
  266. void *
  267. memset(void *s, char c, size_t n) {
  268. #ifdef __HAVE_ARCH_MEMSET
  269. return __memset(s, c, n);
  270. #else
  271. char *p = s;
  272. while (n -- > 0) {
  273. *p ++ = c;
  274. }
  275. return s;
  276. #endif /* __HAVE_ARCH_MEMSET */
  277. }
  278. /* *
  279. * memmove - copies the values of @n bytes from the location pointed by @src to
  280. * the memory area pointed by @dst. @src and @dst are allowed to overlap.
  281. * @dst pointer to the destination array where the content is to be copied
  282. * @src pointer to the source of data to by copied
  283. * @n: number of bytes to copy
  284. *
  285. * The memmove() function returns @dst.
  286. * */
  287. void *
  288. memmove(void *dst, const void *src, size_t n) {
  289. #ifdef __HAVE_ARCH_MEMMOVE
  290. return __memmove(dst, src, n);
  291. #else
  292. const char *s = src;
  293. char *d = dst;
  294. if (s < d && s + n > d) {
  295. s += n, d += n;
  296. while (n -- > 0) {
  297. *-- d = *-- s;
  298. }
  299. } else {
  300. while (n -- > 0) {
  301. *d ++ = *s ++;
  302. }
  303. }
  304. return dst;
  305. #endif /* __HAVE_ARCH_MEMMOVE */
  306. }
  307. /* *
  308. * memcpy - copies the value of @n bytes from the location pointed by @src to
  309. * the memory area pointed by @dst.
  310. * @dst pointer to the destination array where the content is to be copied
  311. * @src pointer to the source of data to by copied
  312. * @n: number of bytes to copy
  313. *
  314. * The memcpy() returns @dst.
  315. *
  316. * Note that, the function does not check any terminating null character in @src,
  317. * it always copies exactly @n bytes. To avoid overflows, the size of arrays pointed
  318. * by both @src and @dst, should be at least @n bytes, and should not overlap
  319. * (for overlapping memory area, memmove is a safer approach).
  320. * */
  321. void *
  322. memcpy(void *dst, const void *src, size_t n) {
  323. #ifdef __HAVE_ARCH_MEMCPY
  324. return __memcpy(dst, src, n);
  325. #else
  326. const char *s = src;
  327. char *d = dst;
  328. while (n -- > 0) {
  329. *d ++ = *s ++;
  330. }
  331. return dst;
  332. #endif /* __HAVE_ARCH_MEMCPY */
  333. }
  334. /* *
  335. * memcmp - compares two blocks of memory
  336. * @v1: pointer to block of memory
  337. * @v2: pointer to block of memory
  338. * @n: number of bytes to compare
  339. *
  340. * The memcmp() functions returns an integral value indicating the
  341. * relationship between the content of the memory blocks:
  342. * - A zero value indicates that the contents of both memory blocks are equal;
  343. * - A value greater than zero indicates that the first byte that does not
  344. * match in both memory blocks has a greater value in @v1 than in @v2
  345. * as if evaluated as unsigned char values;
  346. * - And a value less than zero indicates the opposite.
  347. * */
  348. int
  349. memcmp(const void *v1, const void *v2, size_t n) {
  350. const char *s1 = (const char *)v1;
  351. const char *s2 = (const char *)v2;
  352. while (n -- > 0) {
  353. if (*s1 != *s2) {
  354. return (int)((unsigned char)*s1 - (unsigned char)*s2);
  355. }
  356. s1 ++, s2 ++;
  357. }
  358. return 0;
  359. }