/// <summary>
        /// Adds a string to the set if it does not already exist.
        /// </summary>
        /// <param name="buffer">The character array which represents the string you want to add.</param>
        /// <param name="start">The index in the character array where your string starts.</param>
        /// <param name="count">The length of the string you want to add.</param>
        /// <param name="str">The string object representation of the characters. A new string is only allocated when it does not already exist in the set.</param>
        /// <param name="knownHashValue">(optional) If the StringHash has already been calculated, you can provide it here to save re-calculation.</param>
        /// <returns>True if the string was added. False if the string already existed in the set.</returns>
        public bool Add(char[] buffer, int start, int count, out string str, StringHash knownHashValue = default(StringHash))
        {
            if (knownHashValue == default(StringHash))
            {
                knownHashValue = StringHash.GetHash(buffer, start, count);
            }
            else
            {
                StringHash.AssertBufferArgumentsAreSane(buffer.Length, start, count);
            }

            str = GetExistingStringImpl(buffer, start, count, knownHashValue);

            if (str != null)
            {
                return(false); // didn't add anything
            }
            // an existing string wasn't found, we need to add it to the hash
            lock (_writeLock)
            {
                // first, check one more time to see if it exists
                str = GetExistingStringImpl(buffer, start, count, knownHashValue);

                if (str == null)
                {
                    // it definitely doesn't exist. Let's add it
                    str = new string(buffer, start, count);
                    AddImpl(str, knownHashValue);
                    return(true);
                }

                return(false);
            }
        }
        /// <summary>
        /// Adds a string to the set if it does not already exist.
        /// </summary>
        /// <param name="chars">A pointer to the string you want to add.</param>
        /// <param name="count">The length of the string (in chars).</param>
        /// <param name="str">The string object representation of the characters. A new string is only allocated when it does not already exist in the set.</param>
        /// <param name="knownHashValue">(optional) If the StringHash has already been calculated, you can provide it here to save re-calculation.</param>
        /// <returns>True if the string was added. False if the string already existed in the set.</returns>
        public unsafe bool Add(char *chars, int count, out string str, StringHash knownHashValue = default(StringHash))
        {
            if (knownHashValue == default(StringHash))
            {
                knownHashValue = StringHash.GetHash(chars, count);
            }

            str = GetExistingString(chars, count, knownHashValue);

            if (str != null)
            {
                return(false); // didn't add anything
            }
            // an existing string wasn't found, we need to add it to the hash
            lock (_writeLock)
            {
                // first, check one more time to see if it exists
                str = GetExistingString(chars, count, knownHashValue);

                if (str == null)
                {
                    // it definitely doesn't exist. Let's add it
                    str = new string(chars, 0, count);
                    AddImpl(str, knownHashValue);
                    return(true);
                }

                return(false);
            }
        }
        /// <summary>
        /// Uses the characters from a buffer to check whether a string exists in the set, and retrieve it if so.
        /// </summary>
        /// <param name="buffer">The character array which represents the string you want to check for.</param>
        /// <param name="start">The index in the character array where your string starts.</param>
        /// <param name="count">The length of the string you want to check for.</param>
        /// <param name="knownHashValue">(optional) If the StringHash has already been calculated, you can provide it here to save re-calculation.</param>
        /// <returns>If found in the set, the existing string is returned. If not found, null is returned.</returns>
        public string GetExistingString(char[] buffer, int start, int count, StringHash knownHashValue = default(StringHash))
        {
            if (knownHashValue == default(StringHash))
            {
                knownHashValue = StringHash.GetHash(buffer, start, count);
            }
            else
            {
                StringHash.AssertBufferArgumentsAreSane(buffer.Length, start, count);
            }

            return(GetExistingStringImpl(buffer, start, count, knownHashValue));
        }
        /// <summary>
        /// Uses the characters from a buffer to check whether a string exists in the set, and retrieve it if so.
        /// </summary>
        /// <param name="chars">A pointer to the string to search for.</param>
        /// <param name="count">The length of the string (in chars).</param>
        /// <param name="knownHashValue">(optional) If the StringHash has already been calculated, you can provide it here to save re-calculation.</param>
        /// <returns>If found in the set, the existing string is returned. If not found, null is returned.</returns>
        public unsafe string GetExistingString(char *chars, int count, StringHash knownHashValue = default(StringHash))
        {
            if (knownHashValue == default(StringHash))
            {
                knownHashValue = StringHash.GetHash(chars, count);
            }

            var cursor = GetSearchCursor(knownHashValue);

            while (cursor.MightHaveMore)
            {
                var value = cursor.NextString();
                if (value != null && UnsafeStringComparer.AreEqual(value, chars, count))
                {
                    return(value);
                }
            }

            return(null);
        }
        /// <summary>
        /// Adds a string to the set if it does not already exist.
        /// </summary>
        /// <param name="str">The string to add to the set.</param>
        /// <param name="knownHashValue">(optional) If the StringHash for str has already been calculated, you can provide it here to save re-calculation.</param>
        /// <returns>True if the string was added. False if the string already existed in the set.</returns>
        public bool Add(string str, StringHash knownHashValue = default(StringHash))
        {
            if (knownHashValue == default(StringHash))
            {
                knownHashValue = StringHash.GetHash(str);
            }

            if (!ContainsString(str, knownHashValue))
            {
                lock (_writeLock)
                {
                    if (!ContainsString(str, knownHashValue))
                    {
                        AddImpl(str, knownHashValue);
                        return(true);
                    }
                }
            }

            return(false);
        }