Internally these would treat the cast same as a normal conversion from int[7] to int[], which allows code at CTFE to erroneously succeed where it would raise a SEGV at run-time.
1 |
/**
|
|
2 |
* Cache the contents from files read from disk into memory.
|
|
3 |
*
|
|
4 |
* Copyright: Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
|
|
5 |
* Authors: $(LINK2 http://www.digitalmars.com, Walter Bright)
|
|
6 |
* License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
|
|
7 |
* Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/filecache.d, filecache.d)
|
|
8 |
* Documentation: https://dlang.org/phobos/dmd_filecache.html
|
|
9 |
* Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/filecache.d
|
|
10 |
*/
|
|
11 |
|
|
12 |
module dmd.filecache; |
|
13 |
|
|
14 |
import dmd.root.stringtable; |
|
15 |
import dmd.root.array; |
|
16 |
import dmd.root.file; |
|
17 |
import dmd.root.filename; |
|
18 |
|
|
19 |
import core.stdc.stdio; |
|
20 |
|
|
21 |
/**
|
|
22 |
A line-by-line representation of a $(REF File, dmd,root,file).
|
|
23 |
*/
|
|
24 |
class FileAndLines |
|
25 |
{
|
|
26 |
FileName* file; |
|
27 |
FileBuffer* buffer; |
|
28 |
const(char[])[] lines; |
|
29 |
|
|
30 |
nothrow: |
|
31 |
|
|
32 |
/**
|
|
33 |
File to read and split into its lines.
|
|
34 |
*/
|
|
35 | 1 |
this(const(char)[] filename) |
36 |
{
|
|
37 | 1 |
file = new FileName(filename); |
38 | 1 |
readAndSplit(); |
39 |
}
|
|
40 |
|
|
41 |
// Read a file and split the file buffer linewise
|
|
42 |
private void readAndSplit() |
|
43 |
{
|
|
44 | 1 |
auto readResult = File.read(file.toChars()); |
45 |
// FIXME: check success
|
|
46 |
// take ownership of buffer
|
|
47 | 1 |
buffer = new FileBuffer(readResult.extractSlice()); |
48 | 1 |
ubyte* buf = buffer.data.ptr; |
49 |
// slice into lines
|
|
50 | 1 |
while (*buf) |
51 |
{
|
|
52 | 1 |
auto prevBuf = buf; |
53 | 1 |
for (; *buf != '\n' && *buf != '\r'; buf++) |
54 |
{
|
|
55 | 1 |
if (!*buf) |
56 |
break; |
|
57 |
}
|
|
58 |
// handle Windows line endings
|
|
59 | 1 |
if (*buf == '\r' && *(buf + 1) == '\n') |
60 |
buf++; |
|
61 | 1 |
lines ~= cast(const(char)[]) prevBuf[0 .. buf - prevBuf]; |
62 | 1 |
buf++; |
63 |
}
|
|
64 |
}
|
|
65 |
|
|
66 |
void destroy() |
|
67 |
{
|
|
68 |
if (file) |
|
69 |
{
|
|
70 |
file.destroy(); |
|
71 |
file = null; |
|
72 |
buffer.destroy(); |
|
73 |
buffer = null; |
|
74 |
lines.destroy(); |
|
75 |
lines = null; |
|
76 |
}
|
|
77 |
}
|
|
78 |
|
|
79 |
~this() |
|
80 |
{
|
|
81 |
destroy(); |
|
82 |
}
|
|
83 |
}
|
|
84 |
|
|
85 |
/**
|
|
86 |
A simple file cache that can be used to avoid reading the same file multiple times.
|
|
87 |
It stores its cached files as $(LREF FileAndLines)
|
|
88 |
*/
|
|
89 |
struct FileCache |
|
90 |
{
|
|
91 |
private StringTable!(FileAndLines) files; |
|
92 |
|
|
93 |
nothrow: |
|
94 |
|
|
95 |
/**
|
|
96 |
Add or get a file from the file cache.
|
|
97 |
If the file isn't part of the cache, it will be read from the filesystem.
|
|
98 |
If the file has been read before, the cached file object will be returned
|
|
99 |
|
|
100 |
Params:
|
|
101 |
file = file to load in (or get from) the cache
|
|
102 |
|
|
103 |
Returns: a $(LREF FileAndLines) object containing a line-by-line representation of the requested file
|
|
104 |
*/
|
|
105 |
FileAndLines addOrGetFile(const(char)[] file) |
|
106 |
{
|
|
107 | 1 |
if (auto payload = files.lookup(file)) |
108 |
{
|
|
109 | 1 |
if (payload !is null) |
110 | 1 |
return payload.value; |
111 |
}
|
|
112 |
|
|
113 | 1 |
auto lines = new FileAndLines(file); |
114 | 1 |
files.insert(file, lines); |
115 | 1 |
return lines; |
116 |
}
|
|
117 |
|
|
118 |
__gshared fileCache = FileCache(); |
|
119 |
|
|
120 |
// Initializes the global FileCache singleton
|
|
121 |
static __gshared void _init() |
|
122 |
{
|
|
123 | 1 |
fileCache.initialize(); |
124 |
}
|
|
125 |
|
|
126 |
void initialize() |
|
127 |
{
|
|
128 | 1 |
files._init(); |
129 |
}
|
|
130 |
|
|
131 |
void deinitialize() |
|
132 |
{
|
|
133 |
foreach (sv; files) |
|
134 |
sv.destroy(); |
|
135 |
files.reset(); |
|
136 |
}
|
|
137 |
}
|
Read our documentation on viewing source code .