Веб-сайт самохостера Lotigara

summaryrefslogtreecommitdiff
path: root/source/core/StarIODevice.hpp
blob: 7bc2a04ffab17b5b1e6f67b59bd06f4210902e85 (plain)
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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#pragma once

#include "StarByteArray.hpp"
#include "StarString.hpp"

namespace Star {

STAR_CLASS(IODevice);

STAR_EXCEPTION(EofException, IOException);

enum class IOMode : uint8_t {
  Closed = 0x0,
  Read = 0x1,
  Write = 0x2,
  ReadWrite = 0x3,
  Append = 0x4,
  Truncate = 0x8,
};

IOMode operator|(IOMode a, IOMode b);
bool operator&(IOMode a, IOMode b);

// Should match SEEK_SET, SEEK_CUR, AND SEEK_END
enum IOSeek : uint8_t {
  Absolute = 0,
  Relative = 1,
  End = 2
};

// Abstract Interface to a random access I/O device.
class IODevice {
public:
  IODevice(IOMode mode = IOMode::Closed);
  virtual ~IODevice();

  // Do a read or write that may result in less data read or written than
  // requested.
  virtual size_t read(char* data, size_t len) = 0;
  virtual size_t write(char const* data, size_t len) = 0;

  virtual StreamOffset pos() = 0;
  virtual void seek(StreamOffset pos, IOSeek mode = IOSeek::Absolute) = 0;

  // Default implementation throws unsupported exception.
  virtual void resize(StreamOffset size);

  // Read / write from an absolute offset in the file without modifying the
  // current file position.  Default implementation stores the file position,
  // then seeks and calls read/write partial, then restores the file position,
  // and is not thread safe.
  virtual size_t readAbsolute(StreamOffset readPosition, char* data, size_t len);
  virtual size_t writeAbsolute(StreamOffset writePosition, char const* data, size_t len);

  // Read and write fully, and throw an exception in every other case.  The
  // default implementations here will call the normal read or write, and if
  // the full amount is not read will throw an exception.
  virtual void readFull(char* data, size_t len);
  virtual void writeFull(char const* data, size_t len);
  virtual void readFullAbsolute(StreamOffset readPosition, char* data, size_t len);
  virtual void writeFullAbsolute(StreamOffset writePosition, char const* data, size_t len);

  // Default implementation throws exception if opening in a different mode
  // than the current mode.
  virtual void open(IOMode mode);

  // Default implementation sets mode equal to Closed
  virtual void close();

  // Default implementation is a no-op
  virtual void sync();

  // Returns a clone of this device with the same mode
  virtual IODevicePtr clone() = 0;

  // Default implementation just prints address of generic IODevice
  virtual String deviceName() const;

  // Is the file position at the end of the file and there is no more to read?
  // This is not the same as feof, which returns true after an unsuccesful read
  // past the end, it should return true after succesfully reading the final
  // byte.  Default implementation returns pos() >= size();
  virtual bool atEnd();

  // Default is to store position, seek end, then restore position.
  virtual StreamOffset size();

  IOMode mode() const;
  bool isOpen() const;
  bool isReadable() const;
  bool isWritable() const;

  ByteArray readBytes(size_t size);
  void writeBytes(ByteArray const& p);

  ByteArray readBytesAbsolute(StreamOffset readPosition, size_t size);
  void writeBytesAbsolute(StreamOffset writePosition, ByteArray const& p);

protected:
  void setMode(IOMode mode);

  IODevice(IODevice const&);
  IODevice& operator=(IODevice const&);

private:
  atomic<IOMode> m_mode;
};

inline IOMode operator|(IOMode a, IOMode b) {
  return (IOMode)((uint8_t)a | (uint8_t)b);
}

inline bool operator&(IOMode a, IOMode b) {
  return (uint8_t)a & (uint8_t)b;
}

inline IOMode IODevice::mode() const {
  return m_mode;
}

inline bool IODevice::isOpen() const {
  return m_mode != IOMode::Closed;
}

inline bool IODevice::isReadable() const {
  return m_mode & IOMode::Read;
}

inline bool IODevice::isWritable() const {
  return m_mode & IOMode::Write;
}

}