Subversion Repositories HelenOS

Rev

Rev 4179 | Rev 4198 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 4179 Rev 4196
1
/*
1
/*
2
 * Copyright (c) 2001-2004 Jakub Jermar
2
 * Copyright (c) 2001-2004 Jakub Jermar
3
 * All rights reserved.
3
 * All rights reserved.
4
 *
4
 *
5
 * Redistribution and use in source and binary forms, with or without
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
6
 * modification, are permitted provided that the following conditions
7
 * are met:
7
 * are met:
8
 *
8
 *
9
 * - Redistributions of source code must retain the above copyright
9
 * - Redistributions of source code must retain the above copyright
10
 *   notice, this list of conditions and the following disclaimer.
10
 *   notice, this list of conditions and the following disclaimer.
11
 * - Redistributions in binary form must reproduce the above copyright
11
 * - Redistributions in binary form must reproduce the above copyright
12
 *   notice, this list of conditions and the following disclaimer in the
12
 *   notice, this list of conditions and the following disclaimer in the
13
 *   documentation and/or other materials provided with the distribution.
13
 *   documentation and/or other materials provided with the distribution.
14
 * - The name of the author may not be used to endorse or promote products
14
 * - The name of the author may not be used to endorse or promote products
15
 *   derived from this software without specific prior written permission.
15
 *   derived from this software without specific prior written permission.
16
 *
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
 */
27
 */
28
 
28
 
29
/** @addtogroup generic
29
/** @addtogroup generic
30
 * @{
30
 * @{
31
 */
31
 */
32
 
32
 
33
/**
33
/**
34
 * @file
34
 * @file
35
 * @brief Miscellaneous functions.
35
 * @brief Miscellaneous functions.
36
 */
36
 */
37
 
37
 
38
#include <string.h>
38
#include <string.h>
39
#include <print.h>
39
#include <print.h>
40
#include <cpu.h>
40
#include <cpu.h>
41
#include <arch/asm.h>
41
#include <arch/asm.h>
42
#include <arch.h>
42
#include <arch.h>
43
#include <console/kconsole.h>
43
#include <console/kconsole.h>
44
 
44
 
45
char invalch = '?';
45
char invalch = '?';
46
 
46
 
-
 
47
/** Byte mask consisting of bits 0 - (@n - 1) */
-
 
48
#define LO_MASK_8(n) ((uint8_t)((1 << (n)) - 1))
-
 
49
 
-
 
50
/** Number of data bits in a UTF-8 continuation byte. */
-
 
51
#define CONT_BITS 6
-
 
52
 
47
/** Decode a single UTF-8 character from a NULL-terminated string.
53
/** Decode a single UTF-8 character from a NULL-terminated string.
48
 *
54
 *
49
 * Decode a single UTF-8 character from a plain char NULL-terminated
55
 * Decode a single UTF-8 character from a plain char NULL-terminated
50
 * string. Decoding starts at @index and this index is incremented
56
 * string. Decoding starts at @index and this index is incremented
51
 * if the current UTF-8 string is encoded in more than a single byte.
57
 * if the current UTF-8 string is encoded in more than a single byte.
52
 *
58
 *
53
 * @param str   Plain character NULL-terminated string.
59
 * @param str   Plain character NULL-terminated string.
54
 * @param index Index (counted in plain characters) where to start
60
 * @param index Index (counted in plain characters) where to start
55
 *              the decoding.
61
 *              the decoding.
56
 * @param limit Maximal allowed value of index.
62
 * @param limit Maximal allowed value of index.
57
 *
63
 *
58
 * @return Decoded character in UTF-32 or '?' if the encoding is wrong.
64
 * @return Decoded character in UTF-32 or '?' if the encoding is wrong.
59
 *
65
 *
60
 */
66
 */
61
wchar_t utf8_decode(const char *str, index_t *index, index_t limit)
67
wchar_t utf8_decode(const char *str, index_t *index, index_t limit)
62
{
68
{
63
    uint8_t c1;           /* First plain character from str */
69
    uint8_t b0, b;          /* Bytes read from str. */
64
    uint8_t c2;           /* Second plain character from str */
70
    wchar_t ch;
-
 
71
 
65
    uint8_t c3;           /* Third plain character from str */
72
    int b0_bits;        /* Data bits in first byte. */
66
    uint8_t c4;           /* Fourth plain character from str */
73
    int cbytes;     /* Number of continuation bytes. */
67
   
74
 
68
    if (*index > limit)
75
    if (*index > limit)
69
        return invalch;
76
        return invalch;
70
   
77
 
71
    c1 = (uint8_t) str[*index];
78
    b0 = (uint8_t) str[*index];
72
   
79
 
73
    if ((c1 & 0x80) == 0) {
-
 
74
        /* Plain ASCII (code points 0 .. 127) */
80
    /* Determine code length. */
75
        return (wchar_t) c1;
-
 
76
    }
-
 
77
   
81
 
78
    if ((c1 & 0xe0) == 0xc0) {
82
    if ((b0 & 0x80) == 0) {
79
        /* Code points 128 .. 2047 */
83
        /* 0xxxxxxx (Plain ASCII) */
-
 
84
        b0_bits = 7;
-
 
85
        cbytes = 0;
-
 
86
    } else if ((b0 & 0xe0) == 0xc0) {
80
        if (*index + 1 > limit)
87
        /* 110xxxxx 10xxxxxx */
-
 
88
        b0_bits = 5;
-
 
89
        cbytes = 1;
-
 
90
    } else if ((b0 & 0xf0) == 0xe0) {
-
 
91
        /* 1110xxxx 10xxxxxx 10xxxxxx */
-
 
92
        b0_bits = 4;
-
 
93
        cbytes = 2;
-
 
94
    } else if ((b0 & 0xf8) == 0xf0) {
-
 
95
        /* 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
-
 
96
        b0_bits = 3;
-
 
97
        cbytes = 3;
-
 
98
    } else {
-
 
99
        /* 10xxxxxx -- unexpected continuation byte. */
81
            return invalch;
100
        return invalch;
-
 
101
    }
82
       
102
 
83
        c2 = (uint8_t) str[*index + 1];
-
 
84
        if ((c2 & 0xc0) == 0x80) {
103
    if (*index + cbytes > limit) {
85
            (*index)++;
-
 
86
            return ((wchar_t) ((c1 & 0x1f) << 6) | (c2 & 0x3f));
-
 
87
        } else
-
 
88
            return invalch;
104
        return invalch;
89
    }
105
    }
90
   
106
 
91
    if ((c1 & 0xf0) == 0xe0) {
107
    ch = b0 & LO_MASK_8(b0_bits);
92
        /* Code points 2048 .. 65535 */
-
 
93
        if (*index + 2 > limit)
-
 
94
            return invalch;
-
 
95
       
108
 
96
        c2 = (uint8_t) str[*index + 1];
109
    /* Decode continuation bytes. */
97
        if ((c2 & 0xc0) == 0x80) {
110
    while (cbytes > 0) {
98
            (*index)++;
-
 
99
            c3 = (uint8_t) str[*index + 1];
111
        b = (uint8_t) str[*index + 1];
100
            if ((c3 & 0xc0) == 0x80) {
-
 
101
                (*index)++;
112
        ++(*index);
102
                return ((wchar_t) ((c1 & 0x0f) << 12) | ((c2 & 0x3f) << 6) | (c3 & 0x3f));
-
 
103
            } else
-
 
104
                return invalch;
-
 
105
        } else
-
 
106
            return invalch;
-
 
107
    }
-
 
108
   
113
 
109
    if ((c1 & 0xf8) == 0xf0) {
-
 
110
        /* Code points 65536 .. 1114111 */
114
        /* Must be 10xxxxxx. */
111
        if (*index + 3 > limit)
115
        if ((b & 0xc0) != 0x80) {
112
            return invalch;
116
            return invalch;
-
 
117
        }
113
       
118
 
114
        c2 = (uint8_t) str[*index + 1];
119
        /* Shift data bits to ch. */
115
        if ((c2 & 0xc0) == 0x80) {
-
 
116
            (*index)++;
-
 
117
            c3 = (uint8_t) str[*index + 1];
-
 
118
            if ((c3 & 0xc0) == 0x80) {
-
 
119
                (*index)++;
-
 
120
                c4 = (uint8_t) str[*index + 1];
-
 
121
                if ((c4 & 0xc0) == 0x80) {
-
 
122
                    (*index)++;
-
 
123
                    return ((wchar_t) ((c1 & 0x07) << 18) | ((c2 & 0x3f) << 12) | ((c3 & 0x3f) << 6) | (c4 & 0x3f));
120
        ch = (ch << CONT_BITS) | (wchar_t) (b & LO_MASK_8(CONT_BITS));
124
                } else
121
        --cbytes;
125
                    return invalch;
-
 
126
            } else
-
 
127
                return invalch;
-
 
128
        } else
-
 
129
            return invalch;
-
 
130
    }
122
    }
131
   
123
 
132
    return invalch;
124
    return ch;
133
}
125
}
134
 
126
 
135
/** Encode a single UTF-32 character as UTF-8
127
/** Encode a single UTF-32 character as UTF-8
136
 *
128
 *
137
 * Encode a single UTF-32 character as UTF-8 and store it into
129
 * Encode a single UTF-32 character as UTF-8 and store it into
138
 * the given buffer at @index. Encoding starts at @index and
130
 * the given buffer at @index. Encoding starts at @index and
139
 * this index is incremented if the UTF-8 character takes
131
 * this index is incremented if the UTF-8 character takes
140
 * more than a single byte.
132
 * more than a single byte.
141
 *
133
 *
142
 * @param ch    Input UTF-32 character.
134
 * @param ch    Input UTF-32 character.
143
 * @param str   Output buffer.
135
 * @param str   Output buffer.
144
 * @param index Index (counted in plain characters) where to start
136
 * @param index Index (counted in plain characters) where to start
145
 *              the encoding
137
 *              the encoding
146
 * @param limit Maximal allowed value of index.
138
 * @param limit Maximal allowed value of index.
147
 *
139
 *
148
 * @return True if the character was encoded or false if there is not
140
 * @return True if the character was encoded or false if there is not
149
 *         enought space in the output buffer or the character is invalid
141
 *         enought space in the output buffer or the character is invalid
150
 *         Unicode code point.
142
 *         Unicode code point.
151
 *
143
 *
152
 */
144
 */
153
bool utf8_encode(const wchar_t ch, char *str, index_t *index, index_t limit)
145
bool utf8_encode(const wchar_t ch, char *str, index_t *index, index_t limit)
154
{
146
{
155
    if (*index > limit)
147
    if (*index > limit)
156
        return false;
148
        return false;
157
   
149
   
158
    if ((ch >= 0) && (ch <= 127)) {
150
    if ((ch >= 0) && (ch <= 127)) {
159
        /* Plain ASCII (code points 0 .. 127) */
151
        /* Plain ASCII (code points 0 .. 127) */
160
        str[*index] = ch & 0x7f;
152
        str[*index] = ch & 0x7f;
161
        return true;
153
        return true;
162
    }
154
    }
163
   
155
   
164
    if ((ch >= 128) && (ch <= 2047)) {
156
    if ((ch >= 128) && (ch <= 2047)) {
165
        /* Code points 128 .. 2047 */
157
        /* Code points 128 .. 2047 */
166
        if (*index + 1 > limit)
158
        if (*index + 1 > limit)
167
            return false;
159
            return false;
168
       
160
       
169
        str[*index] = 0xc0 | ((ch >> 6) & 0x1f);
161
        str[*index] = 0xc0 | ((ch >> 6) & 0x1f);
170
        (*index)++;
162
        (*index)++;
171
        str[*index] = 0x80 | (ch & 0x3f);
163
        str[*index] = 0x80 | (ch & 0x3f);
172
        return true;
164
        return true;
173
    }
165
    }
174
   
166
   
175
    if ((ch >= 2048) && (ch <= 65535)) {
167
    if ((ch >= 2048) && (ch <= 65535)) {
176
        /* Code points 2048 .. 65535 */
168
        /* Code points 2048 .. 65535 */
177
        if (*index + 2 > limit)
169
        if (*index + 2 > limit)
178
            return false;
170
            return false;
179
       
171
       
180
        str[*index] = 0xe0 | ((ch >> 12) & 0x0f);
172
        str[*index] = 0xe0 | ((ch >> 12) & 0x0f);
181
        (*index)++;
173
        (*index)++;
182
        str[*index] = 0x80 | ((ch >> 6) & 0x3f);
174
        str[*index] = 0x80 | ((ch >> 6) & 0x3f);
183
        (*index)++;
175
        (*index)++;
184
        str[*index] = 0x80 | (ch & 0x3f);
176
        str[*index] = 0x80 | (ch & 0x3f);
185
        return true;
177
        return true;
186
    }
178
    }
187
   
179
   
188
    if ((ch >= 65536) && (ch <= 1114111)) {
180
    if ((ch >= 65536) && (ch <= 1114111)) {
189
        /* Code points 65536 .. 1114111 */
181
        /* Code points 65536 .. 1114111 */
190
        if (*index + 3 > limit)
182
        if (*index + 3 > limit)
191
            return false;
183
            return false;
192
       
184
       
193
        str[*index] = 0xf0 | ((ch >> 18) & 0x07);
185
        str[*index] = 0xf0 | ((ch >> 18) & 0x07);
194
        (*index)++;
186
        (*index)++;
195
        str[*index] = 0x80 | ((ch >> 12) & 0x3f);
187
        str[*index] = 0x80 | ((ch >> 12) & 0x3f);
196
        (*index)++;
188
        (*index)++;
197
        str[*index] = 0x80 | ((ch >> 6) & 0x3f);
189
        str[*index] = 0x80 | ((ch >> 6) & 0x3f);
198
        (*index)++;
190
        (*index)++;
199
        str[*index] = 0x80 | (ch & 0x3f);
191
        str[*index] = 0x80 | (ch & 0x3f);
200
        return true;
192
        return true;
201
    }
193
    }
202
   
194
   
203
    return false;
195
    return false;
204
}
196
}
205
 
197
 
206
/** Get bytes used by UTF-8 characters.
198
/** Get bytes used by UTF-8 characters.
207
 *
199
 *
208
 * Get the number of bytes (count of plain characters) which
200
 * Get the number of bytes (count of plain characters) which
209
 * are used by a given count of UTF-8 characters in a string.
201
 * are used by a given count of UTF-8 characters in a string.
210
 * As UTF-8 encoding is multibyte, there is no constant
202
 * As UTF-8 encoding is multibyte, there is no constant
211
 * correspondence between number of characters and used bytes.
203
 * correspondence between number of characters and used bytes.
212
 *
204
 *
213
 * @param str   UTF-8 string to consider.
205
 * @param str   UTF-8 string to consider.
214
 * @param count Number of UTF-8 characters to count.
206
 * @param count Number of UTF-8 characters to count.
215
 *
207
 *
216
 * @return Number of bytes used by the characters.
208
 * @return Number of bytes used by the characters.
217
 *
209
 *
218
 */
210
 */
219
size_t utf8_count_bytes(const char *str, count_t count)
211
size_t utf8_count_bytes(const char *str, count_t count)
220
{
212
{
221
    size_t size = 0;
213
    size_t size = 0;
222
    index_t index = 0;
214
    index_t index = 0;
223
   
215
   
224
    while ((utf8_decode(str, &index, UTF8_NO_LIMIT) != 0) && (size < count)) {
216
    while ((utf8_decode(str, &index, UTF8_NO_LIMIT) != 0) && (size < count)) {
225
        size++;
217
        size++;
226
        index++;
218
        index++;
227
    }
219
    }
228
   
220
   
229
    return index;
221
    return index;
230
}
222
}
231
 
223
 
232
/** Check whether character is plain ASCII.
224
/** Check whether character is plain ASCII.
233
 *
225
 *
234
 * @return True if character is plain ASCII.
226
 * @return True if character is plain ASCII.
235
 *
227
 *
236
 */
228
 */
237
bool ascii_check(const wchar_t ch)
229
bool ascii_check(const wchar_t ch)
238
{
230
{
239
    if ((ch >= 0) && (ch <= 127))
231
    if ((ch >= 0) && (ch <= 127))
240
        return true;
232
        return true;
241
   
233
   
242
    return false;
234
    return false;
243
}
235
}
244
 
236
 
245
/** Check whether character is Unicode.
237
/** Check whether character is Unicode.
246
 *
238
 *
247
 * @return True if character is valid Unicode code point.
239
 * @return True if character is valid Unicode code point.
248
 *
240
 *
249
 */
241
 */
250
bool unicode_check(const wchar_t ch)
242
bool unicode_check(const wchar_t ch)
251
{
243
{
252
    if ((ch >= 0) && (ch <= 1114111))
244
    if ((ch >= 0) && (ch <= 1114111))
253
        return true;
245
        return true;
254
   
246
   
255
    return false;
247
    return false;
256
}
248
}
257
 
249
 
258
/** Return number of plain characters in a string.
250
/** Return number of plain characters in a string.
259
 *
251
 *
260
 * @param str NULL-terminated string.
252
 * @param str NULL-terminated string.
261
 *
253
 *
262
 * @return Number of characters in str.
254
 * @return Number of characters in str.
263
 *
255
 *
264
 */
256
 */
265
size_t strlen(const char *str)
257
size_t strlen(const char *str)
266
{
258
{
267
    size_t size;
259
    size_t size;
268
    for (size = 0; str[size]; size++);
260
    for (size = 0; str[size]; size++);
269
   
261
   
270
    return size;
262
    return size;
271
}
263
}
272
 
264
 
273
/** Return number of UTF-8 characters in a string.
265
/** Return number of UTF-8 characters in a string.
274
 *
266
 *
275
 * @param str NULL-terminated UTF-8 string.
267
 * @param str NULL-terminated UTF-8 string.
276
 *
268
 *
277
 * @return Number of UTF-8 characters in str.
269
 * @return Number of UTF-8 characters in str.
278
 *
270
 *
279
 */
271
 */
280
size_t strlen_utf8(const char *str)
272
size_t strlen_utf8(const char *str)
281
{
273
{
282
    size_t size = 0;
274
    size_t size = 0;
283
    index_t index = 0;
275
    index_t index = 0;
284
   
276
   
285
    while (utf8_decode(str, &index, UTF8_NO_LIMIT) != 0) {
277
    while (utf8_decode(str, &index, UTF8_NO_LIMIT) != 0) {
286
        size++;
278
        size++;
287
        index++;
279
        index++;
288
    }
280
    }
289
   
281
   
290
    return size;
282
    return size;
291
}
283
}
292
 
284
 
293
/** Return number of UTF-32 characters in a string.
285
/** Return number of UTF-32 characters in a string.
294
 *
286
 *
295
 * @param str NULL-terminated UTF-32 string.
287
 * @param str NULL-terminated UTF-32 string.
296
 *
288
 *
297
 * @return Number of UTF-32 characters in str.
289
 * @return Number of UTF-32 characters in str.
298
 *
290
 *
299
 */
291
 */
300
size_t strlen_utf32(const wchar_t *str)
292
size_t strlen_utf32(const wchar_t *str)
301
{
293
{
302
    size_t size;
294
    size_t size;
303
    for (size = 0; str[size]; size++);
295
    for (size = 0; str[size]; size++);
304
   
296
   
305
    return size;
297
    return size;
306
}
298
}
307
 
299
 
308
/** Compare two NULL terminated strings
300
/** Compare two NULL terminated strings
309
 *
301
 *
310
 * Do a char-by-char comparison of two NULL terminated strings.
302
 * Do a char-by-char comparison of two NULL terminated strings.
311
 * The strings are considered equal iff they consist of the same
303
 * The strings are considered equal iff they consist of the same
312
 * characters on the minimum of their lengths.
304
 * characters on the minimum of their lengths.
313
 *
305
 *
314
 * @param src First string to compare.
306
 * @param src First string to compare.
315
 * @param dst Second string to compare.
307
 * @param dst Second string to compare.
316
 *
308
 *
317
 * @return 0 if the strings are equal, -1 if first is smaller, 1 if second smaller.
309
 * @return 0 if the strings are equal, -1 if first is smaller, 1 if second smaller.
318
 *
310
 *
319
 */
311
 */
320
int strcmp(const char *src, const char *dst)
312
int strcmp(const char *src, const char *dst)
321
{
313
{
322
    for (; *src && *dst; src++, dst++) {
314
    for (; *src && *dst; src++, dst++) {
323
        if (*src < *dst)
315
        if (*src < *dst)
324
            return -1;
316
            return -1;
325
        if (*src > *dst)
317
        if (*src > *dst)
326
            return 1;
318
            return 1;
327
    }
319
    }
328
    if (*src == *dst)
320
    if (*src == *dst)
329
        return 0;
321
        return 0;
330
   
322
   
331
    if (!*src)
323
    if (!*src)
332
        return -1;
324
        return -1;
333
   
325
   
334
    return 1;
326
    return 1;
335
}
327
}
336
 
328
 
337
 
329
 
