/* * * Copyright (c) 2021-2022 Project CHIP Authors * * 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. */ #include "AppPreference.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ErrorUtils.h" using chip::DeviceLayer::Internal::TizenToChipError; namespace chip { namespace DeviceLayer { namespace PersistedStorage { namespace Internal { namespace AppPreference { CHIP_ERROR CheckData(const char * key) { bool isExist = false; int err = preference_is_existing(key, &isExist); VerifyOrReturnError(err == PREFERENCE_ERROR_NONE, CHIP_ERROR_INCORRECT_STATE); return isExist ? CHIP_NO_ERROR : CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND; } CHIP_ERROR GetData(const char * key, void * data, size_t dataSize, size_t * getDataSize, size_t offset) { VerifyOrReturnError(data != nullptr, CHIP_ERROR_INVALID_ARGUMENT); char * encodedData = nullptr; // Make sure that string allocated by preference_get_string() will be freed std::unique_ptr _{ encodedData, &::free }; int err = preference_get_string(key, &encodedData); if (err != PREFERENCE_ERROR_NONE) { if (err != PREFERENCE_ERROR_NO_KEY) ChipLogError(DeviceLayer, "Failed to get preference [%s]: %s", StringOrNullMarker(key), get_error_message(err)); return TizenToChipError(err); } size_t encodedDataSize = strlen(encodedData); Platform::ScopedMemoryBuffer decodedData; size_t expectedMaxDecodedSize = BASE64_MAX_DECODED_LEN(encodedDataSize); VerifyOrReturnError(decodedData.Alloc(expectedMaxDecodedSize), CHIP_ERROR_NO_MEMORY); size_t decodedDataSize = Base64Decode(encodedData, static_cast(encodedDataSize), decodedData.Get()); VerifyOrReturnError(dataSize >= decodedDataSize - offset, CHIP_ERROR_BUFFER_TOO_SMALL); size_t copySize = std::min(dataSize, decodedDataSize - offset); if (getDataSize != nullptr) { *getDataSize = copySize; } ::memcpy(data, decodedData.Get() + offset, copySize); ChipLogDetail(DeviceLayer, "Get preference data: key=%s len=%u", key, static_cast(copySize)); ChipLogByteSpan(DeviceLayer, ByteSpan(reinterpret_cast(data), copySize)); return CHIP_NO_ERROR; } CHIP_ERROR SaveData(const char * key, const void * data, size_t dataSize) { // Expected size for null-terminated base64 string size_t expectedEncodedSize = BASE64_ENCODED_LEN(dataSize) + 1; Platform::ScopedMemoryBuffer encodedData; VerifyOrReturnError(encodedData.Alloc(expectedEncodedSize), CHIP_ERROR_NO_MEMORY); size_t encodedDataSize = Base64Encode(static_cast(data), static_cast(dataSize), encodedData.Get()); encodedData[encodedDataSize] = '\0'; int err = preference_set_string(key, encodedData.Get()); VerifyOrReturnError( err == PREFERENCE_ERROR_NONE, TizenToChipError(err), ChipLogError(DeviceLayer, "Failed to set preference [%s]: %s", StringOrNullMarker(key), get_error_message(err))); ChipLogDetail(DeviceLayer, "Save preference data: key=%s len=%u", key, static_cast(dataSize)); ChipLogByteSpan(DeviceLayer, ByteSpan(reinterpret_cast(data), dataSize)); return CHIP_NO_ERROR; } CHIP_ERROR RemoveData(const char * key) { int err = preference_remove(key); if (err != PREFERENCE_ERROR_NONE) { if (err != PREFERENCE_ERROR_NO_KEY) ChipLogError(DeviceLayer, "Failed to remove preference [%s]: %s", StringOrNullMarker(key), get_error_message(err)); return TizenToChipError(err); } ChipLogProgress(DeviceLayer, "Remove preference data: key=%s", key); return CHIP_NO_ERROR; } } // namespace AppPreference } // namespace Internal } // namespace PersistedStorage } // namespace DeviceLayer } // namespace chip