Browse Source

HashSet, HashMap: use signed type for size

https://github.com/urho3d/Urho3D/issues/2940
1vanK 3 years ago
parent
commit
5d8337fa35

+ 4 - 4
Docs/AngelScriptAPI.h

@@ -12448,13 +12448,13 @@ HashBase();
 // Methods:
 HashBase&  operator=(const HashBase&);
 bool Empty() const;
-uint NumBuckets() const;
-uint Size() const;
+int NumBuckets() const;
+int Size() const;
 void Swap(HashBase&);
 
 // Constants:
-static const uint MAX_LOAD_FACTOR;
-static const uint MIN_BUCKETS;
+static const int MAX_LOAD_FACTOR;
+static const int MIN_BUCKETS;
 };
 
 class HashIteratorBase

+ 4 - 4
Docs/ScriptAPI.dox

@@ -14631,14 +14631,14 @@ Methods:
 
 - HashBase&  operator=(const HashBase&)
 - bool Empty() const
-- uint NumBuckets() const
-- uint Size() const
+- int NumBuckets() const
+- int Size() const
 - void Swap(HashBase&)
 
 Constants:
 
-- uint MAX_LOAD_FACTOR
-- uint MIN_BUCKETS
+- int MAX_LOAD_FACTOR
+- int MIN_BUCKETS
 
 <a name="Class_HashIteratorBase"></a>
 

+ 8 - 8
Source/Urho3D/AngelScript/Generated_Members.h

