⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 galnklist.pas

📁 一个sql语法分析程序
💻 PAS
📖 第 1 页 / 共 4 页
字号:
        FFirstNode := FTail;
      if FLastNodeWasBound then
        FLastNode := FHead;
    end;
    // FCount := 0; Do not the count as for mirror list the count is always -1
    // if the list had strict first or last node, then correct them so that the
    // list would not start growing
  end;
end;

procedure TgaSharedDoubleList.DataOwnerDestroyed;
{:
procedure DataOwnerDestroyed is called when the DataOwner list is destroyed.
As all list data is also destroyed, the list is marked as "invalid"
}
begin
  FDataOwner := nil;
  FHead := nil;
  FTail := nil;
  FFirstNode := nil;
  FLastNode := nil;
  FCursor := nil;
end;

procedure TgaSharedDoubleList.InitDoubleList;
{:
procedure InitDoubleList overrides inherited InitDoubleList.
If the list is DataOwner, the inherited InitDoubleList is called.
If it is not, the Cursor it inited to the Head node and the Count is set to -1 -
tom indicate that the count is not valid for the mirror list
(all other initialization is done in CreateMirror constructor)
}
begin
  if IsDataOwner then
    inherited InitDoubleList
  else begin
    {set the cursor to the head node}
    FCursor := FHead;
    FCount := -1;
  end;
end;

procedure TgaSharedDoubleList.InsertAfterCurrent(AItem: Pointer; 
        MoveCursorToNewItem: boolean);
{:
procedure InsertAfterCurrent overrides inherited InsertAfterCurrent.
Reason: to allow the mirroring list with strict start or end position to
"absorb" a item if the current item is the last one in the list
}
var
  FirstNodeWasUnbound: Boolean;
begin
  // Unbind the first node
  FirstNodeWasUnbound := FFirstNode = FTail;
  if FirstNodeWasUnbound then
    FFirstNode := nil;
  if FLastNode <> Cursor then
    inherited InsertAfterCurrent(AItem, MoveCursorToNewItem)
  else begin
    FLastNode := InternalInsert(AItem, Cursor);
    FTail := FLastNode^.dllnNext;
    if MoveCursorToNewItem then
      FCursor := FLastNode;
  end;
  // rebind first node if it was bound before
  if FirstNodeWasUnbound then
    FFirstNode := Head^.dllnNext;
end;

procedure TgaSharedDoubleList.Notify(Ptr: Pointer; Action: TListNotification);
{:
procedure Notify overrides inherited Notify calls inherited Notify.
Also calls the dataowners Notify, if the lis is mirror  list
}
begin
  inherited Notify(Ptr, Action);
  if not IsDataOwner then
    DataOwner.Notify(Ptr, Action);
end;

procedure TgaSharedDoubleList.NotifyMasterChanged(ANode: PdllNode; Action: 
        TgaNodeNotification);
{:
procedure NotifyMasterChanged.
Occurs for mirroring lists if the list is in ActiveDataShare state,
This method should be dispatched after the NotifyNodeChange is finished
ANode - a node which is changing, Action - action to be performed.
}
begin
  case Action of
    nnAdded: begin
      if ANode^.dllnNext = FFirstNode then
      begin
        FHead := ANode;
        if ANode^.dllnPrev = FLastNode then
          FLastNode := ANode;
      end;
      if ANode^.dllnPrev = FLastNode then
        FTail := ANode;
    end;
    nnDeleted: begin
      if ANode = FCursor then
        if Eof then
          Last
        else
          Next;
      if ANode = FTail then
        if Assigned(FLastNode) then
          FTail := FLastNode^.dllnNext
        else
          FTail := ANode^.dllnNext;
      if ANode = FHead then
        if Assigned(FFirstNode) then
          FHead := FFirstNode^.dllnPrev
        else
          FHead := ANode^.dllnPrev;
      if ANode = FLastNode then
        if FFirstNode = Tail then
          FlastNode := Head
        else
          FLastNode := FLastNode^.dllnPrev;
      if ANode = FFirstNode then
        if FLastNode = Head then
          FFirstNode := Tail
        else
          FFirstNode := FFirstNode^.dllnNext;
    end;
    nnCleared: begin
      FHead := DataOwner.Head;
      FTail := DataOwner.Tail;
      if Assigned(FFirstNode) then
        FFirstNode := FTail;
      if Assigned(FLastNode) then
        FLastNode := FHead;
      FCursor := Head;
    end;
  end;
  FNodeRevID := DataOwner.NodeRevID;
  FCursorNodeRev := DataOwner.NodeRevID;
