📈
ucore-analysis
  • Introduction
  • lab1
    • boot
      • bootasm
      • bootmain
    • kern
      • debug
        • kmonitor
        • panic
      • init
        • init
      • libs
        • readline
      • mm
        • pmm
      • trap
        • trap
        • trapentry
        • vectors
    • libs
    • tools
  • lab解析
    • lab1
      • 练习1
      • 练习2
      • 练习3
      • 练习4
      • 练习6
      • 扩展练习
      • Piazza优质问题/笔记收集
    • lab2
      • 练习1
      • 练习2
      • 练习3
    • lab3
    • lab4
    • lab5
    • lab6
    • lab7
    • lab8
  • uCore代码
    • boot
      • asm.h
      • bootasm.S
      • bootmain.c
      • (lab1) bootasm.S
    • kern
      • debug
        • assert.h
        • kdebug.c
        • kdebug.h
        • kmonitor.c
        • kmonitor.h
        • panic.c
        • stab.h
        • (lab1) kdebug.c
      • driver
        • clock.c
        • clock.h
        • console.c
        • console.h
        • ide.c
        • ide.h
        • intr.c
        • intr.h
        • kbdreg.h
        • picirq.c
        • picirq.h
      • fs
        • devs
          • dev.c
          • dev_disk0.c
          • dev.h
          • dev_stdin.c
          • dev_stdout.c
        • sfs
          • bitmap.c
          • bitmap.h
          • sfs.c
          • sfs_fs.c
          • sfs.h
          • sfs_inode.c
          • sfs_io.c
          • sfs_lock.c
        • swap
          • swapfs.c
          • swapfs.h
        • vfs
          • inode.c
          • inode.h
          • README.md
          • vfs.c
          • vfsdev.c
          • vfsfile.c
          • vfs.h
          • vfslookup.c
          • vfspath.c
        • file.c
        • file.h
        • fs.c
        • fs.h
        • iobuf.c
        • iobuf.h
        • sysfile.c
        • sysfile.h
      • init
        • entry.S
        • init.c
        • (lab1) init.c
      • libs
        • readline.c
        • stdio.c
        • string.c
      • mm
        • default_pmm.c
        • default_pmm.h
        • kmalloc.c
        • kmalloc.h
        • memlayout.h
        • mmu.h
        • pmm.c
        • pmm.h
        • swap.c
        • swap_fifo.c
        • swap_fifo.h
        • swap.h
        • vmm.c
        • vmm.h
        • (lab2) pmm.c
        • (lab3) vmm.c
      • process
        • entry.S
        • proc.c
        • proc.h
        • switch.S
        • (lab4) proc.c
        • (lab5) proc.c
      • schedule
        • default_sched.c
        • default_sched.h
        • default_sched_stride.c
        • sched.c
        • sched.h
      • sync
        • check_sync.c
        • monitor.c
        • monitor.h
        • sem.c
        • sem.h
        • sync.h
        • wait.c
        • wait.h
      • syscall
        • syscall.c
        • syscall.h
      • trap
        • trap.c
        • trapentry.S
        • trap.h
        • vectors.S
        • (lab1) trap.c
    • libs
      • atomic.h
      • defs.h
      • dirent.h
      • elf.h
      • error.h
      • hash.c
      • list.h
      • printfmt.c
      • rand.c
      • skew_heap.h
      • stat.h
      • stdarg.h
      • stdio.h
      • stdlib.h
      • string.c
      • string.h
      • unistd.h
      • x86.h
    • tools
      • boot.ld
      • function.mk
      • gdbinit
      • grade.sh
      • kernel.ld
      • mksfs.c
      • sign.c
      • user.ld
      • vector.c
    • user
      • libs
        • dir.c
        • dir.h
        • file.c
        • file.h
        • initcode.S
        • lock.h
        • panic.c
        • stdio.c
        • syscall.c
        • syscall.h
        • ulib.c
        • ulib.h
        • umain.c
      • badarg.c
      • badsegment.c
      • divzero.c
      • exit.c
      • faultread.c
      • faultreadkernel.c
      • forktest.c
      • forktree.c
      • hello.c
      • ls.c
      • matrix.c
      • pgdir.c
      • priority.c
      • sfs_filetest1.c
      • sh.c
      • sleep.c
      • sleepkill.c
      • softint.c
      • spin.c
      • testbss.c
      • waitkill.c
      • yield.c
    • Makefile
    • (lab1) Makefile
  • 附录:工具使用
    • 如何编辑该文档
    • 讨论区的维护方法
    • 使用Travis CI自动化更新gitbook
