forked from KolibriOS/kolibrios
string manipulation routines for drivers and kernel
enable global page support after paging git-svn-id: svn://kolibrios.org@519 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
187
kernel/trunk/core/string.inc
Normal file
187
kernel/trunk/core/string.inc
Normal file
@@ -0,0 +1,187 @@
|
||||
$Revision: 431 $
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; ;;
|
||||
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
|
||||
;; Distributed under terms of the GNU General Public License ;;
|
||||
;; Author: Kees J. Bot 1 Jan 1994 ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
|
||||
; size_t strncat(char *s1, const char *s2, size_t n)
|
||||
; Append string s2 to s1.
|
||||
|
||||
; char *strchr(const char *s, int c)
|
||||
|
||||
|
||||
; int strncmp(const char *s1, const char *s2, size_t n)
|
||||
; Compare two strings.
|
||||
|
||||
; char *strncpy(char *s1, const char *s2, size_t n)
|
||||
; Copy string s2 to s1.
|
||||
|
||||
; size_t strnlen(const char *s, size_t n)
|
||||
; Return the length of a string.
|
||||
|
||||
; proc strrchr stdcall, s:dword, c:dword
|
||||
; Look for the last occurrence a character in a string.
|
||||
|
||||
proc strncat stdcall, s1:dword, s2:dword, n:dword
|
||||
push esi
|
||||
push edi
|
||||
mov edi, [s1] ; String s1
|
||||
mov edx, [n] ; Maximum length
|
||||
|
||||
mov ecx, -1
|
||||
xor al, al ; Null byte
|
||||
cld
|
||||
repne scasb ; Look for the zero byte in s1
|
||||
dec edi ; Back one up (and clear 'Z' flag)
|
||||
push edi ; Save end of s1
|
||||
mov edi, [s2] ; edi = string s2
|
||||
mov ecx, edx ; Maximum count
|
||||
repne scasb ; Look for the end of s2
|
||||
jne @F
|
||||
inc ecx ; Exclude null byte
|
||||
@@:
|
||||
sub edx, ecx ; Number of bytes in s2
|
||||
mov ecx, edx
|
||||
mov esi, [s2] ; esi = string s2
|
||||
pop edi ; edi = end of string s1
|
||||
rep movsb ; Copy bytes
|
||||
stosb ; Add a terminating null
|
||||
mov eax, [s1] ; Return s1
|
||||
pop edi
|
||||
pop esi
|
||||
ret
|
||||
endp
|
||||
|
||||
align 4
|
||||
proc strncmp stdcall, s1:dword, s2:dword, n:dword
|
||||
|
||||
push esi
|
||||
push edi
|
||||
mov ecx, [n]
|
||||
test ecx, ecx ; Max length is zero?
|
||||
je .done
|
||||
|
||||
mov esi, [s1] ; esi = string s1
|
||||
mov edi, [s2] ; edi = string s2
|
||||
cld
|
||||
.compare:
|
||||
cmpsb ; Compare two bytes
|
||||
jne .done
|
||||
cmp byte [esi-1], 0 ; End of string?
|
||||
je .done
|
||||
dec ecx ; Length limit reached?
|
||||
jne .compare
|
||||
.done:
|
||||
seta al ; al = (s1 > s2)
|
||||
setb ah ; ah = (s1 < s2)
|
||||
sub al, ah
|
||||
movsx eax, al ; eax = (s1 > s2) - (s1 < s2), i.e. -1, 0, 1
|
||||
pop edi
|
||||
pop esi
|
||||
ret
|
||||
endp
|
||||
|
||||
align 4
|
||||
proc strncpy stdcall, s1:dword, s2:dword, n:dword
|
||||
|
||||
push esi
|
||||
push edi
|
||||
|
||||
mov ecx, [n] ; Maximum length
|
||||
mov edi, [s2] ; edi = string s2
|
||||
xor al, al ; Look for a zero byte
|
||||
mov edx, ecx ; Save maximum count
|
||||
cld
|
||||
repne scasb ; Look for end of s2
|
||||
sub edx, ecx ; Number of bytes in s2 including null
|
||||
xchg ecx, edx
|
||||
mov esi, [s2] ; esi = string s2
|
||||
mov edi, [s1] ; edi = string s1
|
||||
rep movsb ; Copy bytes
|
||||
|
||||
mov ecx, edx ; Number of bytes not copied
|
||||
rep stosb ; strncpy always copies n bytes by null padding
|
||||
mov eax, [s1] ; Return s1
|
||||
pop edi
|
||||
pop esi
|
||||
ret
|
||||
endp
|
||||
|
||||
align 4
|
||||
proc strnlen stdcall, s:dword, n:dword
|
||||
|
||||
push edi
|
||||
mov edi, [s] ; edi = string
|
||||
xor al, al ; Look for a zero byte
|
||||
mov edx, ecx ; Save maximum count
|
||||
cmp cl, 1 ; 'Z' bit must be clear if ecx = 0
|
||||
cld
|
||||
repne scasb ; Look for zero
|
||||
jne @F
|
||||
inc ecx ; Don't count zero byte
|
||||
@@:
|
||||
mov eax, edx
|
||||
sub eax, ecx ; Compute bytes scanned
|
||||
pop edi
|
||||
ret
|
||||
endp
|
||||
|
||||
align 4
|
||||
proc strchr stdcall, s:dword, c:dword
|
||||
push edi
|
||||
cld
|
||||
mov edi, [s] ; edi = string
|
||||
mov edx, 16 ; Look at small chunks of the string
|
||||
.next:
|
||||
shl edx, 1 ; Chunks become bigger each time
|
||||
mov ecx, edx
|
||||
xor al, al ; Look for the zero at the end
|
||||
repne scasb
|
||||
pushf ; Remember the flags
|
||||
sub ecx, edx
|
||||
neg ecx ; Some or all of the chunk
|
||||
sub edi, ecx ; Step back
|
||||
mov eax, [c] ; The character to look for
|
||||
repne scasb
|
||||
je .found
|
||||
popf ; Did we find the end of string earlier?
|
||||
jne .next ; No, try again
|
||||
xor eax, eax ; Return NULL
|
||||
pop edi
|
||||
ret
|
||||
.found:
|
||||
pop eax ; Get rid of those flags
|
||||
lea eax, [edi-1] ; Address of byte found
|
||||
pop edi
|
||||
ret
|
||||
|
||||
endp
|
||||
|
||||
|
||||
proc strrchr stdcall, s:dword, c:dword
|
||||
push edi
|
||||
mov edi, [s] ; edi = string
|
||||
mov ecx, -1
|
||||
xor al, al
|
||||
cld
|
||||
repne scasb ; Look for the end of the string
|
||||
not ecx ; -1 - ecx = Length of the string + null
|
||||
dec edi ; Put edi back on the zero byte
|
||||
mov eax, [c] ; The character to look for
|
||||
std ; Downwards search
|
||||
repne scasb
|
||||
cld ; Direction bit back to default
|
||||
jne .fail
|
||||
lea eax, [edi+1] ; Found it
|
||||
pop edi
|
||||
ret
|
||||
.fail:
|
||||
xor eax, eax ; Not there
|
||||
pop edi
|
||||
ret
|
||||
endp
|
||||
|
||||
|
Reference in New Issue
Block a user