falco/userspace/engine/indexed_vector.h
Mark Stemm 5f13a9be08 Add equality operators for indexed_vector/falco_{list,macro,rule}
Add an equality operator for indexed_vector.

As indexed_vectors commonly hold falco lists/macros/rules, also add
equality operators for those structs. For condition/sinsp_filter
shared_ptrs, the operator checks that the shared_ptrs point to the
same underlying memory.

Signed-off-by: Mark Stemm <mark.stemm@gmail.com>
2024-10-10 09:20:17 +02:00

123 lines
3.6 KiB
C++

// SPDX-License-Identifier: Apache-2.0
/*
Copyright (C) 2023 The Falco 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.
*/
#pragma once
#include <string>
#include <vector>
#include <unordered_map>
/*!
\brief Simple wrapper of std::vector that allows random access
through both numeric and string indexes with O(1) complexity
*/
template<typename T>
class indexed_vector {
public:
indexed_vector() = default;
virtual ~indexed_vector() = default;
indexed_vector(indexed_vector&&) = default;
indexed_vector& operator=(indexed_vector&&) = default;
indexed_vector(const indexed_vector&) = default;
indexed_vector& operator=(const indexed_vector&) = default;
bool operator==(const indexed_vector& rhs) const {
return (this->m_entries == rhs.m_entries && this->m_index == rhs.m_index);
}
/*!
\brief Returns the number of elements
*/
virtual inline size_t size() const { return m_entries.size(); }
/*!
\brief Returns true if the vector is empty
*/
virtual inline bool empty() const { return m_entries.empty(); }
/*!
\brief Removes all the elements
*/
virtual inline void clear() {
m_entries.clear();
m_index.clear();
}
/*!
\brief Inserts a new element in the vector with a given string index
and returns its numeric index. String indexes are unique in
the vector. If no element is already present with the given string
index, then the provided element is added to the vector and its
numeric index is assigned as the next free slot in the vector.
Otherwise, the existing element gets overwritten with the contents
of the provided one and the numeric index of the existing element
is returned.
\param entry Element to add in the vector
\param index String index of the element to be added in the vector
\return The numeric index assigned to the element
*/
virtual inline size_t insert(const T& entry, const std::string& index) {
size_t id;
auto prev = m_index.find(index);
if(prev != m_index.end()) {
id = prev->second;
m_entries[id] = entry;
return id;
}
id = m_entries.size();
m_entries.push_back(entry);
m_index[index] = id;
return id;
}
/*!
\brief Returns a pointer to the element at the given numeric index,
or nullptr if no element exists at the given index.
*/
virtual inline T* at(size_t id) const {
if(id < m_entries.size()) {
return (T* const)&m_entries[id];
}
return nullptr;
}
/*!
\brief Returns a pointer to the element at the given string index,
or nullptr if no element exists at the given index.
*/
virtual inline T* at(const std::string& index) const {
auto it = m_index.find(index);
if(it != m_index.end()) {
return at(it->second);
}
return nullptr;
}
virtual inline typename std::vector<T>::iterator begin() { return m_entries.begin(); }
virtual inline typename std::vector<T>::iterator end() { return m_entries.end(); }
virtual inline typename std::vector<T>::const_iterator begin() const {
return m_entries.begin();
}
virtual inline typename std::vector<T>::const_iterator end() const { return m_entries.end(); }
private:
std::vector<T> m_entries;
std::unordered_map<std::string, size_t> m_index;
};