1. with Allegro.Files;                     use Allegro.Files; 
  2. with Interfaces;                        use Interfaces; 
  3. with Streams.Buffers;                   use Streams.Buffers; 
  4. with System;                            use System; 
  5.  
  6. private with Ada.Strings.Unbounded; 
  7. private with Ada.Real_Time; 
  8. private with Streams; 
  9.  
  10. package Resources is 
  11.  
  12.     -- Protected state object useful for asynchronously loading resources. 
  13.     protected type Async_Operation is 
  14.  
  15.         -- Notifies the object that the operation is complete. This will free up 
  16.         -- all threads blocking on the Wait entry. 
  17.         procedure Complete; 
  18.  
  19.         -- Checks the state of the operation without waiting for completion. 
  20.         function Is_Complete return Boolean; 
  21.  
  22.         -- Blocks the caller until the operation is complete. 
  23.         entry Wait; 
  24.  
  25.     private 
  26.         c : Boolean := False; 
  27.     end Async_Operation; 
  28.     type A_Async_Operation is access all Async_Operation; 
  29.  
  30.     procedure Delete( op : in out A_Async_Operation ); 
  31.     pragma Postcondition( op = null ); 
  32.  
  33.     ---------------------------------------------------------------------------- 
  34.  
  35.     procedure Loading_Begins; 
  36.  
  37.     procedure Loading_Ends; 
  38.  
  39.     ---------------------------------------------------------------------------- 
  40.  
  41.     -- A Resource_File represents a resource file loaded in memory. The contents 
  42.     -- of the file can be accessed via various methods. Once a Resource_File is 
  43.     -- closed, its backing data should no longer be relied upon. If the file 
  44.     -- data is required after the Resource_File must be closed, a copy of the 
  45.     -- contents should be made. 
  46.     -- 
  47.     -- Resource files are cached to avoid the cost of searching and reading from 
  48.     -- disk each time file is needed but the details of the cache and how/when 
  49.     -- it is purged are private. 
  50.     type Resource_File is tagged limited private; 
  51.     type A_Resource_File is access all Resource_File'Class; 
  52.  
  53.     -- Returns the address of the resource file's data. The length of the data 
  54.     -- can be determined by calling Size. 
  55.     function Get_Address( this : access Resource_File ) return Address; 
  56.  
  57.     -- Returns the filename of the resource. 
  58.     function Get_Filename( this : access Resource_File ) return String; 
  59.  
  60.     -- Returns an identifying string comprised of the original filepath and 
  61.     -- group name used to find the resource. 
  62.     function Get_Id( this : access Resource_File ) return String; 
  63.  
  64.     -- Returns a packfile reference to the resource. Be sure to close the 
  65.     -- packfile before unloading the resource. 
  66.     function Get_Packfile( this : access Resource_File ) return A_Packfile; 
  67.  
  68.     -- Returns a new read-only stream backed by the resource contents. Be sure 
  69.     -- to close the stream before unloading the resource. 
  70.     procedure Get_Stream( this : access Resource_File; 
  71.                           strm : out A_Buffer_Stream ); 
  72.  
  73.     -- Returns the size of the file in bytes; 
  74.     function Size( this : access Resource_File ) return Unsigned_32; 
  75.  
  76.     ---------------------------------------------------------------------------- 
  77.  
  78.     -- Searches for and loads a resource file, returning a reference to it. The 
  79.     -- search order for resources files is as follows: 
  80.     -- 
  81.     -- 1. filepath  (If filepath is an absolute file path) 
  82.     -- 2. working_dir/filename 
  83.     -- 3. working_dir/group.zip/filename 
  84.     -- 4. media_dir/filename 
  85.     -- 5. media_dir/group.zip/filename 
  86.     -- 
  87.     -- (Where 'filename' is the filename taken from 'filepath'.) 
  88.     -- 
  89.     -- NULL will be returned if the file is not found or can't otherwise be 
  90.     -- accessed. Resource files are reference counted, so you must call 
  91.     -- Unload_Resource when finished with the Resource_File. 
  92.     function Load_Resource( filepath : String; group : String ) return A_Resource_File; 
  93.     pragma Precondition( filepath'Length > 0 ); 
  94.  
  95.     -- Unloads a resource file. Resource files are reference counted so be sure 
  96.     -- to call this when finished with a Resource_File. 
  97.     procedure Unload_Resource( resource : in out A_Resource_File ); 
  98.     pragma Postcondition( resource = null ); 
  99.  
  100.     -- Returns the location where a file can be written to overwrite an 
  101.     -- existing resource if possible or override an existing resource that is 
  102.     -- in an archive. 
  103.     -- 
  104.     -- The specified file will searched for with the same algorithm as 
  105.     -- Load_Resource. If the resource file is found and it's not in an archive, 
  106.     -- its absolute path will be returned. If the file was found in an archive 
  107.     -- or couldn't be found at all, then the returned path will point to a file 
  108.     -- of the same name in the executable directory. 
  109.     function Write_Path( filepath : String; group : String ) return String; 
  110.     pragma Precondition( filepath'Length > 0 ); 
  111.     pragma Postcondition( Write_Path'Result'Length > 0 ); 
  112.  
  113.     ---------------------------------------------------------------------------- 
  114.  
  115.     RESOURCE_ERROR, 
  116.     RESOURCE_FORMAT_ERROR : exception; 
  117.  
  118. private 
  119.  
  120.     use Ada.Real_Time; 
  121.     use Ada.Strings.Unbounded; 
  122.     use Streams; 
  123.  
  124.     type Resource_File is tagged limited 
  125.         record 
  126.             refs     : Natural := 1; 
  127.             lastUse  : Time := Clock; 
  128.             filepath : Unbounded_String; 
  129.             group    : Unbounded_String; 
  130.             data     : A_SEA; 
  131.         end record; 
  132.  
  133.     -- The 'data' array is consumed. 
  134.     procedure Create_Resource( this     : out A_Resource_File; 
  135.                                filepath : String; 
  136.                                group    : String; 
  137.                                data     : in out A_SEA ); 
  138.     pragma Precondition( filepath'Length > 0 ); 
  139.     pragma Precondition( data /= null ); 
  140.     pragma Postcondition( data = null ); 
  141.     pragma Postcondition( this /= null ); 
  142.  
  143.     procedure Reference( this : access Resource_File ); 
  144.  
  145.     procedure Unreference( this : access Resource_File ); 
  146.  
  147. end Resources;