Powered by GitBook
On this page

Was this helpful?

  1. uCore代码
  2. libs

string.c

#include <string.h>
#include <x86.h>

/* *
 * strlen - calculate the length of the string @s, not including
 * the terminating '\0' character.
 * @s:      the input string
 *
 * The strlen() function returns the length of string @s.
 * */
size_t
strlen(const char *s) {
    size_t cnt = 0;
    while (*s ++ != '\0') {
        cnt ++;
    }
    return cnt;
}

/* *
 * strnlen - calculate the length of the string @s, not including
 * the terminating '\0' char acter, but at most @len.
 * @s:      the input string
 * @len:    the max-length that function will scan
 *
 * Note that, this function looks only at the first @len characters
 * at @s, and never beyond @s + @len.
 *
 * The return value is strlen(s), if that is less than @len, or
 * @len if there is no '\0' character among the first @len characters
 * pointed by @s.
 * */
size_t
strnlen(const char *s, size_t len) {
    size_t cnt = 0;
    while (cnt < len && *s ++ != '\0') {
        cnt ++;
    }
    return cnt;
}

/* *
 * strcat - appends a copy of the @src string to the @dst string. The terminating null
 * character in @dst is overwritten by the first character of @src, and a new null-character
 * is appended at the end of the new string formed by the concatenation of both in @dst.
 * @dst:    pointer to the @dst array, which should be large enough to contain the concatenated
 *          resulting string.
 * @src:    string to be appended, this should not overlap @dst
 * */
char *
strcat(char *dst, const char *src) {
    return strcpy(dst + strlen(dst), src);
}

/* *
 * strcpy - copies the string pointed by @src into the array pointed by @dst,
 * including the terminating null character.
 * @dst:    pointer to the destination array where the content is to be copied
 * @src:    string to be copied
 *
 * The return value is @dst.
 *
 * To avoid overflows, the size of array pointed by @dst should be long enough to
 * contain the same string as @src (including the terminating null character), and
 * should not overlap in memory with @src.
 * */
char *
strcpy(char *dst, const char *src) {
#ifdef __HAVE_ARCH_STRCPY
    return __strcpy(dst, src);
#else
    char *p = dst;
    while ((*p ++ = *src ++) != '\0')
        /* nothing */;
    return dst;
#endif /* __HAVE_ARCH_STRCPY */
}

/* *
 * strncpy - copies the first @len characters of @src to @dst. If the end of string @src
 * if found before @len characters have been copied, @dst is padded with '\0' until a
 * total of @len characters have been written to it.
 * @dst:    pointer to the destination array where the content is to be copied
 * @src:    string to be copied
 * @len:    maximum number of characters to be copied from @src
 *
 * The return value is @dst
 * */
char *
strncpy(char *dst, const char *src, size_t len) {
    char *p = dst;
    while (len > 0) {
        if ((*p = *src) != '\0') {
            src ++;
        }
        p ++, len --;
    }
    return dst;
}

/* *
 * strcmp - compares the string @s1 and @s2
 * @s1:     string to be compared
 * @s2:     string to be compared
 *
 * This function starts comparing the first character of each string. If
 * they are equal to each other, it continues with the following pairs until
 * the characters differ or until a terminanting null-character is reached.
 *
 * Returns an integral value indicating the relationship between the strings:
 * - A zero value indicates that both strings are equal;
 * - A value greater than zero indicates that the first character that does
 *   not match has a greater value in @s1 than in @s2;
 * - And a value less than zero indicates the opposite.
 * */
