您的位置:首页 > 运维架构 > Linux

解读linux对string.h函数的实现

2011-10-25 15:34 323 查看
/*

file:string.h

#ifndef _LINUX_STRING_H_

#define _LINUX_STRING_H_

/* We don't want strings.h stuff being user by user stuff by accident */

#ifdef __KERNEL__

#include <linux/types.h> /* for size_t */

#include <linux/stddef.h> /* for NULL */

#include <linux/compiler.h> /* for inline ((always_inline)) */

#ifdef __cplusplus

extern "C" {

#endif

extern char * ___strtok;

extern char * strpbrk(const char *,const char *);

extern char * strtok(char *,const char *);

extern char * strsep(char **,const char *);

extern __kernel_size_t strspn(const char *,const char *);

/*

* Include machine specific inline routines

*/

#include <asm/string.h>

#ifndef __HAVE_ARCH_STRCPY

extern char * strcpy(char *,const char *);

#endif

#ifndef __HAVE_ARCH_STRNCPY

extern char * strncpy(char *,const char *, __kernel_size_t);

#endif

#ifndef __HAVE_ARCH_STRCAT

extern char * strcat(char *, const char *);

#endif

#ifndef __HAVE_ARCH_STRNCAT

extern char * strncat(char *, const char *, __kernel_size_t);

#endif

#ifndef __HAVE_ARCH_STRCMP

extern int strcmp(const char *,const char *);

#endif

#ifndef __HAVE_ARCH_STRNCMP

extern int strncmp(const char *,const char *,__kernel_size_t);

#endif

#ifndef __HAVE_ARCH_STRNICMP

extern int strnicmp(const char *, const char *, __kernel_size_t);

#endif

#ifndef __HAVE_ARCH_STRCHR

extern char * strchr(const char *,int);

#endif

#ifndef __HAVE_ARCH_STRRCHR

extern char * strrchr(const char *,int);

#endif

#ifndef __HAVE_ARCH_STRSTR

extern char * strstr(const char *,const char *);

#endif

#ifndef __HAVE_ARCH_STRLEN

extern __kernel_size_t strlen(const char *);

#endif

#ifndef __HAVE_ARCH_STRNLEN

extern __kernel_size_t strnlen(const char *,__kernel_size_t);

#endif

#ifndef __HAVE_ARCH_MEMSET

extern void * memset(void *,int,__kernel_size_t);

#endif

#ifndef __HAVE_ARCH_MEMCPY

extern void * memcpy(void *,const void *,__kernel_size_t);

#endif

#ifndef __HAVE_ARCH_MEMMOVE

extern void * memmove(void *,const void *,__kernel_size_t);

#endif

#ifndef __HAVE_ARCH_MEMSCAN

extern void * memscan(void *,int,__kernel_size_t);

#endif

#ifndef __HAVE_ARCH_MEMCMP

extern int memcmp(const void *,const void *,__kernel_size_t);

#endif

#ifndef __HAVE_ARCH_MEMCHR

extern void * memchr(const void *,int,__kernel_size_t);

#endif

#ifdef __cplusplus

}

#endif

#endif

#endif /* _LINUX_STRING_H_ */

*/

/*

file:string.h

#ifndef _LINUX_STRING_H_

#define _LINUX_STRING_H_

/* We don't want strings.h stuff being user by user stuff by accident */

#ifdef __KERNEL__

#include <linux/types.h> /* for size_t */

#include <linux/stddef.h> /* for NULL */

#include <linux/compiler.h> /* for inline ((always_inline)) */

#ifdef __cplusplus

