Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Do explicit range tests before attempting to convert a 64-bit float into a 64-bit integer. Some systems (windows) seem to throw exceptions if the conversion is out of range. Ticket #2880. (CVS 4706) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
4744257d3cd2dd96485fde6d9f605427 |
User & Date: | drh 2008-01-11 15:27:03.000 |
Context
2008-01-12
| ||
12:48 | Continuing work toward converting the VM into a register machine. (CVS 4707) (check-in: a6dddebcc5 user: drh tags: trunk) | |
2008-01-11
| ||
15:27 | Do explicit range tests before attempting to convert a 64-bit float into a 64-bit integer. Some systems (windows) seem to throw exceptions if the conversion is out of range. Ticket #2880. (CVS 4706) (check-in: 4744257d3c user: drh tags: trunk) | |
00:06 | Attempt to work around a bug in the Borland BCC 5.5.1 compiler. Ticket #2880. (CVS 4705) (check-in: 6de0ee4907 user: drh tags: trunk) | |
Changes
Changes to src/vdbemem.c.
︙ | ︙ | |||
283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 | }else{ sqlite3_free(p->z); } p->z = 0; p->xDel = 0; } } /* ** Return some kind of integer value which is the best we can do ** at representing the value that *pMem describes as an integer. ** If pMem is an integer, then the value is exact. If pMem is ** a floating-point then the value returned is the integer part. ** If pMem is a string or blob, then we make an attempt to convert ** it into a integer and return that. If pMem is NULL, return 0. ** ** If pMem is a string, its encoding might be changed. */ i64 sqlite3VdbeIntValue(Mem *pMem){ int flags; assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); flags = pMem->flags; if( flags & MEM_Int ){ return pMem->u.i; }else if( flags & MEM_Real ){ | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 | }else{ sqlite3_free(p->z); } p->z = 0; p->xDel = 0; } } /* ** Convert a 64-bit IEEE double into a 64-bit signed integer. ** If the double is too large, return 0x8000000000000000. ** ** Most systems appear to do this simply by assigning ** variables and without the extra range tests. But ** there are reports that windows throws an expection ** if the floating point value is out of range. (See ticket #2880.) ** Because we do not completely understand the problem, we will ** take the conservative approach and always do range tests ** before attempting the conversion. */ static i64 doubleToInt64(double r){ /* ** Many compilers we encounter do not define constants for the ** minimum and maximum 64-bit integers, or they define them ** inconsistently. And many do not understand the "LL" notation. ** So we define our own static constants here using nothing ** larger than a 32-bit integer constant. */ static const i64 maxInt = (((i64)0x7fffffff)<<32)|0xffffffff; static const i64 minInt = ((i64)0x80000000)<<32; if( r<(double)minInt ){ return minInt; }else if( r>(double)maxInt ){ return minInt; }else{ return (i64)r; } } /* ** Return some kind of integer value which is the best we can do ** at representing the value that *pMem describes as an integer. ** If pMem is an integer, then the value is exact. If pMem is ** a floating-point then the value returned is the integer part. ** If pMem is a string or blob, then we make an attempt to convert ** it into a integer and return that. If pMem is NULL, return 0. ** ** If pMem is a string, its encoding might be changed. */ i64 sqlite3VdbeIntValue(Mem *pMem){ int flags; assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); flags = pMem->flags; if( flags & MEM_Int ){ return pMem->u.i; }else if( flags & MEM_Real ){ return doubleToInt64(pMem->r); }else if( flags & (MEM_Str|MEM_Blob) ){ i64 value; pMem->flags |= MEM_Str; if( sqlite3VdbeChangeEncoding(pMem, SQLITE_UTF8) || sqlite3VdbeMemNulTerminate(pMem) ){ return 0; } |
︙ | ︙ | |||
352 353 354 355 356 357 358 | ** The MEM structure is already a MEM_Real. Try to also make it a ** MEM_Int if we can. */ void sqlite3VdbeIntegerAffinity(Mem *pMem){ assert( pMem->flags & MEM_Real ); assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); | < < < < < < < < < < < < < | < < < < < | | 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 | ** The MEM structure is already a MEM_Real. Try to also make it a ** MEM_Int if we can. */ void sqlite3VdbeIntegerAffinity(Mem *pMem){ assert( pMem->flags & MEM_Real ); assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); pMem->u.i = doubleToInt64(pMem->r); if( pMem->r==(double)pMem->u.i ){ pMem->flags |= MEM_Int; } } /* ** Convert pMem to type integer. Invalidate any prior representations. */ |
︙ | ︙ | |||
410 411 412 413 414 415 416 | int sqlite3VdbeMemNumerify(Mem *pMem){ double r1, r2; i64 i; assert( (pMem->flags & (MEM_Int|MEM_Real|MEM_Null))==0 ); assert( (pMem->flags & (MEM_Blob|MEM_Str))!=0 ); assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); r1 = sqlite3VdbeRealValue(pMem); | | | 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 | int sqlite3VdbeMemNumerify(Mem *pMem){ double r1, r2; i64 i; assert( (pMem->flags & (MEM_Int|MEM_Real|MEM_Null))==0 ); assert( (pMem->flags & (MEM_Blob|MEM_Str))!=0 ); assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); r1 = sqlite3VdbeRealValue(pMem); i = doubleToInt64(r1); r2 = (double)i; if( r1==r2 ){ sqlite3VdbeMemIntegerify(pMem); }else{ pMem->r = r1; pMem->flags = MEM_Real; sqlite3VdbeMemRelease(pMem); |
︙ | ︙ |