1 module dlangui.core.textsource;
2 
3 private import std.utf;
4 private import std.array;
5 
6 /**
7 * Source file information.
8 * Even if contains only file name, it's better to use it instead of string - object reference size is twice less than array ref.
9 */
10 class SourceFile {
11     protected string _filename;
12     @property string filename() { return _filename; }
13     public this(string filename) {
14         _filename = filename;
15     }
16     override @property string toString() const {
17         return _filename;
18     }
19 }
20 
21 /// source lines for tokenizer
22 interface SourceLines {
23     /// source file
24     @property SourceFile file();
25     /// last read line
26     @property uint line();
27     /// source encoding
28     //@property EncodingType encoding() { return _encoding; }
29     /// error code
30     @property int errorCode();
31     /// error message
32     @property string errorMessage();
33     /// error line
34     @property int errorLine();
35     /// error position
36     @property int errorPos();
37     /// end of file reached
38     @property bool eof();
39 
40     /// read line, return null if EOF reached or error occured
41     dchar[] readLine();
42 }
43 
44 const TEXT_SOURCE_ERROR_EOF = 1;
45 
46 /// Simple text source based on array
47 class ArraySourceLines : SourceLines {
48     protected SourceFile _file;
49     protected uint _line;
50     protected uint _firstLine;
51     protected dstring[] _lines;
52     static __gshared protected dchar[] _emptyLine = ""d.dup;
53 
54     this() {
55     }
56 
57     this(dstring[] lines, SourceFile file, uint firstLine = 0) {
58         initialize(lines, file, firstLine);
59     }
60 
61     this(string code, string filename) {
62         _lines = (toUTF32(code)).split("\n");
63         _file = new SourceFile(filename);
64     }
65 
66     void close() {
67         _lines = null;
68         _line = 0;
69         _firstLine = 0;
70         _file = null;
71     }
72 
73     void initialize(dstring[] lines, SourceFile file, uint firstLine = 0) {
74         _lines = lines;
75         _firstLine = firstLine;
76         _line = 0;
77         _file = file;
78     }
79 
80     bool reset(int line) {
81         _line = line;
82         return true;
83     }
84 
85     /// end of file reached
86     override @property bool eof() {
87         return _line >= _lines.length;
88     }
89     /// source file
90     override @property SourceFile file() { return _file; }
91     /// last read line
92     override @property uint line() { return _line + _firstLine; }
93     /// source encoding
94     //@property EncodingType encoding() { return _encoding; }
95     /// error code
96     override @property int errorCode() { return 0; }
97     /// error message
98     override @property string errorMessage() { return ""; }
99     /// error line
100     override @property int errorLine() { return 0; }
101     /// error position
102     override @property int errorPos() { return 0; }
103 
104     /// read line, return null if EOF reached or error occured
105     override dchar[] readLine() {
106         if (_line < _lines.length) {
107             if (_lines[_line])
108                 return cast(dchar[])_lines[_line++];
109             _line++;
110             return _emptyLine;
111         }
112         return null; // EOF
113     }
114 }
115