Drizzled Public API Documentation

float.cc

00001 /* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
00002  *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
00003  *
00004  *  Copyright (C) 2008 Sun Microsystems, Inc.
00005  *
00006  *  This program is free software; you can redistribute it and/or modify
00007  *  it under the terms of the GNU General Public License as published by
00008  *  the Free Software Foundation; version 2 of the License.
00009  *
00010  *  This program is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  *  GNU General Public License for more details.
00014  *
00015  *  You should have received a copy of the GNU General Public License
00016  *  along with this program; if not, write to the Free Software
00017  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00018  */
00019 
00020 #include <config.h>
00021 
00022 #include <math.h>
00023 
00024 #include <drizzled/error.h>
00025 #include <drizzled/field.h>
00026 #include <drizzled/item/float.h>
00027 #include <drizzled/item/num.h>
00028 #include <drizzled/item/string.h>
00029 
00030 namespace drizzled
00031 {
00032 
00033 extern const CHARSET_INFO *system_charset_info;
00034 
00035 static uint32_t nr_of_decimals(const char *str, const char *end)
00036 {
00037   const char *decimal_point;
00038 
00039   /* Find position for '.' */
00040   for (;;)
00041   {
00042     if (str == end)
00043       return 0;
00044     if (*str == 'e' || *str == 'E')
00045       return NOT_FIXED_DEC;
00046     if (*str++ == '.')
00047       break;
00048   }
00049   decimal_point= str;
00050   for (; my_isdigit(system_charset_info, *str) ; str++)
00051     ;
00052   if (*str == 'e' || *str == 'E')
00053     return NOT_FIXED_DEC;
00054   return (uint32_t) (str - decimal_point);
00055 }
00056 
00057 String *Item_float::val_str(String *str)
00058 {
00059   // following assert is redundant, because fixed=1 assigned in constructor
00060   assert(fixed == 1);
00061   str->set_real(value,decimals,&my_charset_bin);
00062   return str;
00063 }
00064 
00065 
00066 int64_t Item_float::val_int()
00067 {
00068   assert(fixed == 1);
00069   if (value <= (double) INT64_MIN)
00070   {
00071      return INT64_MIN;
00072   }
00073   else if (value >= (double) (uint64_t) INT64_MAX)
00074   {
00075     return INT64_MAX;
00076   }
00077   return (int64_t) rint(value);
00078 }
00079 
00080 type::Decimal *Item_float::val_decimal(type::Decimal *decimal_value)
00081 {
00082   // following assert is redundant, because fixed=1 assigned in constructor
00083   assert(fixed == 1);
00084   double2_class_decimal(E_DEC_FATAL_ERROR, value, decimal_value);
00085   return (decimal_value);
00086 }
00087 
00093 Item_float::Item_float(const char *str_arg, uint32_t length)
00094 {
00095   int error;
00096   char *end_not_used;
00097   value= my_strntod(&my_charset_bin, (char*) str_arg, length, &end_not_used,
00098                     &error);
00099   if (error)
00100   {
00101     /*
00102       Note that we depend on that str_arg is null terminated, which is true
00103       when we are in the parser
00104     */
00105     assert(str_arg[length] == 0);
00106     my_error(ER_ILLEGAL_VALUE_FOR_TYPE, MYF(0), "double", (char*) str_arg);
00107   }
00108   presentation= name=(char*) str_arg;
00109   decimals=(uint8_t) nr_of_decimals(str_arg, str_arg+length);
00110   max_length=length;
00111   fixed= 1;
00112 }
00113 
00114 int Item_float::save_in_field(Field *field, bool)
00115 {
00116   double nr= val_real();
00117   if (null_value)
00118     return set_field_to_null(field);
00119   field->set_notnull();
00120   return field->store(nr);
00121 }
00122 
00123 
00124 void Item_float::print(String *str)
00125 {
00126   if (presentation)
00127   {
00128     str->append(presentation);
00129     return;
00130   }
00131   char buffer[20];
00132   String num(buffer, sizeof(buffer), &my_charset_bin);
00133   num.set_real(value, decimals, &my_charset_bin);
00134   str->append(num);
00135 }
00136 
00137 /*
00138   hex item
00139   In string context this is a binary string.
00140   In number context this is a int64_t value.
00141 */
00142 
00143 bool Item_float::eq(const Item *arg, bool) const
00144 {
00145   if (arg->basic_const_item() && arg->type() == type())
00146   {
00147     /*
00148       We need to cast off const to call val_int(). This should be OK for
00149       a basic constant.
00150     */
00151     Item *item= (Item*) arg;
00152     return item->val_real() == value;
00153   }
00154   return false;
00155 }
00156 
00157 Item *Item_static_float_func::safe_charset_converter(const CHARSET_INFO * const)
00158 {
00159   Item_string *conv;
00160   char buf[64];
00161   String *s, tmp(buf, sizeof(buf), &my_charset_bin);
00162   s= val_str(&tmp);
00163   if ((conv= new Item_static_string_func(func_name, s->ptr(), s->length(),
00164                                          s->charset())))
00165   {
00166     conv->str_value.copy();
00167     conv->str_value.mark_as_const();
00168   }
00169   return conv;
00170 }
00171 
00172 } /* namespace drizzled */