解讀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_ */ 
*/ 
/* 
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 <[email protected]
* - 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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章