blob: 90b30b54b2b11b258c4e15bf2c25cb9afda06528 [file]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
#pragma once
#include <cxxabi.h>
#include <cassert>
#include <cstdint>
#include <cstdlib>
#include <map>
#include <optional>
#include <string>
#include <type_traits>
#include <typeinfo>
#include <utility>
#include "fmt/format.h"
#include "paimon/common/utils/string_utils.h"
#include "paimon/result.h"
#include "paimon/status.h"
namespace paimon {
class OptionsUtils {
public:
template <typename T>
using is_supported_type =
std::disjunction<std::is_trivially_copyable<T>, std::is_same<T, std::string>>;
OptionsUtils() = delete;
~OptionsUtils() = delete;
template <typename T>
static Result<T> GetValueFromMap(const std::map<std::string, std::string>& key_value_map,
const std::string& key, const T& default_value) {
auto value = GetValueFromMap<T>(key_value_map, key);
if (value.ok()) {
return value.value();
} else if (value.status().IsNotExist()) {
return default_value;
}
return value.status();
}
template <typename T>
static Result<T> GetValueFromMap(const std::map<std::string, std::string>& key_value_map,
const std::string& key) {
static_assert(is_supported_type<T>::value, "T must be trivially copyable or string");
auto iter = key_value_map.find(key);
if (iter == key_value_map.end()) {
return Status::NotExist(fmt::format("key {} does not exist in map", key));
}
const auto& value_str = iter->second;
std::optional<T> value = StringUtils::StringToValue<T>(value_str);
if (value == std::nullopt) {
return Status::Invalid(fmt::format("convert key {}, value {} to {} failed", key,
value_str, GetTypeName<T>()));
}
return value.value();
}
/// Fetch options with specific prefix and remove prefix for key.
static std::map<std::string, std::string> FetchOptionsWithPrefix(
const std::string& prefix, const std::map<std::string, std::string>& options) {
std::map<std::string, std::string> options_with_prefix;
int64_t prefix_len = prefix.size();
for (const auto& [key, value] : options) {
if (StringUtils::StartsWith(key, prefix)) {
options_with_prefix[key.substr(prefix_len)] = value;
}
}
return options_with_prefix;
}
template <typename T>
static std::string GetTypeName() {
int32_t status;
char* demangled = abi::__cxa_demangle(typeid(T).name(), nullptr, nullptr, &status);
if (status == 0) {
std::string result(demangled);
free(demangled);
return result;
}
assert(demangled == nullptr);
return typeid(T).name();
}
};
} // namespace paimon