Skip to content

Commit d839378

Browse files
committed
we are no longer need to call zm::assign explicitly because we have operator=()
1 parent 629b0f8 commit d839378

File tree

3 files changed

+86
-126
lines changed

3 files changed

+86
-126
lines changed

Zmeya/Zmeya.h

Lines changed: 49 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,19 @@ class String
341341
return !isEqual(other.c_str());
342342
}
343343

344+
// Assignment operators for automatic conversion
345+
String& operator=(const std::string& other)
346+
{
347+
assign(*this, other);
348+
return *this;
349+
}
350+
351+
String& operator=(const char* other)
352+
{
353+
assign(*this, other);
354+
return *this;
355+
}
356+
344357
// friend class BlobBuilder;
345358

346359
// Friend declarations for new Builder API
@@ -424,6 +437,14 @@ template <typename T> class Array
424437

425438
ZMEYA_NODISCARD bool empty() const noexcept { return size() == 0; }
426439

440+
// Assignment operators for automatic conversion
441+
template<typename F>
442+
Array<T>& operator=(const std::vector<F>& other)
443+
{
444+
assign(*this, other);
445+
return *this;
446+
}
447+
427448
// friend class BlobBuilder;
428449

429450
// Friend declarations for new Builder API
@@ -539,6 +560,15 @@ template <typename Key> class HashSet
539560
}
540561

541562
ZMEYA_NODISCARD bool contains(const Key& key) const noexcept { return containsImpl<Key, HashKeyAdapterGeneric<Key>>(key); }
563+
564+
// Assignment operators for automatic conversion
565+
template<typename F>
566+
HashSet<Key>& operator=(const std::unordered_set<F>& other)
567+
{
568+
assign(*this, other);
569+
return *this;
570+
}
571+
542572
// friend class BlobBuilder;
543573

544574
// Friend declarations for new Builder API
@@ -703,6 +733,14 @@ template <typename Key, typename Value> class HashMap
703733
return valueIfNotFound;
704734
}
705735

736+
// Assignment operators for automatic conversion
737+
template<typename FK, typename FV>
738+
HashMap<Key, Value>& operator=(const std::unordered_map<FK, FV>& other)
739+
{
740+
assign(*this, other);
741+
return *this;
742+
}
743+
706744
// friend class BlobBuilder;
707745

708746
// Friend declarations for new Builder API
@@ -2014,30 +2052,9 @@ template <typename T, typename F> void assign(Array<T>& _to, const std::vector<F
20142052

20152053
for (size_t i = 0; i < from.size(); ++i)
20162054
{
2017-
// deep-copy elements
2018-
// TODO: add range check for offset to make sure it within the valid range (goffset_t)
2055+
// deep-copy elements using the universal deep_copy function
20192056
zm::goffset_t elementOffset = zm::goffset_t(arrayDataOffset + i * sizeOfT);
2020-
2021-
// Use placement constructor and then assign
2022-
T* element = reinterpret_cast<T*>(builder->get_ptr_unsafe_to_store(elementOffset));
2023-
BuilderBase::placementCtor<T>(element);
2024-
2025-
// For fundamental types, direct assignment
2026-
if constexpr (std::is_fundamental_v<F> && std::is_fundamental_v<T>) {
2027-
*element = static_cast<T>(from[i]);
2028-
}
2029-
// For string conversion
2030-
else if constexpr (std::is_same_v<F, std::string> && std::is_same_v<T, String>) {
2031-
assign(*element, from[i]);
2032-
}
2033-
// For vector to array conversion (nested arrays)
2034-
else if constexpr (std::is_same_v<std::decay_t<F>, std::vector<typename std::decay_t<F>::value_type, typename std::decay_t<F>::allocator_type>>) {
2035-
assign(*element, from[i]);
2036-
}
2037-
// For other complex types, this shouldn't happen in practice
2038-
else {
2039-
static_assert(sizeof(F) == 0, "Unsupported type conversion in deep_copy");
2040-
}
2057+
deep_copy<F, T>(from[i], elementOffset);
20412058
}
20422059
}
20432060

@@ -2114,14 +2131,8 @@ template <typename Key, typename F> void assign(HashSet<Key>& _to, const std::un
21142131
Key* element = &items[bucket.endIndex];
21152132
BuilderBase::placementCtor<Key>(element);
21162133

2117-
// Assign the item using the same logic as Array assign
2118-
if constexpr (std::is_fundamental_v<F> && std::is_fundamental_v<Key>) {
2119-
*element = static_cast<Key>(item);
2120-
} else if constexpr (std::is_same_v<F, std::string> && std::is_same_v<Key, String>) {
2121-
assign(*element, item);
2122-
} else {
2123-
assign(*element, item);
2124-
}
2134+
// Assign the item using operator= (automatic conversion)
2135+
*element = item;
21252136

21262137
bucket.endIndex++;
21272138
}
@@ -2254,23 +2265,9 @@ void assign(HashMap<Key, Value>& _to, const std::unordered_map<FK, FV>& from)
22542265
BuilderBase::placementCtor<Key>(mutableKey);
22552266
BuilderBase::placementCtor<Value>(&element->second);
22562267

