1. with Ada.Streams;                       use Ada.Streams; 
  2. with Objects;                           use Objects; 
  3. with Values;                            use Values; 
  4.  
  5. private with Ada.Containers.Indefinite_Ordered_Maps; 
  6. private with Ada.Strings.Less_Case_Insensitive; 
  7.  
  8. package Associations is 
  9.  
  10.     -- An Association is an ordered map of strings to Value objects. Names are 
  11.     -- case insensitive. Associations do not subclass the Value class to avoid 
  12.     -- the possibility of nesting. 
  13.     type Association is new Object with private; 
  14.     type A_Association is access all Association'Class; 
  15.  
  16.     -- Creates a new empty association. 
  17.     function Create_Association return A_Association; 
  18.     pragma Postcondition( Create_Association'Result /= null ); 
  19.  
  20.     -- Returns the named value in the association as a boolean. An exception is 
  21.     -- raised if the value is not found or if it can't be converted to a 
  22.     -- boolean. 
  23.     function As_Boolean( this : access Association; name : String ) return Boolean; 
  24.     pragma Precondition( name'Length > 0 ); 
  25.  
  26.     -- Returns the named value in the association as an integer. An exception is 
  27.     -- raised if the value is not found or if it can't be converted to an 
  28.     -- integer. 
  29.     function As_Integer( this : access Association; name : String ) return Integer; 
  30.     pragma Precondition( name'Length > 0 ); 
  31.  
  32.     -- Returns the named value in the association as a string. An exception is 
  33.     -- raised if the value is not found or if it can't be converted to a string. 
  34.     function As_String( this : access Association; name : String ) return String; 
  35.     pragma Precondition( name'Length > 0 ); 
  36.  
  37.     -- Returns True if 'name' is defined with a value in the association. 
  38.     function Is_Defined( this : access Association; name : String ) return Boolean; 
  39.  
  40.     -- Iterates through the name/value pairs in the association. The iteration 
  41.     -- will be in alphabetical order of names. 
  42.     procedure Iterate( this    : access Association; 
  43.                        examine : not null access procedure( name  : String; 
  44.                                                             value : A_Value ) ); 
  45.  
  46.     -- Returns the number of name/value pairs in the assocation. 
  47.     function Length( this : access Association ) return Natural; 
  48.  
  49.     -- Reads an Association from a stream. This should not be called directly. 
  50.     function Object_Input( stream : access Root_Stream_Type'Class ) return Association; 
  51.  
  52.     -- Removes the named value from the association. 
  53.     procedure Remove( this : access Association; name : String ); 
  54.     pragma Precondition( name'Length > 0 ); 
  55.  
  56.     -- Sets a boolean value in the association by name if it isn't defined. 
  57.     procedure Set_Default( this : access Association; name : String; val : Boolean ); 
  58.     pragma Precondition( name'Length > 0 ); 
  59.  
  60.     -- Sets an integer value in the association by name if it isn't defined. 
  61.     procedure Set_Default( this : access Association; name : String; val : Integer ); 
  62.     pragma Precondition( name'Length > 0 ); 
  63.  
  64.     -- Sets a string value in the association by name if it isn't defined. 
  65.     procedure Set_Default( this : access Association; name : String; val : String ); 
  66.     pragma Precondition( name'Length > 0 ); 
  67.  
  68.     -- Sets a value in the association by name if it isn't defined, consuming 
  69.     -- 'val'. 
  70.     procedure Set_Default( this : access Association; 
  71.                            name : String; 
  72.                            val  : in out A_Value ); 
  73.     pragma Precondition( name'Length > 0 ); 
  74.  
  75.     -- Sets a boolean value in the association by name. 
  76.     procedure Set_Value( this : access Association; name : String; val : Boolean ); 
  77.     pragma Precondition( name'Length > 0 ); 
  78.  
  79.     -- Sets an integer value in the association by name. 
  80.     procedure Set_Value( this : access Association; name : String; val : Integer ); 
  81.     pragma Precondition( name'Length > 0 ); 
  82.  
  83.     -- Sets a string value in the association by name. 
  84.     procedure Set_Value( this : access Association; name : String; val : String ); 
  85.     pragma Precondition( name'Length > 0 ); 
  86.  
  87.     -- Sets a value in the association by name, consuming 'val'. 
  88.     procedure Set_Value( this : access Association; 
  89.                          name : String; 
  90.                          val  : in out A_Value ); 
  91.     pragma Precondition( name'Length > 0 ); 
  92.     pragma Precondition( val /= null ); 
  93.     pragma Postcondition( val = null ); 
  94.  
  95.     -- Returns a deep copy of the assocation or null of 'src' is null. 
  96.     function Copy( src : A_Association ) return A_Association; 
  97.     pragma Postcondition( Copy'Result /= src or else src = null ); 
  98.  
  99.     -- Deletes the association. 
  100.     procedure Delete( this : in out A_Association ); 
  101.     pragma Postcondition( this = null ); 
  102.  
  103. private 
  104.  
  105.     package Value_Maps is new 
  106.         Ada.Containers.Indefinite_Ordered_Maps( String, A_Value, 
  107.                                                 Ada.Strings.Less_Case_Insensitive, 
  108.                                                 "=" ); 
  109.     use Value_Maps; 
  110.  
  111.     type Association is new Object with 
  112.         record 
  113.             pairs : Value_Maps.Map; 
  114.         end record; 
  115.  
  116.     procedure Adjust( this : access Association ); 
  117.  
  118.     procedure Delete( this : in out Association ); 
  119.  
  120.     -- Returns a string representation of the Association for debugging purposes. 
  121.     -- The string is of the form: {[name:'value'[,name:'value']*]} where the []* 
  122.     -- characters denote multiple possible repetitions of name/value pairs. 
  123.     function To_String( this : access Association ) return String; 
  124.  
  125.     -- Object_Input is in the public part of the package. 
  126.     for Association'Input use Object_Input; 
  127.  
  128.     procedure Object_Read( stream : access Root_Stream_Type'Class; 
  129.                            obj    : out Association ); 
  130.     for Association'Read use Object_Read; 
  131.  
  132.     procedure Object_Write( stream : access Root_Stream_Type'Class; 
  133.                             obj    : Association ); 
  134.     for Association'Write use Object_Write; 
  135.  
  136.     function A_Association_Input( stream : access Root_Stream_Type'Class ) return A_Association; 
  137.     for A_Association'Input use A_Association_Input; 
  138.  
  139.     procedure A_Association_Output( stream : access Root_Stream_Type'Class; 
  140.                                     obj    : A_Association ); 
  141.     for A_Association'Output use A_Association_Output; 
  142.  
  143.     procedure A_Association_Read( stream : access Root_Stream_Type'Class; 
  144.                                   obj    : out A_Association ); 
  145.     for A_Association'Read use A_Association_Read; 
  146.  
  147.     procedure A_Association_Write( stream : access Root_Stream_Type'Class; 
  148.                                    obj    : A_Association ); 
  149.     for A_Association'Write use A_Association_Write; 
  150.  
  151. end Associations;