@@ -1744,20 +1744,20 @@ template <class T> void RegisterMembers_HashBase(asIScriptEngine* engine, const
     // bool HashBase::Empty() const
     engine->RegisterObjectMethod(className, "bool Empty() const", AS_METHODPR(T, Empty, () const, bool), AS_CALL_THISCALL);
 
-    // unsigned HashBase::NumBuckets() const
-    engine->RegisterObjectMethod(className, "uint NumBuckets() const", AS_METHODPR(T, NumBuckets, () const, unsigned), AS_CALL_THISCALL);
+    // i32 HashBase::NumBuckets() const
+    engine->RegisterObjectMethod(className, "int NumBuckets() const", AS_METHODPR(T, NumBuckets, () const, i32), AS_CALL_THISCALL);
 
-    // unsigned HashBase::Size() const
-    engine->RegisterObjectMethod(className, "uint Size() const", AS_METHODPR(T, Size, () const, unsigned), AS_CALL_THISCALL);
+    // i32 HashBase::Size() const
+    engine->RegisterObjectMethod(className, "int Size() const", AS_METHODPR(T, Size, () const, i32), AS_CALL_THISCALL);
 
     // void HashBase::Swap(HashBase& rhs)
     engine->RegisterObjectMethod(className, "void Swap(HashBase&)", AS_METHODPR(T, Swap, (HashBase&), void), AS_CALL_THISCALL);
 
-    // static constexpr unsigned HashBase::MIN_BUCKETS
-    engine->SetDefaultNamespace(className);engine->RegisterGlobalProperty("const uint MIN_BUCKETS", (void*)&T::MIN_BUCKETS);engine->SetDefaultNamespace("");
+    // static constexpr i32 HashBase::MIN_BUCKETS
+    engine->SetDefaultNamespace(className);engine->RegisterGlobalProperty("const int MIN_BUCKETS", (void*)&T::MIN_BUCKETS);engine->SetDefaultNamespace("");
 
-    // static constexpr unsigned HashBase::MAX_LOAD_FACTOR
-    engine->SetDefaultNamespace(className);engine->RegisterGlobalProperty("const uint MAX_LOAD_FACTOR", (void*)&T::MAX_LOAD_FACTOR);engine->SetDefaultNamespace("");
+    // static constexpr i32 HashBase::MAX_LOAD_FACTOR
+    engine->SetDefaultNamespace(className);engine->RegisterGlobalProperty("const int MAX_LOAD_FACTOR", (void*)&T::MAX_LOAD_FACTOR);engine->SetDefaultNamespace("");
 
     #ifdef REGISTER_MEMBERS_MANUAL_PART_HashBase
         REGISTER_MEMBERS_MANUAL_PART_HashBase();

+ 15 - 5
Source/Urho3D/Container/HashBase.cpp

@@ -8,12 +8,14 @@
 namespace Urho3D
 {
 
-void HashBase::AllocateBuckets(unsigned size, unsigned numBuckets)
+void HashBase::AllocateBuckets(i32 size, i32 numBuckets)
 {
+    assert(size >= 0 && numBuckets > 0);
+
     delete[] ptrs_;
 
-    auto ptrs = new HashNodeBase* [numBuckets + 2];
-    auto* data = reinterpret_cast<unsigned*>(ptrs);
+    HashNodeBase** ptrs = new HashNodeBase* [numBuckets + 2];
+    i32* data = reinterpret_cast<i32*>(ptrs);
     data[0] = size;
     data[1] = numBuckets;
     ptrs_ = ptrs;
@@ -27,10 +29,18 @@ void HashBase::ResetPtrs()
     if (!ptrs_)
         return;
 
-    unsigned numBuckets = NumBuckets();
+    i32 numBuckets = NumBuckets();
     HashNodeBase** ptrs = Ptrs();
-    for (unsigned i = 0; i < numBuckets; ++i)
+    for (i32 i = 0; i < numBuckets; ++i)
         ptrs[i] = nullptr;
 }
 
+void HashBase::SetSize(i32 size)
+{
+    assert(size >= 0);
+
+    if (ptrs_)
+        (reinterpret_cast<unsigned*>(ptrs_))[0] = size;
+}
+
 }

+ 6 - 6
Source/Urho3D/Container/HashBase.h

@@ -82,10 +82,10 @@ class URHO3D_API HashBase
 {
 public:
     /// Initial amount of buckets.
-    static inline constexpr unsigned MIN_BUCKETS = 8;
+    static inline constexpr i32 MIN_BUCKETS = 8;
 
     /// Maximum load factor.
-    static inline constexpr unsigned MAX_LOAD_FACTOR = 4;
+    static inline constexpr i32 MAX_LOAD_FACTOR = 4;
 
     /// Construct.
     HashBase() :
@@ -106,23 +106,23 @@ public:
     }
 
     /// Return number of elements.
-    unsigned Size() const { return ptrs_ ? (reinterpret_cast<unsigned*>(ptrs_))[0] : 0; }
+    i32 Size() const { return ptrs_ ? (reinterpret_cast<i32*>(ptrs_))[0] : 0; }
 
     /// Return number of buckets.
-    unsigned NumBuckets() const { return ptrs_ ? (reinterpret_cast<unsigned*>(ptrs_))[1] : 0; }
+    i32 NumBuckets() const { return ptrs_ ? (reinterpret_cast<i32*>(ptrs_))[1] : 0; }
 
     /// Return whether has no elements.
     bool Empty() const { return Size() == 0; }
 
 protected:
     /// Allocate bucket head pointers + room for size and bucket count variables.
-    void AllocateBuckets(unsigned size, unsigned numBuckets);
+    void AllocateBuckets(i32 size, i32 numBuckets);
 
     /// Reset bucket head pointers.
     void ResetPtrs();
 
     /// Set new size.
-    void SetSize(unsigned size) { if (ptrs_) (reinterpret_cast<unsigned*>(ptrs_))[0] = size; }
+    void SetSize(i32 size);
 
     /// Return bucket head pointers.
     HashNodeBase** Ptrs() const { return ptrs_ ? ptrs_ + 2 : nullptr; }

+ 7 - 5
Source/Urho3D/Container/HashMap.h

@@ -356,7 +356,7 @@ public:
     /// Insert a pair. Return iterator and set exists flag according to whether the key already existed.
     Iterator Insert(const Pair<T, U>& pair, bool& exists)
     {
-        unsigned oldSize = Size();
+        i32 oldSize = Size();
         Iterator ret(InsertNode(pair.first_, pair.second_));
         exists = (Size() == oldSize);
         return ret;
@@ -459,14 +459,14 @@ public:
     /// Sort pairs. After sorting the map can be iterated in order until new elements are inserted.
     void Sort()
     {
-        unsigned numKeys = Size();
+        i32 numKeys = Size();
         if (!numKeys)
             return;
 
         auto** ptrs = new Node* [numKeys];
         Node* ptr = Head();
 
-        for (unsigned i = 0; i < numKeys; ++i)
+        for (i32 i = 0; i < numKeys; ++i)
         {
             ptrs[i] = ptr;
             ptr = ptr->Next();
@@ -476,7 +476,7 @@ public:
 
         head_ = ptrs[0];
         ptrs[0]->prev_ = 0;
-        for (unsigned i = 1; i < numKeys; ++i)
+        for (i32 i = 1; i < numKeys; ++i)
         {
             ptrs[i - 1]->next_ = ptrs[i];
             ptrs[i]->prev_ = ptrs[i - 1];
@@ -488,8 +488,10 @@ public:
     }
 
     /// Rehash to a specific bucket count, which must be a power of two. Return true if successful.
-    bool Rehash(unsigned numBuckets)
+    bool Rehash(i32 numBuckets)
     {
+        assert(numBuckets > 0);
+
         if (numBuckets == NumBuckets())
             return true;
 

+ 8 - 5
Source/Urho3D/Container/HashSet.h

@@ -297,7 +297,7 @@ public:
     /// Insert a key. Return an iterator and set exists flag according to whether the key already existed.
     Iterator Insert(const T& key, bool& exists)
     {
-        unsigned oldSize = Size();
+        i32 oldSize = Size();
         Iterator ret = Insert(key);
         exists = (Size() == oldSize);
         return ret;
@@ -392,14 +392,14 @@ public:
     /// Sort keys. After sorting the set can be iterated in order until new elements are inserted.
     void Sort()
     {
-        unsigned numKeys = Size();
+        i32 numKeys = Size();
         if (!numKeys)
             return;
 
         auto** ptrs = new Node* [numKeys];
         Node* ptr = Head();
 
-        for (unsigned i = 0; i < numKeys; ++i)
+        for (i32 i = 0; i < numKeys; ++i)
         {
             ptrs[i] = ptr;
             ptr = ptr->Next();
@@ -409,7 +409,7 @@ public:
 
         head_ = ptrs[0];
         ptrs[0]->prev_ = 0;
-        for (unsigned i = 1; i < numKeys; ++i)
+        for (i32 i = 1; i < numKeys; ++i)
         {
             ptrs[i - 1]->next_ = ptrs[i];
             ptrs[i]->prev_ = ptrs[i - 1];
@@ -421,10 +421,13 @@ public:
     }
 
     /// Rehash to a specific bucket count, which must be a power of two. Return true if successful.
-    bool Rehash(unsigned numBuckets)
+    bool Rehash(i32 numBuckets)
     {
+        assert(numBuckets > 0);
+
         if (numBuckets == NumBuckets())
             return true;
+        
         if (!numBuckets || numBuckets < Size() / MAX_LOAD_FACTOR)
             return false;