3 Copyright (C) 2005 and later Cockos Incorporated
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
22 This file provides the WDL_FileRead object, which can be used to read files.
23 On windows systems it supports reading synchronous, asynchronous, memory mapped, and asynchronous unbuffered.
24 On non-windows systems it acts as a wrapper for fopen()/etc.
30 #ifndef _WDL_FILEREAD_H_
31 #define _WDL_FILEREAD_H_
40 #if defined(_WIN32) && !defined(WDL_NO_WIN32_FILEREAD)
41 #ifndef WDL_WIN32_NATIVE_READ
42 #define WDL_WIN32_NATIVE_READ
45 #ifdef WDL_WIN32_NATIVE_READ
46 #undef WDL_WIN32_NATIVE_READ
49 #if !defined(WDL_NO_POSIX_FILEREAD)
50 #define WDL_POSIX_NATIVE_READ
51 #include <sys/fcntl.h>
54 #include <sys/errno.h>
57 #include <sys/param.h>
58 #include <sys/mount.h>
67 #define WDL_FILEREAD_POSTYPE __int64
69 #define WDL_FILEREAD_POSTYPE long long
74 #ifdef WDL_WIN32_NATIVE_READ
77 class WDL_FileRead__ReadEnt
80 WDL_FileRead__ReadEnt(int sz
, char *buf
)
83 memset(&m_ol
,0,sizeof(m_ol
));
84 m_ol
.hEvent
=CreateEvent(NULL
,TRUE
,TRUE
,NULL
);
87 ~WDL_FileRead__ReadEnt()
89 CloseHandle(m_ol
.hEvent
);
99 #if defined(_WIN32) && !defined(WDL_NO_SUPPORT_UTF8)
100 BOOL
HasUTF8(const char *_str
)
102 const unsigned char *str
= (const unsigned char *)_str
;
103 if (!str
) return FALSE
;
106 unsigned char c
= *str
;
109 if (c
<= 0xDF && str
[1] >=0x80 && str
[1] <= 0xBF) return TRUE
;
110 else if (c
<= 0xEF && str
[1] >=0x80 && str
[1] <= 0xBF && str
[2] >=0x80 && str
[2] <= 0xBF) return TRUE
;
111 else if (c
<= 0xF4 && str
[1] >=0x80 && str
[1] <= 0xBF && str
[2] >=0x80 && str
[2] <= 0xBF) return TRUE
;
120 // allow_async=1 for unbuffered async, 2 for buffered async, =-1 for unbuffered sync
121 // async aspect is unused on OS X, but the buffered mode affects F_NOCACHE
122 WDL_FileRead(const char *filename
, int allow_async
=1, int bufsize
=8192, int nbufs
=4, unsigned int mmap_minsize
=0, unsigned int mmap_maxsize
=0) : m_bufspace(4096 WDL_HEAPBUF_TRACEPARM("WDL_FileRead"))
124 m_async_hashaderr
=false;
125 m_sync_bufmode_used
=m_sync_bufmode_pos
=0;
126 m_async_readpos
=m_file_position
=0;
128 m_fsize_maychange
=false;
129 m_syncrd_firstbuf
=true;
131 m_mmap_totalbufmode
=0;
133 #define WDL_UNBUF_ALIGN 8192
134 if (bufsize
&(WDL_UNBUF_ALIGN
-1)) bufsize
=(bufsize
&~(WDL_UNBUF_ALIGN
-1))+WDL_UNBUF_ALIGN
; // ensure bufsize is multiple of 4kb
136 #ifdef WDL_WIN32_NATIVE_READ
140 #ifdef WDL_SUPPORT_WIN9X
141 const bool isNT
= GetVersion()<0x80000000;
143 const bool isNT
= true;
145 m_async
= isNT
? allow_async
: 0;
147 int flags
=FILE_ATTRIBUTE_NORMAL
;
150 flags
|=FILE_FLAG_OVERLAPPED
;
151 if (m_async
==1) flags
|=FILE_FLAG_NO_BUFFERING
;
153 else if (nbufs
*bufsize
>=WDL_UNBUF_ALIGN
&& !mmap_maxsize
&& m_async
==-1)
154 flags
|=FILE_FLAG_NO_BUFFERING
; // non-async mode unbuffered if we do our own buffering
156 #ifndef WDL_NO_SUPPORT_UTF8
157 m_fh
= INVALID_HANDLE_VALUE
;
158 if (isNT
&& HasUTF8(filename
)) // only convert to wide if there are UTF-8 chars
160 int szreq
=MultiByteToWideChar(CP_UTF8
,MB_ERR_INVALID_CHARS
,filename
,-1,NULL
,0);
163 WDL_TypedBuf
<WCHAR
> wfilename
;
164 wfilename
.Resize(szreq
+10);
166 if (MultiByteToWideChar(CP_UTF8
,MB_ERR_INVALID_CHARS
,filename
,-1,wfilename
.Get(),wfilename
.GetSize()))
168 m_fh
= CreateFileW(wfilename
.Get(),GENERIC_READ
,FILE_SHARE_READ
,NULL
,OPEN_EXISTING
,flags
,NULL
);
169 if (m_fh
== INVALID_HANDLE_VALUE
&& GetLastError()==ERROR_SHARING_VIOLATION
)
171 m_fh
= CreateFileW(wfilename
.Get(),GENERIC_READ
,FILE_SHARE_READ
|FILE_SHARE_WRITE
,NULL
,OPEN_EXISTING
,flags
,NULL
);
172 m_fsize_maychange
=true;
178 WCHAR wfilename
[1024];
180 if (MultiByteToWideChar(CP_UTF8
,MB_ERR_INVALID_CHARS
,filename
,-1,wfilename
,1024))
182 m_fh
= CreateFileW(wfilename
,GENERIC_READ
,FILE_SHARE_READ
,NULL
,OPEN_EXISTING
,flags
,NULL
);
183 if (m_fh
== INVALID_HANDLE_VALUE
&& GetLastError()==ERROR_SHARING_VIOLATION
)
185 m_fh
= CreateFileW(wfilename
,GENERIC_READ
,FILE_SHARE_READ
|FILE_SHARE_WRITE
,NULL
,OPEN_EXISTING
,flags
,NULL
);
186 m_fsize_maychange
=true;
191 if (m_fh
== INVALID_HANDLE_VALUE
)
194 m_fh
= CreateFileA(filename
,GENERIC_READ
,FILE_SHARE_READ
,NULL
,OPEN_EXISTING
,flags
,NULL
);
195 if (m_fh
== INVALID_HANDLE_VALUE
&& GetLastError()==ERROR_SHARING_VIOLATION
)
197 m_fh
= CreateFileA(filename
,GENERIC_READ
,FILE_SHARE_READ
|FILE_SHARE_WRITE
,NULL
,OPEN_EXISTING
,flags
,NULL
);
198 m_fsize_maychange
=true;
202 if (m_fh
!= INVALID_HANDLE_VALUE
)
205 DWORD l
=GetFileSize(m_fh
,&h
);
206 m_fsize
=(((WDL_FILEREAD_POSTYPE
)h
)<<32)|l
;
208 if (!h
&& l
< mmap_maxsize
&& m_async
<=0)
210 if (l
>= mmap_minsize
)
212 m_mmap_fmap
=CreateFileMapping(m_fh
,NULL
,PAGE_READONLY
,NULL
,0,NULL
);
215 m_mmap_view
=MapViewOfFile(m_mmap_fmap
,FILE_MAP_READ
,0,0,(int)m_fsize
);
218 CloseHandle(m_mmap_fmap
);
221 else m_fsize_maychange
=false;
226 m_mmap_totalbufmode
= malloc(l
);
228 ReadFile(m_fh
,m_mmap_totalbufmode
,l
,&sz
,NULL
);
229 m_fsize_maychange
=false;
235 m_async_bufsize
=bufsize
;
237 char *bptr
=(char *)m_bufspace
.Resize(nbufs
*bufsize
+ (WDL_UNBUF_ALIGN
-1));
238 int a
=((int)(INT_PTR
)bptr
)&(WDL_UNBUF_ALIGN
-1);
239 if (a
) bptr
+= WDL_UNBUF_ALIGN
-a
;
240 for (x
= 0; x
< nbufs
; x
++)
242 WDL_FileRead__ReadEnt
*t
=new WDL_FileRead__ReadEnt(m_async_bufsize
,bptr
);
244 bptr
+=m_async_bufsize
;
247 else if (!m_mmap_view
&& !m_mmap_totalbufmode
&& nbufs
*bufsize
>=WDL_UNBUF_ALIGN
)
249 m_bufspace
.Resize(nbufs
*bufsize
+(WDL_UNBUF_ALIGN
-1));
253 #elif defined(WDL_POSIX_NATIVE_READ)
254 m_filedes_locked
=false;
256 m_filedes
=open(filename
,O_RDONLY
);
259 if (flock(m_filedes
,LOCK_SH
|LOCK_NB
)>=0) // get shared lock
260 m_filedes_locked
=true;
262 m_fsize_maychange
=true; // if couldnt get shared lock, then it may change
265 if (allow_async
==1 || allow_async
==-1)
268 if (fstatfs(m_filedes
,&sfs
)||(sfs
.f_flags
&MNT_LOCAL
)) // don't use F_NOCACHE on nfs/smb/afp mounts, we need caching there!
269 fcntl(m_filedes
,F_NOCACHE
,1);
272 m_fsize
=lseek(m_filedes
,0,SEEK_END
);
273 lseek(m_filedes
,0,SEEK_SET
);
275 if (m_fsize
< mmap_maxsize
)
277 if (m_fsize
>= mmap_minsize
)
279 m_mmap_view
= mmap(NULL
,m_fsize
,PROT_READ
,MAP_SHARED
,m_filedes
,0);
280 if (m_mmap_view
== MAP_FAILED
) m_mmap_view
= 0;
281 else m_fsize_maychange
=false;
285 m_mmap_totalbufmode
= malloc(m_fsize
);
286 m_fsize
= pread(m_filedes
,m_mmap_totalbufmode
,m_fsize
,0);
287 m_fsize_maychange
=false;
292 if (!m_mmap_view
&& !m_mmap_totalbufmode
&& m_filedes
>=0 && nbufs
*bufsize
>=WDL_UNBUF_ALIGN
)
293 m_bufspace
.Resize(nbufs
*bufsize
+(WDL_UNBUF_ALIGN
-1));
296 m_fp
=fopen(filename
,"rb");
299 fseek(m_fp
,0,SEEK_END
);
301 fseek(m_fp
,0,SEEK_SET
);
303 if (m_fp
&& nbufs
*bufsize
>=WDL_UNBUF_ALIGN
)
304 m_bufspace
.Resize(nbufs
*bufsize
+(WDL_UNBUF_ALIGN
-1));
310 free(m_mmap_totalbufmode
);
311 m_mmap_totalbufmode
=0;
313 #ifdef WDL_WIN32_NATIVE_READ
315 for (x
= 0; x
< m_empties
.GetSize();x
++) delete m_empties
.Get(x
);
317 for (x
= 0; x
< m_full
.GetSize();x
++) delete m_full
.Get(x
);
319 for (x
= 0; x
< m_pending
.GetSize();x
++)
321 WaitForSingleObject(m_pending
.Get(x
)->m_ol
.hEvent
,INFINITE
);
322 delete m_pending
.Get(x
);
326 if (m_mmap_view
) UnmapViewOfFile(m_mmap_view
);
329 if (m_mmap_fmap
) CloseHandle(m_mmap_fmap
);
332 if (m_fh
!= INVALID_HANDLE_VALUE
) CloseHandle(m_fh
);
333 m_fh
=INVALID_HANDLE_VALUE
;
334 #elif defined(WDL_POSIX_NATIVE_READ)
335 if (m_mmap_view
) munmap(m_mmap_view
,m_fsize
);
339 if (m_filedes_locked
) flock(m_filedes
,LOCK_UN
); // release shared lock
344 if (m_fp
) fclose(m_fp
);
352 #ifdef WDL_WIN32_NATIVE_READ
353 return (m_fh
!= INVALID_HANDLE_VALUE
);
354 #elif defined(WDL_POSIX_NATIVE_READ)
355 return m_filedes
>= 0;
361 #ifdef WDL_WIN32_NATIVE_READ
365 while (m_pending
.GetSize())
367 WDL_FileRead__ReadEnt
*ent
=m_pending
.Get(0);
370 if (!ent
->m_size
&& !GetOverlappedResult(m_fh
,&ent
->m_ol
,&s
,FALSE
)) break;
372 if (!ent
->m_size
) ent
->m_size
=s
;
377 if (m_empties
.GetSize()>0)
379 if (m_async_readpos
< m_file_position
) m_async_readpos
= m_file_position
;
381 if (m_async
==1) m_async_readpos
&= ~((WDL_FILEREAD_POSTYPE
) WDL_UNBUF_ALIGN
-1);
383 if (m_async_readpos
>= m_fsize
) return 0;
385 const int rdidx
=m_empties
.GetSize()-1;
386 WDL_FileRead__ReadEnt
*t
=m_empties
.Get(rdidx
);
388 ResetEvent(t
->m_ol
.hEvent
);
390 *(WDL_FILEREAD_POSTYPE
*)&t
->m_ol
.Offset
= m_async_readpos
;
392 m_async_readpos
+= m_async_bufsize
;
394 if (ReadFile(m_fh
,t
->m_buf
,m_async_bufsize
,&dw
,&t
->m_ol
))
400 if (GetLastError() != ERROR_IO_PENDING
) return 1;
404 m_empties
.Delete(rdidx
);
410 int AsyncRead(char *buf
, int maxlen
)
414 if (m_file_position
+maxlen
> m_fsize
)
416 maxlen
=(int) (m_fsize
-m_file_position
);
418 if (maxlen
<1) return 0;
420 int errcnt
=!!m_async_hashaderr
;
423 while (m_full
.GetSize() > 0)
425 WDL_FileRead__ReadEnt
*ti
=m_full
.Get(0);
426 WDL_FILEREAD_POSTYPE tiofs
=*(WDL_FILEREAD_POSTYPE
*)&ti
->m_ol
.Offset
;
427 if (m_file_position
>= tiofs
&& m_file_position
< tiofs
+ ti
->m_size
)
429 if (maxlen
< 1) break;
431 int l
=ti
->m_size
-(int) (m_file_position
-tiofs
);
432 if (l
> maxlen
) l
=maxlen
;
434 memcpy(buf
,(char *)ti
->m_buf
+m_file_position
- tiofs
,l
);
436 m_file_position
+= l
;
447 if (maxlen
> 0 && m_async_readpos
!= m_file_position
)
450 for (x
= 0; x
< m_pending
.GetSize(); x
++)
452 WDL_FileRead__ReadEnt
*ent
=m_pending
.Get(x
);
453 WDL_FILEREAD_POSTYPE tiofs
=*(WDL_FILEREAD_POSTYPE
*)&ent
->m_ol
.Offset
;
454 if (m_file_position
>= tiofs
&& m_file_position
< tiofs
+ m_async_bufsize
) break;
456 if (x
== m_pending
.GetSize())
458 m_async_readpos
=m_file_position
;
464 if (maxlen
> 0 && m_pending
.GetSize() && !m_full
.GetSize())
466 WDL_FileRead__ReadEnt
*ent
=m_pending
.Get(0);
469 if (ent
->m_size
) m_full
.Add(ent
);
472 // WaitForSingleObject(ent->m_ol.hEvent,INFINITE);
475 if (GetOverlappedResult(m_fh
,&ent
->m_ol
,&s
,TRUE
) && s
)
480 else // failed read, set the error flag
489 while (maxlen
> 0 && (m_pending
.GetSize()||m_full
.GetSize()) && !errcnt
);
490 if (!errcnt
) RunReads();
491 else m_async_hashaderr
=true;
498 void *GetMappedView(int offs
, int *len
)
500 if (!m_mmap_view
&& !m_mmap_totalbufmode
) return 0;
502 int maxl
=(int) (m_fsize
-(WDL_FILEREAD_POSTYPE
)offs
);
503 if (*len
> maxl
) *len
=maxl
;
505 return (char *)m_mmap_view
+ offs
;
507 return (char *)m_mmap_totalbufmode
+ offs
;
510 int Read(void *buf
, int len
)
512 if (m_mmap_view
||m_mmap_totalbufmode
)
514 int maxl
=(int) (m_fsize
-m_file_position
);
515 if (maxl
> len
) maxl
=len
;
516 if (maxl
< 0) maxl
=0;
520 memcpy(buf
,(char *)m_mmap_view
+ (int)m_file_position
,maxl
);
522 memcpy(buf
,(char *)m_mmap_totalbufmode
+ (int)m_file_position
,maxl
);
525 m_file_position
+=maxl
;
529 if (m_fsize_maychange
) GetSize(); // update m_fsize
531 #ifdef WDL_WIN32_NATIVE_READ
532 if (m_fh
== INVALID_HANDLE_VALUE
||len
<1) return 0;
536 return AsyncRead((char *)buf
,len
);
538 #elif defined(WDL_POSIX_NATIVE_READ)
539 if (m_filedes
<0 || len
<1) return 0;
542 if (!m_fp
|| len
<1) return 0;
546 if (m_bufspace
.GetSize()>=WDL_UNBUF_ALIGN
*2-1)
549 int sz
=m_bufspace
.GetSize()-(WDL_UNBUF_ALIGN
-1);
550 char *srcbuf
=(char *)m_bufspace
.Get(); // read size
551 if (((int)(INT_PTR
)srcbuf
)&(WDL_UNBUF_ALIGN
-1)) srcbuf
+= WDL_UNBUF_ALIGN
-(((int)(INT_PTR
)srcbuf
)&(WDL_UNBUF_ALIGN
-1));
554 int a
=m_sync_bufmode_used
-m_sync_bufmode_pos
;
555 if (a
>(len
-rdout
)) a
=(len
-rdout
);
558 memcpy((char*)buf
+rdout
,srcbuf
+m_sync_bufmode_pos
,a
);
560 m_sync_bufmode_pos
+=a
;
566 m_sync_bufmode_used
=0;
567 m_sync_bufmode_pos
=0;
570 if (m_syncrd_firstbuf
) // this is a scheduling mechanism to avoid having reads on various files always happening at the same time -- not needed in async modes, only in sync with large buffers
572 m_syncrd_firstbuf
=false;
573 const int blocks
= thissz
/WDL_UNBUF_ALIGN
;
576 static int rrs
; // may not be ideal on multithread, but having it incorrect isnt a big deal.
577 if (blocks
>7) thissz
>>= (rrs
++)&3;
578 else thissz
>>= (rrs
++)&1;
582 #ifdef WDL_WIN32_NATIVE_READ
586 if (m_file_position
&(WDL_UNBUF_ALIGN
-1))
588 int offs
= (int)(m_file_position
&(WDL_UNBUF_ALIGN
-1));
589 LONG high
=(LONG
) ((m_file_position
-offs
)>>32);
590 SetFilePointer(m_fh
,(LONG
)((m_file_position
-offs
)&((WDL_FILEREAD_POSTYPE
)0xFFFFFFFF)),&high
,FILE_BEGIN
);
591 m_sync_bufmode_pos
=offs
;
594 if (!ReadFile(m_fh
,srcbuf
,thissz
,&o
,NULL
) || o
<1 || m_sync_bufmode_pos
>=(int)o
)
598 #elif defined(WDL_POSIX_NATIVE_READ)
599 int o
=(int)pread(m_filedes
,srcbuf
,thissz
,m_filedes_rdpos
);
600 if (o
>0) m_filedes_rdpos
+=o
;
601 if (o
<1 || m_sync_bufmode_pos
>=o
) break;
604 int o
=(int)fread(srcbuf
,1,thissz
,m_fp
);
605 if (o
<1 || m_sync_bufmode_pos
>=o
) break;
607 m_sync_bufmode_used
=o
;
615 #ifdef WDL_WIN32_NATIVE_READ
617 ReadFile(m_fh
,buf
,len
,&dw
,NULL
);
620 #elif defined(WDL_POSIX_NATIVE_READ)
622 int ret
=(int)pread(m_filedes
,buf
,len
,m_filedes_rdpos
);
623 if (ret
>0) m_filedes_rdpos
+=ret
;
624 m_file_position
+=ret
;
627 int ret
=fread(buf
,1,len
,m_fp
);
628 m_file_position
+=ret
;
635 WDL_FILEREAD_POSTYPE
GetSize()
637 #ifdef WDL_WIN32_NATIVE_READ
638 if (m_fh
== INVALID_HANDLE_VALUE
) return 0;
639 #elif defined(WDL_POSIX_NATIVE_READ)
640 if (m_filedes
<0) return -1;
643 if (!m_fp
) return -1;
646 if (m_fsize_maychange
)
648 #ifdef WDL_WIN32_NATIVE_READ
650 DWORD l
=GetFileSize(m_fh
,&h
);
651 m_fsize
=(((WDL_FILEREAD_POSTYPE
)h
)<<32)|l
;
652 #elif defined(WDL_POSIX_NATIVE_READ)
654 if (!fstat64(m_filedes
,&st
)) m_fsize
= st
.st_size
;
662 WDL_FILEREAD_POSTYPE
GetPosition()
664 #ifdef WDL_WIN32_NATIVE_READ
665 if (m_fh
== INVALID_HANDLE_VALUE
) return -1;
666 #elif defined(WDL_POSIX_NATIVE_READ)
667 if (m_filedes
<0) return -1;
669 if (!m_fp
) return -1;
671 return m_file_position
;
674 bool SetPosition(WDL_FILEREAD_POSTYPE pos
) // returns 0 on success
676 m_async_hashaderr
=false;
678 #ifdef WDL_WIN32_NATIVE_READ
679 if (m_fh
== INVALID_HANDLE_VALUE
) return true;
680 #elif defined(WDL_POSIX_NATIVE_READ)
681 if (m_filedes
<0) return true;
683 if (!m_fp
) return true;
686 if (m_fsize_maychange
) GetSize();
689 if (pos
> m_fsize
) pos
=m_fsize
;
690 WDL_FILEREAD_POSTYPE oldpos
=m_file_position
;
691 if (m_file_position
!=pos
) m_file_position
=pos
;
694 if (m_mmap_view
||m_mmap_totalbufmode
) return false;
696 #ifdef WDL_WIN32_NATIVE_READ
699 WDL_FileRead__ReadEnt
*ent
;
701 if (pos
> m_async_readpos
|| !(ent
=m_full
.Get(0)) || pos
< *(WDL_FILEREAD_POSTYPE
*)&ent
->m_ol
.Offset
)
711 if (m_bufspace
.GetSize()>=WDL_UNBUF_ALIGN
*2-1)
713 if (pos
>= oldpos
-m_sync_bufmode_pos
&& pos
< oldpos
-m_sync_bufmode_pos
+ m_sync_bufmode_used
)
715 int diff
=(int) (pos
-oldpos
);
716 m_sync_bufmode_pos
+=diff
;
720 m_sync_bufmode_pos
=m_sync_bufmode_used
=0;
723 m_syncrd_firstbuf
=true;
724 #ifdef WDL_WIN32_NATIVE_READ
725 LONG high
=(LONG
) (m_file_position
>>32);
726 return SetFilePointer(m_fh
,(LONG
)(m_file_position
&((WDL_FILEREAD_POSTYPE
)0xFFFFFFFF)),&high
,FILE_BEGIN
)==0xFFFFFFFF && GetLastError() != NO_ERROR
;
727 #elif defined(WDL_POSIX_NATIVE_READ)
728 m_filedes_rdpos
= m_file_position
;
731 return !!fseek(m_fp
,m_file_position
,SEEK_SET
);
735 WDL_HeapBuf m_bufspace
;
736 int m_sync_bufmode_used
, m_sync_bufmode_pos
;
738 WDL_FILEREAD_POSTYPE m_file_position
,m_async_readpos
;
739 WDL_FILEREAD_POSTYPE m_fsize
;
742 void *m_mmap_totalbufmode
;
744 #ifdef WDL_WIN32_NATIVE_READ
745 HANDLE
GetHandle() { return m_fh
; }
749 int m_async
; // 1=nobuf, 2=buffered async, -1=unbuffered sync
752 WDL_PtrList
<WDL_FileRead__ReadEnt
> m_empties
;
753 WDL_PtrList
<WDL_FileRead__ReadEnt
> m_pending
;
754 WDL_PtrList
<WDL_FileRead__ReadEnt
> m_full
;
756 #elif defined(WDL_POSIX_NATIVE_READ)
757 WDL_FILEREAD_POSTYPE m_filedes_rdpos
;
759 bool m_filedes_locked
;
761 int GetHandle() { return m_filedes
; }
765 int GetHandle() { return fileno(m_fp
); }
768 bool m_fsize_maychange
;
769 bool m_syncrd_firstbuf
;
770 bool m_async_hashaderr
;