type TSOfficeContainer = class public function Create(arr: array of string); function Set(data: any): boolean;overload; // 设置data数据 function Set(name: string; index: integer; data: any): boolean;overload; function Add(data: any): boolean; function Append(data: any): boolean; function Insert(data: any): boolean; function InsertAfter(data: any; pos_data: any); function InsertBefore(data: any; pos_data: any); function Get(name: string; index: integer); function GetElements(include_removed: boolean): array of tslobj; private function GetBucketObj(str: string): LinkList; private bucket_: array of LinkList; child_: array of string; current_index_: integer; min_index_: integer; max_index_: integer; end; type LinkList = class public function Create(name: string); function Set(data: any); function Add(data: any); function Delete(data: any): boolean; function InsertAfter(data: any; pos_data: any): boolean; function InsertBefore(data: any; pos_data: any): boolean; function Name(): string; function Size(): integer; function First(): Node; private head_: Node; tail_: Node; size_: integer; name_: string; end; type Node = class public data; next; end; function TSOfficeContainer.Create(arr: array of string); begin bucket_ := array(); child_ := array(); min_index_ := 0; max_index_ := 0; for str,v in arr do begin child_[str] := v[0]; if v[0] > max_index_ then max_index_ := v[0]; if v[0] < min_index_ then min_index_ := v[0]; end current_index_ := -INF; end; function TSOfficeContainer.Set(data: any): boolean;overload; begin obj := {self.}GetBucketObj(data.ElementName); if ifnil(obj) then return false; obj.Set(data); return true; end; function TSOfficeContainer.Set(name: string; index: integer; data: any): boolean;overload; begin ind := child_[name]; obj := bucket_[ind]; if ifObj(obj) and obj.Name() = name then begin node := obj.First(); while ifObj(node) do begin if node.data.Removed then begin node := node.next; continue; end index--; if index = -1 then begin new_node := new Node(); new_node.data := data; new_node.next := node.next; node.data.Removed := true; node.next := new_node; if tail_ = node then tail_ := new_node; return true; end node := node.next; end end i := max_index_ + 1; for i:=max_index_+1 to current_index_ do begin if i = ind then continue; obj := bucket_[i]; if ifObj(obj) and obj.Name() = name then begin node := obj.First(); while ifObj(node) do begin if node.data.Remove then begin node := node.next; continue; end index--; if index = -1 then begin new_node := new Node(); new_node.data := data; new_node.next := node.next; node.data.Removed := true; node.next := new_node; if tail_ = node then tail_ := new_node; return true; end node := node.next; end end end return false; end; function TSOfficeContainer.Add(data: any): boolean; begin obj := {self.}GetBucketObj(data.ElementName); if ifnil(obj) then return false; obj.Add(data); return true; end; function TSOfficeContainer.Append(data: any): boolean; begin ind := child_[data.ElementName]; if ifnil(ind) or ind < current_index_ then begin obj := bucket_[current_index_]; if ifObj(obj) and obj.Name() = data.ElementName then obj.Add(data); else begin obj := new LinkList(data.ElementName); current_index_ := current_index_ > max_index_ ? current_index_ + 1 : max_index_ + 1; bucket_[current_index_] := obj; obj.Add(data); end end else if ind > current_index_ then begin obj := new LinkList(data.ElementName); bucket_[ind] := obj; obj.Add(data); current_index_ := ind; end else if ind = current_index_ then begin obj := bucket_[ind]; obj.Add(data); end return true; end; function TSOfficeContainer.Insert(data: any): boolean; begin i := max_index_ + 1; while i <= current_index_ do begin obj := bucket_[i]; if ifObj(obj) and obj.Name() = data.ElementName then begin obj.Add(data); return; end i++; end return ifnil(child_[data.ElementName]) ? {self.}Append(data) : {self.}Add(data); end; function TSOfficeContainer.InsertAfter(data: any; pos_data: any); begin for i:=0 to current_index_ do begin obj := bucket_[i]; if ifObj(obj) then if obj.InsertAfter(data, pos_data) then break; end end; function TSOfficeContainer.InsertBefore(data: any; pos_data: any); begin for i:=0 to current_index_ do begin obj := bucket_[i]; if ifObj(obj) then if obj.InsertBefore(data, pos_data) then break; end end; function TSOfficeContainer.GetElements(include_removed: boolean = true): array of tslobj; begin arr := array(); pf := function(arr, i) begin obj := bucket_[i]; if ifObj(obj) then begin node := obj.First(); while ifObj(node) do begin if include_removed or not node.data.Removed then arr[length(arr)] := node.data; node := node.next; end end end for i:=0 to current_index_ do ##pf(arr, i); for i:=min_index_ to -1 do ##pf(arr, i); return arr; end; function TSOfficeContainer.Get(name: string; index: integer); begin ind := child_[name]; arr := array(); obj := bucket_[ind]; if ifObj(obj) and obj.Name() = name then begin node := obj.First(); while ifObj(node) do begin if node.data.Removed then begin node := node.next; continue; end arr[length(arr)] := node.data; index--; if index = -1 then return node.data; node := node.next; end end i := max_index_ + 1; for i:=max_index_+1 to current_index_ do begin if i = ind then continue; obj := bucket_[i]; if ifObj(obj) and obj.Name() = name then begin node := obj.First(); while ifObj(node) do begin if node.data.Removed then begin node := node.next; continue; end arr[length(arr)] := node.data; index--; if index = -1 then return node.data; node := node.next; end end end return arr; end; function TSOfficeContainer.GetBucketObj(str: string): LinkList; begin ind := child_[str]; if ifnil(ind) then return nil; obj := bucket_[ind]; if not ifObj(obj) then begin obj := new LinkList(str); bucket_[ind] := obj; if ind > current_index_ then current_index_ := ind; end return obj; end; function LinkList.Create(name: string); begin head_ := new Node(); tail_ := head_; size_ := 0; name_ := name; end; function LinkList.Set(data: any) begin node := new Node(); node.data := data; if tail_ <> head_ then begin tail_.data.Removed := true; tail_.next := node; tail_ := node; size_++; end else begin head_.next := node; tail_ := node; size_ := 1; end end; function LinkList.Add(data: any) begin node := new Node(); node.data := data; tail_.next := node; tail_ := node; size_++; end; function LinkList.InsertAfter(data: any; pos_data: any): boolean; begin node := {self.}First(); while ifObj(node) do begin if node.data = pos_data then begin new_node := new Node(); new_node.data := data; new_node.next := node.next; node.next := new_node; if tail_ = node then tail_ := new_node; size_++; return true; end node := node.next; end return false; end; function LinkList.InsertBefore(data: any; pos_data: any): boolean; begin node := {self.}First(); prev := nil; while ifObj(node) do begin if node.data = pos_data then begin new_node := new Node(); new_node.data := data; new_node.next := node; if ifnil(prev) then head_.next := new_node; else prev.next := new_node; size_++; return true; end prev := node; node := node.next; end return false; end; function LinkList.Delete(data: any): boolean; begin node := {self.}First(); prev := nil; while ifObj(node) do begin if node.data = data then begin if ifnil(prev) then head_.next := node.next; else if tail_ = node then tail_ := prev; else prev.next := node.next; return true; end prev := node; node := node.next; end return false; end; function LinkList.Name(): string; begin return name_; end; function LinkList.Size(): integer; begin return size_; end; function LinkList.First(): Node; begin return head_ = tail_ ? nil : head_.next; end;