📄 cdlmisc.cxx
字号:
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); } CYG_REPORT_RETURN(); return;}//}}}//{{{ double_to_string() // ----------------------------------------------------------------------------std::stringCdl::double_to_string(double value, CdlValueFormat format){ std::string result; Cdl::double_to_string(value, result, format); return result;}voidCdl::double_to_string(double value, std::string& result, CdlValueFormat format){ CYG_REPORT_FUNCNAME("Cdl::double_to_String"); char buf[256]; // This should be plenty :-) sprintf(buf, "%.*G", DBL_DIG, value); result = buf; CYG_UNUSED_PARAM(CdlValueFormat, format); CYG_REPORT_RETURN();}//}}}//{{{ bool_to_string() // ----------------------------------------------------------------------------// Should the string results be 1/0 or true/false? Not that// it really matters. The testcase in cdl1.cxx expects 1/0.std::stringCdl::bool_to_string(bool value){ std::string result; Cdl::bool_to_string(value, result); return result;}voidCdl::bool_to_string(bool value, std::string& target){ CYG_REPORT_FUNCNAME("Cdl::bool_to_string"); CYG_REPORT_FUNCARG1( "value arg %ld", (long) value); if (value) target = "1"; else target = "0"; CYG_REPORT_RETURN();}//}}}//{{{ integer_to_double() // ----------------------------------------------------------------------------// Currently integer to double cannot fail, although there may well be loss// of accurary. Eventually cdl_int may be an arbitrary precision integer// in which case conversion to double is not guaranteed.doubleCdl::integer_to_double(cdl_int value){ CYG_REPORT_FUNCNAME("Cdl::integer_to_double"); double result = (double) value; CYG_REPORT_RETURN(); return result;}voidCdl::integer_to_double(cdl_int value, double& target){ CYG_REPORT_FUNCNAME("Cdl::integer_to_double"); target = (double) value; CYG_REPORT_RETURN();}//}}}//{{{ double_to_integer() // Conversion from double to integer is only allowed if there is no loss// of data. modf() is useful hereboolCdl::double_to_integer(double value, cdl_int& target){ CYG_REPORT_FUNCNAMETYPE("Cdl::double_to_integer", "result %d"); bool result = false; double integral; double frac; frac = modf(value, &integral); if (0.0 == frac) { // Looking good, but integral may still be too big. cdl_int tmp = (cdl_int) integral; if (tmp == value) { // No fraction, no loss of data, everything looking good target = tmp; result = true; } } CYG_REPORT_RETVAL(result); return result;}//}}}//}}}//{{{ Cdl::xxx_to_yyy() - CDL-specific data types // ----------------------------------------------------------------------------// Conversions between strings and flavors.static struct { char* name; CdlValueFlavor flavor;} valid_flavors[] = { { "none", CdlValueFlavor_None }, { "bool", CdlValueFlavor_Bool }, { "booldata", CdlValueFlavor_BoolData }, { "data", CdlValueFlavor_Data }, { 0, CdlValueFlavor_Invalid }};boolCdl::string_to_flavor(std::string name, CdlValueFlavor& target){ CYG_REPORT_FUNCNAMETYPE("Cdl::string_to_flavor", "success %d"); bool result = false; // First convert the argument to lower case. Arguably this is incorrect, // Tcl is a case-sensitive language, but the conversion is unlikely ever // to be harmfull. for (std::string::iterator str_i = name.begin(); str_i != name.end(); str_i++) { if (isupper(*str_i)) { *str_i = tolower(*str_i); } } // Now look for a match in the table. int match = -1; int i; const char* c_str = name.c_str(); int len = strlen(c_str); for (i = 0; 0 != valid_flavors[i].name; i++) { if (0 == strncmp(c_str, valid_flavors[i].name, len)) { // Check for an ambiguous string match. // This cannot actually happen with the current flavor names. if ( -1 != match) { break; } match = i; } } if (-1 != match) { target = valid_flavors[match].flavor; result = true; } CYG_REPORT_RETVAL(result); return result;}boolCdl::flavor_to_string(CdlValueFlavor flavor, std::string& target){ CYG_REPORT_FUNCNAMETYPE("Cdl::flavor_to_string", "success %d"); bool result = false; for (int i = 0; 0 != valid_flavors[i].name; i++) { if (flavor == valid_flavors[i].flavor) { target = valid_flavors[i].name; result = true; break; } } CYG_REPORT_RETVAL(result); return result;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -