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
RevLine 
[7bb9b53]1/*
2 * Copyright (c) 2011 Petr Koupy
3 * Copyright (c) 2011 Jiri Zarevucky
[99d3123]4 * Copyright (c) 2018 Jiri Svoboda
[7bb9b53]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 */
[5273eb6]34/** @file String manipulation.
[7bb9b53]35 */
36
[a6d908c1]37#include "internal/common.h"
[9b8be79]38#include <string.h>
[7bb9b53]39
[e8d3c6f5]40#include <assert.h>
[0d0b319]41
42#include <errno.h>
43
[9b8be79]44#include <limits.h>
45#include <stdlib.h>
46#include <signal.h>
47#include <str.h>
48#include <str_error.h>
[a6d908c1]49
[7bb9b53]50/**
[5273eb6]51 * Copy a string.
[7bb9b53]52 *
[5273eb6]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.
[7bb9b53]56 */
[7f9df7b9]57char *stpcpy(char *restrict dest, const char *restrict src)
[7bb9b53]58{
[ef6dd3f]59 assert(dest != NULL);
60 assert(src != NULL);
61
[4f4b4e7]62 for (size_t i = 0; ; ++i) {
[ef6dd3f]63 dest[i] = src[i];
[a35b458]64
[ef6dd3f]65 if (src[i] == '\0') {
66 /* pointer to the terminating nul character */
67 return &dest[i];
68 }
69 }
[a35b458]70
[ef6dd3f]71 /* unreachable */
72 return NULL;
[7bb9b53]73}
74
75/**
[5273eb6]76 * Copy fixed length string.
[7bb9b53]77 *
[5273eb6]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].
[7bb9b53]82 */
[7f9df7b9]83char *stpncpy(char *restrict dest, const char *restrict src, size_t n)
[7bb9b53]84{
[ef6dd3f]85 assert(dest != NULL);
86 assert(src != NULL);
87
[4f4b4e7]88 for (size_t i = 0; i < n; ++i) {
[ef6dd3f]89 dest[i] = src[i];
[a35b458]90
[7c3fb9b]91 /*
92 * the standard requires that nul characters
[ef6dd3f]93 * are appended to the length of n, in case src is shorter
94 */
95 if (src[i] == '\0') {
96 char *result = &dest[i];
[4f4b4e7]97 for (++i; i < n; ++i) {
[ef6dd3f]98 dest[i] = '\0';
99 }
100 return result;
101 }
102 }
[a35b458]103
[ef6dd3f]104 return &dest[n];
[7bb9b53]105}
106
107/**
[5273eb6]108 * Copy limited number of bytes in memory.
[7bb9b53]109 *
[5273eb6]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.
[ef6dd3f]114 * @return Pointer to the first byte after c in dest if found, NULL otherwise.
[7bb9b53]115 */
[7f9df7b9]116void *memccpy(void *restrict dest, const void *restrict src, int c, size_t n)
[7bb9b53]117{
[ef6dd3f]118 assert(dest != NULL);
119 assert(src != NULL);
[a35b458]120
[1433ecda]121 unsigned char *bdest = dest;
122 const unsigned char *bsrc = src;
[a35b458]123
[4f4b4e7]124 for (size_t i = 0; i < n; ++i) {
[ef6dd3f]125 bdest[i] = bsrc[i];
[a35b458]126
[ef6dd3f]127 if (bsrc[i] == (unsigned char) c) {
128 /* pointer to the next byte */
129 return &bdest[i + 1];
130 }
131 }
[a35b458]132
[ef6dd3f]133 return NULL;
[7bb9b53]134}
135
[5273eb6]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 */
[517cedc0]144char *gnu_strchrnul(const char *s, int c)
145{
146 assert(s != NULL);
[a35b458]147
[517cedc0]148 while (*s != c && *s != '\0') {
149 s++;
150 }
[a35b458]151
[517cedc0]152 return (char *) s;
153}
154
[12b29f3]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 */
[7f9df7b9]167char *strtok_r(char *s, const char *delim, char **next)
[12b29f3]168{
[99d3123]169 return __strtok_r(s, delim, next);
[ef6dd3f]170}
171
172/**
[5273eb6]173 * Get error message string.
[ef6dd3f]174 *
[5273eb6]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.
[ef6dd3f]179 */
[7f9df7b9]180int strerror_r(int errnum, char *buf, size_t bufsz)
[ef6dd3f]181{
182 assert(buf != NULL);
[a35b458]183
[7f9df7b9]184 char *errstr = strerror(errnum);
[a35b458]185
[7f9df7b9]186 if (strlen(errstr) + 1 > bufsz) {
[1b55da67]187 return ERANGE;
[ef6dd3f]188 } else {
[7f9df7b9]189 strcpy(buf, errstr);
[ef6dd3f]190 }
191
[0d0b319]192 return EOK;
[7bb9b53]193}
194
[d3ce33fa]195/**
[5273eb6]196 * Get description of a signal.
[d3ce33fa]197 *
[5273eb6]198 * @param signum Signal number.
199 * @return Human readable signal description.
[d3ce33fa]200 */
[7f9df7b9]201char *strsignal(int signum)
[d3ce33fa]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
[7bb9b53]241/** @}
242 */
Note: See TracBrowser for help on using the repository browser.