/* * * Copyright (c) 2020 Project CHIP Authors * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * @file * This file defines string operations that allocate heap memory. */ #pragma once #include #include #include #include #include namespace chip { namespace Platform { /** * Copies a C-style string. * * This differs from `strncpy()` in some important ways: * - `dest` can be nullptr, in which case no copy is attempted, and the function returns nullptr. * - A non-nullptr result is always null-terminated. * * @param[in] dest Destination string buffer or nullptr. * * @param[in] destLength Maximum length to be copied. Will need space for null terminator as * well (string will be truncated if it does not fit). If 0 this method * is a noop. * * @param[in] source String to be copied. * * @retval Same as `dest`. */ inline void CopyString(char * dest, size_t destLength, const char * source) { if (dest && destLength) { strncpy(dest, source, destLength); dest[destLength - 1] = 0; } } /** * Convenience method for CopyString to auto-detect destination size. */ template inline void CopyString(char (&dest)[N], const char * source) { CopyString(dest, N, source); } /** * Creates a null-terminated string from a ByteSpan. * If dest is nullptr, no copy happens. Non-nullptr result is always null-terminated. * * @param[in] dest Destination string buffer or nullptr. * * @param[in] destLength Maximum length to be copied. Will need space for null terminator as * well (string will be truncated if it does not fit). If 0 this method * is a noop. * * @param[in] source Data to be copied. */ inline void CopyString(char * dest, size_t destLength, ByteSpan source) { if ((dest == nullptr) || (destLength == 0)) { return; // no space to copy anything, not even a null terminator } if (source.empty()) { *dest = '\0'; // just a null terminator, we are copying empty data return; } size_t maxChars = std::min(destLength - 1, source.size()); memcpy(dest, source.data(), maxChars); dest[maxChars] = '\0'; } /** * Convenience method for CopyString to auto-detect destination size. */ template inline void CopyString(char (&dest)[N], ByteSpan source) { CopyString(dest, N, source); } /** * Creates a null-terminated string from a CharSpan. * If dest is nullptr, no copy happens. Non-nullptr result is always null-terminated. * * @param[in] dest Destination string buffer or nullptr. * * @param[in] destLength Maximum length to be copied. Will need space for null terminator as * well (string will be truncated if it does not fit). If 0 this method * is a noop. * * @param[in] source Data to be copied. */ inline void CopyString(char * dest, size_t destLength, CharSpan source) { if ((dest == nullptr) || (destLength == 0)) { return; // no space to copy anything, not even a null terminator } if (source.empty()) { *dest = '\0'; // just a null terminator, we are copying empty data return; } size_t maxChars = std::min(destLength - 1, source.size()); memcpy(dest, source.data(), maxChars); dest[maxChars] = '\0'; } /** * Convenience method for CopyString to auto-detect destination size. */ template inline void CopyString(char (&dest)[N], CharSpan source) { CopyString(dest, N, source); } /** * This function copies a C-style string to memory newly allocated by Platform::MemoryAlloc(). * * @param[in] string String to be copied. * * @param[in] length Length to be copied. Like `strncpy()`, if the `string` is shorter * than `length`, then the remaining space will be filled with null * bytes. Like `strndup()` but unlike `strncpy()`, the result is always * null-terminated. * * @retval Pointer to a null-terminated string in case of success. * @retval `nullptr` if memory allocation fails. * */ inline char * MemoryAllocString(const char * string, size_t length) { size_t lengthWithNull = length + 1; char * result = static_cast(MemoryAlloc(lengthWithNull)); CopyString(result, lengthWithNull, string); return result; } /** * Represents a C string in a ScopedMemoryBuffer. */ class ScopedMemoryString : public ScopedMemoryBuffer { public: /** * Create a ScopedMemoryString. * * @param[in] string String to be copied. * * @param[in] length Length to be copied. Like `strncpy()`, if the `string` is shorter than * `length`, then the remaining space will be filled with null bytes. Like * `strndup()` but unlike `strncpy()`, the result is always null-terminated. */ ScopedMemoryString(const char * string, size_t length) { size_t lengthWithNull = length + 1; // We must convert the source string to a CharSpan, so we call the // version of CopyString that handles unterminated strings. CopyString(Alloc(lengthWithNull).Get(), lengthWithNull, CharSpan(string, length)); } }; } // namespace Platform } // namespace chip