Пример #1
0
  //---------------------------------------------------------------------------
  IValue& Value::operator+=(const IValue &val)
  {
    if (IsScalar() && val.IsScalar())
    {
      // Scalar/Scalar addition
      m_val += val.GetComplex();
      m_cType = (m_val.imag()==0) ? ( (m_val.real()==(int)m_val.real()) ? 'i' : 'f' ) : 'c';
    }
    else if (IsMatrix() && val.IsMatrix())
    {
      // Matrix/Matrix addition
      assert(m_pvVal);
      *m_pvVal += val.GetArray();
    }
    else if (IsString() && val.IsString())
    {
      // string/string addition
      assert(m_psVal);
      *m_psVal += val.GetString();
    }
    else
    {
      // Type conflict
      throw ParserError(ErrorContext(ecTYPE_CONFLICT_FUN, -1, _T("+"), GetType(), val.GetType(), 2));
    }

    return *this;
  }
Пример #2
0
  /** \brief Assign a value with multiplication
      \param val The value to multiply to this

    When multiplying to values with each value representing a matrix type
    the result is checked whether it is a 1 x 1 matrix. If so the value is
    "unboxed" and stored directly in this value object. It is no longer 
    treated as a matrix internally.
  */
  IValue& Value::operator*=(const IValue &val)
  {
    if (IsScalar() && val.IsScalar())
    {
      // Scalar/Scalar multiplication
      m_val *= val.GetComplex();
      m_cType = (m_val.imag()==0) ? ( (m_val.real()==(int)m_val.real()) ? 'i' : 'f' ) : 'c';
    }
    else if (IsMatrix() && val.IsMatrix())
    {
      // Matrix/Matrix addition
      assert(m_pvVal);
      *m_pvVal *= val.GetArray();

      // The result may actually be a scalar value, i.e. the scalar product of
      // two vectors.
      if (m_pvVal->GetCols()==1 && m_pvVal->GetRows()==1)
      {
        Assign(m_pvVal->At(0,0));
      }
    }
    else if ( IsMatrix() && val.IsScalar() )
    {
      *m_pvVal *= val;
    }
    else if ( IsScalar() * val.IsMatrix() )
    {
      // transform this into a matrix and multiply with rhs
      Value prod = val * (*this);
      Assign(prod);
    }
    else
    {
      // Type conflict
      ErrorContext errc(ecTYPE_CONFLICT_FUN, -1, _T("*"));
      errc.Type1 = GetType();
      errc.Type2 = 'm'; //val.GetType();
      errc.Arg = 2;
      throw ParserError(errc);
    }

    return *this;
  }
Пример #3
0
  //---------------------------------------------------------------------------
  IValue& Value::At(int nRow, int nCol)
  {
    if (IsMatrix())
    {
      if (nRow>=m_pvVal->GetRows() || nCol>=m_pvVal->GetCols() || nRow<0 || nCol<0)
        throw ParserError( ErrorContext(ecINDEX_OUT_OF_BOUNDS, -1, GetIdent()) ); 

      return m_pvVal->At(nRow, nCol);
    }
    else if (nRow==0 && nCol==0)
    {
      return *this;
    }
    else
      throw ParserError( ErrorContext(ecINDEX_OUT_OF_BOUNDS) ); 
  }
Пример #4
0
bool SetPropertyFromNode( const TreeNode& node, Property::Value& value,
                          const Replacement& replacer )
{
  bool done = false;

  // some values are ambiguous as we have no Property::Type but can be disambiguated in the json

  // Currently Rotations and Rectangle must always be disambiguated when a type isnt available
  if( Disambiguated( node, value, replacer ) )
  {
    done = true;
  }
  else
  {
    if( node.Size() )
    {
      // our current heuristic for deciding an array is actually a vector and not say a map
      // is to check if the values are all floats
      bool allNumbers = true;
      for(TreeConstIter iter = node.CBegin(); iter != node.CEnd(); ++iter)
      {
        OptionalFloat f = IsFloat((*iter).second);
        if(!f)
        {
          allNumbers = false;
          break;
        }
      }

      if( allNumbers )
      {
        // prefer finding vectors over presuming composite Property::Array...
        if( OptionalMatrix v = IsMatrix(node) )
        {
          value = *v;
          done = true;
        }
        else if( OptionalMatrix3 v = IsMatrix3(node) )
        {
          value = *v;
          done = true;
        }
        else if( OptionalVector4 v = IsVector4(node) )
        {
          value = *v;
          done = true;
        }
        else if( OptionalVector3 v = IsVector3(node) )
        {
          value = *v;
          done = true;
        }
        else if( OptionalVector2 v = IsVector2(node) )
        {
          value = *v;
          done = true;
        }
        else if( 4 == node.Size() )
        {
          if( OptionalVector4 v = IsVector4(node) )
          {
            value = *v;
            done = true;
          }
        }
        else
        {
          value = Property::Value(Property::ARRAY);
          Property::Array* array = value.GetArray();

          if( array )
          {
            for(TreeConstIter iter = node.CBegin(); iter != node.CEnd(); ++iter)
            {
              Property::Value childValue;
              if( SetPropertyFromNode( (*iter).second, childValue, replacer ) )
              {
                array->PushBack( childValue );
                done = true;
              }
            }
          }
        }
      }

      if(!done)
      {
        // presume an array or map
        // container of size 1
        TreeNode::ConstIterator iter = node.CBegin();

        // its seems legal with current json parser for a map to have an empty key
        // but here we take that to mean the structure is a list
        if( ((*iter).first) == 0 )
        {
          value = Property::Value(Property::ARRAY);
          Property::Array* array = value.GetArray();

          if( array )
          {
            for(unsigned int i = 0; i < node.Size(); ++i, ++iter)
            {
              Property::Value childValue;
              if( SetPropertyFromNode( (*iter).second, childValue, replacer ) )
              {
                array->PushBack( childValue );
                done = true;
              }
            }
          }
        }
        else
        {
          value = Property::Value(Property::MAP);
          Property::Map* map = value.GetMap();

          if( map )
          {
            for(unsigned int i = 0; i < node.Size(); ++i, ++iter)
            {
              Property::Value childValue;
              if( SetPropertyFromNode( (*iter).second, childValue, replacer ) )
              {
                map->Insert( (*iter).first, childValue );
                done = true;
              }
            }
          }
        }
      } // if!done
    } // if node.size()
    else // if( 0 == node.size() )
    {
      // no children so either one of bool, float, integer, string
      OptionalBoolean aBool    = replacer.IsBoolean(node);
      OptionalInteger anInt    = replacer.IsInteger(node);
      OptionalFloat   aFloat   = replacer.IsFloat(node);
      OptionalString  aString  = replacer.IsString(node);

      if(aBool)
      {
        // a bool is also an int but here we presume int
        if(anInt)
        {
          value = *anInt;
          done = true;
        }
        else
        {
          value = *aBool;
          done = true;
        }
      }
      else
      {
        // Note: These are both floats and strings
        // {"value":"123"}
        // {"value":123}
        // This means we can't have a string with purely numeric content without disambiguation.
        if(aFloat)
        {
          value = *aFloat;
          done = true;
        }
        else if(anInt)
        {
          value = *anInt;
          done = true;
        }
        else
        {
          // string always succeeds with the current json parser so its last
          value = *aString;
          done = true;
        }

      } // if aBool

    } // if( node.size() )

  } // if Disambiguated()

  return done;
} // bool SetPropertyFromNode( const TreeNode& node, Property::Value& value )