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

m3AttrIndexWriter

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

unit m3AttrIndexWriter;
 {* Писатель индекса атрибутов в "упрощённом виде".
[RequestLink:901972048] }

// --------------------------------------------------------------------------
// Родители: "Indexer" <> MUID: (58DE48000209) :: "m3" <> MUID: (58DE47D500CA) :: "Shared Delphi For Archi" <> MUID: (4ABA2360025A)
// --------------------------------------------------------------------------
// Модуль: "w:\common\components\rtl\Garant\m3\m3AttrIndexWriter.pas" GeneratorVersion: 1.0.0.883901
// Стереотип: "<>"
// Элемент модели: "Tm3AttrIndexWriter" MUID: (69AC2E42033D)
// --------------------------------------------------------------------------

//#UC START# *69AC2E42033DbeforeDefines*
//#UC END# *69AC2E42033DbeforeDefines*
{$Include m3Define.inc}

interface

uses
 l3IntfUses
 , l3SimpleObject
 , l3BaseStream
 , m3SearcherInterfaces
 , l3Ranges
 , TypInfo
 , l3CoreInterfaces
 , SysUtils
 , l3IntegerToIntegerMap
 , m3IndexElements
 //#UC START# *69AC2E42033Dintf_uses*
;
(*type
 T64to32 = packed record
  rLow : Integer;
  rHigh : Integer;
 end;//T64to32

 T64toSmallInts = packed array [0..3] of SmallInt;

 T64toBytes = packed array [0..7] of Byte;*)
type
 Tm3BodyFrameInfo = packed record
  rCount : Integer;
  rMinKeyID : Int64;
  rMaxKeyID : Int64;
  rNextPartPos : Int64;
 end;//Tm3BodyFrameInfo

const
 c_m3AttrIndexWriterGUID : TGUID = '{2020CBAD-78CC-494B-84B0-2EF18ADEA65A}';
 cSequentialVersion = 2;
 cOurVersion = cSequentialVersion;
 cSignature = 1400951
 //#UC END# *69AC2E42033Dintf_uses*
;

type
 Tm3AttrIndexWriterSubStreamInfoPtr = ^Tm3AttrIndexWriterSubStreamInfo;
  {* Указатель на Tm3AttrIndexWriterSubStreamInfo }

 Tm3AttrIndexWriterBodyElementPtr = ^Tm3AttrIndexWriterBodyElement;
  {* Указатель на Tm3AttrIndexWriterBodyElement }

 Tm3AttrIndexWriterHeaderPtr = ^Tm3AttrIndexWriterHeader;
  {* Указатель на Tm3AttrIndexWriterHeader }

(*
 _Mm3AttrIndexWriter_ = interface
  procedure WriteVersions(const aVersions: Im3IndexedVersions);
  procedure WriteModified(const aModified: Il3RangeEnumerable;
   aTimeStamp: TDateTime);
  procedure WriteRange(const aRange: Tl3Range);
  procedure WriteOperation(anOperation: Tm3GroupOperation);
  procedure StartBody(aCount: Integer);
  procedure FinishBody;
  procedure WriteBodyElement(aKey: Integer;
   const aValue: Il3RangeEnumerable);
 end;//_Mm3AttrIndexWriter_
*)

 Tm3AttrIndexWriter = class;

 Im3AttrIndexWriter = interface
  ['{59C707EB-8FD8-433F-901D-DBC22A0ABA21}']
  procedure WriteVersions(const aVersions: Im3IndexedVersions);
  procedure WriteModified(const aModified: Il3RangeEnumerable;
   aTimeStamp: TDateTime);
  procedure WriteRange(const aRange: Tl3Range);
  procedure WriteOperation(anOperation: Tm3GroupOperation);
  procedure StartBody(aCount: Integer);
  procedure FinishBody;
  procedure WriteBodyElement(aKey: Integer;
   const aValue: Il3RangeEnumerable);
 end;//Im3AttrIndexWriter

 Tm3AttrIndexWriterSubStreamInfo = packed record
 //#UC START# *69AFF780026Apubl*
  rPos : Int64;
  rSize : Int64;
 //#UC END# *69AFF780026Apubl*
 end;//Tm3AttrIndexWriterSubStreamInfo

 Tm3ElementType = (
  m3_etNone
  , m3_etSingle
  , m3_etPair
  , m3_etMultiply
  , m3_etLZO
  , m3_etZLib
  , m3_et4
  , m3_et8
  , m3_etRange
 );//Tm3ElementType

 Tm3AttrIndexWriterBodyElement = packed record
 //#UC START# *69AC79CD0094publ*
  rType : Tm3ElementType;
  rKey : Int64;
  rValue : Int64;
 //#UC END# *69AC79CD0094publ*
 end;//Tm3AttrIndexWriterBodyElement

 Tm3AttrIndexWriterHeader = packed record
 //#UC START# *69AC312A0001publ*
  rZeroStart : Integer;
  rVer : array [0..2] of AnsiChar;
  rVersion : Integer;
  rSig : array [0..2] of AnsiChar;
  rSignature : Integer;
  rTim : array [0..2] of AnsiChar;
  rTimeStamp : Int64;
  //rTimeStamp : TDateTime;
  rHea : array [0..2] of AnsiChar;
  rHeaderStart : Int64;
  rHeaderEnd : Int64;
  rStr : array [0..2] of AnsiChar;
  rStreamEnd : Int64;
  rRan : array [0..2] of AnsiChar;
  rRange : Tm3IDRange;
  rOper : array [0..3] of AnsiChar;
  rOperation : Tm3GroupOperation;
  rMod : array [0..2] of AnsiChar;
  rModified : Tm3AttrIndexWriterSubStreamInfo;
  rVers : array [0..3] of AnsiChar;
  rVersions : Tm3AttrIndexWriterSubStreamInfo;
  rBod : array [0..2] of AnsiChar;
  rBody : Tm3AttrIndexWriterSubStreamInfo;
  rCnt : array [0..2] of AnsiChar;
  rElementsCount : Integer;
  rMin : array [0..2] of AnsiChar;
  rMinKeyID : Integer;
  rMax : array [0..2] of AnsiChar;
  rMaxKeyID : Integer;
  rNextPartPos : Int64;
  rZeroEnd : Integer;
 //#UC END# *69AC312A0001publ*
 end;//Tm3AttrIndexWriterHeader

 Tm3PlainAttrIndexDumperElementEnumerator = class(Tl3SimpleObject, Im3AttrIndexElementEnumerator)
  private
   f_Count: Integer;
   f_Index: Integer;
   f_Current: Im3AttrIndexElement;
   f_FileName: TFileName;
   f_Stream: Tl3Stream;
   f_Body: Tm3AttrIndexWriterSubStreamInfo;
  protected
   function Get_Current: Im3AttrIndexElement;
   procedure Cleanup; override;
    {* Функция очистки полей объекта. }
   procedure ClearFields; override;
  public
   constructor Create(aCount: Integer;
    const aFileName: TFileName;
    const aBody: Tm3AttrIndexWriterSubStreamInfo); reintroduce;
   class function Make(aCount: Integer;
    const aFileName: TFileName;
    const aBody: Tm3AttrIndexWriterSubStreamInfo): Im3AttrIndexElementEnumerator; reintroduce;
   {$If NOT Defined(l3NoSRT)}
   function SetRefTo(var thePlace: Tm3PlainAttrIndexDumperElementEnumerator): Boolean; overload; {$If Defined(l3HasInl)}inline;{$IfEnd}
   {$IfEnd} // NOT Defined(l3NoSRT)
   function MoveNext: Boolean;
    {* Перемещается на следующий элемент контейнера. 

Возвращает true если элемент валидный. }
   function pCurrent: Im3AttrIndexElementEnumerator_PCurrentItemType;
    {* Указатель на текущий элемент. Он "закеширован" }
   function CanMoveNext: Boolean;
    {* Определяет - можно ли переместиться на следующий элемент контейнера. }
  public
   property Current: Im3AttrIndexElement
    read Get_Current;
    {* Текущий элемент. Он "закеширован" }
 end;//Tm3PlainAttrIndexDumperElementEnumerator

 Tm3PlainAttrIndexDumperElement = class(Tl3SimpleObject, Im3AttrIndexElement)
  private
   f_Element: Tm3AttrIndexWriterBodyElement;
   f_FileName: TFileName;
   f_Values: Il3RangeEnumerable;
  protected
   function Get_ID: Integer;
   function Get_Values: Il3RangeEnumerable;
   procedure Cleanup; override;
    {* Функция очистки полей объекта. }
   procedure ClearFields; override;
  public
   constructor Create(const anElement: Tm3AttrIndexWriterBodyElement;
    const aFileName: TFileName); reintroduce;
   class function Make(const anElement: Tm3AttrIndexWriterBodyElement;
    const aFileName: TFileName): Im3AttrIndexElement; reintroduce;
   {$If NOT Defined(l3NoSRT)}
   function SetRefTo(var thePlace: Tm3PlainAttrIndexDumperElement): Boolean; overload; {$If Defined(l3HasInl)}inline;{$IfEnd}
   {$IfEnd} // NOT Defined(l3NoSRT)
 end;//Tm3PlainAttrIndexDumperElement

 //#UC START# *69AE74DB018Aci*
 //#UC END# *69AE74DB018Aci*
 Tm3PlainAttrIndexDumper = class(Tl3SimpleObject, Im3AttrIndexDumper)
  {* Читатель индекса атрибутов в "упрощённом виде".
[RequestLink:901972048] }
  private
   f_Header: Tm3AttrIndexWriterHeader;
   f_FileName: TFileName;
   f_Modified: Il3RangeEnumerable;
   f_Versions: Tl3IntegerToIntegerMap;
   f_Stream: Tl3Stream;
    {* Наверное потому что на всё наше время жизни поток надо держать открытым. Чтобы его не удалили }
   f_SearchMode: Tm3SearchMode;
   f_EnumeratorForSeq: Im3AttrIndexElementEnumerator;
   f_Sequential: Boolean;
  protected
   function pm_GetFirst: Il3RangeEnumerable;
   function pm_GetLast: Il3RangeEnumerable;
   function pm_GetCount: Integer;
   function ModifiedDocuments: Il3RangeEnumerable;
   function IndexedVersions: Im3IndexedVersions;
   function Get_Range: Tm3IDRange;
   function ValuesByKey(aKey: Integer): Il3RangeEnumerable;
   function TimeStamp: TDateTime;
   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;
   procedure Cleanup; override;
    {* Функция очистки полей объекта. }
   procedure ClearFields; override;
  public
   constructor Create(const aFileName: TFileName;
    aStream: Tl3Stream = nil); reintroduce;
   class function Make(const aFileName: TFileName;
    aStream: Tl3Stream = nil): Im3AttrIndexDumper; reintroduce;
   class function TryMake(const aFileName: TFileName;
    out theDumper: Im3AttrIndexDumper): Boolean;
   {$If NOT Defined(l3NoSRT)}
   function SetRefTo(var thePlace: Tm3PlainAttrIndexDumper): 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;
    {* Число элементов. }
 //#UC START# *69AE74DB018Apubl*
 //#UC END# *69AE74DB018Apubl*
 end;//Tm3PlainAttrIndexDumper

 //#UC START# *69AC2E42033Dci*
 //#UC END# *69AC2E42033Dci*
 Tm3AttrIndexWriter = class(Tl3SimpleObject, Im3AttrIndexWriter)
  {* Писатель индекса атрибутов в "упрощённом виде".
[RequestLink:901972048] }
  private
   f_Stream: Tl3Stream;
   f_Header: Tm3AttrIndexWriterHeader;
   f_HeaderSave: Tm3AttrIndexWriterHeader;
   f_IsDirect: Boolean;
   f_Sequential: Boolean;
  private
   procedure WriteEOL;
   procedure SaveHeader;
  protected
   procedure Cleanup; override;
    {* Функция очистки полей объекта. }
   procedure BeforeRelease; override;
  public
   constructor Create(aStream: Tl3Stream;
    aIsDirect: Boolean); reintroduce;
   class function Make(aStream: Tl3Stream;
    aIsDirect: Boolean): Im3AttrIndexWriter; reintroduce;
   {$If NOT Defined(l3NoSRT)}
   function SetRefTo(var thePlace: Tm3AttrIndexWriter): Boolean; overload; {$If Defined(l3HasInl)}inline;{$IfEnd}
   {$IfEnd} // NOT Defined(l3NoSRT)
   procedure WriteVersions(const aVersions: Im3IndexedVersions);
   procedure WriteModified(const aModified: Il3RangeEnumerable;
    aTimeStamp: TDateTime);
   procedure WriteRange(const aRange: Tl3Range);
   procedure WriteOperation(anOperation: Tm3GroupOperation);
   procedure StartBody(aCount: Integer);
   procedure FinishBody;
   procedure WriteBodyElement(aKey: Integer;
    const aValue: Il3RangeEnumerable);
 //#UC START# *69AC2E42033Dpubl*
  private
   f_PrevKey : Int64;
   f_DeclaredCapacity : Integer;
   f_Capacity : Integer;
   f_FrameInfoPos : Int64;
   f_FrameInfo : Tm3BodyFrameInfo;
   f_SequentialInfoPos : Int64;
  private
   procedure ifWriteEOL;
   procedure WriteStart(const aStr: Ansistring);
   procedure WriteEnd(const aStr: Ansistring);
 //#UC END# *69AC2E42033Dpubl*
 end;//Tm3AttrIndexWriter

 IBoxFor_Tm3AttrIndexWriterSubStreamInfo = interface(Il3Box)
  ['{253213BB-4BDA-4461-89E5-00D7F7D0F05D}']
  function Get_Boxed: Tm3AttrIndexWriterSubStreamInfo;
  function Get_pBoxed: Tm3AttrIndexWriterSubStreamInfoPtr;
  property Boxed: Tm3AttrIndexWriterSubStreamInfo
   read Get_Boxed;
  property pBoxed: Tm3AttrIndexWriterSubStreamInfoPtr
   read Get_pBoxed;
 end;//IBoxFor_Tm3AttrIndexWriterSubStreamInfo

 IBoxFor_Tm3AttrIndexWriterBodyElement = interface(Il3Box)
  ['{3109FDED-F5C6-4174-901E-B215D8CEE051}']
  function Get_Boxed: Tm3AttrIndexWriterBodyElement;
  function Get_pBoxed: Tm3AttrIndexWriterBodyElementPtr;
  property Boxed: Tm3AttrIndexWriterBodyElement
   read Get_Boxed;
  property pBoxed: Tm3AttrIndexWriterBodyElementPtr
   read Get_pBoxed;
 end;//IBoxFor_Tm3AttrIndexWriterBodyElement

 IBoxFor_Tm3AttrIndexWriterHeader = interface(Il3Box)
  ['{39FD53E2-BF26-44EA-80F2-B41EC80E03DC}']
  function Get_Boxed: Tm3AttrIndexWriterHeader;
  function Get_pBoxed: Tm3AttrIndexWriterHeaderPtr;
  property Boxed: Tm3AttrIndexWriterHeader
   read Get_Boxed;
  property pBoxed: Tm3AttrIndexWriterHeaderPtr
   read Get_pBoxed;
 end;//IBoxFor_Tm3AttrIndexWriterHeader

function Tm3AttrIndexWriterSubStreamInfo_TypeInfo: PTypeInfo;
{$If NOT Defined(NoScripts)}
function Tm3AttrIndexWriterSubStreamInfo_ToValue(const aSelf: Tm3AttrIndexWriterSubStreamInfo): TtfwStackValue;
{$IfEnd} // NOT Defined(NoScripts)
{$If NOT Defined(NoScripts)}
function TtfwStackValue_C(const aSelf: Tm3AttrIndexWriterSubStreamInfo): TtfwStackValue; overload;
{$IfEnd} // NOT Defined(NoScripts)
{$If NOT Defined(NoScripts)}
function Tm3AttrIndexWriterSubStreamInfo_ToBox(const aSelf: Tm3AttrIndexWriterSubStreamInfo): Il3Box;
{$IfEnd} // NOT Defined(NoScripts)
{$If NOT Defined(NoScripts)}
function Tm3AttrIndexWriterSubStreamInfo_FromValue(const aValue: TtfwStackValue): Tm3AttrIndexWriterSubStreamInfo;
{$IfEnd} // NOT Defined(NoScripts)
function Tm3AttrIndexWriterBodyElement_TypeInfo: PTypeInfo;
{$If NOT Defined(NoScripts)}
function Tm3AttrIndexWriterBodyElement_ToValue(const aSelf: Tm3AttrIndexWriterBodyElement): TtfwStackValue;
{$IfEnd} // NOT Defined(NoScripts)
{$If NOT Defined(NoScripts)}
function TtfwStackValue_C(const aSelf: Tm3AttrIndexWriterBodyElement): TtfwStackValue; overload;
{$IfEnd} // NOT Defined(NoScripts)
{$If NOT Defined(NoScripts)}
function Tm3AttrIndexWriterBodyElement_ToBox(const aSelf: Tm3AttrIndexWriterBodyElement): Il3Box;
{$IfEnd} // NOT Defined(NoScripts)
{$If NOT Defined(NoScripts)}
function Tm3AttrIndexWriterBodyElement_FromValue(const aValue: TtfwStackValue): Tm3AttrIndexWriterBodyElement;
{$IfEnd} // NOT Defined(NoScripts)
function Tm3AttrIndexWriterHeader_TypeInfo: PTypeInfo;
{$If NOT Defined(NoScripts)}
function Tm3AttrIndexWriterHeader_ToValue(const aSelf: Tm3AttrIndexWriterHeader): TtfwStackValue;
{$IfEnd} // NOT Defined(NoScripts)
{$If NOT Defined(NoScripts)}
function TtfwStackValue_C(const aSelf: Tm3AttrIndexWriterHeader): TtfwStackValue; overload;
{$IfEnd} // NOT Defined(NoScripts)
{$If NOT Defined(NoScripts)}
function Tm3AttrIndexWriterHeader_ToBox(const aSelf: Tm3AttrIndexWriterHeader): Il3Box;
{$IfEnd} // NOT Defined(NoScripts)
{$If NOT Defined(NoScripts)}
function Tm3AttrIndexWriterHeader_FromValue(const aValue: TtfwStackValue): Tm3AttrIndexWriterHeader;
{$IfEnd} // NOT Defined(NoScripts)

