Пример #1
0
            /// <summary>
            /// Find the given string in the pool. If not found, returns null.
            /// </summary>
            public NormStr Get(string str, bool add = false)
            {
                AssertValid();

                if (str == null)
                {
                    str = "";
                }

                var  strSpan = str.AsSpan();
                uint hash    = Hashing.HashString(strSpan);
                int  ins     = GetIns(hash);

                while (ins >= 0)
                {
                    ulong meta = _rgmeta[ins];
                    if ((int)Utils.GetLo(meta) == str.Length)
                    {
                        var ns = GetNs(ins);
                        if (strSpan.SequenceEqual(ns.Value.Span))
                        {
                            return(ns);
                        }
                    }
                    ins = (int)Utils.GetHi(meta);
                }
                Contracts.Assert(ins == -1);

                return(add ? AddCore(str.AsMemory(), hash) : null);
            }
Пример #2
0
            /// <summary>
            /// Adds the item. Does NOT check for whether the item is already present.
            /// </summary>
            private NormStr AddCore(ReadOnlyMemory <char> str, uint hash)
            {
                Contracts.Assert(str.Length >= 0);
                Contracts.Assert(Hashing.HashString(str.Span) == hash);

                if (_rgns == null)
                {
                    Contracts.Assert(_cns == 0);
                    _rgmeta = new ulong[10];
                    _rgns   = new NormStr[10];
                }
                else if (_cns >= _rgns.Length)
                {
                    Contracts.Assert(_cns == _rgns.Length);
                    int size = checked (_rgns.Length / 2 + _rgns.Length);
                    Array.Resize(ref _rgmeta, size);
                    Array.Resize(ref _rgns, size);
                }
                Contracts.Assert(_cns < _rgns.Length);

                NormStr ns   = new NormStr(str, _cns, hash);
                int     iins = GetIins(hash);

                _rgns[_cns]   = ns;
                _rgmeta[_cns] = Utils.MakeUlong((uint)_rgins[iins], (uint)ns.Value.Length);
                _rgins[iins]  = _cns;

                if (++_cns >= _rgins.Length)
                {
                    GrowTable();
                }

                AssertValid();
                return(ns);
            }
Пример #3
0
            /// <summary>
            /// Determine if the given sub-string has an equivalent NormStr in the pool.
            /// </summary>
            public NormStr Get(string str, int ichMin, int ichLim, bool add = false)
            {
                AssertValid();

                Contracts.Assert(0 <= ichMin & ichMin <= ichLim & ichLim <= Utils.Size(str));
                if (str == null)
                {
                    return(Get("", add));
                }

                if (ichMin == 0 && ichLim == str.Length)
                {
                    return(Get(str, add));
                }

                uint hash = Hashing.HashString(str, ichMin, ichLim);
                int  ins  = GetIns(hash);

                if (ins >= 0)
                {
                    int cch    = ichLim - ichMin;
                    var rgmeta = _rgmeta;
                    for (; ;)
                    {
                        ulong meta = rgmeta[ins];
                        if ((int)Utils.GetLo(meta) == cch)
                        {
                            var ns    = GetNs(ins);
                            var value = ns.Value;
                            for (int ich = 0; ; ich++)
                            {
                                if (ich == cch)
                                {
                                    return(ns);
                                }
                                if (value[ich] != str[ich + ichMin])
                                {
                                    break;
                                }
                            }
                        }
                        ins = (int)Utils.GetHi(meta);
                        if (ins < 0)
                        {
                            break;
                        }
                    }
                }
                Contracts.Assert(ins == -1);

                return(add ? AddCore(str.Substring(ichMin, ichLim - ichMin), hash) : null);
            }
Пример #4
0
            /// <summary>
            /// Make sure the given string has an equivalent NormStr in the pool and return it.
            /// </summary>
            public NormStr Get(StringBuilder sb, bool add = false)
            {
                AssertValid();

                if (sb == null)
                {
                    return(Get("", add));
                }

                int cch = sb.Length;

                NormStr ns;
                uint    hash = Hashing.HashString(sb);
                int     ins  = GetIns(hash);

                while (ins >= 0)
                {
                    ulong meta = _rgmeta[ins];
                    if ((int)Utils.GetLo(meta) == cch)
                    {
                        ns = GetNs(ins);
                        var value = ns.Value;
                        for (int ich = 0; ; ich++)
                        {
                            if (ich == cch)
                            {
                                return(ns);
                            }
                            if (value.Span[ich] != sb[ich])
                            {
                                break;
                            }
                        }
                    }
                    ins = (int)Utils.GetHi(meta);
                }
                Contracts.Assert(ins == -1);

                return(add ? AddCore(sb.ToString().AsMemory(), hash) : null);
            }