Line data Source code
1 : /*
2 : *
3 : * Copyright (c) 2020 Project CHIP Authors
4 : * All rights reserved.
5 : *
6 : * Licensed under the Apache License, Version 2.0 (the "License");
7 : * you may not use this file except in compliance with the License.
8 : * You may obtain a copy of the License at
9 : *
10 : * http://www.apache.org/licenses/LICENSE-2.0
11 : *
12 : * Unless required by applicable law or agreed to in writing, software
13 : * distributed under the License is distributed on an "AS IS" BASIS,
14 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 : * See the License for the specific language governing permissions and
16 : * limitations under the License.
17 : */
18 :
19 : /**
20 : * @file
21 : * This file defines string operations that allocate heap memory.
22 : */
23 :
24 : #pragma once
25 :
26 : #include <algorithm>
27 : #include <stdlib.h>
28 : #include <string.h>
29 :
30 : #include <lib/support/ScopedBuffer.h>
31 : #include <lib/support/Span.h>
32 :
33 : namespace chip {
34 : namespace Platform {
35 :
36 : /**
37 : * Copies a C-style string.
38 : *
39 : * This differs from `strncpy()` in some important ways:
40 : * - `dest` can be nullptr, in which case no copy is attempted, and the function returns nullptr.
41 : * - A non-nullptr result is always null-terminated.
42 : *
43 : * @param[in] dest Destination string buffer or nullptr.
44 : *
45 : * @param[in] destLength Maximum length to be copied. Will need space for null terminator as
46 : * well (string will be truncated if it does not fit). If 0 this method
47 : * is a noop.
48 : *
49 : * @param[in] source String to be copied.
50 : *
51 : * @retval Same as `dest`.
52 : */
53 6948 : inline void CopyString(char * dest, size_t destLength, const char * source)
54 : {
55 6948 : if (dest && destLength)
56 : {
57 6948 : strncpy(dest, source, destLength);
58 6948 : dest[destLength - 1] = 0;
59 : }
60 6948 : }
61 :
62 : /**
63 : * Convenience method for CopyString to auto-detect destination size.
64 : */
65 : template <size_t N>
66 7262 : inline void CopyString(char (&dest)[N], const char * source)
67 : {
68 7262 : CopyString(dest, N, source);
69 7262 : }
70 :
71 : /**
72 : * Creates a null-terminated string from a ByteSpan.
73 : * If dest is nullptr, no copy happens. Non-nullptr result is always null-terminated.
74 : *
75 : * @param[in] dest Destination string buffer or nullptr.
76 : *
77 : * @param[in] destLength Maximum length to be copied. Will need space for null terminator as
78 : * well (string will be truncated if it does not fit). If 0 this method
79 : * is a noop.
80 : *
81 : * @param[in] source Data to be copied.
82 : */
83 272 : inline void CopyString(char * dest, size_t destLength, ByteSpan source)
84 : {
85 272 : if (dest && destLength)
86 : {
87 272 : size_t maxChars = std::min(destLength - 1, source.size());
88 272 : memcpy(dest, source.data(), maxChars);
89 272 : dest[maxChars] = '\0';
90 : }
91 272 : }
92 :
93 : /**
94 : * Convenience method for CopyString to auto-detect destination size.
95 : */
96 : template <size_t N>
97 : inline void CopyString(char (&dest)[N], ByteSpan source)
98 : {
99 : CopyString(dest, N, source);
100 : }
101 :
102 : /**
103 : * Creates a null-terminated string from a CharSpan.
104 : * If dest is nullptr, no copy happens. Non-nullptr result is always null-terminated.
105 : *
106 : * @param[in] dest Destination string buffer or nullptr.
107 : *
108 : * @param[in] destLength Maximum length to be copied. Will need space for null terminator as
109 : * well (string will be truncated if it does not fit). If 0 this method
110 : * is a noop.
111 : *
112 : * @param[in] source Data to be copied.
113 : */
114 661 : inline void CopyString(char * dest, size_t destLength, CharSpan source)
115 : {
116 661 : if (dest && destLength)
117 : {
118 661 : size_t maxChars = std::min(destLength - 1, source.size());
119 661 : memcpy(dest, source.data(), maxChars);
120 661 : dest[maxChars] = '\0';
121 : }
122 661 : }
123 :
124 : /**
125 : * Convenience method for CopyString to auto-detect destination size.
126 : */
127 : template <size_t N>
128 657 : inline void CopyString(char (&dest)[N], CharSpan source)
129 : {
130 657 : CopyString(dest, N, source);
131 657 : }
132 :
133 : /**
134 : * This function copies a C-style string to memory newly allocated by Platform::MemoryAlloc().
135 : *
136 : * @param[in] string String to be copied.
137 : *
138 : * @param[in] length Length to be copied. Like `strncpy()`, if the `string` is shorter
139 : * than `length`, then the remaining space will be filled with null
140 : * bytes. Like `strndup()` but unlike `strncpy()`, the result is always
141 : * null-terminated.
142 : *
143 : * @retval Pointer to a null-terminated string in case of success.
144 : * @retval `nullptr` if memory allocation fails.
145 : *
146 : */
147 0 : inline char * MemoryAllocString(const char * string, size_t length)
148 : {
149 0 : size_t lengthWithNull = length + 1;
150 0 : char * result = static_cast<char *>(MemoryAlloc(lengthWithNull));
151 0 : CopyString(result, lengthWithNull, string);
152 0 : return result;
153 : }
154 :
155 : /**
156 : * Represents a C string in a ScopedMemoryBuffer.
157 : */
158 :
159 : class ScopedMemoryString : public ScopedMemoryBuffer<char>
160 : {
161 : public:
162 : /**
163 : * Create a ScopedMemoryString.
164 : *
165 : * @param[in] string String to be copied.
166 : *
167 : * @param[in] length Length to be copied. Like `strncpy()`, if the `string` is shorter than
168 : * `length`, then the remaining space will be filled with null bytes. Like
169 : * `strndup()` but unlike `strncpy()`, the result is always null-terminated.
170 : */
171 4 : ScopedMemoryString(const char * string, size_t length)
172 4 : {
173 4 : size_t lengthWithNull = length + 1;
174 :
175 : // We must convert the source string to a CharSpan, so we call the
176 : // version of CopyString that handles unterminated strings.
177 4 : CopyString(Alloc(lengthWithNull).Get(), lengthWithNull, CharSpan(string, length));
178 4 : }
179 : };
180 :
181 : } // namespace Platform
182 : } // namespace chip
|