implementation

uses
 l3ImplUses
 {$If NOT Defined(NoScripts)}
 , tfwClassProcedure
 {$IfEnd} // NOT Defined(NoScripts)
 {$If NOT Defined(NoScripts)}
 , tfwWordInfo
 {$IfEnd} // NOT Defined(NoScripts)
 {$If NOT Defined(NoScripts)}
 , tfwScriptingInterfaces
 {$IfEnd} // NOT Defined(NoScripts)
 {$If NOT Defined(NoScripts)}
 , tfwAxiomaticsResNameGetter
 {$IfEnd} // NOT Defined(NoScripts)
 , l3BoxForStruct
 {$If NOT Defined(NoScripts)}
 , TtfwTypeRegistrator_Proxy
 {$IfEnd} // NOT Defined(NoScripts)
 {$If NOT Defined(NoScripts)}
 , TtfwClassRef_Proxy
 {$IfEnd} // NOT Defined(NoScripts)
 {$If NOT Defined(NoScripts)}
 , tfwTypeInfo
 {$IfEnd} // NOT Defined(NoScripts)
 , l3Interfaces
 , l3String
 {$If NOT Defined(NoScripts)}
 , tfwValueTypes
 {$IfEnd} // NOT Defined(NoScripts)
 {$If NOT Defined(NoScripts)}
 , tfwRegisterableWordPrim
 {$IfEnd} // NOT Defined(NoScripts)
 , tfwCStringFactory
 , l3NamedFileStream
 , l3Stream
 , m2COMLib
 , l3Types
 //#UC START# *69AC2E42033Dimpl_uses*
 , Classes
 , DateUtils
 //, l3Types
 , l3PointerUtils
 , l3Date
 , l3Enumerators
 , m2MemLib
 , m3Exceptions
 , m3DBTools
 , m3RangedDocumentsList
 , m3LZODeflateStreamNew
 , m3LZOInflateStreamNew
 , l3TempMemoryStream
 , m3ZLibDeflateStreamNew
 , m3ZLibInflateStreamNew
 , l3ZLibCompressStream
 , l3ZLibDecompressStream
 , l3Base
;

const
 cFirstFrameInfoMark : AnsiString = 'ffi';
 cSequentialMark : AnsiString = 'seq'
 //#UC END# *69AC2E42033Dimpl_uses*
;

{$If NOT Defined(NoScripts)}
type
 TkwIm3AttrIndexWriterWriteVersions = TtfwClassProcedure;
  {* Слово скрипта m3AttrIndexWriter:WriteVersions }
{$IfEnd} // NOT Defined(NoScripts)

{$If NOT Defined(NoScripts)}
type
 TkwIm3AttrIndexWriterWriteRange = TtfwClassProcedure;
  {* Слово скрипта m3AttrIndexWriter:WriteRange }
{$IfEnd} // NOT Defined(NoScripts)

{$If NOT Defined(NoScripts)}
type
 TkwIm3AttrIndexWriterWriteOperation = TtfwClassProcedure;
  {* Слово скрипта m3AttrIndexWriter:WriteOperation }
{$IfEnd} // NOT Defined(NoScripts)

{$If NOT Defined(NoScripts)}
type
 TkwIm3AttrIndexWriterStartBody = TtfwClassProcedure;
  {* Слово скрипта m3AttrIndexWriter:StartBody }
{$IfEnd} // NOT Defined(NoScripts)

{$If NOT Defined(NoScripts)}
type
 TkwIm3AttrIndexWriterFinishBody = TtfwClassProcedure;
  {* Слово скрипта m3AttrIndexWriter:FinishBody }
{$IfEnd} // NOT Defined(NoScripts)

{$If NOT Defined(NoScripts)}
type
 TkwIm3AttrIndexWriterWriteBodyElement = TtfwClassProcedure;
  {* Слово скрипта m3AttrIndexWriter:WriteBodyElement }
{$IfEnd} // NOT Defined(NoScripts)

{$If NOT Defined(NoScripts)}
type
 TIm3AttrIndexWriterKeywordsPackResNameGetter = {final} class(TtfwAxiomaticsResNameGetter)
  {* Регистрация скриптованой аксиоматики }
  public
   class function ResName: AnsiString; override;
 end;//TIm3AttrIndexWriterKeywordsPackResNameGetter
{$IfEnd} // NOT Defined(NoScripts)

{$If NOT Defined(NoScripts)}
type
 TBoxFor_Tm3AttrIndexWriterSubStreamInfo = {final} class(Tl3BoxForStruct, IBoxFor_Tm3AttrIndexWriterSubStreamInfo)
  private
   f_Boxed: Tm3AttrIndexWriterSubStreamInfo;
  protected
   function Get_Boxed: Tm3AttrIndexWriterSubStreamInfo;
   function Get_pBoxed: Tm3AttrIndexWriterSubStreamInfoPtr;
   function GetDataPtr: Pointer; override;
   function GetDataSize: Integer; override;
   function GetBoxTypeInfo: PTypeInfo; override;
   function GetAsPrintable(const aCtx: TtfwContextStub): Il3CString; override;
   procedure ClearFields; override;
  public
   constructor Create(const aBoxed: Tm3AttrIndexWriterSubStreamInfo); reintroduce;
   class function Make(const aBoxed: Tm3AttrIndexWriterSubStreamInfo): IBoxFor_Tm3AttrIndexWriterSubStreamInfo; reintroduce;
 //#UC START# *69AFF780026ATBoxpubl*
 //#UC END# *69AFF780026ATBoxpubl*
 end;//TBoxFor_Tm3AttrIndexWriterSubStreamInfo
{$IfEnd} // NOT Defined(NoScripts)

{$If NOT Defined(NoScripts)}
type
 TBoxFor_Tm3AttrIndexWriterBodyElement = {final} class(Tl3BoxForStruct, IBoxFor_Tm3AttrIndexWriterBodyElement)
  private
   f_Boxed: Tm3AttrIndexWriterBodyElement;
  protected
   function Get_Boxed: Tm3AttrIndexWriterBodyElement;
   function Get_pBoxed: Tm3AttrIndexWriterBodyElementPtr;
   function GetDataPtr: Pointer; override;
   function GetDataSize: Integer; override;
   function GetBoxTypeInfo: PTypeInfo; override;
   function GetAsPrintable(const aCtx: TtfwContextStub): Il3CString; override;
   procedure ClearFields; override;
  public
   constructor Create(const aBoxed: Tm3AttrIndexWriterBodyElement); reintroduce;
   class function Make(const aBoxed: Tm3AttrIndexWriterBodyElement): IBoxFor_Tm3AttrIndexWriterBodyElement; reintroduce;
 //#UC START# *69AC79CD0094TBoxpubl*
 //#UC END# *69AC79CD0094TBoxpubl*
 end;//TBoxFor_Tm3AttrIndexWriterBodyElement
{$IfEnd} // NOT Defined(NoScripts)

{$If NOT Defined(NoScripts)}
type
 TBoxFor_Tm3AttrIndexWriterHeader = {final} class(Tl3BoxForStruct, IBoxFor_Tm3AttrIndexWriterHeader)
  private
   f_Boxed: Tm3AttrIndexWriterHeader;
  protected
   function Get_Boxed: Tm3AttrIndexWriterHeader;
   function Get_pBoxed: Tm3AttrIndexWriterHeaderPtr;
   function GetDataPtr: Pointer; override;
   function GetDataSize: Integer; override;
   function GetBoxTypeInfo: PTypeInfo; override;
   function GetAsPrintable(const aCtx: TtfwContextStub): Il3CString; override;
   procedure ClearFields; override;
  public
   constructor Create(const aBoxed: Tm3AttrIndexWriterHeader); reintroduce;
   class function Make(const aBoxed: Tm3AttrIndexWriterHeader): IBoxFor_Tm3AttrIndexWriterHeader; reintroduce;
 //#UC START# *69AC312A0001TBoxpubl*
 //#UC END# *69AC312A0001TBoxpubl*
 end;//TBoxFor_Tm3AttrIndexWriterHeader
{$IfEnd} // NOT Defined(NoScripts)

{$If NOT Defined(NoScripts)}
procedure TkwIm3AttrIndexWriterWriteVersions_ImplWriteVersions(const aCtx: TtfwContext;
 const aSelf: Im3AttrIndexWriter;
 const aVersions: Im3IndexedVersions);
begin
 if (aSelf = nil) then
 begin
  Exit;
 end;
 aSelf.WriteVersions(aVersions);
end;//TkwIm3AttrIndexWriterWriteVersions_ImplWriteVersions
{$IfEnd} // NOT Defined(NoScripts)

{$If NOT Defined(NoScripts)}
function TkwIm3AttrIndexWriterWriteVersions_ParamsTypes: PTypeInfoArray;
begin
 Result := TtfwWord.OpenTypesToTypes([TtfwParamInfo_C('aSelf', TypeInfo(Im3AttrIndexWriter)), TtfwParamInfo_C('aVersions', TtfwValueTypes.MakeTypedef('Im3IndexedVersions', TypeInfo(Im3IndexedVersions)))]);
end;//TkwIm3AttrIndexWriterWriteVersions_ParamsTypes
{$IfEnd} // NOT Defined(NoScripts)

{$If NOT Defined(NoScripts)}
procedure TkwIm3AttrIndexWriterWriteVersions_DoIt(const aCtx: TtfwContext);
var l_aSelf: Im3AttrIndexWriter;
var l_aVersions: Im3IndexedVersions;
begin
 try
  l_aSelf := Im3AttrIndexWriter(aCtx.rEngine.Pop.AsIntf(TypeInfo(Im3AttrIndexWriter)));
 except
  on E: Exception do
  begin
   aCtx.GetParamError('aSelf: Im3AttrIndexWriter : ', E);
   Exit;
  end;//on E: Exception
 end;//try..except
 try
  l_aVersions := Im3IndexedVersions(aCtx.rEngine.Pop.AsIntf(TypeInfo(Im3IndexedVersions)));
 except
  on E: Exception do
  begin
   aCtx.GetParamError('aVersions: Im3IndexedVersions : ', E);
   Exit;
  end;//on E: Exception
 end;//try..except
 TkwIm3AttrIndexWriterWriteVersions_ImplWriteVersions(aCtx, l_aSelf, l_aVersions);
end;//TkwIm3AttrIndexWriterWriteVersions_DoIt
{$IfEnd} // NOT Defined(NoScripts)

{$If NOT Defined(NoScripts)}
procedure TkwIm3AttrIndexWriterWriteRange_ImplWriteRange(const aCtx: TtfwContext;
 const aSelf: Im3AttrIndexWriter;
 const aRange: Tl3Range);
begin
 if (aSelf = nil) then
 begin
  Exit;
 end;
 aSelf.WriteRange(aRange);
end;//TkwIm3AttrIndexWriterWriteRange_ImplWriteRange
{$IfEnd} // NOT Defined(NoScripts)

{$If NOT Defined(NoScripts)}
function TkwIm3AttrIndexWriterWriteRange_ParamsTypes: PTypeInfoArray;
begin
 Result := TtfwWord.OpenTypesToTypes([TtfwParamInfo_C('aSelf', TypeInfo(Im3AttrIndexWriter)), TtfwParamInfo_C('aRange', TtfwValueTypes.MakeBox('Tl3Range', Tl3Range_TypeInfo))]);
end;//TkwIm3AttrIndexWriterWriteRange_ParamsTypes
{$IfEnd} // NOT Defined(NoScripts)

{$If NOT Defined(NoScripts)}
procedure TkwIm3AttrIndexWriterWriteRange_DoIt(const aCtx: TtfwContext);
var l_aSelf: Im3AttrIndexWriter;
var l_aRange: IBoxFor_Tl3Range;
begin
 try
  l_aSelf := Im3AttrIndexWriter(aCtx.rEngine.Pop.AsIntf(TypeInfo(Im3AttrIndexWriter)));
 except
  on E: Exception do
  begin
   aCtx.GetParamError('aSelf: Im3AttrIndexWriter : ', E);
   Exit;
  end;//on E: Exception
 end;//try..except
 try
  l_aRange := IBoxFor_Tl3Range(aCtx.rEngine.Pop.AsIntf(TypeInfo(IBoxFor_Tl3Range)));
 except
  on E: Exception do
  begin
   aCtx.GetParamError('aRange: IBoxFor_Tl3Range : ', E);
   Exit;
  end;//on E: Exception
 end;//try..except
 TkwIm3AttrIndexWriterWriteRange_ImplWriteRange(aCtx, l_aSelf, l_aRange.pBoxed^);
end;//TkwIm3AttrIndexWriterWriteRange_DoIt
{$IfEnd} // NOT Defined(NoScripts)

{$If NOT Defined(NoScripts)}
procedure TkwIm3AttrIndexWriterWriteOperation_ImplWriteOperation(const aCtx: TtfwContext;
 const aSelf: Im3AttrIndexWriter;
 anOperation: Tm3GroupOperation);
begin
 if (aSelf = nil) then
 begin
  Exit;
 end;
 aSelf.WriteOperation(anOperation);
end;//TkwIm3AttrIndexWriterWriteOperation_ImplWriteOperation
{$IfEnd} // NOT Defined(NoScripts)

{$If NOT Defined(NoScripts)}
function TkwIm3AttrIndexWriterWriteOperation_ParamsTypes: PTypeInfoArray;
begin
 Result := TtfwWord.OpenTypesToTypes([TtfwParamInfo_C('aSelf', TypeInfo(Im3AttrIndexWriter)), TtfwParamInfo_C('anOperation', TypeInfo(Tm3GroupOperation))]);
end;//TkwIm3AttrIndexWriterWriteOperation_ParamsTypes
{$IfEnd} // NOT Defined(NoScripts)

{$If NOT Defined(NoScripts)}
procedure TkwIm3AttrIndexWriterWriteOperation_DoIt(const aCtx: TtfwContext);
var l_aSelf: Im3AttrIndexWriter;
var l_anOperation: Tm3GroupOperation;
begin
 try
  l_aSelf := Im3AttrIndexWriter(aCtx.rEngine.Pop.AsIntf(TypeInfo(Im3AttrIndexWriter)));
 except
  on E: Exception do
  begin
   aCtx.GetParamError('aSelf: Im3AttrIndexWriter : ', E);
   Exit;
  end;//on E: Exception
 end;//try..except
 try
  l_anOperation := Tm3GroupOperation(aCtx.rEngine.PopInt(TypeInfo(Tm3GroupOperation)));
 except
  on E: Exception do
  begin
   aCtx.GetParamError('anOperation: Tm3GroupOperation : ', E);
   Exit;
  end;//on E: Exception
 end;//try..except
 TkwIm3AttrIndexWriterWriteOperation_ImplWriteOperation(aCtx, l_aSelf, l_anOperation);
end;//TkwIm3AttrIndexWriterWriteOperation_DoIt
{$IfEnd} // NOT Defined(NoScripts)

{$If NOT Defined(NoScripts)}
procedure TkwIm3AttrIndexWriterStartBody_ImplStartBody(const aCtx: TtfwContext;
 const aSelf: Im3AttrIndexWriter;
 aCount: Integer);
begin
 if (aSelf = nil) then
 begin
  Exit;
 end;
 aSelf.StartBody(aCount);
end;//TkwIm3AttrIndexWriterStartBody_ImplStartBody
{$IfEnd} // NOT Defined(NoScripts)

{$If NOT Defined(NoScripts)}
function TkwIm3AttrIndexWriterStartBody_ParamsTypes: PTypeInfoArray;
begin
 Result := TtfwWord.OpenTypesToTypes([TtfwParamInfo_C('aSelf', TypeInfo(Im3AttrIndexWriter)), TtfwParamInfo_C('aCount', TtfwTypeInfo.MakeInteger)]);
