1#include "File.h"
2
3
4void File::open(int file_descr, FileMode m, bool own)
5{
6    if (fd != -1) ::close(fd);
7    fd     = file_descr;
8    mode   = m;
9    own_fd = own;
10    pos    = 0;
11    buf    = xmalloc<uchar>(File_BufSize);
12    if (mode == READ) size = read(fd, buf, File_BufSize);
13    else              size = -1;
14}
15
16void File::open(cchar* name, cchar* mode_)
17{
18    if (fd != -1) ::close(fd);
19    bool    has_r = strchr(mode_, 'r') != NULL;
20    bool    has_w = strchr(mode_, 'w') != NULL;
21    bool    has_a = strchr(mode_, 'a') != NULL;
22    bool    has_p = strchr(mode_, '+') != NULL;
23    bool    has_x = strchr(mode_, 'x') != NULL;
24    assert(!(has_r && has_w));
25    assert(has_r || has_w || has_a);
26
27    int mask = 0;
28    if      (has_p) mask |= O_RDWR;
29    else if (has_r) mask |= O_RDONLY;
30    else            mask |= O_WRONLY;
31
32    if (!has_r) mask |= O_CREAT;
33    if (has_w)  mask |= O_TRUNC;
34    if (has_x)  mask |= O_EXCL;
35
36    fd = open64(name, mask, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
37
38    if (fd != -1){
39        mode   = has_r ? READ : WRITE;
40        own_fd = true;
41        pos    = 0;
42        if (has_a) lseek64(fd, 0, SEEK_END);
43        buf    = xmalloc<uchar>(File_BufSize);
44        if (mode == READ) size = read(fd, buf, File_BufSize);
45        else              size = -1;
46    }
47}
48
49
50void File::close(void)
51{
52    if (fd == -1) return;
53    if (mode == WRITE)
54        flush();
55    xfree(buf); buf = NULL;
56    if (own_fd)
57        ::close(fd);
58    fd = -1;
59}
60
61void File::seek(int64 file_pos, int whence)
62{
63    if (mode == WRITE){
64        flush();
65        pos = 0;
66        lseek64(fd, file_pos, whence);
67    }else{
68        if (whence == SEEK_CUR) lseek64(fd, file_pos - (size - pos), SEEK_CUR);
69        else                    lseek64(fd, file_pos, whence);
70        size = read(fd, buf, File_BufSize);
71        pos = 0;
72    }
73}
74
75int64 File::tell(void)
76{
77    if (mode == WRITE)
78        return lseek64(fd, 0, SEEK_CUR);
79    else
80        return lseek64(fd, 0, SEEK_CUR) - (size - pos);
81}
82
83
84//=================================================================================================
85// Marshaling:
86
87
88void putUInt(File& out, uint64 val)
89{
90    if (val < 0x20000000){
91        uint    v = (uint)val;
92        if (v < 0x80)
93            out.putChar(v);
94        else{
95            if (v < 0x2000)
96                out.putChar(0x80 | (v >> 8)),
97                out.putChar((uchar)v);
98            else if (v < 0x200000)
99                out.putChar(0xA0 | (v >> 16)),
100                out.putChar((uchar)(v >> 8)),
101                out.putChar((uchar)v);
102            else
103                out.putChar((v >> 24) | 0xC0),
104                out.putChar((uchar)(v >> 16)),
105                out.putChar((uchar)(v >> 8)),
106                out.putChar((uchar)v);
107        }
108    }else
109        out.putChar(0xE0),
110        out.putChar((uchar)(val >> 56)),
111        out.putChar((uchar)(val >> 48)),
112        out.putChar((uchar)(val >> 40)),
113        out.putChar((uchar)(val >> 32)),
114        out.putChar((uchar)(val >> 24)),
115        out.putChar((uchar)(val >> 16)),
116        out.putChar((uchar)(val >> 8)),
117        out.putChar((uchar)val);
118}
119
120
121uint64 getUInt(File& in)
122    throw(Exception_EOF)
123{
124    uint byte0, byte1, byte2, byte3, byte4, byte5, byte6, byte7;
125    byte0 = in.getChar();
126    if (byte0 == (uint)EOF)
127        throw Exception_EOF();
128    if (!(byte0 & 0x80))
129        return byte0;
130    else{
131        switch ((byte0 & 0x60) >> 5){
132        case 0:
133            byte1 = in.getChar();
134            return ((byte0 & 0x1F) << 8) | byte1;
135        case 1:
136            byte1 = in.getChar();
137            byte2 = in.getChar();
138            return ((byte0 & 0x1F) << 16) | (byte1 << 8) | byte2;
139        case 2:
140            byte1 = in.getChar();
141            byte2 = in.getChar();
142            byte3 = in.getChar();
143            return ((byte0 & 0x1F) << 24) | (byte1 << 16) | (byte2 << 8) | byte3;
144        default:
145            byte0 = in.getChar();
146            byte1 = in.getChar();
147            byte2 = in.getChar();
148            byte3 = in.getChar();
149            byte4 = in.getChar();
150            byte5 = in.getChar();
151            byte6 = in.getChar();
152            byte7 = in.getChar();
153            return ((uint64)((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3) << 32)
154                 |  (uint64)((byte4 << 24) | (byte5 << 16) | (byte6 << 8) | byte7);
155        }
156    }
157}
158