comparison src/fns.c @ 416:ebe98a74bd68 r21-2-16

Import from CVS: tag r21-2-16
author cvs
date Mon, 13 Aug 2007 11:22:23 +0200
parents da8ed4261e83
children 41dbb7a9d5f2
comparison
equal deleted inserted replaced
415:a27f76b40c83 416:ebe98a74bd68
337 /* There is no hope of this working under Mule. Even if we converted 337 /* There is no hope of this working under Mule. Even if we converted
338 the data into an external format so that strcoll() processed it 338 the data into an external format so that strcoll() processed it
339 properly, it would still not work because strcoll() does not 339 properly, it would still not work because strcoll() does not
340 handle multiple locales. This is the fundamental flaw in the 340 handle multiple locales. This is the fundamental flaw in the
341 locale model. */ 341 locale model. */
342 Bytecount bcend = charcount_to_bytecount (string_data (p1), end); 342 {
343 /* Compare strings using collation order of locale. */ 343 Bytecount bcend = charcount_to_bytecount (string_data (p1), end);
344 /* Need to be tricky to handle embedded nulls. */ 344 /* Compare strings using collation order of locale. */
345 345 /* Need to be tricky to handle embedded nulls. */
346 for (i = 0; i < bcend; i += strlen((char *) string_data (p1) + i) + 1) 346
347 { 347 for (i = 0; i < bcend; i += strlen((char *) string_data (p1) + i) + 1)
348 int val = strcoll ((char *) string_data (p1) + i, 348 {
349 (char *) string_data (p2) + i); 349 int val = strcoll ((char *) string_data (p1) + i,
350 if (val < 0) 350 (char *) string_data (p2) + i);
351 return Qt; 351 if (val < 0)
352 if (val > 0) 352 return Qt;
353 return Qnil; 353 if (val > 0)
354 } 354 return Qnil;
355 }
356 }
355 #else /* not I18N2, or MULE */ 357 #else /* not I18N2, or MULE */
356 /* #### It is not really necessary to do this: We could compare 358 {
357 byte-by-byte and still get a reasonable comparison, since this 359 Bufbyte *ptr1 = string_data (p1);
358 would compare characters with a charset in the same way. 360 Bufbyte *ptr2 = string_data (p2);
359 With a little rearrangement of the leading bytes, we could 361
360 make most inter-charset comparisons work out the same, too; 362 /* #### It is not really necessary to do this: We could compare
361 even if some don't, this is not a big deal because inter-charset 363 byte-by-byte and still get a reasonable comparison, since this
362 comparisons aren't really well-defined anyway. */ 364 would compare characters with a charset in the same way. With
363 for (i = 0; i < end; i++) 365 a little rearrangement of the leading bytes, we could make most
364 { 366 inter-charset comparisons work out the same, too; even if some
365 if (string_char (p1, i) != string_char (p2, i)) 367 don't, this is not a big deal because inter-charset comparisons
366 return string_char (p1, i) < string_char (p2, i) ? Qt : Qnil; 368 aren't really well-defined anyway. */
367 } 369 for (i = 0; i < end; i++)
370 {
371 if (charptr_emchar (ptr1) != charptr_emchar (ptr2))
372 return charptr_emchar (ptr1) < charptr_emchar (ptr2) ? Qt : Qnil;
373 INC_CHARPTR (ptr1);
374 INC_CHARPTR (ptr2);
375 }
376 }
368 #endif /* not I18N2, or MULE */ 377 #endif /* not I18N2, or MULE */
369 /* Can't do i < len2 because then comparison between "foo" and "foo^@" 378 /* Can't do i < len2 because then comparison between "foo" and "foo^@"
370 won't work right in I18N2 case */ 379 won't work right in I18N2 case */
371 return end < len2 ? Qt : Qnil; 380 return end < len2 ? Qt : Qnil;
372 } 381 }
3380 return unbind_to (speccount, feature); 3389 return unbind_to (speccount, feature);
3381 } 3390 }
3382 } 3391 }
3383 3392
3384 /* base64 encode/decode functions. 3393 /* base64 encode/decode functions.
3385 Based on code from GNU recode. */ 3394
3386 3395 Originally based on code from GNU recode. Ported to FSF Emacs by
3387 #define MIME_LINE_LENGTH 76 3396 Lars Magne Ingebrigtsen and Karl Heuer. Ported to XEmacs and
3397 subsequently heavily hacked by Hrvoje Niksic. */
3398
3399 #define MIME_LINE_LENGTH 72
3388 3400
3389 #define IS_ASCII(Character) \ 3401 #define IS_ASCII(Character) \
3390 ((Character) < 128) 3402 ((Character) < 128)
3391 #define IS_BASE64(Character) \ 3403 #define IS_BASE64(Character) \
3392 (IS_ASCII (Character) && base64_char_to_value[Character] >= 0) 3404 (IS_ASCII (Character) && base64_char_to_value[Character] >= 0)
3502 3514
3503 return e - to; 3515 return e - to;
3504 } 3516 }
3505 #undef ADVANCE_INPUT 3517 #undef ADVANCE_INPUT
3506 3518
3507 /* Semantically identical to ADVANCE_INPUT above, only no >255 3519 /* Get next character from the stream, except that non-base64
3508 checking is needed for decoding -- checking is covered by IS_BASE64 3520 characters are ignored. This is in accordance with rfc2045. EC
3509 below. */ 3521 should be an Emchar, so that it can hold -1 as the value for EOF. */
3510 #define ADVANCE_INPUT(c, stream) \ 3522 #define ADVANCE_INPUT_IGNORE_NONBASE64(ec, stream, streampos) do { \
3511 (ec = Lstream_get_emchar (stream), \ 3523 ec = Lstream_get_emchar (stream); \
3512 ec == -1 ? 0 : (c = (Bufbyte)ec, 1)) 3524 ++streampos; \
3513 3525 /* IS_BASE64 may not be called with negative arguments so check for \
3514 /* Get next character from the stream, but ignore it if it's 3526 EOF first. */ \
3515 whitespace. ENDP is set to 1 if EOF is hit. */ 3527 if (ec < 0 || IS_BASE64 (ec) || ec == '=') \
3516 #define ADVANCE_INPUT_IGNORE_WHITESPACE(c, endp, stream) do { \ 3528 break; \
3517 endp = 0; \ 3529 } while (1)
3518 do { \ 3530
3519 if (!ADVANCE_INPUT (c, stream)) \ 3531 #define STORE_BYTE(pos, val, ccnt) do { \
3520 endp = 1; \
3521 } while (!endp && (c == ' ' || c == '\t' || c == '\r' || c == '\n' \
3522 || c == '\f' || c == '\v')); \
3523 } while (0)
3524
3525 #define STORE_BYTE(pos, val) do { \
3526 pos += set_charptr_emchar (pos, (Emchar)((unsigned char)(val))); \ 3532 pos += set_charptr_emchar (pos, (Emchar)((unsigned char)(val))); \
3527 ++*ccptr; \ 3533 ++ccnt; \
3528 } while (0) 3534 } while (0)
3529 3535
3530 static Bytind 3536 static Bytind
3531 base64_decode_1 (Lstream *istream, Bufbyte *to, Charcount *ccptr) 3537 base64_decode_1 (Lstream *istream, Bufbyte *to, Charcount *ccptr)
3532 { 3538 {
3539 Charcount ccnt = 0;
3533 Bufbyte *e = to; 3540 Bufbyte *e = to;
3534 unsigned long value; 3541 EMACS_INT streampos = 0;
3535 3542
3536 *ccptr = 0;
3537 while (1) 3543 while (1)
3538 { 3544 {
3539 Bufbyte c;
3540 Emchar ec; 3545 Emchar ec;
3541 int endp; 3546 unsigned long value;
3542 3547
3543 ADVANCE_INPUT_IGNORE_WHITESPACE (c, endp, istream); 3548 /* Process first byte of a quadruplet. */
3544 if (endp) 3549 ADVANCE_INPUT_IGNORE_NONBASE64 (ec, istream, streampos);
3550 if (ec < 0)
3545 break; 3551 break;
3546 3552 if (ec == '=')
3547 /* Process first byte of a quadruplet. */ 3553 signal_simple_error ("Illegal `=' character while decoding base64",
3548 if (!IS_BASE64 (c)) 3554 make_int (streampos));
3549 return -1; 3555 value = base64_char_to_value[ec] << 18;
3550 value = base64_char_to_value[c] << 18;
3551 3556
3552 /* Process second byte of a quadruplet. */ 3557 /* Process second byte of a quadruplet. */
3553 ADVANCE_INPUT_IGNORE_WHITESPACE (c, endp, istream); 3558 ADVANCE_INPUT_IGNORE_NONBASE64 (ec, istream, streampos);
3554 if (endp) 3559 if (ec < 0)
3555 return -1; 3560 error ("Premature EOF while decoding base64");
3556 3561 if (ec == '=')
3557 if (!IS_BASE64 (c)) 3562 signal_simple_error ("Illegal `=' character while decoding base64",
3558 return -1; 3563 make_int (streampos));
3559 value |= base64_char_to_value[c] << 12; 3564 value |= base64_char_to_value[ec] << 12;
3560 3565 STORE_BYTE (e, value >> 16, ccnt);
3561 STORE_BYTE (e, value >> 16);
3562 3566
3563 /* Process third byte of a quadruplet. */ 3567 /* Process third byte of a quadruplet. */
3564 ADVANCE_INPUT_IGNORE_WHITESPACE (c, endp, istream); 3568 ADVANCE_INPUT_IGNORE_NONBASE64 (ec, istream, streampos);
3565 if (endp) 3569 if (ec < 0)
3566 return -1; 3570 error ("Premature EOF while decoding base64");
3567 3571
3568 if (c == '=') 3572 if (ec == '=')
3569 { 3573 {
3570 ADVANCE_INPUT_IGNORE_WHITESPACE (c, endp, istream); 3574 ADVANCE_INPUT_IGNORE_NONBASE64 (ec, istream, streampos);
3571 if (endp) 3575 if (ec < 0)
3572 return -1; 3576 error ("Premature EOF while decoding base64");
3573 if (c != '=') 3577 if (ec != '=')
3574 return -1; 3578 signal_simple_error ("Padding `=' expected but not found while decoding base64",
3579 make_int (streampos));
3575 continue; 3580 continue;
3576 } 3581 }
3577 3582
3578 if (!IS_BASE64 (c)) 3583 value |= base64_char_to_value[ec] << 6;
3579 return -1; 3584 STORE_BYTE (e, 0xff & value >> 8, ccnt);
3580 value |= base64_char_to_value[c] << 6;
3581
3582 STORE_BYTE (e, 0xff & value >> 8);
3583 3585
3584 /* Process fourth byte of a quadruplet. */ 3586 /* Process fourth byte of a quadruplet. */
3585 ADVANCE_INPUT_IGNORE_WHITESPACE (c, endp, istream); 3587 ADVANCE_INPUT_IGNORE_NONBASE64 (ec, istream, streampos);
3586 if (endp) 3588 if (ec < 0)
3587 return -1; 3589 error ("Premature EOF while decoding base64");
3588 3590 if (ec == '=')
3589 if (c == '=')
3590 continue; 3591 continue;
3591 3592
3592 if (!IS_BASE64 (c)) 3593 value |= base64_char_to_value[ec];
3593 return -1; 3594 STORE_BYTE (e, 0xff & value, ccnt);
3594 value |= base64_char_to_value[c]; 3595 }
3595 3596
3596 STORE_BYTE (e, 0xff & value); 3597 *ccptr = ccnt;
3597 }
3598
3599 return e - to; 3598 return e - to;
3600 } 3599 }
3601 #undef ADVANCE_INPUT 3600 #undef ADVANCE_INPUT
3602 #undef ADVANCE_INPUT_IGNORE_WHITESPACE 3601 #undef ADVANCE_INPUT_IGNORE_NONBASE64
3603 #undef STORE_BYTE 3602 #undef STORE_BYTE
3604 3603
3605 static Lisp_Object 3604 static Lisp_Object
3606 free_malloced_ptr (Lisp_Object unwind_obj) 3605 free_malloced_ptr (Lisp_Object unwind_obj)
3607 { 3606 {
3675 and delete the old. (Insert first in order to preserve markers.) */ 3674 and delete the old. (Insert first in order to preserve markers.) */
3676 buffer_insert_raw_string_1 (buf, begv, encoded, encoded_length, 0); 3675 buffer_insert_raw_string_1 (buf, begv, encoded, encoded_length, 0);
3677 XMALLOC_UNBIND (encoded, allength, speccount); 3676 XMALLOC_UNBIND (encoded, allength, speccount);
3678 buffer_delete_range (buf, begv + encoded_length, zv + encoded_length, 0); 3677 buffer_delete_range (buf, begv + encoded_length, zv + encoded_length, 0);
3679 3678
3680 /* Simulate FSF Emacs: if point was in the region, place it at the 3679 /* Simulate FSF Emacs implementation of this function: if point was
3681 beginning. */ 3680 in the region, place it at the beginning. */
3682 if (old_pt >= begv && old_pt < zv) 3681 if (old_pt >= begv && old_pt < zv)
3683 BUF_SET_PT (buf, begv); 3682 BUF_SET_PT (buf, begv);
3684 3683
3685 /* We return the length of the encoded text. */ 3684 /* We return the length of the encoded text. */
3686 return make_int (encoded_length); 3685 return make_int (encoded_length);
3717 3716
3718 DEFUN ("base64-decode-region", Fbase64_decode_region, 2, 2, "r", /* 3717 DEFUN ("base64-decode-region", Fbase64_decode_region, 2, 2, "r", /*
3719 Base64-decode the region between BEG and END. 3718 Base64-decode the region between BEG and END.
3720 Return the length of the decoded text. 3719 Return the length of the decoded text.
3721 If the region can't be decoded, return nil and don't modify the buffer. 3720 If the region can't be decoded, return nil and don't modify the buffer.
3721 Characters out of the base64 alphabet are ignored.
3722 */ 3722 */
3723 (beg, end)) 3723 (beg, end))
3724 { 3724 {
3725 struct buffer *buf = current_buffer; 3725 struct buffer *buf = current_buffer;
3726 Bufpos begv, zv, old_pt = BUF_PT (buf); 3726 Bufpos begv, zv, old_pt = BUF_PT (buf);
3741 decoded_length = base64_decode_1 (XLSTREAM (input), decoded, &cc_decoded_length); 3741 decoded_length = base64_decode_1 (XLSTREAM (input), decoded, &cc_decoded_length);
3742 if (decoded_length > length * MAX_EMCHAR_LEN) 3742 if (decoded_length > length * MAX_EMCHAR_LEN)
3743 abort (); 3743 abort ();
3744 Lstream_delete (XLSTREAM (input)); 3744 Lstream_delete (XLSTREAM (input));
3745 3745
3746 if (decoded_length < 0)
3747 {
3748 /* The decoding wasn't possible. */
3749 XMALLOC_UNBIND (decoded, length * MAX_EMCHAR_LEN, speccount);
3750 return Qnil;
3751 }
3752
3753 /* Now we have decoded the region, so we insert the new contents 3746 /* Now we have decoded the region, so we insert the new contents
3754 and delete the old. (Insert first in order to preserve markers.) */ 3747 and delete the old. (Insert first in order to preserve markers.) */
3755 BUF_SET_PT (buf, begv); 3748 BUF_SET_PT (buf, begv);
3756 buffer_insert_raw_string_1 (buf, begv, decoded, decoded_length, 0); 3749 buffer_insert_raw_string_1 (buf, begv, decoded, decoded_length, 0);
3757 XMALLOC_UNBIND (decoded, length * MAX_EMCHAR_LEN, speccount); 3750 XMALLOC_UNBIND (decoded, length * MAX_EMCHAR_LEN, speccount);
3758 buffer_delete_range (buf, begv + cc_decoded_length, 3751 buffer_delete_range (buf, begv + cc_decoded_length,
3759 zv + cc_decoded_length, 0); 3752 zv + cc_decoded_length, 0);
3760 3753
3761 /* Simulate FSF Emacs: if point was in the region, place it at the 3754 /* Simulate FSF Emacs implementation of this function: if point was
3762 beginning. */ 3755 in the region, place it at the beginning. */
3763 if (old_pt >= begv && old_pt < zv) 3756 if (old_pt >= begv && old_pt < zv)
3764 BUF_SET_PT (buf, begv); 3757 BUF_SET_PT (buf, begv);
3765 3758
3766 return make_int (cc_decoded_length); 3759 return make_int (cc_decoded_length);
3767 } 3760 }
3768 3761
3769 DEFUN ("base64-decode-string", Fbase64_decode_string, 1, 1, 0, /* 3762 DEFUN ("base64-decode-string", Fbase64_decode_string, 1, 1, 0, /*
3770 Base64-decode STRING and return the result. 3763 Base64-decode STRING and return the result.
3764 Characters out of the base64 alphabet are ignored.
3771 */ 3765 */
3772 (string)) 3766 (string))
3773 { 3767 {
3774 Bufbyte *decoded; 3768 Bufbyte *decoded;
3775 Bytind decoded_length; 3769 Bytind decoded_length;
3787 decoded_length = base64_decode_1 (XLSTREAM (input), decoded, 3781 decoded_length = base64_decode_1 (XLSTREAM (input), decoded,
3788 &cc_decoded_length); 3782 &cc_decoded_length);
3789 if (decoded_length > length * MAX_EMCHAR_LEN) 3783 if (decoded_length > length * MAX_EMCHAR_LEN)
3790 abort (); 3784 abort ();
3791 Lstream_delete (XLSTREAM (input)); 3785 Lstream_delete (XLSTREAM (input));
3792
3793 if (decoded_length < 0)
3794 {
3795 /* The decoding wasn't possible. */
3796 XMALLOC_UNBIND (decoded, length * MAX_EMCHAR_LEN, speccount);
3797 return Qnil;
3798 }
3799 3786
3800 result = make_string (decoded, decoded_length); 3787 result = make_string (decoded, decoded_length);
3801 XMALLOC_UNBIND (decoded, length * MAX_EMCHAR_LEN, speccount); 3788 XMALLOC_UNBIND (decoded, length * MAX_EMCHAR_LEN, speccount);
3802 return result; 3789 return result;
3803 } 3790 }