-
Notifications
You must be signed in to change notification settings - Fork 3
/
Stream.cpp
113 lines (103 loc) · 3.66 KB
/
Stream.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
/*
* This file is part of rSON
* Copyright © 2016-2017 Rachel Mant (dx-mon@users.sourceforge.net)
*
* rSON is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* rSON is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <sys/stat.h>
#include <stddef.h>
#include <fcntl.h>
#ifndef _MSC_VER
#include <unistd.h>
#else
#include <io.h>
#include <type_traits>
using ssize_t = typename std::make_signed<size_t>::type;
#endif
#include <errno.h>
#include <system_error>
#include "internal.h"
fileStream_t::fileStream_t(const char *const fileName, const int32_t _mode, const int32_t perms) : fd(-1), eof(false), mode(_mode)
{
struct stat fileStat;
fd = open(fileName, mode, perms);
if (fd == -1 || fstat(fd, &fileStat) != 0)
throw std::system_error(errno, std::system_category());
length = fileStat.st_size + 1;
}
fileStream_t::~fileStream_t() noexcept { close(fd); }
bool fileStream_t::read(void *const value, const size_t valueLen, size_t &actualLen)
{
// If write-only and not read-write mode, or we got to eof.. return false.
if (eof || ((mode & O_WRONLY) && !(mode & O_RDWR)))
return false;
#ifndef _MSC_VER
ssize_t ret = ::read(fd, value, valueLen);
#else
ssize_t ret = ::read(fd, value, uint32_t(valueLen));
#endif
if (ret < 0)
throw std::system_error(errno, std::system_category());
// This call sets EOF for us.
seek(0, SEEK_CUR);
actualLen = size_t(ret);
return true;
}
bool fileStream_t::write(const void *const value, const size_t valueLen)
{
// If read-only and not read-write mode, or we ran out of space.. return false.
if (eof || !(mode & (O_WRONLY | O_RDWR)))
return false;
#ifndef _MSC_VER
ssize_t ret = ::write(fd, value, valueLen);
#else
ssize_t ret = ::write(fd, value, uint32_t(valueLen));
#endif
if (ret < 0)
throw std::system_error(errno, std::system_category());
eof = ret == 0;
length = lseek(fd, 0, SEEK_CUR);
return !eof;
}
off_t fileStream_t::seek(const off_t offset, const int whence) noexcept
{
off_t result = lseek(fd, offset, whence);
eof = length == size_t(result);
return result;
}
memoryStream_t::memoryStream_t(void *const stream, const size_t streamLength) noexcept :
memory(static_cast<char *const>(stream)), length(streamLength), pos(0) { }
bool memoryStream_t::read(void *const value, const size_t valueLen, size_t &actualLen) noexcept
{
// If at "end of file", or the requested read would cause position wrap around, return false.
if (atEOF() || (pos + valueLen) < pos)
return false;
// Calculate how much we can really read vs requested.
actualLen = (pos + valueLen) > length ? length - pos : valueLen;
memcpy(value, memory + pos, actualLen);
pos += actualLen;
return true;
}
bool memoryStream_t::write(const void *const value, const size_t valueLen) noexcept
{
// If at "end of file", or the requested write would cause position wrap-around, return false.
if (atEOF() || (pos + valueLen) < pos)
return false;
// Calculate how much we can really write vs requested.
const size_t actualLen = (pos + valueLen) > length ? length - pos : valueLen;
memcpy(memory + pos, value, actualLen);
pos += actualLen;
// If we did not acomplish a complete write, we consider that a failure.
return valueLen == actualLen;
}