/* Copyright 2021 - 2026 R. Thomas
*
* 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 "logging.hpp"
#include "LIEF/DEX/Field.hpp"
#include "LIEF/DEX/Class.hpp"
#include "LIEF/DEX/hash.hpp"
#include "LIEF/DEX/enums.hpp"
#include "LIEF/DEX/EnumToString.hpp"
#include "LIEF/DEX/Method.hpp"
#include <numeric>
#include <utility>
namespace LIEF::DEX {
Field::Field(const Field&) = default;
Field& Field::operator=(const Field&) = default;
Field::Field() = default;
Field::Field(std::string name, Class* parent) :
name_{std::move(name)},
parent_{parent} {}
const std::string& Field::name() const {
return name_;
}
bool Field::has_class() const {
return parent_ != nullptr;
}
const Class* Field::cls() const {
return parent_;
}
Class* Field::cls() {
return const_cast<Class*>(static_cast<const Field*>(this)->cls());
}
size_t Field::index() const {
return original_index_;
}
bool Field::is_static() const {
return is_static_;
}
void Field::set_static(bool v) {
is_static_ = v;
}
bool Field::has(ACCESS_FLAGS f) const {
return (access_flags_ & f) != 0u;
}
Field::access_flags_list_t Field::access_flags() const {
Field::access_flags_list_t flags;
std::copy_if(std::begin(access_flags_list), std::end(access_flags_list),
std::back_inserter(flags),
[this](ACCESS_FLAGS f) { return has(f); });
return flags;
}
const Type* Field::type() const {
CHECK(type_ != nullptr, "Type is null!");
return type_;
}
Type* Field::type() {
return const_cast<Type*>(static_cast<const Field*>(this)->type());
}
void Field::accept(Visitor& visitor) const {
visitor.visit(*this);
}
std::ostream& operator<<(std::ostream& os, const Field& field) {
std::string pretty_cls_name = field.cls()->fullname();
if (!pretty_cls_name.empty()) {
pretty_cls_name = pretty_cls_name.substr(1, pretty_cls_name.size() - 2);
std::replace(pretty_cls_name.begin(), pretty_cls_name.end(), '/', '.');
}
Method::access_flags_list_t aflags = field.access_flags();
std::string flags_str =
std::accumulate(aflags.begin(), aflags.end(), std::string{},
[](const std::string& l, ACCESS_FLAGS r) {
std::string str = to_string(r);
std::transform(str.begin(), str.end(), str.begin(),
::tolower);
return l.empty() ? str : l + " " + str;
});
if (!flags_str.empty()) {
os << flags_str << " ";
}
os << field.type() << " " << pretty_cls_name << "->" << field.name();
return os;
}
Field::~Field() = default;
}