end;//TkwIm3AttrIndexWriterStartBody_ParamsTypes
{$IfEnd} // NOT Defined(NoScripts)

{$If NOT Defined(NoScripts)}
procedure TkwIm3AttrIndexWriterStartBody_DoIt(const aCtx: TtfwContext);
var l_aSelf: Im3AttrIndexWriter;
var l_aCount: Integer;
begin
 try
  l_aSelf := Im3AttrIndexWriter(aCtx.rEngine.Pop.AsIntf(TypeInfo(Im3AttrIndexWriter)));
 except
  on E: Exception do
  begin
   aCtx.GetParamError('aSelf: Im3AttrIndexWriter : ', E);
   Exit;
  end;//on E: Exception
 end;//try..except
 try
  l_aCount := aCtx.rEngine.PopInt(TypeInfo(Integer));
 except
  on E: Exception do
  begin
   aCtx.GetParamError('aCount: Integer : ', E);
   Exit;
  end;//on E: Exception
 end;//try..except
 TkwIm3AttrIndexWriterStartBody_ImplStartBody(aCtx, l_aSelf, l_aCount);
end;//TkwIm3AttrIndexWriterStartBody_DoIt
{$IfEnd} // NOT Defined(NoScripts)

{$If NOT Defined(NoScripts)}
procedure TkwIm3AttrIndexWriterFinishBody_ImplFinishBody(const aCtx: TtfwContext;
 const aSelf: Im3AttrIndexWriter);
begin
 if (aSelf = nil) then
 begin
  Exit;
 end;
 aSelf.FinishBody;
end;//TkwIm3AttrIndexWriterFinishBody_ImplFinishBody
{$IfEnd} // NOT Defined(NoScripts)

{$If NOT Defined(NoScripts)}
procedure TkwIm3AttrIndexWriterFinishBody_DoIt(const aCtx: TtfwContext);
var l_aSelf: Im3AttrIndexWriter;
begin
 try
  l_aSelf := Im3AttrIndexWriter(aCtx.rEngine.Pop.AsIntf(TypeInfo(Im3AttrIndexWriter)));
 except
  on E: Exception do
  begin
   aCtx.GetParamError('aSelf: Im3AttrIndexWriter : ', E);
   Exit;
  end;//on E: Exception
 end;//try..except
 TkwIm3AttrIndexWriterFinishBody_ImplFinishBody(aCtx, l_aSelf);
end;//TkwIm3AttrIndexWriterFinishBody_DoIt
{$IfEnd} // NOT Defined(NoScripts)

{$If NOT Defined(NoScripts)}
procedure TkwIm3AttrIndexWriterWriteBodyElement_ImplWriteBodyElement(const aCtx: TtfwContext;
 const aSelf: Im3AttrIndexWriter;
 aKey: Integer;
 const aValue: Il3RangeEnumerable);
begin
 if (aSelf = nil) then
 begin
  Exit;
 end;
 aSelf.WriteBodyElement(aKey, aValue);
end;//TkwIm3AttrIndexWriterWriteBodyElement_ImplWriteBodyElement
{$IfEnd} // NOT Defined(NoScripts)

{$If NOT Defined(NoScripts)}
function TkwIm3AttrIndexWriterWriteBodyElement_ParamsTypes: PTypeInfoArray;
begin
 Result := TtfwWord.OpenTypesToTypes([TtfwParamInfo_C('aSelf', TypeInfo(Im3AttrIndexWriter)), TtfwParamInfo_C('aKey', TtfwTypeInfo.MakeInteger), TtfwParamInfo_C('aValue', TypeInfo(Il3RangeEnumerable))]);
end;//TkwIm3AttrIndexWriterWriteBodyElement_ParamsTypes
{$IfEnd} // NOT Defined(NoScripts)

{$If NOT Defined(NoScripts)}
procedure TkwIm3AttrIndexWriterWriteBodyElement_DoIt(const aCtx: TtfwContext);
var l_aSelf: Im3AttrIndexWriter;
var l_aKey: Integer;
var l_aValue: Il3RangeEnumerable;
begin
 try
  l_aSelf := Im3AttrIndexWriter(aCtx.rEngine.Pop.AsIntf(TypeInfo(Im3AttrIndexWriter)));
 except
  on E: Exception do
  begin
   aCtx.GetParamError('aSelf: Im3AttrIndexWriter : ', E);
   Exit;
  end;//on E: Exception
 end;//try..except
 try
  l_aKey := aCtx.rEngine.PopInt(TypeInfo(Integer));
 except
  on E: Exception do
  begin
   aCtx.GetParamError('aKey: Integer : ', E);
   Exit;
  end;//on E: Exception
 end;//try..except
 try
  l_aValue := Il3RangeEnumerable(aCtx.rEngine.Pop.AsIntf(TypeInfo(Il3RangeEnumerable)));
 except
  on E: Exception do
  begin
   aCtx.GetParamError('aValue: Il3RangeEnumerable : ', E);
   Exit;
  end;//on E: Exception
 end;//try..except
 TkwIm3AttrIndexWriterWriteBodyElement_ImplWriteBodyElement(aCtx, l_aSelf, l_aKey, l_aValue);
end;//TkwIm3AttrIndexWriterWriteBodyElement_DoIt
{$IfEnd} // NOT Defined(NoScripts)

{$If NOT Defined(NoScripts)}
function Im3AttrIndexWriterKeywordsPack_Im3AttrIndexWriter_SelfTypeInfo: TtfwValueTypes;
begin
 Result := TtfwValueTypes.Make(TypeInfo(Im3AttrIndexWriter));
end;//Im3AttrIndexWriterKeywordsPack_Im3AttrIndexWriter_SelfTypeInfo
{$IfEnd} // NOT Defined(NoScripts)

function Tm3AttrIndexWriterSubStreamInfo_TypeInfo: PTypeInfo;
begin
 Result := TypeInfo(IBoxFor_Tm3AttrIndexWriterSubStreamInfo);
end;//Tm3AttrIndexWriterSubStreamInfo_TypeInfo

{$If NOT Defined(NoScripts)}
function Tm3AttrIndexWriterSubStreamInfo_ToValue(const aSelf: Tm3AttrIndexWriterSubStreamInfo): TtfwStackValue;
begin
 Result := TtfwStackValue_C(Tm3AttrIndexWriterSubStreamInfo_ToBox(aSelf), Tm3AttrIndexWriterSubStreamInfo_TypeInfo);
end;//Tm3AttrIndexWriterSubStreamInfo_ToValue
{$IfEnd} // NOT Defined(NoScripts)

{$If NOT Defined(NoScripts)}
function TtfwStackValue_C(const aSelf: Tm3AttrIndexWriterSubStreamInfo): TtfwStackValue;
begin
 Result := TtfwStackValue_C(Tm3AttrIndexWriterSubStreamInfo_ToBox(aSelf), Tm3AttrIndexWriterSubStreamInfo_TypeInfo);
end;//TtfwStackValue_C
{$IfEnd} // NOT Defined(NoScripts)

{$If NOT Defined(NoScripts)}
function Tm3AttrIndexWriterSubStreamInfo_ToBox(const aSelf: Tm3AttrIndexWriterSubStreamInfo): Il3Box;
begin
 Result := TBoxFor_Tm3AttrIndexWriterSubStreamInfo.Make(aSelf);
end;//Tm3AttrIndexWriterSubStreamInfo_ToBox
{$IfEnd} // NOT Defined(NoScripts)

{$If NOT Defined(NoScripts)}
function Tm3AttrIndexWriterSubStreamInfo_FromValue(const aValue: TtfwStackValue): Tm3AttrIndexWriterSubStreamInfo;
begin
 System.FillChar(Result, SizeOf(Result), 0);
 Result := IBoxFor_Tm3AttrIndexWriterSubStreamInfo(aValue.AsIntf(Tm3AttrIndexWriterSubStreamInfo_TypeInfo)).pBoxed^;
end;//Tm3AttrIndexWriterSubStreamInfo_FromValue
{$IfEnd} // NOT Defined(NoScripts)

function Tm3AttrIndexWriterBodyElement_TypeInfo: PTypeInfo;
begin
 Result := TypeInfo(IBoxFor_Tm3AttrIndexWriterBodyElement);
end;//Tm3AttrIndexWriterBodyElement_TypeInfo

{$If NOT Defined(NoScripts)}
function Tm3AttrIndexWriterBodyElement_ToValue(const aSelf: Tm3AttrIndexWriterBodyElement): TtfwStackValue;
begin
 Result := TtfwStackValue_C(Tm3AttrIndexWriterBodyElement_ToBox(aSelf), Tm3AttrIndexWriterBodyElement_TypeInfo);
end;//Tm3AttrIndexWriterBodyElement_ToValue
{$IfEnd} // NOT Defined(NoScripts)

{$If NOT Defined(NoScripts)}
function TtfwStackValue_C(const aSelf: Tm3AttrIndexWriterBodyElement): TtfwStackValue;
begin
 Result := TtfwStackValue_C(Tm3AttrIndexWriterBodyElement_ToBox(aSelf), Tm3AttrIndexWriterBodyElement_TypeInfo);
end;//TtfwStackValue_C
{$IfEnd} // NOT Defined(NoScripts)

{$If NOT Defined(NoScripts)}
function Tm3AttrIndexWriterBodyElement_ToBox(const aSelf: Tm3AttrIndexWriterBodyElement): Il3Box;
begin
 Result := TBoxFor_Tm3AttrIndexWriterBodyElement.Make(aSelf);
end;//Tm3AttrIndexWriterBodyElement_ToBox
{$IfEnd} // NOT Defined(NoScripts)

{$If NOT Defined(NoScripts)}
function Tm3AttrIndexWriterBodyElement_FromValue(const aValue: TtfwStackValue): Tm3AttrIndexWriterBodyElement;
begin
 System.FillChar(Result, SizeOf(Result), 0);
 Result := IBoxFor_Tm3AttrIndexWriterBodyElement(aValue.AsIntf(Tm3AttrIndexWriterBodyElement_TypeInfo)).pBoxed^;
end;//Tm3AttrIndexWriterBodyElement_FromValue
{$IfEnd} // NOT Defined(NoScripts)

function Tm3AttrIndexWriterHeader_TypeInfo: PTypeInfo;
begin
 Result := TypeInfo(IBoxFor_Tm3AttrIndexWriterHeader);
end;//Tm3AttrIndexWriterHeader_TypeInfo

{$If NOT Defined(NoScripts)}
function Tm3AttrIndexWriterHeader_ToValue(const aSelf: Tm3AttrIndexWriterHeader): TtfwStackValue;
begin
 Result := TtfwStackValue_C(Tm3AttrIndexWriterHeader_ToBox(aSelf), Tm3AttrIndexWriterHeader_TypeInfo);
end;//Tm3AttrIndexWriterHeader_ToValue
{$IfEnd} // NOT Defined(NoScripts)

{$If NOT Defined(NoScripts)}
function TtfwStackValue_C(const aSelf: Tm3AttrIndexWriterHeader): TtfwStackValue;
begin
 Result := TtfwStackValue_C(Tm3AttrIndexWriterHeader_ToBox(aSelf), Tm3AttrIndexWriterHeader_TypeInfo);
end;//TtfwStackValue_C
{$IfEnd} // NOT Defined(NoScripts)

{$If NOT Defined(NoScripts)}
function Tm3AttrIndexWriterHeader_ToBox(const aSelf: Tm3AttrIndexWriterHeader): Il3Box;
begin
 Result := TBoxFor_Tm3AttrIndexWriterHeader.Make(aSelf);
end;//Tm3AttrIndexWriterHeader_ToBox
{$IfEnd} // NOT Defined(NoScripts)

{$If NOT Defined(NoScripts)}
function Tm3AttrIndexWriterHeader_FromValue(const aValue: TtfwStackValue): Tm3AttrIndexWriterHeader;
begin
 Finalize(Result);
 System.FillChar(Result, SizeOf(Result), 0);
 Result := IBoxFor_Tm3AttrIndexWriterHeader(aValue.AsIntf(Tm3AttrIndexWriterHeader_TypeInfo)).pBoxed^;
end;//Tm3AttrIndexWriterHeader_FromValue
{$IfEnd} // NOT Defined(NoScripts)

constructor Tm3PlainAttrIndexDumperElementEnumerator.Create(aCount: Integer;
 const aFileName: TFileName;
 const aBody: Tm3AttrIndexWriterSubStreamInfo);
//#UC START# *69AF4C8F003A_69AE79CA0044_var*
//#UC END# *69AF4C8F003A_69AE79CA0044_var*
begin
//#UC START# *69AF4C8F003A_69AE79CA0044_impl*
 inherited Create;
 f_Count := aCount;
 f_Index := -1;
 f_FileName := aFileName;
 f_Body := aBody;
//#UC END# *69AF4C8F003A_69AE79CA0044_impl*
end;//Tm3PlainAttrIndexDumperElementEnumerator.Create

class function Tm3PlainAttrIndexDumperElementEnumerator.Make(aCount: Integer;
 const aFileName: TFileName;
 const aBody: Tm3AttrIndexWriterSubStreamInfo): Im3AttrIndexElementEnumerator;
var
 l_Inst : Tm3PlainAttrIndexDumperElementEnumerator;
begin
 l_Inst := Create(aCount, aFileName, aBody);
 try
  Result := l_Inst;
 finally
  l_Inst.Free;
 end;//try..finally
end;//Tm3PlainAttrIndexDumperElementEnumerator.Make

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

function Tm3PlainAttrIndexDumperElementEnumerator.MoveNext: Boolean;
 {* Перемещается на следующий элемент контейнера. 

Возвращает true если элемент валидный. }
//#UC START# *5ACB6780016E_69AE79CA0044_var*
//#UC END# *5ACB6780016E_69AE79CA0044_var*
begin
//#UC START# *5ACB6780016E_69AE79CA0044_impl*
 Result := CanMoveNext;
 if Result then
 begin
  Dec(f_Count);
  Inc(f_Index);
  f_Current := nil;
  // - инициализироваться он будет в pCurrent
 end;//Result
//#UC END# *5ACB6780016E_69AE79CA0044_impl*
end;//Tm3PlainAttrIndexDumperElementEnumerator.MoveNext

function Tm3PlainAttrIndexDumperElementEnumerator.pCurrent: Im3AttrIndexElementEnumerator_PCurrentItemType;
 {* Указатель на текущий элемент. Он "закеширован" }
//#UC START# *5C4EFC140038_69AE79CA0044_var*
var
 l_Stream : Tl3Stream;
 l_Element : Tm3AttrIndexWriterBodyElement;
//#UC END# *5C4EFC140038_69AE79CA0044_var*
begin
//#UC START# *5C4EFC140038_69AE79CA0044_impl*
 if (f_Current = nil) then
 begin
  if (f_Body.rPos <= 0)
     OR (f_Body.rSize <= 0) then
   Assert(false);
  if (f_Stream = nil) then
  begin
   f_Stream := Tl3NamedFileStream.Create(f_FileName, l3_fmRead);
   f_Stream.Seek(f_Body.rPos, soBeginning);
   l_Stream := Tl3SubStream.Create(f_Stream, f_Body.rPos, f_Body.rSize);
   try
    l_Stream.SetRefTo(f_Stream);
   finally
    FreeAndNil(l_Stream);
   end;//try..finally
  end;//f_Stream = nil
  f_Stream.Seek(f_Index * SizeOf(l_Element), soBeginning);
  f_Stream.ReadBuffer(l_Element, SizeOf(l_Element));
  f_Current := Tm3PlainAttrIndexDumperElement.Make(l_Element, Self.f_FileName);
 end;//f_Current = nil
 Result := @f_Current;
//#UC END# *5C4EFC140038_69AE79CA0044_impl*
end;//Tm3PlainAttrIndexDumperElementEnumerator.pCurrent

function Tm3PlainAttrIndexDumperElementEnumerator.CanMoveNext: Boolean;
 {* Определяет - можно ли переместиться на следующий элемент контейнера. }
//#UC START# *5E60D4B30164_69AE79CA0044_var*
//#UC END# *5E60D4B30164_69AE79CA0044_var*
begin
//#UC START# *5E60D4B30164_69AE79CA0044_impl*
 Result := f_Count > 0;
//#UC END# *5E60D4B30164_69AE79CA0044_impl*
end;//Tm3PlainAttrIndexDumperElementEnumerator.CanMoveNext

function Tm3PlainAttrIndexDumperElementEnumerator.Get_Current: Im3AttrIndexElement;
//#UC START# *6739C0470374_69AE79CA0044get_var*
//#UC END# *6739C0470374_69AE79CA0044get_var*
begin
//#UC START# *6739C0470374_69AE79CA0044get_impl*
 Result := Self.pCurrent^;
//#UC END# *6739C0470374_69AE79CA0044get_impl*
end;//Tm3PlainAttrIndexDumperElementEnumerator.Get_Current

procedure Tm3PlainAttrIndexDumperElementEnumerator.Cleanup;
 {* Функция очистки полей объекта. }