extern "C" {

#endif

extern char * ___strtok;

extern char * strpbrk(const char *,const char *);

extern char * strtok(char *,const char *);

extern char * strsep(char **,const char *);

extern __kernel_size_t strspn(const char *,const char *);

/*

* Include machine specific inline routines

*/

#include <asm/string.h>

#ifndef __HAVE_ARCH_STRCPY

extern char * strcpy(char *,const char *);

#endif

#ifndef __HAVE_ARCH_STRNCPY

extern char * strncpy(char *,const char *, __kernel_size_t);

#endif

#ifndef __HAVE_ARCH_STRCAT

extern char * strcat(char *, const char *);

#endif

#ifndef __HAVE_ARCH_STRNCAT

extern char * strncat(char *, const char *, __kernel_size_t);

#endif

#ifndef __HAVE_ARCH_STRCMP

extern int strcmp(const char *,const char *);

#endif

#ifndef __HAVE_ARCH_STRNCMP

extern int strncmp(const char *,const char *,__kernel_size_t);

#endif

#ifndef __HAVE_ARCH_STRNICMP

extern int strnicmp(const char *, const char *, __kernel_size_t);

#endif

#ifndef __HAVE_ARCH_STRCHR

extern char * strchr(const char *,int);

#endif

#ifndef __HAVE_ARCH_STRRCHR

extern char * strrchr(const char *,int);

#endif

#ifndef __HAVE_ARCH_STRSTR

extern char * strstr(const char *,const char *);

#endif

#ifndef __HAVE_ARCH_STRLEN

extern __kernel_size_t strlen(const char *);

#endif

#ifndef __HAVE_ARCH_STRNLEN

extern __kernel_size_t strnlen(const char *,__kernel_size_t);

#endif

#ifndef __HAVE_ARCH_MEMSET

extern void * memset(void *,int,__kernel_size_t);

#endif

#ifndef __HAVE_ARCH_MEMCPY

extern void * memcpy(void *,const void *,__kernel_size_t);

#endif

#ifndef __HAVE_ARCH_MEMMOVE

extern void * memmove(void *,const void *,__kernel_size_t);

#endif

#ifndef __HAVE_ARCH_MEMSCAN

extern void * memscan(void *,int,__kernel_size_t);

#endif

#ifndef __HAVE_ARCH_MEMCMP

extern int memcmp(const void *,const void *,__kernel_size_t);

#endif

#ifndef __HAVE_ARCH_MEMCHR

extern void * memchr(const void *,int,__kernel_size_t);

#endif

#ifdef __cplusplus

}

#endif

#endif

#endif /* _LINUX_STRING_H_ */

*/

实现文件string.c

C代码

/*

* linux/lib/string.c

*

* Copyright (C) 1991, 1992 Linus Torvalds

*/

/*

* stupid library routines.. The optimized versions should generally be found

* as inline code in <asm-xx/string.h>

*

* These are buggy as well..

*

* * Fri Jun 25 1999, Ingo Oeser <ioe@informatik.tu-chemnitz.de>

* - Added strsep() which will replace strtok() soon (because strsep() is

* reentrant and should be faster). Use only strsep() in new code, please.

*/

#include <linux/types.h>

#include <linux/string.h>

#include <linux/ctype.h>

#ifndef __HAVE_ARCH_STRNICMP

/**

* strnicmp - Case insensitive(忽视大小写), length-limited string comparison

* @s1: One string

* @s2: The other string

* @len: the maximum number of characters to compare

*/

int strnicmp(const char *s1, const char *s2, size_t len)

{

/* Yes, Virginia, it had better be unsigned */

unsigned char c1, c2;

c1 = 0; c2 = 0;

if (len) {

do {

c1 = *s1; c2 = *s2;

s1++; s2++;

//是否已到字符串的末尾或两字符串是否有空串,如果到了末尾或有空串,则比较完毕

if (!c1)

break;

if (!c2)

break;

//如果没有,且字符串相等,则继续比较下个字符

if (c1 == c2)

continue;

//如果不相同,则同时转换为小写字符再进行比较

c1 = tolower(c1);

c2 = tolower(c2);

//如果不相同,则比较完毕,否则继续

if (c1 != c2)

break;

} while (--len);

}

return (int)c1 - (int)c2;

}

#endif

char * ___strtok;

#ifndef __HAVE_ARCH_STRCPY

/**

* strcpy - Copy a %NUL terminated string

* @dest: Where to copy the string to

* @src: Where to copy the string from

*/

char * strcpy(char * dest,const char *src)

{

char *tmp = dest;

while ((*dest++ = *src++) != '/0')

/* nothing */;

return tmp;

}

#endif

#ifndef __HAVE_ARCH_STRNCPY

/**

* strncpy - Copy a length-limited, %NUL-terminated string

* @dest: Where to copy the string to

* @src: Where to copy the string from

* @count: The maximum number of bytes to copy

*

* Note that unlike userspace strncpy, this does not %NUL-pad the buffer.

* However, the result is not %NUL-terminated if the source exceeds

* @count bytes.

*/

char * strncpy(char * dest,const char *src,size_t count)

{

char *tmp = dest;

while (count-- && (*dest++ = *src++) != '/0')

/* nothing */;

return tmp;

}

#endif

#ifndef __HAVE_ARCH_STRCAT

/**

* strcat - Append one %NUL-terminated string to another

* @dest: The string to be appended to

* @src: The string to append to it

*/

char * strcat(char * dest, const char * src)

{

char *tmp = dest;

while (*dest)

dest++;

while ((*dest++ = *src++) != '/0')

;

return tmp;

}

#endif

#ifndef __HAVE_ARCH_STRNCAT

