include/corelib/ncbireg.hpp

Go to the documentation of this file.
00001 #ifndef CORELIB___NCBIREG__HPP
00002 #define CORELIB___NCBIREG__HPP
00003 
00004 /*  $Id: ncbireg.hpp 165949 2009-07-15 19:12:37Z ucko $
00005  * ===========================================================================
00006  *
00007  *                            PUBLIC DOMAIN NOTICE
00008  *               National Center for Biotechnology Information
00009  *
00010  *  This software/database is a "United States Government Work" under the
00011  *  terms of the United States Copyright Act.  It was written as part of
00012  *  the author's official duties as a United States Government employee and
00013  *  thus cannot be copyrighted.  This software/database is freely available
00014  *  to the public for use. The National Library of Medicine and the U.S.
00015  *  Government have not placed any restriction on its use or reproduction.
00016  *
00017  *  Although all reasonable efforts have been taken to ensure the accuracy
00018  *  and reliability of the software and data, the NLM and the U.S.
00019  *  Government do not and cannot warrant the performance or results that
00020  *  may be obtained by using this software or data. The NLM and the U.S.
00021  *  Government disclaim all warranties, express or implied, including
00022  *  warranties of performance, merchantability or fitness for any particular
00023  *  purpose.
00024  *
00025  *  Please cite the author in any work or product based on this material.
00026  *
00027  * ===========================================================================
00028  *
00029  * Authors:  Denis Vakatov, Aaron Ucko
00030  *
00031  */
00032 
00033 /// @file ncbireg.hpp
00034 /// Process information in the NCBI Registry, including working with
00035 /// configuration files.
00036 ///
00037 /// Classes to perform NCBI Registry operations including:
00038 /// - Read and parse configuration file
00039 /// - Search, edit, etc. the retrieved configuration information
00040 /// - Write information back to configuration file
00041 ///
00042 /// The Registry is defined as a text file with sections and entries in the 
00043 /// form of "name=value" strings in each section. 
00044 ///
00045 /// For an explanation of the syntax of the Registry file, see the
00046 /// C++ Toolkit documentation.
00047 
00048 
00049 #include <corelib/ncbi_limits.h>
00050 #include <corelib/ncbimtx.hpp>
00051 #include <corelib/ncbiobj.hpp>
00052 #include <map>
00053 #include <set>
00054 
00055 
00056 /** @addtogroup Registry
00057  *
00058  * @{
00059  */
00060 
00061 
00062 BEGIN_NCBI_SCOPE
00063 
00064 
00065 
00066 /////////////////////////////////////////////////////////////////////////////
00067 ///
00068 /// IRegistry --
00069 ///
00070 /// Base class for organized configuration data.
00071 ///
00072 /// Does not define a specific in-memory representation, just a
00073 /// read-only API and some convenience methods.
00074 
00075 class  IRegistry : public CObject
00076 {
00077 public:
00078     /// Flags controlling the behavior of registry methods.  Please note:
00079     /// - Although CNcbiRegistry supports a full complement of layers, other
00080     ///   derived classes may ignore some or all level-related flags.
00081     /// - Most read-only operations consider all layers; the only exception
00082     ///   is Write, which defaults to fPersistent and fJustCore.
00083     /// - The presence or absence of fSectionCase and fEntryCase is relevant
00084     ///   ONLY when constructing new registry objects.
00085     enum EFlags {
00086         fTransient      = 0x1,   ///< Transient -- not saved by default
00087         fPersistent     = 0x100, ///< Persistent -- saved when file is written
00088         fOverride       = 0x2,   ///< Existing value can be overriden
00089         fNoOverride     = 0x200, ///< Cannot change existing value
00090         fTruncate       = 0x4,   ///< Leading, trailing blanks can be truncated
00091         fNoTruncate     = 0x400, ///< Cannot truncate parameter value
00092         fJustCore       = 0x8,   ///< Ignore auxiliary subregistries
00093         fNotJustCore    = 0x800, ///< Include auxiliary subregistries
00094         fIgnoreErrors   = 0x10,  ///< Continue Read()ing after parse errors
00095         fInternalSpaces = 0x20,  ///< Allow internal whitespace in names
00096         fWithNcbirc     = 0x40,  ///< Include .ncbirc (used only by CNcbiReg.)
00097         fCountCleared   = 0x80,  ///< Let explicitly cleared entries stand
00098         fSectionCase    = 0x1000,///< Create with case-sensitive section names
00099         fEntryCase      = 0x2000,///< Create with case-sensitive entry names
00100         fCoreLayers     = fTransient | fPersistent | fJustCore,
00101         fAllLayers      = fTransient | fPersistent | fNotJustCore,
00102         fCaseFlags      = fSectionCase | fEntryCase
00103     };
00104     typedef int TFlags;  ///< Binary OR of "EFlags"
00105 
00106     /// Verify if Registry is empty.
00107     /// @param flags
00108     ///   Layer(s) to check.
00109     /// @return
00110     ///   TRUE if the registry contains no entries.
00111     bool Empty(TFlags flags = fAllLayers) const;
00112 
00113     /// Verify if persistent values have been modified.
00114     /// @param flags
00115     ///   Layer(s) to check.
00116     /// @return
00117     ///   TRUE if the relevant part(s) of the registry were modified since the
00118     ///   last call to SetModifiedFlag(false).
00119     bool Modified(TFlags flags = fPersistent) const;
00120 
00121     /// Indicate whether any relevant values are out of sync with some
00122     /// external resource (typically a configuration file).  You
00123     /// should normally not need to call this explicitly.
00124     /// @param flags
00125     ///   Relevant layer(s).
00126     void SetModifiedFlag(bool modified, TFlags flags = fPersistent);
00127 
00128     /// Write the registry content to output stream.
00129     /// @param os
00130     ///   Output stream to write the registry to.
00131     ///   NOTE:  if the stream is a file, it must be opened in binary mode!
00132     /// @param flags
00133     ///   Layer(s) to write.  By default, only persistent entries are
00134     ///   written, and only entries from the core layer(s) are written.
00135     /// @return
00136     ///   TRUE if operation is successful.
00137     /// @sa
00138     ///   IRWRegistry::Read()
00139     bool Write(CNcbiOstream& os, TFlags flags = 0) const;
00140 
00141     /// Get the parameter value.
00142     ///
00143     /// Get the parameter with the specified "name" from the specified
00144     /// "section".  First, search for the transient parameter value, and if
00145     /// cannot find in there, then continue the search in the non-transient
00146     /// parameters. If "fPersistent" flag is set in "flags", then don't
00147     /// search in the transient parameters at all.
00148     /// @param section
00149     ///   Section name to search under (case-insensitive).
00150     /// @param name
00151     ///   Parameter name to search for (case-insensitive).
00152     /// @param flags
00153     ///   To control search.
00154     /// @return
00155     ///   The parameter value, or empty string if the parameter is not found.
00156     /// @sa
00157     ///   GetString()
00158     const string& Get(const string& section,
00159                       const string& name,
00160                       TFlags        flags = 0) const;
00161 
00162     bool HasEntry(const string& section,
00163                   const string& name = kEmptyStr,
00164                   TFlags        flags = 0) const;
00165 
00166     /// Get the parameter string value.
00167     ///
00168     /// Similar to the "Get()", but if the configuration parameter is not
00169     /// found, then return 'default_value' rather than empty string.
00170     /// @sa
00171     ///   Get()
00172     string GetString(const string& section,
00173                      const string& name,
00174                      const string& default_value,
00175                      TFlags        flags = 0) const;
00176 
00177     /// What to do if parameter value is present but cannot be converted into
00178     /// the requested type.
00179     enum EErrAction {
00180         eThrow,   ///< Throw an exception if an error occurs
00181         eErrPost, ///< Log the error message and return default value
00182         eReturn   ///< Return default value
00183     };
00184 
00185     /// Get integer value of specified parameter name.
00186     ///
00187     /// Like "GetString()", plus convert the value into integer.
00188     /// @param err_action
00189     ///   What to do if error encountered in converting parameter value.
00190     /// @sa
00191     ///   GetString()
00192     int GetInt(const string& section,
00193                const string& name,
00194                int           default_value,
00195                TFlags        flags      = 0,
00196                EErrAction    err_action = eThrow) const;
00197 
00198     /// Get boolean value of specified parameter name.
00199     ///
00200     /// Like "GetString()", plus convert the value into boolean.
00201     /// @param err_action
00202     ///   What to do if error encountered in converting parameter value.
00203     /// @sa
00204     ///   GetString()
00205     bool GetBool(const string& section,
00206                  const string& name,
00207                  bool          default_value,
00208                  TFlags        flags      = 0,
00209                  EErrAction    err_action = eThrow) const;
00210 
00211     /// Get double value of specified parameter name.
00212     ///
00213     /// Like "GetString()", plus convert the value into double.
00214     /// @param err_action
00215     ///   What to do if error encountered in converting parameter value.
00216     /// @sa
00217     ///   GetString()
00218     double GetDouble(const string& section,
00219                      const string& name,
00220                      double        default_value,
00221                      TFlags        flags = 0,
00222                      EErrAction    err_action = eThrow) const;
00223 
00224     /// Get comment of the registry entry "section:name".
00225     ///
00226     /// @param section
00227     ///   Section name.
00228     ///   If passed empty string, then get the registry comment.
00229     /// @param name
00230     ///   Parameter name.
00231     ///   If empty string, then get the "section" comment.
00232     /// @param flags
00233     ///   To control search.
00234     /// @return
00235     ///   Comment string. If not found, return an empty string.
00236     const string& GetComment(const string& section = kEmptyStr,
00237                              const string& name    = kEmptyStr,
00238                              TFlags        flags   = 0) const;
00239 
00240     /// Enumerate section names.
00241     ///
00242     /// Write all section names to the "sections" list in
00243     /// (case-insensitive) order.  Previous contents of the list are
00244     /// erased.
00245     /// @param flags
00246     ///   To control search.
00247     void EnumerateSections(list<string>* sections,
00248                            TFlags        flags = fAllLayers) const;
00249 
00250     /// Enumerate parameter names for a specified section.
00251     ///
00252     /// Write all parameter names for specified "section" to the "entries"
00253     /// list in order.  Previous contents of the list are erased.  Enumerates
00254     /// sections rather than entries if section is empty.
00255     /// @param flags
00256     ///   To control search.
00257     void EnumerateEntries(const string& section,
00258                           list<string>* entries,
00259                           TFlags        flags = fAllLayers) const;
00260 
00261     /// Support for locking.  Individual operations already use these
00262     /// to ensure atomicity, but the locking mechanism is recursive,
00263     /// so users can also make entire sequences of operations atomic.
00264     void ReadLock (void);
00265     void WriteLock(void);
00266     void Unlock   (void);
00267 
00268 #ifdef NCBI_COMPILER_ICC
00269     /// Work around a compiler bug that can cause memory leaks.
00270     virtual ~IRegistry() { }
00271 #endif
00272 
00273 protected:
00274     enum EMasks {
00275         fLayerFlags = fAllLayers | fJustCore,
00276         fTPFlags    = fTransient | fPersistent
00277     };
00278 
00279     static void x_CheckFlags(const string& func, TFlags& flags,
00280                              TFlags allowed);
00281     /// Implementations of the fundamental operations above, to be run with
00282     /// the lock already acquired and some basic sanity checks performed.
00283     virtual bool x_Empty(TFlags flags) const = 0;
00284     virtual bool x_Modified(TFlags /* flags */) const { return false; }
00285     virtual void x_SetModifiedFlag(bool /* modified */, TFlags /* flags */) {}
00286     virtual const string& x_Get(const string& section, const string& name,
00287                                 TFlags flags) const = 0;
00288     virtual bool x_HasEntry(const string& section, const string& name,
00289                             TFlags flags) const = 0;
00290     virtual const string& x_GetComment(const string& section,
00291                                        const string& name, TFlags flags)
00292         const = 0;
00293     // enumerate sections rather than entries if section is empty
00294     virtual void x_Enumerate(const string& section, list<string>& entries,
00295                              TFlags flags) const = 0;
00296 
00297     typedef void (IRegistry::*FLockAction)(void);
00298     virtual void x_ChildLockAction(FLockAction /* action */) {}
00299 
00300 private:
00301     mutable CRWLock m_Lock;
00302 };
00303 
00304 
00305 
00306 /////////////////////////////////////////////////////////////////////////////
00307 ///
00308 /// IRWRegistry --
00309 ///
00310 /// Abstract subclass for modifiable registries.
00311 ///
00312 /// To avoid confusion, all registry classes that support modification
00313 /// should inherit from this class.
00314 
00315 class  IRWRegistry : public IRegistry
00316 {
00317 public:
00318     /// Categories of modifying operations
00319     enum EOperation {
00320         eClear,
00321         eRead,
00322         eSet
00323     };
00324 
00325     /// Indicate which portions of the registry the given operation
00326     /// would affect.
00327     static TFlags AssessImpact(TFlags flags, EOperation op);
00328 
00329     /// Reset the registry content.
00330     void Clear(TFlags flags = fAllLayers);
00331 
00332     /// Read and parse the stream "is", and merge its content with current
00333     /// Registry entries.
00334     ///
00335     /// Once the Registry has been initialized by the constructor, it is 
00336     /// possible to load other parameters from other files using this method.
00337     /// @param is
00338     ///   Input stream to read and parse.
00339     ///   NOTE:  if the stream is a file, it must be opened in binary mode!
00340     /// @param flags
00341     ///   How parameters are stored. The default is for all values to be read
00342     ///   as persistent with the capability of overriding any previously
00343     ///   loaded value associated with the same name. The default can be
00344     ///   modified by specifying "fTransient", "fNoOverride" or 
00345     ///   "fTransient | fNoOverride". If there is a conflict between the old
00346     ///   and the new (loaded) entry value and if "fNoOverride" flag is set,
00347     ///   then just ignore the new value; otherwise, replace the old value by
00348     ///   the new one. If "fTransient" flag is set, then store the newly
00349     ///   retrieved parameters as transient;  otherwise, store them as
00350     ///   persistent.
00351     /// @return
00352     ///   A pointer to a newly created subregistry, if any, directly
00353     ///   containing the entries loaded from is.
00354     /// @sa
00355     ///   Write()
00356     IRWRegistry* Read(CNcbiIstream& is, TFlags flags = 0);
00357 
00358     /// Set the configuration parameter value.
00359     ///
00360     /// Unset the parameter if specified "value" is empty.
00361     ///
00362     /// @param value
00363     ///   Value that the parameter is set to.
00364     /// @param flags
00365     ///   To control search.
00366     ///   Valid flags := { fPersistent, fNoOverride, fTruncate }
00367     ///   If there was already an entry with the same <section,name> key:
00368     ///     if "fNoOverride" flag is set then do not override old value
00369     ///     and return FALSE;  else override the old value and return TRUE.
00370     ///   If "fPersistent" flag is set then store the entry as persistent;
00371     ///     else store it as transient.
00372     ///   If "fTruncate" flag is set then truncate the leading and trailing
00373     ///     spaces -- " \r\t\v" (NOTE:  '\n' is not considered a space!).
00374     /// @param comment
00375     ///   Optional comment string describing parameter.
00376     /// @return
00377     ///   TRUE if successful (including replacing a value with itself)
00378     bool Set(const string& section,
00379              const string& name,
00380              const string& value,
00381              TFlags        flags   = 0,
00382              const string& comment = kEmptyStr);
00383 
00384     /// Set comment "comment" for the registry entry "section:name".
00385     ///
00386     /// @param comment
00387     ///   Comment string value.
00388     ///   Set to kEmptyStr to delete the comment.
00389     /// @param section
00390     ///   Section name.
00391     ///   If "section" is empty string, then set as the registry comment.
00392     /// @param name
00393     ///   Parameter name.
00394     ///   If "name" is empty string, then set as the "section" comment.
00395     /// @param flags
00396     ///   How the comment is stored. The default is for comments to be
00397     ///   stored as persistent with the capability of overriding any
00398     ///   previously loaded value associated with the same name. The
00399     ///   default can be modified by specifying "fTransient", "fNoOverride"
00400     ///   or "fTransient | fNoOverride". If there is a conflict between the
00401     ///   old and the new comment and if "fNoOverride" flag is set, then
00402     ///   just ignore the new comment; otherwise, replace the old comment
00403     ///   by the new one. If "fTransient" flag is set, then store the new
00404     ///   comment as transient (generally not desired); otherwise, store it
00405     ///   as persistent.
00406     /// @return
00407     ///   FALSE if "section" and/or "name" do not exist in registry.
00408     bool SetComment(const string& comment,
00409                     const string& section = kEmptyStr,
00410                     const string& name    = kEmptyStr,
00411                     TFlags        flags   = 0);
00412 
00413 #ifdef NCBI_COMPILER_ICC
00414     /// Work around a compiler bug that can cause memory leaks.
00415     virtual ~IRWRegistry() { }
00416 #endif
00417 
00418 protected:
00419     /// Called locked, like the virtual methods inherited from IRegistry.
00420     virtual void x_Clear(TFlags flags) = 0;
00421     virtual bool x_Set(const string& section, const string& name,
00422                        const string& value, TFlags flags,
00423                        const string& comment) = 0;
00424     virtual bool x_SetComment(const string& comment, const string& section,
00425                               const string& name, TFlags flags) = 0;
00426 
00427     /// Most implementations should not override this, but
00428     /// CNcbiRegistry must, to handle some special cases properly.
00429     virtual IRWRegistry* x_Read(CNcbiIstream& is, TFlags flags);
00430 
00431     // for use by implementations
00432     static bool MaybeSet(string& target, const string& value, TFlags flags);
00433 };
00434 
00435 
00436 
00437 /////////////////////////////////////////////////////////////////////////////
00438 ///
00439 /// CMemoryRegistry --
00440 ///
00441 /// Straightforward monolithic modifiable registry.
00442 
00443 class  CMemoryRegistry : public IRWRegistry
00444 {
00445 public:
00446     CMemoryRegistry(TFlags flags = 0)
00447         : m_IsModified(false),
00448           m_Sections((flags & fSectionCase) == 0 ? NStr::eNocase : NStr::eCase),
00449           m_Flags(flags)
00450         {}
00451 
00452 #ifdef NCBI_COMPILER_ICC
00453     /// Work around a compiler bug that can cause memory leaks.
00454     virtual ~CMemoryRegistry() { }
00455 #endif
00456 
00457 protected:
00458     bool x_Empty(TFlags flags) const;
00459     bool x_Modified(TFlags) const { return m_IsModified; }
00460     void x_SetModifiedFlag(bool modified, TFlags) { m_IsModified = modified; }
00461     const string& x_Get(const string& section, const string& name,
00462                         TFlags flags) const;
00463     bool x_HasEntry(const string& section, const string& name, TFlags flags)
00464         const;
00465     const string& x_GetComment(const string& section, const string& name,
00466                                TFlags flags) const;
00467     void x_Enumerate(const string& section, list<string>& entries,
00468                      TFlags flags) const;
00469 
00470     void x_Clear(TFlags flags);
00471     bool x_Set(const string& section, const string& name,
00472                const string& value, TFlags flags,
00473                const string& comment);
00474     bool x_SetComment(const string& comment, const string& section,
00475                       const string& name, TFlags flags);
00476 
00477 public: // WorkShop needs these exposed
00478     struct SEntry {
00479         string value, comment;
00480     };
00481     typedef map<string, SEntry, PNocase_Conditional> TEntries;
00482     struct SSection {
00483         SSection(TFlags flags)
00484             : entries((flags & fEntryCase) == 0 ? NStr::eNocase : NStr::eCase)
00485             { }
00486         string   comment;
00487         TEntries entries;
00488         bool     cleared;
00489     };
00490     typedef map<string, SSection, PNocase_Conditional> TSections;
00491 
00492 private:
00493     bool      m_IsModified;
00494     string    m_RegistryComment;
00495     TSections m_Sections;
00496     TFlags    m_Flags;
00497 };
00498 
00499 
00500 
00501 /////////////////////////////////////////////////////////////////////////////
00502 ///
00503 /// CCompoundRegistry --
00504 ///
00505 /// Prioritized read-only collection of sub-registries.
00506 ///
00507 /// @sa
00508 ///  CTwoLayerRegistry
00509 
00510 class  CCompoundRegistry : public IRegistry
00511 {
00512 public:
00513     CCompoundRegistry() : m_CoreCutoff(ePriority_Default) { }
00514 
00515 #ifdef NCBI_COMPILER_ICC
00516     /// Work around a compiler bug that can cause memory leaks.
00517     virtual ~CCompoundRegistry() { }
00518 #endif
00519 
00520     /// Priority for sub-registries; entries in higher-priority
00521     /// sub-registries take precedence over (identically named) entries
00522     /// in lower-priority ones.  Ties are broken arbitrarily.
00523     enum EPriority {
00524         ePriority_Min     = kMin_Int,
00525         ePriority_Default = 0,
00526         ePriority_Max     = kMax_Int
00527     };
00528     typedef int TPriority; ///< Not restricted to ePriority_*.
00529 
00530     /// Non-empty names must be unique within each compound registry,
00531     /// but there is no limit to the number of anonymous sub-registries.
00532     /// Sub-registries themselves may not (directly) appear more than once.
00533     void Add(const IRegistry& reg,
00534              TPriority        prio = ePriority_Default,
00535              const string&    name = kEmptyStr);
00536 
00537     /// Remove sub-registry "reg".
00538     /// Throw an exception if "reg" is not a (direct) sub-registry.
00539     void Remove(const IRegistry& reg);
00540 
00541     /// Subregistries whose priority is less than the core cutoff
00542     /// (ePriority_Default by default) will be ignored for fJustCore
00543     /// operations, such as Write by default.
00544     TPriority GetCoreCutoff(void) const     { return m_CoreCutoff; }
00545     void      SetCoreCutoff(TPriority prio) { m_CoreCutoff = prio; }
00546 
00547     /// Return a pointer to the sub-registry with the given name, or
00548     /// NULL if not found.
00549     CConstRef<IRegistry> FindByName(const string& name) const;
00550 
00551     /// Return a pointer to the highest-priority sub-registry with a
00552     /// section named SECTION containing (if ENTRY is non-empty) an entry
00553     /// named ENTRY, or NULL if not found.
00554     CConstRef<IRegistry> FindByContents(const string& section,
00555                                         const string& entry = kEmptyStr,
00556                                         TFlags        flags = 0) const;
00557 
00558     // allow enumerating sub-registries?
00559 
00560 protected:    
00561     // virtual methods of IRegistry
00562 
00563     /// True iff all sub-registries are empty
00564     bool x_Empty(TFlags flags) const;
00565 
00566     /// True iff any sub-registry is modified
00567     bool x_Modified(TFlags flags) const;
00568     void x_SetModifiedFlag(bool modified, TFlags flags);
00569     const string& x_Get(const string& section, const string& name,
00570                         TFlags flags) const;
00571     bool x_HasEntry(const string& section, const string& name, TFlags flags)
00572         const;
00573     const string& x_GetComment(const string& section, const string& name,
00574                                TFlags flags) const;
00575     void x_Enumerate(const string& section, list<string>& entries,
00576                      TFlags flags) const;
00577     void x_ChildLockAction(FLockAction action);
00578 
00579 private:
00580     typedef multimap<TPriority, CRef<IRegistry> > TPriorityMap;
00581     typedef map<string, CRef<IRegistry> >         TNameMap;
00582 
00583     TPriorityMap m_PriorityMap; 
00584     TNameMap     m_NameMap;     ///< excludes anonymous sub-registries
00585     TPriority    m_CoreCutoff;
00586 
00587     friend class CCompoundRWRegistry;
00588 };
00589 
00590 
00591 
00592 /////////////////////////////////////////////////////////////////////////////
00593 ///
00594 /// CTwoLayerRegistry --
00595 ///
00596 /// Limited to two direct layers (transient above persistent), but
00597 /// supports modification.
00598 ///
00599 /// @sa
00600 ///  CCompoundRegistry
00601 
00602 class  CTwoLayerRegistry : public IRWRegistry
00603 {
00604 public:
00605     /// Constructor.  The transient layer is always a new memory registry,
00606     /// and so is the persistent layer by default.
00607     CTwoLayerRegistry(IRWRegistry* persistent = 0, TFlags flags = 0);
00608 
00609 #ifdef NCBI_COMPILER_ICC
00610     /// Work around a compiler bug that can cause memory leaks.
00611     virtual ~CTwoLayerRegistry() { }
00612 #endif
00613 
00614 protected:
00615     bool x_Empty(TFlags flags) const;
00616     bool x_Modified(TFlags flags) const;
00617     void x_SetModifiedFlag(bool modified, TFlags flags);
00618     const string& x_Get(const string& section, const string& name,
00619                         TFlags flags) const;
00620     bool x_HasEntry(const string& section, const string& name,
00621                     TFlags flags) const;
00622     const string& x_GetComment(const string& section, const string& name,
00623                                TFlags flags) const;
00624     void x_Enumerate(const string& section, list<string>& entries,
00625                      TFlags flags) const;
00626     void x_ChildLockAction(FLockAction action);
00627 
00628     void x_Clear(TFlags flags);
00629     bool x_Set(const string& section, const string& name,
00630                const string& value, TFlags flags,
00631                const string& comment);
00632     bool x_SetComment(const string& comment, const string& section,
00633                       const string& name, TFlags flags);
00634 
00635 private:
00636     typedef CRef<IRWRegistry> CRegRef;
00637     CRegRef m_Transient;
00638     CRegRef m_Persistent;
00639 };
00640 
00641 
00642 /////////////////////////////////////////////////////////////////////////////
00643 ///
00644 /// CCompoundRWRegistry --
00645 ///
00646 /// Writeable compound registry.
00647 ///
00648 /// Compound registry whose top layer is a two-layer registry; all
00649 /// writes go to the two-layer registry.
00650 
00651 class  CCompoundRWRegistry : public IRWRegistry
00652 {
00653 public:
00654     /// Constructor.
00655     CCompoundRWRegistry(TFlags m_Flags = 0);
00656 
00657     /// Destructor.
00658     ~CCompoundRWRegistry();
00659 
00660     /// Priority for sub-registries; entries in higher-priority
00661     /// sub-registries take precedence over (identically named) entries
00662     /// in lower-priority ones.  Ties are broken arbitrarily.
00663     enum EPriority {
00664         ePriority_MinUser  = CCompoundRegistry::ePriority_Min,
00665         ePriority_Default  = CCompoundRegistry::ePriority_Default,
00666         ePriority_MaxUser  = CCompoundRegistry::ePriority_Max - 0x10000,
00667         ePriority_Reserved ///< Everything greater is for internal use.
00668     };
00669     typedef int TPriority; ///< Not restricted to ePriority_*.
00670 
00671     /// Subregistries whose priority is less than the core cutoff
00672     /// (ePriority_Reserved by default) will be ignored for fJustCore
00673     /// operations, such as Write by default.
00674     TPriority GetCoreCutoff(void) const;
00675     void      SetCoreCutoff(TPriority prio);
00676 
00677     /// Non-empty names must be unique within each compound registry,
00678     /// but there is no limit to the number of anonymous sub-registries.
00679     /// Sub-registries themselves may not (directly) appear more than once.
00680     void Add(const IRegistry& reg,
00681              TPriority        prio = ePriority_Default,
00682              const string&    name = kEmptyStr);
00683 
00684     /// Remove sub-registry "reg".
00685     /// Throw an exception if "reg" is not a (direct) sub-registry.
00686     void Remove(const IRegistry& reg);
00687 
00688     /// Return a pointer to the sub-registry with the given name, or
00689     /// NULL if not found.
00690     CConstRef<IRegistry> FindByName(const string& name) const;
00691 
00692     /// Return a pointer to the highest-priority sub-registry with a
00693     /// section named SECTION containing (if ENTRY is non-empty) an entry
00694     /// named ENTRY, or NULL if not found.
00695     CConstRef<IRegistry> FindByContents(const string& section,
00696                                         const string& entry = kEmptyStr,
00697                                         TFlags        flags = 0) const;
00698 
00699     /// Load any base registries listed in [NCBI].Inherits; returns
00700     /// true if able to load at least one, false otherwise.
00701     bool LoadBaseRegistries(TFlags flags = 0,
00702                             int /* CMetaRegistry::TFlags */ metareg_flags = 0);
00703 
00704     /// Predefined subregistry's name.
00705     static const char* sm_MainRegName;
00706     /// Prefix for any base registries' names.
00707     static const char* sm_BaseRegNamePrefix;
00708 
00709 protected:
00710     bool x_Empty(TFlags flags) const;
00711     bool x_Modified(TFlags flags) const;
00712     void x_SetModifiedFlag(bool modified, TFlags flags);
00713     const string& x_Get(const string& section, const string& name,
00714                         TFlags flags) const;
00715     bool x_HasEntry(const string& section, const string& name,
00716                     TFlags flags) const;
00717     const string& x_GetComment(const string& section, const string& name,
00718                                TFlags flags) const;
00719     void x_Enumerate(const string& section, list<string>& entries,
00720                      TFlags flags) const;
00721     void x_ChildLockAction(FLockAction action);
00722 
00723     void x_Clear(TFlags flags);
00724     bool x_Set(const string& section, const string& name,
00725                const string& value, TFlags flags,
00726                const string& comment);
00727     bool x_SetComment(const string& comment, const string& section,
00728                       const string& name, TFlags flags);
00729     IRWRegistry* x_Read(CNcbiIstream& is, TFlags flags);
00730 
00731     /// Add an internal high-priority subregistry.
00732     void x_Add(const IRegistry& reg,
00733                TPriority        prio = ePriority_Default,
00734                const string&    name = kEmptyStr);
00735 
00736 private:
00737     typedef map<string, TFlags> TClearedEntries;
00738 
00739     TClearedEntries         m_ClearedEntries;
00740     CRef<CTwoLayerRegistry> m_MainRegistry;
00741     CRef<CCompoundRegistry> m_AllRegistries;
00742     set<string>             m_BaseRegNames;
00743     TFlags                  m_Flags;
00744 };
00745 
00746 
00747 class CEnvironmentRegistry; // see <corelib/env_reg.hpp>
00748 
00749 
00750 
00751 /////////////////////////////////////////////////////////////////////////////
00752 ///
00753 /// CNcbiRegistry --
00754 ///
00755 /// Define the Registry.
00756 ///
00757 /// Load, access, modify and store runtime information (usually used
00758 /// to work with configuration files).
00759 
00760 class  CNcbiRegistry : public CCompoundRWRegistry
00761 {
00762 public:
00763     enum ECompatFlags {
00764         eTransient   = fTransient,
00765         ePersistent  = fPersistent,
00766         eOverride    = fOverride,
00767         eNoOverride  = fNoOverride,
00768         eTruncate    = fTruncate,
00769         eNoTruncate  = fNoTruncate
00770     };
00771 
00772     /// Constructor.
00773     CNcbiRegistry(TFlags flags = 0);
00774 
00775     /// Constructor.
00776     ///
00777     /// @param is
00778     ///   Input stream to load the Registry from.
00779     ///   NOTE:  if the stream is a file, it must be opened in binary mode!
00780     /// @param flags
00781     ///   How parameters are stored. The default is to store all parameters as
00782     ///   persistent unless the  "eTransient" flag is set in which case the
00783     ///   newly retrieved parameters are stored as transient.
00784     /// @sa
00785     ///   Read()
00786     CNcbiRegistry(CNcbiIstream& is, TFlags flags = 0);
00787 
00788     ~CNcbiRegistry();
00789 
00790     /// Attempt to load a systemwide configuration file (.ncbirc on
00791     /// Unix, ncbi.ini on Windows) as a low-priority registry, as long
00792     /// as the following conditions all hold:
00793     /// - fWithNcbirc is set in FLAGS.
00794     /// - The environment variable NCBI_DONT_USE_NCBIRC is NOT set.
00795     /// - The registry's existing contents do NOT contain a setting of
00796     ///   [NCBI]DONT_USE_NCBIRC (case-insensitive).
00797     /// @param flags
00798     ///   Registry flags to be applied when reading the system
00799     ///   configuration file.  Must also contain fWithNcbirc (which
00800     ///   will be filtered out before calling any other methods) for
00801     ///   the call to have any effect.
00802     /// @return
00803     ///   TRUE if the system configuration file was successfully read
00804     ///   and parsed; FALSE otherwise.
00805     bool IncludeNcbircIfAllowed(TFlags flags = fWithNcbirc);
00806 
00807     /// Predefined subregistries' names.
00808     static const char* sm_EnvRegName;
00809     static const char* sm_FileRegName;
00810     static const char* sm_OverrideRegName;
00811     static const char* sm_SysRegName;
00812 
00813 protected:
00814     void x_Clear(TFlags flags);
00815     IRWRegistry* x_Read(CNcbiIstream& is, TFlags flags);
00816 
00817 private:
00818     void x_Init(void);
00819 
00820     enum EReservedPriority {
00821         ePriority_File = ePriority_Reserved,
00822         ePriority_Overrides,
00823         ePriority_Environment,
00824         ePriority_RuntimeOverrides
00825     };
00826 
00827     CRef<CEnvironmentRegistry> m_EnvRegistry;
00828     CRef<CTwoLayerRegistry>    m_FileRegistry;
00829     CRef<IRWRegistry>          m_OverrideRegistry;
00830     CRef<IRWRegistry>          m_SysRegistry;
00831     unsigned int               m_RuntimeOverrideCount;
00832     TFlags                     m_Flags;
00833 };
00834 
00835 
00836 
00837 /////////////////////////////////////////////////////////////////////////////
00838 ///
00839 /// CRegistryException --
00840 ///
00841 /// Define exceptions generated by IRegistry and derived classes.
00842 ///
00843 /// CRegistryException inherits its basic functionality from
00844 /// CCParseTemplException<CCoreException> and defines additional error codes
00845 /// for the Registry.
00846 
00847 class  CRegistryException : public CParseTemplException<CCoreException>
00848 {
00849 public:
00850     /// Error types that the Registry can generate.
00851     enum EErrCode {
00852         eSection,   ///< Section error
00853         eEntry,     ///< Entry error
00854         eValue,     ///< Value error
00855         eErr        ///< Other error
00856     };
00857 
00858     /// Translate from the error code value to its string representation.
00859     virtual const char* GetErrCodeString(void) const;
00860 
00861     // Standard exception boilerplate code
00862     NCBI_EXCEPTION_DEFAULT2(CRegistryException,
00863                             CParseTemplException<CCoreException>,
00864                             std::string::size_type);
00865 };
00866 
00867 
00868 
00869 /////////////////////////////////////////////////////////////////////////////
00870 ///
00871 /// CRegistry{Read,Write}Guard --
00872 ///
00873 /// Guard classes to ensure one-thread-at-a-time access to registries.
00874 
00875 class  CRegistryReadGuard
00876     : public CGuard<IRegistry, SSimpleReadLock<IRegistry> >
00877 {
00878 public:
00879     typedef CGuard<IRegistry, SSimpleReadLock<IRegistry> > TParent;
00880     CRegistryReadGuard(const IRegistry& reg)
00881         : TParent(const_cast<IRegistry&>(reg))
00882         { }
00883 };
00884 
00885 typedef CGuard<IRegistry, SSimpleWriteLock<IRegistry> > CRegistryWriteGuard;
00886 
00887 END_NCBI_SCOPE
00888 
00889 
00890 /* @} */
00891 
00892 #endif  /* CORELIB___NCBIREG__HPP */
00893 
00894 

Generated on Sun Dec 6 22:01:26 2009 for NCBI C++ ToolKit by  doxygen 1.4.6
Modified on Mon Dec 07 16:20:35 2009 by modify_doxy.py rev. 173732