//#UC START# *479731C50290_69AE79CA0044_var*
//#UC END# *479731C50290_69AE79CA0044_var*
begin
//#UC START# *479731C50290_69AE79CA0044_impl*
 FreeAndNil(f_Stream);
 inherited;
//#UC END# *479731C50290_69AE79CA0044_impl*
end;//Tm3PlainAttrIndexDumperElementEnumerator.Cleanup

procedure Tm3PlainAttrIndexDumperElementEnumerator.ClearFields;
begin
 f_Current := nil;
 inherited;
end;//Tm3PlainAttrIndexDumperElementEnumerator.ClearFields

constructor Tm3PlainAttrIndexDumperElement.Create(const anElement: Tm3AttrIndexWriterBodyElement;
 const aFileName: TFileName);
//#UC START# *69AF4D9C03E5_69AE7A520320_var*
//#UC END# *69AF4D9C03E5_69AE7A520320_var*
begin
//#UC START# *69AF4D9C03E5_69AE7A520320_impl*
 inherited Create;
 f_Element := anElement;
 f_FileName := aFileName;
//#UC END# *69AF4D9C03E5_69AE7A520320_impl*
end;//Tm3PlainAttrIndexDumperElement.Create

class function Tm3PlainAttrIndexDumperElement.Make(const anElement: Tm3AttrIndexWriterBodyElement;
 const aFileName: TFileName): Im3AttrIndexElement;
var
 l_Inst : Tm3PlainAttrIndexDumperElement;
begin
 l_Inst := Create(anElement, aFileName);
 try
  Result := l_Inst;
 finally
  l_Inst.Free;
 end;//try..finally
end;//Tm3PlainAttrIndexDumperElement.Make

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

function Tm3PlainAttrIndexDumperElement.Get_ID: Integer;
//#UC START# *666AD8510295_69AE7A520320get_var*
//#UC END# *666AD8510295_69AE7A520320get_var*
begin
//#UC START# *666AD8510295_69AE7A520320get_impl*
 Result := f_Element.rKey;
//#UC END# *666AD8510295_69AE7A520320get_impl*
end;//Tm3PlainAttrIndexDumperElement.Get_ID

function Tm3PlainAttrIndexDumperElement.Get_Values: Il3RangeEnumerable;
//#UC START# *666ADD3000B4_69AE7A520320get_var*
var
 l_Stream : Tl3Stream;
 l_SubStream : Tl3Stream;
 l_Size : Int64;
//#UC END# *666ADD3000B4_69AE7A520320get_var*
begin
//#UC START# *666ADD3000B4_69AE7A520320get_impl*
 if (f_Values = nil) then
 begin
  Case f_Element.rType of
   m3_etNone:
    f_Values := Tm3RangedDocumentsList.MakeEnum;
   m3_etSingle:
    f_Values := Tm3RangedDocumentsList.MakeEnum(f_Element.rValue);
   m3_etPair:
    f_Values := Tm3RangedDocumentsList.MakeEnum(T64to32(f_Element.rValue));
   m3_et4:
    f_Values := Tm3RangedDocumentsList.MakeEnum(T64toSmallInts(f_Element.rValue));
   m3_et8:
    f_Values := Tm3RangedDocumentsList.MakeEnum(T64toBytes(f_Element.rValue));
   m3_etRange:
    f_Values := Tm3RangedDocumentsList.MakeEnum(Tm3IDRange(f_Element.rValue));
   m3_etMultiply
   , m3_etLZO
   , m3_etZLib:
   begin
    Assert(f_Element.rValue > 0);
    l_Stream := Tl3NamedFileStream.Create(f_FileName, l3_fmRead);
    try
     l_Stream.Seek(f_Element.rValue, soBeginning);
     l_Stream.ReadBuffer(l_Size, SizeOf(l_Size));
     Assert(l_Size > 0);
     l_SubStream := Tl3SubStream.Create(l_Stream, f_Element.rValue + SizeOf(l_Size), l_Size);
     try
      FreeAndNil(l_Stream);
      // - отпускаем, дабы не читать не из того потока
      Case f_Element.rType of
       m3_etLZO:
       begin
        l_Stream := Tm3LZOInflateStreamNew.Create(l_SubStream);
        try
         f_Values := Il3RangeEnumerable_CreateFromStream(l_Stream);
        finally
         FreeAndNil(l_Stream);
        end;//try..finally
       end;//m3_etLZO
       m3_etZLib:
       begin
        l_Stream := Tl3ZLibDecompressStream.Create(l_SubStream);
        try
         f_Values := Il3RangeEnumerable_CreateFromStream(l_Stream);
        finally
         FreeAndNil(l_Stream);
        end;//try..finally
       end;//m3_etZLib
       else
        f_Values := Il3RangeEnumerable_CreateFromStream(l_SubStream);
      end;//Case f_Element.rType
     finally
      FreeAndNil(l_SubStream);
     end;//try..finally
    finally
     FreeAndNil(l_Stream);
    end;//try..finally
   end;//m3_etMultiply
   else
    l3NI;
  end;//Case f_Element.rType
 end;//f_Values = nil
 Result := f_Values;
//#UC END# *666ADD3000B4_69AE7A520320get_impl*
end;//Tm3PlainAttrIndexDumperElement.Get_Values

procedure Tm3PlainAttrIndexDumperElement.Cleanup;
 {* Функция очистки полей объекта. }
//#UC START# *479731C50290_69AE7A520320_var*
//#UC END# *479731C50290_69AE7A520320_var*
begin
//#UC START# *479731C50290_69AE7A520320_impl*
 inherited;
//#UC END# *479731C50290_69AE7A520320_impl*
end;//Tm3PlainAttrIndexDumperElement.Cleanup

procedure Tm3PlainAttrIndexDumperElement.ClearFields;
begin
 Finalize(f_Element);
 f_Values := nil;
 inherited;
end;//Tm3PlainAttrIndexDumperElement.ClearFields

constructor Tm3PlainAttrIndexDumper.Create(const aFileName: TFileName;
 aStream: Tl3Stream = nil);
//#UC START# *69AE76AD032F_69AE74DB018A_var*
var
 l_GUID : AnsiString;
 l_HeaderPos : Int64;
//#UC END# *69AE76AD032F_69AE74DB018A_var*
begin
//#UC START# *69AE76AD032F_69AE74DB018A_impl*
 //f_LastSeqIndex := -1;
 //f_LastSeqKey := Low(f_LastSeqKey);
 inherited Create;
 f_SearchMode := m3_smRandom;
 f_FileName := aFileName;
 if (aStream = nil) then
  f_Stream := Tl3NamedFileStream.Create(f_FileName, l3_fmRead)
 else
 begin
  aStream.SetRefTo(f_Stream);
  f_Stream.Seek(0, soBeginning);
 end;//aStream = nil

 l_GUID := m2COMCLSIDFromStream(f_Stream);
 if (l_GUID = GUIDToString(c_m3AttrIndexWriterGUID)) then
 begin
  f_Stream.Seek(Length(l_GUID), soBeginning);
  f_Stream.ReadBuffer(l_HeaderPos, SizeOf(l_HeaderPos));

  f_Stream.Seek(l_HeaderPos, soBeginning);
  f_Stream.ReadBuffer(f_Header, SizeOf(f_Header));

  Em3Exception.Check(f_Header.rZeroStart = 0, 'f_Header.rZeroStart = 0');
  Em3Exception.Check(f_Header.rZeroEnd = 0, 'f_Header.rZeroEnd = 0');
  Em3Exception.Check(f_Header.rVersion > 0, 'f_Header.rVersion > 0');
  Em3Exception.Check(f_Header.rVersion <= cOurVersion, 'f_Header.rVersion <= cOurVersion');
  Em3Exception.Check(f_Header.rSignature = cSignature, 'f_Header.rSignature = cSignature');
  Em3Exception.Check(f_Header.rTim = 'tim', 'f_Header.rTim = ''tim''');
  Em3Exception.Check(f_Header.rHeaderStart = l_HeaderPos, 'f_Header.rHeaderStart = l_HeaderPos');
  Em3Exception.Check(f_Header.rHeaderEnd = l_HeaderPos + SizeOf(f_Header), 'f_Header.rHeaderEnd = l_HeaderPos + SizeOf(f_Header)');

  Em3Exception.Check(f_Header.rBod = 'bod', 'f_Header.rBod = ''bod''');
  Em3Exception.Check(f_Header.rMod = 'mod', 'f_Header.rMod = ''mod''');
  Em3Exception.Check(f_Header.rVers = 'vers', 'f_Header.rVers = ''vers''');

  f_Sequential := false;
  if (f_Header.rVersion >= cSequentialVersion) then
  begin
   f_Stream.Seek(f_Header.rBody.rPos - SizeOf(f_Sequential), soBeginning);
   f_Stream.ReadBuffer(f_Sequential, SizeOf(f_Sequential));
  end;//f_Header.rVersion >= cSequentialVersion
 end//l_GUID = GUIDToString(c_m3AttrIndexWriterGUID)
 else
 begin
  raise Em3Exception.Create(l3ForceUTF8FPC('Индекс не нового формата: ' + aFileName + ' GUID = ' + l_GUID));
 end;//l_GUID = GUIDToString(c_m3AttrIndexWriterGUID)
//#UC END# *69AE76AD032F_69AE74DB018A_impl*
end;//Tm3PlainAttrIndexDumper.Create

class function Tm3PlainAttrIndexDumper.Make(const aFileName: TFileName;
 aStream: Tl3Stream = nil): Im3AttrIndexDumper;
var
 l_Inst : Tm3PlainAttrIndexDumper;
begin
 l_Inst := Create(aFileName, aStream);
 try
  Result := l_Inst;
 finally
  l_Inst.Free;
 end;//try..finally
end;//Tm3PlainAttrIndexDumper.Make

class function Tm3PlainAttrIndexDumper.TryMake(const aFileName: TFileName;
 out theDumper: Im3AttrIndexDumper): Boolean;
//#UC START# *69AEDDE802BD_69AE74DB018A_var*
var
 l_Stream : Tl3Stream;
 l_GUID : AnsiString;
//#UC END# *69AEDDE802BD_69AE74DB018A_var*
begin
//#UC START# *69AEDDE802BD_69AE74DB018A_impl*
 Result := false;
 l_Stream := Tl3NamedFileStream.Create(aFileName, l3_fmRead);
 try
  l_GUID := m2COMCLSIDFromStream(l_Stream);
  if (l_GUID = GUIDToString(c_m3AttrIndexWriterGUID)) then
  begin
   Result := true;
   //FreeAndNil(l_Stream);
   // - отпускаем поток здесь, чтобы не мешать экземпляру Dumper'а
   theDumper := Self.Make(aFileName, l_Stream);
  end;//l_GUID = GUIDToString(c_m3AttrIndexWriterGUID)
 finally
  FreeAndNil(l_Stream);
 end;//try..finally
//#UC END# *69AEDDE802BD_69AE74DB018A_impl*
end;//Tm3PlainAttrIndexDumper.TryMake

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

function Tm3PlainAttrIndexDumper.pm_GetFirst: Il3RangeEnumerable;
//#UC START# *47D8233603DD_69AE74DB018Aget_var*
//#UC END# *47D8233603DD_69AE74DB018Aget_var*
begin
//#UC START# *47D8233603DD_69AE74DB018Aget_impl*
 Result := nil;
 l3NI;
//#UC END# *47D8233603DD_69AE74DB018Aget_impl*
end;//Tm3PlainAttrIndexDumper.pm_GetFirst

function Tm3PlainAttrIndexDumper.pm_GetLast: Il3RangeEnumerable;
//#UC START# *47D823570315_69AE74DB018Aget_var*
//#UC END# *47D823570315_69AE74DB018Aget_var*
begin
//#UC START# *47D823570315_69AE74DB018Aget_impl*
 Result := nil;
 l3NI;
//#UC END# *47D823570315_69AE74DB018Aget_impl*
end;//Tm3PlainAttrIndexDumper.pm_GetLast

function Tm3PlainAttrIndexDumper.pm_GetCount: Integer;
//#UC START# *4BB08B8902F2_69AE74DB018Aget_var*
//#UC END# *4BB08B8902F2_69AE74DB018Aget_var*
begin
//#UC START# *4BB08B8902F2_69AE74DB018Aget_impl*
 Result := f_Header.rElementsCount;
//#UC END# *4BB08B8902F2_69AE74DB018Aget_impl*
end;//Tm3PlainAttrIndexDumper.pm_GetCount

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

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

for Item in Container do Process(Item);

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

См. http://mdp.garant.ru/pages/viewpage.action?pageId=152961307 }
//#UC START# *5AB8C6B0003A_69AE74DB018A_var*
//#UC END# *5AB8C6B0003A_69AE74DB018A_var*
begin
//#UC START# *5AB8C6B0003A_69AE74DB018A_impl*
 Result := Tm3PlainAttrIndexDumperElementEnumerator.Make(f_Header.rElementsCount, f_FileName, f_Header.rBody);
//#UC END# *5AB8C6B0003A_69AE74DB018A_impl*
end;//Tm3PlainAttrIndexDumper.GetEnumerator

function Tm3PlainAttrIndexDumper.ModifiedDocuments: Il3RangeEnumerable;
//#UC START# *5B2B66730195_69AE74DB018A_var*
var
 l_Stream : Tl3Stream;
//#UC END# *5B2B66730195_69AE74DB018A_var*
begin
//#UC START# *5B2B66730195_69AE74DB018A_impl*
 if (f_Modified = nil) then
 begin
  if (f_Header.rModified.rPos > 0)
     AND (f_Header.rModified.rSize > 0) then
  begin
   f_Stream.Seek(f_Header.rModified.rPos, soBeginning);
   l_Stream := Tl3SubStream.Create(f_Stream, f_Header.rModified.rPos, f_Header.rModified.rSize);
   try
    f_Modified := Il3RangeEnumerable_CreateFromStream(l_Stream);
   finally
    FreeAndNil(l_Stream);
   end;//try..finally
  end//f_Header.rModified.rPos > 0
  else
   f_Modified := Tm3RangedDocumentsList.MakeEnum;
 end;//f_Modified = nil
 Result := f_Modified;
//#UC END# *5B2B66730195_69AE74DB018A_impl*
end;//Tm3PlainAttrIndexDumper.ModifiedDocuments

function Tm3PlainAttrIndexDumper.IndexedVersions: Im3IndexedVersions;
//#UC START# *5B2E194003AE_69AE74DB018A_var*
var
 l_Stream : Tl3Stream;
//#UC END# *5B2E194003AE_69AE74DB018A_var*
begin
//#UC START# *5B2E194003AE_69AE74DB018A_impl*
 if (f_Versions = nil) then
 begin
  f_Versions := Tl3IntegerToIntegerMap.Create;
  if (f_Header.rVersions.rPos > 0)
     AND (f_Header.rVersions.rSize > 0) then
  begin
   f_Stream.Seek(f_Header.rVersions.rPos, soBeginning);
   l_Stream := Tl3SubStream.Create(f_Stream, f_Header.rVersions.rPos, f_Header.rVersions.rSize);
   try
    m3LoadVersionsFromStream(f_Versions, l_Stream);
   finally
    FreeAndNil(l_Stream);
   end;//try..finally
  end;//f_Header.rVersions.rPos > 0
 end;//f_Versions = nil
 Result := f_Versions.AsEnumerable;
//#UC END# *5B2E194003AE_69AE74DB018A_impl*
end;//Tm3PlainAttrIndexDumper.IndexedVersions

function Tm3PlainAttrIndexDumper.Get_Range: Tm3IDRange;
//#UC START# *5DA9C0270207_69AE74DB018Aget_var*
//#UC END# *5DA9C0270207_69AE74DB018Aget_var*
begin
//#UC START# *5DA9C0270207_69AE74DB018Aget_impl*
 Result := f_Header.rRange;
//#UC END# *5DA9C0270207_69AE74DB018Aget_impl*
end;//Tm3PlainAttrIndexDumper.Get_Range

function Tm3PlainAttrIndexDumper.ValuesByKey(aKey: Integer): Il3RangeEnumerable;
//#UC START# *66B4B9740318_69AE74DB018A_var*

