2 Internal file viewer for the Midnight Commander
3 Function for work with growing bufers
5 Copyright (C) 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2003,
6 2004, 2005, 2006, 2007, 2009, 2011
7 The Free Software Foundation, Inc.
10 Miguel de Icaza, 1994, 1995, 1998
11 Janne Kukonlehto, 1994, 1995
13 Joseph M. Hinkle, 1996
16 Roland Illig <roland.illig@gmx.de>, 2004, 2005
17 Slava Zanko <slavazanko@google.com>, 2009
18 Andrew Borodin <aborodin@vmail.ru>, 2009
19 Ilia Maslakov <il.smind@gmail.com>, 2009
21 This file is part of the Midnight Commander.
23 The Midnight Commander is free software: you can redistribute it
24 and/or modify it under the terms of the GNU General Public License as
25 published by the Free Software Foundation, either version 3 of the License,
26 or (at your option) any later version.
28 The Midnight Commander is distributed in the hope that it will be useful,
29 but WITHOUT ANY WARRANTY; without even the implied warranty of
30 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31 GNU General Public License for more details.
33 You should have received a copy of the GNU General Public License
34 along with this program. If not, see <http://www.gnu.org/licenses/>.
40 #include "lib/global.h"
41 #include "lib/vfs/vfs.h"
43 #include "lib/widget.h" /* D_NORMAL */
47 /* Block size for reading files in parts */
48 #define VIEW_PAGE_SIZE ((size_t) 8192)
50 /*** global variables ****************************************************************************/
52 /*** file scope macro definitions ****************************************************************/
54 /*** file scope type declarations ****************************************************************/
56 /*** file scope variables ************************************************************************/
58 /*** file scope functions ************************************************************************/
59 /* --------------------------------------------------------------------------------------------- */
61 /* --------------------------------------------------------------------------------------------- */
62 /*** public functions ****************************************************************************/
63 /* --------------------------------------------------------------------------------------------- */
66 mcview_growbuf_init (mcview_t
* view
)
68 view
->growbuf_in_use
= TRUE
;
69 view
->growbuf_blockptr
= g_ptr_array_new ();
70 view
->growbuf_lastindex
= VIEW_PAGE_SIZE
;
71 view
->growbuf_finished
= FALSE
;
74 /* --------------------------------------------------------------------------------------------- */
77 mcview_growbuf_free (mcview_t
* view
)
80 assert (view
->growbuf_in_use
);
83 g_ptr_array_foreach (view
->growbuf_blockptr
, (GFunc
) g_free
, NULL
);
85 (void) g_ptr_array_free (view
->growbuf_blockptr
, TRUE
);
87 view
->growbuf_blockptr
= NULL
;
88 view
->growbuf_in_use
= FALSE
;
91 /* --------------------------------------------------------------------------------------------- */
94 mcview_growbuf_filesize (mcview_t
* view
)
97 assert (view
->growbuf_in_use
);
100 if (view
->growbuf_blockptr
->len
== 0)
103 return ((off_t
) view
->growbuf_blockptr
->len
- 1) * VIEW_PAGE_SIZE
+ view
->growbuf_lastindex
;
106 /* --------------------------------------------------------------------------------------------- */
107 /** Copies the output from the pipe to the growing buffer, until either
108 * the end-of-pipe is reached or the interval [0..ofs) of the growing
109 * buffer is completely filled.
113 mcview_growbuf_read_until (mcview_t
* view
, off_t ofs
)
121 assert (view
->growbuf_in_use
);
124 if (view
->growbuf_finished
)
128 while (mcview_growbuf_filesize (view
) < ofs
|| short_read
)
130 if (view
->growbuf_lastindex
== VIEW_PAGE_SIZE
)
132 /* Append a new block to the growing buffer */
133 byte
*newblock
= g_try_malloc (VIEW_PAGE_SIZE
);
134 if (newblock
== NULL
)
137 g_ptr_array_add (view
->growbuf_blockptr
, newblock
);
138 view
->growbuf_lastindex
= 0;
140 p
= g_ptr_array_index (view
->growbuf_blockptr
,
141 view
->growbuf_blockptr
->len
- 1) + view
->growbuf_lastindex
;
143 bytesfree
= VIEW_PAGE_SIZE
- view
->growbuf_lastindex
;
145 if (view
->datasource
== DS_STDIO_PIPE
)
147 nread
= fread (p
, 1, bytesfree
, view
->ds_stdio_pipe
);
150 view
->growbuf_finished
= TRUE
;
151 (void) pclose (view
->ds_stdio_pipe
);
152 mcview_display (view
);
153 close_error_pipe (D_NORMAL
, NULL
);
154 view
->ds_stdio_pipe
= NULL
;
161 assert (view
->datasource
== DS_VFS_PIPE
);
165 nread
= mc_read (view
->ds_vfs_pipe
, p
, bytesfree
);
167 while (nread
== -1 && errno
== EINTR
);
168 if (nread
== -1 || nread
== 0)
170 view
->growbuf_finished
= TRUE
;
171 (void) mc_close (view
->ds_vfs_pipe
);
172 view
->ds_vfs_pipe
= -1;
176 short_read
= ((size_t) nread
< bytesfree
);
177 view
->growbuf_lastindex
+= nread
;
181 /* --------------------------------------------------------------------------------------------- */
184 mcview_get_byte_growing_buffer (mcview_t
* view
, off_t byte_index
, int *retval
)
192 pageno
= byte_index
/ VIEW_PAGE_SIZE
;
193 pageindex
= byte_index
% VIEW_PAGE_SIZE
;
196 assert (view
->growbuf_in_use
);
202 mcview_growbuf_read_until (view
, byte_index
+ 1);
203 if (view
->growbuf_blockptr
->len
== 0)
205 if (pageno
< (off_t
) view
->growbuf_blockptr
->len
- 1)
208 *retval
= *((byte
*) (g_ptr_array_index (view
->growbuf_blockptr
, pageno
) + pageindex
));
211 if (pageno
== (off_t
) view
->growbuf_blockptr
->len
- 1
212 && pageindex
< (off_t
) view
->growbuf_lastindex
)
215 *retval
= *((byte
*) (g_ptr_array_index (view
->growbuf_blockptr
, pageno
) + pageindex
));
221 /* --------------------------------------------------------------------------------------------- */
224 mcview_get_ptr_growing_buffer (mcview_t
* view
, off_t byte_index
)
226 off_t pageno
= byte_index
/ VIEW_PAGE_SIZE
;
227 off_t pageindex
= byte_index
% VIEW_PAGE_SIZE
;
230 assert (view
->growbuf_in_use
);
236 mcview_growbuf_read_until (view
, byte_index
+ 1);
237 if (view
->growbuf_blockptr
->len
== 0)
239 if (pageno
< (off_t
) view
->growbuf_blockptr
->len
- 1)
240 return (char *) (g_ptr_array_index (view
->growbuf_blockptr
, pageno
) + pageindex
);
241 if (pageno
== (off_t
) view
->growbuf_blockptr
->len
- 1
242 && pageindex
< (off_t
) view
->growbuf_lastindex
)
243 return (char *) (g_ptr_array_index (view
->growbuf_blockptr
, pageno
) + pageindex
);
247 /* --------------------------------------------------------------------------------------------- */