annotate gcc/ada/libgnat/s-mmap.adb @ 131:84e7813d76e9

gcc-8.2
author mir3636
date Thu, 25 Oct 2018 07:37:49 +0900
parents 04ced10e8804
children 1830386684a0
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 ------------------------------------------------------------------------------
kono
parents:
diff changeset
2 -- --
kono
parents:
diff changeset
3 -- GNAT RUN-TIME COMPONENTS --
kono
parents:
diff changeset
4 -- --
kono
parents:
diff changeset
5 -- S Y S T E M . M M A P --
kono
parents:
diff changeset
6 -- --
kono
parents:
diff changeset
7 -- B o d y --
kono
parents:
diff changeset
8 -- --
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
9 -- Copyright (C) 2007-2018, AdaCore --
111
kono
parents:
diff changeset
10 -- --
kono
parents:
diff changeset
11 -- This library is free software; you can redistribute it and/or modify it --
kono
parents:
diff changeset
12 -- under terms of the GNU General Public License as published by the Free --
kono
parents:
diff changeset
13 -- Software Foundation; either version 3, or (at your option) any later --
kono
parents:
diff changeset
14 -- version. This library is distributed in the hope that it will be useful, --
kono
parents:
diff changeset
15 -- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- --
kono
parents:
diff changeset
16 -- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. --
kono
parents:
diff changeset
17 -- --
kono
parents:
diff changeset
18 -- As a special exception under Section 7 of GPL version 3, you are granted --
kono
parents:
diff changeset
19 -- additional permissions described in the GCC Runtime Library Exception, --
kono
parents:
diff changeset
20 -- version 3.1, as published by the Free Software Foundation. --
kono
parents:
diff changeset
21 -- --
kono
parents:
diff changeset
22 -- You should have received a copy of the GNU General Public License and --
kono
parents:
diff changeset
23 -- a copy of the GCC Runtime Library Exception along with this program; --
kono
parents:
diff changeset
24 -- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
kono
parents:
diff changeset
25 -- <http://www.gnu.org/licenses/>. --
kono
parents:
diff changeset
26 -- --
kono
parents:
diff changeset
27 -- GNAT was originally developed by the GNAT team at New York University. --
kono
parents:
diff changeset
28 -- Extensive contributions were provided by Ada Core Technologies Inc. --
kono
parents:
diff changeset
29 -- --
kono
parents:
diff changeset
30 ------------------------------------------------------------------------------
kono
parents:
diff changeset
31
kono
parents:
diff changeset
32 with Ada.IO_Exceptions;
kono
parents:
diff changeset
33 with Ada.Unchecked_Conversion;
kono
parents:
diff changeset
34 with Ada.Unchecked_Deallocation;
kono
parents:
diff changeset
35
kono
parents:
diff changeset
36 with System.Strings; use System.Strings;
kono
parents:
diff changeset
37
kono
parents:
diff changeset
38 with System.Mmap.OS_Interface; use System.Mmap.OS_Interface;
kono
parents:
diff changeset
39
kono
parents:
diff changeset
40 package body System.Mmap is
kono
parents:
diff changeset
41
kono
parents:
diff changeset
42 type Mapped_File_Record is record
kono
parents:
diff changeset
43 Current_Region : Mapped_Region;
kono
parents:
diff changeset
44 -- The legacy API enables only one region to be mapped, directly
kono
parents:
diff changeset
45 -- associated with the mapped file. This references this region.
kono
parents:
diff changeset
46
kono
parents:
diff changeset
47 File : System_File;
kono
parents:
diff changeset
48 -- Underlying OS-level file
kono
parents:
diff changeset
49 end record;
kono
parents:
diff changeset
50
kono
parents:
diff changeset
51 type Mapped_Region_Record is record
kono
parents:
diff changeset
52 File : Mapped_File;
kono
parents:
diff changeset
53 -- The file this region comes from. Be careful: for reading file, it is
kono
parents:
diff changeset
54 -- valid to have it closed before one of its regions is free'd.
kono
parents:
diff changeset
55
kono
parents:
diff changeset
56 Write : Boolean;
kono
parents:
diff changeset
57 -- Whether the file this region comes from is open for writing.
kono
parents:
diff changeset
58
kono
parents:
diff changeset
59 Data : Str_Access;
kono
parents:
diff changeset
60 -- Unbounded access to the mapped content.
kono
parents:
diff changeset
61
kono
parents:
diff changeset
62 System_Offset : File_Size;
kono
parents:
diff changeset
63 -- Position in the file of the first byte actually mapped in memory
kono
parents:
diff changeset
64
kono
parents:
diff changeset
65 User_Offset : File_Size;
kono
parents:
diff changeset
66 -- Position in the file of the first byte requested by the user
kono
parents:
diff changeset
67
kono
parents:
diff changeset
68 System_Size : File_Size;
kono
parents:
diff changeset
69 -- Size of the region actually mapped in memory
kono
parents:
diff changeset
70
kono
parents:
diff changeset
71 User_Size : File_Size;
kono
parents:
diff changeset
72 -- Size of the region requested by the user
kono
parents:
diff changeset
73
kono
parents:
diff changeset
74 Mapped : Boolean;
kono
parents:
diff changeset
75 -- Whether this region is actually memory mapped
kono
parents:
diff changeset
76
kono
parents:
diff changeset
77 Mutable : Boolean;
kono
parents:
diff changeset
78 -- If the file is opened for reading, wheter this region is writable
kono
parents:
diff changeset
79
kono
parents:
diff changeset
80 Buffer : System.Strings.String_Access;
kono
parents:
diff changeset
81 -- When this region is not actually memory mapped, contains the
kono
parents:
diff changeset
82 -- requested bytes.
kono
parents:
diff changeset
83
kono
parents:
diff changeset
84 Mapping : System_Mapping;
kono
parents:
diff changeset
85 -- Underlying OS-level data for the mapping, if any
kono
parents:
diff changeset
86 end record;
kono
parents:
diff changeset
87
kono
parents:
diff changeset
88 Invalid_Mapped_Region_Record : constant Mapped_Region_Record :=
kono
parents:
diff changeset
89 (null, False, null, 0, 0, 0, 0, False, False, null,
kono
parents:
diff changeset
90 Invalid_System_Mapping);
kono
parents:
diff changeset
91 Invalid_Mapped_File_Record : constant Mapped_File_Record :=
kono
parents:
diff changeset
92 (Invalid_Mapped_Region, Invalid_System_File);
kono
parents:
diff changeset
93
kono
parents:
diff changeset
94 Empty_String : constant String := "";
kono
parents:
diff changeset
95 -- Used to provide a valid empty Data for empty files, for instanc.
kono
parents:
diff changeset
96
kono
parents:
diff changeset
97 procedure Dispose is new Ada.Unchecked_Deallocation
kono
parents:
diff changeset
98 (Mapped_File_Record, Mapped_File);
kono
parents:
diff changeset
99 procedure Dispose is new Ada.Unchecked_Deallocation
kono
parents:
diff changeset
100 (Mapped_Region_Record, Mapped_Region);
kono
parents:
diff changeset
101
kono
parents:
diff changeset
102 function Convert is new Ada.Unchecked_Conversion
kono
parents:
diff changeset
103 (Standard.System.Address, Str_Access);
kono
parents:
diff changeset
104
kono
parents:
diff changeset
105 procedure Compute_Data (Region : Mapped_Region);
kono
parents:
diff changeset
106 -- Fill the Data field according to system and user offsets. The region
kono
parents:
diff changeset
107 -- must actually be mapped or bufferized.
kono
parents:
diff changeset
108
kono
parents:
diff changeset
109 procedure From_Disk (Region : Mapped_Region);
kono
parents:
diff changeset
110 -- Read a region of some file from the disk
kono
parents:
diff changeset
111
kono
parents:
diff changeset
112 procedure To_Disk (Region : Mapped_Region);
kono
parents:
diff changeset
113 -- Write the region of the file back to disk if necessary, and free memory
kono
parents:
diff changeset
114
kono
parents:
diff changeset
115 ----------------------------
kono
parents:
diff changeset
116 -- Open_Read_No_Exception --
kono
parents:
diff changeset
117 ----------------------------
kono
parents:
diff changeset
118
kono
parents:
diff changeset
119 function Open_Read_No_Exception
kono
parents:
diff changeset
120 (Filename : String;
kono
parents:
diff changeset
121 Use_Mmap_If_Available : Boolean := True) return Mapped_File
kono
parents:
diff changeset
122 is
kono
parents:
diff changeset
123 File : constant System_File :=
kono
parents:
diff changeset
124 Open_Read (Filename, Use_Mmap_If_Available);
kono
parents:
diff changeset
125 begin
kono
parents:
diff changeset
126 if File = Invalid_System_File then
kono
parents:
diff changeset
127 return Invalid_Mapped_File;
kono
parents:
diff changeset
128 end if;
kono
parents:
diff changeset
129
kono
parents:
diff changeset
130 return new Mapped_File_Record'
kono
parents:
diff changeset
131 (Current_Region => Invalid_Mapped_Region,
kono
parents:
diff changeset
132 File => File);
kono
parents:
diff changeset
133 end Open_Read_No_Exception;
kono
parents:
diff changeset
134
kono
parents:
diff changeset
135 ---------------
kono
parents:
diff changeset
136 -- Open_Read --
kono
parents:
diff changeset
137 ---------------
kono
parents:
diff changeset
138
kono
parents:
diff changeset
139 function Open_Read
kono
parents:
diff changeset
140 (Filename : String;
kono
parents:
diff changeset
141 Use_Mmap_If_Available : Boolean := True) return Mapped_File
kono
parents:
diff changeset
142 is
kono
parents:
diff changeset
143 Res : constant Mapped_File :=
kono
parents:
diff changeset
144 Open_Read_No_Exception (Filename, Use_Mmap_If_Available);
kono
parents:
diff changeset
145 begin
kono
parents:
diff changeset
146 if Res = Invalid_Mapped_File then
kono
parents:
diff changeset
147 raise Ada.IO_Exceptions.Name_Error
kono
parents:
diff changeset
148 with "Cannot open " & Filename;
kono
parents:
diff changeset
149 else
kono
parents:
diff changeset
150 return Res;
kono
parents:
diff changeset
151 end if;
kono
parents:
diff changeset
152 end Open_Read;
kono
parents:
diff changeset
153
kono
parents:
diff changeset
154 ----------------
kono
parents:
diff changeset
155 -- Open_Write --
kono
parents:
diff changeset
156 ----------------
kono
parents:
diff changeset
157
kono
parents:
diff changeset
158 function Open_Write
kono
parents:
diff changeset
159 (Filename : String;
kono
parents:
diff changeset
160 Use_Mmap_If_Available : Boolean := True) return Mapped_File
kono
parents:
diff changeset
161 is
kono
parents:
diff changeset
162 File : constant System_File :=
kono
parents:
diff changeset
163 Open_Write (Filename, Use_Mmap_If_Available);
kono
parents:
diff changeset
164 begin
kono
parents:
diff changeset
165 if File = Invalid_System_File then
kono
parents:
diff changeset
166 raise Ada.IO_Exceptions.Name_Error
kono
parents:
diff changeset
167 with "Cannot open " & Filename;
kono
parents:
diff changeset
168 else
kono
parents:
diff changeset
169 return new Mapped_File_Record'
kono
parents:
diff changeset
170 (Current_Region => Invalid_Mapped_Region,
kono
parents:
diff changeset
171 File => File);
kono
parents:
diff changeset
172 end if;
kono
parents:
diff changeset
173 end Open_Write;
kono
parents:
diff changeset
174
kono
parents:
diff changeset
175 -----------
kono
parents:
diff changeset
176 -- Close --
kono
parents:
diff changeset
177 -----------
kono
parents:
diff changeset
178
kono
parents:
diff changeset
179 procedure Close (File : in out Mapped_File) is
kono
parents:
diff changeset
180 begin
kono
parents:
diff changeset
181 -- Closing a closed file is allowed and should do nothing
kono
parents:
diff changeset
182
kono
parents:
diff changeset
183 if File = Invalid_Mapped_File then
kono
parents:
diff changeset
184 return;
kono
parents:
diff changeset
185 end if;
kono
parents:
diff changeset
186
kono
parents:
diff changeset
187 if File.Current_Region /= null then
kono
parents:
diff changeset
188 Free (File.Current_Region);
kono
parents:
diff changeset
189 end if;
kono
parents:
diff changeset
190
kono
parents:
diff changeset
191 if File.File /= Invalid_System_File then
kono
parents:
diff changeset
192 Close (File.File);
kono
parents:
diff changeset
193 end if;
kono
parents:
diff changeset
194
kono
parents:
diff changeset
195 Dispose (File);
kono
parents:
diff changeset
196 end Close;
kono
parents:
diff changeset
197
kono
parents:
diff changeset
198 ----------
kono
parents:
diff changeset
199 -- Free --
kono
parents:
diff changeset
200 ----------
kono
parents:
diff changeset
201
kono
parents:
diff changeset
202 procedure Free (Region : in out Mapped_Region) is
kono
parents:
diff changeset
203 Ignored : Integer;
kono
parents:
diff changeset
204 pragma Unreferenced (Ignored);
kono
parents:
diff changeset
205 begin
kono
parents:
diff changeset
206 -- Freeing an already free'd file is allowed and should do nothing
kono
parents:
diff changeset
207
kono
parents:
diff changeset
208 if Region = Invalid_Mapped_Region then
kono
parents:
diff changeset
209 return;
kono
parents:
diff changeset
210 end if;
kono
parents:
diff changeset
211
kono
parents:
diff changeset
212 if Region.Mapping /= Invalid_System_Mapping then
kono
parents:
diff changeset
213 Dispose_Mapping (Region.Mapping);
kono
parents:
diff changeset
214 end if;
kono
parents:
diff changeset
215 To_Disk (Region);
kono
parents:
diff changeset
216 Dispose (Region);
kono
parents:
diff changeset
217 end Free;
kono
parents:
diff changeset
218
kono
parents:
diff changeset
219 ----------
kono
parents:
diff changeset
220 -- Read --
kono
parents:
diff changeset
221 ----------
kono
parents:
diff changeset
222
kono
parents:
diff changeset
223 procedure Read
kono
parents:
diff changeset
224 (File : Mapped_File;
kono
parents:
diff changeset
225 Region : in out Mapped_Region;
kono
parents:
diff changeset
226 Offset : File_Size := 0;
kono
parents:
diff changeset
227 Length : File_Size := 0;
kono
parents:
diff changeset
228 Mutable : Boolean := False)
kono
parents:
diff changeset
229 is
kono
parents:
diff changeset
230 File_Length : constant File_Size := Mmap.Length (File);
kono
parents:
diff changeset
231
kono
parents:
diff changeset
232 Req_Offset : constant File_Size := Offset;
kono
parents:
diff changeset
233 Req_Length : File_Size := Length;
kono
parents:
diff changeset
234 -- Offset and Length of the region to map, used to adjust mapping
kono
parents:
diff changeset
235 -- bounds, reflecting what the user will see.
kono
parents:
diff changeset
236
kono
parents:
diff changeset
237 Region_Allocated : Boolean := False;
kono
parents:
diff changeset
238 begin
kono
parents:
diff changeset
239 -- If this region comes from another file, or simply if the file is
kono
parents:
diff changeset
240 -- writeable, we cannot re-use this mapping: free it first.
kono
parents:
diff changeset
241
kono
parents:
diff changeset
242 if Region /= Invalid_Mapped_Region
kono
parents:
diff changeset
243 and then
kono
parents:
diff changeset
244 (Region.File /= File or else File.File.Write)
kono
parents:
diff changeset
245 then
kono
parents:
diff changeset
246 Free (Region);
kono
parents:
diff changeset
247 end if;
kono
parents:
diff changeset
248
kono
parents:
diff changeset
249 if Region = Invalid_Mapped_Region then
kono
parents:
diff changeset
250 Region := new Mapped_Region_Record'(Invalid_Mapped_Region_Record);
kono
parents:
diff changeset
251 Region_Allocated := True;
kono
parents:
diff changeset
252 end if;
kono
parents:
diff changeset
253
kono
parents:
diff changeset
254 Region.File := File;
kono
parents:
diff changeset
255
kono
parents:
diff changeset
256 if Req_Offset >= File_Length then
kono
parents:
diff changeset
257 -- If the requested offset goes beyond file size, map nothing
kono
parents:
diff changeset
258
kono
parents:
diff changeset
259 Req_Length := 0;
kono
parents:
diff changeset
260
kono
parents:
diff changeset
261 elsif Length = 0
kono
parents:
diff changeset
262 or else
kono
parents:
diff changeset
263 Length > File_Length - Req_Offset
kono
parents:
diff changeset
264 then
kono
parents:
diff changeset
265 -- If Length is 0 or goes beyond file size, map till end of file
kono
parents:
diff changeset
266
kono
parents:
diff changeset
267 Req_Length := File_Length - Req_Offset;
kono
parents:
diff changeset
268
kono
parents:
diff changeset
269 else
kono
parents:
diff changeset
270 Req_Length := Length;
kono
parents:
diff changeset
271 end if;
kono
parents:
diff changeset
272
kono
parents:
diff changeset
273 -- Past this point, the offset/length the user will see is fixed. On the
kono
parents:
diff changeset
274 -- other hand, the system offset/length is either already defined, from
kono
parents:
diff changeset
275 -- a previous mapping, or it is set to 0. In the latter case, the next
kono
parents:
diff changeset
276 -- step will set them according to the mapping.
kono
parents:
diff changeset
277
kono
parents:
diff changeset
278 Region.User_Offset := Req_Offset;
kono
parents:
diff changeset
279 Region.User_Size := Req_Length;
kono
parents:
diff changeset
280
kono
parents:
diff changeset
281 -- If the requested region is inside an already mapped region, adjust
kono
parents:
diff changeset
282 -- user-requested data and do nothing else.
kono
parents:
diff changeset
283
kono
parents:
diff changeset
284 if (File.File.Write or else Region.Mutable = Mutable)
kono
parents:
diff changeset
285 and then
kono
parents:
diff changeset
286 Req_Offset >= Region.System_Offset
kono
parents:
diff changeset
287 and then
kono
parents:
diff changeset
288 (Req_Offset + Req_Length
kono
parents:
diff changeset
289 <= Region.System_Offset + Region.System_Size)
kono
parents:
diff changeset
290 then
kono
parents:
diff changeset
291 Region.User_Offset := Req_Offset;
kono
parents:
diff changeset
292 Compute_Data (Region);
kono
parents:
diff changeset
293 return;
kono
parents:
diff changeset
294
kono
parents:
diff changeset
295 elsif Region.Buffer /= null then
kono
parents:
diff changeset
296 -- Otherwise, as we are not going to re-use the buffer, free it
kono
parents:
diff changeset
297
kono
parents:
diff changeset
298 System.Strings.Free (Region.Buffer);
kono
parents:
diff changeset
299 Region.Buffer := null;
kono
parents:
diff changeset
300
kono
parents:
diff changeset
301 elsif Region.Mapping /= Invalid_System_Mapping then
kono
parents:
diff changeset
302 -- Otherwise, there is a memory mapping that we need to unmap.
kono
parents:
diff changeset
303 Dispose_Mapping (Region.Mapping);
kono
parents:
diff changeset
304 end if;
kono
parents:
diff changeset
305
kono
parents:
diff changeset
306 -- mmap() will sometimes return NULL when the file exists but is empty,
kono
parents:
diff changeset
307 -- which is not what we want, so in the case of a zero length file we
kono
parents:
diff changeset
308 -- fall back to read(2)/write(2)-based mode.
kono
parents:
diff changeset
309
kono
parents:
diff changeset
310 if File_Length > 0 and then File.File.Mapped then
kono
parents:
diff changeset
311
kono
parents:
diff changeset
312 Region.System_Offset := Req_Offset;
kono
parents:
diff changeset
313 Region.System_Size := Req_Length;
kono
parents:
diff changeset
314 Create_Mapping
kono
parents:
diff changeset
315 (File.File,
kono
parents:
diff changeset
316 Region.System_Offset, Region.System_Size,
kono
parents:
diff changeset
317 Mutable,
kono
parents:
diff changeset
318 Region.Mapping);
kono
parents:
diff changeset
319 Region.Mapped := True;
kono
parents:
diff changeset
320 Region.Mutable := Mutable;
kono
parents:
diff changeset
321
kono
parents:
diff changeset
322 else
kono
parents:
diff changeset
323 -- There is no alignment requirement when manually reading the file.
kono
parents:
diff changeset
324
kono
parents:
diff changeset
325 Region.System_Offset := Req_Offset;
kono
parents:
diff changeset
326 Region.System_Size := Req_Length;
kono
parents:
diff changeset
327 Region.Mapped := False;
kono
parents:
diff changeset
328 Region.Mutable := True;
kono
parents:
diff changeset
329 From_Disk (Region);
kono
parents:
diff changeset
330 end if;
kono
parents:
diff changeset
331
kono
parents:
diff changeset
332 Region.Write := File.File.Write;
kono
parents:
diff changeset
333 Compute_Data (Region);
kono
parents:
diff changeset
334
kono
parents:
diff changeset
335 exception
kono
parents:
diff changeset
336 when others =>
kono
parents:
diff changeset
337 -- Before propagating any exception, free any region we allocated
kono
parents:
diff changeset
338 -- here.
kono
parents:
diff changeset
339
kono
parents:
diff changeset
340 if Region_Allocated then
kono
parents:
diff changeset
341 Dispose (Region);
kono
parents:
diff changeset
342 end if;
kono
parents:
diff changeset
343 raise;
kono
parents:
diff changeset
344 end Read;
kono
parents:
diff changeset
345
kono
parents:
diff changeset
346 ----------
kono
parents:
diff changeset
347 -- Read --
kono
parents:
diff changeset
348 ----------
kono
parents:
diff changeset
349
kono
parents:
diff changeset
350 procedure Read
kono
parents:
diff changeset
351 (File : Mapped_File;
kono
parents:
diff changeset
352 Offset : File_Size := 0;
kono
parents:
diff changeset
353 Length : File_Size := 0;
kono
parents:
diff changeset
354 Mutable : Boolean := False)
kono
parents:
diff changeset
355 is
kono
parents:
diff changeset
356 begin
kono
parents:
diff changeset
357 Read (File, File.Current_Region, Offset, Length, Mutable);
kono
parents:
diff changeset
358 end Read;
kono
parents:
diff changeset
359
kono
parents:
diff changeset
360 ----------
kono
parents:
diff changeset
361 -- Read --
kono
parents:
diff changeset
362 ----------
kono
parents:
diff changeset
363
kono
parents:
diff changeset
364 function Read
kono
parents:
diff changeset
365 (File : Mapped_File;
kono
parents:
diff changeset
366 Offset : File_Size := 0;
kono
parents:
diff changeset
367 Length : File_Size := 0;
kono
parents:
diff changeset
368 Mutable : Boolean := False) return Mapped_Region
kono
parents:
diff changeset
369 is
kono
parents:
diff changeset
370 Region : Mapped_Region := Invalid_Mapped_Region;
kono
parents:
diff changeset
371 begin
kono
parents:
diff changeset
372 Read (File, Region, Offset, Length, Mutable);
kono
parents:
diff changeset
373 return Region;
kono
parents:
diff changeset
374 end Read;
kono
parents:
diff changeset
375
kono
parents:
diff changeset
376 ------------
kono
parents:
diff changeset
377 -- Length --
kono
parents:
diff changeset
378 ------------
kono
parents:
diff changeset
379
kono
parents:
diff changeset
380 function Length (File : Mapped_File) return File_Size is
kono
parents:
diff changeset
381 begin
kono
parents:
diff changeset
382 return File.File.Length;
kono
parents:
diff changeset
383 end Length;
kono
parents:
diff changeset
384
kono
parents:
diff changeset
385 ------------
kono
parents:
diff changeset
386 -- Offset --
kono
parents:
diff changeset
387 ------------
kono
parents:
diff changeset
388
kono
parents:
diff changeset
389 function Offset (Region : Mapped_Region) return File_Size is
kono
parents:
diff changeset
390 begin
kono
parents:
diff changeset
391 return Region.User_Offset;
kono
parents:
diff changeset
392 end Offset;
kono
parents:
diff changeset
393
kono
parents:
diff changeset
394 ------------
kono
parents:
diff changeset
395 -- Offset --
kono
parents:
diff changeset
396 ------------
kono
parents:
diff changeset
397
kono
parents:
diff changeset
398 function Offset (File : Mapped_File) return File_Size is
kono
parents:
diff changeset
399 begin
kono
parents:
diff changeset
400 return Offset (File.Current_Region);
kono
parents:
diff changeset
401 end Offset;
kono
parents:
diff changeset
402
kono
parents:
diff changeset
403 ----------
kono
parents:
diff changeset
404 -- Last --
kono
parents:
diff changeset
405 ----------
kono
parents:
diff changeset
406
kono
parents:
diff changeset
407 function Last (Region : Mapped_Region) return Integer is
kono
parents:
diff changeset
408 begin
kono
parents:
diff changeset
409 return Integer (Region.User_Size);
kono
parents:
diff changeset
410 end Last;
kono
parents:
diff changeset
411
kono
parents:
diff changeset
412 ----------
kono
parents:
diff changeset
413 -- Last --
kono
parents:
diff changeset
414 ----------
kono
parents:
diff changeset
415
kono
parents:
diff changeset
416 function Last (File : Mapped_File) return Integer is
kono
parents:
diff changeset
417 begin
kono
parents:
diff changeset
418 return Last (File.Current_Region);
kono
parents:
diff changeset
419 end Last;
kono
parents:
diff changeset
420
kono
parents:
diff changeset
421 -------------------
kono
parents:
diff changeset
422 -- To_Str_Access --
kono
parents:
diff changeset
423 -------------------
kono
parents:
diff changeset
424
kono
parents:
diff changeset
425 function To_Str_Access
kono
parents:
diff changeset
426 (Str : System.Strings.String_Access) return Str_Access is
kono
parents:
diff changeset
427 begin
kono
parents:
diff changeset
428 if Str = null then
kono
parents:
diff changeset
429 return null;
kono
parents:
diff changeset
430 else
kono
parents:
diff changeset
431 return Convert (Str.all'Address);
kono
parents:
diff changeset
432 end if;
kono
parents:
diff changeset
433 end To_Str_Access;
kono
parents:
diff changeset
434
kono
parents:
diff changeset
435 ----------
kono
parents:
diff changeset
436 -- Data --
kono
parents:
diff changeset
437 ----------
kono
parents:
diff changeset
438
kono
parents:
diff changeset
439 function Data (Region : Mapped_Region) return Str_Access is
kono
parents:
diff changeset
440 begin
kono
parents:
diff changeset
441 return Region.Data;
kono
parents:
diff changeset
442 end Data;
kono
parents:
diff changeset
443
kono
parents:
diff changeset
444 ----------
kono
parents:
diff changeset
445 -- Data --
kono
parents:
diff changeset
446 ----------
kono
parents:
diff changeset
447
kono
parents:
diff changeset
448 function Data (File : Mapped_File) return Str_Access is
kono
parents:
diff changeset
449 begin
kono
parents:
diff changeset
450 return Data (File.Current_Region);
kono
parents:
diff changeset
451 end Data;
kono
parents:
diff changeset
452
kono
parents:
diff changeset
453 ----------------
kono
parents:
diff changeset
454 -- Is_Mutable --
kono
parents:
diff changeset
455 ----------------
kono
parents:
diff changeset
456
kono
parents:
diff changeset
457 function Is_Mutable (Region : Mapped_Region) return Boolean is
kono
parents:
diff changeset
458 begin
kono
parents:
diff changeset
459 return Region.Mutable or Region.Write;
kono
parents:
diff changeset
460 end Is_Mutable;
kono
parents:
diff changeset
461
kono
parents:
diff changeset
462 ----------------
kono
parents:
diff changeset
463 -- Is_Mmapped --
kono
parents:
diff changeset
464 ----------------
kono
parents:
diff changeset
465
kono
parents:
diff changeset
466 function Is_Mmapped (File : Mapped_File) return Boolean is
kono
parents:
diff changeset
467 begin
kono
parents:
diff changeset
468 return File.File.Mapped;
kono
parents:
diff changeset
469 end Is_Mmapped;
kono
parents:
diff changeset
470
kono
parents:
diff changeset
471 -------------------
kono
parents:
diff changeset
472 -- Get_Page_Size --
kono
parents:
diff changeset
473 -------------------
kono
parents:
diff changeset
474
kono
parents:
diff changeset
475 function Get_Page_Size return Integer is
kono
parents:
diff changeset
476 Result : constant File_Size := Get_Page_Size;
kono
parents:
diff changeset
477 begin
kono
parents:
diff changeset
478 return Integer (Result);
kono
parents:
diff changeset
479 end Get_Page_Size;
kono
parents:
diff changeset
480
kono
parents:
diff changeset
481 ---------------------
kono
parents:
diff changeset
482 -- Read_Whole_File --
kono
parents:
diff changeset
483 ---------------------
kono
parents:
diff changeset
484
kono
parents:
diff changeset
485 function Read_Whole_File
kono
parents:
diff changeset
486 (Filename : String;
kono
parents:
diff changeset
487 Empty_If_Not_Found : Boolean := False)
kono
parents:
diff changeset
488 return System.Strings.String_Access
kono
parents:
diff changeset
489 is
kono
parents:
diff changeset
490 File : Mapped_File := Open_Read (Filename);
kono
parents:
diff changeset
491 Region : Mapped_Region renames File.Current_Region;
kono
parents:
diff changeset
492 Result : String_Access;
kono
parents:
diff changeset
493 begin
kono
parents:
diff changeset
494 Read (File);
kono
parents:
diff changeset
495
kono
parents:
diff changeset
496 if Region.Data /= null then
kono
parents:
diff changeset
497 Result := new String'(String
kono
parents:
diff changeset
498 (Region.Data (1 .. Last (Region))));
kono
parents:
diff changeset
499
kono
parents:
diff changeset
500 elsif Region.Buffer /= null then
kono
parents:
diff changeset
501 Result := Region.Buffer;
kono
parents:
diff changeset
502 Region.Buffer := null; -- So that it is not deallocated
kono
parents:
diff changeset
503 end if;
kono
parents:
diff changeset
504
kono
parents:
diff changeset
505 Close (File);
kono
parents:
diff changeset
506
kono
parents:
diff changeset
507 return Result;
kono
parents:
diff changeset
508
kono
parents:
diff changeset
509 exception
kono
parents:
diff changeset
510 when Ada.IO_Exceptions.Name_Error =>
kono
parents:
diff changeset
511 if Empty_If_Not_Found then
kono
parents:
diff changeset
512 return new String'("");
kono
parents:
diff changeset
513 else
kono
parents:
diff changeset
514 return null;
kono
parents:
diff changeset
515 end if;
kono
parents:
diff changeset
516
kono
parents:
diff changeset
517 when others =>
kono
parents:
diff changeset
518 Close (File);
kono
parents:
diff changeset
519 return null;
kono
parents:
diff changeset
520 end Read_Whole_File;
kono
parents:
diff changeset
521
kono
parents:
diff changeset
522 ---------------
kono
parents:
diff changeset
523 -- From_Disk --
kono
parents:
diff changeset
524 ---------------
kono
parents:
diff changeset
525
kono
parents:
diff changeset
526 procedure From_Disk (Region : Mapped_Region) is
kono
parents:
diff changeset
527 begin
kono
parents:
diff changeset
528 pragma Assert (Region.File.all /= Invalid_Mapped_File_Record);
kono
parents:
diff changeset
529 pragma Assert (Region.Buffer = null);
kono
parents:
diff changeset
530
kono
parents:
diff changeset
531 Region.Buffer := Read_From_Disk
kono
parents:
diff changeset
532 (Region.File.File, Region.User_Offset, Region.User_Size);
kono
parents:
diff changeset
533 Region.Mapped := False;
kono
parents:
diff changeset
534 end From_Disk;
kono
parents:
diff changeset
535
kono
parents:
diff changeset
536 -------------
kono
parents:
diff changeset
537 -- To_Disk --
kono
parents:
diff changeset
538 -------------
kono
parents:
diff changeset
539
kono
parents:
diff changeset
540 procedure To_Disk (Region : Mapped_Region) is
kono
parents:
diff changeset
541 begin
kono
parents:
diff changeset
542 if Region.Write and then Region.Buffer /= null then
kono
parents:
diff changeset
543 pragma Assert (Region.File.all /= Invalid_Mapped_File_Record);
kono
parents:
diff changeset
544 Write_To_Disk
kono
parents:
diff changeset
545 (Region.File.File,
kono
parents:
diff changeset
546 Region.User_Offset, Region.User_Size,
kono
parents:
diff changeset
547 Region.Buffer);
kono
parents:
diff changeset
548 end if;
kono
parents:
diff changeset
549
kono
parents:
diff changeset
550 System.Strings.Free (Region.Buffer);
kono
parents:
diff changeset
551 Region.Buffer := null;
kono
parents:
diff changeset
552 end To_Disk;
kono
parents:
diff changeset
553
kono
parents:
diff changeset
554 ------------------
kono
parents:
diff changeset
555 -- Compute_Data --
kono
parents:
diff changeset
556 ------------------
kono
parents:
diff changeset
557
kono
parents:
diff changeset
558 procedure Compute_Data (Region : Mapped_Region) is
kono
parents:
diff changeset
559 Base_Data : Str_Access;
kono
parents:
diff changeset
560 -- Address of the first byte actually mapped in memory
kono
parents:
diff changeset
561
kono
parents:
diff changeset
562 Data_Shift : constant Integer :=
kono
parents:
diff changeset
563 Integer (Region.User_Offset - Region.System_Offset);
kono
parents:
diff changeset
564 begin
kono
parents:
diff changeset
565 if Region.User_Size = 0 then
kono
parents:
diff changeset
566 Region.Data := Convert (Empty_String'Address);
kono
parents:
diff changeset
567 return;
kono
parents:
diff changeset
568 elsif Region.Mapped then
kono
parents:
diff changeset
569 Base_Data := Convert (Region.Mapping.Address);
kono
parents:
diff changeset
570 else
kono
parents:
diff changeset
571 Base_Data := Convert (Region.Buffer.all'Address);
kono
parents:
diff changeset
572 end if;
kono
parents:
diff changeset
573 Region.Data := Convert (Base_Data (Data_Shift + 1)'Address);
kono
parents:
diff changeset
574 end Compute_Data;
kono
parents:
diff changeset
575
kono
parents:
diff changeset
576 end System.Mmap;