var
 l_FileStream : Tl3Stream;
 l_Element : Tm3AttrIndexWriterBodyElement;

 procedure ElementToResult;
 var
  l_E : Im3AttrIndexElement;
  l_Size : Int64;
  l_Stream : Tl3Stream;
  l_CStream : Tl3Stream;
 begin
  Case l_Element.rType of
   m3_etNone:
    Result := Tm3RangedDocumentsList.MakeEnum;
   m3_etSingle:
    Result := Tm3RangedDocumentsList.MakeEnum(l_Element.rValue);
   m3_etPair:
    Result := Tm3RangedDocumentsList.MakeEnum(T64to32(l_Element.rValue));
   m3_et4:
    Result := Tm3RangedDocumentsList.MakeEnum(T64toSmallInts(l_Element.rValue));
   m3_et8:
    Result := Tm3RangedDocumentsList.MakeEnum(T64toBytes(l_Element.rValue));
   m3_etRange:
    Result := Tm3RangedDocumentsList.MakeEnum(Tm3IDRange(l_Element.rValue));
   m3_etMultiply
   , m3_etLZO
   , m3_etZLib:
   begin
    // - here we heed to read from l_FileStream
    Assert(l_Element.rValue > 0);
    l_FileStream.Seek(l_Element.rValue, soBeginning);
    l_FileStream.ReadBuffer(l_Size, SizeOf(l_Size));
    Assert(l_Size > 0);
    l_Stream := Tl3SubStream.Create(l_FileStream, l_Element.rValue + SizeOf(l_Size), l_Size);
    try
     Case l_Element.rType of
      m3_etLZO:
      begin
       l_CStream := Tm3LZOInflateStreamNew.Create(l_Stream);
       try
        Result := Il3RangeEnumerable_CreateFromStream(l_CStream);
       finally
        FreeAndNil(l_CStream);
       end;//try..finally
      end;//m3_etZLib
      m3_etZLib:
      begin
       l_CStream := Tl3ZLibDecompressStream.Create(l_Stream);
       try
        Result := Il3RangeEnumerable_CreateFromStream(l_CStream);
       finally
        FreeAndNil(l_CStream);
       end;//try..finally
      end;//m3_etZLib
      else
       Result := Il3RangeEnumerable_CreateFromStream(l_Stream);
     end;//Case l_Element.rType
    finally
     FreeAndNil(l_Stream);
    end;//try..finally
(*    l_E := Tm3PlainAttrIndexDumperElement.Make(l_Element, Self.f_FileName);
    Result := l_E.Values;*)
   end;//m3_etMultiply
   else
    begin
     // - here we heed to read from l_FileStream
     l_E := Tm3PlainAttrIndexDumperElement.Make(l_Element, Self.f_FileName);
     Result := l_E.Values;
    end;//else
  end;//Case l_Element.rType
 end;//ElementToResult

var
 //l_It : Im3AttrIndexElementEnumerator;
 l_ID : Integer;
 L : Integer;
 H : Integer;
 C : Tl3CompareResult;
 i : Integer;
 l_Stream : Tl3Stream;
 l_KeyPos : Int64;
//#UC END# *66B4B9740318_69AE74DB018A_var*
begin
//#UC START# *66B4B9740318_69AE74DB018A_impl*
 Result := nil;

 if (aKey < f_Header.rMinKeyID) then
  Exit;
 if (aKey > f_Header.rMaxKeyID) then
  Exit;

 if (f_SearchMode = m3_smSeq) then
 begin
  if (f_EnumeratorForSeq = nil) then
  begin
   f_EnumeratorForSeq := Self.GetEnumerator;
   Assert(f_EnumeratorForSeq <> nil);
   if not f_EnumeratorForSeq.MoveNext then
   begin
    f_EnumeratorForSeq := nil;
    Exit;
    // - ничего не нашли
    // жмём плечами и отваливаем
   end;//not f_EnumeratorForSeq.MoveNext
  end;//f_EnumeratorForSeq = nil

  while true do
  // - Move был раньше
  //while f_EnumeratorForSeq.MoveNext do
  begin
   l_ID := f_EnumeratorForSeq.pCurrent.ID;
   if (l_ID = aKey) then
   begin
    Result := f_EnumeratorForSeq.pCurrent.Values;
    Exit;
   end//l_ID = aKey
   else
   if (l_ID < aKey) then
   // - ключ правее итератора
   begin
    // Будем искать дальше
    if not f_EnumeratorForSeq.MoveNext then
    begin
     f_EnumeratorForSeq := nil;
     Exit;
     // - ничего не нашли
     // жмём плечами и отваливаем
    end;//not f_EnumeratorForSeq.MoveNext
   end//l_ID > aKey
   else
   if (l_ID > aKey) then
   // - ключ левее итератора
   begin
    // ЕСТЬ ВЕРСИЯ, что это ОТСУТСТВУЮЩИЙ КЛЮЧ

    Result := nil;
    // - явно обозачаем "пусто"
    Exit;
    // - отваливаем

    Assert(false, l3ForceUTF8FPC('Не должны сюда попадать'));
    f_EnumeratorForSeq := nil;
    // - отпускаем предыдущий
    f_EnumeratorForSeq := Self.GetEnumerator;
    // - получаем новый
    Assert(f_EnumeratorForSeq <> nil);
    if not f_EnumeratorForSeq.MoveNext then
    begin
     f_EnumeratorForSeq := nil;
     Exit;
     // - ничего не нашли
     // жмём плечами и отваливаем
    end;//not f_EnumeratorForSeq.MoveNext
    continue;

    raise Em3Exception.Create(l3ForceUTF8FPC('Похоже на рандомный доступ:')
                              + ' aKey = '
                              + IntToStr(aKey)
                              + ' ID = '
                              + IntToStr(l_ID)
                              );
    // - ругаемся
    Exit;
    // - отваливаем
   end;//l_ID > aKey
  end;//while f_EnumeratorForSeq.MoveNext
  Exit;
  // - по-любому больше ничего делать не нужно
 end;//f_SearchMode = m3_smSeq

 if (aKey = f_Header.rMinKeyID)
    OR (aKey = f_Header.rMinKeyID + 1)
    OR (aKey < 20)
    OR (f_Header.rElementsCount < 50)
    OR f_Sequential
    then
 //if false then
 begin
  // - линейный поиск
  l_FileStream := Tl3NamedFileStream.Create(f_FileName, l3_fmRead);
  try
   l_FileStream.Seek(f_Header.rBody.rPos, soBeginning);
   l_Stream := Tl3SubStream.Create(l_FileStream, f_Header.rBody.rPos, f_Header.rBody.rSize);
   try
    if f_Sequential then
    begin
     l_KeyPos := (aKey - f_Header.rMinKeyID);
     l_Stream.Seek(l_KeyPos * SizeOf(l_Element), soBeginning);
     l_Stream.ReadBuffer(l_Element, SizeOf(l_Element));
     Em3Exception.Check(l_Element.rKey = aKey, 'l_Element.rKey = aKey');
     ElementToResult;
     Exit;
    end//f_Sequential
    else
    begin
     i := f_Header.rElementsCount;
     while (i > 0) do
     begin
      //i := (L + H) shr 1;
      //l_Stream.Seek(i * SizeOf(l_Element), soBeginning);
      l_Stream.ReadBuffer(l_Element, SizeOf(l_Element));
      C := l3CompareInt64(l_Element.rKey, aKey);
      if (C = 0) then
      begin
       FreeAndNil(l_Stream);
       ElementToResult;
       Exit;
      end//C = 0
      else
      if (C > 0) then
      // - дальше можно не искать
       Exit;
     end;//i > 0
    end;//f_Sequential
   finally
    FreeAndNil(l_Stream);
   end;//try..finally
  finally
   FreeAndNil(l_FileStream);
  end;//try..finally
