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

Last change on this file was ea4910b, checked in by Jiri Svoboda <jiri@…>, 7 years ago

strdup(), strndup(), strnlen() are commonly used extensions so move them to libc (native ports can use these).

  • Property mode set to 100644
File size: 6.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 * Scan string for a first occurence of a character.
138 *
139 * @param s String in which to look for the character.
140 * @param c Character to look for.
141 * @return Pointer to the specified character on success, pointer to the
142 * string terminator otherwise.
143 */
144char *gnu_strchrnul(const char *s, int c)
145{
146 assert(s != NULL);
147
148 while (*s != c && *s != '\0') {
149 s++;
150 }
151
152 return (char *) s;
153}
154
155/** Split string by delimiters.
156 *
157 * @param s String to be tokenized. May not be NULL.
158 * @param delim String with the delimiters.
159 * @param next Variable which will receive the pointer to the
160 * continuation of the string following the first
161 * occurrence of any of the delimiter characters.
162 * May be NULL.
163 * @return Pointer to the prefix of @a s before the first
164 * delimiter character. NULL if no such prefix
165 * exists.
166 */
167char *strtok_r(char *s, const char *delim, char **next)
168{
169 return __strtok_r(s, delim, next);
170}
171
172/**
173 * Get error message string.
174 *
175 * @param errnum Error code for which to obtain human readable string.
176 * @param buf Buffer to store a human readable string to.
177 * @param bufsz Size of buffer pointed to by buf.
178 * @return Zero on success, errno otherwise.
179 */
180int strerror_r(int errnum, char *buf, size_t bufsz)
181{
182 assert(buf != NULL);
183
184 char *errstr = strerror(errnum);
185
186 if (strlen(errstr) + 1 > bufsz) {
187 return ERANGE;
188 } else {
189 strcpy(buf, errstr);
190 }
191
192 return EOK;
193}
194
195/**
196 * Get description of a signal.
197 *
198 * @param signum Signal number.
199 * @return Human readable signal description.
200 */
201char *strsignal(int signum)
202{
203 static const char *const sigstrings[] = {
204 [SIGABRT] = "SIGABRT (Process abort signal)",
205 [SIGALRM] = "SIGALRM (Alarm clock)",
206 [SIGBUS] = "SIGBUS (Access to an undefined portion of a memory object)",
207 [SIGCHLD] = "SIGCHLD (Child process terminated, stopped, or continued)",
208 [SIGCONT] = "SIGCONT (Continue executing, if stopped)",
209 [SIGFPE] = "SIGFPE (Erroneous arithmetic operation)",
210 [SIGHUP] = "SIGHUP (Hangup)",
211 [SIGILL] = "SIGILL (Illegal instruction)",
212 [SIGINT] = "SIGINT (Terminal interrupt signal)",
213 [SIGKILL] = "SIGKILL (Kill process)",
214 [SIGPIPE] = "SIGPIPE (Write on a pipe with no one to read it)",
215 [SIGQUIT] = "SIGQUIT (Terminal quit signal)",
216 [SIGSEGV] = "SIGSEGV (Invalid memory reference)",
217 [SIGSTOP] = "SIGSTOP (Stop executing)",
218 [SIGTERM] = "SIGTERM (Termination signal)",
219 [SIGTSTP] = "SIGTSTP (Terminal stop signal)",
220 [SIGTTIN] = "SIGTTIN (Background process attempting read)",
221 [SIGTTOU] = "SIGTTOU (Background process attempting write)",
222 [SIGUSR1] = "SIGUSR1 (User-defined signal 1)",
223 [SIGUSR2] = "SIGUSR2 (User-defined signal 2)",
224 [SIGPOLL] = "SIGPOLL (Pollable event)",
225 [SIGPROF] = "SIGPROF (Profiling timer expired)",
226 [SIGSYS] = "SIGSYS (Bad system call)",
227 [SIGTRAP] = "SIGTRAP (Trace/breakpoint trap)",
228 [SIGURG] = "SIGURG (High bandwidth data is available at a socket)",
229 [SIGVTALRM] = "SIGVTALRM (Virtual timer expired)",
230 [SIGXCPU] = "SIGXCPU (CPU time limit exceeded)",
231 [SIGXFSZ] = "SIGXFSZ (File size limit exceeded)"
232 };
233
234 if (signum <= _TOP_SIGNAL) {
235 return (char *) sigstrings[signum];
236 }
237
238 return (char *) "ERROR, Invalid signal number";
239}
240
241/** @}
242 */
Note: See TracBrowser for help on using the repository browser.