comparison src/fns.c @ 20667:64af046211eb

(concat): Move the test for all nil in `append' back to the right place. Always compute result_len_byte as for a multibyte string. Then, if the result will be single-byte, don't use that computation. When converting single-byte to multibyte, don't use copy_text. Do use copy_text between single-byte string and multibyte string. (Fstring_make_multibyte, Fstring_make_unibyte): New functions. (syms_of_fns): defsubr them. (string_char_to_byte): Count from the beginning or the end, whichever is closer. Keep a cache of recent values. (string_byte_to_char): Likewise. (Fstring_lessp): Compare the strings char by char.
author Karl Heuer <kwzh@gnu.org>
date Sun, 18 Jan 1998 04:37:08 +0000
parents 12240a9b3679
children 907d8633c8cc
comparison
equal deleted inserted replaced
20666:7e740edb4d52 20667:64af046211eb
37 #include "window.h" 37 #include "window.h"
38 38
39 #ifndef NULL 39 #ifndef NULL
40 #define NULL (void *)0 40 #define NULL (void *)0
41 #endif 41 #endif
42
43 #define DEFAULT_NONASCII_INSERT_OFFSET 0x800
42 44
43 /* Nonzero enables use of dialog boxes for questions 45 /* Nonzero enables use of dialog boxes for questions
44 asked by mouse commands. */ 46 asked by mouse commands. */
45 int use_dialog_box; 47 int use_dialog_box;
46 48
203 Case is significant.\n\ 205 Case is significant.\n\
204 Symbols are also allowed; their print names are used instead.") 206 Symbols are also allowed; their print names are used instead.")
205 (s1, s2) 207 (s1, s2)
206 register Lisp_Object s1, s2; 208 register Lisp_Object s1, s2;
207 { 209 {
208 register int i;
209 register unsigned char *p1, *p2;
210 register int end; 210 register int end;
211 register int i1, i1_byte, i2, i2_byte;
211 212
212 if (SYMBOLP (s1)) 213 if (SYMBOLP (s1))
213 XSETSTRING (s1, XSYMBOL (s1)->name); 214 XSETSTRING (s1, XSYMBOL (s1)->name);
214 if (SYMBOLP (s2)) 215 if (SYMBOLP (s2))
215 XSETSTRING (s2, XSYMBOL (s2)->name); 216 XSETSTRING (s2, XSYMBOL (s2)->name);
216 CHECK_STRING (s1, 0); 217 CHECK_STRING (s1, 0);
217 CHECK_STRING (s2, 1); 218 CHECK_STRING (s2, 1);
218 219
219 p1 = XSTRING (s1)->data; 220 i1 = i1_byte = i2 = i2_byte = 0;
220 p2 = XSTRING (s2)->data; 221
221 end = XSTRING (s1)->size_byte; 222 end = XSTRING (s1)->size;
222 if (end > XSTRING (s2)->size_byte) 223 if (end > XSTRING (s2)->size)
223 end = XSTRING (s2)->size_byte; 224 end = XSTRING (s2)->size;
224 225
225 for (i = 0; i < end; i++) 226 while (i1 < end)
226 { 227 {
227 if (p1[i] != p2[i]) 228 /* When we find a mismatch, we must compare the
228 return p1[i] < p2[i] ? Qt : Qnil; 229 characters, not just the bytes. */
229 } 230 int c1, c2;
230 return i < XSTRING (s2)->size_byte ? Qt : Qnil; 231
232 if (STRING_MULTIBYTE (s1))
233 FETCH_STRING_CHAR_ADVANCE (c1, s1, i1, i1_byte);
234 else
235 c1 = XSTRING (s1)->data[i1++];
236
237 if (STRING_MULTIBYTE (s2))
238 FETCH_STRING_CHAR_ADVANCE (c2, s2, i2, i2_byte);
239 else
240 c2 = XSTRING (s2)->data[i2++];
241
242 if (c1 != c2)
243 return c1 < c2 ? Qt : Qnil;
244 }
245 return i1 < XSTRING (s2)->size ? Qt : Qnil;
231 } 246 }
232 247
233 static Lisp_Object concat (); 248 static Lisp_Object concat ();
234 249
235 /* ARGSUSED */ 250 /* ARGSUSED */
426 int len; 441 int len;
427 this = args[argnum]; 442 this = args[argnum];
428 len = XFASTINT (Flength (this)); 443 len = XFASTINT (Flength (this));
429 if (target_type == Lisp_String) 444 if (target_type == Lisp_String)
430 { 445 {
431 /* We must pay attention to a multibyte character which 446 /* We must count the number of bytes needed in the string
432 takes more than one byte in string. */ 447 as well as the number of characters. */
433 int i; 448 int i;
434 Lisp_Object ch; 449 Lisp_Object ch;
435 int this_len_byte; 450 int this_len_byte;
436 451
437 if (VECTORP (this)) 452 if (VECTORP (this))
457 some_multibyte = 1; 472 some_multibyte = 1;
458 } 473 }
459 else if (STRINGP (this)) 474 else if (STRINGP (this))
460 { 475 {
461 result_len_byte += XSTRING (this)->size_byte; 476 result_len_byte += XSTRING (this)->size_byte;
462 if (STRING_MULTIBYTE (this)) 477 {
463 some_multibyte = 1; 478 some_multibyte = 1;
479 result_len_byte += XSTRING (this)->size_byte;
480 }
481 else
482 result_len_byte += count_size_as_multibyte (XSTRING (this)->data,
483 XSTRING (this)->size);
464 } 484 }
465 } 485 }
466 486
467 result_len += len; 487 result_len += len;
468 } 488 }
469 489
470 /* In `append', if all but last arg are nil, return last arg. */ 490 if (! some_multibyte)
471 if (target_type == Lisp_Cons && EQ (val, Qnil)) 491 result_len_byte = result_len;
472 return last_tail;
473 492
474 /* Create the output object. */ 493 /* Create the output object. */
475 if (target_type == Lisp_Cons) 494 if (target_type == Lisp_Cons)
476 val = Fmake_list (make_number (result_len), Qnil); 495 val = Fmake_list (make_number (result_len), Qnil);
477 else if (target_type == Lisp_Vectorlike) 496 else if (target_type == Lisp_Vectorlike)
478 val = Fmake_vector (make_number (result_len), Qnil); 497 val = Fmake_vector (make_number (result_len), Qnil);
479 else 498 else
480 val = make_uninit_multibyte_string (result_len, result_len_byte); 499 val = make_uninit_multibyte_string (result_len, result_len_byte);
481 500
501 /* In `append', if all but last arg are nil, return last arg. */
502 if (target_type == Lisp_Cons && EQ (val, Qnil))
503 return last_tail;
482 504
483 /* Copy the contents of the args into the result. */ 505 /* Copy the contents of the args into the result. */
484 if (CONSP (val)) 506 if (CONSP (val))
485 tail = val, toindex = -1; /* -1 in toindex is flag we are making a list */ 507 tail = val, toindex = -1; /* -1 in toindex is flag we are making a list */
486 else 508 else
510 { 532 {
511 int thislen_byte = XSTRING (this)->size_byte; 533 int thislen_byte = XSTRING (this)->size_byte;
512 bcopy (XSTRING (this)->data, XSTRING (val)->data + toindex_byte, 534 bcopy (XSTRING (this)->data, XSTRING (val)->data + toindex_byte,
513 XSTRING (this)->size_byte); 535 XSTRING (this)->size_byte);
514 toindex_byte += thislen_byte; 536 toindex_byte += thislen_byte;
537 toindex += thisleni;
538 }
539 /* Copy a single-byte string to a multibyte string. */
540 else if (STRINGP (this) && STRINGP (val))
541 {
542 toindex_byte += copy_text (XSTRING (this)->data,
543 XSTRING (val)->data + toindex_byte,
544 XSTRING (this)->size, 0, 1);
515 toindex += thisleni; 545 toindex += thisleni;
516 } 546 }
517 else 547 else
518 /* Copy element by element. */ 548 /* Copy element by element. */
519 while (1) 549 while (1)
544 XSETFASTINT (elt, XSTRING (this)->data[thisindex++]); 574 XSETFASTINT (elt, XSTRING (this)->data[thisindex++]);
545 if (some_multibyte && XINT (elt) >= 0200 575 if (some_multibyte && XINT (elt) >= 0200
546 && XINT (elt) < 0400) 576 && XINT (elt) < 0400)
547 { 577 {
548 c = XINT (elt); 578 c = XINT (elt);
549 copy_text (&c, &c, 1, 0, 1); 579 if (nonascii_insert_offset > 0)
580 c += nonascii_insert_offset;
581 else
582 c += DEFAULT_NONASCII_INSERT_OFFSET;
583
550 XSETINT (elt, c); 584 XSETINT (elt, c);
551 } 585 }
552 } 586 }
553 } 587 }
554 else if (BOOL_VECTOR_P (this)) 588 else if (BOOL_VECTOR_P (this))
606 XCONS (prev)->cdr = last_tail; 640 XCONS (prev)->cdr = last_tail;
607 641
608 return val; 642 return val;
609 } 643 }
610 644
645 static Lisp_Object string_char_byte_cache_string;
646 static int string_char_byte_cache_charpos;
647 static int string_char_byte_cache_bytepos;
648
611 /* Return the character index corresponding to CHAR_INDEX in STRING. */ 649 /* Return the character index corresponding to CHAR_INDEX in STRING. */
612 650
613 int 651 int
614 string_char_to_byte (string, char_index) 652 string_char_to_byte (string, char_index)
615 Lisp_Object string; 653 Lisp_Object string;
616 int char_index; 654 int char_index;
617 { 655 {
618 int i = 0, i_byte = 0; 656 int i, i_byte;
657 int best_below, best_below_byte;
658 int best_above, best_above_byte;
619 659
620 if (! STRING_MULTIBYTE (string)) 660 if (! STRING_MULTIBYTE (string))
621 return char_index; 661 return char_index;
622 662
623 while (i < char_index) 663 best_below = best_below_byte = 0;
624 { 664 best_above = XSTRING (string)->size;
625 int c; 665 best_above_byte = XSTRING (string)->size_byte;
626 FETCH_STRING_CHAR_ADVANCE (c, string, i, i_byte); 666
627 } 667 if (EQ (string, string_char_byte_cache_string))
668 {
669 if (string_char_byte_cache_charpos < char_index)
670 {
671 best_below = string_char_byte_cache_charpos;
672 best_below_byte = string_char_byte_cache_bytepos;
673 }
674 else
675 {
676 best_above = string_char_byte_cache_charpos;
677 best_above_byte = string_char_byte_cache_bytepos;
678 }
679 }
680
681 if (char_index - best_below < best_above - char_index)
682 {
683 while (best_below < char_index)
684 {
685 int c;
686 FETCH_STRING_CHAR_ADVANCE (c, string, best_below, best_below_byte);
687 }
688 i = best_below;
689 i_byte = best_below_byte;
690 }
691 else
692 {
693 while (best_above > char_index)
694 {
695 int best_above_byte_saved = --best_above_byte;
696
697 while (best_above_byte > 0
698 && !CHAR_HEAD_P (XSTRING (string)->data[best_above_byte]))
699 best_above_byte--;
700 if (XSTRING (string)->data[best_above_byte] < 0x80)
701 best_above_byte = best_above_byte_saved;
702 best_above--;
703 }
704 i = best_above;
705 i_byte = best_above_byte;
706 }
707
708 string_char_byte_cache_bytepos = i_byte;
709 string_char_byte_cache_charpos = i;
710 string_char_byte_cache_string = string;
628 711
629 return i_byte; 712 return i_byte;
630 } 713 }
631 714
632 /* Return the character index corresponding to BYTE_INDEX in STRING. */ 715 /* Return the character index corresponding to BYTE_INDEX in STRING. */
633 716
634 int 717 int
635 string_byte_to_char (string, byte_index) 718 string_byte_to_char (string, byte_index)
636 Lisp_Object string; 719 Lisp_Object string;
637 int byte_index; 720 int byte_index;
638 { 721 {
639 int i = 0, i_byte = 0; 722 int i, i_byte;
723 int best_below, best_below_byte;
724 int best_above, best_above_byte;
640 725
641 if (! STRING_MULTIBYTE (string)) 726 if (! STRING_MULTIBYTE (string))
642 return byte_index; 727 return byte_index;
643 728
644 while (i_byte < byte_index) 729 best_below = best_below_byte = 0;
645 { 730 best_above = XSTRING (string)->size;
646 int c; 731 best_above_byte = XSTRING (string)->size_byte;
647 FETCH_STRING_CHAR_ADVANCE (c, string, i, i_byte); 732
648 } 733 if (EQ (string, string_char_byte_cache_string))
734 {
735 if (string_char_byte_cache_bytepos < byte_index)
736 {
737 best_below = string_char_byte_cache_charpos;
738 best_below_byte = string_char_byte_cache_bytepos;
739 }
740 else
741 {
742 best_above = string_char_byte_cache_charpos;
743 best_above_byte = string_char_byte_cache_bytepos;
744 }
745 }
746
747 if (byte_index - best_below_byte < best_above_byte - byte_index)
748 {
749 while (best_below_byte < byte_index)
750 {
751 int c;
752 FETCH_STRING_CHAR_ADVANCE (c, string, best_below, best_below_byte);
753 }
754 i = best_below;
755 i_byte = best_below_byte;
756 }
757 else
758 {
759 while (best_above_byte > byte_index)
760 {
761 int best_above_byte_saved = --best_above_byte;
762
763 while (best_above_byte > 0
764 && !CHAR_HEAD_P (XSTRING (string)->data[best_above_byte]))
765 best_above_byte--;
766 if (XSTRING (string)->data[best_above_byte] < 0x80)
767 best_above_byte = best_above_byte_saved;
768 best_above--;
769 }
770 i = best_above;
771 i_byte = best_above_byte;
772 }
773
774 string_char_byte_cache_bytepos = i_byte;
775 string_char_byte_cache_charpos = i;
776 string_char_byte_cache_string = string;
649 777
650 return i; 778 return i;
651 } 779 }
652 780
653 /* Convert STRING to a multibyte string. 781 /* Convert STRING to a multibyte string.
654 Single-byte characters 0200 through 0377 are converted 782 Single-byte characters 0200 through 0377 are converted
655 by adding nonascii_insert_offset to each. */ 783 by adding nonascii_insert_offset to each. */
656 784
657 Lisp_Object 785 Lisp_Object
688 816
689 copy_text (XSTRING (string)->data, buf, XSTRING (string)->size_byte, 817 copy_text (XSTRING (string)->data, buf, XSTRING (string)->size_byte,
690 1, 0); 818 1, 0);
691 819
692 return make_unibyte_string (buf, XSTRING (string)->size); 820 return make_unibyte_string (buf, XSTRING (string)->size);
821 }
822
823 DEFUN ("string-make-multibyte", Fstring_make_multibyte, Sstring_make_multibyte,
824 1, 1, 0,
825 "Return the multibyte equivalent of STRING.")
826 (string)
827 Lisp_Object string;
828 {
829 return string_make_multibyte (string);
830 }
831
832 DEFUN ("string-make-unibyte", Fstring_make_unibyte, Sstring_make_unibyte,
833 1, 1, 0,
834 "Return the unibyte equivalent of STRING.")
835 (string)
836 Lisp_Object string;
837 {
838 return string_make_unibyte (string);
693 } 839 }
694 840
695 DEFUN ("copy-alist", Fcopy_alist, Scopy_alist, 1, 1, 0, 841 DEFUN ("copy-alist", Fcopy_alist, Scopy_alist, 1, 1, 0,
696 "Return a copy of ALIST.\n\ 842 "Return a copy of ALIST.\n\
697 This is an alist which represents the same mapping from objects to objects,\n\ 843 This is an alist which represents the same mapping from objects to objects,\n\
2311 Qcursor_in_echo_area = intern ("cursor-in-echo-area"); 2457 Qcursor_in_echo_area = intern ("cursor-in-echo-area");
2312 staticpro (&Qcursor_in_echo_area); 2458 staticpro (&Qcursor_in_echo_area);
2313 Qwidget_type = intern ("widget-type"); 2459 Qwidget_type = intern ("widget-type");
2314 staticpro (&Qwidget_type); 2460 staticpro (&Qwidget_type);
2315 2461
2462 staticpro (&string_char_byte_cache_string);
2463 string_char_byte_cache_string = Qnil;
2464
2316 Fset (Qyes_or_no_p_history, Qnil); 2465 Fset (Qyes_or_no_p_history, Qnil);
2317 2466
2318 DEFVAR_LISP ("features", &Vfeatures, 2467 DEFVAR_LISP ("features", &Vfeatures,
2319 "A list of symbols which are the features of the executing emacs.\n\ 2468 "A list of symbols which are the features of the executing emacs.\n\
2320 Used by `featurep' and `require', and altered by `provide'."); 2469 Used by `featurep' and `require', and altered by `provide'.");
2334 defsubr (&Sstring_lessp); 2483 defsubr (&Sstring_lessp);
2335 defsubr (&Sappend); 2484 defsubr (&Sappend);
2336 defsubr (&Sconcat); 2485 defsubr (&Sconcat);
2337 defsubr (&Svconcat); 2486 defsubr (&Svconcat);
2338 defsubr (&Scopy_sequence); 2487 defsubr (&Scopy_sequence);
2488 defsubr (&Sstring_make_multibyte);
2489 defsubr (&Sstring_make_unibyte);
2339 defsubr (&Scopy_alist); 2490 defsubr (&Scopy_alist);
2340 defsubr (&Ssubstring); 2491 defsubr (&Ssubstring);
2341 defsubr (&Snthcdr); 2492 defsubr (&Snthcdr);
2342 defsubr (&Snth); 2493 defsubr (&Snth);
2343 defsubr (&Selt); 2494 defsubr (&Selt);