(*  l_It := Self.GetEnumerator;
  // - пока будем искать последовательно, а потом переделаем на поиск делением пополам
  if (l_It <> nil) then
  begin
   while l_It.MoveNext do
   begin
    l_ID := l_It.pCurrent.ID;
    if (l_ID = aKey) then
    begin
     Result := l_It.pCurrent.Values;
     Exit;
    end//l_ID = aKey
    else
    if (l_ID > aKey) then
    // - дальше можно не искать
     Exit;
   end;//while l_It.MoveNext
  end;//l_It <> nil*)
 end//линейный поиск
 else
 //if false then
 begin
  // - поиск делением пополам
  C := 0;
  L := 0;
  H := Pred(f_Header.rElementsCount);

  l_FileStream := Tl3NamedFileStream.Create(f_FileName, l3_fmRead);
  try
   l_FileStream.Seek(f_Header.rBody.rPos, soBeginning);
   l_Stream := Tl3SubStream.Create(l_FileStream, f_Header.rBody.rPos, f_Header.rBody.rSize);
   try
    while (L <= H) do
    begin
     i := (L + H) shr 1;
     l_Stream.Seek(i * SizeOf(l_Element), soBeginning);
     l_Stream.ReadBuffer(l_Element, SizeOf(l_Element));
     C := l3CompareInt64(l_Element.rKey, aKey);
     if (C < 0) then
      L := Succ(i)
     else
     begin
      if (C = 0) then
      begin
       H := Pred(i);
       FreeAndNil(l_Stream);
       ElementToResult;
       Exit;
      end//C = 0
      else
       H := Pred(i);
     end;//C < 0
    end;//while (L..
   finally
    FreeAndNil(l_Stream);
   end;//try..finally
  finally
   FreeAndNil(l_FileStream);
  end;//try..finally
 end;//поиск пополам
//#UC END# *66B4B9740318_69AE74DB018A_impl*
end;//Tm3PlainAttrIndexDumper.ValuesByKey

function Tm3PlainAttrIndexDumper.TimeStamp: TDateTime;
//#UC START# *66C46E6801D3_69AE74DB018A_var*
//#UC END# *66C46E6801D3_69AE74DB018A_var*
begin
//#UC START# *66C46E6801D3_69AE74DB018A_impl*
 Result := 0;
 System.Move(f_Header.rTimeStamp, Result, SizeOf(f_Header.rTimeStamp));
//#UC END# *66C46E6801D3_69AE74DB018A_impl*
end;//Tm3PlainAttrIndexDumper.TimeStamp

function Tm3PlainAttrIndexDumper.Get_MaxKeyID: Integer;
//#UC START# *671D18210090_69AE74DB018Aget_var*
//#UC END# *671D18210090_69AE74DB018Aget_var*
begin
//#UC START# *671D18210090_69AE74DB018Aget_impl*
 Result := f_Header.rMaxKeyID;
//#UC END# *671D18210090_69AE74DB018Aget_impl*
end;//Tm3PlainAttrIndexDumper.Get_MaxKeyID

function Tm3PlainAttrIndexDumper.Get_Operation: Tm3GroupOperation;
//#UC START# *68E135160346_69AE74DB018Aget_var*
//#UC END# *68E135160346_69AE74DB018Aget_var*
begin
//#UC START# *68E135160346_69AE74DB018Aget_impl*
 Result := f_Header.rOperation;
//#UC END# *68E135160346_69AE74DB018Aget_impl*
end;//Tm3PlainAttrIndexDumper.Get_Operation

function Tm3PlainAttrIndexDumper.Get_MinKeyID: Integer;
//#UC START# *69B14AAE0155_69AE74DB018Aget_var*
//#UC END# *69B14AAE0155_69AE74DB018Aget_var*
begin
//#UC START# *69B14AAE0155_69AE74DB018Aget_impl*
 Result := f_Header.rMinKeyID;
//#UC END# *69B14AAE0155_69AE74DB018Aget_impl*
end;//Tm3PlainAttrIndexDumper.Get_MinKeyID

procedure Tm3PlainAttrIndexDumper.Set_SearchMode(aValue: Tm3SearchMode);
//#UC START# *69BBB8A101BA_69AE74DB018Aset_var*
//#UC END# *69BBB8A101BA_69AE74DB018Aset_var*
begin
//#UC START# *69BBB8A101BA_69AE74DB018Aset_impl*
 if (aValue = m3_smRandom) then
  f_EnumeratorForSeq := nil;
  // - отпусткаем текущий перечислитель
 f_SearchMode := aValue;
//#UC END# *69BBB8A101BA_69AE74DB018Aset_impl*
end;//Tm3PlainAttrIndexDumper.Set_SearchMode

function Tm3PlainAttrIndexDumper.Get_Sequential: Boolean;
//#UC START# *69C1D45B01E5_69AE74DB018Aget_var*
//#UC END# *69C1D45B01E5_69AE74DB018Aget_var*
begin
//#UC START# *69C1D45B01E5_69AE74DB018Aget_impl*
 Result := f_Sequential;
//#UC END# *69C1D45B01E5_69AE74DB018Aget_impl*
end;//Tm3PlainAttrIndexDumper.Get_Sequential

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

procedure Tm3PlainAttrIndexDumper.Cleanup;
 {* Функция очистки полей объекта. }
//#UC START# *479731C50290_69AE74DB018A_var*
//#UC END# *479731C50290_69AE74DB018A_var*
begin
//#UC START# *479731C50290_69AE74DB018A_impl*
 //FreeAndNil(f_SubStreamForSeq);
 //FreeAndNil(f_StreamForSeq);
 f_EnumeratorForSeq := nil;
 FreeAndNil(f_Stream);
 FreeAndNil(f_Versions);
 f_Modified := nil;
 inherited;
//#UC END# *479731C50290_69AE74DB018A_impl*
end;//Tm3PlainAttrIndexDumper.Cleanup

procedure Tm3PlainAttrIndexDumper.ClearFields;
begin
 f_Modified := nil;
 f_EnumeratorForSeq := nil;
 inherited;
end;//Tm3PlainAttrIndexDumper.ClearFields

//#UC START# *69AE74DB018Aimpl*
//#UC END# *69AE74DB018Aimpl*

constructor Tm3AttrIndexWriter.Create(aStream: Tl3Stream;
 aIsDirect: Boolean);
//#UC START# *69AC2FDB01A1_69AC2E42033D_var*
const
 cHeader : AnsiString = 'header';
var
 l_S : AnsiString;
 l_AfterGUIDPos : Int64;
 l_HeaderStart : Int64;
//#UC END# *69AC2FDB01A1_69AC2E42033D_var*
begin
//#UC START# *69AC2FDB01A1_69AC2E42033D_impl*
 f_IsDirect := aIsDirect;
 Assert(aStream <> nil);
 inherited Create;
 aStream.SetRefTo(f_Stream);
 f_Header.rZeroStart := 0;
 f_Header.rVer := 'ver';
 f_Header.rVersion := cOurVersion;
 f_Header.rSig := 'sig';
 f_Header.rSignature := cSignature;
 f_Header.rTim := 'tim';
 //f_Header.rTimeStamp := BadDateTime;
 f_Header.rTimeStamp := 0;
 f_Header.rHea := 'hea';
 f_Header.rHeaderStart := -1;
 f_Header.rHeaderEnd := -1;
 f_Header.rStr := 'str';
 f_Header.rStreamEnd := -1;
 f_Header.rRan := 'ran';
 f_Header.rRange := Tl3Range_E;
 f_Header.rOper := 'oper';
 f_Header.rOperation := m3_gopNone;
 f_Header.rMod := 'mod';
 f_Header.rModified.rPos := -1;
 f_Header.rModified.rSize := 0;
 f_Header.rVers := 'vers';
 f_Header.rVersions.rPos := -1;
 f_Header.rVersions.rSize := 0;
 f_Header.rBod := 'bod';
 f_Header.rBody.rPos := -1;
 f_Header.rBody.rSize := 0;
 f_Header.rCnt := 'cnt';
 f_Header.rElementsCount := 0;
 f_Header.rMin := 'min';
 f_Header.rMinKeyID := High(f_Header.rMinKeyID);
 f_Header.rMax := 'max';
 f_Header.rMaxKeyID := Low(f_Header.rMaxKeyID);
 f_Header.rNextPartPos := -1;
 f_Header.rZeroEnd := 0;

 f_Stream.Seek(0, soBeginning);

 l_S := GUIDToString(c_m3AttrIndexWriterGUID);
 f_Stream.WriteBuffer(l_S[1], Length(l_S));

 l_AfterGUIDPos := f_Stream.Position;
 // - позиция после GUID
 f_Header.rStreamEnd := l_AfterGUIDPos;

 l_HeaderStart := 0;
 f_Stream.WriteBuffer(l_HeaderStart, SizeOf(l_HeaderStart));
 // - пишем заглушку

 Self.WriteStart(cHeader);
 // - пишем маркер заголовка

 l_HeaderStart := f_Header.rStreamEnd;
 //l_HeaderStart := f_Stream.Position;
 // - реальная позиция заголовка
 //f_Header.rStreamEnd := l_HeaderStart;
 f_Header.rHeaderStart := l_HeaderStart;
 // - тут у нас закончился заголовок
 f_Header.rHeaderEnd := l_HeaderStart + SizeOf(f_Header);
 // - в заголовок присваиваем его начало

 f_Stream.Seek(l_AfterGUIDPos, soBeginning);
 // - смещаемся за GUID
 f_Stream.WriteBuffer(l_HeaderStart, SizeOf(l_HeaderStart));
 // - пишем реальное значение

 f_Stream.Seek(l_HeaderStart, soBeginning);
 // - возвращаемся к начало заголовка

 f_Stream.WriteBuffer(f_Header, SizeOf(f_Header));
 f_HeaderSave := f_Header;
 // - пишем заголовок
 //f_Header.rHeaderEnd := f_Stream.Position;
 // - тут у нас закончился заголовок

 Self.WriteEnd(cHeader);
 // - пишем маркер заголовка

 //f_Header.rStreamEnd := f_Stream.Position;
 // - тут в данный момент закончился поток
 Self.SaveHeader;
 // - перезаписываем заголовок с актуальными значениями
//#UC END# *69AC2FDB01A1_69AC2E42033D_impl*
end;//Tm3AttrIndexWriter.Create

class function Tm3AttrIndexWriter.Make(aStream: Tl3Stream;
 aIsDirect: Boolean): Im3AttrIndexWriter;
var
 l_Inst : Tm3AttrIndexWriter;
begin
 l_Inst := Create(aStream, aIsDirect);
 try
  Result := l_Inst;
 finally
  l_Inst.Free;
 end;//try..finally
end;//Tm3AttrIndexWriter.Make

procedure Tm3AttrIndexWriter.WriteEOL;
//#UC START# *69AC3E360052_69AC2E42033D_var*
var
 l_C : AnsiChar;
//#UC END# *69AC3E360052_69AC2E42033D_var*
begin
//#UC START# *69AC3E360052_69AC2E42033D_impl*
 l_C := #13;
 f_Stream.WriteBuffer(l_C, SizeOf(l_C));
 l_C := #10;
 f_Stream.WriteBuffer(l_C, SizeOf(l_C));
//#UC END# *69AC3E360052_69AC2E42033D_impl*
end;//Tm3AttrIndexWriter.WriteEOL

procedure Tm3AttrIndexWriter.SaveHeader;
//#UC START# *69AC40D00345_69AC2E42033D_var*
//#UC END# *69AC40D00345_69AC2E42033D_var*
begin
//#UC START# *69AC40D00345_69AC2E42033D_impl*
 if (f_Stream <> nil) then
 begin
  if (m2MEMCompare(@f_Header, @f_HeaderSave, SizeOf(f_Header)) <> 0) then
  begin
   f_Stream.Seek(f_Header.rHeaderStart, soBeginning);
   f_Stream.WriteBuffer(f_Header, SizeOf(f_Header));
   f_HeaderSave := f_Header;
  end;//m2MEMCompare(@f_Header, @f_HeaderSave, SizeOf(f_Header)) <> 0
 end;//f_Stream <> nil
//#UC END# *69AC40D00345_69AC2E42033D_impl*
end;//Tm3AttrIndexWriter.SaveHeader

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

procedure Tm3AttrIndexWriter.WriteVersions(const aVersions: Im3IndexedVersions);
//#UC START# *69AC303F0197_69AC2E42033D_var*
const
 cVersions : AnsiString = 'versions';
//#UC END# *69AC303F0197_69AC2E42033D_var*
begin
//#UC START# *69AC303F0197_69AC2E42033D_impl*
 Assert(f_Header.rVersions.rPos = -1, l3ForceUTF8FPC('Уже писали версии'));
 f_Stream.Seek(f_Header.rStreamEnd, soBeginning);

 Self.WriteStart(cVersions);

 f_Header.rVersions.rPos := f_Header.rStreamEnd;
 //f_Header.rVersions.rPos := f_Stream.Position;
 m3WriteVersionsToStream(aVersions, f_Stream);
 f_Header.rVersions.rSize := f_Stream.Position - f_Header.rVersions.rPos;

 Self.WriteEnd(cVersions);

//#UC END# *69AC303F0197_69AC2E42033D_impl*
end;//Tm3AttrIndexWriter.WriteVersions

procedure Tm3AttrIndexWriter.WriteModified(const aModified: Il3RangeEnumerable;
 aTimeStamp: TDateTime);
//#UC START# *69AC30920069_69AC2E42033D_var*
const
 cModified : AnsiString = 'modified';
var
 l_TimeStamp: TDateTime;
//#UC END# *69AC30920069_69AC2E42033D_var*
begin
//#UC START# *69AC30920069_69AC2E42033D_impl*
 l_TimeStamp := 0;
 f_Header.rTimeStamp := 0;
 System.Move(aTimeStamp, f_Header.rTimeStamp, SizeOf(f_Header.rTimeStamp));
 System.Move(f_Header.rTimeStamp, l_TimeStamp, SizeOf(f_Header.rTimeStamp));

 Assert(SameDateTime(l_TimeStamp, aTimeStamp));
 //Assert(SameValue(l_TimeStamp, aTimeStamp));

 //f_Header.rTimeStamp := aTimeStamp;

 Assert(f_Header.rModified.rPos = -1, l3ForceUTF8FPC('Уже писали модифицированные'));
 f_Stream.Seek(f_Header.rStreamEnd, soBeginning);

 Self.WriteStart(cModified);

 f_Header.rModified.rPos := f_Header.rStreamEnd;
 //f_Header.rModified.rPos := f_Stream.Position;
 Il3RangeEnumerable_WriteTo(aModified, f_Stream);
 f_Header.rModified.rSize := f_Stream.Position - f_Header.rModified.rPos;

 Self.WriteEnd(cModified);

//#UC END# *69AC30920069_69AC2E42033D_impl*
end;//Tm3AttrIndexWriter.WriteModified

procedure Tm3AttrIndexWriter.WriteRange(const aRange: Tl3Range);
//#UC START# *69AC30EC01E0_69AC2E42033D_var*
//#UC END# *69AC30EC01E0_69AC2E42033D_var*
begin
//#UC START# *69AC30EC01E0_69AC2E42033D_impl*
 f_Header.rRange := aRange;
 //Self.SaveHeader;
//#UC END# *69AC30EC01E0_69AC2E42033D_impl*
end;//Tm3AttrIndexWriter.WriteRange

procedure Tm3AttrIndexWriter.WriteOperation(anOperation: Tm3GroupOperation);
//#UC START# *69AC31B40187_69AC2E42033D_var*
//#UC END# *69AC31B40187_69AC2E42033D_var*
begin
//#UC START# *69AC31B40187_69AC2E42033D_impl*
 f_Header.rOperation := anOperation;
 //Self.SaveHeader;
//#UC END# *69AC31B40187_69AC2E42033D_impl*
end;//Tm3AttrIndexWriter.WriteOperation

procedure Tm3AttrIndexWriter.StartBody(aCount: Integer);
//#UC START# *69AC757C029F_69AC2E42033D_var*
const
 cBody : AnsiString = 'body';
var
 l_Element : Tm3AttrIndexWriterBodyElement;
 l_Index : Integer;
//#UC END# *69AC757C029F_69AC2E42033D_var*
begin
//#UC START# *69AC757C029F_69AC2E42033D_impl*
 Assert(f_Header.rBody.rPos = -1, l3ForceUTF8FPC('Уже писали тело'));
 f_Sequential := true;
 // - будем оптимистами
 f_PrevKey := Low(f_PrevKey);
 f_Header.rMinKeyID := High(f_Header.rMinKeyID);
 f_Header.rMaxKeyID := Low(f_Header.rMaxKeyID);
 f_DeclaredCapacity := aCount;
 f_Capacity := aCount;
 f_Header.rElementsCount := 0;

 f_FrameInfo.rCount := 0;
 f_FrameInfo.rMinKeyID := High(f_FrameInfo.rMinKeyID);
 f_FrameInfo.rMaxKeyID := Low(f_FrameInfo.rMaxKeyID);
 f_FrameInfo.rNextPartPos := -1;

 f_Stream.Seek(f_Header.rStreamEnd, soBeginning);

 Self.WriteStart(cBody);

 f_Stream.WriteBuffer(cFirstFrameInfoMark[1], Length(cFirstFrameInfoMark));
 f_Header.rStreamEnd := f_Stream.Position;
 f_FrameInfoPos := f_Header.rStreamEnd;
 f_Stream.WriteBuffer(f_FrameInfo, SizeOf(f_FrameInfo));
 // - записываем placeholder'а
 f_Header.rStreamEnd := f_Stream.Position;

 f_Stream.WriteBuffer(cSequentialMark[1], Length(cSequentialMark));
 f_Header.rStreamEnd := f_Stream.Position;
 f_SequentialInfoPos := f_Header.rStreamEnd;
 f_Stream.WriteBuffer(f_Sequential, SizeOf(f_Sequential));
 // - записываем placeholder'а
 f_Header.rStreamEnd := f_Stream.Position;

 f_Header.rBody.rPos := f_Header.rStreamEnd;
 //f_Header.rBody.rPos := f_Stream.Position;

 l_Element.rType := m3_etNone;
 l_Element.rKey := Low(l_Element.rKey);
 l_Element.rValue := Low(l_Element.rValue);

 for l_Index := 0 to Pred(aCount) do
 begin
  f_Stream.WriteBuffer(l_Element, SizeOf(l_Element));
 end;//for l_Index

 f_Header.rBody.rSize := f_Stream.Position - f_Header.rBody.rPos;

 Self.WriteEnd(cBody);

 f_Stream.Seek(f_Header.rBody.rPos, soBeginning);
//#UC END# *69AC757C029F_69AC2E42033D_impl*
end;//Tm3AttrIndexWriter.StartBody

procedure Tm3AttrIndexWriter.FinishBody;
//#UC START# *69AC75A80048_69AC2E42033D_var*
//#UC END# *69AC75A80048_69AC2E42033D_var*
begin
//#UC START# *69AC75A80048_69AC2E42033D_impl*
 f_Stream.Seek(f_FrameInfoPos, soBeginning);
 f_Stream.WriteBuffer(f_FrameInfo, SizeOf(f_FrameInfo));

 if not f_Sequential then
 begin
  f_Stream.Seek(f_SequentialInfoPos, soBeginning);
  f_Stream.WriteBuffer(f_Sequential, SizeOf(f_Sequential));
 end;//not f_Sequential
//#UC END# *69AC75A80048_69AC2E42033D_impl*
end;//Tm3AttrIndexWriter.FinishBody

procedure Tm3AttrIndexWriter.WriteBodyElement(aKey: Integer;
 const aValue: Il3RangeEnumerable);
//#UC START# *69AC818E005F_69AC2E42033D_var*

 {.$Define _m3UsePack}

var
 l_Element : Tm3AttrIndexWriterBodyElement;
 l_Enum : Il3IntegerEnumerable;
 l_It : Il3IntegerEnumerator;
 l_RangesCount : Integer;
 l_Count : Integer;
 l_Pos : Int64;
 l_Size : Int64;
 l_SizePos : Int64;
 l_ValuePos : Int64;
 l_KeyStr : AnsiString;
 l_NeedPack : Boolean;
 {.$IfDef _m3UsePack}
 l_Orig : Tl3Stream;
 l_Packed : Tl3Stream;
 l_PackedSize : Int64;
 l_PackStream : Tl3Stream;
 {.$EndIf _m3UsePack}
 i : Integer;
 l_R : Tm3IDRange;
 l_NeedMultiply : Boolean;
 l_NeedCheckSimple : Boolean;
 // - https://mdp.garant.ru/pages/viewpage.action?pageId=902725962
//#UC END# *69AC818E005F_69AC2E42033D_var*
begin
//#UC START# *69AC818E005F_69AC2E42033D_impl*
 Assert(f_PrevKey < aKey);

 if f_Sequential then
  if not (f_PrevKey + 1 = aKey) then
   if (f_PrevKey <> Low(f_PrevKey)) then
    f_Sequential := false;

 if (f_Capacity <= 0) then
 begin
  if (aValue = nil)
     OR aValue.Empty then
  begin
   l3System.Msg2Log(l3ForceUTF8FPC('Для ключа: ') + IntToStr(aKey) + l3ForceUTF8FPC(' не будем писать пустые значения'));
   Exit;
   // - хрен с этими пустыми значениями
  end;//aValue = nil
  l3System.Msg2Log(l3ForceUTF8FPC('Для ключа: ') + IntToStr(aKey) + l3ForceUTF8FPC(' потеряны значения при записи. Т.к. исчерпана мощность: ') + IntToStr(f_DeclaredCapacity));
  {$IfDef nsTest}
  Assert(false, l3ForceUTF8FPC('Исчерпана мощность: ') + IntToStr(f_DeclaredCapacity));
  {$EndIf nsTest}
  Exit;
  // - чтобы уж не порушить весь процесс
 end;//f_Capacity <= 0

 if f_IsDirect then
 begin
  if (aValue = nil)
     OR aValue.Empty then
  begin
   Exit;
   // - пока не пишем в лог
   l3System.Msg2Log(l3ForceUTF8FPC('Для ключа: ') + IntToStr(aKey) + l3ForceUTF8FPC(' не будем писать пустые значения'));
   Exit;
   // - хрен с этими пустыми значениями
   // Чтобы не расходовать мощность впустую.
  end;//aValue = nil
 end;//f_IsDirect

 Dec(f_Capacity);
 Inc(f_Header.rElementsCount);
 Inc(f_FrameInfo.rCount);

 if (aKey > f_Header.rMaxKeyID) then
  f_Header.rMaxKeyID := aKey;
 if (aKey < f_Header.rMinKeyID) then
  f_Header.rMinKeyID := aKey;

 if (aKey > f_FrameInfo.rMaxKeyID) then
  f_FrameInfo.rMaxKeyID := aKey;
 if (aKey < f_FrameInfo.rMinKeyID) then
  f_FrameInfo.rMinKeyID := aKey;

 f_PrevKey := aKey;
 l_Pos := f_Stream.Position;
 l_Element.rType := m3_etNone;
 l_Element.rKey := aKey;
 l_Element.rValue := Low(l_Element.rValue);

 if (aValue = nil) then
  l_RangesCount := 0
 else
  l_RangesCount := aValue.Count;

 l_R := Tl3Range_E;
 if (l_RangesCount = 1) then
 begin
  l_R := aValue.First;
  if (l_R.rLow = l_R.rHigh) then
   l_RangesCount := -1;
  // - ну пусть будет минус
 end;//l_RangesCount = 1

 if (l_RangesCount = 1) then
 begin
  l_Element.rType := m3_etRange;
  Tm3IDRange(l_Element.rValue) := l_R;
 end//l_RangesCount = 1
 else
 begin
  l_NeedMultiply := true;

  if (l_RangesCount = -1) then
   l_RangesCount := 1;

  l_NeedCheckSimple := true;
  if (l_RangesCount = 1) then
  begin
   Assert(l_R.rLow = l_R.rHigh);
   // - сюда не можем попасть, т.к. обработали выше
   l_Element.rType := m3_etSingle;
   l_Element.rValue := l_R.rLow;
   l_NeedCheckSimple := false;
   l_NeedMultiply := false;
  end//l_RangesCount = 1
  else
  if (l_RangesCount > 10) then
  // https://mdp.garant.ru/pages/viewpage.action?pageId=902725962
  // – тут надо сделать проверку l_RangesCount чтобы для больших чисел не преобразовывать Il3RangeEnumerable к Il3IntegerEnumerable.
  begin
   l_NeedCheckSimple := false;
  end;//l_RangesCount > 10

  if l_NeedCheckSimple then
  // - https://mdp.garant.ru/pages/viewpage.action?pageId=902725962
  begin
   l_NeedMultiply := false;
   // - предполагаем что обойдёмся малой кровью
   l_Enum := Il3RangeEnumerable_ToIntegerEnumerable(aValue);
   if (l_Enum = nil) then
    l_Count := 0
   else
    l_Count := l_Enum.Count;
   if (l_Count = 0) then
    l_Element.rType := m3_etNone
   else
   if (l_Count = 1) then
   begin
    l_Element.rType := m3_etSingle;
    l_Element.rValue := l_Enum.First;
   end//l_Count = 1
   else
   if (l_Count = 2) then
   begin
    l_Element.rType := m3_etPair;
    l_It := l_Enum.GetEnumerator;
    if not l_It.MoveNext then
     Assert(false);
    T64to32(l_Element.rValue).rLow := l_It.Current;
    if not l_It.MoveNext then
     Assert(false);
    T64to32(l_Element.rValue).rHigh := l_It.Current;
   end//l_Count = 2
   else
    l_NeedMultiply := true;
  end;//l_NeedCheckSimple

  if l_NeedMultiply then
  begin

   l_NeedPack := false;
   l_Element.rType := m3_etMultiply;
   if l_NeedCheckSimple then
   // - https://mdp.garant.ru/pages/viewpage.action?pageId=902725962
   begin
    if (l_Count = 4) then
    begin
     l_Element.rType := m3_et4;
     l_It := l_Enum.GetEnumerator;
     i := 0;
     while l_It.MoveNext do
     begin
      if (l_It.Current <= High(SmallInt))
         AND (l_It.Current >= Low(SmallInt))
         then
      begin
       T64toSmallInts(l_Element.rValue)[i] := l_It.Current;
       Inc(i);
      end//l_It.Current <= High(SmallInt)
      else
      begin
       l_Element.rType := m3_etMultiply;
       break;
      end;//l_It.Current <= High(SmallInt)
     end;//l_It.MoveNext
    end//l_Count = 4
    else
    if (l_Count = 8) then
    begin
     l_Element.rType := m3_et8;
     l_It := l_Enum.GetEnumerator;
     i := 0;
     while l_It.MoveNext do
     begin
      if (l_It.Current <= High(Byte))
         AND (l_It.Current >= Low(Byte))
         then
      begin
       T64toBytes(l_Element.rValue)[i] := l_It.Current;
       Inc(i);
      end//l_It.Current <= High(SmallInt)
      else
      begin
       l_Element.rType := m3_etMultiply;
       break;
      end;//l_It.Current <= High(SmallInt)
     end;//l_It.MoveNext
    end;//l_Count = 8
   end;//l_NeedCheckSimple

   if (l_Element.rType = m3_etMultiply) then
   begin
    l_Size := 0;
    l_KeyStr := IntToStr(aKey);
    l_SizePos := f_Header.rStreamEnd;
    // - размер будет записан в конец потока
    f_Stream.Seek(l_SizePos, soBeginning);
    // - смещаемся к концу потока

    Self.WriteStart(l_KeyStr);
    // - записываем маркер потока

    if (l_RangesCount > 1000) then
     l_NeedPack := true;

    if l_NeedPack then
    begin
     l_Orig := Tl3TempMemoryStream.Create;
     try
      Il3RangeEnumerable_WriteTo(aValue, l_Orig);
      l_Size := l_Orig.Size;
      Assert(l_Size > 0);
      l_Packed := Tl3TempMemoryStream.Create;
      try
       l_PackStream := Tl3ZLibCompressStream.Create(l_Packed);
       //l_PackStream := Tm3LZODeflateStreamNew.Create(l_Packed);
       try
        l_Orig.Seek(0, soBeginning);
        l3CopyStream(IStream(l_Orig), IStream(l_PackStream));
        //l_PackStream.CopyFrom(l_Orig, 0);
       finally
        FreeAndNil(l_PackStream);
       end;//try..finally

       l_PackedSize := l_Packed.Size;
       Assert(l_PackedSize > 0);

       l_SizePos := f_Header.rStreamEnd;
       // - запоминаем место где начнётся Size + Value

       if (l_PackedSize < l_Size) then
       begin
        l_Element.rType := m3_etZLib;
        //l_Element.rType := m3_etLZO;
        f_Stream.WriteBuffer(l_PackedSize, SizeOf(l_PackedSize));
        // - записывем реальный размер (вместо placeholer)
        f_Stream.CopyFrom(l_Packed, 0);
       end//l_PackedSize < l_Size
       else
       begin
        f_Stream.WriteBuffer(l_Size, SizeOf(l_Size));
        // - записывем реальный размер (вместо placeholer)
        f_Stream.CopyFrom(l_Orig, 0);
       end;//l_PackedSize < l_Size
      finally
       FreeAndNil(l_Packed);
      end;//try..finally
     finally
      FreeAndNil(l_Orig);
     end;//try..finally
     Self.WriteEnd(l_KeyStr);
     // - записываем маркер потока
    end//l_NeedPack
    else
    begin
     l_SizePos := f_Header.rStreamEnd;
     // - запоминаем место где начнётся Size + Value
     f_Stream.WriteBuffer(l_Size, SizeOf(l_Size));
     // - записывем место для Size (placeholer)
     l_ValuePos := f_Stream.Position;
     // - запоминаем место где начались значения
     Il3RangeEnumerable_WriteTo(aValue, f_Stream);
     // - записываем значения
     f_Header.rStreamEnd := f_Stream.Position;
     // - устанавливаем новый конец потока
     l_Size := f_Header.rStreamEnd - l_ValuePos;
     // - вычисляем размер значений

     Self.WriteEnd(l_KeyStr);
     // - записываем маркер потока

     Assert(l_Size > 0);
     f_Stream.Seek(l_SizePos, soBeginning);
     // - смещаемся к месту где надо писать размер
     f_Stream.WriteBuffer(l_Size, SizeOf(l_Size));
     // - записывем реальный размер (вместо placeholer)
    end;//l_NeedPack

    l_Element.rValue := l_SizePos;
    // - отсюда потом будем вычитывать Size + Value

    f_Stream.Seek(l_Pos, soBeginning);
    // - возвращаем позицию элемента
   end;//l_Element.rType = m3_etMultiply
  end;//l_NeedMultiply
 end;//l_Count = 1

 f_Stream.WriteBuffer(l_Element, SizeOf(l_Element));
//#UC END# *69AC818E005F_69AC2E42033D_impl*
end;//Tm3AttrIndexWriter.WriteBodyElement

procedure Tm3AttrIndexWriter.Cleanup;
 {* Функция очистки полей объекта. }
//#UC START# *479731C50290_69AC2E42033D_var*
//#UC END# *479731C50290_69AC2E42033D_var*
begin
//#UC START# *479731C50290_69AC2E42033D_impl*
 //Self.SaveHeader;
 FreeAndNil(f_Stream);
 inherited;
//#UC END# *479731C50290_69AC2E42033D_impl*
end;//Tm3AttrIndexWriter.Cleanup

procedure Tm3AttrIndexWriter.BeforeRelease;
//#UC START# *49BFC98902FF_69AC2E42033D_var*
//#UC END# *49BFC98902FF_69AC2E42033D_var*
begin
//#UC START# *49BFC98902FF_69AC2E42033D_impl*
 Self.SaveHeader;
 inherited;
//#UC END# *49BFC98902FF_69AC2E42033D_impl*
end;//Tm3AttrIndexWriter.BeforeRelease

//#UC START# *69AC2E42033Dimpl*
procedure Tm3AttrIndexWriter.ifWriteEOL;
var
 l_Pos : Int64;
 l_C : AnsiChar;
begin
 l_Pos := f_Stream.Position;
 f_Stream.Seek(-1, soCurrent);
 f_Stream.ReadBuffer(l_C, SizeOf(l_C));
 f_Stream.Seek(l_Pos, soBeginning);
 if (l_C <> #10) then
  Self.WriteEOL;
end;//Tm3AttrIndexWriter.ifWriteEOL

procedure Tm3AttrIndexWriter.WriteStart(const aStr: Ansistring);
var
 l_C : AnsiChar;
 l_Pos : Int64;
begin
 Self.ifWriteEOL;
 l_C := '{';
 f_Stream.WriteBuffer(l_C, SizeOf(l_C));
 f_Stream.WriteBuffer(aStr[1], Length(aStr));
 l_C := '}';
 f_Stream.WriteBuffer(l_C, SizeOf(l_C));
 Self.WriteEOL;
 l_Pos := f_Stream.Position;
 if (f_Header.rStreamEnd < l_Pos) then
  f_Header.rStreamEnd := l_Pos;
end;//Tm3AttrIndexWriter.WriteStart

procedure Tm3AttrIndexWriter.WriteEnd(const aStr: Ansistring);
var
 l_C : AnsiChar;
 l_Pos : Int64;
begin
 Self.ifWriteEOL;
 l_C := '{';
 f_Stream.WriteBuffer(l_C, SizeOf(l_C));
 l_C := '/';
 f_Stream.WriteBuffer(l_C, SizeOf(l_C));
 f_Stream.WriteBuffer(aStr[1], Length(aStr));
 l_C := '}';
 f_Stream.WriteBuffer(l_C, SizeOf(l_C));
 Self.WriteEOL;
 l_Pos := f_Stream.Position;
 if (f_Header.rStreamEnd < l_Pos) then
  f_Header.rStreamEnd := l_Pos;
end;//Tm3AttrIndexWriter.WriteEnd
//#UC END# *69AC2E42033Dimpl*

{$If NOT Defined(NoScripts)}
class function TIm3AttrIndexWriterKeywordsPackResNameGetter.ResName: AnsiString;
begin
 Result := 'Im3AttrIndexWriterKeywordsPack';
end;//TIm3AttrIndexWriterKeywordsPackResNameGetter.ResName

{$R Im3AttrIndexWriterKeywordsPack.res}
{$IfEnd} // NOT Defined(NoScripts)

{$If NOT Defined(NoScripts)}
constructor TBoxFor_Tm3AttrIndexWriterSubStreamInfo.Create(const aBoxed: Tm3AttrIndexWriterSubStreamInfo);
begin
 inherited Create;
 f_Boxed := aBoxed;
end;//TBoxFor_Tm3AttrIndexWriterSubStreamInfo.Create

class function TBoxFor_Tm3AttrIndexWriterSubStreamInfo.Make(const aBoxed: Tm3AttrIndexWriterSubStreamInfo): IBoxFor_Tm3AttrIndexWriterSubStreamInfo;
var
 l_Inst : TBoxFor_Tm3AttrIndexWriterSubStreamInfo;
begin
 l_Inst := Create(aBoxed);
 try
  Result := l_Inst;
 finally
  l_Inst.Free;
 end;//try..finally
end;//TBoxFor_Tm3AttrIndexWriterSubStreamInfo.Make

function TBoxFor_Tm3AttrIndexWriterSubStreamInfo.Get_Boxed: Tm3AttrIndexWriterSubStreamInfo;
begin
 Result := f_Boxed;
end;//TBoxFor_Tm3AttrIndexWriterSubStreamInfo.Get_Boxed

function TBoxFor_Tm3AttrIndexWriterSubStreamInfo.Get_pBoxed: Tm3AttrIndexWriterSubStreamInfoPtr;
begin
 Result := @f_Boxed;
end;//TBoxFor_Tm3AttrIndexWriterSubStreamInfo.Get_pBoxed

function TBoxFor_Tm3AttrIndexWriterSubStreamInfo.GetDataPtr: Pointer;
begin
 Result := @f_Boxed;
end;//TBoxFor_Tm3AttrIndexWriterSubStreamInfo.GetDataPtr

function TBoxFor_Tm3AttrIndexWriterSubStreamInfo.GetDataSize: Integer;
begin
 Result := SizeOf(f_Boxed);
end;//TBoxFor_Tm3AttrIndexWriterSubStreamInfo.GetDataSize

function TBoxFor_Tm3AttrIndexWriterSubStreamInfo.GetBoxTypeInfo: PTypeInfo;
begin
 Result := TypeInfo(IBoxFor_Tm3AttrIndexWriterSubStreamInfo);
end;//TBoxFor_Tm3AttrIndexWriterSubStreamInfo.GetBoxTypeInfo

function TBoxFor_Tm3AttrIndexWriterSubStreamInfo.GetAsPrintable(const aCtx: TtfwContextStub): Il3CString;
var
 l_Value: AnsiString;
begin
 l_Value := '(';
 l_Value := l_Value + ' )';
 Result := TtfwCStringFactory.C(l_Value);
end;//TBoxFor_Tm3AttrIndexWriterSubStreamInfo.GetAsPrintable

procedure TBoxFor_Tm3AttrIndexWriterSubStreamInfo.ClearFields;
begin
 Finalize(f_Boxed);
 inherited;
end;//TBoxFor_Tm3AttrIndexWriterSubStreamInfo.ClearFields

//#UC START# *69AFF780026ATBoximpl*
//#UC END# *69AFF780026ATBoximpl*
{$IfEnd} // NOT Defined(NoScripts)

{$If NOT Defined(NoScripts)}
constructor TBoxFor_Tm3AttrIndexWriterBodyElement.Create(const aBoxed: Tm3AttrIndexWriterBodyElement);
begin
 inherited Create;
 f_Boxed := aBoxed;
end;//TBoxFor_Tm3AttrIndexWriterBodyElement.Create

class function TBoxFor_Tm3AttrIndexWriterBodyElement.Make(const aBoxed: Tm3AttrIndexWriterBodyElement): IBoxFor_Tm3AttrIndexWriterBodyElement;
var
 l_Inst : TBoxFor_Tm3AttrIndexWriterBodyElement;
begin
 l_Inst := Create(aBoxed);
 try
  Result := l_Inst;
 finally
  l_Inst.Free;
 end;//try..finally
end;//TBoxFor_Tm3AttrIndexWriterBodyElement.Make

function TBoxFor_Tm3AttrIndexWriterBodyElement.Get_Boxed: Tm3AttrIndexWriterBodyElement;
begin
 Result := f_Boxed;
end;//TBoxFor_Tm3AttrIndexWriterBodyElement.Get_Boxed

function TBoxFor_Tm3AttrIndexWriterBodyElement.Get_pBoxed: Tm3AttrIndexWriterBodyElementPtr;
begin
 Result := @f_Boxed;
end;//TBoxFor_Tm3AttrIndexWriterBodyElement.Get_pBoxed

function TBoxFor_Tm3AttrIndexWriterBodyElement.GetDataPtr: Pointer;
begin
 Result := @f_Boxed;
end;//TBoxFor_Tm3AttrIndexWriterBodyElement.GetDataPtr

function TBoxFor_Tm3AttrIndexWriterBodyElement.GetDataSize: Integer;
begin
 Result := SizeOf(f_Boxed);
end;//TBoxFor_Tm3AttrIndexWriterBodyElement.GetDataSize

function TBoxFor_Tm3AttrIndexWriterBodyElement.GetBoxTypeInfo: PTypeInfo;
begin
 Result := TypeInfo(IBoxFor_Tm3AttrIndexWriterBodyElement);
end;//TBoxFor_Tm3AttrIndexWriterBodyElement.GetBoxTypeInfo

function TBoxFor_Tm3AttrIndexWriterBodyElement.GetAsPrintable(const aCtx: TtfwContextStub): Il3CString;
var
 l_Value: AnsiString;
begin
 l_Value := '(';
 l_Value := l_Value + ' )';
 Result := TtfwCStringFactory.C(l_Value);
end;//TBoxFor_Tm3AttrIndexWriterBodyElement.GetAsPrintable

procedure TBoxFor_Tm3AttrIndexWriterBodyElement.ClearFields;
begin
 Finalize(f_Boxed);
 inherited;
end;//TBoxFor_Tm3AttrIndexWriterBodyElement.ClearFields

//#UC START# *69AC79CD0094TBoximpl*
//#UC END# *69AC79CD0094TBoximpl*
{$IfEnd} // NOT Defined(NoScripts)

{$If NOT Defined(NoScripts)}
constructor TBoxFor_Tm3AttrIndexWriterHeader.Create(const aBoxed: Tm3AttrIndexWriterHeader);
begin
 inherited Create;
 f_Boxed := aBoxed;
end;//TBoxFor_Tm3AttrIndexWriterHeader.Create

class function TBoxFor_Tm3AttrIndexWriterHeader.Make(const aBoxed: Tm3AttrIndexWriterHeader): IBoxFor_Tm3AttrIndexWriterHeader;
var
 l_Inst : TBoxFor_Tm3AttrIndexWriterHeader;
begin
 l_Inst := Create(aBoxed);
 try
  Result := l_Inst;
 finally
  l_Inst.Free;
 end;//try..finally
end;//TBoxFor_Tm3AttrIndexWriterHeader.Make

function TBoxFor_Tm3AttrIndexWriterHeader.Get_Boxed: Tm3AttrIndexWriterHeader;
begin
 Result := f_Boxed;
end;//TBoxFor_Tm3AttrIndexWriterHeader.Get_Boxed

function TBoxFor_Tm3AttrIndexWriterHeader.Get_pBoxed: Tm3AttrIndexWriterHeaderPtr;
begin
 Result := @f_Boxed;
end;//TBoxFor_Tm3AttrIndexWriterHeader.Get_pBoxed

function TBoxFor_Tm3AttrIndexWriterHeader.GetDataPtr: Pointer;
begin
 Result := @f_Boxed;
end;//TBoxFor_Tm3AttrIndexWriterHeader.GetDataPtr

function TBoxFor_Tm3AttrIndexWriterHeader.GetDataSize: Integer;
begin
 Result := SizeOf(f_Boxed);
end;//TBoxFor_Tm3AttrIndexWriterHeader.GetDataSize

function TBoxFor_Tm3AttrIndexWriterHeader.GetBoxTypeInfo: PTypeInfo;
begin
 Result := TypeInfo(IBoxFor_Tm3AttrIndexWriterHeader);
end;//TBoxFor_Tm3AttrIndexWriterHeader.GetBoxTypeInfo

function TBoxFor_Tm3AttrIndexWriterHeader.GetAsPrintable(const aCtx: TtfwContextStub): Il3CString;
var
 l_Value: AnsiString;
begin
 l_Value := '(';
 l_Value := l_Value + ' )';
 Result := TtfwCStringFactory.C(l_Value);
end;//TBoxFor_Tm3AttrIndexWriterHeader.GetAsPrintable

procedure TBoxFor_Tm3AttrIndexWriterHeader.ClearFields;
begin
 Finalize(f_Boxed);
 inherited;
end;//TBoxFor_Tm3AttrIndexWriterHeader.ClearFields

//#UC START# *69AC312A0001TBoximpl*
//#UC END# *69AC312A0001TBoximpl*
{$IfEnd} // NOT Defined(NoScripts)

initialization
{$If NOT Defined(NoScripts)}
 TtfwTypeRegistrator.RegisterType(TypeInfo(Im3AttrIndexWriter));
{$IfEnd} // NOT Defined(NoScripts)
{$If NOT Defined(NoScripts)}
 TkwIm3AttrIndexWriterWriteVersions.RegisterInEngine(TtfwRegisterContext_E
  .SetSelfTypeInfo(Im3AttrIndexWriterKeywordsPack_Im3AttrIndexWriter_SelfTypeInfo)
  .SetParamsTypesFunc(TkwIm3AttrIndexWriterWriteVersions_ParamsTypes)
  .SetDoItProc(TkwIm3AttrIndexWriterWriteVersions_DoIt)
  .SetMethodName('WriteVersions'), ['m3AttrIndexWriter:WriteVersions', '.Im3AttrIndexWriter.WriteVersions', 'pop:m3AttrIndexWriter:WriteVersions']);
{$IfEnd} // NOT Defined(NoScripts)
{$If NOT Defined(NoScripts)}
 TkwIm3AttrIndexWriterWriteRange.RegisterInEngine(TtfwRegisterContext_E
  .SetSelfTypeInfo(Im3AttrIndexWriterKeywordsPack_Im3AttrIndexWriter_SelfTypeInfo)
  .SetParamsTypesFunc(TkwIm3AttrIndexWriterWriteRange_ParamsTypes)
  .SetDoItProc(TkwIm3AttrIndexWriterWriteRange_DoIt)
  .SetMethodName('WriteRange'), ['m3AttrIndexWriter:WriteRange', '.Im3AttrIndexWriter.WriteRange', 'pop:m3AttrIndexWriter:WriteRange']);
{$IfEnd} // NOT Defined(NoScripts)
{$If NOT Defined(NoScripts)}
 TkwIm3AttrIndexWriterWriteOperation.RegisterInEngine(TtfwRegisterContext_E
  .SetSelfTypeInfo(Im3AttrIndexWriterKeywordsPack_Im3AttrIndexWriter_SelfTypeInfo)
  .SetParamsTypesFunc(TkwIm3AttrIndexWriterWriteOperation_ParamsTypes)
  .SetDoItProc(TkwIm3AttrIndexWriterWriteOperation_DoIt)
  .SetMethodName('WriteOperation'), ['m3AttrIndexWriter:WriteOperation', '.Im3AttrIndexWriter.WriteOperation', 'pop:m3AttrIndexWriter:WriteOperation']);
{$IfEnd} // NOT Defined(NoScripts)
{$If NOT Defined(NoScripts)}
 TkwIm3AttrIndexWriterStartBody.RegisterInEngine(TtfwRegisterContext_E
  .SetSelfTypeInfo(Im3AttrIndexWriterKeywordsPack_Im3AttrIndexWriter_SelfTypeInfo)
  .SetParamsTypesFunc(TkwIm3AttrIndexWriterStartBody_ParamsTypes)
  .SetDoItProc(TkwIm3AttrIndexWriterStartBody_DoIt)
  .SetMethodName('StartBody'), ['m3AttrIndexWriter:StartBody', '.Im3AttrIndexWriter.StartBody', 'pop:m3AttrIndexWriter:StartBody']);
{$IfEnd} // NOT Defined(NoScripts)
{$If NOT Defined(NoScripts)}
 TkwIm3AttrIndexWriterFinishBody.RegisterInEngine(TtfwRegisterContext_E
  .SetSelfTypeInfo(Im3AttrIndexWriterKeywordsPack_Im3AttrIndexWriter_SelfTypeInfo)
  .SetDoItProc(TkwIm3AttrIndexWriterFinishBody_DoIt)
  .SetMethodName('FinishBody'), ['m3AttrIndexWriter:FinishBody', '.Im3AttrIndexWriter.FinishBody', 'pop:m3AttrIndexWriter:FinishBody']);
{$IfEnd} // NOT Defined(NoScripts)
{$If NOT Defined(NoScripts)}
 TkwIm3AttrIndexWriterWriteBodyElement.RegisterInEngine(TtfwRegisterContext_E
  .SetSelfTypeInfo(Im3AttrIndexWriterKeywordsPack_Im3AttrIndexWriter_SelfTypeInfo)
  .SetParamsTypesFunc(TkwIm3AttrIndexWriterWriteBodyElement_ParamsTypes)
  .SetDoItProc(TkwIm3AttrIndexWriterWriteBodyElement_DoIt)
  .SetMethodName('WriteBodyElement'), ['m3AttrIndexWriter:WriteBodyElement', '.Im3AttrIndexWriter.WriteBodyElement', 'pop:m3AttrIndexWriter:WriteBodyElement']);
{$IfEnd} // NOT Defined(NoScripts)
{$If NOT Defined(NoScripts)}
 TIm3AttrIndexWriterKeywordsPackResNameGetter.Register;
{$IfEnd} // NOT Defined(NoScripts)
{$If NOT Defined(NoScripts)}
 TtfwTypeRegistrator.RegisterType(TtfwValueTypes.MakeTypedef('Im3IndexedVersions', TypeInfo(Im3IndexedVersions)));
{$IfEnd} // NOT Defined(NoScripts)
{$If NOT Defined(NoScripts)}
 TtfwTypeRegistrator.RegisterType(TtfwValueTypes.MakeBox('Tl3Range', Tl3Range_TypeInfo));
{$IfEnd} // NOT Defined(NoScripts)
{$If NOT Defined(NoScripts)}
 TtfwTypeRegistrator.RegisterType(TypeInfo(Tm3GroupOperation));
{$IfEnd} // NOT Defined(NoScripts)
{$If NOT Defined(NoScripts)}
 TtfwTypeRegistrator.RegisterType(TtfwTypeInfo.MakeInteger
 , 'Целое число');
{$IfEnd} // NOT Defined(NoScripts)
{$If NOT Defined(NoScripts)}
 TtfwClassRef_Proxy.TtfwClassRef.Register(TypeInfo(Tm3PlainAttrIndexDumperElementEnumerator));
{$IfEnd} // NOT Defined(NoScripts)
{$If NOT Defined(NoScripts)}
 TtfwClassRef_Proxy.TtfwClassRef.Register(TypeInfo(Tm3PlainAttrIndexDumperElement));
{$IfEnd} // NOT Defined(NoScripts)
{$If NOT Defined(NoScripts)}
 TtfwClassRef_Proxy.TtfwClassRef.Register(TypeInfo(Tm3PlainAttrIndexDumper)
 , 'Читатель индекса атрибутов в "упрощённом виде".'
  + #13#10 + '{RequestLink:901972048}');
{$IfEnd} // NOT Defined(NoScripts)
{$If NOT Defined(NoScripts)}
 TtfwClassRef_Proxy.TtfwClassRef.Register(TypeInfo(Tm3AttrIndexWriter)
 , 'Писатель индекса атрибутов в "упрощённом виде".'
  + #13#10 + '{RequestLink:901972048}');
{$IfEnd} // NOT Defined(NoScripts)


//#UC START# *69AC2E42033DforDiagramm*
(*
[*
+-----------------------------------------------------------------------+
|              m3AttrIndexWriter - СТРУКТУРА ИНДЕКСА АТРИБУТОВ          |
+-----------------------------------------------------------------------+

1. ФОРМАТ ФАЙЛА ИНДЕКСА
+-----------------------------------------------------------------------+
|                                                                       |
|  +-----------------------------------------------------------------+  |
|  | [GUID] {2020CBAD-78CC-494B-84B0-2EF18ADEA65A}                  |  |
|  | [HeaderPos] Int64                                              |  |
|  |                                                                 |  |
|  | +-------------------------------------------------------------+ |  |
|  | | {header}                                                    | |  |
|  | | +---------------------------------------------------------+ | |  |
|  | | | Tm3AttrIndexWriterHeader (packed record)                | | |  |
|  | | | +-----------------------------------------------------+ | | |  |
|  | | | | rVersion : Integer                                  | | | |  |
|  | | | | rTimeStamp : Int64                                  | | | |  |
|  | | | | rRange : Tm3IDRange                                 | | | |  |
|  | | | | rOperation : Tm3GroupOperation                      | | | |  |
|  | | | | rModified : Tm3AttrIndexWriterSubStreamInfo         | | | |  |
|  | | | | rVersions : Tm3AttrIndexWriterSubStreamInfo         | | | |  |
|  | | | | rBody : Tm3AttrIndexWriterSubStreamInfo             | | | |  |
|  | | | | rElementsCount : Integer                            | | | |  |
|  | | | | rMinKeyID : Integer                                 | | | |  |
|  | | | | rMaxKeyID : Integer                                 | | | |  |
|  | | | | rNextPartPos : Int64                                | | | |  |
|  | | | +-----------------------------------------------------+ | | |  |
|  | | +---------------------------------------------------------+ | |  |
|  | | {/header}                                                   | |  |
|  | +-------------------------------------------------------------+ |  |
|  |                                                                 |  |
|  | +-------------------------------------------------------------+ |  |
|  | | {modified}                                                  | |  |
|  | | +---------------------------------------------------------+ | |  |
|  | | | Il3RangeEnumerable (модифицированные документы)         | | |  |
|  | | +---------------------------------------------------------+ | |  |
|  | | {/modified}                                                 | |  |
|  | +-------------------------------------------------------------+ |  |
|  |                                                                 |  |
|  | +-------------------------------------------------------------+ |  |
|  | | {versions}                                                  | |  |
|  | | +---------------------------------------------------------+ | |  |
|  | | | Im3IndexedVersions (версии)                             | | |  |
|  | | +---------------------------------------------------------+ | |  |
|  | | {/versions}                                                 | |  |
|  | +-------------------------------------------------------------+ |  |
|  |                                                                 |  |
|  | +-------------------------------------------------------------+ |  |
|  | | {body}                                                      | |  |
|  | | +---------------------------------------------------------+ | |  |
|  | | | ffi (маркер фрейма)                                     | | |  |
|  | | | Tm3BodyFrameInfo                                        | | |  |
|  | | | seq (маркер sequential)                                 | | |  |
|  | | | f_Sequential : Boolean                                  | | |  |
|  | | |                                                         | | |  |
|  | | | [элемент 0] Tm3AttrIndexWriterBodyElement               | | |  |
|  | | | [элемент 1] Tm3AttrIndexWriterBodyElement               | | |  |
|  | | | ...                                                     | | |  |
|  | | | [элемент N-1] Tm3AttrIndexWriterBodyElement             | | |  |
|  | | +---------------------------------------------------------+ | |  |
|  | | {/body}                                                    | |  |
|  | +-------------------------------------------------------------+ |  |
|  |                                                                 |  |
|  | +-------------------------------------------------------------+ |  |
|  | | [следующая часть] если rNextPartPos > 0                    | |  |
|  | +-------------------------------------------------------------+ |  |
|  |                                                                 |  |
|  +-----------------------------------------------------------------+  |
|                                                                       |
+-----------------------------------------------------------------------+

2. СТРУКТУРА ЭЛЕМЕНТА (Tm3AttrIndexWriterBodyElement)
+-----------------------------------------------------------------------+
|                                                                       |
|  +-----------------------------------------------------------------+  |
|  | rType : Tm3ElementType                                         |  |
|  | +-------------------------------------------------------------+ |  |
|  | | m3_etNone    - пусто                                       | |  |
|  | | m3_etSingle  - одно значение                               | |  |
|  | | m3_etPair    - два значения (T64to32)                      | |  |
|  | | m3_et4       - четыре SmallInt                             | |  |
|  | | m3_et8       - восемь Byte                                 | |  |
|  | | m3_etRange   - диапазон (Tl3Range)                         | |  |
|  | | m3_etMultiply- список значений (упакованный)               | |  |
|  | | m3_etLZO     - сжатый LZO                                  | |  |
|  | | m3_etZLib    - сжатый ZLib                                 | |  |
|  | +-------------------------------------------------------------+ |  |
|  | rKey : Int64 (ID ключа)                                        |  |
|  | rValue : Int64 (значение или смещение)                         |  |
|  +-----------------------------------------------------------------+  |
|                                                                       |
+-----------------------------------------------------------------------+

3. КЛАССЫ
+-----------------------------------------------------------------------+
|                                                                       |
|  +-----------------------------------------------------------------+  |
|  | Tm3AttrIndexWriter (писатель)                                  |  |
|  | +-------------------------------------------------------------+ |  |
|  | | - f_Stream : Tl3Stream                                     | |  |
|  | | - f_Header : Tm3AttrIndexWriterHeader                      | |  |
|  | | - f_IsDirect : Boolean                                     | |  |
|  | | - f_Sequential : Boolean                                   | |  |
|  | | - f_FrameInfo : Tm3BodyFrameInfo                           | |  |
|  | +-------------------------------------------------------------+ |  |
|  | | + WriteVersions(aVersions)                                 | |  |
|  | | + WriteModified(aModified, aTimeStamp)                     | |  |
|  | | + WriteRange(aRange)                                       | |  |
|  | | + WriteOperation(anOperation)                              | |  |
|  | | + StartBody(aCount)                                        | |  |
|  | | + FinishBody                                               | |  |
|  | | + WriteBodyElement(aKey, aValue)                           | |  |
|  | +-------------------------------------------------------------+ |  |
|  +-----------------------------------------------------------------+  |
|                                                                       |
|  +-----------------------------------------------------------------+  |
|  | Tm3PlainAttrIndexDumper (читатель)                             |  |
|  | +-------------------------------------------------------------+ |  |
|  | | - f_Header : Tm3AttrIndexWriterHeader                      | |  |
|  | | - f_FileName : TFileName                                   | |  |
|  | | - f_Stream : Tl3Stream                                     | |  |
|  | | - f_SearchMode : Tm3SearchMode                             | |  |
|  | | - f_Sequential : Boolean                                   | |  |
|  | +-------------------------------------------------------------+ |  |
|  | | + ModifiedDocuments : Il3RangeEnumerable                   | |  |
|  | | + IndexedVersions : Im3IndexedVersions                     | |  |
|  | | + Range : Tm3IDRange                                       | |  |
|  | | + TimeStamp : TDateTime                                    | |  |
|  | | + Count : Integer                                          | |  |
|  | | + ValuesByKey(aKey) : Il3RangeEnumerable                   | |  |
|  | | + GetEnumerator : Im3AttrIndexElementEnumerator            | |  |
|  | +-------------------------------------------------------------+ |  |
|  +-----------------------------------------------------------------+  |
|                                                                       |
+-----------------------------------------------------------------------+

4. ЛОГИКА ПОИСКА ValuesByKey
+-----------------------------------------------------------------------+
|                                                                       |
|  +-----------------------------------------------------------------+  |
|  | if (aKey < MinKeyID) or (aKey > MaxKeyID) then                 |  |
|  |     Result := nil                                               |  |
|  |     Exit                                                        |  |
|  |                                                                 |  |
|  | if SearchMode = m3_smSeq then                                   |  |
|  |     // последовательный перебор                                 |  |
|  |     while Enumerator.MoveNext do                                |  |
|  |         if ID = aKey then                                       |  |
|  |             Result := Values                                    |  |
|  |             Exit                                                |  |
|  |                                                                 |  |
|  | if Sequential then                                              |  |
|  |     // прямой доступ по индексу                                 |  |
|  |     Pos := (aKey - MinKeyID) * SizeOf(Element)                  |  |
|  |     ReadElement                                                 |  |
|  |     ElementToResult                                             |  |
|  |                                                                 |  |
|  | else                                                            |  |
|  |     // бинарный поиск                                           |  |
|  |     L := 0; H := Count - 1                                      |  |
|  |     while L <= H do                                             |  |
|  |         i := (L + H) shr 1                                      |  |
|  |         ReadElement                                             |  |
|  |         if Element.Key < aKey then                              |  |
|  |             L := i + 1                                          |  |
|  |         else if Element.Key > aKey then                         |  |
|  |             H := i - 1                                          |  |
|  |         else                                                    |  |
|  |             ElementToResult                                     |  |
|  |             Exit                                                |  |
|  |                                                                 |  |
|  +-----------------------------------------------------------------+  |
|                                                                       |
+-----------------------------------------------------------------------+

5. ФОРМАТЫ СЕРИАЛИЗАЦИИ
+-----------------------------------------------------------------------+
|                                                                       |
|  +-----------------------------------------------------------------+  |
|  | Одиночное значение (m3_etSingle)                               |  |
|  |   rValue = ID                                                   |  |
|  +-----------------------------------------------------------------+  |
|  |                                                                 |  |
|  | Диапазон (m3_etRange)                                           |  |
|  |   rValue = (rLow shl 32) or rHigh (Tm3IDRange)                 |  |
|  +-----------------------------------------------------------------+  |
|  |                                                                 |  |
|  | Список значений (m3_etMultiply / m3_etZLib / m3_etLZO)         |  |
|  |   rValue = смещение на Size + Data                              |  |
|  |   [Size] Int64                                                  |  |
|  |   [Data] Il3RangeEnumerable                                     |  |
|  +-----------------------------------------------------------------+  |
|                                                                       |
+-----------------------------------------------------------------------+

6. КОНСТАНТЫ
+-----------------------------------------------------------------------+
|                                                                       |
|  c_m3AttrIndexWriterGUID = '{2020CBAD-78CC-494B-84B0-2EF18ADEA65A}'  |
|  cSequentialVersion = 2                                               |
|  cOurVersion = 2                                                      |
|  cSignature = 1400951                                                 |
|                                                                       |
+-----------------------------------------------------------------------+
*]
*)
//#UC END# *69AC2E42033DforDiagramm*

end.

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

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