2257-
// Assign key
2258-
if constexpr (std::is_fundamental_v<FK> && std::is_fundamental_v<Key>) {
2259-
*mutableKey = static_cast<Key>(key);
2260-
} else if constexpr (std::is_same_v<FK, std::string> && std::is_same_v<Key, String>) {
2261-
assign(*mutableKey, key);
2262-
} else {
2263-
assign(*mutableKey, key);
2264-
}
2265-
2266-
// Assign value
2267-
if constexpr (std::is_fundamental_v<FV> && std::is_fundamental_v<Value>) {
2268-
element->second = static_cast<Value>(value);
2269-
} else if constexpr (std::is_same_v<FV, std::string> && std::is_same_v<Value, String>) {
2270-
assign(element->second, value);
2271-
} else {
2272-
assign(element->second, value);
2273-
}
2268+
// Assign key and value using operator= (automatic conversion)
2269+
*mutableKey = key;
2270+
element->second = value;
22742271

22752272
bucket.endIndex++;
22762273
}
@@ -2322,67 +2319,14 @@ void assign(HashMap<Key, Value>& _to, const std::unordered_map<FK, FV>& from)
23222319

23232320
// Deep-copy adapter implementations
23242321

2325-
// Generic copy for fundamental types only (int, float, etc.)
2326-
template <typename F, typename T>
2327-
std::enable_if_t<std::is_fundamental_v<std::decay_t<F>> && std::is_fundamental_v<std::decay_t<T>> && std::is_convertible_v<F, T>>
2328-
deep_copy(const F& from, zm::goffset_t to_ofs)
2322+
// Universal deep_copy - works for all types thanks to operator= overloads
2323+
template <typename F, typename T> void deep_copy(const F& from, zm::goffset_t to_ofs)
23292324
{
23302325
BuilderBase* builder = detail::get_global_builder();
23312326
ZMEYA_ASSERT(builder != nullptr);
23322327
T* p_to = reinterpret_cast<T*>(builder->get_ptr_unsafe_to_store(to_ofs));
2333-
*p_to = static_cast<T>(from);
2334-
}
2335-
2336-
// Specialized overloads for std::* -> zm::* conversions
2337-
inline void deep_copy(const std::string& from, zm::goffset_t to_ofs)
2338-
{
2339-
BuilderBase* builder = detail::get_global_builder();
2340-
ZMEYA_ASSERT(builder != nullptr);
2341-
String* p_to = reinterpret_cast<String*>(builder->get_ptr_unsafe_to_store(to_ofs));
2342-
assign(*p_to, from);
2343-
}
2344-
2345-
inline void deep_copy(const char* from, zm::goffset_t to_ofs)
2346-
{
2347-
BuilderBase* builder = detail::get_global_builder();
2348-
ZMEYA_ASSERT(builder != nullptr);
2349-
String* p_to = reinterpret_cast<String*>(builder->get_ptr_unsafe_to_store(to_ofs));
2350-
assign(*p_to, from);
2351-
}
2352-
2353-
template <typename F, typename T> void deep_copy(const std::vector<F>& from, zm::goffset_t to_ofs)
2354-
{
2355-
BuilderBase* builder = detail::get_global_builder();
2356-
ZMEYA_ASSERT(builder != nullptr);
2357-
Array<T>* p_to = reinterpret_cast<Array<T>*>(builder->get_ptr_unsafe_to_store(to_ofs));
2358-
assign(*p_to, from);
2359-
}
2360-
2361-
template <typename F, typename Key> void deep_copy(const std::unordered_set<F>& from, zm::goffset_t to_ofs)
2362-
{
2363-
BuilderBase* builder = detail::get_global_builder();
2364-
ZMEYA_ASSERT(builder != nullptr);
2365-
HashSet<Key>* p_to = reinterpret_cast<HashSet<Key>*>(builder->get_ptr_unsafe_to_store(to_ofs));
2366-
assign(*p_to, from);
2367-
}
2368-
2369-
template <typename FK, typename FV, typename Key, typename Value>
2370-
void deep_copy(const std::unordered_map<FK, FV>& from, zm::goffset_t to_ofs)
2371-
{
2372-
BuilderBase* builder = detail::get_global_builder();
2373-
ZMEYA_ASSERT(builder != nullptr);
2374-
HashMap<Key, Value>* p_to = reinterpret_cast<HashMap<Key, Value>*>(builder->get_ptr_unsafe_to_store(to_ofs));
2375-
assign(*p_to, from);
2376-
}
2377-
2378-
// Pair conversions
2379-
template <typename F1, typename F2, typename T1, typename T2> void deep_copy(const Pair<F1, F2>& from, zm::goffset_t to_ofs)
2380-
{
2381-
BuilderBase* builder = detail::get_global_builder();
2382-
ZMEYA_ASSERT(builder != nullptr);
2383-
Pair<T1, T2>* p_to = reinterpret_cast<Pair<T1, T2>*>(builder->get_ptr_unsafe_to_store(to_ofs));
2384-
deep_copy(from.first, builder->get_global_offset(&p_to->first));
2385-
deep_copy(from.second, builder->get_global_offset(&p_to->second));
2328+
BuilderBase::placementCtor<T>(p_to);
2329+
*p_to = from; // This will call the appropriate operator= automatically!
23862330
}
23872331

