/// <summary> /// Add the next set of values; return the ID that was allocated. /// </summary> /// <remarks> /// This only supports appending all the sets of values ID by ID in order. /// TODO: allow more flexible building. /// </remarks> public virtual TId Add(ReadOnlySpan <TValue> multiValues) { if (SingleValues.Count > 0) { Offsets.Add(Offsets[Count - 1] + SingleValues[Count - 1]); } else { Offsets.Add(0); } SingleValues.Add(multiValues.Length); MultiValues.AddRange(multiValues); return(default(TId).ToId(Count)); }
/// <summary> /// All relationships have been added; sort them all and build the final relation table. /// </summary> public void Complete() { m_list.AsSpan().Sort((tuple1, tuple2) => { int fromIdCompare = tuple1.fromId.FromId().CompareTo(tuple2.fromId.FromId()); if (fromIdCompare != 0) { return(fromIdCompare); } return(tuple1.toId.FromId().CompareTo(tuple2.toId.FromId())); }); // and bin them by groups int listIndex = 0; SpannableList <TToId> buffer = new SpannableList <TToId>(); int listCount = m_list.Count; Table.SetMultiValueCapacity(listCount); foreach (TFromId id in Table.BaseTableOpt.Ids) { if (listIndex >= m_list.Count) { // ran outta entries, rest all 0 break; } // Count up how many are for id. int count = 0; buffer.Clear(); // create a to-ID that will never equal any other ID (even default) TToId lastToId = default(TToId).ToId(-1); while (listIndex + count < m_list.Count) { var(fromId, toId) = m_list[listIndex + count]; if (fromId.Equals(id)) { // drop duplicates (silently...) // TODO: are duplicates here a logic bug? Because they do happen in practice. if (!toId.Equals(lastToId)) { buffer.Add(toId); } count++; lastToId = toId; continue; } // ok we're done break; } Table.Add(buffer.AsSpan()); listIndex += count; } }
/// <summary> /// Add the next set of values; return the ID that was allocated. /// </summary> /// <remarks> /// This only supports appending all the sets of values ID by ID in order. /// TODO: allow more flexible building. /// </remarks> public virtual TId Add(ReadOnlySpan <TValue> multiValues) { if (BaseTableOpt != null && SingleValues.Count == BaseTableOpt.Count) { throw new Exception("Can't add to end of a table that has already been filled"); } if (SingleValues.Count > 0) { Offsets.Add(Offsets[Count - 1] + SingleValues[Count - 1]); } else { Offsets.Add(0); } SingleValues.Add(multiValues.Length); MultiValues.AddRange(multiValues); return(default(TId).CreateFrom(Count)); }