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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since c483fca was 9b8be79, checked in by Jiří Zárevúcky <jiri.zarevucky@…>, 7 years ago

libposix: Change header organization and remove passthrough headers

Posix headers now function like an overlay. The system include directories
are searched after posix directories. The headers don't need to be patched
for export now. libposix files now include headers using bracket notation
instead of quoted notation.

  • Property mode set to 100644
File size: 7.8 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 <string.h>
39
40#include <assert.h>
41
42#include <errno.h>
43
44#include <limits.h>
45#include <stdlib.h>
46#include <signal.h>
47#include <str.h>
48#include <str_error.h>
49
50/**
51 * Copy a string.
52 *
53 * @param dest Destination pre-allocated buffer.
54 * @param src Source string to be copied.
55 * @return Pointer to the nul character in the destination string.
56 */
57char *stpcpy(char *restrict dest, const char *restrict src)
58{
59 assert(dest != NULL);
60 assert(src != NULL);
61
62 for (size_t i = 0; ; ++i) {
63 dest[i] = src[i];
64
65 if (src[i] == '\0') {
66 /* pointer to the terminating nul character */
67 return &dest[i];
68 }
69 }
70
71 /* unreachable */
72 return NULL;
73}
74
75/**
76 * Copy fixed length string.
77 *
78 * @param dest Destination pre-allocated buffer.
79 * @param src Source string to be copied.
80 * @param n Number of bytes to be stored into destination buffer.
81 * @return Pointer to the first written nul character or &dest[n].
82 */
83char *stpncpy(char *restrict dest, const char *restrict src, size_t n)
84{
85 assert(dest != NULL);
86 assert(src != NULL);
87
88 for (size_t i = 0; i < n; ++i) {
89 dest[i] = src[i];
90
91 /*
92 * the standard requires that nul characters
93 * are appended to the length of n, in case src is shorter
94 */
95 if (src[i] == '\0') {
96 char *result = &dest[i];
97 for (++i; i < n; ++i) {
98 dest[i] = '\0';
99 }
100 return result;
101 }
102 }
103
104 return &dest[n];
105}
106
107/**
108 * Copy limited number of bytes in memory.
109 *
110 * @param dest Destination buffer.
111 * @param src Source buffer.
112 * @param c Character after which the copying shall stop.
113 * @param n Number of bytes that shall be copied if not stopped earlier by c.
114 * @return Pointer to the first byte after c in dest if found, NULL otherwise.
115 */
116void *memccpy(void *restrict dest, const void *restrict src, int c, size_t n)
117{
118 assert(dest != NULL);
119 assert(src != NULL);
120
121 unsigned char *bdest = dest;
122 const unsigned char *bsrc = src;
123
124 for (size_t i = 0; i < n; ++i) {
125 bdest[i] = bsrc[i];
126
127 if (bsrc[i] == (unsigned char) c) {
128 /* pointer to the next byte */
129 return &bdest[i + 1];
130 }
131 }
132
133 return NULL;
134}
135
136/**
137 * Duplicate a string.
138 *
139 * @param s String to be duplicated.
140 * @return Newly allocated copy of the string.
141 */
142char *strdup(const char *s)
143{
144 return strndup(s, SIZE_MAX);
145}
146
147/**
148 * Duplicate a specific number of bytes from a string.
149 *
150 * @param s String to be duplicated.
151 * @param n Maximum length of the resulting string..
152 * @return Newly allocated string copy of length at most n.
153 */
154char *strndup(const char *s, size_t n)
155{
156 assert(s != NULL);
157
158 size_t len = strnlen(s, n);
159 char *dup = malloc(len + 1);
160 if (dup == NULL) {
161 return NULL;
162 }
163
164 memcpy(dup, s, len);
165 dup[len] = '\0';
166
167 return dup;
168}
169
170/**
171 * Scan string for a first occurence of a character.
172 *
173 * @param s String in which to look for the character.
174 * @param c Character to look for.
175 * @return Pointer to the specified character on success, pointer to the
176 * string terminator otherwise.
177 */
178char *gnu_strchrnul(const char *s, int c)
179{
180 assert(s != NULL);
181
182 while (*s != c && *s != '\0') {
183 s++;
184 }
185
186 return (char *) s;
187}
188
189/** Split string by delimiters.
190 *
191 * @param s String to be tokenized. May not be NULL.
192 * @param delim String with the delimiters.
193 * @param next Variable which will receive the pointer to the
194 * continuation of the string following the first
195 * occurrence of any of the delimiter characters.
196 * May be NULL.
197 * @return Pointer to the prefix of @a s before the first
198 * delimiter character. NULL if no such prefix
199 * exists.
200 */
201char *strtok_r(char *s, const char *delim, char **next)
202{
203 return __strtok_r(s, delim, next);
204}
205
206/**
207 * Get error message string.
208 *
209 * @param errnum Error code for which to obtain human readable string.
210 * @param buf Buffer to store a human readable string to.
211 * @param bufsz Size of buffer pointed to by buf.
212 * @return Zero on success, errno otherwise.
213 */
214int strerror_r(int errnum, char *buf, size_t bufsz)
215{
216 assert(buf != NULL);
217
218 char *errstr = strerror(errnum);
219
220 if (strlen(errstr) + 1 > bufsz) {
221 return ERANGE;
222 } else {
223 strcpy(buf, errstr);
224 }
225
226 return EOK;
227}
228
229/**
230 * Get limited length of the string.
231 *
232 * @param s String which length shall be determined.
233 * @param n Maximum number of bytes that can be examined to determine length.
234 * @return The lower of either string length or n limit.
235 */
236size_t strnlen(const char *s, size_t n)
237{
238 assert(s != NULL);
239
240 for (size_t sz = 0; sz < n; ++sz) {
241
242 if (s[sz] == '\0') {
243 return sz;
244 }
245 }
246
247 return n;
248}
249
250/**
251 * Get description of a signal.
252 *
253 * @param signum Signal number.
254 * @return Human readable signal description.
255 */
256char *strsignal(int signum)
257{
258 static const char *const sigstrings[] = {
259 [SIGABRT] = "SIGABRT (Process abort signal)",
260 [SIGALRM] = "SIGALRM (Alarm clock)",
261 [SIGBUS] = "SIGBUS (Access to an undefined portion of a memory object)",
262 [SIGCHLD] = "SIGCHLD (Child process terminated, stopped, or continued)",
263 [SIGCONT] = "SIGCONT (Continue executing, if stopped)",
264 [SIGFPE] = "SIGFPE (Erroneous arithmetic operation)",
265 [SIGHUP] = "SIGHUP (Hangup)",
266 [SIGILL] = "SIGILL (Illegal instruction)",
267 [SIGINT] = "SIGINT (Terminal interrupt signal)",
268 [SIGKILL] = "SIGKILL (Kill process)",
269 [SIGPIPE] = "SIGPIPE (Write on a pipe with no one to read it)",
270 [SIGQUIT] = "SIGQUIT (Terminal quit signal)",
271 [SIGSEGV] = "SIGSEGV (Invalid memory reference)",
272 [SIGSTOP] = "SIGSTOP (Stop executing)",
273 [SIGTERM] = "SIGTERM (Termination signal)",
274 [SIGTSTP] = "SIGTSTP (Terminal stop signal)",
275 [SIGTTIN] = "SIGTTIN (Background process attempting read)",
276 [SIGTTOU] = "SIGTTOU (Background process attempting write)",
277 [SIGUSR1] = "SIGUSR1 (User-defined signal 1)",
278 [SIGUSR2] = "SIGUSR2 (User-defined signal 2)",
279 [SIGPOLL] = "SIGPOLL (Pollable event)",
280 [SIGPROF] = "SIGPROF (Profiling timer expired)",
281 [SIGSYS] = "SIGSYS (Bad system call)",
282 [SIGTRAP] = "SIGTRAP (Trace/breakpoint trap)",
283 [SIGURG] = "SIGURG (High bandwidth data is available at a socket)",
284 [SIGVTALRM] = "SIGVTALRM (Virtual timer expired)",
285 [SIGXCPU] = "SIGXCPU (CPU time limit exceeded)",
286 [SIGXFSZ] = "SIGXFSZ (File size limit exceeded)"
287 };
288
289 if (signum <= _TOP_SIGNAL) {
290 return (char *) sigstrings[signum];
291 }
292
293 return (char *) "ERROR, Invalid signal number";
294}
295
296/** @}
297 */
Note: See TracBrowser for help on using the repository browser.