]> git.tdb.fi Git - libs/core.git/blob - source/io/seekable.cpp
35ab5a05104fef55fbe625a3e55cdff2d1b18590
[libs/core.git] / source / io / seekable.cpp
1 #ifndef WIN32
2 #define _LARGEFILE64_SOURCE
3 #include <cerrno>
4 #include <unistd.h>
5 #else
6 #include <windows.h>
7 #endif
8 #include <msp/core/systemerror.h>
9 #include <msp/strings/format.h>
10 #include "handle.h"
11 #include "handle_private.h"
12 #include "seekable.h"
13
14 using namespace std;
15
16 namespace {
17
18 using namespace Msp::IO;
19
20 int sys_seek_type(SeekType st)
21 {
22 #ifdef WIN32
23         if(st==S_BEG)
24                 return FILE_BEGIN;
25         else if(st==S_CUR)
26                 return FILE_CURRENT;
27         else if(st==S_END)
28                 return FILE_END;
29 #else
30         if(st==S_BEG)
31                 return SEEK_SET;
32         else if(st==S_CUR)
33                 return SEEK_CUR;
34         else if(st==S_END)
35                 return SEEK_END;
36 #endif
37
38         throw invalid_argument("sys_seek_type");
39 }
40
41 } // namespace
42
43
44 namespace Msp {
45 namespace IO {
46
47 bad_seek::bad_seek(SeekOffset offset, SeekType type):
48         runtime_error(type==S_BEG ? lexical_cast<string>(offset) :
49                 type==S_CUR ? format("CUR%+d", offset) :
50                 type==S_END ? format("END%+d", offset) :
51                 format("SeekType(%d)", type))
52 { }
53
54
55 SeekOffset sys_seek(Handle &handle, SeekOffset offset, SeekType type)
56 {
57 #ifdef WIN32
58         LONG high = offset>>32;
59         DWORD ret = SetFilePointer(*handle, offset, &high, sys_seek_type(type));
60         if(ret==INVALID_SET_FILE_POINTER)
61         {
62                 DWORD err = GetLastError();
63                 if(err!=NO_ERROR)
64                         throw system_error("SetFilePointer");
65         }
66
67         return (SeekOffset(high)<<32) | ret;
68 #else
69         off64_t ret = lseek64(*handle, offset, sys_seek_type(type));
70         if(ret==(off64_t)-1)
71         {
72                 if(errno==EINVAL)
73                         throw bad_seek(offset, type);
74                 else
75                         throw system_error("lseek64");
76         }
77
78         return ret;
79 #endif
80 }
81
82 } // namespace IO
83 } // namespace Msp