Coverage Report

Created: 2026-06-30 07:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}