int
strcmp(const char *s1, const char *s2) {
#ifdef __HAVE_ARCH_STRCMP
    return __strcmp(s1, s2);
#else
    while (*s1 != '\0' && *s1 == *s2) {
        s1 ++, s2 ++;
    }
    return (int)((unsigned char)*s1 - (unsigned char)*s2);
#endif /* __HAVE_ARCH_STRCMP */
}

/* *
 * strncmp - compares up to @n characters of the string @s1 to those of the string @s2
 * @s1:     string to be compared
 * @s2:     string to be compared
 * @n:      maximum number of characters to compare
 *
 * This function starts comparing the first character of each string. If
 * they are equal to each other, it continues with the following pairs until
 * the characters differ, until a terminating null-character is reached, or
 * until @n characters match in both strings, whichever happens first.
 * */
int
strncmp(const char *s1, const char *s2, size_t n) {
    while (n > 0 && *s1 != '\0' && *s1 == *s2) {
        n --, s1 ++, s2 ++;
    }
    return (n == 0) ? 0 : (int)((unsigned char)*s1 - (unsigned char)*s2);
}

/* *
 * strchr - locates first occurrence of character in string
 * @s:      the input string
 * @c:      character to be located
 *
 * The strchr() function returns a pointer to the first occurrence of
 * character in @s. If the value is not found, the function returns 'NULL'.
 * */
char *
strchr(const char *s, char c) {
    while (*s != '\0') {
        if (*s == c) {
            return (char *)s;
        }
        s ++;
    }
    return NULL;
}

/* *
 * strfind - locates first occurrence of character in string
 * @s:      the input string
 * @c:      character to be located
 *
 * The strfind() function is like strchr() except that if @c is
 * not found in @s, then it returns a pointer to the null byte at the
 * end of @s, rather than 'NULL'.
 * */
char *
strfind(const char *s, char c) {
    while (*s != '\0') {
        if (*s == c) {
            break;
        }
        s ++;
    }
    return (char *)s;
}

/* *
 * strtol - converts string to long integer
 * @s:      the input string that contains the representation of an integer number
 * @endptr: reference to an object of type char *, whose value is set by the
 *          function to the next character in @s after the numerical value. This
 *          parameter can also be a null pointer, in which case it is not used.
 * @base:   x
 *
 * The function first discards as many whitespace characters as necessary until
 * the first non-whitespace character is found. Then, starting from this character,
 * takes as many characters as possible that are valid following a syntax that
 * depends on the base parameter, and interprets them as a numerical value. Finally,
 * a pointer to the first character following the integer representation in @s
 * is stored in the object pointed by @endptr.
 *
 * If the value of base is zero, the syntax expected is similar to that of
 * integer constants, which is formed by a succession of:
 * - An optional plus or minus sign;
 * - An optional prefix indicating octal or hexadecimal base ("0" or "0x" respectively)
 * - A sequence of decimal digits (if no base prefix was specified) or either octal
 *   or hexadecimal digits if a specific prefix is present
 *
 * If the base value is between 2 and 36, the format expected for the integral number
 * is a succession of the valid digits and/or letters needed to represent integers of
 * the specified radix (starting from '0' and up to 'z'/'Z' for radix 36). The
 * sequence may optionally be preceded by a plus or minus sign and, if base is 16,
 * an optional "0x" or "0X" prefix.
 *
 * The strtol() function returns the converted integral number as a long int value.
 * */
