Merge pull request #110 from tesselode/fixes
[wdl/wdl-ol.git] / WDL / fileread.h
blobc185e96a9a79493aa4441543673eba1794f55c22
1 /*
2 WDL - fileread.h
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_
36 #include "ptrlist.h"
40 #if defined(_WIN32) && !defined(WDL_NO_WIN32_FILEREAD)
41 #ifndef WDL_WIN32_NATIVE_READ
42 #define WDL_WIN32_NATIVE_READ
43 #endif
44 #else
45 #ifdef WDL_WIN32_NATIVE_READ
46 #undef WDL_WIN32_NATIVE_READ
47 #endif
49 #if !defined(WDL_NO_POSIX_FILEREAD)
50 #define WDL_POSIX_NATIVE_READ
51 #include <sys/fcntl.h>
52 #include <sys/file.h>
53 #include <sys/stat.h>
54 #include <sys/errno.h>
55 #include <sys/mman.h>
56 #ifdef __APPLE__
57 #include <sys/param.h>
58 #include <sys/mount.h>
59 #endif
60 #endif
62 #endif
66 #ifdef _MSC_VER
67 #define WDL_FILEREAD_POSTYPE __int64
68 #else
69 #define WDL_FILEREAD_POSTYPE long long
70 #endif
71 class WDL_FileRead
74 #ifdef WDL_WIN32_NATIVE_READ
77 class WDL_FileRead__ReadEnt
79 public:
80 WDL_FileRead__ReadEnt(int sz, char *buf)
82 m_size=0;
83 memset(&m_ol,0,sizeof(m_ol));
84 m_ol.hEvent=CreateEvent(NULL,TRUE,TRUE,NULL);
85 m_buf=buf;
87 ~WDL_FileRead__ReadEnt()
89 CloseHandle(m_ol.hEvent);
92 OVERLAPPED m_ol;
93 DWORD m_size;
94 LPVOID m_buf;
97 #endif
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;
104 while (*str)
106 unsigned char c = *str;
107 if (c >= 0xC2)
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;
113 str++;
115 return FALSE;
117 #endif
119 public:
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;
127 m_fsize=0;
128 m_fsize_maychange=false;
129 m_syncrd_firstbuf=true;
130 m_mmap_view=0;
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
138 m_mmap_fmap=0;
140 #ifdef WDL_SUPPORT_WIN9X
141 const bool isNT = GetVersion()<0x80000000;
142 #else
143 const bool isNT = true;
144 #endif
145 m_async = isNT ? allow_async : 0;
147 int flags=FILE_ATTRIBUTE_NORMAL;
148 if (m_async>0)
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);
161 if (szreq > 1000)
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;
176 else
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)
192 #endif
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)
204 DWORD h=0;
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);
213 if (m_mmap_fmap)
215 m_mmap_view=MapViewOfFile(m_mmap_fmap,FILE_MAP_READ,0,0,(int)m_fsize);
216 if (!m_mmap_view)
218 CloseHandle(m_mmap_fmap);
219 m_mmap_fmap=0;
221 else m_fsize_maychange=false;
224 else if (l>0)
226 m_mmap_totalbufmode = malloc(l);
227 DWORD sz;
228 ReadFile(m_fh,m_mmap_totalbufmode,l,&sz,NULL);
229 m_fsize_maychange=false;
233 if (m_async>0)
235 m_async_bufsize=bufsize;
236 int x;
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);
243 m_empties.Add(t);
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;
255 m_filedes_rdpos=0;
256 m_filedes=open(filename,O_RDONLY);
257 if (m_filedes>=0)
259 if (flock(m_filedes,LOCK_SH|LOCK_NB)>=0) // get shared lock
260 m_filedes_locked=true;
261 else
262 m_fsize_maychange=true; // if couldnt get shared lock, then it may change
264 #ifdef __APPLE__
265 if (allow_async==1 || allow_async==-1)
267 struct statfs sfs;
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);
271 #endif
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;
283 else
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));
295 #else
296 m_fp=fopen(filename,"rb");
297 if(m_fp)
299 fseek(m_fp,0,SEEK_END);
300 m_fsize=ftell(m_fp);
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));
305 #endif
308 ~WDL_FileRead()
310 free(m_mmap_totalbufmode);
311 m_mmap_totalbufmode=0;
313 #ifdef WDL_WIN32_NATIVE_READ
314 int x;
315 for (x = 0; x < m_empties.GetSize();x ++) delete m_empties.Get(x);
316 m_empties.Empty();
317 for (x = 0; x < m_full.GetSize();x ++) delete m_full.Get(x);
318 m_full.Empty();
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);
324 m_pending.Empty();
326 if (m_mmap_view) UnmapViewOfFile(m_mmap_view);
327 m_mmap_view=0;
329 if (m_mmap_fmap) CloseHandle(m_mmap_fmap);
330 m_mmap_fmap=0;
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);
336 m_mmap_view=0;
337 if (m_filedes>=0)
339 if (m_filedes_locked) flock(m_filedes,LOCK_UN); // release shared lock
340 close(m_filedes);
342 m_filedes=-1;
343 #else
344 if (m_fp) fclose(m_fp);
345 m_fp=0;
346 #endif
350 bool IsOpen()
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;
356 #else
357 return m_fp != NULL;
358 #endif
361 #ifdef WDL_WIN32_NATIVE_READ
363 int RunReads()
365 while (m_pending.GetSize())
367 WDL_FileRead__ReadEnt *ent=m_pending.Get(0);
368 DWORD s=0;
370 if (!ent->m_size && !GetOverlappedResult(m_fh,&ent->m_ol,&s,FALSE)) break;
371 m_pending.Delete(0);
372 if (!ent->m_size) ent->m_size=s;
373 m_full.Add(ent);
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;
393 DWORD dw;
394 if (ReadFile(m_fh,t->m_buf,m_async_bufsize,&dw,&t->m_ol))
396 if (!dw) return 1;
398 else
400 if (GetLastError() != ERROR_IO_PENDING) return 1;
401 dw=0;
403 t->m_size=dw;
404 m_empties.Delete(rdidx);
405 m_pending.Add(t);
407 return 0;
410 int AsyncRead(char *buf, int maxlen)
412 char *obuf=buf;
413 int lenout=0;
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);
435 buf += l;
436 m_file_position += l;
437 maxlen -= l;
438 lenout += l;
440 else
442 m_empties.Add(ti);
443 m_full.Delete(0);
447 if (maxlen > 0 && m_async_readpos != m_file_position)
449 int x;
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;
462 errcnt+=RunReads();
464 if (maxlen > 0 && m_pending.GetSize() && !m_full.GetSize())
466 WDL_FileRead__ReadEnt *ent=m_pending.Get(0);
467 m_pending.Delete(0);
469 if (ent->m_size) m_full.Add(ent);
470 else
472 // WaitForSingleObject(ent->m_ol.hEvent,INFINITE);
474 DWORD s=0;
475 if (GetOverlappedResult(m_fh,&ent->m_ol,&s,TRUE) && s)
477 ent->m_size=s;
478 m_full.Add(ent);
480 else // failed read, set the error flag
482 errcnt++;
483 ent->m_size=0;
484 m_empties.Add(ent);
489 while (maxlen > 0 && (m_pending.GetSize()||m_full.GetSize()) && !errcnt);
490 if (!errcnt) RunReads();
491 else m_async_hashaderr=true;
493 return lenout;
496 #endif
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;
504 if (m_mmap_view)
505 return (char *)m_mmap_view + offs;
506 else
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;
517 if (maxl>0)
519 if (m_mmap_view)
520 memcpy(buf,(char *)m_mmap_view + (int)m_file_position,maxl);
521 else
522 memcpy(buf,(char *)m_mmap_totalbufmode + (int)m_file_position,maxl);
525 m_file_position+=maxl;
526 return 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;
534 if (m_async>0)
536 return AsyncRead((char *)buf,len);
538 #elif defined(WDL_POSIX_NATIVE_READ)
539 if (m_filedes<0 || len<1) return 0;
541 #else
542 if (!m_fp || len<1) return 0;
544 #endif
546 if (m_bufspace.GetSize()>=WDL_UNBUF_ALIGN*2-1)
548 int rdout=0;
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));
552 while (len > rdout)
554 int a=m_sync_bufmode_used-m_sync_bufmode_pos;
555 if (a>(len-rdout)) a=(len-rdout);
556 if (a>0)
558 memcpy((char*)buf+rdout,srcbuf+m_sync_bufmode_pos,a);
559 rdout+=a;
560 m_sync_bufmode_pos+=a;
561 m_file_position+=a;
564 if (len > rdout)
566 m_sync_bufmode_used=0;
567 m_sync_bufmode_pos=0;
569 int thissz=sz;
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;
574 if (blocks > 1)
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
583 DWORD o;
584 if (m_async==-1)
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)
596 break;
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;
603 #else
604 int o=(int)fread(srcbuf,1,thissz,m_fp);
605 if (o<1 || m_sync_bufmode_pos>=o) break;
606 #endif
607 m_sync_bufmode_used=o;
611 return rdout;
613 else
615 #ifdef WDL_WIN32_NATIVE_READ
616 DWORD dw=0;
617 ReadFile(m_fh,buf,len,&dw,NULL);
618 m_file_position+=dw;
619 return dw;
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;
625 return ret;
626 #else
627 int ret=fread(buf,1,len,m_fp);
628 m_file_position+=ret;
629 return ret;
630 #endif
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;
642 #else
643 if (!m_fp) return -1;
644 #endif
646 if (m_fsize_maychange)
648 #ifdef WDL_WIN32_NATIVE_READ
649 DWORD h=0;
650 DWORD l=GetFileSize(m_fh,&h);
651 m_fsize=(((WDL_FILEREAD_POSTYPE)h)<<32)|l;
652 #elif defined(WDL_POSIX_NATIVE_READ)
653 struct stat64 st;
654 if (!fstat64(m_filedes,&st)) m_fsize = st.st_size;
656 #endif
659 return m_fsize;
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;
668 #else
669 if (!m_fp) return -1;
670 #endif
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;
682 #else
683 if (!m_fp) return true;
684 #endif
686 if (m_fsize_maychange) GetSize();
688 if (pos < 0) pos=0;
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;
692 else return false;
694 if (m_mmap_view||m_mmap_totalbufmode) return false;
696 #ifdef WDL_WIN32_NATIVE_READ
697 if (m_async>0)
699 WDL_FileRead__ReadEnt *ent;
701 if (pos > m_async_readpos || !(ent=m_full.Get(0)) || pos < *(WDL_FILEREAD_POSTYPE *)&ent->m_ol.Offset)
703 m_async_readpos=pos;
706 return FALSE;
708 #endif
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;
718 return 0;
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;
729 return false;
730 #else
731 return !!fseek(m_fp,m_file_position,SEEK_SET);
732 #endif
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;
741 void *m_mmap_view;
742 void *m_mmap_totalbufmode;
744 #ifdef WDL_WIN32_NATIVE_READ
745 HANDLE GetHandle() { return m_fh; }
746 HANDLE m_fh;
747 HANDLE m_mmap_fmap;
748 int m_mmap_size;
749 int m_async; // 1=nobuf, 2=buffered async, -1=unbuffered sync
751 int m_async_bufsize;
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;
758 int m_filedes;
759 bool m_filedes_locked;
761 int GetHandle() { return m_filedes; }
762 #else
763 FILE *m_fp;
765 int GetHandle() { return fileno(m_fp); }
766 #endif
768 bool m_fsize_maychange;
769 bool m_syncrd_firstbuf;
770 bool m_async_hashaderr;
772 } WDL_FIXALIGN;
779 #endif