private Ident GetLast(string name)
        {
            if (last == null)
            {
                last = new Ident(0, new[] { new Segment(GetWidthAtDepth(0), name) });
            }

            return(last);
        }
        private Ident GetFirst(string name)
        {
            if (first == null)
            {
                first = new Ident(0, new[] { new Segment(0, name) });
            }

            return(first);
        }
        protected int IndexOf(Ident id)
        {
            var pos = BisectLeft(id);

            if (pos != m_AtomList.Count && m_AtomList[pos].id.CompareTo(id) == 0)
            {
                return(pos);
            }

            return(-1);
        }
        protected int Remove(Ident id)
        {
            var pos = IndexOf(id);

            if (pos >= 0)
            {
                m_AtomList.RemoveAt(pos);
                return(pos);
            }

            return(-1);
        }
        public Ident GetIdent(string name, long time, Ident before, Ident after)
        {
            if (before == null)
            {
                before = GetFirst(name);
            }

            if (after == null)
            {
                after = GetLast(name);
            }

            var distance = 0;
            var depth    = -1;
            var min      = 0;
            var max      = 0;

            while (distance < 1)
            {
                depth++;
                min      = depth < before.depth ? before.Get(depth).digit : 0;
                max      = depth < after.depth ? after.Get(depth).digit : GetWidthAtDepth(depth);
                distance = max - min - 1;
            }

            var boundary = Math.Min(distance, maxDistance);
            var delta    = (int)Math.Floor(GetRandom() * boundary) + 1;
            var strategy = GetStrategyAtDepth(depth);
            var path     = new List <Segment>(depth + 1);

            for (var i = 0; i < depth; i++)
            {
                path.Add(i < before.depth ? before.Get(i) : new Segment(0, name));
            }

            switch (strategy)
            {
            case LSEQStrategy.AddFromLeft:
                path.Add(new Segment(min + delta, name));
                break;

            case LSEQStrategy.SubtractFromRight:
                path.Add(new Segment(max - delta, name));
                break;
            }

            return(new Ident(time, path.ToArray()));
        }
        protected int Add(Ident id, T value)
        {
            var pos         = BisectRight(id);
            var hasExisting = pos - 1 >= 0 && pos - 1 < Count;
            int index       = pos - 1;

            if (hasExisting && m_AtomList[index].id.CompareTo(id) == 0)
            {
                return(-1);
            }

            var atom = new Atom <T>(id, value);

            m_AtomList.Insert(pos, atom);
            return(pos);
        }
        protected int BisectRight(Ident id)
        {
            var min = 0;
            var max = m_AtomList.Count;

            while (min < max)
            {
                var curr = (min + max) / 2;
                if (id.CompareTo(m_AtomList[curr].id) < 0)
                {
                    max = curr;
                }
                else
                {
                    min = curr + 1;
                }
            }

            return(min);
        }
예제 #8
0
 public Atom(Ident id, T value)
 {
     this.id    = id;
     this.value = value;
 }