line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
/* -*- c -*- |
2
|
|
|
|
|
|
|
* File: loadfile.h |
3
|
|
|
|
|
|
|
* Author: Igor Vlasenko |
4
|
|
|
|
|
|
|
* Created: Thu Sep 8 17:16:48 2005 |
5
|
|
|
|
|
|
|
* |
6
|
|
|
|
|
|
|
* $Id$ |
7
|
|
|
|
|
|
|
*/ |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H |
10
|
|
|
|
|
|
|
#include "config.h" |
11
|
|
|
|
|
|
|
#endif |
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
#ifdef USE_MMAP |
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
#ifdef WIN32 |
16
|
|
|
|
|
|
|
/* |
17
|
|
|
|
|
|
|
* the win32 code of Viacheslav Sheveliov |
18
|
|
|
|
|
|
|
* viy: should work for win64 too. |
19
|
|
|
|
|
|
|
*/ |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
#include |
22
|
|
|
|
|
|
|
#include |
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
static PSTRING mmap_load_file(const char *filepath) { |
25
|
|
|
|
|
|
|
PSTRING memarea = { NULL, NULL }; |
26
|
|
|
|
|
|
|
HANDLE hFile, hMapObject = NULL; |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
hFile = CreateFile( |
29
|
|
|
|
|
|
|
TEXT(filepath), |
30
|
|
|
|
|
|
|
GENERIC_READ, |
31
|
|
|
|
|
|
|
FILE_SHARE_READ, |
32
|
|
|
|
|
|
|
NULL, |
33
|
|
|
|
|
|
|
OPEN_EXISTING, |
34
|
|
|
|
|
|
|
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, |
35
|
|
|
|
|
|
|
NULL |
36
|
|
|
|
|
|
|
); |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
if (hFile != INVALID_HANDLE_VALUE) { |
39
|
|
|
|
|
|
|
hMapObject = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL); |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
if (hMapObject) { |
42
|
|
|
|
|
|
|
// Get a pointer to the file-mapped shared memory. |
43
|
|
|
|
|
|
|
LPCTSTR lpvMem = (LPTSTR) MapViewOfFile(hMapObject, FILE_MAP_READ, 0, 0, 0); |
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
if (lpvMem) { |
46
|
|
|
|
|
|
|
// Everything OK! |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
memarea.begin = (char *) lpvMem; |
49
|
|
|
|
|
|
|
memarea.endnext = memarea.begin + GetFileSize(hFile, NULL); |
50
|
|
|
|
|
|
|
// After MapViewOfFile we don't need file handles no more. |
51
|
|
|
|
|
|
|
// Undocumented, but it works! (In read-only mode?) |
52
|
|
|
|
|
|
|
CloseHandle(hMapObject); |
53
|
|
|
|
|
|
|
CloseHandle(hFile); |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
return memarea; |
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
} |
58
|
|
|
|
|
|
|
} |
59
|
|
|
|
|
|
|
} |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
// Something goes wrong |
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
{ |
64
|
|
|
|
|
|
|
// Save last error code, before any system call |
65
|
|
|
|
|
|
|
DWORD dwLastError = GetLastError(); |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
// Report error, if file size != 0 |
68
|
|
|
|
|
|
|
// Mapping of zero-length file cause CreateFileMapping to fail. |
69
|
|
|
|
|
|
|
// So skip error messages in this case. |
70
|
|
|
|
|
|
|
if (hFile == INVALID_HANDLE_VALUE && GetFileSize(hFile, NULL) != 0) |
71
|
|
|
|
|
|
|
fprintf(stderr, "Could not open file '%s'. (system error#%ld)\n", filepath, dwLastError); |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
} |
74
|
|
|
|
|
|
|
// Close all opened handles |
75
|
|
|
|
|
|
|
if (hMapObject) CloseHandle(hMapObject); |
76
|
|
|
|
|
|
|
if (hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile); |
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
return memarea; |
79
|
|
|
|
|
|
|
} |
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
/* we use function, not define, because someday we may need its address */ |
82
|
|
|
|
|
|
|
static int mmap_unload_file(PSTRING memarea) { return UnmapViewOfFile((void*) memarea.begin) ? 0 : -1; }; |
83
|
|
|
|
|
|
|
/* define mmap_unload_file(map) (UnmapViewOfFile((LPCVOID) map.begin) ? 0 : -1) */ |
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
#else /* unix, sweet unix :) */ |
86
|
|
|
|
|
|
|
#if defined(HAVE_SYS_MMAN_H) && defined(HAVE_SYS_STAT_H) |
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
/* # define NULL 0 */ |
89
|
|
|
|
|
|
|
#include |
90
|
|
|
|
|
|
|
#include |
91
|
|
|
|
|
|
|
#include /* open */ |
92
|
|
|
|
|
|
|
#include /* close */ |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
static |
95
|
|
|
|
|
|
|
PSTRING |
96
|
301
|
|
|
|
|
|
mmap_load_file (const char* filepath) { |
97
|
|
|
|
|
|
|
int fd; |
98
|
|
|
|
|
|
|
struct stat st; |
99
|
|
|
|
|
|
|
size_t size_in_bytes; |
100
|
301
|
|
|
|
|
|
PSTRING memarea={NULL,NULL}; |
101
|
301
|
|
|
|
|
|
fd = open(filepath, O_RDONLY); |
102
|
301
|
50
|
|
|
|
|
if (fd == -1) return memarea; /* {NULL,NULL} */ |
103
|
301
|
|
|
|
|
|
fstat(fd, &st); |
104
|
301
|
|
|
|
|
|
size_in_bytes = st.st_size; |
105
|
|
|
|
|
|
|
/* mmap size_in_bytes+1 to avoid crash with empty file */ |
106
|
301
|
|
|
|
|
|
memarea.begin = (char *) mmap(0, size_in_bytes+1, PROT_READ, MAP_SHARED, fd, 0); |
107
|
301
|
|
|
|
|
|
close(fd); |
108
|
301
|
|
|
|
|
|
memarea.endnext=memarea.begin+size_in_bytes; |
109
|
301
|
|
|
|
|
|
return memarea; |
110
|
|
|
|
|
|
|
} |
111
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
static |
113
|
|
|
|
|
|
|
int |
114
|
301
|
|
|
|
|
|
mmap_unload_file (PSTRING memarea) { |
115
|
|
|
|
|
|
|
/* destroying */ |
116
|
301
|
|
|
|
|
|
return munmap((void *)memarea.begin, memarea.endnext-memarea.begin); |
117
|
|
|
|
|
|
|
} |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
#endif /* UNIX */ |
120
|
|
|
|
|
|
|
#endif /* WIN32 */ |
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
#else |
123
|
|
|
|
|
|
|
/* |
124
|
|
|
|
|
|
|
* system seems to have no mmap ; |
125
|
|
|
|
|
|
|
* we use standard C buffered read |
126
|
|
|
|
|
|
|
*/ |
127
|
|
|
|
|
|
|
#include |
128
|
|
|
|
|
|
|
static |
129
|
|
|
|
|
|
|
PSTRING |
130
|
|
|
|
|
|
|
mmap_load_file (const char* filepath) { |
131
|
|
|
|
|
|
|
FILE *stream; |
132
|
|
|
|
|
|
|
size_t size_in_bytes=0; |
133
|
|
|
|
|
|
|
size_t realsize; |
134
|
|
|
|
|
|
|
size_t chunksize=4096; |
135
|
|
|
|
|
|
|
size_t memsize=chunksize; |
136
|
|
|
|
|
|
|
PSTRING memarea={NULL,NULL}; |
137
|
|
|
|
|
|
|
char* writepoint; |
138
|
|
|
|
|
|
|
/* text mode for HTML::Template compatibility */ |
139
|
|
|
|
|
|
|
stream = fopen(filepath, "r"); |
140
|
|
|
|
|
|
|
if (stream == NULL) return memarea; /* {NULL,NULL} */ |
141
|
|
|
|
|
|
|
/* mmap size_in_bytes+1 to avoid crash with empty file */ |
142
|
|
|
|
|
|
|
memarea.begin=(const char*) malloc(memsize+1); |
143
|
|
|
|
|
|
|
writepoint=(char*)memarea.begin; |
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
while (1) { |
146
|
|
|
|
|
|
|
realsize=fread(writepoint, 1, chunksize, stream); |
147
|
|
|
|
|
|
|
size_in_bytes+=realsize; |
148
|
|
|
|
|
|
|
if (realsize==chunksize) { |
149
|
|
|
|
|
|
|
writepoint+=chunksize; |
150
|
|
|
|
|
|
|
if (size_in_bytes+chunksize>memsize) { |
151
|
|
|
|
|
|
|
memsize*=2; |
152
|
|
|
|
|
|
|
memarea.begin=(char*) realloc((char*)memarea.begin, memsize+1); |
153
|
|
|
|
|
|
|
writepoint=((char*)memarea.begin)+size_in_bytes; |
154
|
|
|
|
|
|
|
} |
155
|
|
|
|
|
|
|
} else { |
156
|
|
|
|
|
|
|
fclose(stream); |
157
|
|
|
|
|
|
|
memarea.endnext=memarea.begin+size_in_bytes; |
158
|
|
|
|
|
|
|
return memarea; |
159
|
|
|
|
|
|
|
} |
160
|
|
|
|
|
|
|
} |
161
|
|
|
|
|
|
|
} |
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
static |
164
|
|
|
|
|
|
|
int |
165
|
|
|
|
|
|
|
mmap_unload_file (PSTRING memarea) { |
166
|
|
|
|
|
|
|
/* destroying */ |
167
|
|
|
|
|
|
|
free((char*)memarea.begin); |
168
|
|
|
|
|
|
|
return 0; |
169
|
|
|
|
|
|
|
} |
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
#endif /* USE_MMAP */ |