diff options
| author | Kenichi Handa | 2000-07-21 06:45:30 +0000 |
|---|---|---|
| committer | Kenichi Handa | 2000-07-21 06:45:30 +0000 |
| commit | 3c9de1afcde82a99137721436c822059cce79b5b (patch) | |
| tree | 4f39cd49651f701fc5cb422a174d8bf5c1e649b2 /src/data.c | |
| parent | 11270583fe28b5af6b2c19862af597e8d676783d (diff) | |
| download | emacs-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.c | 93 |
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 | |||
| 1838 | DEFUN ("aset", Faset, Saset, 3, 3, 0, | 1843 | DEFUN ("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\ |
| 1840 | ARRAY may be a vector, a string, a char-table or a bool-vector.\n\ | 1845 | ARRAY 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; |