⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ncbireg.cpp

📁 ncbi源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/* * =========================================================================== * PRODUCTION $Log: ncbireg.cpp,v $ * PRODUCTION Revision 1000.1  2004/06/01 19:09:18  gouriano * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.39 * PRODUCTION * =========================================================================== *//*  $Id: ncbireg.cpp,v 1000.1 2004/06/01 19:09:18 gouriano Exp $ * =========================================================================== * *                            PUBLIC DOMAIN NOTICE *               National Center for Biotechnology Information * *  This software/database is a "United States Government Work" under the *  terms of the United States Copyright Act.  It was written as part of *  the author's official duties as a United States Government employee and *  thus cannot be copyrighted.  This software/database is freely available *  to the public for use. The National Library of Medicine and the U.S. *  Government have not placed any restriction on its use or reproduction. * *  Although all reasonable efforts have been taken to ensure the accuracy *  and reliability of the software and data, the NLM and the U.S. *  Government do not and cannot warrant the performance or results that *  may be obtained by using this software or data. The NLM and the U.S. *  Government disclaim all warranties, express or implied, including *  warranties of performance, merchantability or fitness for any particular *  purpose. * *  Please cite the author in any work or product based on this material. * * =========================================================================== * * Author:  Denis Vakatov * * File Description: *   Handle info in the NCBI configuration file(s): *      read and parse config. file *      search, edit, etc. in the retrieved configuration info *      dump info back to config. file * */#include <ncbi_pch.hpp>#include <corelib/ncbireg.hpp>#include <corelib/ncbimtx.hpp>// Platform-specific EndOfLine#if   defined(NCBI_OS_MAC)const char s_Endl[] = "\r";#elif defined(NCBI_OS_MSWIN)const char s_Endl[] = "\r\n";#else /* assume UNIX-like EOLs */const char s_Endl[] = "\n";#endifBEGIN_NCBI_SCOPE#define CHECK_FLAGS(func_name, flags, allowed_flags)  do { \    if (flags & ~((TFlags)(allowed_flags))) \        _TRACE("CNcbiRegistry::" func_name "(): extra flags passed: " \               << setiosflags(IOS_BASE::hex) << flags); \    flags = flags & (TFlags)(allowed_flags); \} while (0)/* Valid symbols for a section/entry name */inline bool s_IsNameSectionSymbol(char ch){    return (isalnum(ch)  ||  ch == '_'  ||  ch == '-'  ||  ch == '.');}/* Check if "str" consists of alphanumeric and '_' only */static bool s_IsNameSection(const string& str){    if ( str.empty() )        return false;    ITERATE (string, it, str) {        if ( !s_IsNameSectionSymbol(*it) )            return false;    }    return true;}/* Convert "comment" from plain text to comment */static const string s_ConvertComment(const string& comment,                                     bool is_file_comment = false){    if ( !comment.length() )        return kEmptyStr;    string x_comment;    const char c_comment = is_file_comment ? '#' : ';';    SIZE_TYPE endl_pos = 0;    for (SIZE_TYPE beg = 0;  beg < comment.length();         beg = endl_pos + 1) {        SIZE_TYPE pos = comment.find_first_not_of(" \t", beg);        endl_pos = comment.find_first_of("\n", beg);        if (endl_pos == NPOS) {            endl_pos = comment.length();        }        if (((pos != NPOS  &&  comment[pos] != c_comment) ||             (pos == NPOS  &&  endl_pos == comment.length())) &&            (is_file_comment  ||  beg != endl_pos) ) {            x_comment += c_comment;        }        x_comment.append(comment, beg, endl_pos - beg);        x_comment += '\n';    }    return x_comment;}/* Dump the comment to stream "os" */static bool s_WriteComment(CNcbiOstream& os, const string& comment){    if (!comment.length())        return true;    if (strcmp(s_Endl, "\n") == 0) {        os << comment;    } else {        ITERATE(string, i, comment) {            if (*i == '\n') {                os << s_Endl;            } else {                os << *i;            }        }    }    return os.good();}// Protective mutex for registry Get() and Set() functionsDEFINE_STATIC_FAST_MUTEX(s_RegMutex);CNcbiRegistry::CNcbiRegistry(void)    : m_Modified(false), m_Written(false){    return;}CNcbiRegistry::~CNcbiRegistry(void){    return;}CNcbiRegistry::CNcbiRegistry(CNcbiIstream& is, TFlags flags)    : m_Modified(false), m_Written(false){    CHECK_FLAGS("CNcbiRegistry", flags, eTransient);    Read(is, flags);}bool CNcbiRegistry::Empty(void) const {    return m_Registry.empty();}bool CNcbiRegistry::Modified(void) const{    return m_Modified;}/* Read data to reqistry from stream */void CNcbiRegistry::Read(CNcbiIstream& is, TFlags flags){    CHECK_FLAGS("Read", flags, eTransient | eNoOverride);    // If to consider this read to be (unconditionally) non-modifying    bool non_modifying = !m_Modified  &&  !m_Written  &&  x_IsAllTransient();    // Adjust flags for Set()    if (flags & eTransient) {        flags &= ~((TFlags) eTransient);    } else {        flags |= ePersistent;    }    string    str;          // the line being parsed    SIZE_TYPE line;         // # of the line being parsed    string    section;      // current section name    string    comment;      // current comment    for (line = 1;  NcbiGetlineEOL(is, str);  line++) {        SIZE_TYPE len = str.length();        SIZE_TYPE beg;        for (beg = 0;  beg < len  &&  isspace(str[beg]);  beg++)            continue;        if (beg == len) {            comment += str;            comment += '\n';            continue;        }        switch ( str[beg] ) {        case '#':  { // file comment            m_Comment += str;            m_Comment += '\n';            break;        }        case ';':  { // comment            comment += str;            comment += '\n';            break;        }        case '[':  { // section name            beg++;            SIZE_TYPE end = str.find_first_of(']');            if (end == NPOS)                NCBI_THROW2(CRegistryException, eSection,                            "Invalid registry section(']' is missing): `"                            + str + "'", line);            while ( isspace(str[beg]) )                beg++;            if (str[beg] == ']') {                NCBI_THROW2(CRegistryException, eSection,                            "Unnamed registry section: `" + str + "'", line);            }            for (end = beg;  s_IsNameSectionSymbol(str[end]);  end++)                continue;            section = str.substr(beg, end - beg);            // an extra validity check            while ( isspace(str[end]) )                end++;            _ASSERT( end <= str.find_first_of(']', 0) );            if (str[end] != ']')                NCBI_THROW2(CRegistryException, eSection,                            "Invalid registry section name: `"                            + str + "'", line);            // add section comment            if ( !comment.empty() ) {                _ASSERT( s_IsNameSection(section) );                // create section if it not exist                m_Registry.insert(TRegistry::value_type(section,                                                        TRegSection()));                SetComment(GetComment(section) + comment, section);                comment.erase();            }            break;        }        default:  { // regular entry            if (!s_IsNameSectionSymbol(str[beg])  ||                str.find_first_of('=') == NPOS)                NCBI_THROW2(CRegistryException, eEntry,                            "Invalid registry entry format: '" + str + "'",                            line);            // name            SIZE_TYPE mid;            for (mid = beg;  s_IsNameSectionSymbol(str[mid]);  mid++)                continue;            string name = str.substr(beg, mid - beg);            // '=' and surrounding spaces            while ( isspace(str[mid]) )                mid++;            if (str[mid] != '=')                NCBI_THROW2(CRegistryException, eEntry,                            "Invalid registry entry name: '" + str + "'",                            line);            for (mid++;  mid < len  &&  isspace(str[mid]);  mid++)                continue;            _ASSERT( mid <= len );            // ? empty value            if (mid == len) {                if ( !(flags & eNoOverride) ) {                    Set(section, name, kEmptyStr, flags, comment);                    comment.erase();                }                break;            }            // value            string value;            beg = mid;            if (str[beg] == '"')                beg++;            bool read_next_line;            do {                read_next_line = false;                // strip trailing spaces, check for an empty string                if ( str.empty() )                    break;                SIZE_TYPE end;                for (end = str.length() - 1;                     end > beg  &&  isspace(str[end]);  end--)                    continue;                if (end < beg  ||  isspace(str[end]) )                    break;                // un-escape the value                for (SIZE_TYPE i = beg;  i <= end;  i++) {                    if (str[i] == '"') {                        if (i != end) {                            NCBI_THROW2(CRegistryException, eValue,                                        "Single(unescaped) '\"' in the middle "                                        "of registry value: '" + str + "'",                                        line);                        }                        break;                    }                    if (str[i] != '\\') {                        value += str[i];                        continue;                    }                    // process back-slash                    if (i == end) {                        value += '\n';                        beg = 0;                        read_next_line = true;                        line++;                    } else if (str[i+1] == 'r') {                        value += '\r';                        i++;                    } else if (str[i+1] == '\\') {                        value += '\\';                        i++;                    } else if (str[i+1] == '"') {                        value += '"';                        i++;                    } else {                        NCBI_THROW2(CRegistryException, eValue,                                    "Badly placed '\\' in the registry "                                    "value: '" + str + "'", line);                    }                }            } while (read_next_line  &&  NcbiGetlineEOL(is, str));            Set(section, name, value, flags, comment);            comment.erase();        }        }    }    if ( !is.eof() ) {        NCBI_THROW2(CRegistryException, eErr,                    "Error in reading the registry: '" + str + "'", line);    }    if ( non_modifying ) {        m_Modified = false;    }}/* Write data from reqistry to stream */bool CNcbiRegistry::Write(CNcbiOstream& os)    const{    CFastMutexGuard LOCK(s_RegMutex);    // write file comment    if ( !s_WriteComment(os, m_Comment) )        return false;    // write data    ITERATE (TRegistry, section, m_Registry) {        //        const TRegSection& reg_section = section->second;        _ASSERT( !reg_section.empty() );        // write section comment, if any        TRegSection::const_iterator comm_entry = reg_section.find(kEmptyStr);        if (comm_entry != reg_section.end()  &&            !s_WriteComment(os, comm_entry->second.comment) ) {            return false;        }        // write section header        os << '[' << section->first << ']' << s_Endl;        if ( !os )            return false;        // write section entries        ITERATE (TRegSection, entry, reg_section) {            // if this entry is actually a section comment, then skip it            if (entry == comm_entry)                continue;            // dump only persistent entries            if ( entry->second.persistent.empty() )                continue;            // write entry comment            if ( !s_WriteComment(os, entry->second.comment) )                return false;            // write next entry;  escape all back-slash and new-line symbols;            // add "\\i" to the beginning/end of the string if it has            // spaces there            os << entry->first << " = ";            const char* cs = entry->second.persistent.c_str();            if (isspace(*cs)  &&  *cs != '\n')                os << '"';            for ( ;  *cs;  cs++) {                switch ( *cs ) {                case '\n':                    os << '\\' << s_Endl;  break;                case '\r':                    os << "\\r";  break;                case '\\':                    os << "\\\\";  break;                case '"':                    os << "\\\"";  break;                default:                    os << *cs;                }            }            cs--;            if (isspace(*cs)  &&  *cs != '\n')                os << '"';            os << s_Endl;            if ( !os )                return false;        }    }    m_Modified = false;    m_Written  = true;    return true;}void CNcbiRegistry::Clear(void){    m_Modified = (m_Modified  ||  !x_IsAllTransient());    m_Comment.erase();    m_Registry.clear();}const string& CNcbiRegistry::Get(const string& section, const string& name,                                 TFlags flags)    const{    CHECK_FLAGS("Get", flags, ePersistent);    // Truncate marginal spaces of "section" and "name"    // Make sure they aren't empty and consist of alpanum and '_' only    string x_section = NStr::TruncateSpaces(section);    if ( !s_IsNameSection(x_section) ) {        _TRACE("CNcbiRegistry::Get():  bad or empty section name: " + section);        return kEmptyStr;    }    string x_name = NStr::TruncateSpaces(name);    if ( !s_IsNameSection(x_name) ) {        _TRACE("CNcbiRegistry::Get():  bad or empty entry name: " + name);        return kEmptyStr;    }    CFastMutexGuard LOCK(s_RegMutex);    // find section    TRegistry::const_iterator find_section = m_Registry.find(x_section);    if (find_section == m_Registry.end())        return kEmptyStr;    // find entry in the section    const TRegSection& reg_section = find_section->second;    _ASSERT( !reg_section.empty() );    TRegSection::const_iterator find_entry = reg_section.find(x_name);    if (find_entry == reg_section.end())        return kEmptyStr;    // ok -- found the requested entry    const TRegEntry& entry = find_entry->second;    _ASSERT( !entry.persistent.empty()  ||  !entry.transient.empty() );    return ((flags & ePersistent) == 0  &&  !entry.transient.empty()) ?        entry.transient : entry.persistent;}const string CNcbiRegistry::GetString(const string& section,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -