Initial import into git.
[galago.git] / cpp / galago / contrib / indri / src / File.cpp
blobf4911d134e15e360c09ff788ab6932da226ded46
1 /*==========================================================================
2 * Copyright (c) 2004 University of Massachusetts. All Rights Reserved.
4 * Use of the Lemur Toolkit for Language Modeling and Information Retrieval
5 * is subject to the terms of the software license set forth in the LICENSE
6 * file included with this software, and also available at
7 * http://www.lemurproject.org/license.html
9 *==========================================================================
13 // File
15 // 15 November 2004 -- tds
18 #include <string>
19 #include "indri/indri-platform.h"
20 #include "indri/File.hpp"
22 #ifndef WIN32
23 #include <fcntl.h>
24 #include <sys/stat.h>
25 #include <sys/types.h>
26 #include <sys/mman.h>
27 #endif
29 #include "lemur/Exception.hpp"
30 #include "indri/ScopedLock.hpp"
33 // File constructor
36 indri::file::File::File() :
37 #ifdef WIN32
38 _handle(INVALID_HANDLE_VALUE)
39 #else
40 _handle(-1)
41 #endif
46 // File destructor
49 indri::file::File::~File() {
50 close();
54 // create
55 //
57 bool indri::file::File::create( const std::string& filename ) {
58 #ifdef WIN32
59 _handle = ::CreateFile( filename.c_str(),
60 GENERIC_READ | GENERIC_WRITE,
62 NULL,
63 CREATE_ALWAYS,
64 FILE_ATTRIBUTE_NORMAL,
65 NULL );
67 if( _handle == INVALID_HANDLE_VALUE )
68 LEMUR_THROW( LEMUR_IO_ERROR, "Couldn't create: " + filename );
70 return true;
71 #else
72 _handle = creat( filename.c_str(), 0600 );
74 if( _handle < 0 )
75 LEMUR_THROW( LEMUR_IO_ERROR, "Couldn't create: " + filename );
77 return true;
78 #endif
81 bool indri::file::File::open( const std::string& filename ) {
82 #ifdef WIN32
83 _handle = ::CreateFile( filename.c_str(),
84 GENERIC_READ | GENERIC_WRITE,
86 NULL,
87 OPEN_EXISTING,
88 FILE_ATTRIBUTE_NORMAL,
89 NULL );
91 if( _handle == INVALID_HANDLE_VALUE )
92 LEMUR_THROW( LEMUR_IO_ERROR, "Couldn't open: " + filename );
94 return true;
95 #else
96 #ifndef O_LARGEFILE
97 _handle = ::open( filename.c_str(), O_RDWR );
98 #else
99 _handle = ::open( filename.c_str(), O_LARGEFILE | O_RDWR );
100 #endif
102 if( _handle < 0 )
103 LEMUR_THROW( LEMUR_IO_ERROR, "Couldn't open: " + filename );
105 return true;
106 #endif
109 bool indri::file::File::openRead( const std::string& filename ) {
110 #ifdef WIN32
111 _handle = ::CreateFile( filename.c_str(),
112 GENERIC_READ,
113 FILE_SHARE_READ,
114 NULL,
115 OPEN_EXISTING,
116 FILE_ATTRIBUTE_NORMAL,
117 NULL );
119 if( _handle == INVALID_HANDLE_VALUE )
120 LEMUR_THROW( LEMUR_IO_ERROR, "Couldn't open for reading: " + filename );
122 return true;
123 #else
124 #ifndef O_LARGEFILE
125 _handle = ::open( filename.c_str(), O_RDONLY );
126 #else
127 _handle = ::open( filename.c_str(), O_LARGEFILE | O_RDONLY );
128 #endif
130 if( _handle < 0 )
131 LEMUR_THROW( LEMUR_IO_ERROR, "Couldn't open for reading: " + filename );
133 return true;
134 #endif
137 bool indri::file::File::openTemporary( std::string& fileName ) {
138 #ifdef HAVE_MKSTEMP
139 char name[] = "/tmp/indriXXXXXX";
140 _handle = ::mkstemp( name );
141 fileName = name;
143 if( _handle < 0 )
144 LEMUR_THROW( LEMUR_IO_ERROR, "Couldn't create temporary file." );
145 #else
146 fileName = tmpnam( NULL );
147 open( fileName );
148 #endif
150 return true;
153 size_t indri::file::File::read( void* buffer, UINT64 position, size_t length ) {
154 #ifdef WIN32
155 assert( _handle != INVALID_HANDLE_VALUE );
157 indri::thread::ScopedLock sl( _mutex );
158 LARGE_INTEGER actual;
159 BOOL result;
160 LARGE_INTEGER largePosition;
161 largePosition.QuadPart = position;
163 result = SetFilePointerEx( _handle, largePosition, &actual, FILE_BEGIN );
164 assert( largePosition.QuadPart == actual.QuadPart );
166 if( !result )
167 LEMUR_THROW( LEMUR_IO_ERROR, "Failed to seek to some file position" );
169 DWORD actualBytes;
170 result = ::ReadFile( _handle, buffer, length, &actualBytes, NULL );
172 if( !result )
173 LEMUR_THROW( LEMUR_IO_ERROR, "Error when reading file" );
175 return actualBytes;
176 #else // POSIX
177 assert( _handle > 0 );
178 ssize_t result = ::pread( _handle, buffer, length, position );
180 if( result < 0 )
181 LEMUR_THROW( LEMUR_IO_ERROR, "Error when reading file" );
183 return size_t(result);
184 #endif
187 size_t indri::file::File::write( const void* buffer, UINT64 position, size_t length ) {
188 if( length == 0 )
189 return 0;
191 #ifdef WIN32
192 assert( _handle != INVALID_HANDLE_VALUE );
194 indri::thread::ScopedLock sl( _mutex );
195 LARGE_INTEGER actual;
196 BOOL result;
197 LARGE_INTEGER largePosition;
198 largePosition.QuadPart = position;
200 result = SetFilePointerEx( _handle, largePosition, &actual, FILE_BEGIN );
201 assert( largePosition.QuadPart == actual.QuadPart );
203 if( !result )
204 LEMUR_THROW( LEMUR_IO_ERROR, "Failed to seek to some file position" );
206 DWORD actualBytes;
207 result = ::WriteFile( _handle, buffer, length, &actualBytes, NULL );
209 if( !result )
210 LEMUR_THROW( LEMUR_IO_ERROR, "Error when writing file" );
212 return actualBytes;
213 #else // POSIX
214 assert( _handle > 0 );
216 ssize_t result = ::pwrite( _handle, buffer, length, position );
218 if( result < 0 )
219 LEMUR_THROW( LEMUR_IO_ERROR, "Error when writing file" );
221 return size_t(result);
222 #endif
225 void indri::file::File::close() {
226 #ifdef WIN32
227 if( _handle != INVALID_HANDLE_VALUE ) {
228 ::CloseHandle( _handle );
229 _handle = INVALID_HANDLE_VALUE;
231 #else
232 if( _handle >= 0 ) {
233 ::close( _handle );
234 _handle = -1;
236 #endif
239 UINT64 indri::file::File::size() {
240 #ifdef WIN32
241 if( _handle == INVALID_HANDLE_VALUE )
242 return 0;
244 LARGE_INTEGER length;
245 BOOL result = ::GetFileSizeEx( _handle, &length );
247 if( !result )
248 LEMUR_THROW( LEMUR_IO_ERROR, "Got an error while trying to retrieve file size" );
250 return length.QuadPart;
251 #else // POSIX
252 struct stat stats;
254 if( _handle == -1 )
255 return 0;
257 fstat( _handle, &stats );
258 return stats.st_size;
259 #endif
262 indri::file::FileMapping* indri::file::File::mapRegion( UINT64 position, UINT64 length, bool readOnly, bool wholeFile ) {
263 #ifdef WIN32
264 if( wholeFile ) {
265 position = 0;
266 length = 0;
269 DWORD createFlags = readOnly ? PAGE_READONLY : PAGE_READWRITE;
270 DWORD flags = readOnly ? FILE_MAP_READ : FILE_MAP_ALL_ACCESS;
272 DWORD offsetHigh = (position >> 32);
273 DWORD offsetLow = (position & 0xFFffFFff);
275 // on 32-bit windows, we may ask for a region that's too big
276 SIZE_T maxSizeT = ~( (SIZE_T) 0 );
277 if( length > (UINT64)maxSizeT )
278 LEMUR_THROW( LEMUR_IO_ERROR, "Requested a file mapping that's too big for your operating system" );
280 UINT64 end = position + length;
281 DWORD endHigh = (end >> 32);
282 DWORD endLow = (end & 0xFFffFFff);
284 HANDLE mappingHandle = CreateFileMapping( _handle, NULL, createFlags, endHigh, endLow, 0 );
286 if( mappingHandle == INVALID_HANDLE_VALUE ) {
287 LEMUR_THROW( LEMUR_IO_ERROR, "Failed to create file mapping" );
290 void* map = MapViewOfFileEx( mappingHandle, flags, offsetHigh, offsetLow, (SIZE_T)length );
292 if( map == 0 ) {
293 CloseHandle(mappingHandle);
294 LEMUR_THROW( LEMUR_IO_ERROR, "Failed to create file mapping" );
297 return new FileMapping( mappingHandle, map, length );
298 #else
299 if( wholeFile ) {
300 position = 0;
301 length = size();
304 size_t maxSizeT = ~( (size_t) 0 );
305 if( length > (UINT64)maxSizeT )
306 return 0;
308 int prot = readOnly ? PROT_READ : (PROT_READ|PROT_WRITE);
309 void* map = mmap(0, (size_t)length, prot, MAP_SHARED, _handle, position );
311 if( !map || map == MAP_FAILED ) {
312 LEMUR_THROW( LEMUR_IO_ERROR, "Failed to create file mapping" );
315 return new FileMapping( map, length );
316 #endif
319 indri::file::FileMapping* indri::file::File::mapFileRead() {
320 return mapRegion( 0, 0, true, true );
323 indri::file::FileMapping* indri::file::File::mapFile() {
324 return mapRegion( 0, 0, false, true );
327 indri::file::FileMapping* indri::file::File::mapRegion( UINT64 position, UINT64 length ) {
328 return mapRegion( position, length, false, false );
331 indri::file::FileMapping* indri::file::File::mapRegionRead( UINT64 position, UINT64 length ) {
332 return mapRegion( position, length, true, false );