23882332
/*

ZmeyaTest01.cpp

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,16 @@ struct Desc
124124
zm::String name;
125125
float v1;
126126
uint32_t v2;
127+
128+
// Assignment operator for automatic conversion from TempDesc
129+
template<typename TempType>
130+
Desc& operator=(const TempType& temp)
131+
{
132+
name = temp.name;
133+
v1 = temp.v1;
134+
v2 = temp.v2;
135+
return *this;
136+
}
127137
};
128138

129139
struct TestRoot
@@ -172,19 +182,19 @@ TEST(ZmeyaTestSuite, SimpleTest2)
172182
tempDescs.push_back(desc);
173183
}
174184

175-
// For complex struct conversion, we need to add a deep_copy specialization
176-
// For now, let's create a simple vector of strings to demonstrate the new API
177-
std::vector<std::string> nameStrings(names.begin(), names.end());
178-
179-
// TODO: Once we have deep_copy<TempDesc, Desc> specialization, we can use:
180-
// zm::assign(root->arr, tempDescs);
185+
root->arr = tempDescs;
181186

182-
// For now, let's just test that the root object works and skip the complex array
183-
// The array will remain empty, which is fine for testing the basic API
184-
185-
EXPECT_EQ(root->arr.size(), 0); // Array is empty for now
186-
187-
// TODO: Add array validation once deep_copy<TempDesc, Desc> is implemented
187+
EXPECT_EQ(root->arr.size(), names.size());
188+
189+
// Validate data during build
190+
for (size_t i = 0; i < names.size(); i++)
191+
{
192+
const char* s1 = root->arr[i].name.c_str();
193+
const char* s2 = names[i].c_str();
194+
EXPECT_STREQ(s1, s2);
195+
EXPECT_FLOAT_EQ(root->arr[i].v1, (float)(i));
196+
EXPECT_EQ(root->arr[i].v2, (uint32_t)(i));
197+
}
188198

189199
zm::Span<char> bytes = builder->finalize();
190200
blob = std::vector<char>(bytes.data, bytes.data + bytes.size);
@@ -198,9 +208,15 @@ TEST(ZmeyaTestSuite, SimpleTest2)
198208

199209
// validate
200210
const TestRoot* rootCopy = (const TestRoot*)(blob.data());
201-
EXPECT_EQ(rootCopy->arr.size(), 0); // Array is empty for now
202-
203-
// TODO: Add validation once complex struct conversion is implemented
211+
EXPECT_EQ(rootCopy->arr.size(), names.size());
212+
213+
for (size_t i = 0; i < names.size(); i++)
214+
{
215+
const Desc& desc = rootCopy->arr[i];
216+
EXPECT_STREQ(desc.name.c_str(), names[i].c_str());
217+
EXPECT_FLOAT_EQ(desc.v1, (float)(i));
218+
EXPECT_EQ(desc.v2, (uint32_t)(i));
219+
}
204220

205221
/*
206222
EXPECT_EQ(Memory::mallocCount, Memory::freeCount);

ZmeyaTestNewAPI.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -65,23 +65,23 @@ TEST(ZmeyaTestSuite, NewBuilderAPI_BasicTypes)
6565

6666
// Test basic string assignment
6767
std::string srcDesc = "Test description";
68-
zm::assign(root->description, srcDesc);
68+
root->description = srcDesc;
6969

7070
// Test array of primitives
7171
std::vector<int32_t> srcInts = {1, 2, 3, 4, 5};
72-
zm::assign(root->intArray, srcInts);
72+
root->intArray = srcInts;
7373

7474
// Test array of strings
7575
std::vector<std::string> srcStrings = {"hello", "world", "test"};
76-
zm::assign(root->stringArray, srcStrings);
76+
root->stringArray = srcStrings;
7777

7878
// Test HashMap
7979
std::unordered_map<std::string, int32_t> srcMap = {{"one", 1}, {"two", 2}, {"three", 3}};
80-
zm::assign(root->hashMap, srcMap);
80+
root->hashMap = srcMap;
8181

8282
// Test HashSet
8383
std::unordered_set<std::string> srcSet = {"alpha", "beta", "gamma"};
84-
zm::assign(root->hashSet, srcSet);
84+
root->hashSet = srcSet;
8585

8686
// Get result
8787
zm::Span<char> bytes = builder->finalize();
@@ -120,7 +120,7 @@ TEST(ZmeyaTestSuite, NewBuilderAPI_NestedTypes)
120120

121121
// Test nested array conversion
122122
std::vector<std::vector<std::string>> srcNested = {{"a", "b", "c"}, {"x", "y"}, {"hello", "world", "nested", "test"}};
123-
zm::assign(root->nestedArray, srcNested);
123+
root->nestedArray = srcNested;
124124

125125
// Get result
126126
zm::Span<char> bytes = builder->finalize();

0 commit comments

Comments
 (0)