воскресенье, 12 апреля 2026 г.

m3AttrIndexDumper

{$IfDef FPC}{$CodePage cp1251}{$EndIf FPC}

unit m3AttrIndexDumper;

// --------------------------------------------------------------------------
// Родители: "Attributes" <> MUID: (667D35D300BC) :: "m3" <> MUID: (548712F60101) :: "Shared Delphi Low Level" <> MUID: (4ABCC25A0322)
// --------------------------------------------------------------------------
// Модуль: "w:\common\components\rtl\Garant\m3\m3AttrIndexDumper.pas" GeneratorVersion: 1.0.0.883901
// Стереотип: "<>"
// Элемент модели: "Tm3AttrIndexDumper" MUID: (667D594C030C)
// --------------------------------------------------------------------------

//#UC START# *667D594C030CbeforeDefines*
//#UC END# *667D594C030CbeforeDefines*
{$Include m3Define.inc}

interface

uses
 l3IntfUses
 , m3IndexDumper
 , m3SearcherInterfaces
 , l3CoreInterfaces
 , l3Types
 , SysUtils
 , m3StorageInterfaces
 , l3Ranges
;

type
 Tm3AttrIndexDumper = class(Tm3IndexDumper, Im3AttrIndexDumper)
  private
   f_Operation: Tm3GroupOperation;
   f_Count: Integer;
   f_SearchMode: Tm3SearchMode;
  protected
   function pm_GetFirst: Il3RangeEnumerable;
   function pm_GetLast: Il3RangeEnumerable;
   function pm_GetCount: Integer;
   function ValuesByKey(aKey: Integer): Il3RangeEnumerable;
   function Get_MaxKeyID: Integer;
   function Get_Operation: Tm3GroupOperation;
   function Get_MinKeyID: Integer;
   procedure Set_SearchMode(aValue: Tm3SearchMode);
   function Get_Sequential: Boolean;
   function ToTheLeftOf(const anOther: Im3AttrIndexDumper): Boolean;
  public
   constructor Create(const anIndexName: AnsiString); reintroduce; overload;
   class function MakePrim(const anIndexName: AnsiString): Im3AttrIndexDumper; reintroduce;
   class procedure MakeCopyFromDumper(var aDumper: Im3AttrIndexDumper;
    const aCopyName: Il3CString;
    aWriteVersions: Boolean;
    aFilesMeter: Tl3ProgressProc;
    const aBaseName: TFileName;
    aIsDirect: Boolean);
    {* Утилитный метод для копирования индексов. }
   class function Make(const anIndexName: AnsiString): Im3AttrIndexDumper;
   constructor Create(const anIndex: Im3IndexedStorage); reintroduce; overload;
   {$If NOT Defined(l3NoSRT)}
   function SetRefTo(var thePlace: Tm3AttrIndexDumper): Boolean; overload; {$If Defined(l3HasInl)}inline;{$IfEnd}
   {$IfEnd} // NOT Defined(l3NoSRT)
   function GetEnumerator: Im3AttrIndexElementEnumerator;
    {* Получает Enumerator для перебора элементов "контейнера".

Вся  эта конструкция совместима с "синтаксическим сахаром" вида:

for Item in Container do Process(Item);

Который поддерживается в "новых" Delphi.

См. http://mdp.garant.ru/pages/viewpage.action?pageId=152961307 }
  public
   property First: Il3RangeEnumerable
    read pm_GetFirst;
    {* Первый элемент. }
   property Last: Il3RangeEnumerable
    read pm_GetLast;
    {* Последний элемент. }
   property Count: Integer
    read pm_GetCount;
    {* Число элементов. }
 end;//Tm3AttrIndexDumper

implementation

uses
 l3ImplUses
 , Im3AttrIndexElementList
 , m3AttrIndexElement
 {$If NOT Defined(NoScripts)}
 , TtfwTypeRegistrator_Proxy
 {$IfEnd} // NOT Defined(NoScripts)
 {$If NOT Defined(NoScripts)}
 , TtfwClassRef_Proxy
 {$IfEnd} // NOT Defined(NoScripts)
 //#UC START# *667D594C030Cimpl_uses*
 //, SysUtils
 {$IfNDef FPC}
 , Windows
 {$EndIf  FPC}
 , m3stgmgr
 //, m3StorageInterfaces
 , l3Interfaces
 , l3StringsEnumerator
 , l3StoreInterfaces
 , l3Date
 , l3Base
 , l3FileUtils
 , l3SysUtils
 , l3BaseStream
 , m3StorageTools
 , l3String
 , m2HASLib
 , m2COMLib
 , m3IndexerTypes
 , m3IndexConst
 , m3DBTools
 , m3ProxyIndexStream
 , m3StorageService
 , m3AttrIndexWriter
 , m3DocumentAttrIndexBuilder // Для g_UseNewIndexesOnly
 , m3IndexElements
 //#UC END# *667D594C030Cimpl_uses*
;

constructor Tm3AttrIndexDumper.Create(const anIndexName: AnsiString);
//#UC START# *68E135A302D3_667D594C030C_var*
//#UC END# *68E135A302D3_667D594C030C_var*
begin
//#UC START# *68E135A302D3_667D594C030C_impl*
 f_Operation := m3_gopNone;
 f_Count := -1;
 inherited Create(anIndexName);
//#UC END# *68E135A302D3_667D594C030C_impl*
end;//Tm3AttrIndexDumper.Create

class function Tm3AttrIndexDumper.MakePrim(const anIndexName: AnsiString): Im3AttrIndexDumper;
var
 l_Inst : Tm3AttrIndexDumper;
begin
 l_Inst := Create(anIndexName);
 try
  Result := l_Inst;
 finally
  l_Inst.Free;
 end;//try..finally
end;//Tm3AttrIndexDumper.MakePrim

class procedure Tm3AttrIndexDumper.MakeCopyFromDumper(var aDumper: Im3AttrIndexDumper;
 const aCopyName: Il3CString;
 aWriteVersions: Boolean;
 aFilesMeter: Tl3ProgressProc;
 const aBaseName: TFileName;
 aIsDirect: Boolean);
 {* Утилитный метод для копирования индексов. }
//#UC START# *671A1493028D_667D594C030C_var*

var
 l_UpdateName : String;

 procedure DoWrite;
 var
  l_OutHash  : Im3IndexedStorage;
  l_Start : Cardinal;

  function DoElement(const anElement: Im3AttrIndexElement): Boolean;
  const
   cTimeDelta = 20 * 60 * 1000;
  var
   l_St : Il3Stream;
   l_N : AnsiString;
   l_TimeDelta : Int64;
  begin//DoElement
   Result := true;
   if Assigned(aFilesMeter) then
    if (anElement.ID >= 0) then
     aFilesMeter(piCurrent, anElement.ID, '');
   if (l_OutHash <> nil) then
   begin
    if (anElement.ID < 0) then
    begin
     l_N := l3CCP(IntToStr(anElement.ID));
     l_St := m3COMOpenStream(l_OutHash,
                             l3PCharLen(l_N),
                             m3_saWrite,
                             true,
                             true{false});
    end//anElement.ID < 0
    else
     l_St := m3COMOpenStream(l_OutHash,
                             anElement.ID,
                             m3_saWrite,
                             true,
                             true{false});
    try
     if (l_St <> nil) then
      Il3RangeEnumerable_WriteTo(anElement.Values, l_St.As_IStream);
    finally
     l_St := nil;
    end;//try..finally
   end;//l_OutHash <> nil
   l_TimeDelta := cTimeDelta;
   {$IfNDef nsTest}
   if (l3Date.DayOfWeek(SysUtils.Date) <> l3Date.Sunday)
      AND (l3Date.DayOfWeek(SysUtils.Date) <> l3Date.Saturday) then
   begin
    l_TimeDelta := cTimeDelta div 2;
    if (l_TimeDelta <= 1000) then
     l_TimeDelta := cTimeDelta;
   end;//l3Date.DayOfWeek(SysUtils.Date) <> l3Date.Sunday
   {$EndIf  nsTest}
   if l3IsTimeElapsed(l_Start, l_TimeDelta) then
   begin
    // - здесь будем новые дельты строить
    if (aBaseName <> '') then
    begin
     l3System.Msg2Log('Здесь будем новые дельты строить');
     m3DBBuildIndexDelta(aBaseName, nil, true, false{aForceFullIndex});
     l3System.Msg2Log('Закончили строить новые дельты');
    end;//aBaseName <> ''
    l_Start := GetTickCount;
    // - новая точка отсчёта
   end;//l3IsTimeElapsed(l_Start, l_TimeDelta)
  end;//DoElement

  var
   l_OutIndex: Im3IndexedStorage;
   l_Writer : Tm3AttrIndexWriter;

  procedure WriteRange;
  var
   l_St : Il3Stream;
   l_Range : Tm3IDRange;
  begin//WriteRange
   if (l_Writer <> nil) then
   begin
    l_Range := aDumper.Range;
    l_Writer.WriteRange(l_Range);
   end;//l_Writer <> nil
   if (l_OutIndex <> nil) then
   begin
    l_St := m3COMOpenStream(l_OutIndex,
                            l3PCharLen('range'),
                            m3_saWrite,
                            true,
                            false);
    try
     if (l_St <> nil) then
     begin
      l_Range := aDumper.Range;
      l_Range.WriteTo(l_St.As_IStream);
     end;//l_St <> nil
    finally
     l_St := nil;
    end;//try..finally
   end;//l_OutIndex <> nil
  end;//WriteRange

  procedure WriteOperation;
  var
   l_St : Il3Stream;
   l_S : IStream;
   l_Op : Tm3GroupOperation;
  begin//WriteOperation
   l_Op := aDumper.Operation;
   if (l_Writer <> nil) then
    l_Writer.WriteOperation(l_Op);
   if (l_OutIndex <> nil) then
   begin
    l_St := m3COMOpenStream(l_OutIndex,
                            l3PCharLen('operation'),
                            m3_saWrite,
                            true,
                            false);
    try
     if (l_St <> nil) then
     begin
      l_S := l_St.As_IStream;
      m2COMWriteBuffer(l_S, l_Op, SizeOf(l_Op));
     end;//l_St <> nil
    finally
     l_St := nil;
    end;//try..finally
   end;//l_OutIndex <> nil
  end;//WriteOperation

  {$IfDef m3UseProxyIndexStream}
   {$Define m3LocUseProxyIndexStream}
  {$EndIf m3UseProxyIndexStream}

 var
  l_Enum : Im3AttrIndexElementEnumerator;
  l_MaxKeyID : Integer;
  {$IfDef m3LocUseProxyIndexStream}
  l_Temp : Tl3Stream;
  l_H : Im3StorageHolder;
  {$EndIf m3LocUseProxyIndexStream}
  l_Capacity : Integer;
  l_pCurrent : Im3AttrIndexElementEnumerator_PCurrentItemType;
 begin//DoWrite
  l_Capacity := 0;
  l_Writer := nil;
  try
   {$IfDef m3LocUseProxyIndexStream}
   if g_UseNewIndexesOnly then
   begin
    l_Temp := Tm3ProxyIndexStream.Create(l_UpdateName);
    try
     l_Writer := Tm3AttrIndexWriter.Create(l_Temp, aIsDirect);
    finally
     FreeAndNil(l_Temp);
    end;//try..finally
   end//g_UseNewIndexesOnly
   else
   if not Tm3StorageService.Instance.UseSplitted then
   begin
    l_Temp := Tm3ProxyIndexStream.Create(l_UpdateName);
    try
     l_H := Tm3FullModeExclusiveStorageManager.MakeInterface(l_Temp, c_m3UseVersionedIndexDeltas, def_FullModeStorageUseCompression);
     try
      l_OutIndex := l_H.Storage;
     finally
      l_H := nil;
     end;//try..finally
    finally
     FreeAndNil(l_Temp);
    end;//try..finally
   end//not Tm3StorageService.Instance.UseSplitted
   else
    l_OutIndex := Tm3FullModeExclusiveStorageManager.MakeInterface(l_UpdateName, c_m3UseVersionedIndexDeltas);
   {$Else  m3LocUseProxyIndexStream}
   l_OutIndex := Tm3FullModeExclusiveStorageManager.MakeInterface(l_UpdateName, c_m3UseVersionedIndexDeltas);
   {$EndIf m3LocUseProxyIndexStream}
   try
    {$IfNDef m3UseVersionedIndexDeltas}
    l_OutIndex.ClearAll;
    {$EndIf  m3UseVersionedIndexDeltas}
    l_MaxKeyID := aDumper.MaxKeyID;
    if Assigned(aFilesMeter) then
     aFilesMeter(piStart, l_MaxKeyID, 'Обновление индекса: ' + ExtractFileName(l_UpdateName));
     //aFilesMeter(piStart, Cm2HASDefCount, 'Обновление индекса');
    try
     if Assigned(aFilesMeter) then
      aFilesMeter(piCurrent, 0, 'Запись списка документов');
     if (l_Writer <> nil) then
      l_Writer.WriteModified(aDumper.ModifiedDocuments, aDumper.TimeStamp);
     if (l_OutIndex <> nil) then
      m3WriteModified(l_OutIndex, aDumper.ModifiedDocuments, aDumper.TimeStamp);
     if aWriteVersions then
     begin
      if Assigned(aFilesMeter) then
       aFilesMeter(piCurrent, 0, 'Запись версий документов');
      if (l_Writer <> nil) then
       l_Writer.WriteVersions(aDumper.IndexedVersions);
      if (l_OutIndex <> nil) then
       m3WriteVersions(l_OutIndex, aDumper.IndexedVersions);
     end;//aWriteVersions
     WriteRange;
     WriteOperation;
     if (l_Writer <> nil) then
     begin
      if Assigned(aFilesMeter) then
       aFilesMeter(piCurrent, 0, 'Обновление индекса (вычисление Capacity): ' + ExtractFileName(l_UpdateName));
      l_Capacity := aDumper.Count;
(*      l_Enum := aDumper.GetEnumerator;
      Assert(l_Enum <> nil);
      l_Capacity := 0;
      while l_Enum.MoveNext do
       Inc(l_Capacity);*)

      if Assigned(aFilesMeter) then
       aFilesMeter(piCurrent, 0, 'Обновление индекса: ' + ExtractFileName(l_UpdateName));
      l_Writer.StartBody(l_Capacity);
      try
       l_Enum := aDumper.GetEnumerator;
       Assert(l_Enum <> nil);
       while l_Enum.MoveNext do
       begin
        l_pCurrent := l_Enum.pCurrent;
        Assert(l_pCurrent <> nil);
        if Assigned(aFilesMeter) then
         if (l_pCurrent.ID >= 0) then
          aFilesMeter(piCurrent, l_pCurrent.ID, '');
        l_Writer.WriteBodyElement(l_pCurrent.ID, l_pCurrent.Values);
       end;//while l_Enum.MoveNext
      finally
       l_Writer.FinishBody;
      end;//try..finally
     end;//l_Writer <> nil
     if (l_OutIndex <> nil) then
     begin
      l_OutHash := m3COMOpenStorage(l_OutIndex,
                                    l3PCharLen(AnsiString(m3HashDataName)),
                                    m3_saReadWrite,
                                    true);
      if (l_OutHash <> nil) then
       if (l_MaxKeyID <= 32767) then
        l_OutHash.SetIndexParam(16, 16);
        // - MaxElementID тут возможно прикрутить
      try
       l_OutIndex := nil; // - типа можно отпустить
       if Assigned(aFilesMeter) then
        aFilesMeter(piCurrent, 0, 'Обновление индекса: ' + ExtractFileName(l_UpdateName));
       l_Enum := aDumper.GetEnumerator;
       aDumper := nil;
       // - типа можно отпустить
       try
        l_Start := GetTickCount;
        Assert(l_Enum <> nil);
        while l_Enum.MoveNext do
         if not DoElement(l_Enum.Current) then
          break;
       finally
        l_Enum := nil;
       end;//try..finally
      finally
       l_OutHash := nil;
      end;//try..finally
     end;//l_OutIndex <> nil
    finally
     if Assigned(aFilesMeter) then
      aFilesMeter(piEnd, 0, '');
    end;//try..finally
   finally
    l_OutIndex := nil;
   end;//try..finally
  finally
   FreeAndNil(l_Writer);
  end;//try..finally
 end;//DoWrite

var
 l_UpdateNameBak : String;
//#UC END# *671A1493028D_667D594C030C_var*
begin
//#UC START# *671A1493028D_667D594C030C_impl*
 l_UpdateName := Il3CString_ToFileName(aCopyName);
 if Tm3StorageManager.StorageFileExists(l_UpdateName) then
 begin
  l_UpdateNameBak := l_UpdateName + cBackExt;
  Tm3StorageManager.DeleteStorageFile(l_UpdateNameBak);
  Tm3StorageManager.RenameStorageFile(l_UpdateName, l_UpdateNameBak);
 end;//Tm3StorageManager.StorageFileExists(l_UpdateName)
 DoWrite;
//#UC END# *671A1493028D_667D594C030C_impl*
end;//Tm3AttrIndexDumper.MakeCopyFromDumper

class function Tm3AttrIndexDumper.Make(const anIndexName: AnsiString): Im3AttrIndexDumper;
//#UC START# *66A21BA9035E_667D594C030C_var*

 function CheckStorage: Boolean;
 var
  l_S : Im3IndexedStorage;
  l_SS : Im3IndexedStorage;
  l_E : Il3StringsEnumerable;
 begin
  Result := false;
  l_S := Tm3ConstantStorageManager.MakeInterface(anIndexName);
  try
   if (l_S = nil) then
    Exit;
   if l3IOk(m3COMSafeOpenStorage(l_S,
                                l3PCharLen(AnsiString(m3HashDataName)),
                                m3_saRead,
                                false,
                                l_SS)) then
    try
     l_S := nil;
     if (l_SS.MaxElementID < 0) then
     begin
      l_E := l_SS.TOCEnumerable;
      if (l_E = nil) then
       Exit;
      if l_E.Empty then
       Exit;
      // - а иначе у нас наверное есть неиндексные элементы
      // например отрицательные номера
     end;//l_SS.MaxElementID < 0
     Result := true;
    finally
     l_SS := nil;
    end;//try..finally
  finally
   l_S := nil;
  end;//try..finally
 end;//CheckStorage

var
 l_D : Tm3AttrIndexDumper;
//#UC END# *66A21BA9035E_667D594C030C_var*
begin
//#UC START# *66A21BA9035E_667D594C030C_impl*
 if (anIndexName = '') then
 begin
  l_D := Create(nil);
  try
   Result := l_D;
  finally
   FreeAndNil(l_D);
  end;//try..finally
 end//anIndexName = ''
 else
 if Tm3StorageManager.StorageFileExists(anIndexName) then
 begin
  if Tm3PlainAttrIndexDumper.TryMake(anIndexName, Result) then
  // - пробуем открыть индекс "новой системы".
   Exit;
  if CheckStorage then
   Result := MakePrim(anIndexName)
  else
  begin
   l_D := Create(nil);
   try
    Result := l_D;
   finally
    FreeAndNil(l_D);
   end;//try..finally
  end;//CheckStorage
 end//Tm3StorageManager.StorageFileExists(anIndexName)
 else
  Result := nil;
//#UC END# *66A21BA9035E_667D594C030C_impl*
end;//Tm3AttrIndexDumper.Make

constructor Tm3AttrIndexDumper.Create(const anIndex: Im3IndexedStorage);
//#UC START# *68E13E0402B4_667D594C030C_var*
//#UC END# *68E13E0402B4_667D594C030C_var*
begin
//#UC START# *68E13E0402B4_667D594C030C_impl*
 f_Operation := m3_gopNone;
 f_Count := -1;
 inherited Create(anIndex);
//#UC END# *68E13E0402B4_667D594C030C_impl*
end;//Tm3AttrIndexDumper.Create

{$If NOT Defined(l3NoSRT)}
function Tm3AttrIndexDumper.SetRefTo(var thePlace: Tm3AttrIndexDumper): Boolean;
begin
 if (thePlace = Self) then
  Result := false
 else
 begin
  Result := true;
  thePlace.Free;
  thePlace := Self.Use;
 end;//thePlace = Self
end;//Tm3AttrIndexDumper.SetRefTo
{$IfEnd} // NOT Defined(l3NoSRT)

function Tm3AttrIndexDumper.pm_GetFirst: Il3RangeEnumerable;
//#UC START# *47D8233603DD_667D594C030Cget_var*
//#UC END# *47D8233603DD_667D594C030Cget_var*
begin
//#UC START# *47D8233603DD_667D594C030Cget_impl*
 Result := nil;
 l3NI;
//#UC END# *47D8233603DD_667D594C030Cget_impl*
end;//Tm3AttrIndexDumper.pm_GetFirst

function Tm3AttrIndexDumper.pm_GetLast: Il3RangeEnumerable;
//#UC START# *47D823570315_667D594C030Cget_var*
//#UC END# *47D823570315_667D594C030Cget_var*
begin
//#UC START# *47D823570315_667D594C030Cget_impl*
 Result := nil;
 l3NI;
//#UC END# *47D823570315_667D594C030Cget_impl*
end;//Tm3AttrIndexDumper.pm_GetLast

function Tm3AttrIndexDumper.pm_GetCount: Integer;
//#UC START# *4BB08B8902F2_667D594C030Cget_var*
var
 l_It : Im3AttrIndexElementEnumerator;
//#UC END# *4BB08B8902F2_667D594C030Cget_var*
begin
//#UC START# *4BB08B8902F2_667D594C030Cget_impl*
 if (f_Count < 0) then
 begin
  f_Count := 0;
  l_It := Self.GetEnumerator;
  if (l_It <> nil) then
   while l_It.MoveNext do
    Inc(f_Count);
 end;//f_Count < 0
 Result := f_Count;
//#UC END# *4BB08B8902F2_667D594C030Cget_impl*
end;//Tm3AttrIndexDumper.pm_GetCount

function Tm3AttrIndexDumper.ValuesByKey(aKey: Integer): Il3RangeEnumerable;
//#UC START# *66B4B9740318_667D594C030C_var*
var
 l_InHash : Im3IndexedStorage;
 l_Stream : Il3Stream;
 l_N : AnsiString;
//#UC END# *66B4B9740318_667D594C030C_var*
begin
//#UC START# *66B4B9740318_667D594C030C_impl*
 Result := nil;
 if (f_Index <> nil) then
 begin
  if l3IOk(m3COMSafeOpenStorage(f_Index,
                               l3PCharLen(AnsiString(m3HashDataName)),
                               m3_saRead,
                               false,
                               l_InHash)) then
   try
    if (l_InHash <> nil) then
    begin
     if (aKey < 0) then
     begin
      l_N := l3CCP(IntToStr(aKey));
      m3COMSafeOpenStream(l_InHash, l3PCharLen(l_N), m3_saRead, false, l_Stream);
     end//aKey < 0
     else
      m3COMSafeOpenStream(l_InHash, aKey, m3_saRead, false, l_Stream);
     try
      Result := Il3RangeEnumerable_CreateFromStream(l_Stream);
     finally
      l_Stream := nil;
     end;//try..finally
    end;//l_InHash <> nil
   finally
    l_InHash := nil;
   end;//try..finally
 end;//f_Index <> nil
//#UC END# *66B4B9740318_667D594C030C_impl*
end;//Tm3AttrIndexDumper.ValuesByKey

function Tm3AttrIndexDumper.Get_MaxKeyID: Integer;
//#UC START# *671D18210090_667D594C030Cget_var*
var
 l_InHash : Im3IndexedStorage;
//#UC END# *671D18210090_667D594C030Cget_var*
begin
//#UC START# *671D18210090_667D594C030Cget_impl*
 Result := 0;
 if (f_Index <> nil) then
 begin
  if l3IOk(m3COMSafeOpenStorage(f_Index,
                               l3PCharLen(AnsiString(m3HashDataName)),
                               m3_saRead,
                               false,
                               l_InHash)) then
   try
    if (l_InHash <> nil) then
    begin
     Result := l_InHash.MaxElementID;
    end;//l_InHash <> nil
   finally
    l_InHash := nil;
   end;//try..finally
 end;//f_Index <> nil
//#UC END# *671D18210090_667D594C030Cget_impl*
end;//Tm3AttrIndexDumper.Get_MaxKeyID

function Tm3AttrIndexDumper.Get_Operation: Tm3GroupOperation;
//#UC START# *68E135160346_667D594C030Cget_var*
var
 l_St : Il3Stream;
 l_S : IStream;
//#UC END# *68E135160346_667D594C030Cget_var*
begin
//#UC START# *68E135160346_667D594C030Cget_impl*
 if (f_Operation = m3_gopNone) then
 begin
  if (f_Index = nil) then
   f_Operation := m3_gopSet
  else
  begin
   l_St := m3COMOpenStream(f_Index,
                           l3PCharLen('operation'),
                           m3_saRead,
                           false,
                           false);
   try
    if (l_St = nil) then
     f_Operation := m3_gopSet
    else
    begin
     l_S := l_St.As_IStream;
     m2COMReadBuffer(l_S, f_Operation, SizeOf(f_Operation));
     l_S := nil;
    end;//l_St <> nil
   finally
    l_St := nil;
   end;//try..finally
  end;//f_Index = nil
 end;//f_Operation = m3_gopNone
 Result := f_Operation;
//#UC END# *68E135160346_667D594C030Cget_impl*
end;//Tm3AttrIndexDumper.Get_Operation

function Tm3AttrIndexDumper.Get_MinKeyID: Integer;
//#UC START# *69B14AAE0155_667D594C030Cget_var*
//#UC END# *69B14AAE0155_667D594C030Cget_var*
begin
//#UC START# *69B14AAE0155_667D594C030Cget_impl*
 Result := 0;
 l3NI; // - можно потом вычислить, если понадобится
 // (+) L2Mm3StorageIteratorsIterateAllFAction (+) TOCEnumerable
//#UC END# *69B14AAE0155_667D594C030Cget_impl*
end;//Tm3AttrIndexDumper.Get_MinKeyID

procedure Tm3AttrIndexDumper.Set_SearchMode(aValue: Tm3SearchMode);
//#UC START# *69BBB8A101BA_667D594C030Cset_var*
//#UC END# *69BBB8A101BA_667D594C030Cset_var*
begin
//#UC START# *69BBB8A101BA_667D594C030Cset_impl*
 f_SearchMode := aValue;
//#UC END# *69BBB8A101BA_667D594C030Cset_impl*
end;//Tm3AttrIndexDumper.Set_SearchMode

function Tm3AttrIndexDumper.Get_Sequential: Boolean;
//#UC START# *69C1D45B01E5_667D594C030Cget_var*
//#UC END# *69C1D45B01E5_667D594C030Cget_var*
begin
//#UC START# *69C1D45B01E5_667D594C030Cget_impl*
 Result := false;
 // - нет у нас такой информации
//#UC END# *69C1D45B01E5_667D594C030Cget_impl*
end;//Tm3AttrIndexDumper.Get_Sequential

function Tm3AttrIndexDumper.ToTheLeftOf(const anOther: Im3AttrIndexDumper): Boolean;
//#UC START# *69C1DE0300B2_667D594C030C_var*
//#UC END# *69C1DE0300B2_667D594C030C_var*
begin
//#UC START# *69C1DE0300B2_667D594C030C_impl*
 Result := (Self.Get_MaxKeyID < anOther.MinKeyID);
//#UC END# *69C1DE0300B2_667D594C030C_impl*
end;//Tm3AttrIndexDumper.ToTheLeftOf

function Tm3AttrIndexDumper.GetEnumerator: Im3AttrIndexElementEnumerator;
 {* Получает Enumerator для перебора элементов "контейнера".

Вся  эта конструкция совместима с "синтаксическим сахаром" вида:

for Item in Container do Process(Item);

Который поддерживается в "новых" Delphi.

См. http://mdp.garant.ru/pages/viewpage.action?pageId=152961307 }
//#UC START# *5AB8C6B0003A_667D594C030C_var*
var
 l_List : TIm3AttrIndexElementList;
 l_InHash : Im3IndexedStorage;

 function DoHash(const aStoreInfo : Tm3StorageElementInfo): Boolean;
 var
  l_N : AnsiString;
  l_Index : Integer;
  l_E : Im3AttrIndexElement;
 begin//DoHash
  Result := true;
  if (aStoreInfo.rIndex >= 0) then
  begin
   l_E := Tm3AttrIndexElement.Make(aStoreInfo.rIndex, l_InHash, aStoreInfo);
   l_List.Add(l_E);
  end//aStoreInfo.rIndex >= 0
  else
  begin
   l_N := aStoreInfo.rName.AsString;
   if (l_N[1] = '-') then
   begin
    if TryStrToInt(l_N, l_Index) then
    begin
     if (l_Index < 0) then
     begin
      l_E := Tm3AttrIndexElement.Make(l_Index, l_InHash, aStoreInfo);
      l_List.Add(l_E);
     end;//l_Index < 0
    end;//TryStrToInt(l_N, l_Index)
   end;//l_N[1] = '-'
  end;//aStoreInfo.rIndex >= 0
 end;//DoHash

(* function DoHash(const aStoreInfo: Tm3StoreInfo; anIndex: Integer): Boolean;
 begin//DoHash
  Result := true;
  l_List.Add(Tm3AttrIndexElement.Make(anIndex, l_InHash, aStoreInfo));
 end;//DoHash*)

//#UC END# *5AB8C6B0003A_667D594C030C_var*
begin
//#UC START# *5AB8C6B0003A_667D594C030C_impl*
 Result := nil;
 l_List := TIm3AttrIndexElementList.CreateSorted;
 try
  if (f_Index <> nil) then
  begin
   if l3IOk(m3COMSafeOpenStorage(f_Index,
                                l3PCharLen(AnsiString(m3HashDataName)),
                                m3_saRead,
                                false,
                                l_InHash)) then
    try
     if (l_InHash <> nil) then
     begin
      l_InHash.IterateAllF(L2Mm3StorageIteratorsIterateAllFAction(@DoHash));
      //l_InHash.IterateIndexedF(L2Mm3StorageIteratorsIterateIndexedFAction(@DoHash), 0);
     end;//l_InHash <> nil
    finally
     l_InHash := nil;
    end;//try..finally
  end;//f_Index <> nil
  Result := l_List.GetEnumerator;
 finally
  FreeAndNil(l_List);
 end;//try..finally
//#UC END# *5AB8C6B0003A_667D594C030C_impl*
end;//Tm3AttrIndexDumper.GetEnumerator

initialization
{$If NOT Defined(NoScripts)}
 TtfwClassRef_Proxy.TtfwClassRef.Register(TypeInfo(Tm3AttrIndexDumper));
{$IfEnd} // NOT Defined(NoScripts)


//#UC START# *667D594C030CforDiagramm*
(*
*)
//#UC END# *667D594C030CforDiagramm*

end.

Комментариев нет:

Отправить комментарий