/**

* strncat - Append a length-limited, %NUL-terminated string to another

* @dest: The string to be appended to

* @src: The string to append to it

* @count: The maximum numbers of bytes to copy

*

* Note that in contrast to strncpy, strncat ensures the result is

* terminated.

*/

char * strncat(char *dest, const char *src, size_t count)

{

char *tmp = dest;

if (count) { //如果追加的字符数不为0

while (*dest) //达到字符串的末尾

dest++;

while ((*dest++ = *src++)) { //如果没有到源字符串末尾

if (--count == 0) { //如果已经追加了count字符

*dest = '/0';//末尾置null字符

break;//结束循环

}

}

}

return tmp;

}

#endif

#ifndef __HAVE_ARCH_STRCMP

/**

* strcmp - Compare two strings

* @cs: One string

* @ct: Another string

*/

int strcmp(const char * cs,const char * ct)

{

register signed char __res;

while (1) {

if ((__res = *cs - *ct++) != 0 || !*cs++)

break;

}

return __res;

}

#endif

#ifndef __HAVE_ARCH_STRNCMP

/**

* strncmp - Compare two length-limited strings

* @cs: One string

* @ct: Another string

* @count: The maximum number of bytes to compare

*/

int strncmp(const char * cs,const char * ct,size_t count)

{

register signed char __res = 0;

while (count) {

if ((__res = *cs - *ct++) != 0 || !*cs++)

break;

count--;

}

return __res;

}

#endif

#ifndef __HAVE_ARCH_STRCHR

/**

* strchr - Find the first occurrence of a character in a string

* @s: The string to be searched

* @c: The character to search for

*/

char * strchr(const char * s, int c)

{

for(; *s != (char) c; ++s)

if (*s == '/0')

return NULL;

return (char *) s;

}

#endif

#ifndef __HAVE_ARCH_STRRCHR

/**

* strrchr - Find the last occurrence of a character in a string

* @s: The string to be searched

* @c: The character to search for

*/

char * strrchr(const char * s, int c)

{

const char *p = s + strlen(s);

do {

if (*p == (char)c)

return (char *)p;

} while (--p >= s);

return NULL;

}

#endif

#ifndef __HAVE_ARCH_STRLEN

/**

* strlen - Find the length of a string

* @s: The string to be sized

*/

size_t strlen(const char * s)

{

const char *sc;

for (sc = s; *sc != '/0'; ++sc)

/* nothing */;

return sc - s;

}

#endif

#ifndef __HAVE_ARCH_STRNLEN

/**

* strnlen - Find the length of a length-limited string

* @s: The string to be sized

* @count: The maximum number of bytes to search

*/

size_t strnlen(const char * s, size_t count)

{

const char *sc;

for (sc = s; count-- && *sc != '/0'; ++sc)

/* nothing */;

return sc - s;

}

#endif

#ifndef __HAVE_ARCH_STRSPN

/**

* strspn - Calculate the length of the initial substring of @s which only

* contain letters in @accept

* @s: The string to be searched

* @accept: The string to search for

*/

size_t strspn(const char *s, const char *accept)

{

const char *p;

const char *a;

size_t count = 0;

for (p = s; *p != '/0'; ++p) {

for (a = accept; *a != '/0'; ++a) {

if (*p == *a)

break;

}

if (*a == '/0')

return count;

++count;

}

return count;

}

#endif

#ifndef __HAVE_ARCH_STRPBRK

/**

* strpbrk - Find the first occurrence of a set of characters

* @cs: The string to be searched

* @ct: The characters to search for

*/

char * strpbrk(const char * cs,const char * ct)

{

const char *sc1,*sc2;

for( sc1 = cs; *sc1 != '/0'; ++sc1) {

for( sc2 = ct; *sc2 != '/0'; ++sc2) {

if (*sc1 == *sc2)

return (char *) sc1;

}

}

return NULL;

}

#endif

#ifndef __HAVE_ARCH_STRTOK

/**

* strtok - Split a string into tokens

* @s: The string to be searched

* @ct: The characters to search for

*

* WARNING: strtok is deprecated, use strsep instead.

*/

char * strtok(char * s,const char * ct)

{

char *sbegin, *send;

sbegin = s ? s : ___strtok;

if (!sbegin) {

return NULL;

}

sbegin += strspn(sbegin,ct);

if (*sbegin == '/0') {

___strtok = NULL;

return( NULL );

}

send = strpbrk( sbegin, ct);

if (send && *send != '/0')

*send++ = '/0';

___strtok = send;

return (sbegin);

}

#endif

#ifndef __HAVE_ARCH_STRSEP

