Skip to content

Commit

Permalink
[wpiutil] DynamicStruct: Store StructDescriptor by value
Browse files Browse the repository at this point in the history
  • Loading branch information
PeterJohnson committed Nov 1, 2024
1 parent caae535 commit 2cfe114
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 32 deletions.
53 changes: 24 additions & 29 deletions wpiutil/src/main/native/cpp/struct/DynamicStruct.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
#include "wpi/struct/DynamicStruct.h"

#include <algorithm>
#include <memory>
#include <string>
#include <utility>

Expand Down Expand Up @@ -195,14 +194,12 @@ const StructDescriptor* StructDescriptorDatabase::Add(std::string_view name,
}

// turn parsed schema into descriptors
auto& theStruct = m_structs[name];
if (!theStruct) {
theStruct = std::make_unique<StructDescriptor>(
name, StructDescriptor::private_init{});
}
theStruct->m_schema = schema;
theStruct->m_fields.clear();
theStruct->m_fields.reserve(parsed.declarations.size());
auto& theStruct =
m_structs.try_emplace(name, name, StructDescriptor::private_init{})
.first->second;
theStruct.m_schema = schema;
theStruct.m_fields.clear();
theStruct.m_fields.reserve(parsed.declarations.size());
bool isValid = true;
for (auto&& decl : parsed.declarations) {
auto type = TypeStringToType(decl.typeString);
Expand Down Expand Up @@ -251,51 +248,49 @@ const StructDescriptor* StructDescriptorDatabase::Add(std::string_view name,
}

// cross-reference struct, creating a placeholder if necessary
auto& aStruct = m_structs[decl.typeString];
if (!aStruct) {
aStruct = std::make_unique<StructDescriptor>(
decl.typeString, StructDescriptor::private_init{});
}
auto& aStruct = m_structs
.try_emplace(decl.typeString, decl.typeString,
StructDescriptor::private_init{})
.first->second;

// if the struct isn't valid, we can't be valid either
if (aStruct->IsValid()) {
size = aStruct->GetSize();
if (aStruct.IsValid()) {
size = aStruct.GetSize();
} else {
isValid = false;
}

// add to cross-references for when the struct does become valid
aStruct->m_references.emplace_back(theStruct.get());
structDesc = aStruct.get();
aStruct.m_references.emplace_back(&theStruct);
structDesc = &aStruct;
}

// create field
if (!theStruct->m_fieldsByName
.insert({decl.name, theStruct->m_fields.size()})
if (!theStruct.m_fieldsByName.insert({decl.name, theStruct.m_fields.size()})
.second) {
*err = fmt::format("duplicate field {}", decl.name);
[[unlikely]] return nullptr;
}

theStruct->m_fields.emplace_back(theStruct.get(), decl.name, type, size,
decl.arraySize, decl.bitWidth,
std::move(decl.enumValues), structDesc,
StructFieldDescriptor::private_init{});
theStruct.m_fields.emplace_back(&theStruct, decl.name, type, size,
decl.arraySize, decl.bitWidth,
std::move(decl.enumValues), structDesc,
StructFieldDescriptor::private_init{});
}

theStruct->m_valid = isValid;
theStruct.m_valid = isValid;
if (isValid) {
// we have all the info needed, so calculate field offset & shift
wpi::SmallVector<const StructDescriptor*, 16> stack;
auto err2 = theStruct->CalculateOffsets(stack);
auto err2 = theStruct.CalculateOffsets(stack);
if (!err2.empty()) {
*err = std::move(err2);
[[unlikely]] return nullptr;
}
} else {
// check for circular reference
wpi::SmallVector<const StructDescriptor*, 16> stack;
if (!theStruct->CheckCircular(stack)) {
if (!theStruct.CheckCircular(stack)) {
wpi::SmallString<128> buf;
wpi::raw_svector_ostream os{buf};
for (auto&& elem : stack) {
Expand All @@ -309,7 +304,7 @@ const StructDescriptor* StructDescriptorDatabase::Add(std::string_view name,
}
}

return theStruct.get();
return &theStruct;
}

const StructDescriptor* StructDescriptorDatabase::Find(
Expand All @@ -318,7 +313,7 @@ const StructDescriptor* StructDescriptorDatabase::Find(
if (it == m_structs.end()) {
return nullptr;
}
return it->second.get();
return &it->second;
}

uint64_t DynamicStruct::GetFieldImpl(const StructFieldDescriptor* field,
Expand Down
4 changes: 1 addition & 3 deletions wpiutil/src/main/native/include/wpi/struct/DynamicStruct.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,12 @@
#include <stdint.h>

#include <cassert>
#include <memory>
#include <span>
#include <string>
#include <string_view>
#include <utility>
#include <vector>

#include "wpi/MathExtras.h"
#include "wpi/StringMap.h"
#include "wpi/bit.h"

Expand Down Expand Up @@ -357,7 +355,7 @@ class StructDescriptorDatabase {
const StructDescriptor* Find(std::string_view name) const;

private:
StringMap<std::unique_ptr<StructDescriptor>> m_structs;
StringMap<StructDescriptor> m_structs;
};

/**
Expand Down
1 change: 1 addition & 0 deletions wpiutil/src/test/native/cpp/struct/DynamicStructTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include <stdint.h>

#include <cstring>
#include <string>

#include <gtest/gtest.h>
Expand Down

0 comments on commit 2cfe114

Please sign in to comment.