blob: e4a9d963afb53ca918b05634a9e49e967af7226a [file] [log] [blame]
# Copyright (C) 2022 The Android Open Source Project
#
# 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.
from typing import List
from typing import Optional
from python.generators.trace_processor_table.public import Alias
from python.generators.trace_processor_table.public import ColumnFlag
from python.generators.trace_processor_table.util import ParsedTable
from python.generators.trace_processor_table.util import ParsedColumn
from python.generators.trace_processor_table.util import data_layer_type
from python.generators.trace_processor_table.util import parse_type
from python.generators.trace_processor_table.util import typed_column_type
class ColumnSerializer:
"""Functions for serializing a single Column in a table into C++."""
def __init__(self, table: ParsedTable, column: ParsedColumn, col_index: int):
self.col_index = col_index
self.parsed_col = column
self.col = self.parsed_col.column
self.name = self.col.name
self.flags = self.col.flags
parsed_type = parse_type(table.table, self.col.type)
self.typed_column_type = typed_column_type(table.table, self.parsed_col)
self.cpp_type = parsed_type.cpp_type_with_optionality()
self.data_layer_type = data_layer_type(table.table, self.parsed_col)
self.is_implicit_id = self.parsed_col.is_implicit_id
self.is_implicit_type = self.parsed_col.is_implicit_type
self.is_ancestor = self.parsed_col.is_ancestor
self.is_string = parsed_type.cpp_type == 'StringPool::Id'
self.is_optional = parsed_type.is_optional
def colindex(self) -> str:
return f' static constexpr uint32_t {self.name} = {self.col_index};'
def coltype_enum(self) -> str:
return f' using {self.name} = {self.typed_column_type};'
def row_field(self) -> Optional[str]:
if self.is_implicit_id or self.is_implicit_type:
return None
if self.is_ancestor:
return None
return f' {self.cpp_type} {self.name};'
def row_param(self) -> Optional[str]:
if self.is_implicit_id or self.is_implicit_type:
return None
return f'{self.cpp_type} in_{self.name} = {{}}'
def parent_row_initializer(self) -> Optional[str]:
if self.is_implicit_id or self.is_implicit_type:
return None
if not self.is_ancestor:
return None
return f'in_{self.name}'
def row_initializer(self) -> Optional[str]:
if self.is_implicit_id or self.is_implicit_type:
return None
if self.is_ancestor:
return None
return f'{self.name}(in_{self.name})'
def const_row_ref_getter(self) -> Optional[str]:
return f'''ColumnType::{self.name}::type {self.name}() const {{
return table_->{self.name}()[row_number_];
}}'''
def row_ref_getter(self) -> Optional[str]:
if self.is_implicit_id or self.is_implicit_type:
return None
return f'''void set_{self.name}(
ColumnType::{self.name}::non_optional_type v) {{
return mutable_table()->mutable_{self.name}()->Set(row_number_, v);
}}'''
def flag(self) -> Optional[str]:
if self.is_implicit_id or self.is_implicit_type:
return None
if self.is_ancestor:
return None
default = f'ColumnType::{self.name}::default_flags()'
if self.flags == ColumnFlag.NONE:
flags = default
else:
flags = f'static_cast<uint32_t>({to_cpp_flags(self.flags)}) | {default}'
return f'''
static constexpr uint32_t {self.name} = {flags};
'''
def storage_init(self) -> Optional[str]:
if self.is_implicit_id or self.is_implicit_type:
return None
if self.is_ancestor:
return None
storage = f'ColumnStorage<ColumnType::{self.name}::stored_type>'
dense = str(ColumnFlag.DENSE in self.flags).lower()
return f'''{self.name}_({storage}::Create<{dense}>())'''
def column_init(self) -> Optional[str]:
if self.is_implicit_id or self.is_implicit_type:
return None
if self.is_ancestor:
return None
return f'''
columns.emplace_back("{self.name}", &self->{self.name}_, ColumnFlag::{self.name},
static_cast<uint32_t>(columns.size()), olay_idx);
'''
def shrink_to_fit(self) -> Optional[str]:
if self.is_implicit_id:
return None
if self.is_ancestor:
return None
return f' {self.name}_.ShrinkToFit();'
def append(self) -> Optional[str]:
if self.is_implicit_id or self.is_implicit_type:
return None
if self.is_ancestor:
return None
return f' mutable_{self.name}()->Append(row.{self.name});'
def accessor(self) -> Optional[str]:
inner = f'columns()[ColumnIndex::{self.name}]'
return f'''
const {self.typed_column_type}& {self.name}() const {{
return static_cast<const ColumnType::{self.name}&>({inner});
}}
'''
def mutable_accessor(self) -> Optional[str]:
if self.is_implicit_id or self.is_implicit_type:
return None
return f'''
{self.typed_column_type}* mutable_{self.name}() {{
return static_cast<ColumnType::{self.name}*>(
GetColumn(ColumnIndex::{self.name}));
}}
'''
def storage(self) -> Optional[str]:
if self.is_implicit_id or self.is_implicit_type:
return None
if self.is_ancestor:
return None
name = self.name
return f' ColumnStorage<ColumnType::{name}::stored_type> {name}_;'
def iterator_getter(self) -> Optional[str]:
name = self.name
return f'''
ColumnType::{self.name}::type {name}() const {{
const auto& col = table_->{name}();
return col.GetAtIdx(
iterator_.StorageIndexForColumn(col.index_in_table()));
}}
'''
def iterator_setter(self) -> Optional[str]:
if self.is_implicit_id or self.is_implicit_type:
return None
return f'''
void set_{self.name}(ColumnType::{self.name}::non_optional_type v) {{
auto* col = mutable_table_->mutable_{self.name}();
col->SetAtIdx(
iterator_.StorageIndexForColumn(col->index_in_table()), v);
}}
'''
def static_schema(self) -> Optional[str]:
if self.is_implicit_id or self.is_implicit_type:
return None
return f'''
schema.columns.emplace_back(Table::Schema::Column{{
"{self.name}", ColumnType::{self.name}::SqlValueType(), false,
{str(ColumnFlag.SORTED in self.flags).lower()},
{str(ColumnFlag.HIDDEN in self.flags).lower()},
{str(ColumnFlag.SET_ID in self.flags).lower()}}});
'''
def row_eq(self) -> Optional[str]:
if self.is_implicit_id or self.is_implicit_type:
return None
return f'ColumnType::{self.name}::Equals({self.name}, other.{self.name})'
def extend_parent_param(self) -> Optional[str]:
if self.is_implicit_id or self.is_implicit_type:
return None
if self.is_ancestor:
return None
return f'ColumnStorage<ColumnType::{self.name}::stored_type> {self.name}'
def extend_parent_param_arg(self) -> Optional[str]:
if self.is_implicit_id or self.is_implicit_type:
return None
if self.is_ancestor:
return None
return f'std::move({self.name})'
def static_assert_flags(self) -> Optional[str]:
if self.is_implicit_id or self.is_implicit_type:
return None
if self.is_ancestor:
return None
return f'''
static_assert(
ColumnLegacy::IsFlagsAndTypeValid<ColumnType::{self.name}::stored_type>(
ColumnFlag::{self.name}),
"Column type and flag combination is not valid");
'''
def extend_nullable_vector(self) -> Optional[str]:
if self.is_implicit_id or self.is_implicit_type:
return None
if self.is_ancestor:
return None
return f'''
PERFETTO_DCHECK({self.name}.size() == parent_overlay.size());
{self.name}_ = std::move({self.name});
'''
def storage_layer(self) -> Optional[str]:
if self.is_ancestor:
return None
return f'''
RefPtr<{self.data_layer_type}> {self.name}_storage_layer_;
'''
def null_layer(self) -> Optional[str]:
if self.is_ancestor:
return None
if not self.is_optional or self.is_string:
return f''
return f'''
RefPtr<column::NullOverlay> {self.name}_null_layer_;
'''
def storage_layer_create(self) -> str:
if self.is_ancestor:
return f'''
storage_layers[ColumnIndex::{self.name}] = const_parent_->storage_layers()[ColumnIndex::{self.name}];
'''
return f'''
storage_layers[ColumnIndex::{self.name}].reset({self.name}_storage_layer_.get());
'''
def null_layer_create(self) -> str:
if not self.is_optional or self.is_string:
return f''
if self.is_ancestor:
return f'''
null_layers[ColumnIndex::{self.name}] = const_parent_->null_layers()[ColumnIndex::{self.name}];
'''
return f'''
null_layers[ColumnIndex::{self.name}].reset({self.name}_null_layer_.get());
'''
def storage_layer_init(self) -> str:
if self.is_ancestor:
return f''
if self.is_implicit_id:
return f'{self.name}_storage_layer_(new column::IdStorage())'
if self.is_string:
return f'''{self.name}_storage_layer_(
new column::StringStorage(string_pool(), &{self.name}_.vector()))'''
if ColumnFlag.SET_ID in self.flags:
return f'''{self.name}_storage_layer_(
new column::SetIdStorage(&{self.name}_.vector()))'''
if self.is_optional:
return f'''{self.name}_storage_layer_(
new column::NumericStorage<ColumnType::{self.name}::non_optional_stored_type>(
&{self.name}_.non_null_vector(),
ColumnTypeHelper<ColumnType::{self.name}::stored_type>::ToColumnType(),
{str(ColumnFlag.SORTED in self.flags).lower()}))'''
return f'''{self.name}_storage_layer_(
new column::NumericStorage<ColumnType::{self.name}::non_optional_stored_type>(
&{self.name}_.vector(),
ColumnTypeHelper<ColumnType::{self.name}::stored_type>::ToColumnType(),
{str(ColumnFlag.SORTED in self.flags).lower()}))'''
def null_layer_init(self) -> str:
if self.is_ancestor:
return f''
if not self.is_optional or self.is_string:
return f''
return f'''{self.name}_null_layer_(new column::NullOverlay({self.name}_.bv()))'''
class TableSerializer(object):
"""Functions for seralizing a single Table into C++."""
def __init__(self, parsed: ParsedTable):
self.table = parsed.table
self.table_name = parsed.table.class_name
self.column_serializers = []
if parsed.table.parent:
self.parent_class_name = parsed.table.parent.class_name
else:
self.parent_class_name = 'macros_internal::RootParentTable'
self.column_serializers = []
for c in parsed.columns:
# Aliases should be ignored as they are handled in SQL currently.
if isinstance(c.column.type, Alias):
continue
self.column_serializers.append(
ColumnSerializer(parsed, c, len(self.column_serializers)))
def foreach_col(self, serialize_fn, delimiter='\n') -> str:
lines = []
for c in self.column_serializers:
serialized = serialize_fn(c)
if serialized:
lines.append(serialized.lstrip('\n').rstrip())
return delimiter.join(lines).strip()
def id_defn(self) -> str:
if self.table.parent:
return f'''
using Id = {self.table.parent.class_name}::Id;
'''
return '''
struct Id : public BaseId {
Id() = default;
explicit constexpr Id(uint32_t v) : BaseId(v) {}
};
static_assert(std::is_trivially_destructible_v<Id>,
"Inheritance used without trivial destruction");
'''
def row_struct(self) -> str:
param = self.foreach_col(
ColumnSerializer.row_param, delimiter=',\n ')
parent_row_init = self.foreach_col(
ColumnSerializer.parent_row_initializer, delimiter=', ')
row_init = self.foreach_col(
ColumnSerializer.row_initializer, delimiter=',\n ')
parent_separator = ',' if row_init else ''
row_eq = self.foreach_col(ColumnSerializer.row_eq, delimiter=' &&\n ')
return f'''
struct Row : public {self.parent_class_name}::Row {{
Row({param},
std::nullptr_t = nullptr)
: {self.parent_class_name}::Row({parent_row_init}){parent_separator}
{row_init} {{
type_ = "{self.table.sql_name}";
}}
{self.foreach_col(ColumnSerializer.row_field)}
bool operator==(const {self.table_name}::Row& other) const {{
return type() == other.type() && {row_eq};
}}
}};
'''
def const_row_reference_struct(self) -> str:
row_ref_getters = self.foreach_col(
ColumnSerializer.const_row_ref_getter, delimiter='\n ')
return f'''
class ConstRowReference : public macros_internal::AbstractConstRowReference<
{self.table_name}, RowNumber> {{
public:
ConstRowReference(const {self.table_name}* table, uint32_t row_number)
: AbstractConstRowReference(table, row_number) {{}}
{row_ref_getters}
}};
static_assert(std::is_trivially_destructible_v<ConstRowReference>,
"Inheritance used without trivial destruction");
'''
def row_reference_struct(self) -> str:
row_ref_getters = self.foreach_col(
ColumnSerializer.row_ref_getter, delimiter='\n ')
return f'''
class RowReference : public ConstRowReference {{
public:
RowReference(const {self.table_name}* table, uint32_t row_number)
: ConstRowReference(table, row_number) {{}}
{row_ref_getters}
private:
{self.table_name}* mutable_table() const {{
return const_cast<{self.table_name}*>(table_);
}}
}};
static_assert(std::is_trivially_destructible_v<RowReference>,
"Inheritance used without trivial destruction");
'''
def overlay_layer_create(self) -> str:
if not self.table.parent:
return f''
return f'''
for (uint32_t i = 0; i < kSelectorOverlayCount; ++i) {{
PERFETTO_CHECK(overlays()[i].row_map().IsBitVector());
overlay_layers[i].reset(new column::SelectorOverlay(
overlays()[i].row_map().GetIfBitVector()));
}}
'''
def constructor(self) -> str:
storage_init = self.foreach_col(
ColumnSerializer.storage_init, delimiter=',\n ')
storage_layer_init = self.foreach_col(
ColumnSerializer.storage_layer_init, delimiter=',\n ')
storage_layer_sep = '\n,' if storage_layer_init else ''
null_layer_init = self.foreach_col(
ColumnSerializer.null_layer_init, delimiter=',\n ')
null_layer_sep = '\n,' if null_layer_init else ''
if self.table.parent:
parent_param = f', {self.parent_class_name}* parent'
parent_arg = 'parent'
parent_init = 'parent_(parent), const_parent_(parent)' + (
', ' if storage_init else '')
else:
parent_param = ''
parent_arg = 'nullptr'
parent_init = ''
col_init = self.foreach_col(ColumnSerializer.column_init)
if col_init:
olay = 'uint32_t olay_idx = OverlayCount(parent);'
else:
olay = ''
return f'''
static std::vector<ColumnLegacy> GetColumns(
{self.table_name}* self,
const macros_internal::MacroTable* parent) {{
std::vector<ColumnLegacy> columns =
CopyColumnsFromParentOrAddRootColumns(self, parent);
{olay}
{col_init}
return columns;
}}
explicit {self.table_name}(StringPool* pool{parent_param})
: macros_internal::MacroTable(
pool,
GetColumns(this, {parent_arg}),
{parent_arg}),
{parent_init}{storage_init}{storage_layer_sep}
{storage_layer_init}{null_layer_sep}
{null_layer_init} {{
{self.foreach_col(ColumnSerializer.static_assert_flags)}
std::vector<RefPtr<column::DataLayer>> storage_layers(kColumnCount);
{self.foreach_col(ColumnSerializer.storage_layer_create)}
std::vector<RefPtr<column::DataLayer>> null_layers(kColumnCount);
{self.foreach_col(ColumnSerializer.null_layer_create)}
std::vector<RefPtr<column::DataLayer>> overlay_layers(
kSelectorOverlayCount + 1);
{self.overlay_layer_create()}
OnConstructionCompleted(
std::move(storage_layers), std::move(null_layers), std::move(overlay_layers));
}}
'''
def parent_field(self) -> str:
if self.table.parent:
return f'''
{self.parent_class_name}* parent_ = nullptr;
const {self.parent_class_name}* const_parent_ = nullptr;
'''
return ''
def insert_common(self) -> str:
if self.table.parent:
return '''
Id id = Id{parent_->Insert(row).id};
UpdateOverlaysAfterParentInsert();
'''
return '''
Id id = Id{row_number};
type_.Append(string_pool()->InternString(row.type()));
'''
def const_iterator(self) -> str:
iterator_getters = self.foreach_col(
ColumnSerializer.iterator_getter, delimiter='\n')
return f'''
class ConstIterator;
class ConstIterator : public macros_internal::AbstractConstIterator<
ConstIterator, {self.table_name}, RowNumber, ConstRowReference> {{
public:
{iterator_getters}
protected:
explicit ConstIterator(const {self.table_name}* table,
Table::Iterator iterator)
: AbstractConstIterator(table, std::move(iterator)) {{}}
uint32_t CurrentRowNumber() const {{
return iterator_.StorageIndexForLastOverlay();
}}
private:
friend class {self.table_name};
friend class macros_internal::AbstractConstIterator<
ConstIterator, {self.table_name}, RowNumber, ConstRowReference>;
}};
'''
def iterator(self) -> str:
iterator_setters = self.foreach_col(
ColumnSerializer.iterator_setter, delimiter='\n')
return f'''
class Iterator : public ConstIterator {{
public:
{iterator_setters}
RowReference row_reference() const {{
return RowReference(mutable_table_, CurrentRowNumber());
}}
private:
friend class {self.table_name};
explicit Iterator({self.table_name}* table, Table::Iterator iterator)
: ConstIterator(table, std::move(iterator)),
mutable_table_(table) {{}}
{self.table_name}* mutable_table_ = nullptr;
}};
'''
def extend(self) -> str:
if not self.table.parent:
return ''
params = self.foreach_col(
ColumnSerializer.extend_parent_param, delimiter='\n, ')
args = self.foreach_col(
ColumnSerializer.extend_parent_param_arg, delimiter=', ')
delim = ',' if params else ''
return f'''
static std::unique_ptr<Table> ExtendParent(
const {self.parent_class_name}& parent{delim}
{params}) {{
return std::unique_ptr<Table>(new {self.table_name}(
parent.string_pool(), parent, RowMap(0, parent.row_count()){delim}
{args}));
}}
static std::unique_ptr<Table> SelectAndExtendParent(
const {self.parent_class_name}& parent,
std::vector<{self.parent_class_name}::RowNumber> parent_overlay{delim}
{params}) {{
std::vector<uint32_t> prs_untyped(parent_overlay.size());
for (uint32_t i = 0; i < parent_overlay.size(); ++i) {{
prs_untyped[i] = parent_overlay[i].row_number();
}}
return std::unique_ptr<Table>(new {self.table_name}(
parent.string_pool(), parent, RowMap(std::move(prs_untyped)){delim}
{args}));
}}
'''
def extend_constructor(self) -> str:
if not self.table.parent:
return ''
storage_layer_init = self.foreach_col(
ColumnSerializer.storage_layer_init, delimiter=',\n ')
storage_layer_sep = '\n,' if storage_layer_init else ''
params = self.foreach_col(
ColumnSerializer.extend_parent_param, delimiter='\n, ')
return f'''
{self.table_name}(StringPool* pool,
const {self.parent_class_name}& parent,
const RowMap& parent_overlay{',' if params else ''}
{params})
: macros_internal::MacroTable(
pool,
GetColumns(this, &parent),
parent,
parent_overlay),
const_parent_(&parent){storage_layer_sep}
{storage_layer_init} {{
{self.foreach_col(ColumnSerializer.static_assert_flags)}
{self.foreach_col(ColumnSerializer.extend_nullable_vector)}
std::vector<RefPtr<column::DataLayer>> storage_layers(kColumnCount);
{self.foreach_col(ColumnSerializer.storage_layer_create)}
std::vector<RefPtr<column::DataLayer>> null_layers(kColumnCount);
{self.foreach_col(ColumnSerializer.null_layer_create)}
std::vector<RefPtr<column::DataLayer>> overlay_layers(kSelectorOverlayCount + 1);
for (uint32_t i = 0; i < kSelectorOverlayCount; ++i) {{
if (overlays()[i].row_map().IsIndexVector()) {{
overlay_layers[i].reset(new column::ArrangementOverlay(
overlays()[i].row_map().GetIfIndexVector(),
Indices::State::kNonmonotonic));
}} else if (overlays()[i].row_map().IsBitVector()) {{
overlay_layers[i].reset(new column::SelectorOverlay(
overlays()[i].row_map().GetIfBitVector()));
}} else if (overlays()[i].row_map().IsRange()) {{
overlay_layers[i].reset(new column::RangeOverlay(
overlays()[i].row_map().GetIfIRange()));
}}
}}
OnConstructionCompleted(
std::move(storage_layers), std::move(null_layers), std::move(overlay_layers));
}}
'''
def selector_overlay_count(self) -> str:
if self.table.parent:
return f'{self.parent_class_name}::kSelectorOverlayCount + 1'
return '0'
def column_count(self) -> str:
return str(len(self.column_serializers))
def serialize(self) -> str:
return f'''
class {self.table_name} : public macros_internal::MacroTable {{
public:
static constexpr uint32_t kColumnCount = {self.column_count().strip()};
static constexpr uint32_t kSelectorOverlayCount = {self.selector_overlay_count().strip()};
{self.id_defn().lstrip()}
struct ColumnIndex {{
{self.foreach_col(ColumnSerializer.colindex)}
}};
struct ColumnType {{
{self.foreach_col(ColumnSerializer.coltype_enum)}
}};
{self.row_struct().strip()}
struct ColumnFlag {{
{self.foreach_col(ColumnSerializer.flag)}
}};
class RowNumber;
class ConstRowReference;
class RowReference;
class RowNumber : public macros_internal::AbstractRowNumber<
{self.table_name}, ConstRowReference, RowReference> {{
public:
explicit RowNumber(uint32_t row_number)
: AbstractRowNumber(row_number) {{}}
}};
static_assert(std::is_trivially_destructible_v<RowNumber>,
"Inheritance used without trivial destruction");
{self.const_row_reference_struct().strip()}
{self.row_reference_struct().strip()}
{self.const_iterator().strip()}
{self.iterator().strip()}
struct IdAndRow {{
Id id;
uint32_t row;
RowReference row_reference;
RowNumber row_number;
}};
{self.constructor().strip()}
~{self.table_name}() override;
static const char* Name() {{ return "{self.table.sql_name}"; }}
static Table::Schema ComputeStaticSchema() {{
Table::Schema schema;
schema.columns.emplace_back(Table::Schema::Column{{
"id", SqlValue::Type::kLong, true, true, false, false}});
schema.columns.emplace_back(Table::Schema::Column{{
"type", SqlValue::Type::kString, false, false, false, false}});
{self.foreach_col(ColumnSerializer.static_schema)}
return schema;
}}
ConstIterator IterateRows() const {{
return ConstIterator(this, Table::IterateRows());
}}
Iterator IterateRows() {{ return Iterator(this, Table::IterateRows()); }}
ConstIterator FilterToIterator(
const std::vector<Constraint>& cs,
RowMap::OptimizeFor opt = RowMap::OptimizeFor::kMemory) const {{
return ConstIterator(
this, ApplyAndIterateRows(QueryToRowMap(cs, {{}}, opt)));
}}
Iterator FilterToIterator(
const std::vector<Constraint>& cs,
RowMap::OptimizeFor opt = RowMap::OptimizeFor::kMemory) {{
return Iterator(this, ApplyAndIterateRows(QueryToRowMap(cs, {{}}, opt)));
}}
void ShrinkToFit() {{
{self.foreach_col(ColumnSerializer.shrink_to_fit)}
}}
std::optional<ConstRowReference> FindById(Id find_id) const {{
std::optional<uint32_t> row = id().IndexOf(find_id);
return row ? std::make_optional(ConstRowReference(this, *row))
: std::nullopt;
}}
std::optional<RowReference> FindById(Id find_id) {{
std::optional<uint32_t> row = id().IndexOf(find_id);
return row ? std::make_optional(RowReference(this, *row)) : std::nullopt;
}}
IdAndRow Insert(const Row& row) {{
uint32_t row_number = row_count();
{self.insert_common().strip()}
{self.foreach_col(ColumnSerializer.append)}
UpdateSelfOverlayAfterInsert();
return IdAndRow{{id, row_number, RowReference(this, row_number),
RowNumber(row_number)}};
}}
{self.extend().strip()}
{self.foreach_col(ColumnSerializer.accessor)}
{self.foreach_col(ColumnSerializer.mutable_accessor)}
private:
{self.extend_constructor().strip()}
{self.parent_field().strip()}
{self.foreach_col(ColumnSerializer.storage)}
{self.foreach_col(ColumnSerializer.storage_layer)}
{self.foreach_col(ColumnSerializer.null_layer)}
}};
'''.strip('\n')
def serialize_header(ifdef_guard: str, tables: List[ParsedTable],
include_paths: List[str]) -> str:
"""Serializes a table header file containing the given set of tables."""
include_paths_str = '\n'.join([f'#include "{i}"' for i in include_paths])
tables_str = '\n\n'.join([TableSerializer(t).serialize() for t in tables])
return f'''
#ifndef {ifdef_guard}
#define {ifdef_guard}
#include <array>
#include <cstddef>
#include <cstdint>
#include <memory>
#include <optional>
#include <type_traits>
#include <utility>
#include <vector>
#include "perfetto/base/logging.h"
#include "perfetto/trace_processor/basic_types.h"
#include "perfetto/trace_processor/ref_counted.h"
#include "src/trace_processor/containers/bit_vector.h"
#include "src/trace_processor/containers/row_map.h"
#include "src/trace_processor/containers/string_pool.h"
#include "src/trace_processor/db/column/arrangement_overlay.h"
#include "src/trace_processor/db/column/data_layer.h"
#include "src/trace_processor/db/column/numeric_storage.h"
#include "src/trace_processor/db/column/id_storage.h"
#include "src/trace_processor/db/column/null_overlay.h"
#include "src/trace_processor/db/column/range_overlay.h"
#include "src/trace_processor/db/column/selector_overlay.h"
#include "src/trace_processor/db/column/set_id_storage.h"
#include "src/trace_processor/db/column/string_storage.h"
#include "src/trace_processor/db/column/types.h"
#include "src/trace_processor/db/column_storage.h"
#include "src/trace_processor/db/column.h"
#include "src/trace_processor/db/table.h"
#include "src/trace_processor/db/typed_column.h"
#include "src/trace_processor/db/typed_column_internal.h"
#include "src/trace_processor/tables/macros_internal.h"
{include_paths_str}
namespace perfetto::trace_processor::tables {{
{tables_str.strip()}
}} // namespace perfetto
#endif // {ifdef_guard}
'''.strip()
def to_cpp_flags(raw_flag: ColumnFlag) -> str:
"""Converts a ColumnFlag to the C++ flags which it represents
It is not valid to call this function with ColumnFlag.NONE as in this case
defaults for that column should be implicitly used."""
assert raw_flag != ColumnFlag.NONE
flags = []
if ColumnFlag.SORTED in raw_flag:
flags.append('ColumnLegacy::Flag::kSorted')
if ColumnFlag.HIDDEN in raw_flag:
flags.append('ColumnLegacy::Flag::kHidden')
if ColumnFlag.DENSE in raw_flag:
flags.append('ColumnLegacy::Flag::kDense')
if ColumnFlag.SET_ID in raw_flag:
flags.append('ColumnLegacy::Flag::kSetId')
return ' | '.join(flags)