libspatialindex API Reference  (git-trunk)
Tools.cc
Go to the documentation of this file.
1 /******************************************************************************
2  * Project: libspatialindex - A C++ library for spatial indexing
3  * Author: Marios Hadjieleftheriou, mhadji@gmail.com
4  ******************************************************************************
5  * Copyright (c) 2004, Marios Hadjieleftheriou
6  *
7  * All rights reserved.
8  *
9  * Permission is hereby granted, free of charge, to any person obtaining a
10  * copy of this software and associated documentation files (the "Software"),
11  * to deal in the Software without restriction, including without limitation
12  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13  * and/or sell copies of the Software, and to permit persons to whom the
14  * Software is furnished to do so, subject to the following conditions:
15  *
16  * The above copyright notice and this permission notice shall be included
17  * in all copies or substantial portions of the Software.
18  *
19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25  * DEALINGS IN THE SOFTWARE.
26 ******************************************************************************/
27 
28 #include <ctime>
29 #include <limits>
31 
32 #ifndef HAVE_SRAND48
34 #endif
35 
36 #include <cstring>
37 
38 #if (defined _WIN32 || defined _WIN64 || defined WIN32 || defined WIN64)
39 #include <direct.h>
40 #define mkdir _mkdir
41 #endif
42 
43 #if HAVE_PTHREAD_H
44 #if !defined(_POSIX_THREADS)
45 #include <sched.h> // for sched_yield()
46 #endif
47 #endif
48 
50 {
51  std::ostringstream s;
52  s << "Invalid index " << i;
53  m_error = s.str();
54 }
55 
57 {
58  return "IndexOutOfBoundsException: " + m_error;
59 }
60 
62 {
63 }
64 
66 {
67  return "IllegalArgumentException: " + m_error;
68 }
69 
71 {
72 }
73 
75 {
76  return "IllegalStateException: " + m_error;
77 }
78 
80 {
81 }
82 
84 {
85  return "EndOfStreamException: " + m_error;
86 }
87 
89 {
90 }
91 
93 {
94  return "ResourceLockedException: " + m_error;
95 }
96 
98 {
99 }
100 
102 {
103  return "NotSupportedException: " + m_error;
104 }
105 
107 = default;
108 
110 {
111  loadFromByteArray(data);
112 }
113 
115 = default;
116 
118 = default;
120 {
121  m_propertySet.clear();
122 
123  uint32_t numberOfProperties;
124  memcpy(&numberOfProperties, ptr, sizeof(uint32_t));
125  ptr += sizeof(uint32_t);
126 
127  Variant v;
128 
129  for (uint32_t cIndex = 0; cIndex < numberOfProperties; ++cIndex)
130  {
131  std::string s(reinterpret_cast<const char*>(ptr));
132  ptr += s.size() + 1;
133  memcpy(&(v.m_varType), ptr, sizeof(VariantType));
134  ptr += sizeof(VariantType);
135 
136  switch (v.m_varType)
137  {
138  case VT_SHORT:
139  int16_t st;
140  memcpy(&st, ptr, sizeof(int16_t));
141  ptr += sizeof(int16_t);
142  v.m_val.iVal = st;
143  break;
144  case VT_LONG:
145  int32_t l;
146  memcpy(&l, ptr, sizeof(int32_t));
147  ptr += sizeof(int32_t);
148  v.m_val.lVal = l;
149  break;
150  case VT_LONGLONG:
151  int64_t ll;
152  memcpy(&ll, ptr, sizeof(int64_t));
153  ptr += sizeof(int64_t);
154  v.m_val.llVal = ll;
155  break;
156  case VT_BYTE:
157  uint8_t b;
158  memcpy(&b, ptr, sizeof(uint8_t));
159  ptr += sizeof(uint8_t);
160  v.m_val.bVal = b;
161  break;
162  case VT_FLOAT:
163  float f;
164  memcpy(&f, ptr, sizeof(float));
165  ptr += sizeof(float);
166  v.m_val.fltVal = f;
167  break;
168  case VT_DOUBLE:
169  double d;
170  memcpy(&d, ptr, sizeof(double));
171  ptr += sizeof(double);
172  v.m_val.dblVal = d;
173  break;
174  case VT_CHAR:
175  char c;
176  memcpy(&c, ptr, sizeof(char));
177  ptr += sizeof(char);
178  v.m_val.cVal = c;
179  break;
180  case VT_USHORT:
181  uint16_t us;
182  memcpy(&us, ptr, sizeof(uint16_t));
183  ptr += sizeof(uint16_t);
184  v.m_val.uiVal = us;
185  break;
186  case VT_ULONG:
187  uint32_t ul;
188  memcpy(&ul, ptr, sizeof(uint32_t));
189  ptr += sizeof(uint32_t);
190  v.m_val.ulVal = ul;
191  break;
192  case VT_ULONGLONG:
193  uint64_t ull;
194  memcpy(&ull, ptr, sizeof(uint64_t));
195  ptr += sizeof(uint64_t);
196  v.m_val.ullVal = ull;
197  break;
198  case VT_BOOL:
199  uint8_t bl;
200  memcpy(&bl, ptr, sizeof(uint8_t));
201  ptr += sizeof(uint8_t);
202  v.m_val.blVal = (bl != 0);
203  break;
204  default:
205  throw IllegalStateException(
206  "Tools::PropertySet::PropertySet: Deserialization problem."
207  );
208  }
209 
210  m_propertySet.insert(std::pair<std::string, Variant>(s, v));
211  }
212 }
213 
215 {
216  uint32_t size = sizeof(uint32_t);
217 
218  for (auto it = m_propertySet.begin(); it != m_propertySet.end(); ++it)
219  {
220  switch ((*it).second.m_varType)
221  {
222  case VT_SHORT:
223  size += sizeof(int16_t);
224  break;
225  case VT_LONG:
226  size += sizeof(int32_t);
227  break;
228  case VT_LONGLONG:
229  size += sizeof(int64_t);
230  break;
231  case VT_BYTE:
232  size += sizeof(uint8_t);
233  break;
234  case VT_FLOAT:
235  size += sizeof(float);
236  break;
237  case VT_DOUBLE:
238  size += sizeof(double);
239  break;
240  case VT_CHAR:
241  size += sizeof(char);
242  break;
243  case VT_USHORT:
244  size += sizeof(uint16_t);
245  break;
246  case VT_ULONG:
247  size += sizeof(uint32_t);
248  break;
249  case VT_ULONGLONG:
250  size += sizeof(uint64_t);
251  break;
252  case VT_BOOL:
253  size += sizeof(uint8_t);
254  break;
255  default:
256  throw NotSupportedException(
257  "Tools::PropertySet::getSize: Unknown type."
258  );
259  }
260  size += static_cast<uint32_t>((*it).first.size()) + 1 + sizeof(VariantType);
261  }
262 
263  return size;
264 }
265 
266 void Tools::PropertySet::storeToByteArray(uint8_t** data, uint32_t& length)
267 {
268  length = getByteArraySize();
269  *data = new uint8_t[length];
270  uint8_t* ptr = *data;
271 
272  uint32_t numberOfProperties = static_cast<uint32_t>(m_propertySet.size());
273  memcpy(ptr, &numberOfProperties, sizeof(uint32_t));
274  ptr += sizeof(uint32_t);
275 
276 
277  for (auto it = m_propertySet.begin(); it != m_propertySet.end(); ++it)
278  {
279  size_t strSize = (*it).first.size();
280  memcpy(ptr, (*it).first.c_str(), strSize);
281  ptr += strSize;
282  *ptr = 0;
283  ++ptr;
284 
285  memcpy(ptr, &((*it).second.m_varType), sizeof(VariantType));
286  ptr += sizeof(VariantType);
287 
288  switch ((*it).second.m_varType)
289  {
290  case VT_SHORT:
291  memcpy(ptr, &((*it).second.m_val.iVal), sizeof(int16_t));
292  ptr += sizeof(int16_t);
293  break;
294  case VT_LONG:
295  memcpy(ptr, &((*it).second.m_val.lVal), sizeof(int32_t));
296  ptr += sizeof(int32_t);
297  break;
298  case VT_LONGLONG:
299  memcpy(ptr, &((*it).second.m_val.llVal), sizeof(int64_t));
300  ptr += sizeof(int64_t);
301  break;
302  case VT_BYTE:
303  memcpy(ptr, &((*it).second.m_val.bVal), sizeof(uint8_t));
304  ptr += sizeof(uint8_t);
305  break;
306  case VT_FLOAT:
307  memcpy(ptr, &((*it).second.m_val.fltVal), sizeof(float));
308  ptr += sizeof(float);
309  break;
310  case VT_DOUBLE:
311  memcpy(ptr, &((*it).second.m_val.dblVal), sizeof(double));
312  ptr += sizeof(double);
313  break;
314  case VT_CHAR:
315  memcpy(ptr, &((*it).second.m_val.cVal), sizeof(char));
316  ptr += sizeof(char);
317  break;
318  case VT_USHORT:
319  memcpy(ptr, &((*it).second.m_val.uiVal), sizeof(uint16_t));
320  ptr += sizeof(uint16_t);
321  break;
322  case VT_ULONG:
323  memcpy(ptr, &((*it).second.m_val.ulVal), sizeof(uint32_t));
324  ptr += sizeof(uint32_t);
325  break;
326  case VT_ULONGLONG:
327  memcpy(ptr, &((*it).second.m_val.ullVal), sizeof(uint64_t));
328  ptr += sizeof(uint64_t);
329  break;
330  case VT_BOOL:
331  uint8_t bl;
332  bl = (*it).second.m_val.blVal;
333  memcpy(ptr, &bl, sizeof(uint8_t));
334  ptr += sizeof(uint8_t);
335  break;
336  default:
337  throw NotSupportedException(
338  "Tools::PropertySet::getData: Cannot serialize a variant of this type."
339  );
340  }
341  }
342 
343  assert(ptr == (*data) + length);
344 }
345 
347 {
348  const auto& it = m_propertySet.find(property);
349 
350  if (it != m_propertySet.end()) return (*it).second;
351  else return Variant();
352 }
353 
354 void Tools::PropertySet::setProperty(std::string property, Variant const& v)
355 {
356  std::pair<std::map<std::string, Variant>::iterator, bool> ret;
357  std::map<std::string, Variant>::iterator it;
358 
359  ret = m_propertySet.insert(std::pair<std::string, Variant>(property, v));
360 
361  // If we weren't able to insert because it is already in the map
362  // update our existing value
363  if (ret.second == false) ret.first->second = v;
364 }
365 
366 void Tools::PropertySet::removeProperty(std::string property)
367 {
368  auto it = m_propertySet.find(property);
369  if (it != m_propertySet.end()) m_propertySet.erase(it);
370 }
371 
373 = default;
374 
375 Tools::Interval::Interval(IntervalType t, double l, double h) : m_type(t), m_low(l), m_high(h)
376 {
377  assert(l < h);
378 }
379 
381 {
382  assert(l < h);
383 }
384 
386 {
387  m_low = iv.m_low;
388  m_high = iv.m_high;
389  m_type = iv.m_type;
390 }
391 
393 {
394  if (this != &iv)
395  {
396  m_low = iv.getLowerBound();
397  m_high = iv.getUpperBound();
398  m_type = iv.getIntervalType();
399  }
400 
401  return *this;
402 }
403 
405 {
406  if (
407  m_type == iv.m_type &&
408  m_low >= iv.m_low - std::numeric_limits<double>::epsilon() &&
409  m_low <= iv.m_low + std::numeric_limits<double>::epsilon() &&
410  m_high >= iv.m_high - std::numeric_limits<double>::epsilon() &&
411  m_high <= iv.m_high + std::numeric_limits<double>::epsilon())
412  return true;
413 
414  return false;
415 }
416 
418 {
419  return ! (*this == iv);
420 }
421 
423 {
424  return m_low;
425 }
426 
428 {
429  return m_high;
430 }
431 
432 void Tools::Interval::setBounds(double l, double h)
433 {
434  assert(l <= h);
435 
436  m_low = l;
437  m_high = h;
438 }
439 
441 {
443 }
444 
445 bool Tools::Interval::intersectsInterval(IntervalType type, const double low, const double high) const
446 {
447  if (m_high < m_low)
448  throw IllegalStateException(
449  "Tools::Interval::intersectsInterval: high boundary is smaller than low boundary."
450  );
451 
452  if (m_low > high || m_high < low) return false;
453  if ((m_low > low && m_low < high) || (m_high > low && m_high < high)) return true;
454 
455  switch (m_type)
456  {
457  case IT_CLOSED:
458  if (m_low == high)
459  {
460  if (type == IT_CLOSED || type == IT_LEFTOPEN) return true;
461  else return false;
462  }
463  else if (m_high == low)
464  {
465  if (type == IT_CLOSED || type == IT_RIGHTOPEN) return true;
466  else return false;
467  }
468  break;
469  case IT_OPEN:
470  if (m_low == high || m_high == low) return false;
471  break;
472  case IT_RIGHTOPEN:
473  if (m_low == high)
474  {
475  if (type == IT_CLOSED || type == IT_LEFTOPEN) return true;
476  else return false;
477  }
478  else if (m_high == low)
479  {
480  return false;
481  }
482  break;
483  case IT_LEFTOPEN:
484  if (m_low == high)
485  {
486  return false;
487  }
488  else if (m_high == low)
489  {
490  if (type == IT_CLOSED || type == IT_RIGHTOPEN) return true;
491  else return false;
492  }
493  break;
494  }
495 
496  return true;
497 }
498 
500 {
501  if (m_high < m_low)
502  throw IllegalStateException(
503  "Tools::Interval::containsInterval: high boundary is smaller than low boundary."
504  );
505 
506  double low = i.getLowerBound();
507  double high = i.getUpperBound();
508  IntervalType type = i.getIntervalType();
509 
510  if (m_low < low && m_high > high) return true;
511  if (m_low > low || m_high < high) return false;
512 
513  switch (m_type)
514  {
515  case IT_CLOSED:
516  break;
517  case IT_OPEN:
518  if ((m_low == low && m_high == high && type != IT_OPEN) ||
519  (m_low == low && (type == IT_CLOSED || type == IT_RIGHTOPEN)) ||
520  (m_high == high && ( type == IT_CLOSED || type == IT_LEFTOPEN)))
521  return false;
522  break;
523  case IT_RIGHTOPEN:
524  if (m_high == high && (type == IT_CLOSED || type == IT_LEFTOPEN))
525  return false;
526  break;
527  case IT_LEFTOPEN:
528  if (m_low == low && (type == IT_CLOSED || type == IT_RIGHTOPEN))
529  return false;
530  break;
531  }
532 
533  return true;
534 }
535 
537 {
538  return m_type;
539 }
540 
542 {
543  m_pBuffer = nullptr;
544  initDrand(static_cast<uint32_t>(time(nullptr)), 0xD31A);
545 }
546 
547 Tools::Random::Random(uint32_t seed, uint16_t xsubi0)
548 {
549  m_pBuffer = nullptr;
550  initDrand(seed, xsubi0);
551 }
552 
554 {
555  delete[] m_pBuffer;
556 }
557 
558 void Tools::Random::initDrand(uint32_t seed, uint16_t xsubi0)
559 {
560  m_pBuffer = new uint16_t[3];
561  m_pBuffer[0] = static_cast<uint16_t>(xsubi0);
562  uint32_t mask = 0xFFFF;
563  m_pBuffer[1] = static_cast<uint16_t>(seed & mask);
564  mask = mask << 16;
565  m_pBuffer[2] = static_cast<uint16_t>((seed & mask) >> 16);
566 
567 #ifdef BUILD_OS_CYGWIN
568  srand48(*(reinterpret_cast<uint32_t*>(m_pBuffer)));
569  // BUG: There is a bug in cygwin gcc 3.4.4. srand48 needs to be called
570  // even if we are using the functions that take the seed as a parameter.
571  // This does not affect random number generation, which still happens
572  // using the seed provided as a parameter and not the one provided to srand48 :-S
573 #endif
574 }
575 
577 {
578  return jrand48(m_pBuffer);
579 }
580 
582 {
583  return static_cast<uint32_t>(nextUniformLong());
584 }
585 
586 int32_t Tools::Random::nextUniformLong(int32_t low, int32_t high)
587 {
588  return low + static_cast<int32_t>((high - low) * nextUniformDouble());
589 }
590 
591 uint32_t Tools::Random::nextUniformUnsignedLong(uint32_t low, uint32_t high)
592 {
593  return low + static_cast<uint32_t>((high - low) * nextUniformDouble());
594 }
595 
597 {
598  return static_cast<int64_t>(nextUniformUnsignedLongLong());
599 }
600 
602 {
603  uint64_t lh = static_cast<uint64_t>(nextUniformLong());
604  uint64_t ll = static_cast<uint64_t>(nextUniformLong());
605  uint64_t ret = (lh << 32) | ll;
606  return ret;
607 }
608 
609 int64_t Tools::Random::nextUniformLongLong(int64_t low, int64_t high)
610 {
611  return low + static_cast<int64_t>((high - low) * nextUniformDouble());
612 }
613 
614 uint64_t Tools::Random::nextUniformUnsignedLongLong(uint64_t low, uint64_t high)
615 {
616  return low + static_cast<uint64_t>((high - low) * nextUniformDouble());
617 }
618 
620 {
621  return static_cast<int16_t>(nextUniformUnsignedShort());
622 }
623 
625 {
626  return nextUniformUnsignedLong() >> 16;
627  // retain the high order bits.
628 }
629 
631 {
632  uint16_t* xsubi = reinterpret_cast<uint16_t*>(m_pBuffer);
633  return erand48(xsubi);
634 }
635 
636 double Tools::Random::nextUniformDouble(double low, double high)
637 {
638  return (high - low) * nextUniformDouble() + low;
639 }
640 
642 {
643  if (nextUniformDouble() < 0.5) return true;
644  return false;
645 }
646 
647 std::ostream& Tools::operator<<(std::ostream& os, const Tools::PropertySet& p)
648 {
649 
650  for (auto it = p.m_propertySet.begin(); it != p.m_propertySet.end(); ++it)
651  {
652  if (it != p.m_propertySet.begin()) os << ", ";
653 
654  switch ((*it).second.m_varType)
655  {
656  case VT_LONG:
657  os << (*it).first << ": " << (*it).second.m_val.lVal;
658  break;
659  case VT_LONGLONG:
660  os << (*it).first << ": " << (*it).second.m_val.llVal;
661  break;
662  case VT_BYTE:
663  os << (*it).first << ": " << (*it).second.m_val.bVal;
664  break;
665  case VT_SHORT:
666  os << (*it).first << ": " << (*it).second.m_val.iVal;
667  break;
668  case VT_FLOAT:
669  os << (*it).first << ": " << (*it).second.m_val.fltVal;
670  break;
671  case VT_DOUBLE:
672  os << (*it).first << ": " << (*it).second.m_val.dblVal;
673  break;
674  case VT_CHAR:
675  os << (*it).first << ": " << (*it).second.m_val.cVal;
676  break;
677  case VT_USHORT:
678  os << (*it).first << ": " << (*it).second.m_val.uiVal;
679  break;
680  case VT_ULONG:
681  os << (*it).first << ": " << (*it).second.m_val.ulVal;
682  break;
683  case VT_ULONGLONG:
684  os << (*it).first << ": " << (*it).second.m_val.ullVal;
685  break;
686  case VT_BOOL:
687  os << (*it).first << ": " << (*it).second.m_val.blVal;
688  break;
689  case VT_PCHAR:
690  os << (*it).first << ": " << (*it).second.m_val.pcVal;
691  break;
692  case VT_PVOID:
693  os << (*it).first << ": ?";
694  break;
695  case VT_EMPTY:
696  os << (*it).first << ": empty";
697  break;
698  default:
699  os << (*it).first << ": unknown";
700  }
701  }
702 
703  return os;
704 }
705 
706 std::ostream& Tools::operator<<(std::ostream& os, const Tools::Interval& iv)
707 {
708  os << iv.m_type << " " << iv.m_low << " " << iv.m_high;
709  return os;
710 }
711 
712 //
713 // BufferedFile
714 //
715 Tools::BufferedFile::BufferedFile(uint32_t u32BufferSize)
716 : m_buffer(new char[u32BufferSize]), m_u32BufferSize(u32BufferSize)
717 {
718 }
719 
721 {
722  m_file.close();
723  delete[] m_buffer;
724 }
725 
727 {
728  m_file.close();
729 }
730 
732 {
733  return m_bEOF;
734 }
735 
736 //
737 // BufferedFileReader
738 //
740 = default;
741 
742 Tools::BufferedFileReader::BufferedFileReader(const std::string& sFileName, uint32_t u32BufferSize)
743 : BufferedFile(u32BufferSize)
744 {
745  open(sFileName);
746 }
747 
748 void Tools::BufferedFileReader::open(const std::string& sFileName)
749 {
750  m_bEOF = false;
751  m_file.close(); m_file.clear();
752 
753 
754  m_file.open(sFileName.c_str(), std::ios_base::in | std::ios_base::binary);
755  if (! m_file.good())
756  throw std::ios_base::failure("Tools::BufferedFileReader::BufferedFileReader: Cannot open file.");
757 
758  m_file.rdbuf()->pubsetbuf(m_buffer, m_u32BufferSize);
759 }
760 
762 = default;
763 
765 {
766  m_file.clear();
767  m_file.seekg(0, std::ios_base::beg);
768  if (! m_file.good())
769  throw std::ios_base::failure("Tools::BufferedFileReader::rewind: seek failed.");
770 
771  m_bEOF = false;
772 }
773 
774 void Tools::BufferedFileReader::seek(std::fstream::off_type offset)
775 {
776  m_bEOF = false;
777  m_file.clear();
778  m_file.seekg(offset, std::ios_base::beg);
779  if (! m_file.good())
780  throw std::ios_base::failure("Tools::BufferedFileReader::seek: seek failed.");
781 }
782 
784 {
785  if (m_bEOF) throw Tools::EndOfStreamException("");
786 
787  uint8_t ret;
788  m_file.read(reinterpret_cast<char*>(&ret), sizeof(uint8_t));
789  if (! m_file.good())
790  {
791  m_bEOF = true;
792  throw Tools::EndOfStreamException("");
793  }
794  return ret;
795 }
796 
798 {
799  if (m_bEOF) throw Tools::EndOfStreamException("");
800 
801  uint16_t ret;
802  m_file.read(reinterpret_cast<char*>(&ret), sizeof(uint16_t));
803  if (! m_file.good())
804  {
805  m_bEOF = true;
806  throw Tools::EndOfStreamException("");
807  }
808  return ret;
809 }
810 
812 {
813  if (m_bEOF) throw Tools::EndOfStreamException("");
814 
815  uint32_t ret;
816  m_file.read(reinterpret_cast<char*>(&ret), sizeof(uint32_t));
817  if (! m_file.good())
818  {
819  m_bEOF = true;
820  throw Tools::EndOfStreamException("");
821  }
822  return ret;
823 }
824 
826 {
827  if (m_bEOF) throw Tools::EndOfStreamException("");
828 
829  uint64_t ret;
830  m_file.read(reinterpret_cast<char*>(&ret), sizeof(uint64_t));
831  if (! m_file.good())
832  {
833  m_bEOF = true;
834  throw Tools::EndOfStreamException("");
835  }
836  return ret;
837 }
838 
840 {
841  if (m_bEOF) throw Tools::EndOfStreamException("");
842 
843  float ret;
844  m_file.read(reinterpret_cast<char*>(&ret), sizeof(float));
845  if (! m_file.good())
846  {
847  m_bEOF = true;
848  throw Tools::EndOfStreamException("");
849  }
850  return ret;
851 }
852 
854 {
855  if (m_bEOF) throw Tools::EndOfStreamException("");
856 
857  double ret;
858  m_file.read(reinterpret_cast<char*>(&ret), sizeof(double));
859  if (! m_file.good())
860  {
861  m_bEOF = true;
862  throw Tools::EndOfStreamException("");
863  }
864  return ret;
865 }
866 
868 {
869  if (m_bEOF) throw Tools::EndOfStreamException("");
870 
871  bool ret;
872  m_file.read(reinterpret_cast<char*>(&ret), sizeof(bool));
873  if (! m_file.good())
874  {
875  m_bEOF = true;
876  throw Tools::EndOfStreamException("");
877  }
878  return ret;
879 }
880 
882 {
883  if (m_bEOF) throw Tools::EndOfStreamException("");
884 
885  uint32_t len;
886  m_file.read(reinterpret_cast<char*>(&len), sizeof(uint32_t));
887  if (! m_file.good())
888  {
889  m_bEOF = true;
890  throw Tools::EndOfStreamException("");
891  }
892 
893  std::string::value_type* buf = new std::string::value_type[len];
894  m_file.read(reinterpret_cast<char*>(buf), len * sizeof(std::string::value_type));
895  if (! m_file.good())
896  {
897  delete[] buf;
898  m_bEOF = true;
899  throw Tools::EndOfStreamException("");
900  }
901 
902  std::string ret(buf, len);
903  delete[] buf;
904 
905  return ret;
906 }
907 
908 void Tools::BufferedFileReader::readBytes(uint32_t u32Len, uint8_t** pData)
909 {
910  if (m_bEOF) throw Tools::EndOfStreamException("");
911 
912  *pData = new uint8_t[u32Len];
913  m_file.read(reinterpret_cast<char*>(*pData), u32Len);
914  if (! m_file.good())
915  {
916  delete[] *pData;
917  m_bEOF = true;
918  throw Tools::EndOfStreamException("");
919  }
920 }
921 
922 //
923 // BufferedFileWriter
924 //
926 {
927  open("");
928 }
929 
930 Tools::BufferedFileWriter::BufferedFileWriter(const std::string& sFileName, FileMode mode, uint32_t u32BufferSize)
931 : BufferedFile(u32BufferSize)
932 {
933  open(sFileName, mode);
934 }
935 
937 {
938  m_file.flush();
939 }
940 
941 void Tools::BufferedFileWriter::open(const std::string& sFileName, FileMode mode)
942 {
943  m_bEOF = false;
944  m_file.close(); m_file.clear();
945 
946  if (mode == CREATE)
947  {
948  m_file.open(sFileName.c_str(), std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
949  if (! m_file.good())
950  throw std::ios_base::failure("Tools::BufferedFileWriter::open: Cannot open file.");
951  }
952  else if (mode == APPEND)
953  {
954  // Idiotic fstream::open truncates an existing file anyway, if it is only opened
955  // for output (no ios_base::in flag)!! On the other hand, if a file does not exist
956  // and the ios_base::in flag is specified, then the open fails!!
957 
958  m_file.open(sFileName.c_str(), std::ios_base::in | std::ios_base::out | std::ios_base::binary);
959  if (! m_file.good())
960  {
961  m_file.clear();
962  m_file.open(sFileName.c_str(), std::ios_base::out | std::ios_base::binary);
963  if (! m_file.good())
964  throw std::ios_base::failure("Tools::BufferedFileWriter::open: Cannot open file.");
965  }
966  else
967  {
968  m_file.seekp(0, std::ios_base::end);
969  if (! m_file.good())
970  throw std::ios_base::failure("Tools::BufferedFileWriter::open: Cannot open file.");
971  }
972  }
973  else
974  throw Tools::IllegalArgumentException("Tools::BufferedFileWriter::open: Unknown mode.");
975 }
976 
978 {
979  m_bEOF = false;
980  m_file.clear();
981  m_file.seekp(0, std::ios_base::beg);
982  if (! m_file.good())
983  throw std::ios_base::failure("Tools::BufferedFileWriter::rewind: seek failed.");
984 }
985 
986 void Tools::BufferedFileWriter::seek(std::fstream::off_type offset)
987 {
988  m_bEOF = false;
989  m_file.clear();
990  m_file.seekp(offset, std::ios_base::beg);
991  if (! m_file.good())
992  throw std::ios_base::failure("Tools::BufferedFileWriter::seek: seek failed.");
993 }
994 
996 {
997  m_file.write(reinterpret_cast<const char*>(&i), sizeof(uint8_t));
998  if (! m_file.good()) throw std::ios_base::failure("");
999 }
1000 
1002 {
1003  m_file.write(reinterpret_cast<const char*>(&i), sizeof(uint16_t));
1004  if (! m_file.good()) throw std::ios_base::failure("");
1005 }
1006 
1008 {
1009  m_file.write(reinterpret_cast<const char*>(&i), sizeof(uint32_t));
1010  if (! m_file.good()) throw std::ios_base::failure("");
1011 }
1012 
1014 {
1015  m_file.write(reinterpret_cast<const char*>(&i), sizeof(uint64_t));
1016  if (! m_file.good()) throw std::ios_base::failure("");
1017 }
1018 
1020 {
1021  m_file.write(reinterpret_cast<const char*>(&i), sizeof(float));
1022  if (! m_file.good()) throw std::ios_base::failure("");
1023 }
1024 
1026 {
1027  m_file.write(reinterpret_cast<const char*>(&i), sizeof(double));
1028  if (! m_file.good()) throw std::ios_base::failure("");
1029 }
1030 
1032 {
1033  m_file.write(reinterpret_cast<const char*>(&b), sizeof(bool));
1034  if (! m_file.good()) throw std::ios_base::failure("");
1035 }
1036 
1037 void Tools::BufferedFileWriter::write(const std::string& s)
1038 {
1039  uint32_t len = static_cast<uint32_t>(s.size());
1040  m_file.write(reinterpret_cast<const char*>(&len), sizeof(uint32_t));
1041  if (! m_file.good()) throw std::ios_base::failure("");
1042  m_file.write(reinterpret_cast<const char*>(s.c_str()), len * sizeof(std::string::value_type));
1043  if (! m_file.good()) throw std::ios_base::failure("");
1044 }
1045 
1046 void Tools::BufferedFileWriter::write(uint32_t u32Len, uint8_t* pData)
1047 {
1048  m_file.write(reinterpret_cast<const char*>(pData), u32Len);
1049  if (! m_file.good()) throw std::ios_base::failure("");
1050 }
1051 
1052 //
1053 // TemporaryFile
1054 //
1056 {
1057 
1058 #ifdef _MSC_VER
1059 
1060 #ifndef L_tmpnam_s
1061 // MSVC 2003 doesn't have tmpnam_s, so we'll have to use the old functions
1062 
1063  char* tmpName = NULL;
1064  tmpName = tmpnam( NULL );
1065 
1066  if (tmpName == NULL)
1067  throw std::ios_base::failure("Tools::TemporaryFile: Cannot create temporary file name.");
1068 
1069 #else
1070  char tmpName[L_tmpnam_s];
1071  errno_t err = tmpnam_s(tmpName, L_tmpnam_s);
1072  if (err)
1073  throw std::ios_base::failure("Tools::TemporaryFile: Cannot create temporary file name.");
1074 
1075 #endif
1076  if (tmpName[0] == '\\')
1077  m_sFile = std::string(tmpName + 1);
1078  else
1079  m_sFile = std::string(tmpName);
1080 
1081 #else
1082  // see https://github.com/boostorg/filesystem/blob/b4d606cdd08640c9bca68f7e97b52245aeef398d/src/operations.cpp#L2783
1083  const char* val = nullptr;
1084 
1085  (val = std::getenv("TMPDIR" )) ||
1086  (val = std::getenv("TMP" )) ||
1087  (val = std::getenv("TEMP" )) ||
1088  (val = std::getenv("TEMPDIR"));
1089 
1090 # ifdef __ANDROID__
1091  const char* default_tmp = "/data/local/tmp";
1092 # else
1093  const char* default_tmp = "/tmp";
1094 # endif
1095  std::string tempDir ((val != nullptr) ? val : default_tmp);
1096 
1097  // now contruct the temporary filename
1098  std::string tempName = tempDir + "/spatialindex-XXXXXX";
1099  char* tmpName = strdup(tempName.c_str());
1100  if (!tmpName || mkstemp(tmpName) == -1)
1101  throw std::ios_base::failure("Tools::TemporaryFile: Cannot create temporary file name.");
1102  m_sFile = tmpName;
1103  free(tmpName);
1104 #endif
1105 
1106  m_pFile = new Tools::BufferedFileWriter(m_sFile, Tools::CREATE);
1107 }
1108 
1110 {
1111  delete m_pFile;
1112 
1113 #ifdef _MSC_VER
1114  _unlink(m_sFile.c_str());
1115 #else
1116  std::remove(m_sFile.c_str());
1117 #endif
1118 }
1119 
1121 {
1122  Tools::BufferedFileReader* br = dynamic_cast<Tools::BufferedFileReader*>(m_pFile);
1123  if (br != nullptr)
1124  m_pFile->rewind();
1125  else
1126  {
1127  delete m_pFile;
1128  m_pFile = new Tools::BufferedFileReader(m_sFile);
1129  }
1130 }
1131 
1133 {
1134  Tools::BufferedFileWriter* bw = dynamic_cast<Tools::BufferedFileWriter*>(m_pFile);
1135  if (bw != nullptr)
1136  m_pFile->rewind();
1137  else
1138  {
1139  delete m_pFile;
1140  m_pFile = new Tools::BufferedFileWriter(m_sFile);
1141  }
1142 }
1143 
1145 {
1146  return m_pFile->eof();
1147 }
1148 
1150 {
1151  return m_sFile;
1152 }
1153 
1155 {
1156  Tools::BufferedFileReader* br = dynamic_cast<Tools::BufferedFileReader*>(m_pFile);
1157  if (br == nullptr)
1158  throw std::ios_base::failure("Tools::TemporaryFile::readUInt8: file not open for reading.");
1159 
1160  return br->readUInt8();
1161 }
1162 
1164 {
1165  Tools::BufferedFileReader* br = dynamic_cast<Tools::BufferedFileReader*>(m_pFile);
1166  if (br == nullptr)
1167  throw std::ios_base::failure("Tools::TemporaryFile::readUInt16: file not open for reading.");
1168 
1169  return br->readUInt16();
1170 }
1171 
1173 {
1174  Tools::BufferedFileReader* br = dynamic_cast<Tools::BufferedFileReader*>(m_pFile);
1175  if (br == nullptr)
1176  throw std::ios_base::failure("Tools::TemporaryFile::readUInt32: file not open for reading.");
1177 
1178  return br->readUInt32();
1179 }
1180 
1182 {
1183  Tools::BufferedFileReader* br = dynamic_cast<Tools::BufferedFileReader*>(m_pFile);
1184  if (br == nullptr)
1185  throw std::ios_base::failure("Tools::TemporaryFile::readUInt64: file not open for reading.");
1186 
1187  return br->readUInt64();
1188 }
1189 
1191 {
1192  Tools::BufferedFileReader* br = dynamic_cast<Tools::BufferedFileReader*>(m_pFile);
1193  if (br == nullptr)
1194  throw std::ios_base::failure("Tools::TemporaryFile::readFloat: file not open for reading.");
1195 
1196  return br->readFloat();
1197 }
1198 
1200 {
1201  Tools::BufferedFileReader* br = dynamic_cast<Tools::BufferedFileReader*>(m_pFile);
1202  if (br == nullptr)
1203  throw std::ios_base::failure("Tools::TemporaryFile::readDouble: file not open for reading.");
1204 
1205  return br->readDouble();
1206 }
1207 
1209 {
1210  Tools::BufferedFileReader* br = dynamic_cast<Tools::BufferedFileReader*>(m_pFile);
1211  if (br == nullptr)
1212  throw std::ios_base::failure("Tools::TemporaryFile::readString: file not open for reading.");
1213 
1214  return br->readString();
1215 }
1216 
1217 void Tools::TemporaryFile::readBytes(uint32_t u32Len, uint8_t** pData)
1218 {
1219  Tools::BufferedFileReader* br = dynamic_cast<Tools::BufferedFileReader*>(m_pFile);
1220  if (br == nullptr)
1221  throw std::ios_base::failure("Tools::TemporaryFile::readString: file not open for reading.");
1222 
1223  return br->readBytes(u32Len, pData);
1224 }
1225 
1227 {
1228  Tools::BufferedFileWriter* bw = dynamic_cast<Tools::BufferedFileWriter*>(m_pFile);
1229  if (bw == nullptr)
1230  throw std::ios_base::failure("Tools::TemporaryFile::write: file not open for writing.");
1231 
1232  return bw->write(i);
1233 }
1234 
1236 {
1237  Tools::BufferedFileWriter* bw = dynamic_cast<Tools::BufferedFileWriter*>(m_pFile);
1238  if (bw == nullptr)
1239  throw std::ios_base::failure("Tools::TemporaryFile::write: file not open for writing.");
1240 
1241  return bw->write(i);
1242 }
1243 
1245 {
1246  Tools::BufferedFileWriter* bw = dynamic_cast<Tools::BufferedFileWriter*>(m_pFile);
1247  if (bw == nullptr)
1248  throw std::ios_base::failure("Tools::TemporaryFile::write: file not open for writing.");
1249 
1250  return bw->write(i);
1251 }
1252 
1254 {
1255  Tools::BufferedFileWriter* bw = dynamic_cast<Tools::BufferedFileWriter*>(m_pFile);
1256  if (bw == nullptr)
1257  throw std::ios_base::failure("Tools::TemporaryFile::write: file not open for writing.");
1258 
1259  return bw->write(i);
1260 }
1261 
1263 {
1264  Tools::BufferedFileWriter* bw = dynamic_cast<Tools::BufferedFileWriter*>(m_pFile);
1265  if (bw == nullptr)
1266  throw std::ios_base::failure("Tools::TemporaryFile::write: file not open for writing.");
1267 
1268  return bw->write(i);
1269 }
1270 
1272 {
1273  Tools::BufferedFileWriter* bw = dynamic_cast<Tools::BufferedFileWriter*>(m_pFile);
1274  if (bw == nullptr)
1275  throw std::ios_base::failure("Tools::TemporaryFile::write: file not open for writing.");
1276 
1277  return bw->write(i);
1278 }
1279 
1280 void Tools::TemporaryFile::write(const std::string& s)
1281 {
1282  Tools::BufferedFileWriter* bw = dynamic_cast<Tools::BufferedFileWriter*>(m_pFile);
1283  if (bw == nullptr)
1284  throw std::ios_base::failure("Tools::TemporaryFile::write: file not open for writing.");
1285 
1286  return bw->write(s);
1287 }
1288 
1289 void Tools::TemporaryFile::write(uint32_t u32Len, uint8_t* pData)
1290 {
1291  Tools::BufferedFileWriter* bw = dynamic_cast<Tools::BufferedFileWriter*>(m_pFile);
1292  if (bw == nullptr)
1293  throw std::ios_base::failure("Tools::TemporaryFile::write: file not open for writing.");
1294 
1295  return bw->write(u32Len, pData);
1296 }
double getUpperBound() const override
Definition: Tools.cc:427
double getLowerBound() const override
Definition: Tools.cc:422
void removeProperty(std::string property)
Definition: Tools.cc:366
std::string what() override
Definition: Tools.cc:101
VariantType m_varType
Definition: Tools.h:277
uint32_t ulVal
Definition: Tools.h:289
FileMode
Definition: Tools.h:109
bool flipCoin()
Definition: Tools.cc:641
std::string readString()
Definition: Tools.cc:1208
virtual ~Random()
Definition: Tools.cc:553
void setProperty(std::string property, Variant const &v)
Definition: Tools.cc:354
uint64_t ullVal
Definition: Tools.h:290
std::fstream m_file
Definition: Tools.h:418
BufferedFile(uint32_t u32BufferSize=16384)
Definition: Tools.cc:715
virtual void open(const std::string &sFileName, FileMode mode=CREATE)
Definition: Tools.cc:941
void rewind() override
Definition: Tools.cc:977
void rewindForWriting()
Definition: Tools.cc:1132
VariantType
Definition: Tools.h:88
virtual std::string readString()
Definition: Tools.cc:881
IllegalArgumentException(std::string s)
Definition: Tools.cc:61
std::string what() override
Definition: Tools.cc:92
double m_low
Definition: Tools.h:348
std::string getFileName() const
Definition: Tools.cc:1149
uint16_t nextUniformUnsignedShort()
Definition: Tools.cc:624
virtual double getLowerBound() const =0
double nextUniformDouble()
Definition: Tools.cc:630
void loadFromByteArray(const uint8_t *data) override
Definition: Tools.cc:119
double erand48(unsigned short xseed[3]) __THROW
Definition: rand48.cc:136
double readDouble()
Definition: Tools.cc:1199
virtual uint16_t readUInt16()
Definition: Tools.cc:797
virtual void close()
Definition: Tools.cc:726
virtual bool eof()
Definition: Tools.cc:731
uint8_t bVal
Definition: Tools.h:284
uint32_t nextUniformUnsignedLong()
Definition: Tools.cc:581
IntervalType getIntervalType() const override
Definition: Tools.cc:536
char * m_buffer
Definition: Tools.h:419
std::string what() override
Definition: Tools.cc:83
uint64_t nextUniformUnsignedLongLong()
Definition: Tools.cc:601
int32_t nextUniformLong()
Definition: Tools.cc:576
NotSupportedException(std::string s)
Definition: Tools.cc:97
uint16_t uiVal
Definition: Tools.h:288
~PropertySet() override
std::string what() override
Definition: Tools.cc:74
virtual ~TemporaryFile()
Definition: Tools.cc:1109
union Tools::Variant::@0 m_val
virtual uint32_t readUInt32()
Definition: Tools.cc:811
virtual bool operator!=(const Interval &) const
Definition: Tools.cc:417
void rewind() override
Definition: Tools.cc:764
long jrand48(unsigned short xseed[3]) __THROW
Definition: rand48.cc:129
void rewindForReading()
Definition: Tools.cc:1120
int64_t llVal
Definition: Tools.h:283
void srand48(long int seed) __THROW
double m_high
Definition: Tools.h:349
~BufferedFileWriter() override
Definition: Tools.cc:936
std::string what() override
Definition: Tools.cc:65
ResourceLockedException(std::string s)
Definition: Tools.cc:88
void readBytes(uint32_t u32Len, uint8_t **pData)
Definition: Tools.cc:1217
bool containsInterval(const IInterval &) const override
Definition: Tools.cc:499
uint32_t getByteArraySize() override
Definition: Tools.cc:214
uint8_t readUInt8()
Definition: Tools.cc:1154
float fltVal
Definition: Tools.h:285
virtual IntervalType getIntervalType() const =0
EndOfStreamException(std::string s)
Definition: Tools.cc:79
virtual void open(const std::string &sFileName)
Definition: Tools.cc:748
IndexOutOfBoundsException(size_t i)
Definition: Tools.cc:49
void seek(std::fstream::off_type offset) override
Definition: Tools.cc:986
char cVal
Definition: Tools.h:287
virtual float readFloat()
Definition: Tools.cc:839
virtual void readBytes(uint32_t u32Len, uint8_t **pData)
Definition: Tools.cc:908
IllegalStateException(std::string s)
Definition: Tools.cc:70
SIDX_DLL std::ostream & operator<<(std::ostream &os, const Tools::PropertySet &p)
Definition: Tools.cc:647
uint64_t readUInt64()
Definition: Tools.cc:1181
virtual uint8_t readUInt8()
Definition: Tools.cc:783
IntervalType m_type
Definition: Tools.h:347
uint16_t readUInt16()
Definition: Tools.cc:1163
uint32_t readUInt32()
Definition: Tools.cc:1172
int32_t lVal
Definition: Tools.h:282
virtual bool operator==(const Interval &) const
Definition: Tools.cc:404
int64_t nextUniformLongLong()
Definition: Tools.cc:596
double dblVal
Definition: Tools.h:286
virtual IInterval & operator=(const IInterval &)
Definition: Tools.cc:392
uint32_t m_u32BufferSize
Definition: Tools.h:420
virtual uint64_t readUInt64()
Definition: Tools.cc:825
virtual double readDouble()
Definition: Tools.cc:853
int16_t iVal
Definition: Tools.h:281
virtual bool readBoolean()
Definition: Tools.cc:867
Variant getProperty(std::string property) const
Definition: Tools.cc:346
virtual void write(uint8_t i)
Definition: Tools.cc:995
bool intersectsInterval(const IInterval &) const override
Definition: Tools.cc:440
bool blVal
Definition: Tools.h:291
void setBounds(double, double) override
Definition: Tools.cc:432
virtual ~BufferedFile()
Definition: Tools.cc:720
IntervalType
Definition: Tools.h:80
std::string what() override
Definition: Tools.cc:56
void storeToByteArray(uint8_t **data, uint32_t &length) override
Definition: Tools.cc:266
void write(uint8_t i)
Definition: Tools.cc:1226
int16_t nextUniformShort()
Definition: Tools.cc:619
virtual double getUpperBound() const =0
void seek(std::fstream::off_type offset) override
Definition: Tools.cc:774