Ok, there is a TON of new stuff - there is a high probability I'm leaving something out. If that happens, I'll post the other updates when I find a feature I forgot to share. You can download the
updated zip.
I want to state that I still haven't fixed the shallow clone - still wrapping my mind around it - been focusing on other areas. Also, the Dictionary classes that are added are in a "beta" state. They work, have no memory leaks, etc; however, I may change the internals. This won't affect your code, so don't worry about it, but this is why the features for the Dictionary classes aren't up to par with Vector and Array - I need to decide what to do. I'm thinking about adding hashing, because lookups take WAY too long. On my computer it takes around 1 second to add 2500 "dictionary entries" (I can add 5000 Vector entries in the same time). The internals of the Dictionary classes are set-up to allow changing it to a HashMap. Don't worry, all additions or changes will be backward-compatable. I wanted to get it out, so that it can be incorporated into code. When I figure out the small details, I'll upload the updated version.
Functionality that affects Array is updated in Vector as well (and visa-versa)
Updates:
1) Added "Type options". Specify NoEquals / NoClone to skip a Class' value during an equals / clone operation. For example, instead "uint" specify "NoEquals& uint" to skip the value during the equals operation, specify "NoClone& uint" to skip the value during clone, and specify "NoClone& NoEquals& uint" to skip the value during both. The space between is optional (used for clarity).
2) Added Dictionary & SDictionary Container classes. These are a mapping / dictionary class that associates a key to a value. See the included Dictionary_test.ahk and SDictionary_test.ahk for usage. For both classes, only Strings are accepted as keys (value is an class object). The key can only be used once. Use Dictionary_put (mimics Vector_set) or Dictionary_replace to set a new value to the key. If the key doesn't exist, it will be created. There is no "add" method, use put or replace instead. The difference between the classes is that Dictionary uses
case-insensitive keys while SDictionary (case-Sensitive Dictionary) uses
case-sensitive keys. Otherwise, they function identically. Both are based on Vector, so their capacity grows as needed.
3) Overloaded Vector_indexOf type functions to allow both these formats:
Code:
Vector_indexOf(VectorObject, searchValue, startIndex, useFunction) - current
Vector_indexOf(VectorObject, searchValue, useFunction, startIndex)
The format remains like the first (the original), but the second is used if startIndex is not a integer type (decimal or hex). So, provided you don't have any class functions named, as examples, YourClass_1234 or YourClass_0x1234, then you can use the second format seemlessly. This allows this shortened format for finding the index of the first occurance:
Vector_indexOf(VectorObject, searchValue, useFunction) (if omitted, the startIndex will be 1 when finding the first occurance, and 0 (the last item) when finding the last occurance).
4) Added Array_size function and refitted Array, Vector, and the newly added container classes to use V2 design.
5) Fixed a syntax error in the SString wrapper. It now correctly compares the strings using a case-sensitive compare (it was case-insensitive by mistake)
6) added #NoEnv to Class.ahk This significantly speeds up the program, and does not need to be specified directly in the code - automatically included when using any Class, or Class.ahk function
7) added several search features to vector and array
a) RegEx searches - index and object
b) Find object (updated)
c) Find unset
Code:
Vector_indexOf(VectorObject, searchValue, startIndex = 1, useFunction = "getValue")
Vector_regexIndexOf(VectorObject, compareRegEx, startIndex = 1, useFunction = "getValue")
Vector_findObject(VectorObject, searchObject, startIndex = 1)
Vector_firstUnset(VectorObject, startIndex = 1)
Vector_findMatch(VectorObject, searchValue, startIndex = 1, useFunction = "getValue")
Vector_findRegExMatch(VectorObject, compareRegEx, startIndex = 1, useFunction = "getValue")
Vector_lastIndexOf(VectorObject, searchValue, startIndex = 0, useFunction = "getValue")
Vector_regexLastIndexOf(VectorObject, compareRegEx, startIndex = 0, useFunction = "getValue")
Vector_findLastObject(VectorObject, searchObject, startIndex = 0)
Vector_lastUnset(VectorObject, startIndex = 0)
Vector_findLastMatch(VectorObject, searchValue, startIndex = 0, useFunction = "getValue")
Vector_findLastRegExMatch(VectorObject, compareRegEx, startIndex = 0, useFunction = "getValue")

I'm not sure if I mentioned this add already, but you can specify the empty string for the useFunction to compare the object (the address) instead of calling a function.
9) Overloaded Vector_get:
Code:
Vector_get(VectorObject, index, useFunction = "")
Vector_getAddress(VectorObject, index, useFunction = "")
If useFunction is the empty string (default), the behavior is the same as before. If useFunction != "", then in both Get and GetAddress, for wrappers and non-wrappers alike, the specified function is called on the would-be return object, and it's return is returned instead. This is a shortcut for the following.
Code:
node := Vector_get(VectorObject, index)
className := Class_getName(node)
value := %className%_%useFunction%(node)
<value> is returned instead of <node>. Wrapper objects won't unwrap if useFunction != ""; instead, this behavior will be used. This allows using the get function to return a class value, or running a class function on the returned object.
For example, if myVector contains Rectangle objects, then
Vector_get(myVector, 1, "area") would return the area for the first Rectangle object.
Like I said, I think that's it for updates, but if I forgot something, I'll be back. Still working on the other stuff, and I'll post the update when I figure it out.