----------------------------------------------------------------------------- -- Config - A simple package for parsing and modifying configuration files -- (also known as .ini, .inf, .cfg, ... files) -- -- Copyright (c) Rolf Ebert & Gautier de Montmollin 1996 .. 2019 -- -- Permission is hereby granted, free of charge, to any person obtaining a copy -- of this software and associated documentation files (the "Software"), to deal -- in the Software without restriction, including without limitation the rights -- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -- copies of the Software, and to permit persons to whom the Software is -- furnished to do so, subject to the following conditions: -- The above copyright notice and this permission notice shall be included in -- all copies or substantial portions of the Software. -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -- THE SOFTWARE. -- NB: this is the MIT License, as found 12-Sep-2007 on the site -- http://www.opensource.org/licenses/mit-license.php ----------------------------------------------------------------------------- -- Change log -- -- 19-Aug-2017: RE: Report offending line number in case of error -- 16-Jan-2017: GdM: Variable terminator symbol can be different than '=' -- 18-Dec-2016: RE: Added Read_Sections -- 26-Oct-2011: GdM/DB: Init also as a function -- 18-Mar-2010: GdM: Float replaced by Long_Float -- 20-Jul-2009: GdM: Added Replace_Section -- 17-Jul-2009: GdM: Improved Replace_Value -- 15-Jul-2009: GdM: - Added type Configuration to wrap name and options -- - Added Replace_Value -- - A few fixes -- 26-Apr-1996: RE: Created -- -- Created On : Fri Apr 26 08:09:14 1996 with Ada.Containers.Indefinite_Vectors; package Config is web : constant String := "https://sourceforge.net/projects/ini-files/"; web_alt : constant String := "https://github.com/zertovitch/ini-files"; -- Hopefully the latest version is at one of those locations. type Configuration is tagged private; type Type_Mismatch_Action is (Raise_Data_Error, Print_Warning, Be_Quiet); -- Initialize a Configuration object by providing the absolute path to the -- file where the configuration parameters are stored. The -- routine can be called multiple times to read several files. -- procedure Init (Cfg : out Configuration; Config_File_Name : String; -- -- Read the config file in a case sensitive way if True, i.e. Section -- and Mark must match exactly the upper and lower case spelling. If -- set False, case is irrelevant for Section and Mark. The return value -- still contains the exact case as in the config file. Case_Sensitive : Boolean := True; -- -- What to do in case the found mark does not match the expected type -- (e.g. the program wants an integer, but the config file contains a -- string) On_Type_Mismatch : Type_Mismatch_Action := Raise_Data_Error; -- Some configuration files have the form "Var value" instead of -- "Var=value". Of course, if Variable_Terminator = ' ', variable -- names cannot have a space in them. Variable_Terminator : Character := '=' -- ); -- Same, as a function (can be used in a declaration part as a constructor) function Init (Config_File_Name : String; Case_Sensitive : Boolean := True; On_Type_Mismatch : Type_Mismatch_Action := Raise_Data_Error; Variable_Terminator : Character := '=' ) return Configuration; -- Value_Of : getting values from a configuration file. -- If the Section is "*", the Mark is looked for in the whole configuration file. -- -- We intentionally use the built-in types Integer and Long_Float to keep -- this package as portable as possible and to avoid unnecessary project -- dependencies. Clients of this package generally can directly convert -- to the target types. -- function Value_Of (Cfg : Configuration; Section : String; Mark : String; Default : String := "") return String; function Value_Of (Cfg : Configuration; Section : String; Mark : String; Default : Integer := 0) return Integer; function Value_Of (Cfg : Configuration; Section : String; Mark : String; Default : Long_Float := 0.0) return Long_Float; -- Value_Of for Boolean: you may also want to consider the Is_Set function below. -- function Value_Of (Cfg : Configuration; Section : String; Mark : String; Default : Boolean := False) return Boolean; -- Return True if one of the following conditions is met: -- o the Mark is within the Section, but no equal sign is in that line, -- o the Mark is set to either 1, True or Yes. -- All other cases return False. -- function Is_Set (Cfg : Configuration; Section : String; Mark : String) return Boolean; -- Get the file name, e.g. to rewrite a fresh new config file. -- function File_Name (Cfg : Configuration) return String; -- Replace a single value in a configuration file. -- The whole .ini file is rewritten each time, so it's rather a -- solution for making sporadic changes. -- For changing many values, it might be better to rewrite -- the whole file in one go, or at least use Replace_Section. -- procedure Replace_Value (Cfg : Configuration; Section : String; Mark : String; New_Value : String); Location_Not_Found : exception; -- Replace the full contents of a section with new contents. -- Line breaks are obtained by inserting the LF character -- (defined below) in the New_Contents string. -- Replace_Section is especially useful for config files -- shared by several programs, with not all sections in common. -- procedure Replace_Section (Cfg : Configuration; Section : String; New_Contents : String); LF : constant Character := Character'Val (10); Section_Not_Found : exception; -- Disable the Mark using a semicolon prefix -- procedure Disable (Cfg : Configuration; Section : String; Mark : String); -- retrieve a list of all available sections in the ini file package String_Vector is new Ada.Containers.Indefinite_Vectors (Natural, String); subtype Section_List is String_Vector.Vector; function Read_Sections (Cfg : Configuration) return Section_List; private type Str_Ptr is access String; type Configuration is tagged record Config_File : Str_Ptr := null; Case_Sensitive : Boolean := True; On_Type_Mismatch : Type_Mismatch_Action := Raise_Data_Error; Variable_Terminator : Character := '='; end record; end Config;