Rev 593 | Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
519 | serge | 1 | $Revision: 431 $ |
2 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
||
3 | ;; ;; |
||
4 | ;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
||
5 | ;; Distributed under terms of the GNU General Public License ;; |
||
6 | ;; Author: Kees J. Bot 1 Jan 1994 ;; |
||
7 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
||
8 | |||
9 | |||
10 | ; size_t strncat(char *s1, const char *s2, size_t n) |
||
11 | ; Append string s2 to s1. |
||
12 | |||
13 | ; char *strchr(const char *s, int c) |
||
14 | |||
15 | |||
16 | ; int strncmp(const char *s1, const char *s2, size_t n) |
||
17 | ; Compare two strings. |
||
18 | |||
19 | ; char *strncpy(char *s1, const char *s2, size_t n) |
||
20 | ; Copy string s2 to s1. |
||
21 | |||
22 | ; size_t strnlen(const char *s, size_t n) |
||
23 | ; Return the length of a string. |
||
24 | |||
25 | ; proc strrchr stdcall, s:dword, c:dword |
||
26 | ; Look for the last occurrence a character in a string. |
||
27 | |||
28 | proc strncat stdcall, s1:dword, s2:dword, n:dword |
||
29 | push esi |
||
30 | push edi |
||
31 | mov edi, [s1] ; String s1 |
||
32 | mov edx, [n] ; Maximum length |
||
33 | |||
34 | mov ecx, -1 |
||
35 | xor al, al ; Null byte |
||
36 | cld |
||
37 | repne scasb ; Look for the zero byte in s1 |
||
38 | dec edi ; Back one up (and clear 'Z' flag) |
||
39 | push edi ; Save end of s1 |
||
40 | mov edi, [s2] ; edi = string s2 |
||
41 | mov ecx, edx ; Maximum count |
||
42 | repne scasb ; Look for the end of s2 |
||
43 | jne @F |
||
44 | inc ecx ; Exclude null byte |
||
45 | @@: |
||
46 | sub edx, ecx ; Number of bytes in s2 |
||
47 | mov ecx, edx |
||
48 | mov esi, [s2] ; esi = string s2 |
||
49 | pop edi ; edi = end of string s1 |
||
50 | rep movsb ; Copy bytes |
||
51 | stosb ; Add a terminating null |
||
52 | mov eax, [s1] ; Return s1 |
||
53 | pop edi |
||
54 | pop esi |
||
55 | ret |
||
56 | endp |
||
57 | |||
58 | align 4 |
||
59 | proc strncmp stdcall, s1:dword, s2:dword, n:dword |
||
60 | |||
61 | push esi |
||
62 | push edi |
||
63 | mov ecx, [n] |
||
64 | test ecx, ecx ; Max length is zero? |
||
65 | je .done |
||
66 | |||
67 | mov esi, [s1] ; esi = string s1 |
||
68 | mov edi, [s2] ; edi = string s2 |
||
69 | cld |
||
70 | .compare: |
||
71 | cmpsb ; Compare two bytes |
||
72 | jne .done |
||
73 | cmp byte [esi-1], 0 ; End of string? |
||
74 | je .done |
||
75 | dec ecx ; Length limit reached? |
||
76 | jne .compare |
||
77 | .done: |
||
78 | seta al ; al = (s1 > s2) |
||
79 | setb ah ; ah = (s1 < s2) |
||
80 | sub al, ah |
||
81 | movsx eax, al ; eax = (s1 > s2) - (s1 < s2), i.e. -1, 0, 1 |
||
82 | pop edi |
||
83 | pop esi |
||
84 | ret |
||
85 | endp |
||
86 | |||
87 | align 4 |
||
88 | proc strncpy stdcall, s1:dword, s2:dword, n:dword |
||
89 | |||
90 | push esi |
||
91 | push edi |
||
92 | |||
93 | mov ecx, [n] ; Maximum length |
||
94 | mov edi, [s2] ; edi = string s2 |
||
95 | xor al, al ; Look for a zero byte |
||
96 | mov edx, ecx ; Save maximum count |
||
97 | cld |
||
98 | repne scasb ; Look for end of s2 |
||
99 | sub edx, ecx ; Number of bytes in s2 including null |
||
100 | xchg ecx, edx |
||
101 | mov esi, [s2] ; esi = string s2 |
||
102 | mov edi, [s1] ; edi = string s1 |
||
103 | rep movsb ; Copy bytes |
||
104 | |||
105 | mov ecx, edx ; Number of bytes not copied |
||
106 | rep stosb ; strncpy always copies n bytes by null padding |
||
107 | mov eax, [s1] ; Return s1 |
||
108 | pop edi |
||
109 | pop esi |
||
110 | ret |
||
111 | endp |
||
112 | |||
113 | align 4 |
||
114 | proc strnlen stdcall, s:dword, n:dword |
||
115 | |||
116 | push edi |
||
117 | mov edi, [s] ; edi = string |
||
118 | xor al, al ; Look for a zero byte |
||
119 | mov edx, ecx ; Save maximum count |
||
120 | cmp cl, 1 ; 'Z' bit must be clear if ecx = 0 |
||
121 | cld |
||
122 | repne scasb ; Look for zero |
||
123 | jne @F |
||
124 | inc ecx ; Don't count zero byte |
||
125 | @@: |
||
126 | mov eax, edx |
||
127 | sub eax, ecx ; Compute bytes scanned |
||
128 | pop edi |
||
129 | ret |
||
130 | endp |
||
131 | |||
132 | align 4 |
||
133 | proc strchr stdcall, s:dword, c:dword |
||
134 | push edi |
||
135 | cld |
||
136 | mov edi, [s] ; edi = string |
||
137 | mov edx, 16 ; Look at small chunks of the string |
||
138 | .next: |
||
139 | shl edx, 1 ; Chunks become bigger each time |
||
140 | mov ecx, edx |
||
141 | xor al, al ; Look for the zero at the end |
||
142 | repne scasb |
||
143 | pushf ; Remember the flags |
||
144 | sub ecx, edx |
||
145 | neg ecx ; Some or all of the chunk |
||
146 | sub edi, ecx ; Step back |
||
147 | mov eax, [c] ; The character to look for |
||
148 | repne scasb |
||
149 | je .found |
||
150 | popf ; Did we find the end of string earlier? |
||
151 | jne .next ; No, try again |
||
152 | xor eax, eax ; Return NULL |
||
153 | pop edi |
||
154 | ret |
||
155 | .found: |
||
156 | pop eax ; Get rid of those flags |
||
157 | lea eax, [edi-1] ; Address of byte found |
||
158 | pop edi |
||
159 | ret |
||
160 | |||
161 | endp |
||
162 | |||
163 | |||
164 | proc strrchr stdcall, s:dword, c:dword |
||
165 | push edi |
||
166 | mov edi, [s] ; edi = string |
||
167 | mov ecx, -1 |
||
168 | xor al, al |
||
169 | cld |
||
170 | repne scasb ; Look for the end of the string |
||
171 | not ecx ; -1 - ecx = Length of the string + null |
||
172 | dec edi ; Put edi back on the zero byte |
||
173 | mov eax, [c] ; The character to look for |
||
174 | std ; Downwards search |
||
175 | repne scasb |
||
176 | cld ; Direction bit back to default |
||
177 | jne .fail |
||
178 | lea eax, [edi+1] ; Found it |
||
179 | pop edi |
||
180 | ret |
||
181 | .fail: |
||
182 | xor eax, eax ; Not there |
||
183 | pop edi |
||
184 | ret |
||
185 | endp>> |
||
186 |