1/* 2 * Copyright (c) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include "util/string_pool.h" 17#include "securec.h" 18#include "util/logger.h" 19 20namespace OHOS { 21namespace Idl { 22const char* StringPool::TAG = "StringPool"; 23 24StringPool::StringPool() 25{ 26 data_ = reinterpret_cast<char*>(calloc(1, dataCapacity_)); 27 if (data_ == nullptr) { 28 Logger::E(TAG, "Out of memory."); 29 } 30} 31 32StringPool::~StringPool() 33{ 34 if (data_ != nullptr) { 35 free(data_); 36 } 37} 38 39void StringPool::Add(const String& string) 40{ 41 if (string.IsEmpty() || stringOffsets_.find(string) != stringOffsets_.end()) { 42 return; 43 } 44 45 ptrdiff_t offset = AddInternal(string); 46 if (offset != -1) { 47 stringOffsets_[string] = offset; 48 } 49} 50 51ptrdiff_t StringPool::GetOffset(const String& string) 52{ 53 return stringOffsets_[string]; 54} 55 56ptrdiff_t StringPool::AddInternal(const String& string) 57{ 58 if (!Grow(string.GetLength() + 1)) { 59 return -1; 60 } 61 62 char* addr = data_ + dataOffset_; 63 if (strcpy_s(addr, dataCapacity_ - dataOffset_, string.string())) { 64 Logger::E(TAG, "Error to copy str"); 65 return -1; 66 } 67 dataOffset_ += string.GetLength() + 1; 68 return addr - data_; 69} 70 71bool StringPool::Grow(size_t expand) 72{ 73 size_t newSize = static_cast<size_t>(dataOffset_) + expand; 74 if (newSize < dataCapacity_) { 75 return true; 76 } 77 // 3->3x capacity expansion 78 size_t step = dataCapacity_ * 3; 79 newSize = step > newSize ? step : step + newSize; 80 char* newData = reinterpret_cast<char*>(calloc(1, newSize)); 81 if (newData == nullptr) { 82 Logger::E(TAG, "Out of memory."); 83 return false; 84 } 85 errno_t ret = memcpy_s(newData, newSize, data_, dataOffset_); 86 if (ret != EOK) { 87 free(newData); 88 newData = nullptr; 89 return false; 90 } 91 free(data_); 92 data_ = newData; 93 dataCapacity_ = newSize; 94 return true; 95} 96} 97} 98