1. with Tiles.Matrices;                    use Tiles.Matrices; 
  2.  
  3. private with Ada.Containers; 
  4. private with Ada.Containers.Hashed_Maps; 
  5. private with Ada.Containers.Vectors; 
  6. private with Ada.Unchecked_Conversion; 
  7.  
  8. private package Tiles.Indices is 
  9.  
  10.     -- A Tile_Index indexes and organizes all the Tiles in a Tile_Library. It is 
  11.     -- stored in a tile library as a separate index file, alongside all the 
  12.     -- included bitmaps. In addition to indexing tiles by id, it contains 
  13.     -- tile matrices for repeated tile patterns and large multi-tile objects. 
  14.     type Tile_Index is private; 
  15.     type A_Tile_Index is access all Tile_Index; 
  16.     pragma No_Strict_Aliasing( A_Tile_Index ); 
  17.  
  18.     -- Creates a new empty tile index. 
  19.     function Create_Tile_Index return A_Tile_Index; 
  20.     pragma Postcondition( Create_Tile_Index'Result /= null ); 
  21.  
  22.     -- Loads a tile index from an archive. Null will be returned if an error 
  23.     -- occurs. 
  24.     function Load_Index( archive  : not null A_Archive; 
  25.                          filename : String ) return A_Tile_Index; 
  26.     pragma Postcondition( filename'Length > 0 ); 
  27.  
  28.     -- Adds a new tile matrix to the index. 'matrix' will be consumed. 
  29.     procedure Add_Matrix( index : not null A_Tile_Index; matrix : in out A_Tile_Matrix ); 
  30.     pragma Precondition( matrix /= null ); 
  31.     pragma Postcondition( matrix = null ); 
  32.  
  33.     -- Adds a new tile to the index. 'tile' is consumed. If 'tile' is passed as 
  34.     -- null, a null tile is added to the tile list as a place holder. The 
  35.     -- exception DUPLICATE_TILE will be raised if a tile with the same id 
  36.     -- already exists in the index. 
  37.     procedure Add_Tile( index : not null A_Tile_Index; tile : in out A_Tile ); 
  38.     pragma Postcondition( tile = null ); 
  39.  
  40.     -- Deletes a tile index. 
  41.     procedure Delete( index : in out A_Tile_Index ); 
  42.     pragma Postcondition( index = null ); 
  43.  
  44.     -- Returns a reference to a matrix in the index by ordinal number, base 1. 
  45.     -- If there is no matrix for 'num' then null will be returned. 
  46.     function Get_Matrix( index : not null A_Tile_Index; num : Natural ) return A_Tile_Matrix; 
  47.  
  48.     -- Returns the number of matrices in the index. 
  49.     function Get_Matrix_Count( index : not null A_Tile_Index ) return Natural; 
  50.  
  51.     -- Returns the load completion for the index in the range of 0..100 
  52.     function Get_Progress( index : not null A_Tile_Index ) return Natural; 
  53.     pragma Postcondition( Get_Progress'Result <= 100 ); 
  54.  
  55.     -- Returns the slot number of a tile by id. The slot is determined by the 
  56.     -- order of the tiles in the index. The first tile is at slot 1. Zero will 
  57.     -- be returned if 'id' is not found in the index. 
  58.     function Get_Slot( index : not null A_Tile_Index; id : Natural ) return Natural; 
  59.  
  60.     -- Returns a tile reference by tile id, base 1. Do not modify the tile; it 
  61.     -- belongs to the index. Null will be returned if the tile is not found. 
  62.     function Get_Tile( index : not null A_Tile_Index; id : Natural ) return A_Tile; 
  63.  
  64.     -- Returns a tile reference by name. Do not modify the tile, it belongs to 
  65.     -- the index. Null will be returned if the tile is not found. 
  66.     function Get_Tile( index : not null A_Tile_Index; name : String ) return A_Tile; 
  67.     pragma Precondition( name'Length > 0 ); 
  68.  
  69.     -- Returns a tile reference by slot number, base 1. Do not modify the tile; 
  70.     -- it belongs to the index. Null will be returned if the tile is not found. 
  71.     function Get_Tile_At_Slot( index : not null A_Tile_Index; 
  72.                                slot  : Natural ) return A_Tile; 
  73.  
  74.     -- Returns the number of tiles in the index. 
  75.     function Get_Tile_Count( index : not null A_Tile_Index ) return Natural; 
  76.  
  77.     -- Iterates across the tiles in the index by order of listing, from first 
  78.     -- to last. 
  79.     procedure Iterate_Tiles( index   : not null A_Tile_Index; 
  80.                              examine : not null access procedure( tile : A_Tile ) ); 
  81.  
  82.     -- Indicates to the index that all tiles have been loaded. This will unblock 
  83.     -- any threads waiting for the index to be fully loaded. 
  84.     procedure Load_Complete( index : not null A_Tile_Index ); 
  85.  
  86.     -- Loads all the bitmaps for all the tiles in the index. 
  87.     procedure Load_Images( index   : not null A_Tile_Index; 
  88.                            archive : not null A_Archive ); 
  89.  
  90.     -- Prioritizes a tile to be loaded before non-priority tiles. 
  91.     procedure Prioritize_Tile( index : not null A_Tile_Index; tile : not null A_Tile ); 
  92.  
  93.     -- Writes the index to a file on disk, returning True on success. 
  94.     function Write_Index( index    : not null A_Tile_Index; 
  95.                           filename : String ) return Boolean; 
  96.     pragma Precondition( filename'Length > 0 ); 
  97.  
  98.     ---------------------------------------------------------------------------- 
  99.  
  100.     -- Returns the file extension for tile index tiles, without a leading dot. 
  101.     function Index_Extension return String; 
  102.     pragma Postcondition( Index_Extension'Result'Length > 0 ); 
  103.  
  104.     -- Returns a string that identifies the tile index file format. It is the 
  105.     -- first data found in the file. 
  106.     function Index_Identifier return String; 
  107.     pragma Postcondition( Index_Identifier'Result'Length > 0 ); 
  108.  
  109.     -- raised on attempt to add a tile with a duplicate id 
  110.     DUPLICATE_TILE : exception; 
  111.  
  112. private 
  113.  
  114.     use Ada.Containers; 
  115.  
  116.     -- Queue of tiles remaining to be loaded. Loading can be prioritized. 
  117.     protected type Tile_Queue is 
  118.  
  119.         -- Adds to the end of the list. when the library index is read, all 
  120.         -- tiles are added to the back of the queue. This is used to keep track 
  121.         -- of the total number of tiles that must be loaded. 
  122.         procedure Add_Back( tile : not null A_Tile ); 
  123.  
  124.         -- Returns a loaded percentage in the range of 0..100 
  125.         function Get_Progress return Natural; 
  126.         pragma Postcondition( Get_Progress'Result <= 100 ); 
  127.  
  128.         -- Prioritizes the loading of the tile by adding it to the front of the 
  129.         -- queue. It should already have been added to the back of the queue. 
  130.         procedure Prioritize( tile : not null A_Tile ); 
  131.  
  132.         -- Removes and returns first in the list. 
  133.         procedure Remove( tile : out A_Tile ); 
  134.  
  135.         -- Clears queue and stops accepting tiles. 
  136.         procedure Stop; 
  137.  
  138.     private 
  139.         queue   : Tile_Lists.List; 
  140.         total   : Natural := 0;         -- total number of unique tiles to load 
  141.         loaded  : Natural := 0;         -- number of tiles loaded so far 
  142.         stopped : Boolean := False; 
  143.     end Tile_Queue; 
  144.     type A_Tile_Queue is access all Tile_Queue; 
  145.  
  146.     -- Deletes the Tile_Queue. 
  147.     procedure Delete( queue : in out A_Tile_Queue ); 
  148.     pragma Postcondition( queue = null ); 
  149.  
  150.     ---------------------------------------------------------------------------- 
  151.  
  152.     function Hash is new Ada.Unchecked_Conversion( Integer, Hash_Type ); 
  153.  
  154.     package Integer_Vectors is new Ada.Containers.Vectors( Positive, Natural, "=" ); 
  155.     package Matrix_Vectors is new Ada.Containers.Vectors( Positive, A_Tile_Matrix, "=" ); 
  156.     package Tile_Maps is new Ada.Containers.Hashed_Maps( Integer, A_Tile, Hash, "=", "=" ); 
  157.  
  158.     type Tile_Index is 
  159.         record 
  160.             idmap    : Tile_Maps.Map;          -- mapping of id numbers to tiles 
  161.             list     : Integer_Vectors.Vector; -- ordered list of tile ids 
  162.             matlist  : Matrix_Vectors.Vector;  -- ordered list of tile matrices 
  163.             loadlist : A_Tile_Queue;           -- list of remaining tiles to load 
  164.         end record; 
  165.  
  166.     function A_Tile_Index_Input( stream : access Root_Stream_Type'Class ) return A_Tile_Index; 
  167.     for A_Tile_Index'Input use A_Tile_Index_Input; 
  168.  
  169.     procedure A_Tile_Index_Output( stream : access Root_Stream_Type'Class; index : A_Tile_Index ); 
  170.     for A_Tile_Index'Write use A_Tile_Index_Output; 
  171.     for A_Tile_Index'Output use A_Tile_Index_Output; 
  172.  
  173. end Tiles.Indices;