aboutsummaryrefslogtreecommitdiffstats
path: root/src/data.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/data.c')
-rw-r--r--src/data.c121
1 files changed, 99 insertions, 22 deletions
diff --git a/src/data.c b/src/data.c
index 78bd454056d..a41ffe7a1f6 100644
--- a/src/data.c
+++ b/src/data.c
@@ -2326,33 +2326,110 @@ DEFUN ("zerop", Fzerop, Szerop, 1, 1, 0,
2326 return Qnil; 2326 return Qnil;
2327} 2327}
2328 2328
2329/* Convert between long values and pairs of Lisp integers. 2329/* Convert the cons-of-integers, integer, or float value C to an
2330 Note that long_to_cons returns a single Lisp integer 2330 unsigned value with maximum value MAX. Signal an error if C does not
2331 when the value fits in one. */ 2331 have a valid format or is out of range. */
2332uintmax_t
2333cons_to_unsigned (Lisp_Object c, uintmax_t max)
2334{
2335 int valid = 0;
2336 uintmax_t val IF_LINT (= 0);
2337 if (INTEGERP (c))
2338 {
2339 valid = 0 <= XINT (c);
2340 val = XINT (c);
2341 }
2342 else if (FLOATP (c))
2343 {
2344 double d = XFLOAT_DATA (c);
2345 if (0 <= d
2346 && d < (max == UINTMAX_MAX ? (double) UINTMAX_MAX + 1 : max + 1))
2347 {
2348 val = d;
2349 valid = 1;
2350 }
2351 }
2352 else if (CONSP (c) && NATNUMP (XCAR (c)))
2353 {
2354 uintmax_t top = XFASTINT (XCAR (c));
2355 Lisp_Object rest = XCDR (c);
2356 if (top <= UINTMAX_MAX >> 24 >> 16
2357 && CONSP (rest)
2358 && NATNUMP (XCAR (rest)) && XFASTINT (XCAR (rest)) < 1 << 24
2359 && NATNUMP (XCDR (rest)) && XFASTINT (XCDR (rest)) < 1 << 16)
2360 {
2361 uintmax_t mid = XFASTINT (XCAR (rest));
2362 val = top << 24 << 16 | mid << 16 | XFASTINT (XCDR (rest));
2363 valid = 1;
2364 }
2365 else if (top <= UINTMAX_MAX >> 16)
2366 {
2367 if (CONSP (rest))
2368 rest = XCAR (rest);
2369 if (NATNUMP (rest) && XFASTINT (rest) < 1 << 16)
2370 {
2371 val = top << 16 | XFASTINT (rest);
2372 valid = 1;
2373 }
2374 }
2375 }
2332 2376
2333Lisp_Object 2377 if (! (valid && val <= max))
2334long_to_cons (long unsigned int i) 2378 error ("Not an in-range integer, float, or cons of integers");
2335{ 2379 return val;
2336 unsigned long top = i >> 16;
2337 unsigned int bot = i & 0xFFFF;
2338 if (top == 0)
2339 return make_number (bot);
2340 if (top == (unsigned long)-1 >> 16)
2341 return Fcons (make_number (-1), make_number (bot));
2342 return Fcons (make_number (top), make_number (bot));
2343} 2380}
2344 2381
2345unsigned long 2382/* Convert the cons-of-integers, integer, or float value C to a signed
2346cons_to_long (Lisp_Object c) 2383 value with extrema MIN and MAX. Signal an error if C does not have
2384 a valid format or is out of range. */
2385intmax_t
2386cons_to_signed (Lisp_Object c, intmax_t min, intmax_t max)
2347{ 2387{
2348 Lisp_Object top, bot; 2388 int valid = 0;
2389 intmax_t val IF_LINT (= 0);
2349 if (INTEGERP (c)) 2390 if (INTEGERP (c))
2350 return XINT (c); 2391 {
2351 top = XCAR (c); 2392 val = XINT (c);
2352 bot = XCDR (c); 2393 valid = 1;
2353 if (CONSP (bot)) 2394 }
2354 bot = XCAR (bot); 2395 else if (FLOATP (c))
2355 return ((XINT (top) << 16) | XINT (bot)); 2396 {
2397 double d = XFLOAT_DATA (c);
2398 if (min <= d
2399 && d < (max == INTMAX_MAX ? (double) INTMAX_MAX + 1 : max + 1))
2400 {
2401 val = d;
2402 valid = 1;
2403 }
2404 }
2405 else if (CONSP (c) && INTEGERP (XCAR (c)))
2406 {
2407 intmax_t top = XINT (XCAR (c));
2408 Lisp_Object rest = XCDR (c);
2409 if (INTMAX_MIN >> 24 >> 16 <= top && top <= INTMAX_MAX >> 24 >> 16
2410 && CONSP (rest)
2411 && NATNUMP (XCAR (rest)) && XFASTINT (XCAR (rest)) < 1 << 24
2412 && NATNUMP (XCDR (rest)) && XFASTINT (XCDR (rest)) < 1 << 16)
2413 {
2414 intmax_t mid = XFASTINT (XCAR (rest));
2415 val = top << 24 << 16 | mid << 16 | XFASTINT (XCDR (rest));
2416 valid = 1;
2417 }
2418 else if (INTMAX_MIN >> 16 <= top && top <= INTMAX_MAX >> 16)
2419 {
2420 if (CONSP (rest))
2421 rest = XCAR (rest);
2422 if (NATNUMP (rest) && XFASTINT (rest) < 1 << 16)
2423 {
2424 val = top << 16 | XFASTINT (rest);
2425 valid = 1;
2426 }
2427 }
2428 }
2429
2430 if (! (valid && min <= val && val <= max))
2431 error ("Not an in-range integer, float, or cons of integers");
2432 return val;
2356} 2433}
2357 2434
2358DEFUN ("number-to-string", Fnumber_to_string, Snumber_to_string, 1, 1, 0, 2435DEFUN ("number-to-string", Fnumber_to_string, Snumber_to_string, 1, 1, 0,