/**

* strsep - Split a string into tokens

* @s: The string to be searched

* @ct: The characters to search for

*

* strsep() updates @s to point after the token, ready for the next call.

*

* It returns empty tokens, too, behaving exactly like the libc function

* of that name. In fact, it was stolen from glibc2 and de-fancy-fied.

* Same semantics, slimmer shape. ;)

*/

char * strsep(char **s, const char *ct)

{

char *sbegin = *s, *end;

if (sbegin == NULL)

return NULL;

end = strpbrk(sbegin, ct);

if (end)

*end++ = '/0';

*s = end;

return sbegin;

}

#endif

#ifndef __HAVE_ARCH_MEMSET

/**

* memset - Fill a region of memory with the given value

* @s: Pointer to the start of the area.

* @c: The byte to fill the area with

* @count: The size of the area.

*

* Do not use memset() to access IO space, use memset_io() instead.

*/

void * memset(void * s,int c,size_t count)

{

char *xs = (char *) s;

while (count--)

*xs++ = c;

return s;

}

#endif

#ifndef __HAVE_ARCH_BCOPY

/**

* bcopy - Copy one area of memory to another

* @src: Where to copy from

* @dest: Where to copy to

* @count: The size of the area.

*

* Note that this is the same as memcpy(), with the arguments reversed.

* memcpy() is the standard, bcopy() is a legacy BSD function.

*

* You should not use this function to access IO space, use memcpy_toio()

* or memcpy_fromio() instead.

*/

void bcopy(const void * srcp, void * destp, size_t count)

{

const char *src = srcp;

char *dest = destp;

while (count--)

*dest++ = *src++;

}

#endif

#ifndef __HAVE_ARCH_MEMCPY

/**

* memcpy - Copy one area of memory to another

* @dest: Where to copy to

* @src: Where to copy from

* @count: The size of the area.

*

* You should not use this function to access IO space, use memcpy_toio()

* or memcpy_fromio() instead.

*/

void * memcpy(void * dest,const void *src,size_t count)

{

char *tmp = (char *) dest, *s = (char *) src;

while (count--)

*tmp++ = *s++;

return dest;

}

#endif

#ifndef __HAVE_ARCH_MEMMOVE

/**

* memmove - Copy one area of memory to another

* @dest: Where to copy to

* @src: Where to copy from

* @count: The size of the area.

*

* Unlike memcpy(), memmove() copes with overlapping areas.

*/

void * memmove(void * dest,const void *src,size_t count)

{

char *tmp, *s;

if (dest <= src) {

tmp = (char *) dest;

s = (char *) src;

while (count--)

*tmp++ = *s++;

}

else {

tmp = (char *) dest + count;

s = (char *) src + count;

while (count--)

*--tmp = *--s;

}

return dest;

}

#endif

#ifndef __HAVE_ARCH_MEMCMP

/**

* memcmp - Compare two areas of memory

* @cs: One area of memory

* @ct: Another area of memory

* @count: The size of the area.

*/

int memcmp(const void * cs,const void * ct,size_t count)

{

const unsigned char *su1, *su2;

int res = 0;

for( su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)

if ((res = *su1 - *su2) != 0)

break;

return res;

}

#endif

#ifndef __HAVE_ARCH_MEMSCAN

/**

* memscan - Find a character in an area of memory.

* @addr: The memory area

* @c: The byte to search for

* @size: The size of the area.

*

* returns the address of the first occurrence of @c, or 1 byte past

* the area if @c is not found

*/

void * memscan(void * addr, int c, size_t size)

{

unsigned char * p = (unsigned char *) addr;

while (size) {

if (*p == c)

return (void *) p;

p++;

size--;

}

return (void *) p;

}

#endif

#ifndef __HAVE_ARCH_STRSTR

/**

* strstr - Find the first substring in a %NUL terminated string

* @s1: The string to be searched

* @s2: The string to search for

*/

char * strstr(const char * s1,const char * s2)

{

int l1, l2;

l2 = strlen(s2);

if (!l2)

return (char *) s1;

l1 = strlen(s1);

while (l1 >= l2) {

l1--;

if (!memcmp(s1,s2,l2))

return (char *) s1;

s1++;

}

return NULL;

}

#endif

#ifndef __HAVE_ARCH_MEMCHR

/**

* memchr - Find a character in an area of memory.

* @s: The memory area

* @c: The byte to search for

* @n: The size of the area.

*

* returns the address of the first occurrence of @c, or %NULL

* if @c is not found

*/

void *memchr(const void *s, int c, size_t n)

{

const unsigned char *p = s;

while (n-- != 0) {

if ((unsigned char)c == *p++) {

return (void *)(p-1);

}

}

return NULL;

}

#endif
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: