source: mainline/uspace/lib/posix/src/string.c@ 09ab0a9a

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 09ab0a9a was 99d3123, checked in by Jiri Svoboda <jiri@…>, 7 years ago

libc needs a string.h (for the outside users, at least).

  • Property mode set to 100644
File size: 7.9 KB
Line 
1/*
2 * Copyright (c) 2011 Petr Koupy
3 * Copyright (c) 2011 Jiri Zarevucky
4 * Copyright (c) 2018 Jiri Svoboda
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * - Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * - Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * - The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31/** @addtogroup libposix
32 * @{
33 */
34/** @file String manipulation.
35 */
36
37#include "internal/common.h"
38#include "posix/string.h"
39
40#include <assert.h>
41
42#include <errno.h>
43
44#include "posix/limits.h"
45#include "posix/stdlib.h"
46#include "posix/signal.h"
47
48#include "libc/str.h"
49#include "libc/str_error.h"
50
51/**
52 * Copy a string.
53 *
54 * @param dest Destination pre-allocated buffer.
55 * @param src Source string to be copied.
56 * @return Pointer to the nul character in the destination string.
57 */
58char *stpcpy(char *restrict dest, const char *restrict src)
59{
60 assert(dest != NULL);
61 assert(src != NULL);
62
63 for (size_t i = 0; ; ++i) {
64 dest[i] = src[i];
65
66 if (src[i] == '\0') {
67 /* pointer to the terminating nul character */
68 return &dest[i];
69 }
70 }
71
72 /* unreachable */
73 return NULL;
74}
75
76/**
77 * Copy fixed length string.
78 *
79 * @param dest Destination pre-allocated buffer.
80 * @param src Source string to be copied.
81 * @param n Number of bytes to be stored into destination buffer.
82 * @return Pointer to the first written nul character or &dest[n].
83 */
84char *stpncpy(char *restrict dest, const char *restrict src, size_t n)
85{
86 assert(dest != NULL);
87 assert(src != NULL);
88
89 for (size_t i = 0; i < n; ++i) {
90 dest[i] = src[i];
91
92 /*
93 * the standard requires that nul characters
94 * are appended to the length of n, in case src is shorter
95 */
96 if (src[i] == '\0') {
97 char *result = &dest[i];
98 for (++i; i < n; ++i) {
99 dest[i] = '\0';
100 }
101 return result;
102 }
103 }
104
105 return &dest[n];
106}
107
108/**
109 * Copy limited number of bytes in memory.
110 *
111 * @param dest Destination buffer.
112 * @param src Source buffer.
113 * @param c Character after which the copying shall stop.
114 * @param n Number of bytes that shall be copied if not stopped earlier by c.
115 * @return Pointer to the first byte after c in dest if found, NULL otherwise.
116 */
117void *memccpy(void *restrict dest, const void *restrict src, int c, size_t n)
118{
119 assert(dest != NULL);
120 assert(src != NULL);
121
122 unsigned char *bdest = dest;
123 const unsigned char *bsrc = src;
124
125 for (size_t i = 0; i < n; ++i) {
126 bdest[i] = bsrc[i];
127
128 if (bsrc[i] == (unsigned char) c) {
129 /* pointer to the next byte */
130 return &bdest[i + 1];
131 }
132 }
133
134 return NULL;
135}
136
137/**
138 * Duplicate a string.
139 *
140 * @param s String to be duplicated.
141 * @return Newly allocated copy of the string.
142 */
143char *strdup(const char *s)
144{
145 return strndup(s, SIZE_MAX);
146}
147
148/**
149 * Duplicate a specific number of bytes from a string.
150 *
151 * @param s String to be duplicated.
152 * @param n Maximum length of the resulting string..
153 * @return Newly allocated string copy of length at most n.
154 */
155char *strndup(const char *s, size_t n)
156{
157 assert(s != NULL);
158
159 size_t len = strnlen(s, n);
160 char *dup = malloc(len + 1);
161 if (dup == NULL) {
162 return NULL;
163 }
164
165 memcpy(dup, s, len);
166 dup[len] = '\0';
167
168 return dup;
169}
170
171/**
172 * Scan string for a first occurence of a character.
173 *
174 * @param s String in which to look for the character.
175 * @param c Character to look for.
176 * @return Pointer to the specified character on success, pointer to the
177 * string terminator otherwise.
178 */
179char *gnu_strchrnul(const char *s, int c)
180{
181 assert(s != NULL);
182
183 while (*s != c && *s != '\0') {
184 s++;
185 }
186
187 return (char *) s;
188}
189
190/** Split string by delimiters.
191 *
192 * @param s String to be tokenized. May not be NULL.
193 * @param delim String with the delimiters.
194 * @param next Variable which will receive the pointer to the
195 * continuation of the string following the first
196 * occurrence of any of the delimiter characters.
197 * May be NULL.
198 * @return Pointer to the prefix of @a s before the first
199 * delimiter character. NULL if no such prefix
200 * exists.
201 */
202char *strtok_r(char *s, const char *delim, char **next)
203{
204 return __strtok_r(s, delim, next);
205}
206
207/**
208 * Get error message string.
209 *
210 * @param errnum Error code for which to obtain human readable string.
211 * @param buf Buffer to store a human readable string to.
212 * @param bufsz Size of buffer pointed to by buf.
213 * @return Zero on success, errno otherwise.
214 */
215int strerror_r(int errnum, char *buf, size_t bufsz)
216{
217 assert(buf != NULL);
218
219 char *errstr = strerror(errnum);
220
221 if (strlen(errstr) + 1 > bufsz) {
222 return ERANGE;
223 } else {
224 strcpy(buf, errstr);
225 }
226
227 return EOK;
228}
229
230/**
231 * Get limited length of the string.
232 *
233 * @param s String which length shall be determined.
234 * @param n Maximum number of bytes that can be examined to determine length.
235 * @return The lower of either string length or n limit.
236 */
237size_t strnlen(const char *s, size_t n)
238{
239 assert(s != NULL);
240
241 for (size_t sz = 0; sz < n; ++sz) {
242
243 if (s[sz] == '\0') {
244 return sz;
245 }
246 }
247
248 return n;
249}
250
251/**
252 * Get description of a signal.
253 *
254 * @param signum Signal number.
255 * @return Human readable signal description.
256 */
257char *strsignal(int signum)
258{
259 static const char *const sigstrings[] = {
260 [SIGABRT] = "SIGABRT (Process abort signal)",
261 [SIGALRM] = "SIGALRM (Alarm clock)",
262 [SIGBUS] = "SIGBUS (Access to an undefined portion of a memory object)",
263 [SIGCHLD] = "SIGCHLD (Child process terminated, stopped, or continued)",
264 [SIGCONT] = "SIGCONT (Continue executing, if stopped)",
265 [SIGFPE] = "SIGFPE (Erroneous arithmetic operation)",
266 [SIGHUP] = "SIGHUP (Hangup)",
267 [SIGILL] = "SIGILL (Illegal instruction)",
268 [SIGINT] = "SIGINT (Terminal interrupt signal)",
269 [SIGKILL] = "SIGKILL (Kill process)",
270 [SIGPIPE] = "SIGPIPE (Write on a pipe with no one to read it)",
271 [SIGQUIT] = "SIGQUIT (Terminal quit signal)",
272 [SIGSEGV] = "SIGSEGV (Invalid memory reference)",
273 [SIGSTOP] = "SIGSTOP (Stop executing)",
274 [SIGTERM] = "SIGTERM (Termination signal)",
275 [SIGTSTP] = "SIGTSTP (Terminal stop signal)",
276 [SIGTTIN] = "SIGTTIN (Background process attempting read)",
277 [SIGTTOU] = "SIGTTOU (Background process attempting write)",
278 [SIGUSR1] = "SIGUSR1 (User-defined signal 1)",
279 [SIGUSR2] = "SIGUSR2 (User-defined signal 2)",
280 [SIGPOLL] = "SIGPOLL (Pollable event)",
281 [SIGPROF] = "SIGPROF (Profiling timer expired)",
282 [SIGSYS] = "SIGSYS (Bad system call)",
283 [SIGTRAP] = "SIGTRAP (Trace/breakpoint trap)",
284 [SIGURG] = "SIGURG (High bandwidth data is available at a socket)",
285 [SIGVTALRM] = "SIGVTALRM (Virtual timer expired)",
286 [SIGXCPU] = "SIGXCPU (CPU time limit exceeded)",
287 [SIGXFSZ] = "SIGXFSZ (File size limit exceeded)"
288 };
289
290 if (signum <= _TOP_SIGNAL) {
291 return (char *) sigstrings[signum];
292 }
293
294 return (char *) "ERROR, Invalid signal number";
295}
296
297/** @}
298 */
Note: See TracBrowser for help on using the repository browser.