Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
usModuleResourceBuffer.cpp
Go to the documentation of this file.
1 /*=============================================================================
2 
3  Library: CppMicroServices
4 
5  Copyright (c) German Cancer Research Center,
6  Division of Medical and Biological Informatics
7 
8  Licensed under the Apache License, Version 2.0 (the "License");
9  you may not use this file except in compliance with the License.
10  You may obtain a copy of the License at
11 
12  http://www.apache.org/licenses/LICENSE-2.0
13 
14  Unless required by applicable law or agreed to in writing, software
15  distributed under the License is distributed on an "AS IS" BASIS,
16  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  See the License for the specific language governing permissions and
18  limitations under the License.
19 
20 =============================================================================*/
21 
22 #include "usModuleResourceBuffer_p.h"
23 
24 #include "us_stdint.h"
25 
26 #include <limits>
27 #include <cassert>
28 #include <stdlib.h>
29 
30 #ifdef US_PLATFORM_WINDOWS
31 #define DATA_NEEDS_NEWLINE_CONVERSION 1
32 #undef REMOVE_LAST_NEWLINE_IN_TEXT_MODE
33 #else
34 #undef DATA_NEEDS_NEWLINE_CONVERSION
35 #define REMOVE_LAST_NEWLINE_IN_TEXT_MODE 1
36 #endif
37 
38 US_BEGIN_NAMESPACE
39 
40 class ModuleResourceBufferPrivate
41 {
42 public:
43 
44  ModuleResourceBufferPrivate(void* data, std::size_t size, const char* begin, std::ios_base::openmode mode)
45  : begin(begin)
46  , end(begin + size)
47  , current(begin)
48  , mode(mode)
49  , uncompressedData(reinterpret_cast<unsigned char*>(data))
50  #ifdef DATA_NEEDS_NEWLINE_CONVERSION
51  , pos(0)
52  #endif
53  {
54  }
55 
56  ~ModuleResourceBufferPrivate()
57  {
58  free(uncompressedData);
59  }
60 
61  const char* const begin;
62  const char* const end;
63  const char* current;
64 
65  const std::ios_base::openmode mode;
66 
67  unsigned char* uncompressedData;
68 
69 #ifdef DATA_NEEDS_NEWLINE_CONVERSION
70  // records the stream position ignoring CR characters
71  std::streambuf::pos_type pos;
72 #endif
73 
74 };
75 
76 ModuleResourceBuffer::ModuleResourceBuffer(void* data, std::size_t _size,
77  std::ios_base::openmode mode)
78  : d(NULL)
79 {
80  assert(_size < static_cast<std::size_t>(std::numeric_limits<uint32_t>::max()));
81  // assert(data != NULL);
82 
83  char* begin = reinterpret_cast<char*>(data);
84  std::size_t size = _size;
85 
86 #ifdef DATA_NEEDS_NEWLINE_CONVERSION
87  if (data != NULL && !(mode & std::ios_base::binary) && begin[0] == '\r')
88  {
89  ++begin;
90  --size;
91  }
92 #endif
93 
94 #ifdef REMOVE_LAST_NEWLINE_IN_TEXT_MODE
95  if (data != NULL && !(mode & std::ios_base::binary) && begin[size-1] == '\n')
96  {
97  --size;
98  }
99 #endif
100 
101  d = new ModuleResourceBufferPrivate(data, size, begin, mode);
102 }
103 
104 ModuleResourceBuffer::~ModuleResourceBuffer()
105 {
106  delete d;
107 }
108 
109 ModuleResourceBuffer::int_type ModuleResourceBuffer::underflow()
110 {
111  if (d->current == d->end)
112  return traits_type::eof();
113 
114 #ifdef DATA_NEEDS_NEWLINE_CONVERSION
115  char c = *d->current;
116  if (!(d->mode & std::ios_base::binary))
117  {
118  if (c == '\r')
119  {
120  if (d->current + 1 == d->end)
121  {
122  return traits_type::eof();
123  }
124  c = d->current[1];
125  }
126  }
127  return traits_type::to_int_type(c);
128 #else
129  return traits_type::to_int_type(*d->current);
130 #endif
131 }
132 
133 ModuleResourceBuffer::int_type ModuleResourceBuffer::uflow()
134 {
135  if (d->current == d->end)
136  return traits_type::eof();
137 
138 #ifdef DATA_NEEDS_NEWLINE_CONVERSION
139  char c = *d->current++;
140  if (!(d->mode & std::ios_base::binary))
141  {
142  if (c == '\r')
143  {
144  if (d->current == d->end)
145  {
146  return traits_type::eof();
147  }
148  c = *d->current++;
149  }
150  }
151  return traits_type::to_int_type(c);
152 #else
153  return traits_type::to_int_type(*d->current++);
154 #endif
155 }
156 
157 ModuleResourceBuffer::int_type ModuleResourceBuffer::pbackfail(int_type ch)
158 {
159  int backOffset = -1;
160 #ifdef DATA_NEEDS_NEWLINE_CONVERSION
161  if (!(d->mode & std::ios_base::binary))
162  {
163  while ((d->current - backOffset) >= d->begin && d->current[backOffset] == '\r')
164  {
165  --backOffset;
166  }
167  // d->begin always points to a character != '\r'
168  }
169 #endif
170  if (d->current == d->begin || (ch != traits_type::eof() && ch != d->current[backOffset]))
171  {
172  return traits_type::eof();
173  }
174 
175  d->current += backOffset;
176  return traits_type::to_int_type(*d->current);
177 }
178 
179 std::streamsize ModuleResourceBuffer::showmanyc()
180 {
181  assert(d->current <= d->end);
182 
183 #ifdef DATA_NEEDS_NEWLINE_CONVERSION
184  std::streamsize ssize = 0;
185  std::size_t chunkSize = d->end - d->current;
186  for (std::size_t i = 0; i < chunkSize; ++i)
187  {
188  if (d->current[i] != '\r')
189  {
190  ++ssize;
191  }
192  }
193  return ssize;
194 #else
195  return d->end - d->current;
196 #endif
197 }
198 
199 std::streambuf::pos_type ModuleResourceBuffer::seekoff(std::streambuf::off_type off,
200  std::ios_base::seekdir way,
201  std::ios_base::openmode /*which*/)
202 {
203 #ifdef DATA_NEEDS_NEWLINE_CONVERSION
204  std::streambuf::off_type step = 1;
205  if (way == std::ios_base::beg)
206  {
207  d->current = d->begin;
208  }
209  else if (way == std::ios_base::end)
210  {
211  d->current = d->end;
212  step = -1;
213  }
214 
215  if (!(d->mode & std::ios_base::binary))
216  {
217  if (way == std::ios_base::beg)
218  {
219  d->pos = 0;
220  }
221  else if (way == std::ios_base::end)
222  {
223  d->current -= 1;
224  }
225 
226  std::streambuf::off_type i = 0;
227  // scan through off amount of characters excluding '\r'
228  while (i != off)
229  {
230  if (*d->current != '\r')
231  {
232  i += step;
233  d->pos += step;
234  }
235  d->current += step;
236  }
237 
238  // adjust the position in case of a "backwards" seek
239  if (way == std::ios_base::end)
240  {
241  // fix pointer from previous while loop
242  d->current += 1;
243  d->pos = 0;
244  i = 0;
245  const std::streampos currInternalPos = d->current - d->begin;
246  while (i != currInternalPos)
247  {
248  if (d->begin[i] != '\r')
249  {
250  d->pos += 1;
251  }
252  ++i;
253  }
254  }
255  }
256  else
257  {
258  d->current += off;
259  d->pos = d->current - d->begin;
260  }
261  return d->pos;
262 #else
263  if (way == std::ios_base::beg)
264  {
265  d->current = d->begin + off;
266  return off;
267  }
268  else if (way == std::ios_base::cur)
269  {
270  d->current += off;
271  return d->current - d->begin;
272  }
273  else
274  {
275  d->current = d->end + off;
276  return d->current - d->begin;
277  }
278 #endif
279 }
280 
281 std::streambuf::pos_type ModuleResourceBuffer::seekpos(std::streambuf::pos_type sp,
282  std::ios_base::openmode /*which*/)
283 {
284  return this->seekoff(sp, std::ios_base::beg);
285 }
286 
287 US_END_NAMESPACE
static T max(T x, T y)
Definition: svm.cpp:70