📄 corbafixed.cc
字号:
// -*- Mode: C++; -*-// Package : omniORB// corbaFixed.cc Created on: 07/02/2001// Author : Duncan Grisby (dpg1)//// Copyright (C) 2001 AT&T Laboratories Cambridge//// This file is part of the omniORB library//// The omniORB library is free software; you can redistribute it and/or// modify it under the terms of the GNU Library General Public// License as published by the Free Software Foundation; either// version 2 of the License, or (at your option) any later version.//// This library 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// Library General Public License for more details.//// You should have received a copy of the GNU Library General Public// License along with this library; if not, write to the Free// Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA// 02111-1307, USA////// Description://// Implementation of the fixed point type// $Log: corbaFixed.cc,v $// Revision 1.1.2.18 2005/03/29 16:09:48 dgrisby// Copying too many digits if truncating a fixed point value.//// Revision 1.1.2.17 2005/03/03 12:45:56 dgrisby// Bug in fixed point multiplication. Thanks Simone Viani.//// Revision 1.1.2.16 2004/10/17 20:14:32 dgrisby// Updated support for OpenVMS. Many thanks to Bruce Visscher.//// Revision 1.1.2.15 2004/07/23 13:22:53 dgrisby// Fixed point rounding was still broken.//// Revision 1.1.2.14 2004/07/01 19:15:17 dgrisby// Fix fixed point. It was broken point. Thanks Simone Viani.//// Revision 1.1.2.13 2003/06/02 13:26:14 dgrisby// Silly bug in fixed division when result has leading zeros.//// Revision 1.1.2.12 2003/02/25 12:35:20 dgrisby// Typo in assertion.//// Revision 1.1.2.11 2002/11/25 21:07:25 dgrisby// Add new to_string() function to Fixed.//// Revision 1.1.2.10 2002/07/12 10:17:30 dgrisby// Bug in fixed point unmarshal.//// Revision 1.1.2.9 2002/01/21 17:40:05 dpg1// Lost sign in Fixed->double conversion. (Thanks Slava Garelin)//// Revision 1.1.2.8 2001/11/14 17:13:43 dpg1// Long double support.//// Revision 1.1.2.7 2001/11/08 16:33:51 dpg1// Local servant POA shortcut policy.//// Revision 1.1.2.6 2001/10/17 16:44:06 dpg1// Update DynAny to CORBA 2.5 spec, const Any exception extraction.//// Revision 1.1.2.5 2001/08/17 13:47:32 dpg1// Small bug fixes.//// Revision 1.1.2.4 2001/08/03 17:41:18 sll// System exception minor code overhaul. When a system exeception is raised,// a meaning minor code is provided.//// Revision 1.1.2.3 2001/06/13 20:12:32 sll// Minor updates to make the ORB compiles with MSVC++.//// Revision 1.1.2.2 2001/04/09 15:18:46 dpg1// Tweak fixed point to make life easier for omniORBpy.//// Revision 1.1.2.1 2001/03/13 10:32:10 dpg1// Fixed point support.//#include <omniORB4/CORBA.h>#include <exceptiondefs.h>#include <stdio.h>#include <string.h>#include <ctype.h>OMNI_USING_NAMESPACE(omni)CORBA::Fixed::Fixed(int val) : pd_digits(0), pd_scale(0), pd_negative(0), pd_idl_digits(0), pd_idl_scale(0){ if (val < 0) { pd_negative = 1; val = - val; } while (val) { pd_val[pd_digits++] = val % 10; val /= 10; } memset(pd_val + pd_digits, 0, OMNI_FIXED_DIGITS - pd_digits);}CORBA::Fixed::Fixed(unsigned val) : pd_digits(0), pd_scale(0), pd_negative(0), pd_idl_digits(0), pd_idl_scale(0){ while (val) { pd_val[pd_digits++] = val % 10; val /= 10; } memset(pd_val + pd_digits, 0, OMNI_FIXED_DIGITS - pd_digits);}#ifndef OMNI_LONG_IS_INTCORBA::Fixed::Fixed(CORBA::Long val) : pd_digits(0), pd_scale(0), pd_negative(0), pd_idl_digits(0), pd_idl_scale(0){ if (val < 0) { pd_negative = 1; val = - val; } while (val) { pd_val[pd_digits++] = val % 10; val /= 10; } memset(pd_val + pd_digits, 0, OMNI_FIXED_DIGITS - pd_digits);}CORBA::Fixed::Fixed(CORBA::ULong val) : pd_digits(0), pd_scale(0), pd_negative(0), pd_idl_digits(0), pd_idl_scale(0){ while (val) { pd_val[pd_digits++] = val % 10; val /= 10; } memset(pd_val + pd_digits, 0, OMNI_FIXED_DIGITS - pd_digits);}#endif#ifdef HAS_LongLongCORBA::Fixed::Fixed(CORBA::LongLong val) : pd_digits(0), pd_scale(0), pd_negative(0), pd_idl_digits(0), pd_idl_scale(0){ if (val < 0) { pd_negative = 1; val = - val; } while (val) { pd_val[pd_digits++] = val % 10; val /= 10; } memset(pd_val + pd_digits, 0, OMNI_FIXED_DIGITS - pd_digits);}CORBA::Fixed::Fixed(CORBA::ULongLong val) : pd_digits(0), pd_scale(0), pd_negative(0), pd_idl_digits(0), pd_idl_scale(0){ while (val) { pd_val[pd_digits++] = val % 10; val /= 10; } memset(pd_val + pd_digits, 0, OMNI_FIXED_DIGITS - pd_digits);}#endif#ifndef NO_FLOATCORBA::Fixed::Fixed(CORBA::Double val) : pd_idl_digits(0), pd_idl_scale(0){ if ((double)val > 1e32 || (double)val < -1e32) { // Too big OMNIORB_THROW(DATA_CONVERSION, DATA_CONVERSION_RangeError, CORBA::COMPLETED_NO); } char buffer[80]; int len = sprintf(buffer, "%.31f", val); OMNIORB_ASSERT(len < 79); NP_fromString(buffer);}#endif#ifdef HAS_LongDoubleCORBA::Fixed::Fixed(CORBA::LongDouble val) : pd_idl_digits(0), pd_idl_scale(0){ if (val > 1e32 || val < -1e32) { // Too big / small OMNIORB_THROW(DATA_CONVERSION, DATA_CONVERSION_RangeError, CORBA::COMPLETED_NO); } char buffer[80]; int len = sprintf(buffer, "%.31f", (double)val); OMNIORB_ASSERT(len < 79); NP_fromString(buffer);}#endifCORBA::Fixed::Fixed(const Fixed& val) : pd_digits (val.pd_digits), pd_scale (val.pd_scale), pd_negative (val.pd_negative), pd_idl_digits(0), pd_idl_scale (0){ memcpy(pd_val, val.pd_val, OMNI_FIXED_DIGITS);}CORBA::Fixed::Fixed(const char* val) : pd_idl_digits(0), pd_idl_scale(0){ NP_fromString(val);}CORBA::Fixed::Fixed(const CORBA::Octet* val, CORBA::UShort digits, CORBA::UShort scale, CORBA::Boolean negative) : pd_digits(digits), pd_scale(scale), pd_negative(negative), pd_idl_digits(0), pd_idl_scale(0){ OMNIORB_ASSERT(digits <= OMNI_FIXED_DIGITS); OMNIORB_ASSERT(scale <= digits); while (pd_digits > 0 && pd_scale > 0 && val[0] == 0) { pd_digits--; pd_scale--; val++; } if (pd_digits == 0) pd_negative = 0; memcpy(pd_val, val, pd_digits); memset(pd_val + pd_digits, 0, OMNI_FIXED_DIGITS - pd_digits);}CORBA::Fixed::~Fixed(){}#ifdef HAS_LongLongCORBA::Fixed::operator CORBA::LongLong() const{ CORBA::LongLong r = 0, s; for (int i = pd_digits - 1; i >= pd_scale; --i) { s = r * 10 + pd_val[i]; if (s < r) { // Overflow OMNIORB_THROW(DATA_CONVERSION, DATA_CONVERSION_RangeError, CORBA::COMPLETED_NO); } r = s; } if (pd_negative) r = -r; return r;}#elseCORBA::Fixed::operator CORBA::Long() const{ CORBA::Long r = 0, s; for (int i = pd_digits - 1; i >= pd_scale; --i) { s = r * 10 + pd_val[i]; if (s < r) { // Overflow OMNIORB_THROW(DATA_CONVERSION, DATA_CONVERSION_RangeError, CORBA::COMPLETED_NO); } r = s; } if (pd_negative) r = -r; return r;}#endif#ifndef NO_FLOAT# ifdef HAS_LongDoubleCORBA::Fixed::operator CORBA::LongDouble() const{ CORBA::LongDouble r = 0, s = 0; int i; // Digits before decimal point for (i = pd_digits - 1; i >= pd_scale; --i) { r = r * 10 + pd_val[i]; } // Digits after decimal point for (i=0; i < pd_scale; ++i) { s = (s + pd_val[i]) / 10; } if (pd_negative) return -(r + s); else return r + s;}# elseCORBA::Fixed::operator CORBA::Double() const{#ifdef __VMS double r = 0, s = 0;#else CORBA::Double r = 0, s = 0;#endif int i; // Digits before decimal point for (i = pd_digits - 1; i >= pd_scale; --i) { r = r * 10 + pd_val[i]; } // Digits after decimal point for (i=0; i < pd_scale; ++i) { s = (s + pd_val[i]) / 10; } if (pd_negative) return -(r + s); else return r + s;}# endif#endifCORBA::FixedCORBA::Fixed::round(CORBA::UShort scale) const{ if (scale >= pd_scale) return *this; int cut = pd_scale - scale; if (pd_val[cut - 1] >= 5) { // Round up CORBA::Octet work[OMNI_FIXED_DIGITS + 1]; memcpy(work, pd_val, OMNI_FIXED_DIGITS); work[OMNI_FIXED_DIGITS] = 0; int i = cut; for (i = cut; i <= OMNI_FIXED_DIGITS; ++i) { if (++work[i] <= 9) break; work[i] = 0; } int new_digits = pd_digits - cut; if (i >= pd_digits) new_digits++; return CORBA::Fixed(work + cut, new_digits, scale, pd_negative); } else return CORBA::Fixed(pd_val + cut, pd_digits - cut, scale, pd_negative);}CORBA::FixedCORBA::Fixed::truncate(CORBA::UShort scale) const{ if (scale >= pd_scale) return *this; int cut = pd_scale - scale; int newscale = scale; while (pd_val[cut] == 0 && newscale > 0) { ++cut; --newscale; } return CORBA::Fixed(pd_val + cut, pd_digits - cut, newscale, pd_negative);}CORBA::Fixed&CORBA::Fixed::operator=(const Fixed& val){ pd_digits = val.pd_digits; pd_scale = val.pd_scale; pd_negative = val.pd_negative; memcpy(pd_val, val.pd_val, OMNI_FIXED_DIGITS); PR_checkLimits(); return *this;}CORBA::Fixed&CORBA::Fixed::operator+=(const Fixed& val){ *this = *this + val; return *this;}CORBA::Fixed&CORBA::Fixed::operator-=(const Fixed& val){ *this = *this - val; return *this;}CORBA::Fixed&CORBA::Fixed::operator*=(const Fixed& val){ *this = *this * val; return *this;}CORBA::Fixed&CORBA::Fixed::operator/=(const Fixed& val){ *this = *this / val; return *this;}CORBA::Fixed&CORBA::Fixed::operator++(){ *this = *this + CORBA::Fixed(1); return *this;}CORBA::FixedCORBA::Fixed::operator++(int){ CORBA::Fixed r(*this); *this = *this + CORBA::Fixed(1); return r;}CORBA::Fixed&CORBA::Fixed::operator--(){ *this = *this - CORBA::Fixed(1); return *this;}CORBA::FixedCORBA::Fixed::operator--(int){ CORBA::Fixed r(*this); *this = *this - CORBA::Fixed(1); return r;}CORBA::FixedCORBA::Fixed::operator+() const{ return *this;}CORBA::FixedCORBA::Fixed::operator-() const{ if (pd_digits == 0) return *this; CORBA::Fixed r(*this); r.pd_negative = !pd_negative; return r;}CORBA::BooleanCORBA::Fixed::operator!() const{ return pd_digits == 0;}char*CORBA::Fixed::to_string() const{ int len = pd_digits + 1; if (pd_negative) ++len; // for '-' if (pd_digits == pd_scale) ++len; // for '0' if (pd_scale > 0 || pd_idl_scale > 0) ++len; // for '.' if (pd_idl_scale > pd_scale) len += pd_idl_scale - pd_scale; char* r = CORBA::string_alloc(len); int i = 0, j; if (pd_negative) r[i++] = '-'; if (pd_digits == pd_scale) r[i++] = '0'; for (j=pd_digits; j; ) { if (j-- == pd_scale) r[i++] = '.'; r[i++] = pd_val[j] + '0'; } if (pd_idl_scale > pd_scale) { if (pd_scale == 0) r[i++] = '.'; for (j = pd_idl_scale - pd_scale; j; j--) r[i++] = '0'; } r[i] = '\0'; return r;}char*CORBA::Fixed::NP_asString() const{ int len = pd_digits + 1; if (pd_negative) ++len; // for '-' if (pd_digits == pd_scale) ++len; // for '0' if (pd_scale > 0) ++len; // for '.' char* r = CORBA::string_alloc(len); int i = 0, j; if (pd_negative) r[i++] = '-'; if (pd_digits == pd_scale) r[i++] = '0'; for (j=pd_digits; j; ) { if (j-- == pd_scale) r[i++] = '.'; r[i++] = pd_val[j] + '0'; } r[i] = '\0'; return r;}CORBA::BooleanCORBA::Fixed::NP_fromString(const char* s, CORBA::Boolean ignore_end){ CORBA::Boolean precise = 1; // Skip leading white space while (isspace(*s)) ++s; // Sign if (*s == '-') { pd_negative = 1; ++s; } else if (*s == '+') { pd_negative = 0; ++s; } else pd_negative = 0; // Check there are some digits if (!((*s >= '0' && *s <= '9') || *s == '.')) { OMNIORB_THROW(DATA_CONVERSION, DATA_CONVERSION_BadInput, CORBA::COMPLETED_NO); } // Skip leading zeros: while (*s == '0') ++s; int i, j, unscale = -1; // Count digits for (i=0, pd_digits=0; (s[i] >= '0' && s[i] <= '9') || s[i] == '.'; ++i) { if (s[i] == '.') { if (unscale != -1) { // Already seen a decimal point OMNIORB_THROW(DATA_CONVERSION, DATA_CONVERSION_BadInput, CORBA::COMPLETED_NO); } unscale = pd_digits; } else ++pd_digits; } if (unscale == -1) unscale = pd_digits; pd_scale = pd_digits - unscale; // Check there is no trailing garbage if (!ignore_end) { j = i; if (s[i] == 'd' || s[i] == 'D') ++j; while (s[j]) { if (!isspace(s[j])) { OMNIORB_THROW(DATA_CONVERSION, DATA_CONVERSION_BadInput, CORBA::COMPLETED_NO); } ++j; } } --i; // i is now the index of the last digit // Truncate if too many digits while (pd_digits > OMNI_FIXED_DIGITS && pd_scale > 0) { precise = 0; --i; --pd_digits; --pd_scale; } // Back-up over trailing zeros if (pd_scale > 0) { while (s[i] == '0') { --i; --pd_digits; --pd_scale; } } if (pd_digits > OMNI_FIXED_DIGITS) { OMNIORB_THROW(DATA_CONVERSION, DATA_CONVERSION_RangeError, CORBA::COMPLETED_NO); } // Scan back through the string, setting the value least // siginificant digit first. for (j=0; j < pd_digits; ++j, --i) { if (s[i] == '.') --i; pd_val[j] = s[i] - '0'; } // Clear any remaining digits memset(pd_val + j, 0, OMNI_FIXED_DIGITS - j); // Make sure zero is always positive if (pd_digits == 0) pd_negative = 0; return precise && PR_checkLimits();}voidCORBA::Fixed::PR_setLimits(UShort idl_digits, UShort idl_scale){ OMNIORB_ASSERT(idl_digits <= 31); OMNIORB_ASSERT(idl_scale <= idl_digits); pd_idl_digits = idl_digits; pd_idl_scale = idl_scale; PR_checkLimits();}CORBA::BooleanCORBA::Fixed::PR_checkLimits(){ if (pd_idl_digits == 0) return 1; if (pd_scale > pd_idl_scale) { *this = truncate(pd_idl_scale); return 0; } if (pd_digits - pd_scale > pd_idl_digits - pd_idl_scale)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -