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

📄 cdlmisc.cxx

📁 eCos1.31版
💻 CXX
📖 第 1 页 / 共 2 页
字号:
//{{{  Banner                                                   //============================================================================////      cdlmisc.cxx////      Implementation of the various CDL utility member functions.////============================================================================//####COPYRIGHTBEGIN####//                                                                          // ----------------------------------------------------------------------------// Copyright (C) 1998, 1999, 2000 Red Hat, Inc.//// This file is part of the eCos host tools.//// This program is free software; you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by the Free // Software Foundation; either version 2 of the License, or (at your option) // any later version.// // This program is distributed in the hope that it will be useful, but WITHOUT // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for // more details.// // You should have received a copy of the GNU General Public License along with// this program; if not, write to the Free Software Foundation, Inc., // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.//// ----------------------------------------------------------------------------//                                                                          //####COPYRIGHTEND####//============================================================================//#####DESCRIPTIONBEGIN####//// Author(s):   bartv// Contact(s):  bartv// Date:        1998/03/04// Version:     0.01////####DESCRIPTIONEND####//============================================================================//}}}//{{{  #include's                                               // ----------------------------------------------------------------------------#include "cdlconfig.h"// Get the infrastructure types, assertions, tracing and similar// facilities.#include <cyg/infra/cyg_ass.h>#include <cyg/infra/cyg_trac.h>// <cdlcore.hxx> defines everything implemented in this module.// It implicitly supplies <string>, <vector> and <map> because// the class definitions rely on these headers.#include <cdlcore.hxx>// For access to the isdigit(), isupper(), tolower(), ... functions#include <cctype>// For access to sprintf(), specifically double to string conversions.#include <cstdio>// For access to strtod()#include <cstdlib>// strtod() involves errno...#include <cerrno>// For access to fmod()#include <cmath>// For access to DBL_DIG#include <cfloat>//}}}//{{{  Cdl::is_valid_xxx()                                      // ---------------------------------------------------------------------------boolCdl::is_valid_value_flavor(CdlValueFlavor data){    bool result = false;    switch(data) {      case CdlValueFlavor_None     :      case CdlValueFlavor_Bool     :      case CdlValueFlavor_BoolData :      case CdlValueFlavor_Data     :        result = true;        break;      default:        break;    }    return result;}boolCdl::is_valid_value_source(CdlValueSource data){    bool result = false;    switch(data) {      case CdlValueSource_Default         :      case CdlValueSource_User            :      case CdlValueSource_Wizard          :      case CdlValueSource_Inferred        :        result = true;        break;      default:        break;    }    return result;}// ----------------------------------------------------------------------------// For now CDL names are restricted to what is acceptable to the C// preprocessor. This may cause problems in future, e.g. i18n.boolCdl::is_valid_cdl_name(const std::string& name){    CYG_REPORT_FUNCNAMETYPE("Cdl::is_valid_cdl_name", "result %d");    bool result = is_valid_c_preprocessor_symbol(name);        CYG_REPORT_RETVAL(result);    return result;}boolCdl::is_valid_c_preprocessor_symbol(const std::string& symbol){    CYG_REPORT_FUNCNAMETYPE("Cdl::is_valid_c_preprocessor_symbol", "result %d");    bool result = true;    if ("" == symbol) {        result = false;    } else {        // A valid preprocessor symbol should begin with either an underscore        // or a letter. It should then be followed by some number of underscores,        // letters, or digits.        //        // In some locales isalpha() may succeed for characters which are not        // legal for C preprocessor symbols. Instead ASCII is assumed here.        if (('_' != symbol[0]) &&            !(('a' <= symbol[0]) && (symbol[0] <= 'z')) &&            !(('A' <= symbol[0]) && (symbol[0] <= 'Z'))) {                        result = false;        } else {            for (unsigned int i = 1; i < symbol.size(); i++) {                if (('_' != symbol[i]) &&                    !(('a' <= symbol[i]) && (symbol[i] <= 'z')) &&                    !(('A' <= symbol[i]) && (symbol[i] <= 'Z')) &&                    !(('0' <= symbol[i]) && (symbol[i] <= '9'))) {                                        result = false;                    break;                }            }        }    }    CYG_REPORT_RETVAL(result);    return result;}//}}}//{{{  Cdl::xxx_to_yyy() - strings, ints, doubles, ...          // ---------------------------------------------------------------------------// Conversion routines between strings, integers, doubles, bools, ...//// Conversions to/from integers are complicated somewhat because the// data type in question is cdl_int. In the initial implementation this// is 64 bits. In the long term it will be arbitrary precision and// the conversion routines will need to be reimplemented.//// ASCII rather than EBCDIC is assumed.//// Some of the routines may fail, e.g. string to integer conversions.// Others are guaranteed to succeed. //{{{  string_to_integer()                      // ----------------------------------------------------------------------------boolCdl::string_to_integer(std::string data, cdl_int& target){    CYG_REPORT_FUNCNAMETYPE("Cdl::string_to_integer", "success %d");    bool negative       = false;    // Life is a bit easier if I can check for '\0'    const char* ptr           = data.c_str();    // Not essential but harmless.    while (isspace(*ptr))        ptr++;    if ('-' == *ptr) {        negative = true;        ptr++;    }    cdl_int acc = 0;    if ('0' == *ptr) {        // This happens sufficiently often to be worth a special case.        if ('\0' == ptr[1]) {            target = 0;            CYG_REPORT_RETVAL(true);            return true;        }        // Hex is always worth supporting.         if (('x' == ptr[1]) || ('X' == ptr[1])) {            ptr++; ptr++;            if (!isxdigit(*ptr)) {                CYG_REPORT_RETVAL(false);                return false;            }            while (isxdigit(*ptr)) {                cdl_int new_acc = acc * 16;                if (isdigit(*ptr)) {                    new_acc += (*ptr - '0');                } else if (('a' <= *ptr) && (*ptr <= 'f')) {                    new_acc += (*ptr + 10 - 'a');                } else if (('A' <= *ptr) && (*ptr <= 'F')) {                    new_acc += (*ptr + 10 - 'A');                } else {                    CYG_FAIL("this platform's implementation of isxdigit() is broken");                }                if (new_acc < acc) {                    CYG_REPORT_RETVAL(false);                    return false;                }                acc = new_acc;                ptr++;            }            if ('\0' != *ptr) {                CYG_REPORT_RETVAL(false);                return false;            }            if (negative) {                cdl_int new_acc = 0 - acc;                if (new_acc > 0) {                    CYG_REPORT_RETVAL(false);                    return false;                } else {                    acc = new_acc;                }            }            target = acc;            CYG_REPORT_RETVAL(true);            return true;        }        // Octal? Oh well, might as well be complete.        if (('0' <= ptr[1]) && (ptr[1] <= '7')) {            ptr++;            do {                cdl_int new_acc = 8 * acc;                new_acc += (*ptr - '0');                if (new_acc < acc) {                    CYG_REPORT_RETVAL(false);                    return false;                }                acc = new_acc;                ptr++;            } while (('0' <= *ptr) && (*ptr <= '7'));            if ('\0' != *ptr) {                CYG_REPORT_RETVAL(false);                return false;            }            if (negative) {                cdl_int new_acc = 0 - acc;                if (new_acc > 0) {                    CYG_REPORT_RETVAL(false);                    return false;                }                else {                    acc = new_acc;                }            }            target = acc;            CYG_REPORT_RETVAL(true);            return true;        }        // Drop through for the case of a decimal.    }    while(isdigit(*ptr)) {        cdl_int new_acc = 10 * acc;        new_acc += (*ptr - '0');        if (new_acc < acc) {            CYG_REPORT_RETVAL(false);            return false;        }        acc = new_acc;        ptr++;    }    if ('\0' != *ptr) {        CYG_REPORT_RETVAL(false);        return false;    }    if (negative) {        cdl_int new_acc = 0 - acc;        if (new_acc > 0) {            CYG_REPORT_RETVAL(false);            return false;        } else {            acc = new_acc;        }    }    target = acc;    CYG_REPORT_RETVAL(true);    return true;}//}}}//{{{  string_to_double()                       // ----------------------------------------------------------------------------// There is no point in doing this the hard way, just use standard// library calls.//// There is an obvious question as to how much precision can get lost// doing the conversion to a string. In practice this should not matter// too much, since the expression handling code generally keeps the// original double precision lying around to be re-used. However it may// be desirable to keep the libcdl behaviour in synch with Tcl's// tcl_precision variable.boolCdl::string_to_double(std::string value, double& target){    CYG_REPORT_FUNCNAMETYPE("Cdl::string_to_double", "success %d");    bool        result      = true;    const char* start_ptr   = value.c_str();    char*       end_ptr;    int         old_errno   = errno;        errno                   = 0;    double conv             = strtod(start_ptr, &end_ptr);    if (0 != errno) {        CYG_ASSERT(ERANGE == errno, "standard-compliant C library");        result = false;    } else if ('\0' != *end_ptr) {        result = false;    } else {        target = conv;        result = true;    }         errno = old_errno;    CYG_REPORT_RETVAL(result);    return result;}//}}}//{{{  string_to_bool()                         // ----------------------------------------------------------------------------// Conversions to and from bools. The only real issue here is exactly// what strings should be accepted as synonyms for true and false.// It is not actually clear that these functions are useful.boolCdl::string_to_bool(std::string data, bool& target){    CYG_REPORT_FUNCNAMETYPE("Cdl::string_to_bool", "success %d");    // Arguably there should be a precondition ( "" != data )    bool result = false;    // What is truth ?    if (( data == "1"   ) || (data == "true") ||        ( data == "True") || (data == "TRUE") ) {        result = true;        target = true;    } else if ((data == "0"    ) || (data == "false") ||               (data == "False") || (data == "FALSE") ) {        result = true;        target = false;    }    CYG_REPORT_RETVAL(result);    return result;}//}}}//{{{  integer_to_string()                      // ----------------------------------------------------------------------------std::stringCdl::integer_to_string(cdl_int value, CdlValueFormat format){    std::string result;    Cdl::integer_to_string(value, result, format);    return result;}voidCdl::integer_to_string(cdl_int value, std::string& target, CdlValueFormat format){    CYG_REPORT_FUNCNAME("Cdl::integer_to_string");    CYG_REPORT_FUNCARG2XV((long) value, format);    // Optimise this special case.    if (0 == value) {        if (CdlValueFormat_Hex == format) {            target = "0x0";        } else {            target = "0";        }        CYG_REPORT_RETVAL(true);        return;    }    // A local buffer to construct partial strings. This avoids    // unnecessary std::string reallocation.    // 64 bits and three bits at a time for octal numbers gives 21 digits,    // plus spares for the leading '0' and the terminator.    char local_buf[24];    char *local_ptr = &(local_buf[23]);    *local_ptr-- = '\0';        if (CdlValueFormat_Hex == format) {        // Output the data as 0x... with either 8 or 16 digits,        // depending on the size.        int i;        for (i = 0; i < 8; i++) {            int tmp = (int) (value & 0x0F);            value   = value >> 4;            if (tmp < 10) {                *local_ptr-- = '0' + tmp;            } else {                *local_ptr-- = 'A' + (tmp - 10);            }        }        // Beware of right shifts that preserve the sign bit.        {            int tmp1 = (value & 0x0FFFF);            int tmp2 = ((value >> 16) & 0x0FFFF);            value    = (tmp2 << 16) + tmp1;        }        if (value != 0) {            for (i = 0; i < 8; i++) {                int tmp = (int) (value & 0x0F);                value   = value >> 4;                if (tmp < 10) {                    *local_ptr-- = '0' + tmp;                } else {                    *local_ptr-- = 'A' + (tmp - 10);                }            }        }        *local_ptr-- = 'x';        *local_ptr   = '0';        target = std::string(local_ptr);            } else if (CdlValueFormat_Octal == format) {        // Simply output the data three bits at a time, do not worry about any        // particular width restrictions. However it is necessary to worry        // about masking.        cdl_int mask = 0x1FFFFFFF;        mask = (mask << 16) | 0x0FFFF;        mask = (mask << 16) | 0x0FFFF;        target = "";        while (value > 0) {            int tmp = value & 0x07;            value   = (value >> 3) & mask;            *local_ptr-- = '0' + tmp;        }        *local_ptr = '0';        target = std::string(local_ptr);            } else {        // A simple decimal number              // Switch to positive arithmetic.        bool negative = false;        if (value < 0) {            negative = true;            value    = 0 - value;            // Only MININT cannot be converted using the above line            if (value < 0) {                target = "-9223372036854775808";                CYG_REPORT_RETVAL(true);                return;            }        }        while (value > 0) {            int rem = (int) (value % 10);            value   = value / 10;            *local_ptr-- = '0' + rem;        }        if (negative) {            *local_ptr-- = '-';        }        local_ptr++;        target = std::string(local_ptr);    }

⌨️ 快捷键说明

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