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
1.4.6
Modified on Mon Dec 07 16:20:35 2009 by modify_doxy.py rev. 173732