end;

procedure TgaSharedDoubleList.NotifyNodeChange(ANode: PdllNode; Action: 
        TgaNodeNotification);
{:
procedure NotifyNodeChange overrides inherited NotifyNodeChange.
If list IsDataOwner, the calls inherited NotifyNodeChange, otherwise calls
DataOwners NotifyNodeChange
}
begin
  if IsDataOwner then
    inherited NotifyNodeChange(ANode, Action)
  else
    DataOwner.NotifyNodeChange(ANode, Action);
end;

procedure TgaSharedDoubleList.RemoveActiveDataUser(ADataUser: 
        TgaSharedDoubleList);
{:
procedure RemoveActiveDataUser overrides inherited RemoveActiveDataUser.
Calls inherited RemoveActiveDataUser if the list is data owner, otherwise
raises an exception.
}
begin
  if not IsDataOwner then
    raise EgaLinkListError.CreateFmt(SListIsNotDataOwner, [SCantRemoveActiveDataUser]);
  inherited RemoveActiveDataUser(ADataUser);
end;

procedure TgaSharedDoubleList.RemoveDataUser(ADataUser: TgaSharedDoubleList);
{:
procedure RemoveDataUser overrides inherited RemoveDataUser.
Calls inherited RemoveDataUser if the list is data owner, otherwise
raises an exception.
}
begin
  if not IsDataOwner then
    raise EgaLinkListError.CreateFmt(SListIsNotDataOwner, [SCantRemoveDataUser]);
  inherited RemoveDataUser(ADataUser);
end;

procedure TgaSharedDoubleList.SetActiveDataShare(Value: Boolean);
{:
SetActiveDataShare is the write access method of the ActiveDataShare property.
The ACtiveDataShare can be changed only if the list is a mirror list.
If ActiveDataShare is disabled, the list is removed from
DataOwners.ActiveDataUsers list.
If ActiveDataShare is enabled, the list borders and cursor are validated, and
the list is added to the DataOwners ActiveDataUsers list.
}
begin
  if FActiveDataShare <> Value then
  begin
    if IsDataOwner then
      raise EgaLinkListError.CreateFmt(SListIsDataOwner, [SCantChangeActiveDataShare]);
    if Value then
    begin
      ValidateListBorders;
      ValidateCursor(True);
      DataOwner.AddActiveDataUser(Self);
    end else
      DataOwner.RemoveActiveDataUser(Self);
    FActiveDataShare := Value;
  end;
end;

procedure TgaSharedDoubleList.SetEndPos(APositionedList: TgaDoubleList; 
        StrictEndPos: Boolean);
{:
procedure SetEndPos - Sets the lits's last item to be the current item of the
APostionedList. If StrictEnPos is true, the items inserted to the DataOwnerList
between the last item and the item after that, are not accompanied to this list.
If StrictEnPos is False, all items added before the item next to the last item
set are absorbed into the list.
If the PostionedList is at Eof, then StrictEndPos do not have any effect.
APositionedList can be self.
}
begin
  if IsDataOwner then
    raise EgaLinkListError.CreateFmt(SListIsNotAMirroringList, [SCantSetTheStartOrEndPostions]);
  if (DataOwner <> APositionedList) and
    ((APositionedList is TgaSharedDoubleList) and
      (DataOwner <> (APositionedList as TgaSharedDoubleList).DataOwner)) then
    raise EgaLinkListError.CreateFmt(SListsDoNotShareData, [SCantSetTheStartOrEndPostions]);
  if APositionedList.Eof then
  begin
    FTail := APositionedList.Cursor;
    FLastNode := nil;
  end else
  begin
    FTail := APositionedList.FCursor^.dllnNext;
    if StrictEndPos then
      FLastNode := FTail^.dllnPrev
    else
      FLastNode := nil;
  end;
  // the node rev id-s must be reste before the validate
  FNodeRevID := 0;
  FCursorNodeRev := 0;
  ValidateListBorders;
  ValidateCursor(True);
