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

📄 hashes.pas

📁 分析torrent的东西是拿别人的
💻 PAS
📖 第 1 页 / 共 2 页
字号:
    self.f_Keys[k][x].ItemIndex := ItemIndex;    { Add the index to the spares list. }    SetLength(self.f_SpareItems, Length(self.f_SpareItems) + 1);    self.f_SpareItems[High(self.f_SpareItems)] := i;  end else begin    { No, create a new one. }    SetLength(self.f_Keys[k], Length(self.f_Keys[k]) + 1);    self.f_Keys[k][High(self.f_Keys[k])].Key := Key;    self.f_Keys[k][High(self.f_Keys[k])].ItemIndex := ItemIndex;    self.f_Keys[k][High(self.f_Keys[k])].Hash := HashThis(Key);  end;end;function THash.FFindKey(const Key: string; var k, x: integer): boolean;var  i: integer;  h: cardinal;begin  { Which bucket? }  h := HashThis(Key);  k := h and f_CurrentItemMask;  result := false;  { Look for it. }  for i := 0 to High(self.f_Keys[k]) do    if (self.f_Keys[k][i].Hash = h) or true then      if (self.f_Keys[k][i].Key = Key) then begin        { Found it! }        result := true;        x := i;        break;      end;end;procedure THash.Rename(const Key, NewName: string);var  k, x, i: integer;begin  { Hash has been modified, so disallow Next. }  self.f_NextAllowed := false;  if (self.FFindKey(Key, k, x)) then begin    { Remember the ItemIndex. }    i := self.f_Keys[k][x].ItemIndex;    { Overwrite key with the last in the list. }    self.f_Keys[k][x] := self.f_Keys[k][High(self.f_Keys[k])];    { Delete the last in the list. }    SetLength(self.f_Keys[k], Length(self.f_Keys[k]) - 1);    { Create the new item. }    self.FSetOrAddKey(NewName, i);  end else    raise EHashFindError.CreateFmt('Key "%s" not found', [Key]);  self.FAutoCompact;end;function THash.CurrentKey: string;begin  if (not (self.f_NextAllowed)) then    raise EHashIterateError.Create('Cannot find CurrentKey as the hash has '      + 'been modified since Restart was called')  else if (self.f_CurrentKey = '') then    raise EHashIterateError.Create('Cannot find CurrentKey as Next has not yet '      + 'been called after Restart')  else    result := self.f_CurrentKey;end;function THash.Next: boolean;begin  if (not (self.f_NextAllowed)) then    raise EHashIterateError.Create('Cannot get Next as the hash has '      + 'been modified since Restart was called');  result := false;  if (self.f_CurrentIterator.ck = -1) then begin    self.f_CurrentIterator.ck := 0;    self.f_CurrentIterator.cx := 0;  end;  while ((not result) and (self.f_CurrentIterator.ck <= f_CurrentItemMaxIdx)) do begin    if (self.f_CurrentIterator.cx < Length(self.f_Keys[self.f_CurrentIterator.ck])) then begin      result := true;      self.f_CurrentKey := self.f_Keys[self.f_CurrentIterator.ck][self.f_CurrentIterator.cx].Key;      inc(self.f_CurrentIterator.cx);    end else begin      inc(self.f_CurrentIterator.ck);      self.f_CurrentIterator.cx := 0;    end;  end;end;procedure THash.Restart;begin  self.f_CurrentIterator.ck := -1;  self.f_CurrentIterator.cx := 0;  self.f_NextAllowed := true;end;function THash.FGetItemCount: integer;var  i: integer;begin  { Calculate our item count. }  result := 0;  for i := 0 to f_CurrentItemMaxIdx do    inc(result, Length(self.f_Keys[i]));end;function THash.FAllocItemIndex: integer;begin  if (Length(self.f_SpareItems) > 0) then begin    { Use the top SpareItem. }    result := self.f_SpareItems[High(self.f_SpareItems)];    SetLength(self.f_SpareItems, Length(self.f_SpareItems) - 1);  end else begin    result := self.FIndexMax + 1;  end;end;procedure THash.Compact;var  aSpaces: array of boolean;  aMapping: array of integer;  i, j: integer;begin  { Find out where the gaps are. We could do this by sorting, but that's at    least O(n log n), and sometimes O(n^2), so we'll go for the O(n) method,    even though it involves multiple passes. Note that this is a lot faster    than it looks. Disabling this saves about 3% in my benchmarks, but uses a    lot more memory. }  if (self.AllowCompact) then begin    SetLength(aSpaces, self.FIndexMax + 1);    SetLength(aMapping, self.FIndexMax + 1);    for i := 0 to High(aSpaces) do      aSpaces[i] := false;    for i := 0 to High(aMapping) do      aMapping[i] := i;    for i := 0 to High(self.f_SpareItems) do      aSpaces[self.f_SpareItems[i]] := true;    { Starting at the low indexes, fill empty ones from the high indexes. }    i := 0;    j := self.FIndexMax;    while (i < j) do begin      if (aSpaces[i]) then begin        while ((i < j) and (aSpaces[j])) do          dec(j);        if (i < j) then begin          aSpaces[i] := false;          aSpaces[j] := true;          self.FMoveIndex(j, i);          aMapping[j] := i        end;      end else        inc(i);    end;    j := self.FIndexMax;    while (aSpaces[j]) do      dec(j);    { Trim the items array down to size. }    self.FTrimIndexes(j + 1);    { Clear the spaces. }    SetLength(self.f_SpareItems, 0);    { Update our buckets. }    for i := 0 to f_CurrentItemMaxIdx do      for j := 0 to High(self.f_Keys[i]) do        self.f_Keys[i][j].ItemIndex := aMapping[self.f_Keys[i][j].ItemIndex];  end;end;procedure THash.FAutoCompact;begin  if (self.AllowCompact) then    if (Length(self.f_SpareItems) >= c_HashCompactM) then      if (self.FIndexMax * c_HashCompactR > Length(self.f_SpareItems)) then        self.Compact;end;procedure THash.Clear;var  i: integer;begin  self.FClearItems;  SetLength(self.f_SpareItems, 0);  for i := 0 to f_CurrentItemMaxIdx do    SetLength(self.f_Keys[i], 0);end;procedure THash.FUpdateMasks;begin  f_CurrentItemMask := (1 shl f_CurrentItemShift) - 1;  f_CurrentItemMaxIdx := (1 shl f_CurrentItemShift) - 1;  f_CurrentItemCount := (1 shl f_CurrentItemShift);end;procedure THash.FUpdateBuckets;begin  { This is just a temporary thing. }  SetLength(self.f_Keys, self.f_CurrentItemCount);end;function THash.NewIterator: THashIterator;begin  result.ck := -1;  result.cx := 0;end;function THash.Previous: boolean;begin  if (not (self.f_NextAllowed)) then    raise EHashIterateError.Create('Cannot get Next as the hash has '      + 'been modified since Restart was called');  result := false;  if (self.f_CurrentIterator.ck >= 0) then begin    while ((not result) and (self.f_CurrentIterator.ck >= 0)) do begin      dec(self.f_CurrentIterator.cx);      if (self.f_CurrentIterator.cx >= 0) then begin        result := true;        self.f_CurrentKey := self.f_Keys[self.f_CurrentIterator.ck][self.f_CurrentIterator.cx].Key;      end else begin        dec(self.f_CurrentIterator.ck);        if (self.f_CurrentIterator.ck >= 0) then          self.f_CurrentIterator.cx := Length(self.f_Keys[self.f_CurrentIterator.ck]);      end;    end;  end;end;{ TStringHash }procedure TStringHash.FDeleteIndex(i: integer);begin  self.f_Items[i] := '';end;function TStringHash.FGetItem(const Key: string): string;var  k, x: integer;begin  if (self.FFindKey(Key, k, x)) then    result := self.f_Items[self.f_Keys[k][x].ItemIndex]  else    raise EHashFindError.CreateFmt('Key "%s" not found', [Key]);end;procedure TStringHash.FMoveIndex(oldIndex, newIndex: integer);begin  self.f_Items[newIndex] := self.f_Items[oldIndex];end;procedure TStringHash.FSetItem(const Key, Value: string);var  k, x, i: integer;begin  if (self.FFindKey(Key, k, x)) then    self.f_Items[self.f_Keys[k][x].ItemIndex] := Value  else begin    { New index entry, or recycle an old one. }    i := self.FAllocItemIndex;    if (i > High(self.f_Items)) then      SetLength(self.f_Items, i + 1);    self.f_Items[i] := Value;    { Add it to the hash. }    SetLength(self.f_Keys[k], Length(self.f_Keys[k]) + 1);    self.f_Keys[k][High(self.f_Keys[k])].Key := Key;    self.f_Keys[k][High(self.f_Keys[k])].ItemIndex := i;    self.f_Keys[k][High(self.f_Keys[k])].Hash := HashThis(Key);    { Hash has been modified, so disallow Next. }    self.f_NextAllowed := false;  end;end;function TStringHash.FIndexMax: integer;begin  result := High(self.f_Items);end;procedure TStringHash.FTrimIndexes(count: integer);begin  SetLength(self.f_Items, count);end;procedure TStringHash.FClearItems;begin  SetLength(self.f_Items, 0);end;{ TIntegerHash }procedure TIntegerHash.FDeleteIndex(i: integer);begin  self.f_Items[i] := 0;end;function TIntegerHash.FGetItem(const Key: string): integer;var  k, x: integer;begin  if (self.FFindKey(Key, k, x)) then    result := self.f_Items[self.f_Keys[k][x].ItemIndex]  else    raise EHashFindError.CreateFmt('Key "%s" not found', [Key]);end;procedure TIntegerHash.FMoveIndex(oldIndex, newIndex: integer);begin  self.f_Items[newIndex] := self.f_Items[oldIndex];end;procedure TIntegerHash.FSetItem(const Key: string; Value: integer);var  k, x, i: integer;begin  if (self.FFindKey(Key, k, x)) then    self.f_Items[self.f_Keys[k][x].ItemIndex] := Value  else begin    { New index entry, or recycle an old one. }    i := self.FAllocItemIndex;    if (i > High(self.f_Items)) then      SetLength(self.f_Items, i + 1);    self.f_Items[i] := Value;    { Add it to the hash. }    SetLength(self.f_Keys[k], Length(self.f_Keys[k]) + 1);    self.f_Keys[k][High(self.f_Keys[k])].Key := Key;    self.f_Keys[k][High(self.f_Keys[k])].ItemIndex := i;    self.f_Keys[k][High(self.f_Keys[k])].Hash := HashThis(Key);    { Hash has been modified, so disallow Next. }    self.f_NextAllowed := false;  end;end;function TIntegerHash.FIndexMax: integer;begin  result := High(self.f_Items);end;procedure TIntegerHash.FTrimIndexes(count: integer);begin  SetLength(self.f_Items, count);end;procedure TIntegerHash.FClearItems;begin  SetLength(self.f_Items, 0);end;{ TObjectHash }procedure TObjectHash.FDeleteIndex(i: integer);begin  self.f_Items[i].Free;  self.f_Items[i] := nil;end;function TObjectHash.FGetItem(const Key: string): TObject;var  k, x: integer;begin  if (self.FFindKey(Key, k, x)) then    result := self.f_Items[self.f_Keys[k][x].ItemIndex]  else    raise EHashFindError.CreateFmt('Key "%s" not found', [Key]);end;procedure TObjectHash.FMoveIndex(oldIndex, newIndex: integer);begin  self.f_Items[newIndex] := self.f_Items[oldIndex];end;procedure TObjectHash.FSetItem(const Key: string; Value: TObject);var  k, x, i: integer;begin  if (self.FFindKey(Key, k, x)) then begin    self.f_Items[self.f_Keys[k][x].ItemIndex].Free;    self.f_Items[self.f_Keys[k][x].ItemIndex] := Value;  end else begin    { New index entry, or recycle an old one. }    i := self.FAllocItemIndex;    if (i > High(self.f_Items)) then      SetLength(self.f_Items, i + 1);    self.f_Items[i] := Value;    { Add it to the hash. }    SetLength(self.f_Keys[k], Length(self.f_Keys[k]) + 1);    self.f_Keys[k][High(self.f_Keys[k])].Key := Key;    self.f_Keys[k][High(self.f_Keys[k])].ItemIndex := i;    self.f_Keys[k][High(self.f_Keys[k])].Hash := HashThis(Key);    { Hash has been modified, so disallow Next. }    self.f_NextAllowed := false;  end;end;function TObjectHash.FIndexMax: integer;begin  result := High(self.f_Items);end;procedure TObjectHash.FTrimIndexes(count: integer);begin  SetLength(self.f_Items, count);end;procedure TObjectHash.FClearItems;var  i: integer;begin  for i := 0 to High(self.f_Items) do    if (Assigned(self.f_Items[i])) then      self.f_Items[i].Free;  SetLength(self.f_Items, 0);end;destructor TObjectHash.Destroy;var  i: integer;begin  for i := 0 to High(self.f_Items) do    if (Assigned(self.f_Items[i])) then      self.f_Items[i].Free;  inherited;end;end.

⌨️ 快捷键说明

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