MemoryMappedFile.h
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #ifndef __MEMORYMAPPEDFILE_H__
00012 #define __MEMORYMAPPEDFILE_H__
00013
00014 #include "lib/io.h"
00015 #include "base/SGObject.h"
00016
00017 #include <stdio.h>
00018 #include <string.h>
00019 #include <sys/mman.h>
00020 #include <sys/stat.h>
00021 #include <sys/types.h>
00022 #include <fcntl.h>
00023 #include <unistd.h>
00024
00029 template <class T> class CMemoryMappedFile : public CSGObject
00030 {
00031 public:
00045 CMemoryMappedFile(const char* fname, char flag='r', uint64_t fsize=0)
00046 : CSGObject()
00047 {
00048 last_written_byte=0;
00049 rw=flag;
00050
00051 int open_flags;
00052 int mmap_prot;
00053 int mmap_flags;
00054
00055 if (rw=='w')
00056 {
00057 open_flags=O_RDWR | O_CREAT;
00058 mmap_prot=PROT_READ|PROT_WRITE;
00059 mmap_flags=MAP_SHARED;
00060 }
00061 else if (rw=='r')
00062 {
00063 open_flags=O_RDONLY;
00064 mmap_prot=PROT_READ;
00065 mmap_flags=MAP_PRIVATE;
00066 }
00067 else
00068 SG_ERROR("Unknown flags\n");
00069
00070 fd = open(fname, open_flags, S_IRWXU | S_IRWXG | S_IRWXO);
00071 if (fd == -1)
00072 SG_ERROR("Error opening file\n");
00073
00074 if (rw=='w' && fsize)
00075 {
00076 uint8_t byte=0;
00077 if (lseek(fd, fsize, SEEK_SET) != fsize || write(fd, &byte, 1) != 1)
00078 SG_ERROR("Error creating file of size %ld bytes\n", fsize);
00079 }
00080
00081 struct stat sb;
00082 if (fstat(fd, &sb) == -1)
00083 SG_ERROR("Error determining file size\n");
00084
00085 length = sb.st_size;
00086 address = mmap(NULL, length, mmap_prot, mmap_flags, fd, 0);
00087 if (address == MAP_FAILED)
00088 SG_ERROR("Error mapping file");
00089 }
00090
00092 virtual ~CMemoryMappedFile()
00093 {
00094 munmap(address, length);
00095 if (rw=='w' && last_written_byte && ftruncate(fd, last_written_byte) == -1)
00096
00097 {
00098 close(fd);
00099 SG_ERROR("Error Truncating file to %ld bytes\n", last_written_byte);
00100 }
00101 close(fd);
00102 }
00103
00113 inline T* get_map()
00114 {
00115 return (T*) address;
00116 }
00117
00122 uint64_t get_length()
00123 {
00124 return length/sizeof(T);
00125 }
00126
00131 uint64_t get_size()
00132 {
00133 return length;
00134 }
00135
00147 char* get_line(uint64_t& len, uint64_t& offs)
00148 {
00149 char* s = (char*) address;
00150 for (uint64_t i=offs; i<length; i++)
00151 {
00152 if (s[i] == '\n')
00153 {
00154 char* line=&s[offs];
00155 len=i-offs;
00156 offs=i+1;
00157 return line;
00158 }
00159 }
00160
00161 len=0;
00162 offs=length;
00163 return NULL;
00164 }
00165
00176 void write_line(const char* line, uint64_t len, uint64_t& offs)
00177 {
00178 char* s = ((char*) address) + offs;
00179 if (len+1+offs > length)
00180 SG_ERROR("Writing beyond size of file\n");
00181
00182 for (uint64_t i=0; i<len; i++)
00183 s[i] = line[i];
00184
00185 s[len]='\n';
00186 offs+=length+1;
00187 last_written_byte=offs-1;
00188 }
00200 inline void set_truncate_size(uint64_t* sz=0)
00201 {
00202 last_written_byte=sz;
00203 }
00204
00209 int32_t get_num_lines()
00210 {
00211 char* s = (char*) address;
00212 int32_t linecount=0;
00213 for (uint64_t i=0; i<length; i++)
00214 {
00215 if (s[i] == '\n')
00216 linecount++;
00217 }
00218
00219 return linecount;
00220 }
00221
00229 inline T operator[](int32_t index) const
00230 {
00231 return ((T*)address)[index];
00232 }
00233
00235 inline virtual const char* get_name() const { return "MemoryMappedFile"; }
00236
00237 protected:
00239 int fd;
00241 uint64_t length;
00243 void* address;
00245 char rw;
00246
00247
00248 uint64_t last_written_byte;
00249 };
00250 #endif
00251