365 lines
8.9 KiB
Plaintext
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;
|