338
/** Compare two NULL terminated strings
330
/** Compare two NULL terminated strings
339
 *
331
 *
340
 * Do a char-by-char comparison of two NULL terminated strings.
332
 * Do a char-by-char comparison of two NULL terminated strings.
341
 * The strings are considered equal iff they consist of the same
333
 * The strings are considered equal iff they consist of the same
342
 * characters on the minimum of their lengths and specified maximal
334
 * characters on the minimum of their lengths and specified maximal
343
 * length.
335
 * length.
344
 *
336
 *
345
 * @param src First string to compare.
337
 * @param src First string to compare.
346
 * @param dst Second string to compare.
338
 * @param dst Second string to compare.
347
 * @param len Maximal length for comparison.
339
 * @param len Maximal length for comparison.
348
 *
340
 *
349
 * @return 0 if the strings are equal, -1 if first is smaller, 1 if second smaller.
341
 * @return 0 if the strings are equal, -1 if first is smaller, 1 if second smaller.
350
 *
342
 *
351
 */
343
 */
352
int strncmp(const char *src, const char *dst, size_t len)
344
int strncmp(const char *src, const char *dst, size_t len)
353
{
345
{
354
    unsigned int i;
346
    unsigned int i;
355
   
347
   
356
    for (i = 0; (*src) && (*dst) && (i < len); src++, dst++, i++) {
348
    for (i = 0; (*src) && (*dst) && (i < len); src++, dst++, i++) {
357
        if (*src < *dst)
349
        if (*src < *dst)
358
            return -1;
350
            return -1;
359
       
351
       
360
        if (*src > *dst)
352
        if (*src > *dst)
361
            return 1;
353
            return 1;
362
    }
354
    }
363
   
355
   
364
    if (i == len || *src == *dst)
356
    if (i == len || *src == *dst)
365
        return 0;
357
        return 0;
366
   
358
   
367
    if (!*src)
359
    if (!*src)
368
        return -1;
360
        return -1;
369
   
361
   
370
    return 1;
362
    return 1;
371
}
363
}
372
 
364
 
373
 
365
 
374
 
366
 
375
/** Copy NULL terminated string.
367
/** Copy NULL terminated string.
376
 *
368
 *
377
 * Copy at most 'len' characters from string 'src' to 'dest'.
369
 * Copy at most 'len' characters from string 'src' to 'dest'.
378
 * If 'src' is shorter than 'len', '\0' is inserted behind the
370
 * If 'src' is shorter than 'len', '\0' is inserted behind the
379
 * last copied character.
371
 * last copied character.
380
 *
372
 *
381
 * @param src  Source string.
373
 * @param src  Source string.
382
 * @param dest Destination buffer.
374
 * @param dest Destination buffer.
383
 * @param len  Size of destination buffer.
375
 * @param len  Size of destination buffer.
384
 *
376
 *
385
 */
377
 */
386
void strncpy(char *dest, const char *src, size_t len)
378
void strncpy(char *dest, const char *src, size_t len)
387
{
379
{
388
    unsigned int i;
380
    unsigned int i;
389
   
381
   
390
    for (i = 0; i < len; i++) {
382
    for (i = 0; i < len; i++) {
391
        if (!(dest[i] = src[i]))
383
        if (!(dest[i] = src[i]))
392
            return;
384
            return;
393
    }
385
    }
394
   
386
   
395
    dest[i - 1] = '\0';
387
    dest[i - 1] = '\0';
396
}
388
}
397
 
389
 
398
/** Find first occurence of character in string.
390
/** Find first occurence of character in string.
399
 *
391
 *
400
 * @param s String to search.
392
 * @param s String to search.
401
 * @param i Character to look for.
393
 * @param i Character to look for.
402
 *
394
 *
403
 * @return Pointer to character in @a s or NULL if not found.
395
 * @return Pointer to character in @a s or NULL if not found.
404
 */
396
 */
405
extern char *strchr(const char *s, int i)
397
extern char *strchr(const char *s, int i)
406
{
398
{
407
    while (*s != '\0') {
399
    while (*s != '\0') {
408
        if (*s == i)
400
        if (*s == i)
409
            return (char *) s;
401
            return (char *) s;
410
        ++s;
402
        ++s;
411
    }
403
    }
412
   
404
   
413
    return NULL;
405
    return NULL;
414
}
406
}
415
 
407
 
416
/** @}
408
/** @}
417
 */
409
 */
418
 
410