OCILIB (C Driver for Oracle) 3.12.1
number.c
00001 /*
00002     +-----------------------------------------------------------------------------------------+
00003     |                                                                                         |
00004     |                               OCILIB - C Driver for Oracle                              |
00005     |                                                                                         |
00006     |                                (C Wrapper for Oracle OCI)                               |
00007     |                                                                                         |
00008     |                              Website : http://www.ocilib.net                            |
00009     |                                                                                         |
00010     |             Copyright (c) 2007-2013 Vincent ROGIER <vince.rogier@ocilib.net>            |
00011     |                                                                                         |
00012     +-----------------------------------------------------------------------------------------+
00013     |                                                                                         |
00014     |             This library is free software; you can redistribute it and/or               |
00015     |             modify it under the terms of the GNU Lesser General Public                  |
00016     |             License as published by the Free Software Foundation; either                |
00017     |             version 2 of the License, or (at your option) any later version.            |
00018     |                                                                                         |
00019     |             This library is distributed in the hope that it will be useful,             |
00020     |             but WITHOUT ANY WARRANTY; without even the implied warranty of              |
00021     |             MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU           |
00022     |             Lesser General Public License for more details.                             |
00023     |                                                                                         |
00024     |             You should have received a copy of the GNU Lesser General Public            |
00025     |             License along with this library; if not, write to the Free                  |
00026     |             Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.          |
00027     |                                                                                         |
00028     +-----------------------------------------------------------------------------------------+
00029 */
00030 
00031 /* --------------------------------------------------------------------------------------------- *
00032  * $Id: number.c, Vincent Rogier $
00033  * --------------------------------------------------------------------------------------------- */
00034 
00035 #include "ocilib_internal.h"
00036 
00037 /* ********************************************************************************************* *
00038  *                             PRIVATE FUNCTIONS
00039  * ********************************************************************************************* */
00040 
00041 /* --------------------------------------------------------------------------------------------- *
00042  * OCI_NumberGet
00043  * --------------------------------------------------------------------------------------------- */
00044 
00045 boolean OCI_NumberGet
00046 (
00047     OCI_Connection *con,
00048     void           *number,
00049     uword           size,
00050     uword           type,
00051     int             sqlcode,
00052     void           *out_value
00053 )
00054 {
00055     boolean res = TRUE;
00056 
00057     OCI_CHECK(con       == NULL, FALSE);
00058     OCI_CHECK(number    == NULL, FALSE);
00059     OCI_CHECK(out_value == NULL, FALSE);
00060 
00061 #if OCI_VERSION_COMPILE < OCI_10_1
00062 
00063     OCI_NOT_USED(sqlcode);
00064 
00065 #endif
00066 
00067     if (type == OCI_NUM_NUMBER)
00068     {
00069         memcpy(out_value, number, size);
00070     }
00071     else if (type & OCI_NUM_DOUBLE || type & OCI_NUM_FLOAT)
00072     {
00073 
00074     #if OCI_VERSION_COMPILE >= OCI_10_1
00075 
00076         if ((OCILib.version_runtime >= OCI_10_1) && ((sqlcode != SQLT_VNU)))
00077         {
00078             if (((type & OCI_NUM_DOUBLE) && (sqlcode == SQLT_BDOUBLE)) ||
00079                 ((type & OCI_NUM_FLOAT ) && (sqlcode == SQLT_BFLOAT )))
00080             {
00081                 memcpy(out_value, number, size);
00082             }
00083             else if (type & OCI_NUM_DOUBLE && sqlcode == SQLT_BFLOAT)
00084             {
00085                 *((double *) out_value) = (double) *((float *) number);
00086             }
00087             else if (type & OCI_NUM_FLOAT && sqlcode == SQLT_BDOUBLE)
00088             {
00089                  *((float *) out_value) = (float) *((double *) number);
00090             }
00091         }
00092         else
00093 
00094     #endif
00095 
00096         {
00097             OCI_CALL2
00098             (
00099                 res, con,
00100 
00101                 OCINumberToReal(con->err, (OCINumber *) number, size, out_value)
00102             )
00103         }
00104     }  
00105     else
00106     {
00107         uword sign = OCI_NUMBER_SIGNED;
00108 
00109         if (type & OCI_NUM_UNSIGNED)
00110         {
00111             sign = OCI_NUMBER_UNSIGNED;
00112         }
00113 
00114         OCI_CALL2
00115         (
00116             res, con,
00117 
00118             OCINumberToInt(con->err, (OCINumber *) number, size, sign, out_value)
00119         )
00120     }
00121 
00122     return res;
00123 }
00124 
00125 /* --------------------------------------------------------------------------------------------- *
00126  * OCI_NumberSet
00127  * --------------------------------------------------------------------------------------------- */
00128 
00129 boolean OCI_NumberSet
00130 (
00131     OCI_Connection *con,
00132     void           *number,
00133     uword           size,
00134     uword           type,
00135     int             sqlcode,
00136     void           *in_value
00137 )
00138 {
00139     boolean res = TRUE;
00140 
00141     OCI_CHECK(con       == NULL, FALSE);
00142     OCI_CHECK(number    == NULL, FALSE);
00143     OCI_CHECK(in_value  == NULL, FALSE);
00144 
00145 #if OCI_VERSION_COMPILE < OCI_10_1
00146 
00147     OCI_NOT_USED(sqlcode);
00148 
00149 #endif
00150 
00151     if (type & OCI_NUM_DOUBLE || type & OCI_NUM_FLOAT)
00152     {
00153 
00154     #if OCI_VERSION_COMPILE >= OCI_10_1
00155 
00156         if ((OCILib.version_runtime >= OCI_10_1) && ((sqlcode != SQLT_VNU)))
00157         {
00158             if (((type & OCI_NUM_DOUBLE) && (sqlcode == SQLT_BDOUBLE)) ||
00159                 ((type & OCI_NUM_FLOAT ) && (sqlcode == SQLT_BFLOAT )))
00160             {
00161                 memcpy(number, in_value, size);
00162             }
00163             else if (type & OCI_NUM_DOUBLE && sqlcode == SQLT_BFLOAT)
00164             {
00165                 *((double *) number) = (double) *((float *) in_value);
00166             }
00167             else if (type & OCI_NUM_FLOAT && sqlcode == SQLT_BDOUBLE)
00168             {
00169                  *((float *) number) = (float) *((double *) in_value);
00170             }
00171         }
00172         else
00173 
00174     #endif
00175 
00176         {
00177             OCI_CALL2
00178             (
00179                 res, con,
00180 
00181                 OCINumberFromReal(con->err, in_value, size, (OCINumber *) number)
00182             )
00183         }
00184     }  
00185     else
00186     {
00187         uword sign = OCI_NUMBER_SIGNED;
00188 
00189         if (type & OCI_NUM_UNSIGNED)
00190         {
00191             sign = OCI_NUMBER_UNSIGNED;
00192         }
00193 
00194         OCI_CALL2
00195         (
00196             res, con,
00197 
00198             OCINumberFromInt(con->err, in_value, size, sign, (OCINumber *) number)
00199         )
00200     }
00201 
00202     return res;
00203 }
00204 
00205 
00206 /* --------------------------------------------------------------------------------------------- *
00207  * OCI_NumberFromString
00208  * --------------------------------------------------------------------------------------------- */
00209 
00210 boolean OCI_NumberFromString
00211 (
00212     OCI_Connection *con,
00213     void           *out_value,
00214     uword           size,
00215     uword           type,
00216     int             sqlcode,
00217     const dtext    *in_value,
00218     const mtext   * fmt
00219 )
00220 {
00221     boolean res  = TRUE;
00222     boolean done = FALSE;
00223 
00224     /* For binary types, perfom a C based conversion */
00225 
00226     if (type & OCI_NUM_DOUBLE || type & OCI_NUM_FLOAT)
00227     {
00228 
00229     #if OCI_VERSION_COMPILE >= OCI_10_1
00230 
00231         if (OCILib.version_runtime >= OCI_10_1)
00232         {
00233             void *ostr1  = NULL;
00234             int   osize1 = -1;
00235 
00236             fmt = OCI_STRING_FORMAT_NUM_BIN;            
00237  
00238             ostr1 = OCI_GetInputString((void *) fmt, &osize1, sizeof(mtext), sizeof(dtext));
00239 
00240             if (type & OCI_NUM_DOUBLE)
00241             {
00242                 res = (dtscanf(in_value, (dtext *) ostr1, out_value) == 1);
00243             }
00244             else if (type & OCI_NUM_FLOAT)
00245             {
00246                 double tmp_value = 0.0;
00247                 
00248                 res = (dtscanf(in_value, (dtext *) ostr1, &tmp_value) == 1);
00249 
00250                 *((float *) out_value) = (float) tmp_value;
00251             }
00252 
00253             done = TRUE;
00254 
00255             if (fmt != ostr1)
00256             {
00257                 OCI_ReleaseMetaString(ostr1);
00258             }
00259         }
00260 
00261     #endif
00262     
00263     }
00264 
00265     /* use OCINumber conversion if not processed yet */
00266 
00267     if (done == FALSE)
00268     {   
00269         void *ostr1 = NULL;
00270         void *ostr2 = NULL;
00271         int osize1  = -1;
00272         int osize2  = -1;
00273         OCINumber number;
00274         
00275         if (fmt == NULL)
00276         {
00277             fmt = OCI_GetDefaultFormatNumeric(con);
00278         }
00279 
00280         ostr1 = OCI_GetInputString((void *) in_value, &osize1, sizeof(dtext), sizeof(omtext));
00281         ostr2 = OCI_GetInputMetaString(fmt, &osize2);
00282 
00283         memset(&number, 0, sizeof(number));
00284 
00285         OCI_CALL2
00286         (
00287             res, con,
00288 
00289             OCINumberFromText(con->err, (oratext *) ostr1, (ub4) osize1, (oratext *) ostr2,
00290                                 (ub4) osize2, (oratext *) NULL,  (ub4) 0, (OCINumber *) &number)
00291         )
00292  
00293         OCI_ReleaseMetaString(ostr2);
00294 
00295         if (in_value != ostr1)
00296         {
00297             OCI_ReleaseMetaString(ostr1);
00298         }
00299 
00300         res = res && OCI_NumberGet(con, &number, size, type, sqlcode, out_value);
00301     }  
00302 
00303     return res;
00304 }
00305 
00306 /* --------------------------------------------------------------------------------------------- *
00307  * OCI_NumberToString
00308  * --------------------------------------------------------------------------------------------- */
00309 
00310 boolean OCI_NumberToString
00311 (
00312     OCI_Connection *con,
00313     void           *number,
00314     uword           type,
00315     int             sqlcode,
00316     dtext          *out_value,
00317     int             out_value_size,
00318     const mtext   * fmt
00319 )
00320 {
00321     boolean res  = TRUE;
00322     boolean done = FALSE;
00323 
00324     out_value[0] = 0;
00325 
00326     /* For binary types, perfom a C based conversion */
00327 
00328     if (type & OCI_NUM_DOUBLE || type & OCI_NUM_FLOAT)
00329     {
00330 
00331     #if OCI_VERSION_COMPILE >= OCI_10_1
00332 
00333         if ((OCILib.version_runtime >= OCI_10_1) && ((sqlcode != SQLT_VNU)))
00334         {
00335             void *ostr1  = NULL;
00336             int   osize1 = -1;
00337 
00338             if (fmt == NULL)
00339             {
00340                 fmt = OCI_STRING_FORMAT_NUM_BIN;
00341             }
00342  
00343             ostr1 = OCI_GetInputString((void *) fmt, &osize1, sizeof(mtext), sizeof(dtext));
00344 
00345             if (type & OCI_NUM_DOUBLE && sqlcode == SQLT_BDOUBLE)
00346             {
00347                 out_value_size = dtsprintf(out_value, out_value_size, (dtext *) ostr1,  *((double *) number));
00348             }
00349             else if (type & OCI_NUM_FLOAT && sqlcode == SQLT_BFLOAT)
00350             {
00351                  out_value_size = dtsprintf(out_value, out_value_size, (dtext *) ostr1,  *((float *) number));
00352             }
00353 
00354             done = TRUE;
00355 
00356             if (fmt != ostr1)
00357             {
00358                 OCI_ReleaseMetaString(ostr1);
00359             }
00360 
00361             if ((out_value_size) > 0)
00362             {
00363                 while (out_value[out_value_size-1] == DT('0'))
00364                 {
00365                     out_value[out_value_size-1] = 0;
00366                 }
00367 
00368                 out_value--;
00369             }
00370         }
00371 
00372     #else
00373     
00374         OCI_NOT_USED(sqlcode);
00375 
00376     #endif
00377     
00378     }
00379 
00380     /* use OCINumber conversion if not processed yet */
00381 
00382     if (done == FALSE)
00383     {   
00384         void *ostr1 = NULL;
00385         void *ostr2 = NULL;
00386         int osize1  = out_value_size * (int) sizeof(dtext);
00387         int osize2  = -1;
00388         
00389         if (fmt == NULL)
00390         {
00391             fmt = OCI_GetDefaultFormatNumeric(con);
00392         }
00393 
00394         ostr1 = OCI_GetInputString(out_value, &osize1, sizeof(dtext), sizeof(omtext));
00395         ostr2 = OCI_GetInputMetaString(fmt, &osize2);
00396 
00397         OCI_CALL2
00398         (
00399             res, con,
00400 
00401             OCINumberToText(con->err, (OCINumber *) number,  (oratext *) ostr2,
00402                             (ub4) osize2, (oratext *) NULL,  (ub4) 0,
00403                             (ub4 *) &osize1, (oratext *) ostr1)
00404         )
00405 
00406         OCI_GetOutputString(ostr1, out_value, &osize1, sizeof(omtext), sizeof(dtext));
00407         OCI_ReleaseMetaString(ostr2);
00408 
00409         if (out_value != ostr1)
00410         {
00411             OCI_ReleaseMetaString(ostr1);
00412         }
00413 
00414         out_value_size = (osize1 / (int) sizeof(dtext));
00415     }  
00416 
00417     /* do we need to suppress last '.' or ',' from integers */
00418 
00419     if ((--out_value_size) >= 0)
00420     {
00421         if ((out_value[out_value_size] == DT('.')) ||
00422             (out_value[out_value_size] == DT(',')))
00423         {
00424             out_value[out_value_size] = 0;
00425         }
00426     }
00427 
00428     return res;
00429 }