814 lines
19 KiB
Plaintext
814 lines
19 KiB
Plaintext
unit utslvclauxiliary;
|
||
{**
|
||
@explan(说明) tslvcl 辅助库 %%
|
||
**}
|
||
interface
|
||
type TCharDiscrimi=class
|
||
static CD_SMA;
|
||
static CD_BGA;
|
||
static CD_SMZ;
|
||
static CD_BGZ;
|
||
static CD_UDL;
|
||
static CD_NIN;
|
||
static CD_ZER;
|
||
static CD_ISOK;
|
||
class function sinit();virtual;
|
||
begin
|
||
if not CD_ISOK then
|
||
begin
|
||
K := 1;
|
||
CD_SMA := ord("a");
|
||
CD_BGA := ord("A");
|
||
CD_SMZ := ord("z");
|
||
CD_BGZ := ord("Z");
|
||
CD_UDL := ord("_");
|
||
CD_NIN := ord("9");
|
||
CD_ZER := ord("0");
|
||
CD_ISOK := 1;
|
||
end
|
||
end
|
||
class function IsLetter(cc);
|
||
begin
|
||
return IsUppercaseLetter(CC)OR IsLowercaseLetter(cc);
|
||
end
|
||
class function IsLowercaseLetter(cc);
|
||
begin
|
||
return(cc >= CD_SMA)and(cc <= CD_SMZ);
|
||
end
|
||
class function IsUppercaseLetter(cc);
|
||
begin
|
||
return(cc >= CD_BGA)and(cc <= CD_BGZ);
|
||
end
|
||
class function IsNumber(cc);
|
||
begin
|
||
return(cc >= CD_ZER)and(cc <= CD_NIN);
|
||
end
|
||
class function IsVariableName(s);
|
||
begin
|
||
if ifstring(s)and length(s)>= 1 then
|
||
begin
|
||
cc := ord(s[1]);
|
||
if IsLetter(cc)or cc=CD_UDL then
|
||
begin
|
||
for i := 2 To length(s) do
|
||
begin
|
||
cc := ord(s[i]);
|
||
if not(IsLetter(cc)or IsNumber(cc)or(cc=CD_UDL))then
|
||
begin
|
||
return false;
|
||
end
|
||
end
|
||
return true;
|
||
end
|
||
end
|
||
return 0;
|
||
end
|
||
function create();
|
||
begin
|
||
sinit();
|
||
end
|
||
end
|
||
type TByteDataOP=class() //位操作类
|
||
{**
|
||
@explan(说明) 位操作封装
|
||
**}
|
||
{**
|
||
@example(范例:byte数组转整数)
|
||
oa := new TByteDataOP();
|
||
echo tostn(oa.bytesasint(array(1,1,1,1)));
|
||
|
||
**}
|
||
{**
|
||
@example(范例:整数转byte数组)
|
||
oa := new TByteDataOP();
|
||
echo tostn(oa.intasbytes(235);
|
||
|
||
**}
|
||
class function BytesAsInt(a);
|
||
begin
|
||
{**
|
||
@explan(说明) 四个byte转换为integer %%
|
||
@param(a)(array) 正式表示的四字节 %%
|
||
@return(integer) 组装好的整数 %%
|
||
**}
|
||
uu := a[0];
|
||
ul := a[1];
|
||
lu := a[2];
|
||
ll := a[3];
|
||
l := makelong(ll,lu,8);
|
||
u := makelong(ul,uu,8);
|
||
return makelong(l,u);
|
||
end
|
||
class function IntAsBytes(v);
|
||
begin
|
||
{**
|
||
@explan(说明) 整数转换为byte 数组(整数数组模拟) %%
|
||
@param(v)(integer) %%
|
||
@return(array) 模拟的byte数组 %%
|
||
**}
|
||
lowuperdword(v,l,u);
|
||
lowuperdword(l,ll,lu);
|
||
lowuperdword(u,ul,uu);
|
||
return array(uu,ul,lu,ll);
|
||
end
|
||
class function ShortsToInt(a);
|
||
begin
|
||
{**
|
||
@explan(说明) 两个short转换为一个int %%
|
||
@param(a)(array) 两个元素的数组 %%
|
||
@return(integer) 整数 %%
|
||
**}
|
||
l := a[1];
|
||
u := a[0];
|
||
return makelong(l,u);
|
||
end
|
||
class function IntToShorts(v);
|
||
begin
|
||
{**
|
||
@explan(说明) 整数转换为两个short 数组(整数数组模拟) %%
|
||
@param(v)(integer) %%
|
||
@return(array) 模拟的short数组 %%
|
||
**}
|
||
lowuperdword(v,l,u);
|
||
return array(l,u);
|
||
end
|
||
class function StrAsBytes(s);
|
||
begin
|
||
{**
|
||
@explan(说明) 字符串转换为byte数组 %%
|
||
@param(s)(string) 字符串 %%
|
||
@return(array) 模拟的byte数组 %%
|
||
**}
|
||
r := array();
|
||
for i := 0 to length(s) do r[i]:= ord(s[i]);
|
||
return r;
|
||
end
|
||
class function BytesAsStr(b);
|
||
begin
|
||
{**
|
||
@explan(说明) byte数组转字符串 %%
|
||
@param(b)(array) byte数组 %%
|
||
@return(string) 字符串
|
||
**}
|
||
r := "";
|
||
for i := 0 to length(b)-1 do r += chr(b[i]);
|
||
return r;
|
||
end
|
||
end
|
||
|
||
//**************************数组链表类******************************************
|
||
type tarray1dlk=class //从0开始
|
||
private
|
||
_len;
|
||
FCompareValue;
|
||
protected _data; //数据
|
||
public
|
||
{**
|
||
@explan(说明) 一维链表类 %%
|
||
@param(_len)(integer) 长度 %%
|
||
@param(_data)(array) 数据 %%
|
||
@param(CompareValue)(fpointer) 回调函数 function(v1,v2)begin return v1 = v2 ; end %%
|
||
**}
|
||
function setdata(data);
|
||
begin
|
||
{**
|
||
@explan(说明) 一次性设置数据 %%
|
||
@param(data)(array) 数据 %%
|
||
**}
|
||
_data := data;
|
||
_len := length(data);
|
||
end
|
||
function clean();
|
||
begin
|
||
{**
|
||
@explan(说明) 清空 %%
|
||
**}
|
||
_data := array();
|
||
_len := 0;
|
||
end
|
||
function create(); //构造
|
||
begin
|
||
{**
|
||
@explan(说明) 构造 %%
|
||
**}
|
||
_data := array();
|
||
_len := 0;
|
||
end
|
||
function CallCompare(v1,v2,f);
|
||
begin
|
||
if datatype(f)=7 then return call(f,v1,v2);
|
||
if datatype(FCompareValue)=7 then return call(FCompareValue,v1,v2);
|
||
return v1=v2;
|
||
end
|
||
function append(v) //追加
|
||
begin
|
||
{**
|
||
@explan(说明) 追加 %%
|
||
@param(v)() tsl数据 %%
|
||
**}
|
||
_data[_len++]:= v;
|
||
end;
|
||
function geti(i); //获取
|
||
begin
|
||
{**
|
||
@explan(说明) 获得 %%
|
||
@param(i)(integer) id %%
|
||
**}
|
||
return _data[i];
|
||
end
|
||
function seti(i,v); //设置值
|
||
begin
|
||
{**
|
||
@explan(说明) 设置值 %%
|
||
@param(i)(integer) id %%
|
||
@param(v)() tsl数据 %%
|
||
**}
|
||
if i >= 0 and i<_len then
|
||
begin
|
||
_data[i]:= v;
|
||
end
|
||
end
|
||
function deli(i); //删除
|
||
begin
|
||
{**
|
||
@explan(说明) 删除 %%
|
||
@param(i)(integer) id %%
|
||
**}
|
||
//len := length(_data)-1;
|
||
if i<0 or i >= _len then return-1;
|
||
_len -= 1;
|
||
return deleteindex(_data,i,1);
|
||
end
|
||
function delis(i);
|
||
begin
|
||
{**
|
||
@explan(说明) 批量删除 %%
|
||
@param(i)(array) 删除的id %%
|
||
**}
|
||
dels := getdels(i);
|
||
for ii,v in dels do deli(v);
|
||
end
|
||
function getdels(i); //删除多行
|
||
begin
|
||
{**
|
||
@ignore (忽略) %%
|
||
@explan(说明) 批量删除 %%
|
||
@param(i)(array) 删除的id %%
|
||
**}
|
||
ii := sselect thisrow from(i union2 array())where(thisrow >= 0 and thisrow<_len)order by thisrow end;
|
||
dels := array();
|
||
ix := 0;
|
||
for iv in ii do
|
||
begin
|
||
dels[iv]:= ii[iv]-ix;
|
||
ix++;
|
||
end
|
||
return dels;
|
||
end
|
||
function insertbefor(v,i); //之前插入
|
||
begin
|
||
{**
|
||
@explan(说明) 在i之前插入 %%
|
||
@param(v)() 插入数据 %%
|
||
@param(i)(integer) id %%
|
||
**}
|
||
if not ifnumber(i)then return;
|
||
if i >= _len then return append(v);
|
||
else if i <= 0 then
|
||
begin
|
||
_data := array(v)union _data;
|
||
end else
|
||
begin
|
||
_data := _data[0:(i-1)]union array(v)union _data[i:];
|
||
end
|
||
_len++;
|
||
end
|
||
function insertafter(v,i); //之后插入
|
||
begin
|
||
{**
|
||
@explan(说明) 在i之后插入 %%
|
||
@param(v)() 插入数据 %%
|
||
@param(i)(integer) id %%
|
||
**}
|
||
if not ifnumber(i)then return;
|
||
if i >= _len then return append(v);
|
||
else if i<0 then
|
||
begin
|
||
_data := array(v)union _data;
|
||
end else
|
||
begin
|
||
_data := _data[0:i]union array(v)union _data[i+1:];
|
||
end
|
||
_len++;
|
||
end
|
||
function findvid(v1,func,lx); //查找序号,func通过送入的比较函数
|
||
begin
|
||
{**
|
||
@explan(说明) 查找序号和v1 匹配的id %%
|
||
@param(v1)(any) tsl数据 %%
|
||
@param(lx)(bool) 逆序查找 %%
|
||
@param(func)(fpointer) 比较函数 第一个参数为 数组中对象,第二个参数为输入判断条件 %%
|
||
**}
|
||
ret :=-1;
|
||
if lx then
|
||
begin
|
||
for i := length(_data)downto 0 do
|
||
begin
|
||
if CallCompare(_data[i],v1,func)then return i;
|
||
end
|
||
return ret;
|
||
end
|
||
for i,v in _data do
|
||
begin
|
||
if CallCompare(v,v1,func)then
|
||
begin
|
||
return i;
|
||
end
|
||
end
|
||
return ret;
|
||
end
|
||
function getprev(v1); //获得上一个
|
||
begin
|
||
{**
|
||
@explan(说明) 获得上一个 匹配的id %%
|
||
@param(v1)() tsl数据 %%
|
||
**}
|
||
if _len<2 then return nil;
|
||
id :=-1;
|
||
for i,v in _data do
|
||
begin
|
||
if CallCompare(v,v1)then
|
||
begin
|
||
id := i;
|
||
break;
|
||
end
|
||
end
|
||
return _data[id-1];
|
||
end
|
||
function getnext(v1); //获得下一个
|
||
begin
|
||
{**
|
||
@explan(说明) 获得下一个 匹配的id %%
|
||
@param(v1)() tsl数据 %%
|
||
**}
|
||
if _len<2 then return nil;
|
||
id := _len;
|
||
for i,v in _data do
|
||
begin
|
||
if CallCompare(v,v1)then
|
||
begin
|
||
id := i;
|
||
break;
|
||
end
|
||
end
|
||
return _data[id+1];
|
||
end
|
||
function ergodic(f); //循环处理
|
||
begin
|
||
{**
|
||
@explan(说明) 循环所有数据 %%
|
||
@param(f)(fpointer) 处理函数 function(id,v) begin end %%
|
||
**}
|
||
if(datatype(f)<> 7)then return nil;
|
||
for i,v in _data do
|
||
begin
|
||
ret := call(f,i,v); //## f(i,v);
|
||
if ret=-1 then break;
|
||
end
|
||
return 1;
|
||
end
|
||
function data(); //数组数据
|
||
begin
|
||
{**
|
||
@explan(说明) 返回所有数据 %%
|
||
**}
|
||
return _data;
|
||
end
|
||
function replace(i,v) //替换
|
||
begin
|
||
{**
|
||
@explan(说明) 替换 %%
|
||
@param(i)(integer) 序号 %%
|
||
@param(v)() tsl数据 %%
|
||
**}
|
||
if i >= 0 and i<_len then
|
||
begin
|
||
ret := _data[i];
|
||
_data[i]:= v;
|
||
return ret;
|
||
end else
|
||
return nil;
|
||
end
|
||
function len(); //大小
|
||
begin
|
||
{**
|
||
@explan(说明) 长度 %%
|
||
**}
|
||
//return length(_data);
|
||
return _len;
|
||
end
|
||
function setorder(i,j);
|
||
begin
|
||
{**
|
||
@explan(说明) 设置元素位置 %%
|
||
@param(i)(integer)原始位置 %%
|
||
@param(j)(integer) 移动后的位置
|
||
**}
|
||
if j>_len-1 then j := _len-1;
|
||
if j<0 then j := 0;
|
||
if i=j or(i<0 and i>_len)then exit;
|
||
sl := createserial(i,j);
|
||
for ii := 0 to length(sl)-2 do
|
||
begin
|
||
SwapNoCheck(sl[ii],sl[ii+1]);
|
||
end
|
||
end
|
||
function swap(i,j); //交换
|
||
begin
|
||
{**
|
||
@explan(说明) 交换 %%
|
||
@param(i)(integer) 序号 %%
|
||
@param(j)(integer) 序号 %%
|
||
**}
|
||
if ifnumber(i)and ifnumber(j)and i <> j and i >= 0 and j >= 0 and i<_len and j<_len then
|
||
begin
|
||
SwapNoCheck(i,j);
|
||
//vi := _data[i];
|
||
//_data[i]:=_data[j];
|
||
//_data[j] := vi;
|
||
end
|
||
end
|
||
property CompareValue read FCompareValue write FCompareValue;
|
||
private
|
||
function SwapNoCheck(i,j);
|
||
begin
|
||
vi := _data[i];
|
||
_data[i]:= _data[j];
|
||
_data[j]:= vi;
|
||
end
|
||
function createserial(i,j);
|
||
begin
|
||
if j>i then return i -> j;
|
||
r := array();
|
||
kk := 0;
|
||
for ii := i downto j do r[kk++]:= ii;
|
||
return r;
|
||
end
|
||
function moveto(i,j); //将i移动到j前面
|
||
begin
|
||
{**
|
||
@ignore 忽略%%
|
||
@explan(说明) 将i移动到j前面 %%
|
||
@param(i)(integer) 序号 %%
|
||
@param(j)(integer) 序号 %%
|
||
**}
|
||
if not(ifnumber(i)and i >= 0 and i<_len)then return-1;
|
||
if ifnil(j)then j := 0;
|
||
if i=j then return-1;
|
||
vi := geti(i);
|
||
insertbefor(vi,j);
|
||
if i>j then
|
||
begin
|
||
deli(i+1);
|
||
end else
|
||
begin
|
||
deli(i);
|
||
end
|
||
end
|
||
end
|
||
type tstrindexarray = class
|
||
{**
|
||
@explan(数组类型) 忽略字符串下标的大小写%%
|
||
**}
|
||
function create();
|
||
begin
|
||
FData := array();
|
||
FRows := array();
|
||
end
|
||
function DeleteIndex(idx);
|
||
begin
|
||
{**
|
||
@explan(说明) 删除指定下标 %%
|
||
**}
|
||
if ifnil(idx)or ifobj(idx)then return 0;
|
||
if ifstring(idx)then
|
||
begin
|
||
lidx := lowercase(idx);
|
||
::deleteindex(FData,lidx,0);
|
||
return ::deleteindex(FRows,lidx,0);
|
||
end
|
||
::deleteindex(FData,idx,0);
|
||
return ::deleteindex(FRows,idx,0);
|
||
end
|
||
function Operator[1](index,value);
|
||
begin
|
||
if ifstring(index)then
|
||
begin
|
||
li := lowercase(index);
|
||
end else
|
||
li := index;
|
||
if ifnone(value)then
|
||
begin
|
||
r := FData[li];
|
||
if r then return r;
|
||
r := new tstrindexarray();
|
||
FData[li]:= r;
|
||
FRows[li]:= index;
|
||
return r;
|
||
end
|
||
FRows[li]:= index;
|
||
if ifarray(value)and value then
|
||
begin
|
||
r := new tstrindexarray();
|
||
FData[li]:= r;
|
||
for i,v in value do
|
||
begin
|
||
r[i]:= v;
|
||
end
|
||
return;
|
||
end
|
||
FData[li]:= value;
|
||
end
|
||
function Operator[](index);
|
||
begin
|
||
if ifstring(index)then r := FData[lowercase(index)];
|
||
else r := FData[index];
|
||
//if ifnil(r) then return NeW tstrindexarray();
|
||
return r;
|
||
end
|
||
function Size();
|
||
begin
|
||
{**
|
||
@explan(说明) 获得长度 %%
|
||
**}
|
||
return Length(FData);
|
||
end
|
||
function toarray(n);
|
||
begin
|
||
{**
|
||
@explan(说明) 获得tsl array %%
|
||
@param(n)(bool) false 返回小写下标,true 返回原始下标 %%
|
||
**}
|
||
r := array();
|
||
for i,v in FData do
|
||
begin
|
||
if v is class(tstrindexarray)then
|
||
begin
|
||
r[n?i:FRows[i]]:= v.toarray(n);
|
||
end else
|
||
r[n?i:FRows[i]]:= v;
|
||
end
|
||
return r;
|
||
end
|
||
function IndexNames();
|
||
begin
|
||
{**
|
||
@explan(说明) 获得 所有下标 %%
|
||
**}
|
||
return FRows;
|
||
end
|
||
function HaveIndex();
|
||
begin
|
||
{**
|
||
@explan(说明) 判断是否有某个下标 %%
|
||
**}
|
||
o := self(true);
|
||
for i := 1 to Paramcount do
|
||
begin
|
||
if not(o is class(tstrindexarray))then return false;
|
||
id := params[i];
|
||
if ifnil(o.TrueIndex(id))then return false;
|
||
o := o[id];
|
||
end
|
||
return true;
|
||
end
|
||
function TrueIndex(n);
|
||
begin
|
||
{**
|
||
@explan(说明) 获得对应下标 %%
|
||
**}
|
||
if ifstring(n)then idx := lowercase(n);
|
||
else idx := n;
|
||
return FRows[idx];
|
||
end
|
||
property Data write SetData;
|
||
function destroy();
|
||
begin
|
||
FData := nil;
|
||
FRows := nil;
|
||
end
|
||
private
|
||
function SetData(d);
|
||
begin
|
||
if not ifarray(d)then return false;
|
||
FRows := array();
|
||
FData := array();
|
||
si := self(true);
|
||
for i,v in d do
|
||
begin
|
||
si[i]:= v;
|
||
end
|
||
return true;
|
||
end
|
||
FData;
|
||
FRows;
|
||
end
|
||
type tnumindexarray = Class
|
||
{**
|
||
@explan(说明) 数字下标数组对象 %%
|
||
**}
|
||
private
|
||
FData;
|
||
public
|
||
function Create();virtual;
|
||
begin
|
||
{**
|
||
@explan(说明) 构造函数 %%
|
||
**}
|
||
FData := array();
|
||
end
|
||
function Operator[1](idx,v);
|
||
begin
|
||
{**
|
||
@explan(说明)通过下标设置元素 %%
|
||
**}
|
||
return SetValueByIndex(idx,v);
|
||
end
|
||
function Operator[](idx);
|
||
begin
|
||
{**
|
||
@explan(说明) 通过下标获取元素 %%
|
||
**}
|
||
return GetValueByIndex(idx);
|
||
end
|
||
function length();
|
||
begin
|
||
{**
|
||
@explan(说明) 获得数据长度 %%
|
||
@return(integer) 长度 %%
|
||
**}
|
||
return length(FData);
|
||
end
|
||
function Push({value1,value2,....});
|
||
begin
|
||
{**
|
||
@explan(说明) 在末尾追加元素,参数个数不定 %%
|
||
**}
|
||
r := length(FData);
|
||
r1 := r;
|
||
for i := 0 to ParamCount-1 do
|
||
begin
|
||
FData[r]:= Params[i+1];
|
||
r++;
|
||
end
|
||
if r1 <> r then LengthChanged(r1-r);
|
||
return r;
|
||
end
|
||
function Pop();
|
||
begin
|
||
{**
|
||
@explan(说明) 弹出末尾的元素 %%
|
||
**}
|
||
if FData then
|
||
begin
|
||
id := length(FData)-1;
|
||
r := FData[id];
|
||
deleteindex(FData,id);
|
||
LengthChanged(-1);
|
||
return r;
|
||
end
|
||
return nil;
|
||
end
|
||
function IndexOf(v);
|
||
begin
|
||
for i,vi in FData do
|
||
begin
|
||
if vi=v then return i;
|
||
end
|
||
return-1;
|
||
end
|
||
function LastIndexOf(v);
|
||
begin
|
||
for i := length(FData)-1 downto 0 do
|
||
begin
|
||
if v=FData[i]then return i;
|
||
end
|
||
return-1;
|
||
end
|
||
function GetValueByIndex(idx);virtual;
|
||
begin
|
||
return FData[idx];
|
||
end
|
||
function SetValueByIndex(idx,v);virtual;
|
||
begin
|
||
len := length(FData);
|
||
if idx<0 then return nil;
|
||
if idx <= len then
|
||
begin
|
||
FData[idx]:= v;
|
||
end else
|
||
begin
|
||
for i := len to idx do FData[i]:= nil;
|
||
FData[idx]:= v;
|
||
return v;
|
||
end
|
||
end
|
||
function splice({startid,sellength,value1,valfue2,....});
|
||
begin
|
||
{**
|
||
@explan(说明) 替换元素,第一个参数为开始位置,第二个为替换的个数,以后的参数为用来替换的值,返回被替换的值%%
|
||
**}
|
||
p := params;
|
||
st := p[0];
|
||
sl := p[1];
|
||
sl := ifnil(sl)?inf:sl;
|
||
sl := sl<0?0:sl;
|
||
len := length(FData);
|
||
st := st<0?0:st;
|
||
st := st >= len?(len):st;
|
||
et := st+sl;
|
||
et := et >= len?(len):et;
|
||
r := array();
|
||
idx := 0;
|
||
for i := st to et-1 do
|
||
begin
|
||
r[idx++]:= FData[i];
|
||
end
|
||
r1 := FData[0:st-1];
|
||
r2 := FData[et:len-1];
|
||
FData := r1 union p[2:]union r2;
|
||
if len <> length(FData)then LengthChanged(length(FData)-len);
|
||
return r;
|
||
end
|
||
function shift();
|
||
begin
|
||
{**
|
||
@explan(说明) 弹出头部元素 %%
|
||
**}
|
||
r := nil;
|
||
len := length(FData);
|
||
if len>0 then
|
||
begin
|
||
deleteindex(FData,0);
|
||
LengthChanged(-1);
|
||
end
|
||
return len<1?(len):(len-1);
|
||
end
|
||
function unshift({value1,value2,....});
|
||
begin
|
||
{**
|
||
@explan(说明) 在数据头部加入元素,个数待定 %%
|
||
**}
|
||
p := Params;
|
||
if p then
|
||
begin
|
||
FData := p union FData;
|
||
LengthChanged(1);
|
||
end
|
||
return length(FData);
|
||
end
|
||
function swap(i,j);
|
||
begin
|
||
{**
|
||
@explan(说明) 交换下标中的值 %%
|
||
**}
|
||
if i=j then return false;
|
||
len := length(FData);
|
||
if i >= 0 and i<len and j >= 0 and j<len then
|
||
begin
|
||
t := FData[i];
|
||
FData[i]:= FData[j];
|
||
FData[j]:= t;
|
||
return true;
|
||
end
|
||
return false;
|
||
end
|
||
function pushs(vs);
|
||
begin
|
||
return callinarray(thisfunction(push),vs);
|
||
end
|
||
function unshifts(vs);
|
||
begin
|
||
return callinarray(thisfunction(unshift),vs);
|
||
end
|
||
function splices(startid,sellength,vs);
|
||
begin
|
||
if ifarray(vs)then return callinarray(thisfunction(splice),array(startid,sellength)union vs);
|
||
return array();
|
||
end
|
||
function LengthChanged(n);virtual;
|
||
begin
|
||
end
|
||
property Data read FData;
|
||
{**
|
||
@param(Data)(array) 数据 %%
|
||
**}
|
||
end
|
||
|
||
|
||
implementation
|
||
|
||
initialization
|
||
|
||
|
||
end. |