xmscore  1.0
daStreamIo.cpp
Go to the documentation of this file.
1 //------------------------------------------------------------------------------
6 //------------------------------------------------------------------------------
7 
8 //----- Included files ---------------------------------------------------------
9 
10 // 1. Precompiled header
11 
12 // 2. My header
14 
15 // 3. Standard Library Headers
16 #include <fstream>
17 #include <sstream>
18 
19 // 4. External Library Headers
20 #include <boost/archive/iterators/base64_from_binary.hpp>
21 #include <boost/archive/iterators/binary_from_base64.hpp>
22 #include <boost/archive/iterators/transform_width.hpp>
23 #include <boost/unordered_map.hpp>
24 #include <zlib.h>
25 
26 // 5. Shared Headers
28 #include <xmscore/misc/XmError.h>
29 #include <xmscore/misc/XmLog.h>
30 
31 //----- Forward declarations ---------------------------------------------------
32 
33 //----- External globals -------------------------------------------------------
34 
35 //----- Namespace declaration --------------------------------------------------
36 
37 namespace xms
38 {
39 //----- Constants / Enumerations -----------------------------------------------
40 
41 //----- Classes / Structs ------------------------------------------------------
42 
43 //----- Class / Function definitions -------------------------------------------
44 
45 namespace
46 {
47 const int MAX_BLOCK_SIZE = 1024 * 32;
48 }
49 
54 {
55 public:
59  Impl(std::istream& a_inStream, bool a_binaryArrays)
60  : m_inStream(a_inStream)
61  , m_binaryArrays(a_binaryArrays)
62  {
63  }
64 
65  std::istream& m_inStream;
67 };
68 
73 {
74 public:
78  Impl(std::ostream& a_outStream, bool a_binaryArrays)
79  : m_outStream(a_outStream)
80  , m_binaryArrays(a_binaryArrays)
81  {
82  }
83 
84  std::ostream& m_outStream;
86  int m_blockSize = MAX_BLOCK_SIZE;
87 };
88 
89 namespace
90 {
91 //------------------------------------------------------------------------------
98 //------------------------------------------------------------------------------
99 int32_t iCompress(const char* a_source, int32_t a_sourceLength, char* a_dest, int32_t a_destLength)
100 {
101  auto compressedLength = static_cast<uLong>(a_destLength);
102  auto result = compress2(reinterpret_cast<Bytef*>(a_dest), &compressedLength,
103  reinterpret_cast<const Bytef*>(a_source),
104  static_cast<uLong>(a_sourceLength), Z_BEST_SPEED);
105  if (result != Z_OK)
106  {
107  XM_LOG(xmlog::error, "Unable to write file. Compression failed.")
108  return -1;
109  }
110 
111  return static_cast<int32_t>(compressedLength);
112 } // iCompress
113 //------------------------------------------------------------------------------
115 //------------------------------------------------------------------------------
116 bool iUncompress(const char* a_source, int32_t a_sourceLength, char* a_dest, int32_t a_destLength)
117 {
118  auto uncompressedLength = static_cast<uLong>(a_destLength);
119  bool success = uncompress(reinterpret_cast<Bytef*>(a_dest), &uncompressedLength,
120  reinterpret_cast<const Bytef*>(a_source),
121  static_cast<uLong>(a_sourceLength)) == Z_OK;
122  success = success && static_cast<int32_t>(uncompressedLength) == a_destLength;
123  if (!success)
124  {
125  XM_LOG(xmlog::error, "Unable to read file. Unable to uncompress data.")
126  return false;
127  }
128 
129  return true;
130 } // iCompress
131 //------------------------------------------------------------------------------
133 //------------------------------------------------------------------------------
134 int32_t iBase64EncodeSize(int32_t a_sourceLength)
135 {
136  unsigned long length = ((4U * static_cast<unsigned long>(a_sourceLength) / 3U) + 3U) & ~3U;
137  return static_cast<int32_t>(length);
138 } // iBase64EncodeSize
139 //------------------------------------------------------------------------------
141 //------------------------------------------------------------------------------
142 int32_t iBase64Encode(const char* a_source, int32_t a_sourceLength, char* a_dest)
143 {
144  using namespace boost::archive::iterators;
145  typedef base64_from_binary<transform_width<const char*, 6, 8>> base64_text;
146 
147  const char* srcBegin = a_source;
148  const char* srcEnd = srcBegin + a_sourceLength;
149  char* destBegin = a_dest;
150  char* destIterator = a_dest;
151  for (auto it = base64_text(srcBegin); it != base64_text(srcEnd); ++it)
152  *destIterator++ = *it;
153  *destIterator = 0;
154 
155  auto encodedLength = int32_t(destIterator - destBegin);
156  return encodedLength;
157 } // iBase64Encode
158 //------------------------------------------------------------------------------
160 //------------------------------------------------------------------------------
161 int32_t iBase64Decode(const char* a_source, int32_t a_sourceLength, char* a_dest)
162 {
163  using namespace boost::archive::iterators;
164  typedef transform_width<binary_from_base64<const char*>, 8, 6> base64_dec;
165 
166  int32_t size = a_sourceLength;
167  if (size && a_source[size - 1] == '=')
168  {
169  --size;
170  if (size && a_source[size - 1] == '=')
171  --size;
172  }
173 
174  if (size != 0)
175  {
176  char* destBegin = a_dest;
177  char* destIterator = a_dest;
178  auto base64Begin = base64_dec(a_source);
179  auto base64End = base64_dec(a_source + size);
180  for (auto it = base64Begin; it != base64End; ++it)
181  *destIterator++ = *it;
182 
183  auto decodedLength = int32_t(destIterator - destBegin);
184  return decodedLength;
185  }
186 
187  return 0;
188 } // iBase64Decode
189 //------------------------------------------------------------------------------
195 //------------------------------------------------------------------------------
196 bool iReadLineToSStream(std::istream& a_inStream, const char* a_name, std::stringstream& a_ss)
197 {
198  std::string line;
199  if (!daReadLine(a_inStream, line))
200  return false;
201 
202  auto position = line.find(a_name);
203  if (position == std::string::npos)
204  return false;
205  else
206  {
207  for (size_t i = 0; i < position; ++i)
208  {
209  if (!isspace(line[i]))
210  return false;
211  }
212  }
213 
214  a_ss.clear();
215  std::replace(line.begin(), line.end(), ',', ' ');
216  a_ss.str(line.substr(position));
217  return !a_ss.fail();
218 } // iReadLineToSStream
219 //------------------------------------------------------------------------------
224 //------------------------------------------------------------------------------
225 template <typename _T>
226 bool iReadLineValue(std::istream& a_inStream, _T& a_val)
227 {
228  std::string line;
229  if (!daReadLine(a_inStream, line))
230  return false;
231  std::stringstream ss;
232  ss.str(line);
233  ss >> a_val;
234  return !ss.fail();
235 } // iReadLineValue
236 //------------------------------------------------------------------------------
242 //------------------------------------------------------------------------------
243 template <typename _T>
244 bool iReadVector(std::istream& a_inStream, const char* a_name, std::vector<_T>& a_vec)
245 {
246  a_vec.clear();
247  int size;
248  if (!daReadIntLine(a_inStream, a_name, size))
249  return false;
250  for (int ii = 0; ii < size; ++ii)
251  {
252  _T val;
253  if (!iReadLineValue(a_inStream, val))
254  return false;
255  a_vec.push_back(val);
256  }
257  return true;
258 } // iReadVector
259 //------------------------------------------------------------------------------
265 //------------------------------------------------------------------------------
266 template <typename _T>
267 bool iReadValue(std::istream& a_inStream, const char* a_name, _T& a_d1)
268 {
269  std::stringstream ss;
270  if (!iReadLineToSStream(a_inStream, a_name, ss))
271  return false;
272  std::string name;
273  ss >> name;
274  ss >> a_d1;
275  return !ss.fail();
276 } // iReadValue
277 //------------------------------------------------------------------------------
285 //------------------------------------------------------------------------------
286 template <typename _T>
287 bool iRead3Values(std::istream& a_inStream, const char* a_name, _T& d1, _T& d2, _T& d3)
288 {
289  std::stringstream ss;
290  if (!iReadLineToSStream(a_inStream, a_name, ss))
291  return false;
292  std::string name;
293  ss >> name;
294  ss >> d1;
295  ss >> d2;
296  ss >> d3;
297  return !ss.fail();
298 } // iRead3Values
299 //------------------------------------------------------------------------------
306 //------------------------------------------------------------------------------
307 template <typename _T>
308 bool iRead2Values(std::istream& a_inStream, const char* a_name, _T& d1, _T& d2)
309 {
310  std::stringstream ss;
311  if (!iReadLineToSStream(a_inStream, a_name, ss))
312  return false;
313  std::string name;
314  ss >> name;
315  ss >> d1;
316  ss >> d2;
317  return !ss.fail();
318 } // iRead2Values
319 //------------------------------------------------------------------------------
324 //------------------------------------------------------------------------------
325 template <typename _T>
326 bool iReadValueFromLine(std::string& a_line, _T& a_val)
327 {
328  std::string line = a_line;
329  std::string stringValue;
330  if (!daReadStringFromLine(line, stringValue))
331  return false;
332 
333  std::istringstream inStream(stringValue);
334  _T tempVal;
335  inStream >> tempVal;
336  if (inStream.fail() || !inStream.eof())
337  return false;
338  a_val = tempVal;
339  a_line = line;
340  return true;
341 } // iReadValueFromLine
342 
343 } // namespace
344 
351 //------------------------------------------------------------------------------
355 //------------------------------------------------------------------------------
356 DaStreamReader::DaStreamReader(std::istream& a_inStream, bool a_binaryArrays /*= false*/)
357 : m_impl(new Impl(a_inStream, a_binaryArrays))
358 {
359 } // DaStreamReader::DaStreamReader
360 //------------------------------------------------------------------------------
362 //------------------------------------------------------------------------------
364 {
365 } // DaStreamReader::~DaStreamReader
366 //------------------------------------------------------------------------------
369 //------------------------------------------------------------------------------
371 {
372  return m_impl->m_binaryArrays;
373 } // DaStreamReader::IsBinary
374 //------------------------------------------------------------------------------
378 //------------------------------------------------------------------------------
379 bool DaStreamReader::ReadNamedLine(const char* a_name)
380 {
381  std::stringstream ss;
382  return iReadLineToSStream(m_impl->m_inStream, a_name, ss);
383 } // DaStreamReader::ReadNamedLine
384 //------------------------------------------------------------------------------
389 //------------------------------------------------------------------------------
390 bool DaStreamReader::ReadLine(std::string& a_line)
391 {
392  a_line.clear();
393 
394  // The characters in the stream are read one-by-one using a std::streambuf.
395  // That is faster than reading them one-by-one using the std::istream.
396  // Code that uses streambuf this way must be guarded by a sentry object.
397  // The sentry object performs various tasks,
398  // such as thread synchronization and updating the stream state.
399 
400  std::istream::sentry se(m_impl->m_inStream, true);
401  std::streambuf* sb = m_impl->m_inStream.rdbuf();
402 
403  for (;;)
404  {
405  int c = sb->sbumpc();
406  if (c == '\n')
407  {
408  return !!m_impl->m_inStream;
409  }
410 
411  if (c == '\r')
412  {
413  if (sb->sgetc() == '\n')
414  sb->sbumpc();
415  return !!m_impl->m_inStream;
416  }
417 
418  if (c == std::streambuf::traits_type::eof())
419  {
420  // Also handle the case when the last line has no line ending
421  if (a_line.empty())
422  m_impl->m_inStream.setstate(std::ios::eofbit);
423  return !!m_impl->m_inStream;
424  }
425 
426  a_line += static_cast<char>(c);
427  }
428 } // DaStreamReader::ReadLine
429 //------------------------------------------------------------------------------
434 //------------------------------------------------------------------------------
435 bool DaStreamReader::ReadIntLine(const char* a_name, int& a_val)
436 {
437  return iReadValue(m_impl->m_inStream, a_name, a_val);
438 } // DaStreamReader::ReadIntLine
439 //------------------------------------------------------------------------------
444 //------------------------------------------------------------------------------
445 bool DaStreamReader::ReadDoubleLine(const char* a_name, double& a_val)
446 {
447  return iReadValue(m_impl->m_inStream, a_name, a_val);
448 } // DaStreamReader::ReadDoubleLine
449 //------------------------------------------------------------------------------
454 //------------------------------------------------------------------------------
455 bool DaStreamReader::ReadStringLine(const char* a_name, std::string& a_val)
456 {
457  return iReadValue(m_impl->m_inStream, a_name, a_val);
458 } // DaStreamReader::ReadStringLine
459 //------------------------------------------------------------------------------
464 //------------------------------------------------------------------------------
465 bool DaStreamReader::ReadVecInt(const char* a_name, VecInt& a_vec)
466 {
467  if (IsBinary())
468  {
469  int size;
470  if (!ReadIntLine(a_name, size))
471  return false;
472 
473  a_vec.resize(size);
474  if (size != 0)
475  ReadBinaryBytes(reinterpret_cast<char*>(&a_vec[0]), size * sizeof(VecInt::value_type));
476  return true;
477  }
478 
479  return iReadVector(m_impl->m_inStream, a_name, a_vec);
480 } // DaStreamReader::ReadVecInt
481 //------------------------------------------------------------------------------
486 //------------------------------------------------------------------------------
487 bool DaStreamReader::ReadVecDbl(const char* a_name, VecDbl& a_vec)
488 {
489  if (IsBinary())
490  {
491  int size;
492  if (!ReadIntLine(a_name, size))
493  return false;
494 
495  a_vec.resize(size);
496  if (size != 0)
497  ReadBinaryBytes(reinterpret_cast<char*>(&a_vec[0]), size * sizeof(VecDbl::value_type));
498  return true;
499  }
500 
501  return iReadVector(m_impl->m_inStream, a_name, a_vec);
502 } // DaStreamReader::ReadVecDbl
503 //------------------------------------------------------------------------------
508 //------------------------------------------------------------------------------
509 bool DaStreamReader::ReadVecPt3d(const char* a_name, VecPt3d& a_vec)
510 {
511  int size;
512  if (!daReadIntLine(m_impl->m_inStream, a_name, size))
513  return false;
514 
515  if (IsBinary())
516  {
517  a_vec.resize(size);
518  if (size != 0)
519  ReadBinaryBytes(reinterpret_cast<char*>(&a_vec[0]), size * sizeof(VecPt3d::value_type));
520  }
521  else
522  {
523  a_vec.resize(0);
524  a_vec.reserve(size);
525  std::string pointLine;
526  std::string pointValue;
527  for (int i = 0; i < size; ++i)
528  {
529  if (!daReadLine(m_impl->m_inStream, pointLine))
530  return false;
531 
532  bool success = daReadStringFromLine(pointLine, pointValue);
533  success = success && pointValue == "POINT";
534  int readPointIdx = -1;
535  success = success && daReadIntFromLine(pointLine, readPointIdx);
536  success = success && readPointIdx == static_cast<int>(i);
537  Pt3d pt;
538  success = success && daReadDoubleFromLine(pointLine, pt.x);
539  success = success && daReadDoubleFromLine(pointLine, pt.y);
540  success = success && daReadDoubleFromLine(pointLine, pt.z);
541  if (!success)
542  return false;
543  a_vec.push_back(pt);
544  }
545  }
546 
547  return true;
548 } // DaStreamReader::ReadVecPt3d
549 //------------------------------------------------------------------------------
555 //------------------------------------------------------------------------------
556 bool DaStreamReader::Read2StringLine(const char* a_name, std::string& a_val1, std::string& a_val2)
557 {
558  return iRead2Values(m_impl->m_inStream, a_name, a_val1, a_val2);
559 } // DaStreamReader::Read2StringLine
560 //------------------------------------------------------------------------------
567 //------------------------------------------------------------------------------
568 bool DaStreamReader::Read3StringLine(const char* a_name,
569  std::string& a_val1,
570  std::string& a_val2,
571  std::string& a_val3)
572 {
573  return iRead3Values(m_impl->m_inStream, a_name, a_val1, a_val2, a_val3);
574 } // DaStreamReader::Read3StringLine
575 //------------------------------------------------------------------------------
582 //------------------------------------------------------------------------------
583 bool DaStreamReader::Read3DoubleLine(const char* a_name,
584  double& a_val1,
585  double& a_val2,
586  double& a_val3)
587 {
588  return iRead3Values(m_impl->m_inStream, a_name, a_val1, a_val2, a_val3);
589 } // DaStreamReader::Read3DoubleLine
590 //------------------------------------------------------------------------------
595 //------------------------------------------------------------------------------
596 bool DaStreamReader::ReadIntFromLine(std::string& a_line, int& a_val)
597 {
598  return iReadValueFromLine(a_line, a_val);
599 } // DaStreamReader::ReadIntFromLine
600 //------------------------------------------------------------------------------
605 //------------------------------------------------------------------------------
606 bool DaStreamReader::ReadStringFromLine(std::string& a_line, std::string& a_val)
607 {
608  std::istringstream inStream(a_line);
609  inStream >> a_val;
610  if (inStream.fail())
611  return false;
612  size_t position = inStream.tellg();
613  if (position != std::string::npos)
614  a_line = inStream.str().substr(position);
615  else
616  a_line = "";
617  return true;
618 } // DaStreamReader::ReadStringFromLine
619 //------------------------------------------------------------------------------
624 //------------------------------------------------------------------------------
625 bool DaStreamReader::ReadDoubleFromLine(std::string& a_line, double& a_val)
626 {
627  return iReadValueFromLine(a_line, a_val);
628 } // DaStreamReader::ReadDoubleFromLine
629 //------------------------------------------------------------------------------
633 //------------------------------------------------------------------------------
634 bool DaStreamReader::ReadString(std::string& a_val)
635 {
636  m_impl->m_inStream >> a_val;
637  return !m_impl->m_inStream.fail();
638 } // DaStreamReader::ReadString
639 //------------------------------------------------------------------------------
643 //------------------------------------------------------------------------------
644 bool DaStreamReader::ReadInt(int& a_val)
645 {
646  m_impl->m_inStream >> a_val;
647  return !m_impl->m_inStream.fail();
648 } // DaStreamReader::ReadInt
649 //------------------------------------------------------------------------------
652 //------------------------------------------------------------------------------
654 {
655  std::string line;
656  ReadLine(line);
657  return !m_impl->m_inStream.fail();
658 } // DaStreamReader::NextLine
659 //------------------------------------------------------------------------------
664 //------------------------------------------------------------------------------
665 bool DaStreamReader::ReadBinaryBytes(char* a_dest, long long a_destLength)
666 {
667  auto maxCompressedLength = static_cast<int32_t>(compressBound(MAX_BLOCK_SIZE));
668  int32_t maxEncodeLength = iBase64EncodeSize(maxCompressedLength);
669  std::unique_ptr<char[]> compressed(new char[maxCompressedLength]);
670  std::unique_ptr<char[]> encoded(new char[maxEncodeLength + 1]);
671 
672  while (a_destLength > 0)
673  {
674  // read block info
675  std::string blockString;
676  int32_t encodedLength;
677  int32_t blockLength;
678  ReadString(blockString);
679  ReadInt(encodedLength);
680  ReadInt(blockLength);
681  NextLine();
682 
683  // read and decode
684  m_impl->m_inStream.read(encoded.get(), encodedLength);
685  NextLine();
686 
687  auto compressedLength = iBase64Decode(encoded.get(), encodedLength, compressed.get());
688 
689  // decompress data
690  if (!iUncompress(compressed.get(), compressedLength, a_dest, blockLength))
691  return false;
692 
693  a_dest += blockLength;
694  a_destLength -= blockLength;
695  }
696 
697  return true;
698 } // DaStreamReader::ReadBinaryBytes
699 //------------------------------------------------------------------------------
703 //------------------------------------------------------------------------------
704 bool DaStreamReader::LineBeginsWith(const char* a_text)
705 {
706  return daLineBeginsWith(m_impl->m_inStream, a_text);
707 } // DaStreamReader::LineBeginsWith
708 
715 //------------------------------------------------------------------------------
719 //------------------------------------------------------------------------------
720 DaStreamWriter::DaStreamWriter(std::ostream& a_outStream, bool a_binaryArrays /*= false*/)
721 : m_impl(new Impl(a_outStream, a_binaryArrays))
722 {
723 } // DaStreamWriter::DaStreamWriter
724 //------------------------------------------------------------------------------
726 //------------------------------------------------------------------------------
728 {
729 } // DaStreamWriter::~DaStreamWriter
730 //------------------------------------------------------------------------------
733 //------------------------------------------------------------------------------
735 {
736  return m_impl->m_binaryArrays;
737 } // DaStreamWriter::IsBinary
738 //------------------------------------------------------------------------------
741 //------------------------------------------------------------------------------
742 void DaStreamWriter::WriteLine(const std::string& a_line)
743 {
744  daWriteLine(m_impl->m_outStream, a_line);
745 } // DaStreamWriter::WriteLine
746 //------------------------------------------------------------------------------
750 //------------------------------------------------------------------------------
751 void DaStreamWriter::WriteStringLine(const char* a_name, const std::string& a_val)
752 {
753  daWriteStringLine(m_impl->m_outStream, a_name, a_val);
754 } // DaStreamWriter::WriteStringLine
755 //------------------------------------------------------------------------------
759 //------------------------------------------------------------------------------
760 void DaStreamWriter::WriteIntLine(const char* a_name, int a_val)
761 {
762  daWriteIntLine(m_impl->m_outStream, a_name, a_val);
763 } // DaStreamWriter::WriteIntLine
764 //------------------------------------------------------------------------------
768 //------------------------------------------------------------------------------
769 void DaStreamWriter::WriteDoubleLine(const char* a_name, double a_val)
770 {
771  daWriteDoubleLine(m_impl->m_outStream, a_name, a_val);
772 } // DaStreamWriter::WriteDoubleLine
773 //------------------------------------------------------------------------------
777 //------------------------------------------------------------------------------
778 void DaStreamWriter::WriteVecInt(const char* a_name, const VecInt& a_vec)
779 {
780  if (IsBinary())
781  {
782  m_impl->m_outStream << a_name << ' ' << a_vec.size() << '\n';
783  if (!a_vec.empty())
784  WriteBinaryBytes(reinterpret_cast<const char*>(&a_vec[0]),
785  a_vec.size() * sizeof(VecInt::value_type));
786  }
787  else
788  {
789  daWriteVecInt(m_impl->m_outStream, a_name, a_vec);
790  }
791 } // DaStreamWriter::WriteVecInt
792 //------------------------------------------------------------------------------
796 //------------------------------------------------------------------------------
797 void DaStreamWriter::WriteVecDbl(const char* a_name, const VecDbl& a_vec)
798 {
799  if (IsBinary())
800  {
801  m_impl->m_outStream << a_name << ' ' << a_vec.size() << '\n';
802  if (!a_vec.empty())
803  WriteBinaryBytes(reinterpret_cast<const char*>(&a_vec[0]),
804  a_vec.size() * sizeof(VecDbl::value_type));
805  }
806  else
807  {
808  daWriteVecDbl(m_impl->m_outStream, a_name, a_vec);
809  }
810 } // DaStreamWriter::WriteVecDbl
811 //------------------------------------------------------------------------------
815 //------------------------------------------------------------------------------
816 void DaStreamWriter::WriteVecPt3d(const char* a_name, const VecPt3d& a_points)
817 {
818  if (IsBinary())
819  {
820  m_impl->m_outStream << a_name << ' ' << a_points.size() << '\n';
821  if (!a_points.empty())
822  WriteBinaryBytes(reinterpret_cast<const char*>(&a_points[0]),
823  a_points.size() * sizeof(VecPt3d::value_type));
824  }
825  else
826  {
827  daWriteVecPt3d(m_impl->m_outStream, a_name, a_points);
828  }
829 } // DaStreamWriter::WriteVecPt3d
830 //------------------------------------------------------------------------------
835 //------------------------------------------------------------------------------
836 void DaStreamWriter::Write2StringLine(const char* a_name,
837  const std::string& a_val1,
838  const std::string& a_val2)
839 {
840  daWrite2StringLine(m_impl->m_outStream, a_name, a_val1, a_val2);
841 } // DaStreamWriter::Write2StringLine
842 //------------------------------------------------------------------------------
848 //------------------------------------------------------------------------------
849 void DaStreamWriter::Write3StringLine(const char* a_name,
850  const std::string& a_val1,
851  const std::string& a_val2,
852  const std::string& a_val3)
853 {
854  daWrite3StringLine(m_impl->m_outStream, a_name, a_val1, a_val2, a_val3);
855 } // DaStreamWriter::Write3StringLine
856 //------------------------------------------------------------------------------
862 //------------------------------------------------------------------------------
863 void DaStreamWriter::Write3DoubleLine(const char* a_name,
864  const double& a_val1,
865  const double& a_val2,
866  const double& a_val3)
867 {
868  daWrite3DoubleLine(m_impl->m_outStream, a_name, a_val1, a_val2, a_val3);
869 } // DaStreamWriter::Write3DoubleLine
870 //------------------------------------------------------------------------------
873 //------------------------------------------------------------------------------
874 void DaStreamWriter::WriteString(const char* a_string)
875 {
876  m_impl->m_outStream << a_string;
877 } // DaStreamWriter::WriteString
878 //------------------------------------------------------------------------------
881 //------------------------------------------------------------------------------
883 {
884  m_impl->m_outStream << ' ' << a_val;
885 } // DaStreamWriter::AppendInt
886 //------------------------------------------------------------------------------
890 //------------------------------------------------------------------------------
891 void DaStreamWriter::AppendInts(const int* a_values, int a_numValues)
892 {
893  for (int i = 0; i < a_numValues; ++i)
894  m_impl->m_outStream << ' ' << *a_values++;
895 } // DaStreamWriter::AppendInts
896 //------------------------------------------------------------------------------
899 //------------------------------------------------------------------------------
900 void DaStreamWriter::AppendString(const std::string& a_val)
901 {
902  m_impl->m_outStream << ' ' << a_val;
903 } // DaStreamWriter::AppendString
904 //------------------------------------------------------------------------------
906 //------------------------------------------------------------------------------
908 {
909  m_impl->m_outStream << '\n';
910 } // DaStreamWriter::EndLine
911 //------------------------------------------------------------------------------
916 //------------------------------------------------------------------------------
917 bool DaStreamWriter::WriteBinaryBytes(const char* a_source, long long a_sourceLength)
918 {
919  auto maxCompressedLength = static_cast<int32_t>(compressBound(m_impl->m_blockSize));
920  int32_t maxEncodeLength = iBase64EncodeSize(maxCompressedLength);
921  std::unique_ptr<char[]> compressed(new char[maxCompressedLength]);
922  std::unique_ptr<char[]> encoded(new char[maxEncodeLength + 1]);
923 
924  while (a_sourceLength > 0)
925  {
926  // compress a block
927  int32_t blockLength = a_sourceLength < m_impl->m_blockSize
928  ? static_cast<int32_t>(a_sourceLength)
929  : m_impl->m_blockSize;
930  int32_t compressedLength =
931  iCompress(a_source, blockLength, compressed.get(), maxCompressedLength);
932  if (compressedLength < 0)
933  return false;
934  a_sourceLength -= blockLength;
935  a_source += blockLength;
936 
937  // encode a block
938  int32_t encodedLength = iBase64Encode(compressed.get(), compressedLength, encoded.get());
939 
940  // write block info
941  WriteString("BINARY_BLOCK");
942  AppendInt(encodedLength);
943  AppendInt(blockLength);
944  EndLine();
945  m_impl->m_outStream.write(encoded.get(), encodedLength);
946  EndLine();
947  }
948 
949  return true;
950 } // DaStreamWriter::WriteBinaryBytes
951 //------------------------------------------------------------------------------
954 //------------------------------------------------------------------------------
956 {
957  m_impl->m_blockSize = a_blockSize > MAX_BLOCK_SIZE ? MAX_BLOCK_SIZE : a_blockSize;
958 } // DaStreamWriter::SetBinaryBlockSize
959 
960 //------------------------------------------------------------------------------
965 //------------------------------------------------------------------------------
966 bool daReadNamedLine(std::istream& a_inStream, const char* a_name)
967 {
968  std::stringstream ss;
969  return iReadLineToSStream(a_inStream, a_name, ss);
970 } // daReadNamedLine
971 //------------------------------------------------------------------------------
977 //------------------------------------------------------------------------------
978 bool daReadLine(std::istream& a_inStream, std::string& a_line)
979 {
980  a_line.clear();
981 
982  // The characters in the stream are read one-by-one using a std::streambuf.
983  // That is faster than reading them one-by-one using the std::istream.
984  // Code that uses streambuf this way must be guarded by a sentry object.
985  // The sentry object performs various tasks,
986  // such as thread synchronization and updating the stream state.
987 
988  std::istream::sentry se(a_inStream, true);
989  std::streambuf* sb = a_inStream.rdbuf();
990 
991  for (;;)
992  {
993  int c = sb->sbumpc();
994  if (c == '\n')
995  {
996  return !!a_inStream;
997  }
998 
999  if (c == '\r')
1000  {
1001  if (sb->sgetc() == '\n')
1002  sb->sbumpc();
1003  return !!a_inStream;
1004  }
1005 
1006  if (c == std::streambuf::traits_type::eof())
1007  {
1008  // Also handle the case when the last line has no line ending
1009  if (a_line.empty())
1010  a_inStream.setstate(std::ios::eofbit);
1011  return !!a_inStream;
1012  }
1013 
1014  a_line += (char)c;
1015  }
1016 } // daReadLine
1017 //------------------------------------------------------------------------------
1023 //------------------------------------------------------------------------------
1024 bool daReadIntLine(std::istream& a_inStream, const char* a_name, int& a_val)
1025 {
1026  return iReadValue(a_inStream, a_name, a_val);
1027 } // daReadIntLine
1028 //------------------------------------------------------------------------------
1034 //------------------------------------------------------------------------------
1035 bool daReadDoubleLine(std::istream& a_inStream, const char* a_name, double& a_val)
1036 {
1037  return iReadValue(a_inStream, a_name, a_val);
1038 } // daReadDoubleLine
1039 //------------------------------------------------------------------------------
1045 //------------------------------------------------------------------------------
1046 bool daReadStringLine(std::istream& a_inStream, const char* a_name, std::string& a_val)
1047 {
1048  return iReadValue(a_inStream, a_name, a_val);
1049 } // daReadStringLine
1050 //------------------------------------------------------------------------------
1056 //------------------------------------------------------------------------------
1057 bool daReadVecInt(std::istream& a_inStream, const char* a_name, VecInt& a_vec)
1058 {
1059  return iReadVector(a_inStream, a_name, a_vec);
1060 } // daReadVecInt
1061 //------------------------------------------------------------------------------
1067 //------------------------------------------------------------------------------
1068 bool daReadVecDbl(std::istream& a_inStream, const char* a_name, VecDbl& a_vec)
1069 {
1070  return iReadVector(a_inStream, a_name, a_vec);
1071 } // daReadVecDbl
1072 //------------------------------------------------------------------------------
1078 //------------------------------------------------------------------------------
1079 bool daReadVecPt3d(std::istream& a_inStream, const char* a_name, VecPt3d& a_vec)
1080 {
1081  int size;
1082  if (!daReadIntLine(a_inStream, a_name, size))
1083  return false;
1084 
1085  a_vec.resize(0);
1086  a_vec.reserve(size);
1087  std::string pointLine;
1088  std::string pointValue;
1089  for (int i = 0; i < size; ++i)
1090  {
1091  if (!daReadLine(a_inStream, pointLine))
1092  return false;
1093 
1094  bool success = daReadStringFromLine(pointLine, pointValue);
1095  success = success && pointValue == "POINT";
1096  int readPointIdx = -1;
1097  success = success && daReadIntFromLine(pointLine, readPointIdx);
1098  success = success && readPointIdx == (int)i;
1099  Pt3d pt;
1100  success = success && daReadDoubleFromLine(pointLine, pt.x);
1101  success = success && daReadDoubleFromLine(pointLine, pt.y);
1102  success = success && daReadDoubleFromLine(pointLine, pt.z);
1103  if (!success)
1104  return false;
1105  a_vec.push_back(pt);
1106  }
1107 
1108  return true;
1109 } // daReadVecPt3d
1110 //------------------------------------------------------------------------------
1117 //------------------------------------------------------------------------------
1118 bool daRead2StringLine(std::istream& a_inStream,
1119  const char* a_name,
1120  std::string& a_val1,
1121  std::string& a_val2)
1122 {
1123  return iRead2Values(a_inStream, a_name, a_val1, a_val2);
1124 } // daRead2StringLine
1125 //------------------------------------------------------------------------------
1133 //------------------------------------------------------------------------------
1134 bool daRead3StringLine(std::istream& a_inStream,
1135  const char* a_name,
1136  std::string& a_val1,
1137  std::string& a_val2,
1138  std::string& a_val3)
1139 {
1140  return iRead3Values(a_inStream, a_name, a_val1, a_val2, a_val3);
1141 } // daRead3StringLine
1142 //------------------------------------------------------------------------------
1150 //------------------------------------------------------------------------------
1151 bool daRead3DoubleLine(std::istream& a_inStream,
1152  const char* a_name,
1153  double& a_val1,
1154  double& a_val2,
1155  double& a_val3)
1156 {
1157  return iRead3Values(a_inStream, a_name, a_val1, a_val2, a_val3);
1158 } // daRead3DoubleLine
1159 //------------------------------------------------------------------------------
1164 //------------------------------------------------------------------------------
1165 bool daReadIntFromLine(std::string& a_line, int& a_val)
1166 {
1167  return iReadValueFromLine(a_line, a_val);
1168 } // daReadIntFromLine
1169 //------------------------------------------------------------------------------
1174 //------------------------------------------------------------------------------
1175 bool daReadStringFromLine(std::string& a_line, std::string& a_val)
1176 {
1177  std::istringstream inStream(a_line);
1178  inStream >> a_val;
1179  if (inStream.fail())
1180  return false;
1181  size_t position = inStream.tellg();
1182  if (position != std::string::npos)
1183  a_line = inStream.str().substr(position);
1184  else
1185  a_line = "";
1186  return true;
1187 } // daReadStringFromLine
1188 //------------------------------------------------------------------------------
1193 //------------------------------------------------------------------------------
1194 bool daReadDoubleFromLine(std::string& a_line, double& a_val)
1195 {
1196  return iReadValueFromLine(a_line, a_val);
1197 } // daReadDoubleFromLine
1198 //------------------------------------------------------------------------------
1203 //------------------------------------------------------------------------------
1204 bool daLineBeginsWith(std::istream& a_inStream, const std::string& a_text)
1205 {
1206  auto streamPosition = a_inStream.tellg();
1207  bool foundText = false;
1208  std::string line;
1209  if (daReadLine(a_inStream, line))
1210  {
1211  foundText = line.find(a_text) == 0;
1212  }
1213 
1214  a_inStream.seekg(streamPosition);
1215  return foundText;
1216 } // daLineBeginsWith
1217 //------------------------------------------------------------------------------
1221 //------------------------------------------------------------------------------
1222 void daWriteNamedLine(std::ostream& a_outStream, const char* a_name)
1223 {
1224  a_outStream << a_name << '\n';
1225 } // daWriteNamedLine
1226  //------------------------------------------------------------------------------
1230  //------------------------------------------------------------------------------
1231 void daWriteLine(std::ostream& a_outStream, const std::string& a_line)
1232 {
1233  a_outStream << a_line << '\n';
1234 } // daWriteLine
1235 //------------------------------------------------------------------------------
1240 //------------------------------------------------------------------------------
1241 void daWriteDoubleLine(std::ostream& a_outStream, const char* a_name, double a_val)
1242 {
1243  StTemp2DigitExponents temp2DigitExponents;
1244  a_outStream << a_name << ' ' << STRstd(a_val) << '\n';
1245 } // daWriteDoubleLine
1246 //------------------------------------------------------------------------------
1251 //------------------------------------------------------------------------------
1252 //------------------------------------------------------------------------------
1253 void daWriteStringLine(std::ostream& a_outStream, const char* a_name, const std::string& a_val)
1254 {
1255  a_outStream << a_name << ' ' << a_val << '\n';
1256 } // daWriteStringLine
1257 //------------------------------------------------------------------------------
1262 //------------------------------------------------------------------------------
1263 void daWriteVecInt(std::ostream& a_outStream, const char* a_name, const VecInt& a_vec)
1264 {
1265  size_t size = a_vec.size();
1266  a_outStream << a_name << ' ' << size << '\n';
1267  for (auto val : a_vec)
1268  {
1269  a_outStream << " " << val << '\n';
1270  }
1271 } // daWriteVecInt
1272 //------------------------------------------------------------------------------
1278 //------------------------------------------------------------------------------
1279 void daWrite2StringLine(std::ostream& a_outStream,
1280  const char* a_name,
1281  const std::string& a_val1,
1282  const std::string& a_val2)
1283 {
1284  a_outStream << a_name << ' ' << a_val1 << ' ' << a_val2 << '\n';
1285 } // daWrite2StringLine
1286 //------------------------------------------------------------------------------
1293 //------------------------------------------------------------------------------
1294 void daWrite3StringLine(std::ostream& a_outStream,
1295  const char* a_name,
1296  const std::string& a_val1,
1297  const std::string& a_val2,
1298  const std::string& a_val3)
1299 {
1300  a_outStream << a_name << ' ' << a_val1 << ' ' << a_val2 << ' ' << a_val3 << '\n';
1301 } // daWrite3StringLine
1302 //------------------------------------------------------------------------------
1309 //------------------------------------------------------------------------------
1310 void daWrite3DoubleLine(std::ostream& a_outStream,
1311  const char* a_name,
1312  const double& a_val1,
1313  const double& a_val2,
1314  const double& a_val3)
1315 {
1316  a_outStream << a_name << ' ' << STRstd(a_val1) << ' ' << STRstd(a_val2) << ' ' << STRstd(a_val3)
1317  << '\n';
1318 } // daWrite3DoubleLine
1319 //------------------------------------------------------------------------------
1324 //------------------------------------------------------------------------------
1325 void daWriteIntLine(std::ostream& a_outStream, const char* a_name, int a_val)
1326 {
1327  a_outStream << a_name << ' ' << a_val << '\n';
1328 } // daWriteIntLine
1329 //------------------------------------------------------------------------------
1334 //------------------------------------------------------------------------------
1335 void daWriteVecDbl(std::ostream& a_outStream, const char* a_name, const VecDbl& a_vec)
1336 {
1337  StTemp2DigitExponents temp2DigitExponents;
1338  size_t size = a_vec.size();
1339  a_outStream << a_name << ' ' << size << '\n';
1340  for (auto val : a_vec)
1341  {
1342  a_outStream << " " << STRstd(val) << '\n';
1343  }
1344 } // daWriteVecDbl
1345 //------------------------------------------------------------------------------
1350 //------------------------------------------------------------------------------
1351 void daWriteVecPt3d(std::ostream& a_outStream, const char* a_name, const VecPt3d& a_points)
1352 {
1353  // write name and size of vector
1354  a_outStream << a_name << ' ' << a_points.size() << '\n';
1355 
1356  // write each indented point and XYZ (why not remove POINT text?)
1357  StTemp2DigitExponents use2DigitExponents;
1358  for (size_t i = 0; i < a_points.size(); ++i)
1359  {
1360  const Pt3d& point = a_points[i];
1361  std::string sx(STRstd(point.x));
1362  std::string sy(STRstd(point.y));
1363  std::string sz(STRstd(point.z));
1364  a_outStream << " POINT " << i << ' ' << sx << ' ' << sy << ' ' << sz << '\n';
1365  }
1366 } // daWriteVecPt3d
1367 
1368 } // namespace xms
1369 
1370 #if CXX_TEST
1371 // TESTS
1374 
1376 
1377 #include <numeric>
1378 
1379 using namespace xms;
1380 
1385 //------------------------------------------------------------------------------
1387 //------------------------------------------------------------------------------
1389 {
1390  // test read with CR LF, LF, CR, and no line endings
1391  std::string lineEndingsInput =
1392  "Windows Line\r\n"
1393  "Unix Line\n"
1394  "Mac Line\r"
1395  "Last Line";
1396  std::istringstream inStream(lineEndingsInput);
1397  TS_ASSERT(daReadNamedLine(inStream, "Windows Line"));
1398  TS_ASSERT(daReadNamedLine(inStream, "Unix Line"));
1399  TS_ASSERT(daReadNamedLine(inStream, "Mac Line"));
1400  TS_ASSERT(daReadNamedLine(inStream, "Last Line"));
1401 } // DaStreamIoUnitTests::testReadNamedLine
1402 //------------------------------------------------------------------------------
1404 //------------------------------------------------------------------------------
1406 {
1407  std::ostringstream outputStream;
1408  daWriteLine(outputStream, "daWriteLine version 1.0");
1409  std::string expected = "daWriteLine version 1.0\n";
1410  std::string found = outputStream.str();
1411  TS_ASSERT_EQUALS(expected, found);
1412 
1413  std::istringstream inputStream(outputStream.str());
1414  std::string value;
1415  daReadLine(inputStream, value);
1416  expected = "daWriteLine version 1.0";
1417  TS_ASSERT_EQUALS(expected, value);
1418 
1419  // test read with CR LF, LF, CR, and no line endings
1420  std::string lineEndingsInput =
1421  "Windows Line\r\n"
1422  "Unix Line\n"
1423  "Mac Line\r"
1424  "Last Line";
1425  std::istringstream endingsIn(lineEndingsInput);
1426  daReadLine(endingsIn, value);
1427  TS_ASSERT_EQUALS("Windows Line", value);
1428  daReadLine(endingsIn, value);
1429  TS_ASSERT_EQUALS("Unix Line", value);
1430  daReadLine(endingsIn, value);
1431  TS_ASSERT_EQUALS("Mac Line", value);
1432  daReadLine(endingsIn, value);
1433  TS_ASSERT_EQUALS("Last Line", value);
1434 } // DaStreamIoUnitTests::testReadWriteLine
1435 //------------------------------------------------------------------------------
1437 //------------------------------------------------------------------------------
1439 {
1440  std::ostringstream outputStream;
1441  const char* name = "LINE_NAME";
1442  std::string expectedValue = "VALUE";
1443  daWriteStringLine(outputStream, name, expectedValue);
1444  std::string expected = "LINE_NAME VALUE\n";
1445  std::string found = outputStream.str();
1446  TS_ASSERT_EQUALS(expected, found);
1447 
1448  std::istringstream inputStream(outputStream.str());
1449  std::string foundValue;
1450  TS_ASSERT(daReadStringLine(inputStream, name, foundValue));
1451  TS_ASSERT_EQUALS(expectedValue, foundValue);
1452 } // DaStreamIoUnitTests::testReadWriteStringLine
1453 //------------------------------------------------------------------------------
1455 //------------------------------------------------------------------------------
1457 {
1458  std::ostringstream outputStream;
1459  const char* name = "LINE_NAME";
1460  std::string expectedValue1 = "VALUE1";
1461  std::string expectedValue2 = "VALUE2";
1462  daWrite2StringLine(outputStream, name, expectedValue1, expectedValue2);
1463  std::string expected = "LINE_NAME VALUE1 VALUE2\n";
1464  std::string found = outputStream.str();
1465  TS_ASSERT_EQUALS(expected, found);
1466 
1467  std::istringstream inputStream(outputStream.str());
1468  std::string foundValue1;
1469  std::string foundValue2;
1470  TS_ASSERT(daRead2StringLine(inputStream, name, foundValue1, foundValue2));
1471  TS_ASSERT_EQUALS(expectedValue1, foundValue1);
1472  TS_ASSERT_EQUALS(expectedValue2, foundValue2);
1473 } // DaStreamIoUnitTests::testReadWrite2StringLine
1474 //------------------------------------------------------------------------------
1476 //------------------------------------------------------------------------------
1478 {
1479  std::ostringstream outputStream;
1480  const char* name = "LINE_NAME";
1481  std::string expectedValue1 = "VALUE1";
1482  std::string expectedValue2 = "VALUE2";
1483  std::string expectedValue3 = "VALUE3";
1484  daWrite3StringLine(outputStream, name, expectedValue1, expectedValue2, expectedValue3);
1485  std::string expected = "LINE_NAME VALUE1 VALUE2 VALUE3\n";
1486  std::string found = outputStream.str();
1487  TS_ASSERT_EQUALS(expected, found);
1488 
1489  std::istringstream inputStream(outputStream.str());
1490  std::string foundValue1;
1491  std::string foundValue2;
1492  std::string foundValue3;
1493  TS_ASSERT(daRead3StringLine(inputStream, name, foundValue1, foundValue2, foundValue3));
1494  TS_ASSERT_EQUALS(expectedValue1, foundValue1);
1495  TS_ASSERT_EQUALS(expectedValue2, foundValue2);
1496  TS_ASSERT_EQUALS(expectedValue3, foundValue3);
1497 } // DaStreamIoUnitTests::testReadWrite3StringLine
1498 //------------------------------------------------------------------------------
1500 //------------------------------------------------------------------------------
1502 {
1503  std::string line;
1504 
1505  // read from front
1506  int intValue;
1507  line = "1 -1 A 2.0 B 4";
1508  TS_ASSERT(daReadIntFromLine(line, intValue));
1509  TS_ASSERT_EQUALS(1, intValue);
1510  TS_ASSERT_EQUALS(" -1 A 2.0 B 4", line);
1511 
1512  // read second value (with a space)
1513  line = " -1 A 2.0 B 4";
1514  TS_ASSERT(daReadIntFromLine(line, intValue));
1515  TS_ASSERT_EQUALS(-1, intValue);
1516  TS_ASSERT_EQUALS(" A 2.0 B 4", line);
1517 
1518  // fails to read alpha (int value stays the same)
1519  line = " A 2.0 B 4";
1520  intValue = -1;
1521  TS_ASSERT(!daReadIntFromLine(line, intValue));
1522  TS_ASSERT_EQUALS(-1, intValue);
1523  TS_ASSERT_EQUALS(" A 2.0 B 4", line);
1524 
1525  // fails to read double (int value stays the same)
1526  line = " A 2.0 B 4";
1527  intValue = -1;
1528  TS_ASSERT(!daReadIntFromLine(line, intValue));
1529  TS_ASSERT_EQUALS(-1, intValue);
1530  TS_ASSERT_EQUALS(" A 2.0 B 4", line);
1531 
1532  // fails with empty line
1533  line = "";
1534  intValue = -1;
1535  TS_ASSERT(!daReadIntFromLine(line, intValue));
1536  TS_ASSERT_EQUALS(-1, intValue);
1537  TS_ASSERT_EQUALS("", line);
1538 } // DaStreamIoUnitTests::testReadIntFromLine
1539 //------------------------------------------------------------------------------
1541 //------------------------------------------------------------------------------
1543 {
1544  std::string line;
1545 
1546  // read from front
1547  std::string stringValue;
1548  line = "value1 value2 3";
1549  TS_ASSERT(daReadStringFromLine(line, stringValue));
1550  TS_ASSERT_EQUALS("value1", stringValue);
1551  TS_ASSERT_EQUALS(" value2 3", line);
1552 
1553  // read second value (with a space)
1554  line = " value2 value3";
1555  TS_ASSERT(daReadStringFromLine(line, stringValue));
1556  TS_ASSERT_EQUALS("value2", stringValue);
1557  TS_ASSERT_EQUALS(" value3", line);
1558 
1559  // read last value
1560  line = "3";
1561  TS_ASSERT(daReadStringFromLine(line, stringValue));
1562  TS_ASSERT_EQUALS("3", stringValue);
1563  TS_ASSERT_EQUALS("", line);
1564 
1565  // fails with empty line (string value stays the same)
1566  line = "";
1567  stringValue = "3";
1568  TS_ASSERT(!daReadStringFromLine(line, stringValue));
1569  TS_ASSERT_EQUALS("3", stringValue);
1570  TS_ASSERT_EQUALS("", line);
1571 } // DaStreamIoUnitTests::testReadStringFromLine
1572 //------------------------------------------------------------------------------
1574 //------------------------------------------------------------------------------
1576 {
1577  std::string line;
1578 
1579  // read from front
1580  double doubleValue;
1581  line = "1.1 -1.0e-3 3";
1582  TS_ASSERT(daReadDoubleFromLine(line, doubleValue));
1583  TS_ASSERT_EQUALS(1.1, doubleValue);
1584  TS_ASSERT_EQUALS(" -1.0e-3 3", line);
1585 
1586  // read second value (with a space)
1587  line = " -1.0e-3 3";
1588  TS_ASSERT(daReadDoubleFromLine(line, doubleValue));
1589  TS_ASSERT_EQUALS(-1.0e-3, doubleValue);
1590  TS_ASSERT_EQUALS(" 3", line);
1591 
1592  // read last value
1593  line = "3";
1594  TS_ASSERT(daReadDoubleFromLine(line, doubleValue));
1595  TS_ASSERT_EQUALS(3, doubleValue);
1596  TS_ASSERT_EQUALS("", line);
1597 
1598  // fails with empty line (string value stays the same)
1599  line = "";
1600  doubleValue = 3;
1601  TS_ASSERT(!daReadDoubleFromLine(line, doubleValue));
1602  TS_ASSERT_EQUALS(3, doubleValue);
1603  TS_ASSERT_EQUALS("", line);
1604 } // DaStreamIoUnitTests::testReadDoubleFromLine
1605 //------------------------------------------------------------------------------
1607 //------------------------------------------------------------------------------
1609 {
1610  std::ostringstream outputStream;
1611  const char* name = "LINE_NAME";
1612  const int expect = 22;
1613  daWriteIntLine(outputStream, name, expect);
1614  std::string outputExpected = "LINE_NAME 22\n";
1615  std::string outputFound = outputStream.str();
1616  TS_ASSERT_EQUALS(outputExpected, outputFound);
1617 
1618  std::istringstream inputStream(outputStream.str());
1619  int found;
1620  TS_ASSERT(daReadIntLine(inputStream, name, found));
1621  TS_ASSERT_EQUALS(expect, found);
1622 } // DaStreamIoUnitTests::testReadWriteIntLine
1623 //------------------------------------------------------------------------------
1625 //------------------------------------------------------------------------------
1627 {
1628  std::ostringstream outputStream;
1629  const char* name = "LINE_NAME";
1630  const double expect1 = 1.123e-20;
1631  const double expect2 = 2.0;
1632  daWriteDoubleLine(outputStream, name, expect1);
1633  daWriteDoubleLine(outputStream, name, expect2);
1634  std::string outputExpected = "LINE_NAME 1.123e-20\nLINE_NAME 2.0\n";
1635  std::string outputFound = outputStream.str();
1636  TS_ASSERT_EQUALS(outputExpected, outputFound);
1637 
1638  std::istringstream inputStream(outputStream.str());
1639  double found;
1640  TS_ASSERT(daReadDoubleLine(inputStream, name, found));
1641  TS_ASSERT_EQUALS(expect1, found);
1642  TS_ASSERT(daReadDoubleLine(inputStream, name, found));
1643  TS_ASSERT_EQUALS(expect2, found);
1644 } // DaStreamIoUnitTests::testReadWriteDoubleLine
1645 //------------------------------------------------------------------------------
1647 //------------------------------------------------------------------------------
1649 {
1650  std::ostringstream outputStream;
1651  const char* name = "LINE_NAME";
1652  const double expect1 = 560770.5;
1653  const double expect2 = 70055.4;
1654  const double expect3 = 22.3;
1655  daWrite3DoubleLine(outputStream, name, expect1, expect2, expect3);
1656  std::string outputExpected = "LINE_NAME 560770.5 70055.4 22.3\n";
1657  std::string outputFound = outputStream.str();
1658  TS_ASSERT_EQUALS(outputExpected, outputFound);
1659 
1660  std::istringstream inputStream(outputStream.str());
1661  double found1;
1662  double found2;
1663  double found3;
1664  TS_ASSERT(daRead3DoubleLine(inputStream, name, found1, found2, found3));
1665  TS_ASSERT_EQUALS(expect1, found1);
1666  TS_ASSERT_EQUALS(expect2, found2);
1667  TS_ASSERT_EQUALS(expect3, found3);
1668 } // DaStreamIoUnitTests::testReadWrite3DoubleLine
1669 //------------------------------------------------------------------------------
1671 //------------------------------------------------------------------------------
1673 {
1674  std::ostringstream outputStream;
1675  const char* name = "VECTOR_NAME";
1676  const VecInt expect = {1, 2, 3};
1677  daWriteVecInt(outputStream, name, expect);
1678  std::string outputExpected =
1679  "VECTOR_NAME 3\n"
1680  " 1\n"
1681  " 2\n"
1682  " 3\n";
1683  std::string outputFound = outputStream.str();
1684  TS_ASSERT_EQUALS(outputExpected, outputFound);
1685 
1686  std::istringstream inputStream(outputStream.str());
1687  VecInt found;
1688  TS_ASSERT(daReadVecInt(inputStream, name, found));
1689  TS_ASSERT_EQUALS(expect, found);
1690 } // DaStreamIoUnitTests::testReadWriteVecInt
1691 //------------------------------------------------------------------------------
1693 //------------------------------------------------------------------------------
1695 {
1696  std::ostringstream outputStream;
1697  const char* name = "VECTOR_NAME";
1698  const VecDbl expect = {1.0, 2.2e-20, 3.3};
1699  daWriteVecDbl(outputStream, name, expect);
1700  std::string outputExpected =
1701  "VECTOR_NAME 3\n"
1702  " 1.0\n"
1703  " 2.2e-20\n"
1704  " 3.3\n";
1705  std::string outputFound = outputStream.str();
1706  TS_ASSERT_EQUALS(outputExpected, outputFound);
1707 
1708  std::istringstream inputStream(outputStream.str());
1709  VecDbl found;
1710  TS_ASSERT(daReadVecDbl(inputStream, name, found));
1711  TS_ASSERT_EQUALS(expect, found);
1712 } // DaStreamIoUnitTests::testReadWriteVecDbl
1713 //------------------------------------------------------------------------------
1715 //------------------------------------------------------------------------------
1717 {
1718  std::ostringstream outputStream;
1719  const char* name = "VECTOR_NAME";
1720  const VecPt3d expect = {
1721  {1.0, 1.2, 1.3},
1722  {2.1, 2.2, 2.3e-20},
1723  };
1724  daWriteVecPt3d(outputStream, name, expect);
1725  std::string outputExpected =
1726  "VECTOR_NAME 2\n"
1727  " POINT 0 1.0 1.2 1.3\n"
1728  " POINT 1 2.1 2.2 2.3e-20\n";
1729  std::string outputFound = outputStream.str();
1730  TS_ASSERT_EQUALS(outputExpected, outputFound);
1731 
1732  std::istringstream inputStream(outputStream.str());
1733  VecPt3d found;
1734  TS_ASSERT(daReadVecPt3d(inputStream, name, found));
1735  TS_ASSERT_EQUALS(expect, found);
1736 } // DaStreamIoUnitTests::testReadWriteVecPt3d
1737 //------------------------------------------------------------------------------
1739 //------------------------------------------------------------------------------
1741 {
1742  const char* inputText =
1743  "VECTOR_NAME 2\n"
1744  " POINT 0 1.1 1.2 1.3\n"
1745  " POINT 1 2.1 2.2 2.3\n";
1746  std::istringstream inputStream(inputText);
1747  TS_ASSERT(daLineBeginsWith(inputStream, "VECTOR_NAME"));
1748  std::string line;
1749  TS_ASSERT(daReadLine(inputStream, line));
1750  TS_ASSERT_EQUALS("VECTOR_NAME 2", line);
1751  TS_ASSERT(daLineBeginsWith(inputStream, " POINT"));
1752  TS_ASSERT(daReadLine(inputStream, line));
1753  TS_ASSERT_EQUALS(" POINT 0 1.1 1.2 1.3", line);
1754  TS_ASSERT(daLineBeginsWith(inputStream, " POINT 1 2.1 2.2 2.3"));
1755  TS_ASSERT(daReadLine(inputStream, line));
1756  TS_ASSERT_EQUALS(" POINT 1 2.1 2.2 2.3", line);
1757 } // DaStreamIoUnitTests::testLineBeginsWith
1762 //------------------------------------------------------------------------------
1764 //------------------------------------------------------------------------------
1766 {
1767  // test read with CR LF, LF, CR, and no line endings
1768  std::string lineEndingsInput =
1769  "Windows Line\r\n"
1770  "Unix Line\n"
1771  "Mac Line\r"
1772  "Last Line";
1773  std::istringstream inStream(lineEndingsInput);
1774  DaStreamReader reader(inStream);
1775  TS_ASSERT(reader.ReadNamedLine("Windows Line"));
1776  TS_ASSERT(reader.ReadNamedLine("Unix Line"));
1777  TS_ASSERT(reader.ReadNamedLine("Mac Line"));
1778  TS_ASSERT(reader.ReadNamedLine("Last Line"));
1779 } // DaReaderWriterIoUnitTests::testReadNamedLine
1780 //------------------------------------------------------------------------------
1782 //------------------------------------------------------------------------------
1784 {
1785  std::ostringstream outputStream;
1786  DaStreamWriter writer(outputStream);
1787  writer.WriteLine("daWriteLine version 1.0");
1788  std::string expected = "daWriteLine version 1.0\n";
1789  std::string found = outputStream.str();
1790  TS_ASSERT_EQUALS(expected, found);
1791 
1792  std::istringstream inputStream(outputStream.str());
1793  DaStreamReader reader(inputStream);
1794  std::string value;
1795  reader.ReadLine(value);
1796  expected = "daWriteLine version 1.0";
1797  TS_ASSERT_EQUALS(expected, value);
1798 
1799  // test read with CR LF, LF, CR, and no line endings
1800  std::string lineEndingsInput =
1801  "Windows Line\r\n"
1802  "Unix Line\n"
1803  "Mac Line\r"
1804  "Last Line";
1805  std::istringstream endingsIn(lineEndingsInput);
1806  DaStreamReader readerIn(endingsIn);
1807  readerIn.ReadLine(value);
1808  TS_ASSERT_EQUALS("Windows Line", value);
1809  readerIn.ReadLine(value);
1810  TS_ASSERT_EQUALS("Unix Line", value);
1811  readerIn.ReadLine(value);
1812  TS_ASSERT_EQUALS("Mac Line", value);
1813  readerIn.ReadLine(value);
1814  TS_ASSERT_EQUALS("Last Line", value);
1815 } // DaReaderWriterIoUnitTests::testReadWriteLine
1816 //------------------------------------------------------------------------------
1818 //------------------------------------------------------------------------------
1820 {
1821  std::ostringstream outputStream;
1822  DaStreamWriter writer(outputStream);
1823  const char* name = "LINE_NAME";
1824  std::string expectedValue = "VALUE";
1825  writer.WriteStringLine(name, expectedValue);
1826  std::string expected = "LINE_NAME VALUE\n";
1827  std::string found = outputStream.str();
1828  TS_ASSERT_EQUALS(expected, found);
1829 
1830  std::istringstream inputStream(outputStream.str());
1831  DaStreamReader reader(inputStream);
1832  std::string foundValue;
1833  TS_ASSERT(reader.ReadStringLine(name, foundValue));
1834  TS_ASSERT_EQUALS(expectedValue, foundValue);
1835 } // DaReaderWriterIoUnitTests::testReadWriteStringLine
1836 //------------------------------------------------------------------------------
1838 //------------------------------------------------------------------------------
1840 {
1841  std::ostringstream outputStream;
1842  DaStreamWriter writer(outputStream);
1843  const char* name = "LINE_NAME";
1844  std::string expectedValue1 = "VALUE1";
1845  std::string expectedValue2 = "VALUE2";
1846  writer.Write2StringLine(name, expectedValue1, expectedValue2);
1847  std::string expected = "LINE_NAME VALUE1 VALUE2\n";
1848  std::string found = outputStream.str();
1849  TS_ASSERT_EQUALS(expected, found);
1850 
1851  std::istringstream inputStream(outputStream.str());
1852  DaStreamReader reader(inputStream);
1853  std::string foundValue1;
1854  std::string foundValue2;
1855  TS_ASSERT(reader.Read2StringLine(name, foundValue1, foundValue2));
1856  TS_ASSERT_EQUALS(expectedValue1, foundValue1);
1857  TS_ASSERT_EQUALS(expectedValue2, foundValue2);
1858 } // DaReaderWriterIoUnitTests::testReadWrite2StringLine
1859 //------------------------------------------------------------------------------
1861 //------------------------------------------------------------------------------
1863 {
1864  std::ostringstream outputStream;
1865  DaStreamWriter writer(outputStream);
1866  const char* name = "LINE_NAME";
1867  std::string expectedValue1 = "VALUE1";
1868  std::string expectedValue2 = "VALUE2";
1869  std::string expectedValue3 = "VALUE3";
1870  writer.Write3StringLine(name, expectedValue1, expectedValue2, expectedValue3);
1871  std::string expected = "LINE_NAME VALUE1 VALUE2 VALUE3\n";
1872  std::string found = outputStream.str();
1873  TS_ASSERT_EQUALS(expected, found);
1874 
1875  std::istringstream inputStream(outputStream.str());
1876  DaStreamReader reader(inputStream);
1877  std::string foundValue1;
1878  std::string foundValue2;
1879  std::string foundValue3;
1880  TS_ASSERT(reader.Read3StringLine(name, foundValue1, foundValue2, foundValue3));
1881  TS_ASSERT_EQUALS(expectedValue1, foundValue1);
1882  TS_ASSERT_EQUALS(expectedValue2, foundValue2);
1883  TS_ASSERT_EQUALS(expectedValue3, foundValue3);
1884 } // DaReaderWriterIoUnitTests::testReadWrite3StringLine
1885 //------------------------------------------------------------------------------
1887 //------------------------------------------------------------------------------
1889 {
1890  // read from front
1891  int intValue;
1892  std::string line = "1 -1 A 2.0 B 4";
1893  TS_ASSERT(DaStreamReader::ReadIntFromLine(line, intValue));
1894  TS_ASSERT_EQUALS(1, intValue);
1895  TS_ASSERT_EQUALS(" -1 A 2.0 B 4", line);
1896 
1897  // read second value (with a space)
1898  line = " -1 A 2.0 B 4";
1899  TS_ASSERT(DaStreamReader::ReadIntFromLine(line, intValue));
1900  TS_ASSERT_EQUALS(-1, intValue);
1901  TS_ASSERT_EQUALS(" A 2.0 B 4", line);
1902 
1903  // fails to read alpha (int value stays the same)
1904  line = " A 2.0 B 4";
1905  intValue = -1;
1906  TS_ASSERT(!DaStreamReader::ReadIntFromLine(line, intValue));
1907  TS_ASSERT_EQUALS(-1, intValue);
1908  TS_ASSERT_EQUALS(" A 2.0 B 4", line);
1909 
1910  // fails to read double (int value stays the same)
1911  line = " A 2.0 B 4";
1912  intValue = -1;
1913  TS_ASSERT(!DaStreamReader::ReadIntFromLine(line, intValue));
1914  TS_ASSERT_EQUALS(-1, intValue);
1915  TS_ASSERT_EQUALS(" A 2.0 B 4", line);
1916 
1917  // fails with empty line
1918  line = "";
1919  intValue = -1;
1920  TS_ASSERT(!DaStreamReader::ReadIntFromLine(line, intValue));
1921  TS_ASSERT_EQUALS(-1, intValue);
1922  TS_ASSERT_EQUALS("", line);
1923 } // DaReaderWriterIoUnitTests::testReadIntFromLine
1924 //------------------------------------------------------------------------------
1926 //------------------------------------------------------------------------------
1928 {
1929  // read from front
1930  std::string stringValue;
1931  std::string line = "value1 value2 3";
1932  TS_ASSERT(DaStreamReader::ReadStringFromLine(line, stringValue));
1933  TS_ASSERT_EQUALS("value1", stringValue);
1934  TS_ASSERT_EQUALS(" value2 3", line);
1935 
1936  // read second value (with a space)
1937  line = " value2 value3";
1938  TS_ASSERT(DaStreamReader::ReadStringFromLine(line, stringValue));
1939  TS_ASSERT_EQUALS("value2", stringValue);
1940  TS_ASSERT_EQUALS(" value3", line);
1941 
1942  // read last value
1943  line = "3";
1944  TS_ASSERT(DaStreamReader::ReadStringFromLine(line, stringValue));
1945  TS_ASSERT_EQUALS("3", stringValue);
1946  TS_ASSERT_EQUALS("", line);
1947 
1948  // fails with empty line (string value stays the same)
1949  line = "";
1950  stringValue = "3";
1951  TS_ASSERT(!DaStreamReader::ReadStringFromLine(line, stringValue));
1952  TS_ASSERT_EQUALS("3", stringValue);
1953  TS_ASSERT_EQUALS("", line);
1954 } // DaReaderWriterIoUnitTests::testReadStringFromLine
1955 //------------------------------------------------------------------------------
1957 //------------------------------------------------------------------------------
1959 {
1960  // read from front
1961  double doubleValue;
1962  std::string line = "1.1 -1.0e-3 3";
1963  TS_ASSERT(DaStreamReader::ReadDoubleFromLine(line, doubleValue));
1964  TS_ASSERT_EQUALS(1.1, doubleValue);
1965  TS_ASSERT_EQUALS(" -1.0e-3 3", line);
1966 
1967  // read second value (with a space)
1968  line = " -1.0e-3 3";
1969  TS_ASSERT(DaStreamReader::ReadDoubleFromLine(line, doubleValue));
1970  TS_ASSERT_EQUALS(-1.0e-3, doubleValue);
1971  TS_ASSERT_EQUALS(" 3", line);
1972 
1973  // read last value
1974  line = "3";
1975  TS_ASSERT(DaStreamReader::ReadDoubleFromLine(line, doubleValue));
1976  TS_ASSERT_EQUALS(3, doubleValue);
1977  TS_ASSERT_EQUALS("", line);
1978 
1979  // fails with empty line (string value stays the same)
1980  line = "";
1981  doubleValue = 3;
1982  TS_ASSERT(!DaStreamReader::ReadDoubleFromLine(line, doubleValue));
1983  TS_ASSERT_EQUALS(3, doubleValue);
1984  TS_ASSERT_EQUALS("", line);
1985 } // DaReaderWriterIoUnitTests::testReadDoubleFromLine
1986 //------------------------------------------------------------------------------
1988 //------------------------------------------------------------------------------
1990 {
1991  std::ostringstream outputStream;
1992  DaStreamWriter writer(outputStream);
1993  const char* name = "LINE_NAME";
1994  const int expect = 22;
1995  writer.WriteIntLine(name, expect);
1996  std::string outputExpected = "LINE_NAME 22\n";
1997  std::string outputFound = outputStream.str();
1998  TS_ASSERT_EQUALS(outputExpected, outputFound);
1999 
2000  std::istringstream inputStream(outputStream.str());
2001  DaStreamReader reader(inputStream);
2002  int found;
2003  TS_ASSERT(reader.ReadIntLine(name, found));
2004  TS_ASSERT_EQUALS(expect, found);
2005 } // DaReaderWriterIoUnitTests::testReadWriteIntLine
2006 //------------------------------------------------------------------------------
2008 //------------------------------------------------------------------------------
2010 {
2011  std::ostringstream outputStream;
2012  DaStreamWriter writer(outputStream);
2013  const char* name = "LINE_NAME";
2014  const double expect = 22.1;
2015  writer.WriteDoubleLine(name, expect);
2016  std::string outputExpected = "LINE_NAME 22.1\n";
2017  std::string outputFound = outputStream.str();
2018  TS_ASSERT_EQUALS(outputExpected, outputFound);
2019 
2020  std::istringstream inputStream(outputStream.str());
2021  DaStreamReader reader(inputStream);
2022  double found;
2023  TS_ASSERT(reader.ReadDoubleLine(name, found));
2024  TS_ASSERT_EQUALS(expect, found);
2025 } // DaReaderWriterIoUnitTests::testReadWriteDoubleLine
2026 //------------------------------------------------------------------------------
2028 //------------------------------------------------------------------------------
2030 {
2031  std::ostringstream outputStream;
2032  DaStreamWriter writer(outputStream);
2033  const char* name = "LINE_NAME";
2034  const double expect1 = 22.1;
2035  const double expect2 = 22.2;
2036  const double expect3 = 22.3;
2037  writer.Write3DoubleLine(name, expect1, expect2, expect3);
2038  std::string outputExpected = "LINE_NAME 22.1 22.2 22.3\n";
2039  std::string outputFound = outputStream.str();
2040  TS_ASSERT_EQUALS(outputExpected, outputFound);
2041 
2042  std::istringstream inputStream(outputStream.str());
2043  DaStreamReader reader(inputStream);
2044  double found1;
2045  double found2;
2046  double found3;
2047  TS_ASSERT(reader.Read3DoubleLine(name, found1, found2, found3));
2048  TS_ASSERT_EQUALS(expect1, found1);
2049  TS_ASSERT_EQUALS(expect2, found2);
2050  TS_ASSERT_EQUALS(expect3, found3);
2051 } // DaReaderWriterIoUnitTests::testReadWrite3DoubleLine
2052 //------------------------------------------------------------------------------
2054 //------------------------------------------------------------------------------
2056 {
2057  std::ostringstream outputStream;
2058  DaStreamWriter writer(outputStream);
2059  const char* name = "VECTOR_NAME";
2060  const VecInt expect = {1, 2, 3};
2061  writer.WriteVecInt(name, expect);
2062  std::string outputExpected =
2063  "VECTOR_NAME 3\n"
2064  " 1\n"
2065  " 2\n"
2066  " 3\n";
2067  std::string outputFound = outputStream.str();
2068  TS_ASSERT_EQUALS(outputExpected, outputFound);
2069 
2070  std::istringstream inputStream(outputStream.str());
2071  DaStreamReader reader(inputStream);
2072  VecInt found;
2073  TS_ASSERT(reader.ReadVecInt(name, found));
2074  TS_ASSERT_EQUALS(expect, found);
2075 } // DaReaderWriterIoUnitTests::testReadWriteVecInt
2076 //------------------------------------------------------------------------------
2078 //------------------------------------------------------------------------------
2080 {
2081  std::ostringstream outputStream;
2082  DaStreamWriter writer(outputStream);
2083  const char* name = "VECTOR_NAME";
2084  const VecDbl expect = {1.1, 2.2, 3.3};
2085  writer.WriteVecDbl(name, expect);
2086  std::string outputExpected =
2087  "VECTOR_NAME 3\n"
2088  " 1.1\n"
2089  " 2.2\n"
2090  " 3.3\n";
2091  std::string outputFound = outputStream.str();
2092  TS_ASSERT_EQUALS(outputExpected, outputFound);
2093 
2094  std::istringstream inputStream(outputStream.str());
2095  DaStreamReader reader(inputStream);
2096  VecDbl found;
2097  TS_ASSERT(reader.ReadVecDbl(name, found));
2098  TS_ASSERT_EQUALS(expect, found);
2099 } // DaReaderWriterIoUnitTests::testReadWriteVecDbl
2100 //------------------------------------------------------------------------------
2102 //------------------------------------------------------------------------------
2104 {
2105  std::ostringstream outputStream;
2106  DaStreamWriter writer(outputStream);
2107  const char* name = "VECTOR_NAME";
2108  const VecPt3d expect = {
2109  {1.1, 1.2, 1.3},
2110  {2.1, 2.2, 2.3},
2111  };
2112  writer.WriteVecPt3d(name, expect);
2113  std::string outputExpected =
2114  "VECTOR_NAME 2\n"
2115  " POINT 0 1.1 1.2 1.3\n"
2116  " POINT 1 2.1 2.2 2.3\n";
2117  std::string outputFound = outputStream.str();
2118  TS_ASSERT_EQUALS(outputExpected, outputFound);
2119 
2120  std::istringstream inputStream(outputStream.str());
2121  DaStreamReader reader(inputStream);
2122  VecPt3d found;
2123  TS_ASSERT(reader.ReadVecPt3d(name, found));
2124  TS_ASSERT_EQUALS(expect, found);
2125 } // DaReaderWriterIoUnitTests::testReadWriteVecPt3d
2126 //------------------------------------------------------------------------------
2128 //------------------------------------------------------------------------------
2130 {
2131  std::ostringstream outputStream;
2132  bool useBinaryArrays = true;
2133  DaStreamWriter writer(outputStream, useBinaryArrays);
2134  const char* name = "VECTOR_NAME";
2135  VecInt expect(100);
2136  std::iota(expect.begin(), expect.end(), 0);
2137  writer.WriteVecInt(name, expect);
2138 
2139  std::istringstream inputStream(outputStream.str());
2140  DaStreamReader reader(inputStream, useBinaryArrays);
2141  VecInt found;
2142  TS_ASSERT(reader.ReadVecInt(name, found));
2143  TS_ASSERT_EQUALS(expect, found);
2144 } // DaReaderWriterIoUnitTests::testReadWriteBinaryVecInt
2145 //------------------------------------------------------------------------------
2147 //------------------------------------------------------------------------------
2149 {
2150  std::ostringstream outputStream;
2151  bool useBinaryArrays = true;
2152  DaStreamWriter writer(outputStream, useBinaryArrays);
2153  const char* name = "VECTOR_NAME";
2154  VecDbl expect(100);
2155  int count = 0;
2156  for (auto& e : expect)
2157  e = ++count;
2158  writer.WriteVecDbl(name, expect);
2159 
2160  std::istringstream inputStream(outputStream.str());
2161  DaStreamReader reader(inputStream, useBinaryArrays);
2162  VecDbl found;
2163  TS_ASSERT(reader.ReadVecDbl(name, found));
2164  TS_ASSERT_EQUALS(expect, found);
2165 } // DaReaderWriterIoUnitTests::testReadWriteBinaryVecDbl
2166 //------------------------------------------------------------------------------
2168 //------------------------------------------------------------------------------
2170 {
2171  std::ostringstream outputStream;
2172  bool useBinaryArrays = true;
2173  DaStreamWriter writer(outputStream, useBinaryArrays);
2174  const char* name = "VECTOR_NAME";
2175  VecPt3d expect(100);
2176  int count = 0;
2177  for (auto& e : expect)
2178  {
2179  e = Pt3d(count, count + 1, count + 2);
2180  ++count;
2181  }
2182  writer.WriteVecPt3d(name, expect);
2183 
2184  std::istringstream inputStream(outputStream.str());
2185  DaStreamReader reader(inputStream, useBinaryArrays);
2186  VecPt3d found;
2187  TS_ASSERT(reader.ReadVecPt3d(name, found));
2188  TS_ASSERT_EQUALS(expect, found);
2189 } // DaReaderWriterIoUnitTests::testReadWriteBinaryVecPt3d
2190 //------------------------------------------------------------------------------
2192 //------------------------------------------------------------------------------
2194 {
2195  std::ostringstream outputStream;
2196  DaStreamWriter writer(outputStream);
2197  writer.WriteString("STRING_ONE");
2198  TS_ASSERT_EQUALS("STRING_ONE", outputStream.str());
2199  writer.AppendInt(0);
2200  TS_ASSERT_EQUALS("STRING_ONE 0", outputStream.str());
2201  writer.AppendString("STRING_TWO");
2202  TS_ASSERT_EQUALS("STRING_ONE 0 STRING_TWO", outputStream.str());
2203  int ints[] = {1, 2, 3};
2204  writer.AppendInts(ints, 3);
2205  TS_ASSERT_EQUALS("STRING_ONE 0 STRING_TWO 1 2 3", outputStream.str());
2206  writer.EndLine();
2207  TS_ASSERT_EQUALS("STRING_ONE 0 STRING_TWO 1 2 3\n", outputStream.str());
2208 
2209  std::istringstream inputStream("STRING_ONE 0\n1 STRING_TWO");
2210  DaStreamReader reader(inputStream);
2211  std::string s;
2212  int i;
2213  TS_ASSERT(reader.ReadString(s));
2214  TS_ASSERT_EQUALS("STRING_ONE", s)
2215  TS_ASSERT(reader.ReadInt(i));
2216  TS_ASSERT_EQUALS(0, i);
2217  TS_ASSERT(reader.NextLine());
2218 
2219  TS_ASSERT(reader.ReadInt(i));
2220  TS_ASSERT_EQUALS(1, i);
2221  TS_ASSERT(reader.ReadString(s));
2222  TS_ASSERT_EQUALS("STRING_TWO", s)
2223  TS_ASSERT(!reader.NextLine());
2224 } // DaReaderWriterIoUnitTests::testReadWriteLineParts
2225 //------------------------------------------------------------------------------
2227 //------------------------------------------------------------------------------
2229 {
2230  VecInt outValues(500);
2231  std::iota(outValues.begin(), outValues.end(), 0);
2232  long long lengthInBytes = (long long)outValues.size() * sizeof(VecInt::value_type);
2233  std::ostringstream output;
2234  DaStreamWriter writer(output);
2235  writer.SetBinaryBlockSize(120);
2236  writer.WriteBinaryBytes((char*)&outValues[0], lengthInBytes);
2237  std::string text = output.str();
2238  std::string expectedText =
2239  "BINARY_BLOCK 74 120\n"
2240  "eAENw4UNwDAAAKDO3d3+f3OQEEIIkbGJqZm5haWVtY2tnb2Do5Ozi6ubu4enl7ePr58/RrQBtA\n"
2241  "BINARY_BLOCK 78 120\n"
2242  "eAENw4UNwzAAALBcUuaVGf7/a7bkKIQQm5iamVtYWlnb2Nr5s3dwdHJ2cXVz9/D08vbx9fMPILsFOA\n"
2243  "BINARY_BLOCK 78 120\n"
2244  "eAENw4UNwzAAALAcVuaVGf5/ZLbkKIQQm5iamVtYWlnb2Nr5s3dwdHJ2cXVz9/D08vbx9fMP+rMIvA\n"
2245  "BINARY_BLOCK 76 120\n"
2246  "eAENw4UNwzAAALDcWeaVGd6fLTkKIcQmpmbmFpZW1ja2dv7sHRydnF1c3dw9PL28fXz9/APUugxA\n"
2247  "BINARY_BLOCK 76 120\n"
2248  "eAENw4UNwzAAALCcXeaVGf6dLTkKIcQmpmbmFpZW1ja2dv7sHRydnF1c3dw9PL28fXz9/AOuwQ/E\n"
2249  "BINARY_BLOCK 78 120\n"
2250  "eAENw4UNwzAAALD8f0CZV2Z4cLbkKIQQm5iamVtYWlnb2Nr5s3dwdHJ2cXVz9/D08vbx9fMPiMgTSA\n"
2251  "BINARY_BLOCK 78 120\n"
2252  "eAENw4UNwzAAALD8f0+ZV2b4aLbkKIQQm5iamVtYWlnb2Nr5s3dwdHJ2cXVz9/D08vbx9fMPYs8WzA\n"
2253  "BINARY_BLOCK 78 120\n"
2254  "eAENw4UNwzAAALD8f16ZV2Z4YbbkKIQQm5iamVtYWlnb2Nr5s3dwdHJ2cXVz9/D08vbx9fMPPNYaUA\n"
2255  "BINARY_BLOCK 74 120\n"
2256  "eAENw4UNwDAAAKDO/f83524k0IcQBkcnZxdXN3cPTy9vH18/Q4SxiamZuYWllbWNrZ0/dFUP4g\n"
2257  "BINARY_BLOCK 82 120\n"
2258  "eAENw4URg0AAALBnAbRIkeJS2H8/krvEUQiJqZm5hR9LK2sbv7Z29g7+HJ2cXVzd3D08vfx7+/gCs5IDdg\n"
2259  "BINARY_BLOCK 82 120\n"
2260  "eAENw4URg0AAALBnH7RIkeJS2H8hkrvEUQiJqZm5hR9LK2sbv7Z29g7+HJ2cXVzd3D08vfx7+/gCjZkG+g\n"
2261  "BINARY_BLOCK 82 120\n"
2262  "eAENw4URg0AAALBnPbRIkeJS2H8DkrvEUQiJqZm5hR9LK2sbv7Z29g7+HJ2cXVzd3D08vfx7+/gCZ6AKfg\n"
2263  "BINARY_BLOCK 79 120\n"
2264  "eAENwwUOg0AAALDjt+iQIcNl8G/apHEUQmJqZm7hx9LK2savrZ29gz9HJ2cXVzd3D08v/94+vkGnDgI\n"
2265  "BINARY_BLOCK 79 120\n"
2266  "eAENwwUOg0AAALDj8+iQIcNl8FHapHEUQmJqZm7hx9LK2savrZ29gz9HJ2cXVzd3D08v/94+vhuuEYY\n"
2267  "BINARY_BLOCK 82 120\n"
2268  "eAENw4URg0AAALBn/zXQIkWKS2EzkrvEUQiJqZm5hR9LK2sbv7Z29g7+HJ2cXVzd3D08vfx7+/gC9aYVCg\n"
2269  "BINARY_BLOCK 82 120\n"
2270  "eAENw4URg0AAALBn/63QIkWKS2EVkrvEUQiJqZm5hR9LK2sbv7Z29g7+HJ2cXVzd3D08vfx7+/gCz60Yjg\n"
2271  "BINARY_BLOCK 63 80\n"
2272  "eAENwwESQCAAALD8/5NEkUj0Advd5imExejqZjK7e1g8rV7eNh+7r5/DH/dqElM\n";
2273  TS_ASSERT_EQUALS(expectedText, text);
2274 
2275  std::istringstream input(expectedText);
2276  DaStreamReader reader(input);
2277  VecInt inValues(500);
2278  TS_ASSERT(reader.ReadBinaryBytes((char*)&inValues[0], lengthInBytes));
2279  TS_ASSERT_EQUALS(outValues, inValues);
2280 } // DaReaderWriterIoUnitTests::testReadWriteBinaryArrays
2281 //------------------------------------------------------------------------------
2283 //------------------------------------------------------------------------------
2285 {
2286  const char* inputText =
2287  "VECTOR_NAME 2\n"
2288  " POINT 0 1.1 1.2 1.3\n"
2289  " POINT 1 2.1 2.2 2.3\n";
2290  std::istringstream inputStream(inputText);
2291  DaStreamReader reader(inputStream);
2292  TS_ASSERT(reader.LineBeginsWith("VECTOR_NAME"));
2293  std::string line;
2294  TS_ASSERT(reader.ReadLine(line));
2295  TS_ASSERT_EQUALS("VECTOR_NAME 2", line);
2296  TS_ASSERT(reader.LineBeginsWith(" POINT"));
2297  TS_ASSERT(reader.ReadLine(line));
2298  TS_ASSERT_EQUALS(" POINT 0 1.1 1.2 1.3", line);
2299  TS_ASSERT(reader.LineBeginsWith(" POINT 1 2.1 2.2 2.3"));
2300  TS_ASSERT(reader.ReadLine(line));
2301  TS_ASSERT_EQUALS(" POINT 1 2.1 2.2 2.3", line);
2302 } // DaReaderWriterIoUnitTests::testLineBeginsWith
2303 
2304 #endif
Class for reading ASCII files with named card fields. Also includes the ability to embed non-portable...
Definition: daStreamIo.h:35
T z
z coordinate
Definition: pt.h:799
void daWriteVecPt3d(std::ostream &a_outStream, const char *a_name, const VecPt3d &a_points)
Write a named vector of Pt3d to multiple lines.
#define XM_LOG(A, B)
Log message which can have a log type (Debug, Stackable, Gui).
Definition: XmLog.h:56
bool IsBinary() const
Are array values written as binary?
Definition: daStreamIo.cpp:734
bool daReadLine(std::istream &a_inStream, std::string &a_line)
Read a line from a stream with the following line endings: CR LF, LF, CR, or none.
Definition: daStreamIo.cpp:978
std::vector< int > VecInt
short rename
Definition: vector.h:27
bool daReadStringLine(std::istream &a_inStream, const char *a_name, std::string &a_val)
Read a named string value from a line.
void testReadWriteDoubleLine()
Test daWriteDoubleLine and daReadDoubleLine.
bool ReadString(std::string &a_val)
Read a white space separated string.
Definition: daStreamIo.cpp:634
void testReadNamedLine()
Test daReadNamedLine.
void daWriteLine(std::ostream &a_outStream, const std::string &a_line)
Write a given line to a stream.
void SetBinaryBlockSize(int a_blockSize)
Set the block size to use when writing binary arrays.
Definition: daStreamIo.cpp:955
void testReadStringFromLine()
Test ReadStringFromLine.
void Write3StringLine(const char *a_name, const std::string &a_val1, const std::string &a_val2, const std::string &a_val3)
Write a named triplet of words to a line.
Definition: daStreamIo.cpp:849
std::string STRstd(double a_value, int a_n, int width, int flags)
Get a properly formatted string from a double.
Definition: StringUtil.cpp:995
bool ReadVecDbl(const char *a_name, VecDbl &a_vec)
Read named vector of doubles from multiple lines.
Definition: daStreamIo.cpp:487
T x
x coordinate
Definition: pt.h:797
void daWriteDoubleLine(std::ostream &a_outStream, const char *a_name, double a_val)
Write a named double line value.
std::vector< double > VecDbl
short rename
Definition: vector.h:25
bool m_binaryArrays
Should binary arrays be read?
Definition: daStreamIo.cpp:66
void testReadWrite3StringLine()
Test daWrite3StringLine and daRead3StringLine.
void daWriteVecInt(std::ostream &a_outStream, const char *a_name, const VecInt &a_vec)
Write a named vector of integers to several lines.
std::istream & m_inStream
The input stream.
Definition: daStreamIo.cpp:65
bool daRead3DoubleLine(std::istream &a_inStream, const char *a_name, double &a_val1, double &a_val2, double &a_val3)
Read a named triplet of doubles from a line.
void AppendInts(const int *a_vals, int a_numVals)
Append a list of integer values to the end of a line of text.
Definition: daStreamIo.cpp:891
void daWriteIntLine(std::ostream &a_outStream, const char *a_name, int a_val)
Write a named integer value to a line.
void WriteIntLine(const char *a_name, int a_val)
Write a named integer value to a line.
Definition: daStreamIo.cpp:760
std::unique_ptr< Impl > m_impl
Implementation.
Definition: daStreamIo.h:74
bool ReadInt(int &a_val)
Read an integer value.
Definition: daStreamIo.cpp:644
void daWriteStringLine(std::ostream &a_outStream, const char *a_name, const std::string &a_val)
Write a named word line.
void testLineBeginsWith()
Test DaStreamReader::LineBeginsWith.
bool daReadVecDbl(std::istream &a_inStream, const char *a_name, VecDbl &a_vec)
Read named vector of doubles from multiple lines.
void testReadIntFromLine()
Test ReadIntFromLine.
bool daReadNamedLine(std::istream &a_inStream, const char *a_name)
Read a line that begins with a name.
Definition: daStreamIo.cpp:966
void testReadWriteBinaryArrays()
Test reading and writing a binary array.
When constructed std::cout will temporarily output 2-digit exponents for floating point numbers...
Definition: StringUtil.h:44
void Write2StringLine(const char *a_name, const std::string &a_val1, const std::string &a_val2)
Write a named pair of words to a line.
Definition: daStreamIo.cpp:836
void testReadWriteLine()
Test daWriteLine and daReadLine.
bool IsBinary() const
Are array values read as binary?
Definition: daStreamIo.cpp:370
void WriteStringLine(const char *a_name, const std::string &a_val)
Write a named word line.
Definition: daStreamIo.cpp:751
void testReadWriteIntLine()
Test WriteIntLine and ReadIntLine.
bool ReadIntLine(const char *a_name, int &a_val)
Read a named integer value from a line.
Definition: daStreamIo.cpp:435
bool ReadStringLine(const char *a_name, std::string &a_val)
Read a named string value from a line.
Definition: daStreamIo.cpp:455
bool daRead2StringLine(std::istream &a_inStream, const char *a_name, std::string &a_val1, std::string &a_val2)
Read a named pair of words from a line.
void testReadIntFromLine()
Test daReadIntFromLine.
void daWrite3StringLine(std::ostream &a_outStream, const char *a_name, const std::string &a_val1, const std::string &a_val2, const std::string &a_val3)
Write a named triplet of words to a line.
bool daReadVecInt(std::istream &a_inStream, const char *a_name, VecInt &a_vec)
Read named vector of integers from multiple lines.
void WriteDoubleLine(const char *a_name, double a_val)
Write a named double line value.
Definition: daStreamIo.cpp:769
static bool ReadDoubleFromLine(std::string &a_line, double &a_val)
Read a double value from a string. Return the remaining string.
Definition: daStreamIo.cpp:625
bool ReadLine(std::string &a_line)
Read a line from a stream with the following line endings: CR LF, LF, CR, or none.
Definition: daStreamIo.cpp:390
bool ReadDoubleLine(const char *a_name, double &a_val)
Read a named double value from a line.
Definition: daStreamIo.cpp:445
void testReadWrite2StringLine()
Test daWrite2StringLine and daRead2StringLine.
void testReadWriteStringLine()
Test daWriteStringLine and daReadStringLine.
void WriteString(const char *a_string)
Write a string value to the stream.
Definition: daStreamIo.cpp:874
void testReadWriteDoubleLine()
Test WriteDoubleLine and ReadDoubleLine.
void EndLine()
Add return to move to the next line of text.
Definition: daStreamIo.cpp:907
std::unique_ptr< Impl > m_impl
Implementation.
Definition: daStreamIo.h:117
bool daReadIntLine(std::istream &a_inStream, const char *a_name, int &a_val)
Read a named integer value from a line.
bool ReadVecInt(const char *a_name, VecInt &a_vec)
Read named vector of integers from multiple lines.
Definition: daStreamIo.cpp:465
void testReadWriteVecDbl()
Test daWriteVecDbl and daReadVecDbl.
void testReadNamedLine()
Test ReadNamedLine.
bool ReadNamedLine(const char *a_name)
Read a line that begins with a name.
Definition: daStreamIo.cpp:379
bool Read3DoubleLine(const char *a_name, double &a_val1, double &a_val2, double &a_val3)
Read a named triplet of doubles from a line.
Definition: daStreamIo.cpp:583
void testReadWriteVecPt3d()
Test WriteVecPt3d and ReadVecPt3d.
void testReadWrite2StringLine()
Test Write2StringLine and Read2StringLine.
void testReadWriteVecInt()
Test WriteVecInt and ReadVecInt.
void WriteLine(const std::string &a_line)
Write a given line to a stream.
Definition: daStreamIo.cpp:742
bool m_binaryArrays
Should binary arrays be written?
Definition: daStreamIo.cpp:85
bool daReadDoubleLine(std::istream &a_inStream, const char *a_name, double &a_val)
Read a named double value from a line.
void testReadWriteLineParts()
Test function that read and write parts of a line.
Implementation for DaStreamReader.
Definition: daStreamIo.cpp:53
void testReadWriteIntLine()
Test daWriteIntLine and daReadIntLine.
bool daLineBeginsWith(std::istream &a_inStream, const std::string &a_text)
Determines if next line read will begin given text.
void testReadWriteBinaryVecDbl()
Test binary WriteVecDbl and binary ReadVecDbl.
bool daReadStringFromLine(std::string &a_line, std::string &a_val)
Read a string value from a string. Return the remaining string.
void testReadDoubleFromLine()
Test daReadDoubleFromLine.
void AppendString(const std::string &a_val)
Append a string to the end of a line of text.
Definition: daStreamIo.cpp:900
bool ReadBinaryBytes(char *a_dest, long long a_destLength)
Read binary bytes of a given length from a file.
Definition: daStreamIo.cpp:665
static bool ReadIntFromLine(std::string &a_line, int &a_val)
Read an integer value from a string. Return the remaining string.
Definition: daStreamIo.cpp:596
void Write3DoubleLine(const char *a_name, const double &a_val1, const double &a_val2, const double &a_val3)
Write a named triplet of doubles to a line.
Definition: daStreamIo.cpp:863
bool Read3StringLine(const char *a_name, std::string &a_val1, std::string &a_val2, std::string &a_val3)
Read a named triplet of words from a line.
Definition: daStreamIo.cpp:568
void WriteVecInt(const char *a_name, const VecInt &a_vec)
Write a named vector of integers to several lines.
Definition: daStreamIo.cpp:778
void daWrite3DoubleLine(std::ostream &a_outStream, const char *a_name, const double &a_val1, const double &a_val2, const double &a_val3)
Write a named triplet of doubles to a line.
void testReadWriteVecPt3d()
Test daWriteVecPt3d and daReadVecPt3d.
~DaStreamWriter()
Destructor.
Definition: daStreamIo.cpp:727
3d point template class
Definition: pt.h:791
DaStreamReader(std::istream &a_inStream, bool a_binaryArrays=false)
Constructor.
Definition: daStreamIo.cpp:356
bool LineBeginsWith(const char *a_text)
Determines if next line read will begin given text.
Definition: daStreamIo.cpp:704
void daWriteNamedLine(std::ostream &a_outStream, const char *a_name)
Write a given line to a stream.
void testLineBeginsWith()
Test DaStreamReader::LineBeginsWith.
void WriteVecPt3d(const char *a_name, const VecPt3d &a_points)
Write a named vector of Pt3d to multiple lines.
Definition: daStreamIo.cpp:816
void AppendInt(int a_val)
Append an integer value to the end of a line of text.
Definition: daStreamIo.cpp:882
std::ostream & m_outStream
The output stream.
Definition: daStreamIo.cpp:84
void testReadWriteBinaryVecInt()
Test binary WriteVecInt and binary ReadVecInt.
T y
y coordinate
Definition: pt.h:798
void testReadWriteLine()
Test WriteLine and ReadLine.
void testReadWriteBinaryVecPt3d()
Test binary WriteVecPt3d and binary ReadVecPt3d.
static bool ReadStringFromLine(std::string &a_line, std::string &a_val)
Read a string value from a string. Return the remaining string.
Definition: daStreamIo.cpp:606
void testReadWrite3DoubleLine()
Test daWrite3DoubleLine and daRead3DoubleLine.
Impl(std::istream &a_inStream, bool a_binaryArrays)
Definition: daStreamIo.cpp:59
DaStreamWriter(std::ostream &a_outStream, bool a_binaryArrays=false)
Constructor.
Definition: daStreamIo.cpp:720
Implementation for DaStreamWriter.
Definition: daStreamIo.cpp:72
void testReadWrite3DoubleLine()
Test Write3DoubleLine and Read3DoubleLine.
bool ReadVecPt3d(const char *a_name, VecPt3d &a_vec)
Read named vector of Pt3d from multiple lines.
Definition: daStreamIo.cpp:509
bool WriteBinaryBytes(const char *a_source, long long a_sourceLength)
Write binary bytes of a given length to the stream.
Definition: daStreamIo.cpp:917
void daWriteVecDbl(std::ostream &a_outStream, const char *a_name, const VecDbl &a_vec)
Write a named vector of doubles to multiple lines.
void testReadStringFromLine()
Test daReadStringFromLine.
Functions and macros for assertion and checking for errors.
Routines for creating and writing to logs and stacking errors.
void testReadWriteVecDbl()
Test WriteVecDbl and ReadVecDbl.
Impl(std::ostream &a_outStream, bool a_binaryArrays)
Definition: daStreamIo.cpp:78
void testReadWriteVecInt()
Test daWriteVecInt and daReadVecInt.
void testReadDoubleFromLine()
Test ReadDoubleFromLine.
bool daRead3StringLine(std::istream &a_inStream, const char *a_name, std::string &a_val1, std::string &a_val2, std::string &a_val3)
Read a named triplet of words from a line.
bool NextLine()
Go to the next line in the stream.
Definition: daStreamIo.cpp:653
bool daReadDoubleFromLine(std::string &a_line, double &a_val)
Read a double value from a string. Return the remaining string.
void WriteVecDbl(const char *a_name, const VecDbl &a_vec)
Write a named vector of doubles to multiple lines.
Definition: daStreamIo.cpp:797
Class for writing ASCII files with named card fields. Also includes the ability to embed non-portable...
Definition: daStreamIo.h:79
bool daReadVecPt3d(std::istream &a_inStream, const char *a_name, VecPt3d &a_vec)
Read named vector of Pt3d from multiple lines.
bool Read2StringLine(const char *a_name, std::string &a_val1, std::string &a_val2)
Read a named pair of words from a line.
Definition: daStreamIo.cpp:556
Critical error message for the user.
Definition: XmLog.h:81
void testReadWriteStringLine()
Test WriteStringLine and ReadStringLine.
~DaStreamReader()
Destructor.
Definition: daStreamIo.cpp:363
void testReadWrite3StringLine()
Test Write3StringLine and Read3StringLine.
void daWrite2StringLine(std::ostream &a_outStream, const char *a_name, const std::string &a_val1, const std::string &a_val2)
Write a named pair of words to a line.
bool daReadIntFromLine(std::string &a_line, int &a_val)
Read an integer value from a string. Return the remaining string.
std::vector< Pt3d > VecPt3d
short rename
Definition: vector.h:51