OfficeXml/utils/TSOfficeContainer.tsf

365 lines
8.9 KiB
Plaintext

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 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 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.GetElements(include_removed: boolean = true): array of tslobj;
begin
arr := array();
for i:=min_index_ to current_index_ do
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
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.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;