Line data Source code
1 : /**
2 : Copyright (c) 2016-2022 Roman Katuntsev <sbkarr@stappler.org>
3 : Copyright (c) 2023 Stappler LLC <admin@stappler.dev>
4 :
5 : Permission is hereby granted, free of charge, to any person obtaining a copy
6 : of this software and associated documentation files (the "Software"), to deal
7 : in the Software without restriction, including without limitation the rights
8 : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 : copies of the Software, and to permit persons to whom the Software is
10 : furnished to do so, subject to the following conditions:
11 :
12 : The above copyright notice and this permission notice shall be included in
13 : all copies or substantial portions of the Software.
14 :
15 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 : THE SOFTWARE.
22 : **/
23 :
24 : #ifndef STAPPLER_CORE_IO_SPIOPRODUCER_H_
25 : #define STAPPLER_CORE_IO_SPIOPRODUCER_H_
26 :
27 : #include "SPIOCommon.h"
28 :
29 : namespace STAPPLER_VERSIONIZED stappler::io {
30 :
31 : struct ProducerTraitsStream {
32 : using stream_type = std::basic_istream<char>;
33 :
34 : static size_t ReadFn(void *ptr, uint8_t *buf, size_t nbytes) {
35 : ((stream_type *)ptr)->get((stream_type::char_type *)buf, nbytes);
36 : return ((stream_type *)ptr)->gcount();
37 : }
38 :
39 : static size_t SeekFn(void *ptr, int64_t offset, Seek s) {
40 : std::ios_base::seekdir d;
41 : switch(s) {
42 : case Seek::Set: d = std::ios_base::beg; break;
43 : case Seek::Current: d = std::ios_base::cur; break;
44 : case Seek::End: d = std::ios_base::end; break;
45 : }
46 : auto & stream = *((stream_type *)ptr);
47 : stream.seekg(offset, d);
48 : if (stream.fail()) {
49 : return maxOf<size_t>();
50 : } else {
51 : return (size_t)stream.tellg();
52 : }
53 : }
54 :
55 : static size_t TellFn(void *ptr) {
56 : auto & stream = *((stream_type *)ptr);
57 : return (size_t)stream.tellg();
58 : }
59 : };
60 :
61 : template <class T> size_t ReadFunction(T &, uint8_t *buf, size_t nbytes);
62 : template <class T> size_t SeekFunction(T &, int64_t offset, Seek s);
63 : template <class T> size_t TellFunction(T &);
64 :
65 : template <class T>
66 : struct ProducerTraitsOverload {
67 : static size_t ReadFn(void *ptr, uint8_t *buf, size_t nbytes) {
68 : return ReadFunction(*((T *)ptr), buf, nbytes);
69 : }
70 :
71 : static size_t SeekFn(void *ptr, int64_t offset, Seek s) {
72 : return SeekFunction(*((T *)ptr), offset, s);
73 : }
74 :
75 : static size_t TellFn(void *ptr) {
76 : return TellFunction(*((T *)ptr));
77 : }
78 : };
79 :
80 : template <typename T>
81 : struct ProducerTraitsResolution {
82 : using type = typename std::conditional<
83 : std::is_base_of<std::basic_istream<char>, T>::value,
84 : ProducerTraitsStream,
85 : ProducerTraitsOverload<T>>::type;
86 : };
87 :
88 : template <typename T>
89 : struct ProducerTraits {
90 : using traits_type = typename ProducerTraitsResolution<T>::type;
91 : static size_t ReadFn(void *ptr, uint8_t *buf, size_t nbytes) {
92 : return traits_type::ReadFn(ptr, buf, nbytes);
93 : }
94 :
95 : static size_t SeekFn(void *ptr, int64_t offset, Seek s) { return traits_type::SeekFn(ptr, offset, s); }
96 : static size_t TellFn(void *ptr) { return traits_type::TellFn(ptr); }
97 : };
98 :
99 : struct Producer {
100 : template <typename T, typename Traits = ProducerTraits<typename std::decay<T>::type>> Producer(T &t);
101 :
102 : size_t read(uint8_t *buf, size_t nbytes) const;
103 : size_t read(const Buffer &, size_t nbytes) const;
104 : size_t seek(int64_t offset, Seek s) const;
105 :
106 : template <typename T>
107 : size_t seekAndRead(size_t offset, T &&, size_t nbytes) const;
108 :
109 : size_t tell() const;
110 :
111 : void *ptr = nullptr;
112 : read_fn read_ptr = nullptr;
113 : seek_fn seek_ptr = nullptr;
114 : size_fn tell_ptr = nullptr;
115 : };
116 :
117 : template <typename T, typename Traits>
118 5194 : inline Producer::Producer(T &t)
119 5194 : : ptr((void *)(&t))
120 5194 : , read_ptr(&Traits::ReadFn)
121 5194 : , seek_ptr(&Traits::SeekFn)
122 5194 : , tell_ptr(&Traits::TellFn) { }
123 :
124 : inline size_t Producer::read(uint8_t *buf, size_t nbytes) const {
125 : return read_ptr(ptr, buf, nbytes);
126 : }
127 :
128 7069 : inline size_t Producer::seek(int64_t offset, Seek s) const {
129 7069 : return seek_ptr(ptr, offset, s);
130 : }
131 :
132 : template <typename T>
133 7044 : inline size_t Producer::seekAndRead(size_t offset, T && t, size_t nbytes) const {
134 7044 : seek(offset, Seek::Set);
135 7044 : return read(std::forward<T>(t), nbytes);
136 : }
137 :
138 : inline size_t Producer::tell() const { return tell_ptr(ptr); }
139 :
140 : }
141 :
142 : #endif /* STAPPLER_CORE_IO_SPIOPRODUCER_H_ */
|