end;

procedure TgaSharedDoubleList.SetStartPos(APositionedList: TgaDoubleList; 
        StrictStartPos: boolean);
{:
procedure SetStartPos - Sets the lits's first item to be the current item of the
APostionedList. If StrictStartPos is true, the items inserted to the
DataOwnerList between the first item and the item before that, are not
accompanied to this list. If StrictEnPos is False, all items added after the
item previous to the last item set are absorbed into the list.
If the PostionedList is at Bof, then StrictStartPos do not have any effect.
APositionedList can be self.
}
begin
  if IsDataOwner then
    raise EgaLinkListError.CreateFmt(SListIsNotAMirroringList, [SCantSetTheStartOrEndPostions]);
  if (DataOwner <> APositionedList) and
    ((APositionedList is TgaSharedDoubleList) and
      (DataOwner <> (APositionedList as TgaSharedDoubleList).DataOwner)) then
    raise EgaLinkListError.CreateFmt(SListsDoNotShareData, [SCantSetTheStartOrEndPostions]);
  if APositionedList.Bof then
  begin
    FHead := APositionedList.Cursor;
    FFirstNode := nil;
  end else
  begin
    FHead := APositionedList.Cursor^.dllnPrev;
    if StrictStartPos then
      FFirstNode := FHead^.dllnNext
    else
      FFirstNode := nil;
  end;
  // the node rev id-s must be reste before the validate
  FNodeRevID := 0;
  FCursorNodeRev := 0;
  ValidateListBorders;
  ValidateCursor(True);
end;

procedure TgaSharedDoubleList.ValidateCursor(CorrectIfInvalid: Boolean);
{:
procedure ValidateCursor - Checks the cursor of the list. If it is postioned
incorrectly, the if CorrectIfInvalid = True, Cursor is set to be at the Bof.
If False, an exception is raised.
}
begin
  if FCursorNodeRev <> DataOwner.NodeRevID then
  begin
    if not IsCursorCorrect then
    begin
      if CorrectIfInvalid then
        FCursor := Head
      else
        raise EgaLinkListError.CreateFmt(SMirrorListValidateFailed, [SInvalidCursor]);
    end;
    FCursorNodeRev := DataOwner.NodeRevID;
  end;
end;

procedure TgaSharedDoubleList.ValidateListBorders;
{:
procedure ValidateListBorders - checks if the list Tail and Head are inside the
dataowners list, and that the Strict astrt and end postions are correctly
preserved.
Raises an exception if the list can't be validated
}
begin
  if not IsDataOwner then
  begin
    { if the Master list node Revision ID is not changed, exit - list is up to
    date }
    if NodeRevID = DataOwner.NodeRevID then
      Exit;
    { Check wheter FFirstItem and FLastItem are part of master list. if are,
      then Tail and Head can be silently set (As they are used only for
      convience)}
    if Assigned(FFirstNode) then
    begin
      if DataOwner.IsNodeInside(FFirstNode) then
      begin
        if FFirstNode = DataOwner.Head then
          raise EgaLinkListError.CreateFmt(SMirrorListValidateFailed, [SStrictFirstNodePointsToTheHeadOfMasterList]);
        FHead := FFirstNode^.dllnPrev;
        if (FFirstNode = FTail) and Assigned(FLastNode) then
          FLastNode := FHead;
      end else
        raise EgaLinkListError.CreateFmt(SMirrorListValidateFailed, [SStrictFirstNodeNotPartOfTheMasterList]);
    end else
      if not DataOwner.IsNodeInside(FHead) then
        raise EgaLinkListError.CreateFmt(SMirrorListValidateFailed, [SHeadNodeNotInMasterList]);
    if Assigned(FLastNode) then
      FTail := FLastNode^.dllnNext;
    { begin
       it is not strictly required to check wheter the tail node is inside the
        master list. As the head node is (verified), then if
        IsList(Head, Tail) = True, and provided that the master list is not
        corrupted, the last node has to be inside master list
      if DataOwner.IsNodeInside(FLastNode) then
      begin
        if FLastNode = DataOwner.Tail then
          raise EgaLinkListError.CreateFmt(SMirrorListValidateFailed, ['Strict last node is invalid - points to the Tail item of master list']);
        FTail := FLastNode^.dllnNext;
       end else
        raise EgaLinkListError.CreateFmt(SMirrorListValidateFailed, ['Strict last node is invalid - not part of the master list']);
    end else
      if not DataOwner.IsNodeInside(FTail) then
        raise EgaLinkListError.CreateFmt(SMirrorListValidateFailed, ['Tail node is invalid - not part of the master list']);}
    if not IsList(FHead, FTail) then
      raise EgaLinkListError.CreateFmt(SMirrorListValidateFailed, [SInvalidHeadOrTail]);
    { remember the last validate time }
    FNodeRevID := DataOwner.NodeRevID;
  end;
