/src/dcmtk/dcmdata/libsrc/dcistrmf.cc
Line | Count | Source |
1 | | /* |
2 | | * |
3 | | * Copyright (C) 2002-2025, OFFIS e.V. |
4 | | * All rights reserved. See COPYRIGHT file for details. |
5 | | * |
6 | | * This software and supporting documentation were developed by |
7 | | * |
8 | | * OFFIS e.V. |
9 | | * R&D Division Health |
10 | | * Escherweg 2 |
11 | | * D-26121 Oldenburg, Germany |
12 | | * |
13 | | * |
14 | | * Module: dcmdata |
15 | | * |
16 | | * Author: Marco Eichelberg |
17 | | * |
18 | | * Purpose: DcmInputFileStream and related classes, |
19 | | * implements streamed input from files. |
20 | | * |
21 | | */ |
22 | | |
23 | | #include "dcmtk/config/osconfig.h" |
24 | | #include "dcmtk/dcmdata/dcistrmf.h" |
25 | | #include "dcmtk/dcmdata/dcistrmb.h" |
26 | | #include "dcmtk/dcmdata/dcerror.h" |
27 | | |
28 | | BEGIN_EXTERN_C |
29 | | #include <fcntl.h> |
30 | | #ifdef HAVE_IO_H |
31 | | #include <io.h> |
32 | | #endif |
33 | | END_EXTERN_C |
34 | | |
35 | | DcmFileProducer::DcmFileProducer(const OFFilename &filename, offile_off_t offset) |
36 | 0 | : DcmProducer() |
37 | 0 | , file_() |
38 | 0 | , status_(EC_Normal) |
39 | 0 | , size_(0) |
40 | 0 | { |
41 | 0 | if (file_.fopen(filename, "rb")) |
42 | 0 | { |
43 | | // Get number of bytes in file |
44 | 0 | file_.fseek(0L, SEEK_END); |
45 | 0 | size_ = file_.ftell(); |
46 | 0 | if (0 != file_.fseek(offset, SEEK_SET)) |
47 | 0 | { |
48 | 0 | OFString s("(unknown error code)"); |
49 | 0 | file_.getLastErrorString(s); |
50 | 0 | status_ = makeOFCondition(OFM_dcmdata, 18, OF_error, s.c_str()); |
51 | 0 | } |
52 | 0 | } |
53 | 0 | else |
54 | 0 | { |
55 | 0 | OFString s("(unknown error code)"); |
56 | 0 | file_.getLastErrorString(s); |
57 | 0 | status_ = makeOFCondition(OFM_dcmdata, 18, OF_error, s.c_str()); |
58 | 0 | } |
59 | 0 | } |
60 | | |
61 | | DcmFileProducer::~DcmFileProducer() |
62 | 0 | { |
63 | 0 | } |
64 | | |
65 | | OFBool DcmFileProducer::good() const |
66 | 0 | { |
67 | 0 | return status_.good(); |
68 | 0 | } |
69 | | |
70 | | OFCondition DcmFileProducer::status() const |
71 | 0 | { |
72 | 0 | return status_; |
73 | 0 | } |
74 | | |
75 | | OFBool DcmFileProducer::eos() |
76 | 0 | { |
77 | 0 | if (file_.open()) |
78 | 0 | { |
79 | 0 | return (file_.eof() || (size_ == file_.ftell())); |
80 | 0 | } |
81 | 0 | else return OFTrue; |
82 | 0 | } |
83 | | |
84 | | offile_off_t DcmFileProducer::avail() |
85 | 0 | { |
86 | 0 | if (file_.open()) return size_ - file_.ftell(); else return 0; |
87 | 0 | } |
88 | | |
89 | | offile_off_t DcmFileProducer::read(void *buf, offile_off_t buflen) |
90 | 0 | { |
91 | 0 | offile_off_t result = 0; |
92 | 0 | if (status_.good() && file_.open() && buf && buflen) |
93 | 0 | { |
94 | 0 | result = OFstatic_cast(offile_off_t, file_.fread(buf, 1, OFstatic_cast(size_t, buflen))); |
95 | 0 | } |
96 | 0 | return result; |
97 | 0 | } |
98 | | |
99 | | offile_off_t DcmFileProducer::skip(offile_off_t skiplen) |
100 | 0 | { |
101 | 0 | offile_off_t result = 0; |
102 | 0 | if (status_.good() && file_.open() && skiplen) |
103 | 0 | { |
104 | 0 | offile_off_t pos = file_.ftell(); |
105 | 0 | result = (size_ - pos < skiplen) ? (size_ - pos) : skiplen; |
106 | 0 | if (file_.fseek(result, SEEK_CUR)) |
107 | 0 | { |
108 | 0 | OFString s("(unknown error code)"); |
109 | 0 | file_.getLastErrorString(s); |
110 | 0 | status_ = makeOFCondition(OFM_dcmdata, 18, OF_error, s.c_str()); |
111 | 0 | } |
112 | 0 | } |
113 | 0 | return result; |
114 | 0 | } |
115 | | |
116 | | void DcmFileProducer::putback(offile_off_t num) |
117 | 0 | { |
118 | 0 | if (status_.good() && file_.open() && num) |
119 | 0 | { |
120 | 0 | offile_off_t pos = file_.ftell(); |
121 | 0 | if (num <= pos) |
122 | 0 | { |
123 | 0 | if (file_.fseek(-num, SEEK_CUR)) |
124 | 0 | { |
125 | 0 | OFString s("(unknown error code)"); |
126 | 0 | file_.getLastErrorString(s); |
127 | 0 | status_ = makeOFCondition(OFM_dcmdata, 18, OF_error, s.c_str()); |
128 | 0 | } |
129 | 0 | } |
130 | 0 | else status_ = EC_PutbackFailed; // tried to putback before start of file |
131 | 0 | } |
132 | 0 | } |
133 | | |
134 | | |
135 | | /* ======================================================================= */ |
136 | | |
137 | | DcmInputFileStreamFactory::DcmInputFileStreamFactory(const OFFilename &filename, offile_off_t offset) |
138 | 0 | : DcmInputStreamFactory() |
139 | 0 | , filename_(filename) |
140 | 0 | , offset_(offset) |
141 | 0 | { |
142 | 0 | } |
143 | | |
144 | | DcmInputFileStreamFactory::DcmInputFileStreamFactory(const DcmInputFileStreamFactory& arg) |
145 | 0 | : DcmInputStreamFactory(arg) |
146 | 0 | , filename_(arg.filename_) |
147 | 0 | , offset_(arg.offset_) |
148 | 0 | { |
149 | 0 | } |
150 | | |
151 | | DcmInputFileStreamFactory::~DcmInputFileStreamFactory() |
152 | 0 | { |
153 | 0 | } |
154 | | |
155 | | DcmInputStream *DcmInputFileStreamFactory::create() const |
156 | 0 | { |
157 | 0 | return new DcmInputFileStream(filename_, offset_); |
158 | 0 | } |
159 | | |
160 | | /* ======================================================================= */ |
161 | | |
162 | | DcmInputFileStream::DcmInputFileStream(const OFFilename &filename, offile_off_t offset) |
163 | 0 | : DcmInputStream(&producer_) // safe because DcmInputStream only stores pointer |
164 | 0 | , producer_(filename, offset) |
165 | 0 | , filename_(filename) |
166 | 0 | { |
167 | 0 | } |
168 | | |
169 | | DcmInputFileStream::~DcmInputFileStream() |
170 | 0 | { |
171 | 0 | } |
172 | | |
173 | | DcmInputStreamFactory *DcmInputFileStream::newFactory() const |
174 | 0 | { |
175 | 0 | DcmInputStreamFactory *result = NULL; |
176 | 0 | if (currentProducer() == &producer_) |
177 | 0 | { |
178 | | // no filter installed, can create factory object |
179 | 0 | result = new DcmInputFileStreamFactory(filename_, tell()); |
180 | 0 | } |
181 | 0 | return result; |
182 | 0 | } |
183 | | |
184 | | /* ======================================================================= */ |
185 | | |
186 | | DcmInputStream *DcmTempFileHandler::create() const |
187 | 0 | { |
188 | 0 | return new DcmInputFileStream(filename_, 0); |
189 | 0 | } |
190 | | |
191 | | DcmTempFileHandler::DcmTempFileHandler(const OFFilename &filename) |
192 | | #ifdef WITH_THREADS |
193 | 0 | : refCount_(1), mutex_(), filename_(filename) |
194 | | #else |
195 | | : refCount_(1), filename_(filename) |
196 | | #endif |
197 | 0 | { |
198 | 0 | } |
199 | | |
200 | | DcmTempFileHandler::~DcmTempFileHandler() |
201 | 0 | { |
202 | 0 | OFStandard::deleteFile(filename_); |
203 | 0 | } |
204 | | |
205 | | DcmTempFileHandler *DcmTempFileHandler::newInstance(const OFFilename &filename) |
206 | 0 | { |
207 | 0 | return new DcmTempFileHandler(filename); |
208 | 0 | } |
209 | | |
210 | | void DcmTempFileHandler::increaseRefCount() |
211 | 0 | { |
212 | 0 | #ifdef WITH_THREADS |
213 | 0 | mutex_.lock(); |
214 | 0 | #endif |
215 | 0 | ++refCount_; |
216 | 0 | #ifdef WITH_THREADS |
217 | 0 | mutex_.unlock(); |
218 | 0 | #endif |
219 | 0 | } |
220 | | |
221 | | void DcmTempFileHandler::decreaseRefCount() |
222 | 0 | { |
223 | 0 | #ifdef WITH_THREADS |
224 | 0 | mutex_.lock(); |
225 | 0 | #endif |
226 | 0 | size_t result = --refCount_; |
227 | 0 | #ifdef WITH_THREADS |
228 | 0 | mutex_.unlock(); |
229 | 0 | #endif |
230 | 0 | if (result == 0) delete this; |
231 | 0 | } |
232 | | |
233 | | /* ======================================================================= */ |
234 | | |
235 | | DcmInputTempFileStreamFactory::DcmInputTempFileStreamFactory(DcmTempFileHandler *handler) |
236 | 0 | : DcmInputStreamFactory() |
237 | 0 | , fileHandler_(handler) |
238 | 0 | { |
239 | 0 | fileHandler_->increaseRefCount(); |
240 | 0 | } |
241 | | |
242 | | DcmInputTempFileStreamFactory::DcmInputTempFileStreamFactory(const DcmInputTempFileStreamFactory &arg) |
243 | 0 | : DcmInputStreamFactory(arg) |
244 | 0 | , fileHandler_(arg.fileHandler_) |
245 | 0 | { |
246 | 0 | fileHandler_->increaseRefCount(); |
247 | 0 | } |
248 | | |
249 | | DcmInputTempFileStreamFactory::~DcmInputTempFileStreamFactory() |
250 | 0 | { |
251 | 0 | fileHandler_->decreaseRefCount(); |
252 | 0 | } |
253 | | |
254 | | DcmInputStream *DcmInputTempFileStreamFactory::create() const |
255 | 0 | { |
256 | 0 | return fileHandler_->create(); |
257 | 0 | } |
258 | | |
259 | | DcmInputStreamFactory *DcmInputTempFileStreamFactory::clone() const |
260 | 0 | { |
261 | 0 | return new DcmInputTempFileStreamFactory(*this); |
262 | 0 | } |