long
strtol(const char *s, char **endptr, int base) {
    int neg = 0;
    long val = 0;

    // gobble initial whitespace
    while (*s == ' ' || *s == '\t') {
        s ++;
    }

    // plus/minus sign
    if (*s == '+') {
        s ++;
    }
    else if (*s == '-') {
        s ++, neg = 1;
    }

    // hex or octal base prefix
    if ((base == 0 || base == 16) && (s[0] == '0' && s[1] == 'x')) {
        s += 2, base = 16;
    }
    else if (base == 0 && s[0] == '0') {
        s ++, base = 8;
    }
    else if (base == 0) {
        base = 10;
    }

    // digits
    while (1) {
        int dig;

        if (*s >= '0' && *s <= '9') {
            dig = *s - '0';
        }
        else if (*s >= 'a' && *s <= 'z') {
            dig = *s - 'a' + 10;
        }
        else if (*s >= 'A' && *s <= 'Z') {
            dig = *s - 'A' + 10;
        }
        else {
            break;
        }
        if (dig >= base) {
            break;
        }
        s ++, val = (val * base) + dig;
        // we don't properly detect overflow!
    }

    if (endptr) {
        *endptr = (char *) s;
    }
    return (neg ? -val : val);
}

/* *
 * memset - sets the first @n bytes of the memory area pointed by @s
 * to the specified value @c.
 * @s:      pointer the the memory area to fill
 * @c:      value to set
 * @n:      number of bytes to be set to the value
 *
 * The memset() function returns @s.
 * */
void *
memset(void *s, char c, size_t n) {
#ifdef __HAVE_ARCH_MEMSET
    return __memset(s, c, n);
#else
    char *p = s;
    while (n -- > 0) {
        *p ++ = c;
    }
    return s;
#endif /* __HAVE_ARCH_MEMSET */
}

/* *
 * memmove - copies the values of @n bytes from the location pointed by @src to
 * the memory area pointed by @dst. @src and @dst are allowed to overlap.
 * @dst     pointer to the destination array where the content is to be copied
 * @src     pointer to the source of data to by copied
 * @n:      number of bytes to copy
 *
 * The memmove() function returns @dst.
 * */
void *
memmove(void *dst, const void *src, size_t n) {
#ifdef __HAVE_ARCH_MEMMOVE
    return __memmove(dst, src, n);
#else
    const char *s = src;
    char *d = dst;
    if (s < d && s + n > d) {
        s += n, d += n;
        while (n -- > 0) {
            *-- d = *-- s;
        }
    } else {
        while (n -- > 0) {
            *d ++ = *s ++;
        }
    }
    return dst;
#endif /* __HAVE_ARCH_MEMMOVE */
}

/* *
 * memcpy - copies the value of @n bytes from the location pointed by @src to
 * the memory area pointed by @dst.
 * @dst     pointer to the destination array where the content is to be copied
 * @src     pointer to the source of data to by copied
 * @n:      number of bytes to copy
 *
 * The memcpy() returns @dst.
 *
 * Note that, the function does not check any terminating null character in @src,
 * it always copies exactly @n bytes. To avoid overflows, the size of arrays pointed
 * by both @src and @dst, should be at least @n bytes, and should not overlap
 * (for overlapping memory area, memmove is a safer approach).
 * */
void *
memcpy(void *dst, const void *src, size_t n) {
#ifdef __HAVE_ARCH_MEMCPY
    return __memcpy(dst, src, n);
#else
    const char *s = src;
    char *d = dst;
    while (n -- > 0) {
        *d ++ = *s ++;
    }
    return dst;
#endif /* __HAVE_ARCH_MEMCPY */
}

/* *
 * memcmp - compares two blocks of memory
 * @v1:     pointer to block of memory
 * @v2:     pointer to block of memory
 * @n:      number of bytes to compare
 *
 * The memcmp() functions returns an integral value indicating the
 * relationship between the content of the memory blocks:
 * - A zero value indicates that the contents of both memory blocks are equal;
 * - A value greater than zero indicates that the first byte that does not
 *   match in both memory blocks has a greater value in @v1 than in @v2
 *   as if evaluated as unsigned char values;
 * - And a value less than zero indicates the opposite.
 * */
int
memcmp(const void *v1, const void *v2, size_t n) {
    const char *s1 = (const char *)v1;
    const char *s2 = (const char *)v2;
    while (n -- > 0) {
        if (*s1 != *s2) {
            return (int)((unsigned char)*s1 - (unsigned char)*s2);
        }
        s1 ++, s2 ++;
    }
    return 0;
}
Previousstdlib.hNextstring.h

Last updated 5 years ago

Was this helpful?