end;

{
**************************** TgaDoubleListBookmark *****************************
}
constructor TgaDoubleListBookmark.Create(AOwnerList: TgaDoubleList);
{:
Constructor Create overrides the inherited Create. 
First inherited Create is called, then the internal data structure is
initialized to store tha list for which a bookmark was created and current
postion inside this list. 
}
begin
  inherited Create;
  FOwnerList := AOwnerList;
  FCursor := FOwnerList.Cursor;
  FNodeRevID := FOwnerList.NodeRevID;
end;

function TgaDoubleListBookmark.GetIsValid: Boolean;
{:
function GetIsValid overrides inherited GetIsValid.
Returns: True, if the Bookmark is valid
False, if it is not.
}
begin
  if NodeRevID = OwnerList.NodeRevID then
    Result := True
  else begin
    Result := OwnerList.IsNodeInside(Cursor);
    if Result then
      FNodeRevID := OwnerList.NodeRevID;
  end;
end;

function TgaDoubleListBookmark.GetItem: Pointer;
{:
function GetItem overrides inherited GetItem.
Returns: A pointer to the item represented by the Bookmark
}
begin
  if not IsValid then
    raise EgaListBookmarkError.CreateFmt(SInvalidBookmark, [SCantGetItem]);
  Result := Cursor.dllnData;
end;

function TgaDoubleListBookmark.IsValidFor(AList: TgaDoubleList): Boolean;
{:
function IsValidFor checks if the bookmark is valid for a list represented by
the AList.
Returns: True, if the AList uses the same data as bookmarks owner list
(AList = OwnerList or AList.DataOwner = OwnerList.DataOwner, if this compare
is (partially) applicable), and the node represented by the bookmark's cursor is
inside the AList
}
begin
  // use IsValid if possible as IsValid is more optimized
  if AList = OwnerList then
    Result := IsValid
  else begin
    if (AList is TgaSharedDoubleList) and (OwnerList is TgaSharedDoubleList) then
      Result := TgaSharedDoubleList(OwnerList).DataOwner = TgaSharedDoubleList(AList).DataOwner
    else if AList is TgaSharedDoubleList then
      Result := OwnerList = TgaSharedDoubleList(AList).DataOwner
    else if OwnerList is TgaSharedDoubleList then
      Result := TgaSharedDoubleList(OwnerList).DataOwner = AList
    else
      Result := False;
    if not Result then
      Exit;
    Result := AList.IsNodeInside(Cursor);
  end;
end;

procedure TgaDoubleListBookmark.SetItem(Value: Pointer);
{:
procedure SetItem overrides inherited SetItem.
Changes the item represented by the bookmark to the new Value.
}
var
  tmpItem: Pointer;
begin
  if not IsValid then
    raise EgaListBookmarkError.CreateFmt(SInvalidBookmark, [SCantSetItem]);
  tmpItem := Cursor^.dllnData;
  if tmpItem <> Value then
  begin
    Cursor^.dllnData := Value;
    OwnerList.NotifyChange(tmpItem, Value);
  end;
end;

end.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -