* Copyright (c) 2024 Huawei Device Co., Ltd.
* 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 "oh_preferences_value.h"
#include "log_print.h"
#include "oh_preferences_err_code.h"
#include "oh_preferences_impl.h"
#include "oh_preferences_value_impl.h"
#include "securec.h"
using namespace OHOS::PreferencesNdk;
static OH_PreferencesValueImpl *GetSelf(const OH_PreferencesValue *value)
{
if (value == nullptr ||
!NDKPreferencesUtils::PreferencesStructValidCheck(
value->cid, PreferencesNdkStructId::PREFERENCES_OH_VALUE_CID)) {
LOG_ERROR("preferences_value invalid, value is null: %{public}d", (value == nullptr));
return nullptr;
}
OH_PreferencesValue *prefValue = const_cast<OH_PreferencesValue *>(value);
return static_cast<OH_PreferencesValueImpl *>(prefValue);
}
const char *OH_PreferencesPair_GetKey(const OH_PreferencesPair *pairs, uint32_t index)
{
if (pairs == nullptr || index >= pairs[0].maxIndex) {
LOG_ERROR("failed to get key from pair, pairs is null or index over limit");
return nullptr;
}
if (!NDKPreferencesUtils::PreferencesStructValidCheck(
pairs[index].cid, PreferencesNdkStructId::PREFERENCES_OH_PAIR_CID)) {
LOG_ERROR("cid error when get key from pair, cid: %{public}ld", static_cast<long>(pairs[index].cid));
return nullptr;
}
return pairs[index].key;
}
const OH_PreferencesValue *OH_PreferencesPair_GetPreferencesValue(const OH_PreferencesPair *pairs, uint32_t index)
{
if (pairs == nullptr || index >= pairs[0].maxIndex) {
LOG_ERROR("failed to get value from pair, pairs is null or index over limit");
return nullptr;
}
if (!NDKPreferencesUtils::PreferencesStructValidCheck(
pairs[index].cid, PreferencesNdkStructId::PREFERENCES_OH_PAIR_CID)) {
LOG_ERROR("cid error when get value from pair, cid: %{public}ld", static_cast<long>(pairs[index].cid));
return nullptr;
}
return pairs[index].value;
}
Preference_ValueType OH_PreferencesValue_GetValueType(const OH_PreferencesValue *object)
{
auto self = GetSelf(object);
if (self == nullptr) {
LOG_ERROR("Preferences GetValueType failed, object is null");
return Preference_ValueType::PREFERENCE_TYPE_NULL;
}
if (self->value_.IsInt()) {
return Preference_ValueType::PREFERENCE_TYPE_INT;
} else if (self->value_.IsBool()) {
return Preference_ValueType::PREFERENCE_TYPE_BOOL;
} else if (self->value_.IsString()) {
return Preference_ValueType::PREFERENCE_TYPE_STRING;
} else if (self->value_.IsLong()) {
return Preference_ValueType::PREFERENCE_TYPE_INT64;
} else if (self->value_.IsDouble()) {
return Preference_ValueType::PREFERENCE_TYPE_DOUBLE;
} else if (self->value_.IsBoolArray()) {
return Preference_ValueType::PREFERENCE_TYPE_BOOL_ARRAY;
} else if (self->value_.IsStringArray()) {
return Preference_ValueType::PREFERENCE_TYPE_STRING_ARRAY;
} else if (self->value_.IsDoubleArray()) {
return Preference_ValueType::PREFERENCE_TYPE_DOUBLE_ARRAY;
} else if (self->value_.IsUint8Array()) {
return Preference_ValueType::PREFERENCE_TYPE_BLOB;
} else if (self->value_.IsIntArray()) {
return Preference_ValueType::PREFERENCE_TYPE_INT_ARRAY;
} else if (self->value_.IsInt64Array()) {
return Preference_ValueType::PREFERENCE_TYPE_INT64_ARRAY;
}
return Preference_ValueType::PREFERENCE_TYPE_NULL;
}
int OH_PreferencesValue_GetInt(const OH_PreferencesValue *object, int *value)
{
auto self = GetSelf(object);
if (self == nullptr || value == nullptr) {
LOG_ERROR("Preferences GetInt failed, object is null: %{public}d, value is null: %{public}d, err: %{public}d",
(self == nullptr), (value == nullptr), OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM);
return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM;
}
if (self->value_.IsInt()) {
*value = (int)(self->value_);
return OH_Preferences_ErrCode::PREFERENCES_OK;
}
LOG_ERROR("Preferences GetInt failed, type error, err: %{public}d",
OH_Preferences_ErrCode::PREFERENCES_ERROR_KEY_NOT_FOUND);
return OH_Preferences_ErrCode::PREFERENCES_ERROR_KEY_NOT_FOUND;
}
int OH_PreferencesValue_GetBool(const OH_PreferencesValue *object, bool *value)
{
auto self = GetSelf(object);
if (self == nullptr || value == nullptr) {
LOG_ERROR("Preferences GetBool failed, object is null: %{public}d, value is null: %{public}d, err: %{public}d",
(self == nullptr), (self == nullptr), OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM);
return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM;
}
if (self->value_.IsBool()) {
*value = (bool)(self->value_);
return OH_Preferences_ErrCode::PREFERENCES_OK;
}
LOG_ERROR("Preferences GetBool failed, type error, err: %{public}d",
OH_Preferences_ErrCode::PREFERENCES_ERROR_KEY_NOT_FOUND);
return OH_Preferences_ErrCode::PREFERENCES_ERROR_KEY_NOT_FOUND;
}
int OH_PreferencesValue_GetString(const OH_PreferencesValue *object, char **value, uint32_t *valueLen)
{
auto self = GetSelf(object);
if (self == nullptr || value == nullptr || valueLen == nullptr) {
LOG_ERROR("Preferences GetString failed, object is null: %{public}d, value is null: %{public}d, "
"valueLen is null: %{public}d, err: %{public}d", (self == nullptr), (value == nullptr),
(valueLen == nullptr), OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM);
return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM;
}
if (self->value_.IsString()) {
std::string str = (std::string)(self->value_);
size_t strLen = str.size();
if (strLen >= SIZE_MAX) {
LOG_ERROR("string length overlimit: %{public}zu", strLen);
return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM;
}
void *ptr = malloc(strLen + 1);
if (ptr == nullptr) {
LOG_ERROR("malloc failed when value get string, errno: %{public}d", errno);
return OH_Preferences_ErrCode::PREFERENCES_ERROR_MALLOC;
}
int sysErr = memset_s(ptr, (strLen + 1), 0, (strLen + 1));
if (sysErr != EOK) {
LOG_ERROR("memset failed when value get string, errCode: %{public}d", sysErr);
}
if (strLen > 0) {
sysErr = memcpy_s(ptr, strLen, str.c_str(), strLen);
if (sysErr != EOK) {
LOG_ERROR("memcpy failed when value get string, errCode: %{public}d", sysErr);
free(ptr);
return OH_Preferences_ErrCode::PREFERENCES_ERROR_MALLOC;
}
}
*value = reinterpret_cast<char *>(ptr);
*valueLen = strLen + 1;
return OH_Preferences_ErrCode::PREFERENCES_OK;
}
LOG_ERROR("Preferences GetString failed, type error, err: %{public}d",
OH_Preferences_ErrCode::PREFERENCES_ERROR_KEY_NOT_FOUND);
return OH_Preferences_ErrCode::PREFERENCES_ERROR_KEY_NOT_FOUND;
}
void OH_PreferencesPair_Destroy(OH_PreferencesPair *pairs, uint32_t count)
{
if (pairs == nullptr) {
return;
}
for (uint32_t i = 0; i < count; ++i) {
if (pairs[i].key != nullptr) {
free(const_cast<char*>(pairs[i].key));
}
OH_PreferencesValue_Destroy(const_cast<OH_PreferencesValue*>(pairs[i].value));
}
free(pairs);
}
OH_PreferencesValue* OH_PreferencesValue_Create(void)
{
OH_PreferencesValue *impl = new (std::nothrow) OH_PreferencesValueImpl();
if (impl == nullptr) {
LOG_ERROR("Failed to create OH_PreferencesValue");
return nullptr;
}
impl->cid = PreferencesNdkStructId::PREFERENCES_OH_VALUE_CID;
return impl;
}
void OH_PreferencesValue_Destroy(OH_PreferencesValue *value)
{
if (value == nullptr ||
!NDKPreferencesUtils::PreferencesStructValidCheck(
value->cid, PreferencesNdkStructId::PREFERENCES_OH_VALUE_CID)) {
LOG_ERROR("destroy value failed, value is null: %{public}d, errCode: %{public}d",
(value == nullptr), OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM);
return;
}
delete static_cast<OH_PreferencesValueImpl*>(value);
}
int OH_PreferencesValue_SetInt(const OH_PreferencesValue *object, int value)
{
auto self = GetSelf(object);
if (self == nullptr) {
LOG_ERROR("SetInt failed: object is null");
return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM;
}
self->value_ = OHOS::NativePreferences::PreferencesValue(value);
return OH_Preferences_ErrCode::PREFERENCES_OK;
}
int OH_PreferencesValue_SetBool(const OH_PreferencesValue *object, bool value)
{
auto self = GetSelf(object);
if (self == nullptr) {
LOG_ERROR("SetBool failed: object is null");
return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM;
}
self->value_ = OHOS::NativePreferences::PreferencesValue(value);
return OH_Preferences_ErrCode::PREFERENCES_OK;
}
int OH_PreferencesValue_SetString(const OH_PreferencesValue *object, const char *value)
{
auto self = GetSelf(object);
if (self == nullptr) {
LOG_ERROR("SetString failed: object is null");
return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM;
}
if (value == nullptr) {
LOG_ERROR("SetString failed: input string is null");
return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM;
}
self->value_ = OHOS::NativePreferences::PreferencesValue(std::string(value));
return OH_Preferences_ErrCode::PREFERENCES_OK;
}
int OH_PreferencesValue_SetInt64(const OH_PreferencesValue *object, int64_t value)
{
auto self = GetSelf(object);
if (self == nullptr) {
LOG_ERROR("SetInt64 failed: object is null");
return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM;
}
self->value_ = OHOS::NativePreferences::PreferencesValue(value);
return OH_Preferences_ErrCode::PREFERENCES_OK;
}
int OH_PreferencesValue_SetDouble(const OH_PreferencesValue *object, double value)
{
auto self = GetSelf(object);
if (self == nullptr) {
LOG_ERROR("SetDouble failed: object is null");
return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM;
}
self->value_ = OHOS::NativePreferences::PreferencesValue(value);
return OH_Preferences_ErrCode::PREFERENCES_OK;
}
template<typename T>
static int CopyArrayOut(const std::vector<T>& src, T** outArray, uint32_t* outCount)
{
if (outArray == nullptr || outCount == nullptr) {
return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM;
}
size_t count = src.size();
if (count > UINT32_MAX) {
LOG_ERROR("Array size too large");
return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM;
}
T* ptr = static_cast<T*>(malloc(sizeof(T) * count));
if (ptr == nullptr) {
LOG_ERROR("malloc failed for array, errno: %{public}d", errno);
return OH_Preferences_ErrCode::PREFERENCES_ERROR_MALLOC;
}
for (size_t i = 0; i < count; ++i) {
ptr[i] = src[i];
}
*outArray = ptr;
*outCount = static_cast<uint32_t>(count);
return OH_Preferences_ErrCode::PREFERENCES_OK;
}
int OH_PreferencesValue_SetIntArray(const OH_PreferencesValue *object, const int *value, uint32_t count)
{
auto self = GetSelf(object);
if (self == nullptr || value == nullptr) {
return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM;
}
std::vector<int> vec(value, value + count);
self->value_ = vec;
return OH_Preferences_ErrCode::PREFERENCES_OK;
}
int OH_PreferencesValue_SetDoubleArray(const OH_PreferencesValue *object, const double *value, uint32_t count)
{
auto self = GetSelf(object);
if (self == nullptr || value == nullptr) {
return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM;
}
std::vector<double> vec(value, value + count);
self->value_ = OHOS::NativePreferences::PreferencesValue(vec);
return OH_Preferences_ErrCode::PREFERENCES_OK;
}
int OH_PreferencesValue_SetBoolArray(const OH_PreferencesValue *object, const bool *value, uint32_t count)
{
auto self = GetSelf(object);
if (self == nullptr || value == nullptr) {
return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM;
}
std::vector<bool> vec(value, value + count);
self->value_ = OHOS::NativePreferences::PreferencesValue(vec);
return OH_Preferences_ErrCode::PREFERENCES_OK;
}
int OH_PreferencesValue_SetStringArray(const OH_PreferencesValue *object, const char **value, uint32_t count)
{
auto self = GetSelf(object);
if (self == nullptr || value == nullptr) {
return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM;
}
std::vector<std::string> vec;
for (uint32_t i = 0; i < count; ++i) {
if (value[i] == nullptr) {
LOG_ERROR("Null string in string array at index %{public}u", i);
return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM;
}
vec.emplace_back(value[i]);
}
self->value_ = OHOS::NativePreferences::PreferencesValue(vec);
return OH_Preferences_ErrCode::PREFERENCES_OK;
}
int OH_PreferencesValue_SetInt64Array(const OH_PreferencesValue *object, const int64_t *value, uint32_t count)
{
auto self = GetSelf(object);
if (self == nullptr || value == nullptr || count == 0) {
return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM;
}
std::vector<int64_t> vec(value, value + count);
self->value_ = vec;
return OH_Preferences_ErrCode::PREFERENCES_OK;
}
int OH_PreferencesValue_SetBlob(const OH_PreferencesValue *object, const uint8_t *value, uint32_t count)
{
auto self = GetSelf(object);
if (self == nullptr || value == nullptr) {
return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM;
}
std::vector<uint8_t> vec(value, value + count);
self->value_ = OHOS::NativePreferences::PreferencesValue(vec);
return OH_Preferences_ErrCode::PREFERENCES_OK;
}
int OH_PreferencesValue_GetInt64(const OH_PreferencesValue *object, int64_t *value)
{
auto self = GetSelf(object);
if (self == nullptr || value == nullptr) {
LOG_ERROR("GetInt64 failed: invalid param");
return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM;
}
if (self->value_.IsLong()) {
*value = (int64_t)(self->value_);
return OH_Preferences_ErrCode::PREFERENCES_OK;
}
LOG_ERROR("GetInt64 failed: type mismatch");
return OH_Preferences_ErrCode::PREFERENCES_ERROR_KEY_NOT_FOUND;
}
int OH_PreferencesValue_GetDouble(const OH_PreferencesValue *object, double *value)
{
auto self = GetSelf(object);
if (self == nullptr || value == nullptr) {
LOG_ERROR("GetDouble failed: invalid param");
return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM;
}
if (self->value_.IsDouble()) {
*value = (double)(self->value_);
return OH_Preferences_ErrCode::PREFERENCES_OK;
}
LOG_ERROR("GetDouble failed: type mismatch");
return OH_Preferences_ErrCode::PREFERENCES_ERROR_KEY_NOT_FOUND;
}
int OH_PreferencesValue_GetIntArray(const OH_PreferencesValue *object, int **value, uint32_t *count)
{
auto self = GetSelf(object);
if (self == nullptr || value == nullptr || count == nullptr) {
return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM;
}
if (self->value_.IsIntArray()) {
std::vector<int> vec = (std::vector<int>)(self->value_);
return CopyArrayOut(vec, value, count);
}
return OH_Preferences_ErrCode::PREFERENCES_ERROR_KEY_NOT_FOUND;
}
int OH_PreferencesValue_GetBoolArray(const OH_PreferencesValue *object, bool **value, uint32_t *count)
{
auto self = GetSelf(object);
if (self == nullptr || value == nullptr || count == nullptr) {
return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM;
}
if (self->value_.IsBoolArray()) {
std::vector<bool> vec = (std::vector<bool>)(self->value_);
if (CopyArrayOut(vec, value, count) != OH_Preferences_ErrCode::PREFERENCES_OK) {
return OH_Preferences_ErrCode::PREFERENCES_ERROR_MALLOC;
}
return OH_Preferences_ErrCode::PREFERENCES_OK;
}
return OH_Preferences_ErrCode::PREFERENCES_ERROR_KEY_NOT_FOUND;
}
int OH_PreferencesValue_GetStringArray(const OH_PreferencesValue *object, char ***value, uint32_t *count)
{
auto self = GetSelf(object);
if (self == nullptr || value == nullptr || count == nullptr) {
return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM;
}
if (!(self->value_.IsStringArray())) {
return OH_Preferences_ErrCode::PREFERENCES_ERROR_KEY_NOT_FOUND;
}
std::vector<std::string> vec = (std::vector<std::string>)(self->value_);
if (vec.size() == 0) {
return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM;
}
char** arrary = static_cast<char**>(malloc(sizeof(char*) * vec.size()));
if (arrary == nullptr) {
return OH_Preferences_ErrCode::PREFERENCES_ERROR_MALLOC;
}
for (size_t i = 0; i < vec.size(); ++i) {
const std::string& s = vec[i];
char* str = static_cast<char*>(malloc(s.size() + 1));
if (str == nullptr) {
for (size_t j = 0; j < i; ++j) {
free(arrary[j]);
}
free(arrary);
return OH_Preferences_ErrCode::PREFERENCES_ERROR_MALLOC;
}
if (memcpy_s(str, s.size() + 1, s.c_str(), s.size() + 1) != EOK) {
free(str);
for (size_t j = 0; j < i; ++j) {
free(arrary[j]);
}
free(arrary);
return OH_Preferences_ErrCode::PREFERENCES_ERROR_MALLOC;
}
arrary[i] = str;
}
*value = arrary;
*count = static_cast<uint32_t>(vec.size());
return OH_Preferences_ErrCode::PREFERENCES_OK;
}
int OH_PreferencesValue_GetInt64Array(const OH_PreferencesValue *object, int64_t **value, uint32_t *count)
{
auto self = GetSelf(object);
if (self == nullptr || value == nullptr || count == nullptr) {
return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM;
}
if (self->value_.IsInt64Array()) {
std::vector<int64_t> vec = (std::vector<int64_t>)(self->value_);
return CopyArrayOut(vec, value, count);
}
return OH_Preferences_ErrCode::PREFERENCES_ERROR_KEY_NOT_FOUND;
}
int OH_PreferencesValue_GetDoubleArray(const OH_PreferencesValue *object, double **value, uint32_t *count)
{
auto self = GetSelf(object);
if (self == nullptr || value == nullptr || count == nullptr) {
return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM;
}
if (self->value_.IsDoubleArray()) {
std::vector<double> vec = (std::vector<double>)(self->value_);
return CopyArrayOut(vec, value, count);
}
return OH_Preferences_ErrCode::PREFERENCES_ERROR_KEY_NOT_FOUND;
}
int OH_PreferencesValue_GetBlob(const OH_PreferencesValue *object, uint8_t **value, uint32_t *count)
{
auto self = GetSelf(object);
if (self == nullptr || value == nullptr || count == nullptr) {
return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM;
}
if (self->value_.IsUint8Array()) {
std::vector<uint8_t> vec = (std::vector<uint8_t>)(self->value_);
return CopyArrayOut(vec, value, count);
}
return OH_Preferences_ErrCode::PREFERENCES_ERROR_KEY_NOT_FOUND;
}