aboutsummaryrefslogtreecommitdiffstats
path: root/src/data.c
diff options
context:
space:
mode:
authorKenichi Handa2000-07-21 06:45:30 +0000
committerKenichi Handa2000-07-21 06:45:30 +0000
commit3c9de1afcde82a99137721436c822059cce79b5b (patch)
tree4f39cd49651f701fc5cb422a174d8bf5c1e649b2 /src/data.c
parent11270583fe28b5af6b2c19862af597e8d676783d (diff)
downloademacs-3c9de1afcde82a99137721436c822059cce79b5b.tar.gz
emacs-3c9de1afcde82a99137721436c822059cce79b5b.zip
(Faset): Allow storing any multibyte character in a string. Convert
unibyte string to multibyte if necessary.
Diffstat (limited to 'src/data.c')
-rw-r--r--src/data.c93
1 files changed, 69 insertions, 24 deletions
diff --git a/src/data.c b/src/data.c
index b06d8cdec4a..0e393bf450d 100644
--- a/src/data.c
+++ b/src/data.c
@@ -1835,6 +1835,11 @@ or a byte-code object. IDX starts at 0.")
1835 } 1835 }
1836} 1836}
1837 1837
1838/* Don't use alloca for relocating string data larger than this, lest
1839 we overflow their stack. The value is the same as what used in
1840 fns.c for base64 handling. */
1841#define MAX_ALLOCA 16*1024
1842
1838DEFUN ("aset", Faset, Saset, 3, 3, 0, 1843DEFUN ("aset", Faset, Saset, 3, 3, 0,
1839 "Store into the element of ARRAY at index IDX the value NEWELT.\n\ 1844 "Store into the element of ARRAY at index IDX the value NEWELT.\n\
1840ARRAY may be a vector, a string, a char-table or a bool-vector.\n\ 1845ARRAY may be a vector, a string, a char-table or a bool-vector.\n\
@@ -1916,41 +1921,81 @@ IDX starts at 0.")
1916 } 1921 }
1917 else if (STRING_MULTIBYTE (array)) 1922 else if (STRING_MULTIBYTE (array))
1918 { 1923 {
1919 int idxval_byte, new_len, actual_len; 1924 int idxval_byte, prev_bytes, new_bytes;
1920 int prev_byte; 1925 unsigned char workbuf[MAX_MULTIBYTE_LENGTH], *p0 = workbuf, *p1;
1921 unsigned char *p, workbuf[MAX_MULTIBYTE_LENGTH], *str = workbuf;
1922 1926
1923 if (idxval < 0 || idxval >= XSTRING (array)->size) 1927 if (idxval < 0 || idxval >= XSTRING (array)->size)
1924 args_out_of_range (array, idx); 1928 args_out_of_range (array, idx);
1929 CHECK_NUMBER (newelt, 2);
1925 1930
1926 idxval_byte = string_char_to_byte (array, idxval); 1931 idxval_byte = string_char_to_byte (array, idxval);
1927 p = &XSTRING (array)->data[idxval_byte]; 1932 p1 = &XSTRING (array)->data[idxval_byte];
1928 1933 PARSE_MULTIBYTE_SEQ (p1, nbytes - idxval_byte, prev_bytes);
1929 actual_len = MULTIBYTE_FORM_LENGTH (p, STRING_BYTES (XSTRING (array))); 1934 new_bytes = CHAR_STRING (XINT (newelt), p0);
1930 CHECK_NUMBER (newelt, 2); 1935 if (prev_bytes != new_bytes)
1931 new_len = CHAR_STRING (XINT (newelt), str); 1936 {
1932 if (actual_len != new_len) 1937 /* We must relocate the string data. */
1933 error ("Attempt to change byte length of a string"); 1938 int nchars = XSTRING (array)->size;
1934 1939 int nbytes = STRING_BYTES (XSTRING (array));
1935 /* We can't accept a change causing byte combining. */ 1940 unsigned char *str;
1936 if (!ASCII_BYTE_P (*str) 1941
1937 && ((idxval > 0 && !CHAR_HEAD_P (*str) 1942 str = (nbytes <= MAX_ALLOCA
1938 && (prev_byte = string_char_to_byte (array, idxval - 1), 1943 ? (unsigned char *) alloca (nbytes)
1939 BYTES_BY_CHAR_HEAD (XSTRING (array)->data[prev_byte]) 1944 : (unsigned char *) xmalloc (nbytes));
1940 > idxval_byte - prev_byte)) 1945 bcopy (XSTRING (array)->data, str, nbytes);
1941 || (idxval < XSTRING (array)->size - 1 1946 allocate_string_data (XSTRING (array), nchars,
1942 && !CHAR_HEAD_P (p[actual_len]) 1947 nbytes + new_bytes - prev_bytes);
1943 && new_len < BYTES_BY_CHAR_HEAD (*str)))) 1948 bcopy (str, XSTRING (array)->data, idxval_byte);
1944 error ("Attempt to change char length of a string"); 1949 p1 = XSTRING (array)->data + idxval_byte;
1945 while (new_len--) 1950 bcopy (str + idxval_byte + prev_bytes, p1 + new_bytes,
1946 *p++ = *str++; 1951 nbytes - (idxval_byte + prev_bytes));
1952 if (nbytes > MAX_ALLOCA)
1953 xfree (str);
1954 clear_string_char_byte_cache ();
1955 }
1956 while (new_bytes--)
1957 *p1++ = *p0++;
1947 } 1958 }
1948 else 1959 else
1949 { 1960 {
1950 if (idxval < 0 || idxval >= XSTRING (array)->size) 1961 if (idxval < 0 || idxval >= XSTRING (array)->size)
1951 args_out_of_range (array, idx); 1962 args_out_of_range (array, idx);
1952 CHECK_NUMBER (newelt, 2); 1963 CHECK_NUMBER (newelt, 2);
1953 XSTRING (array)->data[idxval] = XINT (newelt); 1964
1965 if (XINT (newelt) < 0 || SINGLE_BYTE_CHAR_P (XINT (newelt)))
1966 XSTRING (array)->data[idxval] = XINT (newelt);
1967 else
1968 {
1969 /* We must relocate the string data while converting it to
1970 multibyte. */
1971 int idxval_byte, prev_bytes, new_bytes;
1972 unsigned char workbuf[MAX_MULTIBYTE_LENGTH], *p0 = workbuf, *p1;
1973 unsigned char *origstr = XSTRING (array)->data, *str;
1974 int nchars, nbytes;
1975
1976 nchars = XSTRING (array)->size;
1977 nbytes = idxval_byte = count_size_as_multibyte (origstr, idxval);
1978 nbytes += count_size_as_multibyte (origstr + idxval,
1979 nchars - idxval);
1980 str = (nbytes <= MAX_ALLOCA
1981 ? (unsigned char *) alloca (nbytes)
1982 : (unsigned char *) xmalloc (nbytes));
1983 copy_text (XSTRING (array)->data, str, nchars, 0, 1);
1984 PARSE_MULTIBYTE_SEQ (str + idxval_byte, nbytes - idxval_byte,
1985 prev_bytes);
1986 new_bytes = CHAR_STRING (XINT (newelt), p0);
1987 allocate_string_data (XSTRING (array), nchars,
1988 nbytes + new_bytes - prev_bytes);
1989 bcopy (str, XSTRING (array)->data, idxval_byte);
1990 p1 = XSTRING (array)->data + idxval_byte;
1991 while (new_bytes--)
1992 *p1++ = *p0++;
1993 bcopy (str + idxval_byte + prev_bytes, p1,
1994 nbytes - (idxval_byte + prev_bytes));
1995 if (nbytes > MAX_ALLOCA)
1996 xfree (str);
1997 clear_string_char_byte_cache ();
1998 }
1954 } 1999 }
1955 2000
1956 return newelt; 2001 return newelt;