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 Free Software Foundation, Inc.
8 Written by: 1994, 1995, 1998 Miguel de Icaza
9 1994, 1995 Janne Kukonlehto
14 2004 Roland Illig <roland.illig@gmx.de>
15 2005 Roland Illig <roland.illig@gmx.de>
16 2009 Slava Zanko <slavazanko@google.com>
17 2009 Andrew Borodin <aborodin@vmail.ru>
18 2009 Ilia Maslakov <il.smind@gmail.com>
20 This file is part of the Midnight Commander.
22 The Midnight Commander is free software; you can redistribute it
23 and/or modify it under the terms of the GNU General Public License as
24 published by the Free Software Foundation; either version 2 of the
25 License, or (at your option) any later version.
27 The Midnight Commander is distributed in the hope that it will be
28 useful, but WITHOUT ANY WARRANTY; without even the implied warranty
29 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
30 General Public License for more details.
32 You should have received a copy of the GNU General Public License
33 along with this program; if not, write to the Free Software
34 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
41 #include "../src/global.h"
42 #include "../src/wtools.h"
45 /* Block size for reading files in parts */
46 #define VIEW_PAGE_SIZE ((size_t) 8192)
48 /*** global variables ****************************************************************************/
50 /*** file scope macro definitions ****************************************************************/
52 /*** file scope type declarations ****************************************************************/
54 /*** file scope variables ************************************************************************/
56 /*** file scope functions ************************************************************************/
58 /*** public functions ****************************************************************************/
60 /* --------------------------------------------------------------------------------------------- */
63 mcview_growbuf_init (mcview_t
* view
)
65 view
->growbuf_in_use
= TRUE
;
66 view
->growbuf_blockptr
= NULL
;
67 view
->growbuf_blocks
= 0;
68 view
->growbuf_lastindex
= VIEW_PAGE_SIZE
;
69 view
->growbuf_finished
= FALSE
;
72 /* --------------------------------------------------------------------------------------------- */
75 mcview_growbuf_free (mcview_t
* view
)
79 assert (view
->growbuf_in_use
);
81 for (i
= 0; i
< view
->growbuf_blocks
; i
++)
82 g_free (view
->growbuf_blockptr
[i
]);
83 g_free (view
->growbuf_blockptr
);
84 view
->growbuf_blockptr
= NULL
;
85 view
->growbuf_in_use
= FALSE
;
88 /* --------------------------------------------------------------------------------------------- */
91 mcview_growbuf_filesize (mcview_t
* view
)
93 assert (view
->growbuf_in_use
);
95 if (view
->growbuf_blocks
== 0)
98 return ((off_t
) view
->growbuf_blocks
- 1) * VIEW_PAGE_SIZE
+ view
->growbuf_lastindex
;
101 /* --------------------------------------------------------------------------------------------- */
103 /* Copies the output from the pipe to the growing buffer, until either
104 * the end-of-pipe is reached or the interval [0..ofs) of the growing
105 * buffer is completely filled. */
107 mcview_growbuf_read_until (mcview_t
* view
, off_t ofs
)
114 assert (view
->growbuf_in_use
);
116 if (view
->growbuf_finished
)
120 while (mcview_growbuf_filesize (view
) < ofs
|| short_read
) {
121 if (view
->growbuf_lastindex
== VIEW_PAGE_SIZE
) {
122 /* Append a new block to the growing buffer */
123 byte
*newblock
= g_try_malloc (VIEW_PAGE_SIZE
);
124 byte
**newblocks
= g_try_malloc (sizeof (*newblocks
) * (view
->growbuf_blocks
+ 1));
125 if (!newblock
|| !newblocks
) {
130 memcpy (newblocks
, view
->growbuf_blockptr
, sizeof (*newblocks
) * view
->growbuf_blocks
);
131 g_free (view
->growbuf_blockptr
);
132 view
->growbuf_blockptr
= newblocks
;
133 view
->growbuf_blockptr
[view
->growbuf_blocks
++] = newblock
;
134 view
->growbuf_lastindex
= 0;
136 p
= view
->growbuf_blockptr
[view
->growbuf_blocks
- 1] + view
->growbuf_lastindex
;
137 bytesfree
= VIEW_PAGE_SIZE
- view
->growbuf_lastindex
;
139 if (view
->datasource
== DS_STDIO_PIPE
) {
140 nread
= fread (p
, 1, bytesfree
, view
->ds_stdio_pipe
);
142 view
->growbuf_finished
= TRUE
;
143 (void) pclose (view
->ds_stdio_pipe
);
144 mcview_display (view
);
145 close_error_pipe (D_NORMAL
, NULL
);
146 view
->ds_stdio_pipe
= NULL
;
150 assert (view
->datasource
== DS_VFS_PIPE
);
152 nread
= mc_read (view
->ds_vfs_pipe
, p
, bytesfree
);
153 } while (nread
== -1 && errno
== EINTR
);
154 if (nread
== -1 || nread
== 0) {
155 view
->growbuf_finished
= TRUE
;
156 (void) mc_close (view
->ds_vfs_pipe
);
157 view
->ds_vfs_pipe
= -1;
161 short_read
= ((size_t) nread
< bytesfree
);
162 view
->growbuf_lastindex
+= nread
;
166 /* --------------------------------------------------------------------------------------------- */
169 mcview_get_byte_growing_buffer (mcview_t
* view
, off_t byte_index
, int *retval
)
177 pageno
= byte_index
/ VIEW_PAGE_SIZE
;
178 pageindex
= byte_index
% VIEW_PAGE_SIZE
;
180 assert (view
->growbuf_in_use
);
182 if ((size_t) pageno
!= pageno
)
185 mcview_growbuf_read_until (view
, byte_index
+ 1);
186 if (view
->growbuf_blocks
== 0)
188 if (pageno
< view
->growbuf_blocks
- 1) {
190 *retval
= view
->growbuf_blockptr
[pageno
][pageindex
];
193 if (pageno
== view
->growbuf_blocks
- 1 && pageindex
< view
->growbuf_lastindex
) {
195 *retval
= view
->growbuf_blockptr
[pageno
][pageindex
];
201 /* --------------------------------------------------------------------------------------------- */
204 mcview_get_ptr_growing_buffer (mcview_t
* view
, off_t byte_index
)
206 off_t pageno
= byte_index
/ VIEW_PAGE_SIZE
;
207 off_t pageindex
= byte_index
% VIEW_PAGE_SIZE
;
209 assert (view
->growbuf_in_use
);
211 if ((size_t) pageno
!= pageno
)
214 mcview_growbuf_read_until (view
, byte_index
+ 1);
215 if (view
->growbuf_blocks
== 0)
217 if (pageno
< view
->growbuf_blocks
- 1)
218 return (char *) (view
->growbuf_blockptr
[pageno
] + pageindex
);
219 if (pageno
== view
->growbuf_blocks
- 1 && pageindex
< view
->growbuf_lastindex
)
220 return (char *) (view
->growbuf_blockptr
[pageno
] + pageindex
);
224 /* --------------------------------------------------------------------------------------------- */