diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/fileio.c | 51 |
1 files changed, 29 insertions, 22 deletions
diff --git a/src/fileio.c b/src/fileio.c index 2a53dbbdd07..075b9c590c8 100644 --- a/src/fileio.c +++ b/src/fileio.c | |||
| @@ -3906,7 +3906,8 @@ union read_non_regular | |||
| 3906 | struct | 3906 | struct |
| 3907 | { | 3907 | { |
| 3908 | emacs_fd fd; | 3908 | emacs_fd fd; |
| 3909 | ptrdiff_t inserted, trytry; | 3909 | char *buf; |
| 3910 | ptrdiff_t bufsize; | ||
| 3910 | } s; | 3911 | } s; |
| 3911 | GCALIGNED_UNION_MEMBER | 3912 | GCALIGNED_UNION_MEMBER |
| 3912 | }; | 3913 | }; |
| @@ -3916,11 +3917,7 @@ static Lisp_Object | |||
| 3916 | read_non_regular (Lisp_Object state) | 3917 | read_non_regular (Lisp_Object state) |
| 3917 | { | 3918 | { |
| 3918 | union read_non_regular *data = XFIXNUMPTR (state); | 3919 | union read_non_regular *data = XFIXNUMPTR (state); |
| 3919 | intmax_t nbytes | 3920 | intmax_t nbytes = emacs_fd_read (data->s.fd, data->s.buf, data->s.bufsize); |
| 3920 | = emacs_fd_read (data->s.fd, | ||
| 3921 | ((char *) BEG_ADDR + PT_BYTE - BEG_BYTE | ||
| 3922 | + data->s.inserted), | ||
| 3923 | data->s.trytry); | ||
| 3924 | return make_int (nbytes < 0 ? -errno : nbytes); | 3921 | return make_int (nbytes < 0 ? -errno : nbytes); |
| 3925 | } | 3922 | } |
| 3926 | 3923 | ||
| @@ -4854,18 +4851,18 @@ by calling `format-decode', which see. */) | |||
| 4854 | 4851 | ||
| 4855 | while (inserted < total) | 4852 | while (inserted < total) |
| 4856 | { | 4853 | { |
| 4857 | ptrdiff_t this; | 4854 | char *buf; |
| 4858 | 4855 | ptrdiff_t bufsize, this; | |
| 4859 | if (gap_size == 0) | 4856 | if (gap_size < total - inserted && gap_size < sizeof read_buf) |
| 4860 | { | 4857 | { |
| 4861 | /* The size estimate was wrong. Make the gap 50% larger. */ | 4858 | buf = read_buf; |
| 4862 | make_gap (GAP_SIZE >> 1); | 4859 | bufsize = sizeof read_buf; |
| 4863 | gap_size = GAP_SIZE - inserted; | 4860 | } |
| 4861 | else | ||
| 4862 | { | ||
| 4863 | buf = (char *) BEG_ADDR + PT_BYTE - BEG_BYTE + inserted; | ||
| 4864 | bufsize = min (min (gap_size, total - inserted), READ_BUF_SIZE); | ||
| 4864 | } | 4865 | } |
| 4865 | |||
| 4866 | /* 'try' is reserved in some compilers (Microsoft C). */ | ||
| 4867 | ptrdiff_t trytry = min (gap_size, | ||
| 4868 | min (total - inserted, READ_BUF_SIZE)); | ||
| 4869 | 4866 | ||
| 4870 | if (!seekable && end_offset == TYPE_MAXIMUM (off_t)) | 4867 | if (!seekable && end_offset == TYPE_MAXIMUM (off_t)) |
| 4871 | { | 4868 | { |
| @@ -4875,7 +4872,7 @@ by calling `format-decode', which see. */) | |||
| 4875 | /* Read from the file, capturing `quit'. When an | 4872 | /* Read from the file, capturing `quit'. When an |
| 4876 | error occurs, end the loop, and arrange for a quit | 4873 | error occurs, end the loop, and arrange for a quit |
| 4877 | to be signaled after decoding the text we read. */ | 4874 | to be signaled after decoding the text we read. */ |
| 4878 | union read_non_regular data = {{fd, inserted, trytry}}; | 4875 | union read_non_regular data = {{fd, buf, bufsize}}; |
| 4879 | nbytes = internal_condition_case_1 | 4876 | nbytes = internal_condition_case_1 |
| 4880 | (read_non_regular, make_pointer_integer (&data), | 4877 | (read_non_regular, make_pointer_integer (&data), |
| 4881 | Qerror, read_non_regular_quit); | 4878 | Qerror, read_non_regular_quit); |
| @@ -4894,11 +4891,7 @@ by calling `format-decode', which see. */) | |||
| 4894 | part of the buffer until all the reading is done, so a | 4891 | part of the buffer until all the reading is done, so a |
| 4895 | C-g here doesn't do any harm. */ | 4892 | C-g here doesn't do any harm. */ |
| 4896 | { | 4893 | { |
| 4897 | this = emacs_fd_read (fd, | 4894 | this = emacs_fd_read (fd, buf, bufsize); if (this < 0) |
| 4898 | ((char *) BEG_ADDR + PT_BYTE - BEG_BYTE | ||
| 4899 | + inserted), | ||
| 4900 | trytry); | ||
| 4901 | if (this < 0) | ||
| 4902 | this = -errno; | 4895 | this = -errno; |
| 4903 | } | 4896 | } |
| 4904 | 4897 | ||
| @@ -4908,6 +4901,20 @@ by calling `format-decode', which see. */) | |||
| 4908 | break; | 4901 | break; |
| 4909 | } | 4902 | } |
| 4910 | 4903 | ||
| 4904 | if (buf == read_buf) | ||
| 4905 | { | ||
| 4906 | if (gap_size < this) | ||
| 4907 | { | ||
| 4908 | /* Size estimate was low. Make the gap at least 50% larger, | ||
| 4909 | and big enough so that the next loop iteration will | ||
| 4910 | use the gap directly instead of copying via read_buf. */ | ||
| 4911 | make_gap (max (GAP_SIZE >> 1, | ||
| 4912 | this - gap_size + sizeof read_buf)); | ||
| 4913 | gap_size = GAP_SIZE - inserted; | ||
| 4914 | } | ||
| 4915 | memcpy (BEG_ADDR + PT_BYTE - BEG_BYTE + inserted, | ||
| 4916 | read_buf, this); | ||
| 4917 | } | ||
| 4911 | gap_size -= this; | 4918 | gap_size -= this; |
| 4912 | inserted += this; | 4919 | inserted += this; |
| 4913 | } | 4920 | } |