From d35054efd1dadbfa13a6bc2c2a275663ebfa91d6 Mon Sep 17 00:00:00 2001
From: theazgra <theazgra@gmail.com>
Date: Wed, 30 Jan 2019 13:19:43 +0100
Subject: [PATCH] Switched to custom assert, which is firing even in Release
 mode.

---
 czi-format/Links to Download.txt              |  14 +--
 czi-format/czi-parser/CMakeLists.txt          |   4 +-
 czi-format/czi-parser/always_on_assert.h      |  71 ++++++++++++
 czi-format/czi-parser/binary_converter.cpp    |  20 ++--
 czi-format/czi-parser/binary_converter.h      |   1 -
 czi-format/czi-parser/binary_stream.cpp       |  42 ++++----
 czi-format/czi-parser/binary_stream.h         |   4 +-
 czi-format/czi-parser/custom_types.h          |   2 +-
 czi-format/czi-parser/czi_file.cpp            |  24 +++--
 czi-format/czi-parser/czi_parser.cpp          |  41 +++----
 .../czi_parts/attachment_directory_segment.h  |   2 +-
 .../czi-parser/czi_parts/directory_entry_dv.h |   2 +-
 .../czi_parts/subblock_directory_segment.h    |   2 +-
 czi-format/czi-parser/file_system.h           | 102 ++++++++++++++++++
 czi-format/czi-parser/image_writer.h          |   3 +-
 czi-format/czi-parser/main.cpp                |   7 ++
 16 files changed, 266 insertions(+), 75 deletions(-)
 create mode 100644 czi-format/czi-parser/always_on_assert.h
 create mode 100644 czi-format/czi-parser/file_system.h

diff --git a/czi-format/Links to Download.txt b/czi-format/Links to Download.txt
index 6d11afe..bc4196e 100644
--- a/czi-format/Links to Download.txt	
+++ b/czi-format/Links to Download.txt	
@@ -1,10 +1,10 @@
 Basic testing
 -------------
-http://czisamples.blob.core.windows.net/czi-samples/TESTIMAGES.zip
+X	http://czisamples.blob.core.windows.net/czi-samples/TESTIMAGES.zip
 
 Advanced testing
 ----------------
-http://czisamples.blob.core.windows.net/czi-samples/Legend.txt
+X	http://czisamples.blob.core.windows.net/czi-samples/Legend.txt
 
 http://czisamples.blob.core.windows.net/czi-samples/ApoTome/40x075_Artemia-Flash-AT-1Ch-Z-sect.czi
 http://czisamples.blob.core.windows.net/czi-samples/ApoTome/40x14_GMMe_AT-4ch-Z_Dapi-Vimentin488_Phalloidine568-Lamin647(WF).czi
@@ -20,17 +20,17 @@ http://czisamples.blob.core.windows.net/czi-samples/ApoTome/Kidney-FS44_FS45_Apo
 http://czisamples.blob.core.windows.net/czi-samples/ApoTome/Kidney-FS44_FS45_ApoTome_2ch_raw_Tiles.czi
 http://czisamples.blob.core.windows.net/czi-samples/ApoTome/Kidney-FS44_FS45_ApoTome_2ch_sect_Tiles-stitched.czi
 http://czisamples.blob.core.windows.net/czi-samples/Axio Scan.Z1/20x_HE.czi
-http://czisamples.blob.core.windows.net/czi-samples/Axio Scan.Z1/Intestine_3color_RAC.czi
+X	http://czisamples.blob.core.windows.net/czi-samples/Axio Scan.Z1/Intestine_3color_RAC.czi
 http://czisamples.blob.core.windows.net/czi-samples/Axio Scan.Z1/Kidney_40x_z_stack.czi
 http://czisamples.blob.core.windows.net/czi-samples/Axio Scan.Z1/Kidney_RAC_3color.czi
 http://czisamples.blob.core.windows.net/czi-samples/Axio Scan.Z1/Young_mouse.czi
-http://czisamples.blob.core.windows.net/czi-samples/CellObserver SD/EB3-microtubules-GFP_H2BmCherry_2chT(SD).czi
+X	http://czisamples.blob.core.windows.net/czi-samples/CellObserver SD/EB3-microtubules-GFP_H2BmCherry_2chT(SD).czi
 http://czisamples.blob.core.windows.net/czi-samples/CellObserver SD/LLC-PK1_2chTZ-triggered-20msec(SD).czi
 http://czisamples.blob.core.windows.net/czi-samples/CellObserver SD/LLC-PK1_TubX-emerald_H2B-mCherry-2chZ(SD).czi
 http://czisamples.blob.core.windows.net/czi-samples/CellObserver SD/Micrasterias fimbriata#1_2chTZ(SD).czi
 http://czisamples.blob.core.windows.net/czi-samples/Multiscene/Mouse-kidney-3-scene_VivaTome_1chZS.czi
 http://czisamples.blob.core.windows.net/czi-samples/Tiles/Mouse_stomach_20x_ROI_3chZTiles(WF).czi
 http://czisamples.blob.core.windows.net/czi-samples/VivaTome/Mouse_kidney_VivaTome-1chTZ.czi
-http://czisamples.blob.core.windows.net/czi-samples/Widefield/BPAE-Cells_63x_oversampled-3chZ(WF).czi
-http://czisamples.blob.core.windows.net/czi-samples/Widefield/BPAE-cells-bin2x2_3chTZ(WF).czi
-http://czisamples.blob.core.windows.net/czi-samples/Widefield/BPAE-cells_mitosis_3chZ(WF).czi
+X	http://czisamples.blob.core.windows.net/czi-samples/Widefield/BPAE-Cells_63x_oversampled-3chZ(WF).czi
+X	http://czisamples.blob.core.windows.net/czi-samples/Widefield/BPAE-cells-bin2x2_3chTZ(WF).czi
+X	http://czisamples.blob.core.windows.net/czi-samples/Widefield/BPAE-cells_mitosis_3chZ(WF).czi
diff --git a/czi-format/czi-parser/CMakeLists.txt b/czi-format/czi-parser/CMakeLists.txt
index 146bed2..f9ee73e 100644
--- a/czi-format/czi-parser/CMakeLists.txt
+++ b/czi-format/czi-parser/CMakeLists.txt
@@ -6,10 +6,12 @@ enable_testing()
 
 add_executable(czi-parser main.cpp)
 
+set(CMAKE_CXX_FLAGS "-Wall")
+
 # set(Boost_USE_STATIC_LIBS OFF) 
 set(Boost_USE_MULTITHREADED ON)  
 set(Boost_USE_STATIC_RUNTIME OFF) 
-find_package(Boost REQUIRED COMPONENTS locale)
+find_package(Boost REQUIRED COMPONENTS filesystem locale)
 if(Boost_FOUND)
     include_directories(${Boost_INCLUDE_DIRS}) 
     target_link_libraries(czi-parser ${Boost_LIBRARIES})
diff --git a/czi-format/czi-parser/always_on_assert.h b/czi-format/czi-parser/always_on_assert.h
new file mode 100644
index 0000000..df1bfbc
--- /dev/null
+++ b/czi-format/czi-parser/always_on_assert.h
@@ -0,0 +1,71 @@
+/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/*
+ *	ISO C99 Standard: 7.2 Diagnostics	<assert.h> 
+ */
+
+/*
+    Moravec:
+        Always enabled assert.
+*/
+
+#define _ASSERT_H 1
+#include <features.h>
+
+#ifndef _ASSERT_H_DECLS
+#define _ASSERT_H_DECLS
+__BEGIN_DECLS
+
+/* This prints an "assertion failed" message and aborts.  */
+extern void __assert_fail(const char *__assertion, const char *__file,
+                          unsigned int __line, const char *__function)
+    __THROW __attribute__((__noreturn__));
+
+/* Likewise, but prints the error text for ERRNUM.  */
+extern void __assert_perror_fail(int __errnum, const char *__file,
+                                 unsigned int __line, const char *__function)
+    __THROW __attribute__((__noreturn__));
+
+/* The following is not at all used here but needed for standard
+   compliance.  */
+extern void __assert(const char *__assertion, const char *__file, int __line)
+    __THROW __attribute__((__noreturn__));
+
+__END_DECLS
+#endif /* Not _assert_H_DECLS */
+
+#if defined __cplusplus ? __GNUC_PREREQ(2, 6) : __GNUC_PREREQ(2, 4)
+#define __assert_FUNCTION __extension__ __PRETTY_FUNCTION__
+#else
+#if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L
+#define __assert_FUNCTION __func__
+#else
+#define __assert_FUNCTION ((const char *)0)
+#endif
+#endif
+
+#if defined __cplusplus
+#define always_assert(expr)  \
+    (static_cast<bool>(expr) \
+         ? void(0)           \
+         : __assert_fail(#expr, __FILE__, __LINE__, __assert_FUNCTION))
+#endif
+#if defined __USE_ISOC11 && !defined __cplusplus
+#undef static_assert
+#define static_assert _Static_assert
+#endif
\ No newline at end of file
diff --git a/czi-format/czi-parser/binary_converter.cpp b/czi-format/czi-parser/binary_converter.cpp
index 5ab47db..e553999 100644
--- a/czi-format/czi-parser/binary_converter.cpp
+++ b/czi-format/czi-parser/binary_converter.cpp
@@ -6,8 +6,8 @@
 #include "binary_converter.h"
 short bytes_to_short(const std::vector<byte> &bytes, const uint fromIndex)
 {
-    assert(bytes.size() >= 2);
-    assert(fromIndex <= bytes.size() - 2);
+    always_assert(bytes.size() >= 2);
+    always_assert(fromIndex <= bytes.size() - 2);
 
     // Little endian
     auto bit = &bytes[fromIndex];
@@ -24,8 +24,8 @@ short bytes_to_short(const std::vector<byte> &bytes, const uint fromIndex)
 
 int bytes_to_int(const std::vector<byte> &bytes, const uint fromIndex)
 {
-    assert(bytes.size() >= 4);
-    assert(fromIndex <= bytes.size() - 4);
+    always_assert(bytes.size() >= 4);
+    always_assert(fromIndex <= bytes.size() - 4);
 
     // Little endian
     auto bit = &bytes[fromIndex];
@@ -42,8 +42,8 @@ int bytes_to_int(const std::vector<byte> &bytes, const uint fromIndex)
 
 int bytes_to_long(const std::vector<byte> &bytes, const uint fromIndex)
 {
-    assert(bytes.size() >= 8);
-    assert(fromIndex <= bytes.size() - 8);
+    always_assert(bytes.size() >= 8);
+    always_assert(fromIndex <= bytes.size() - 8);
 
     // Little endian
     auto bit = &bytes[fromIndex];
@@ -61,8 +61,8 @@ int bytes_to_long(const std::vector<byte> &bytes, const uint fromIndex)
 
 float bytes_to_float(const std::vector<byte> &bytes, const uint fromIndex)
 {
-    assert(bytes.size() >= 4);
-    assert(fromIndex <= bytes.size() - 4);
+    always_assert(bytes.size() >= 4);
+    always_assert(fromIndex <= bytes.size() - 4);
 
     float result;
     memcpy(&result, (bytes.data() + fromIndex), 4);
@@ -71,8 +71,8 @@ float bytes_to_float(const std::vector<byte> &bytes, const uint fromIndex)
 
 double bytes_to_double(const std::vector<byte> &bytes, const uint fromIndex)
 {
-    assert(bytes.size() >= 8);
-    assert(fromIndex <= bytes.size() - 8);
+    always_assert(bytes.size() >= 8);
+    always_assert(fromIndex <= bytes.size() - 8);
 
     double result;
     memcpy(&result, (bytes.data() + fromIndex), 8);
diff --git a/czi-format/czi-parser/binary_converter.h b/czi-format/czi-parser/binary_converter.h
index 8ab95aa..d99112e 100644
--- a/czi-format/czi-parser/binary_converter.h
+++ b/czi-format/czi-parser/binary_converter.h
@@ -10,7 +10,6 @@
 * EVERY CONVERSION DONE HERE WORKS ONLY WITH LITTLE ENDIAN AT THIS MOMENT!
 */
 
-#include <assert.h>
 #include "custom_types.h"
 #include <string>
 
diff --git a/czi-format/czi-parser/binary_stream.cpp b/czi-format/czi-parser/binary_stream.cpp
index 1bc86e5..a0a9d40 100644
--- a/czi-format/czi-parser/binary_stream.cpp
+++ b/czi-format/czi-parser/binary_stream.cpp
@@ -14,10 +14,10 @@ BinaryStream::BinaryStream(const std::string &file)
 
 void BinaryStream::open_stream(const std::string &file)
 {
-    assert(!this->isOpen);
+    always_assert(!this->isOpen);
 
     this->fileStream = std::ifstream(file, std::ios::binary | std::ios::in | std::ios::ate);
-    assert(this->fileStream.is_open());
+    always_assert(this->fileStream.is_open());
 
     this->isOpen = true;
 
@@ -42,37 +42,37 @@ BinaryStream::~BinaryStream()
 
 long BinaryStream::get_size() const
 {
-    assert(this->isOpen);
+    always_assert(this->isOpen);
     return this->fileSize;
 }
 
 long BinaryStream::get_position()
 {
-    assert(this->isOpen);
+    always_assert(this->isOpen);
     return (long)(this->fileStream.tellg());
 }
 
 void BinaryStream::move_to(const long position)
 {
-    assert(this->isOpen);
+    always_assert(this->isOpen);
     this->fileStream.seekg(position);
 }
 
 void BinaryStream::move_to_beginning()
 {
-    assert(this->isOpen);
+    always_assert(this->isOpen);
     this->fileStream.seekg(std::ios::beg);
 }
 
 void BinaryStream::move_to_end()
 {
-    assert(this->isOpen);
+    always_assert(this->isOpen);
     this->fileStream.seekg(std::ios::end);
 }
 
 void BinaryStream::move_by(const long distance)
 {
-    assert(this->isOpen);
+    always_assert(this->isOpen);
     auto currentPosition = this->fileStream.tellg();
     auto requiredPosition = currentPosition + distance;
     this->fileStream.seekg(requiredPosition);
@@ -80,16 +80,16 @@ void BinaryStream::move_by(const long distance)
 
 byte BinaryStream::consume_byte()
 {
-    assert(this->isOpen);
+    always_assert(this->isOpen);
     char readedChar;
     this->fileStream.read(&readedChar, 1);
     byte result = (byte)readedChar;
     return result;
 }
 
-bool BinaryStream::consume_bool(const short byteCount)
+bool BinaryStream::consume_bool(const ushort byteCount)
 {
-    assert(this->isOpen);
+    always_assert(this->isOpen);
     auto bytes = consume_bytes(byteCount);
     int sum = 0;
 
@@ -101,37 +101,37 @@ bool BinaryStream::consume_bool(const short byteCount)
 
 short BinaryStream::consume_short()
 {
-    assert(this->isOpen);
+    always_assert(this->isOpen);
     return bytes_to_short(consume_bytes(2));
 }
 
 int BinaryStream::consume_int()
 {
-    assert(this->isOpen);
+    always_assert(this->isOpen);
     return bytes_to_int(consume_bytes(4));
 }
 
 long BinaryStream::consume_long()
 {
-    assert(this->isOpen);
+    always_assert(this->isOpen);
     return bytes_to_long(consume_bytes(8));
 }
 
 float BinaryStream::consume_float()
 {
-    assert(this->isOpen);
+    always_assert(this->isOpen);
     return bytes_to_float(consume_bytes(4));
 }
 
 double BinaryStream::consume_double()
 {
-    assert(this->isOpen);
+    always_assert(this->isOpen);
     return bytes_to_double(consume_bytes(8));
 }
 
 std::vector<byte> BinaryStream::consume_whole_file()
 {
-    assert(this->isOpen);
+    always_assert(this->isOpen);
     std::vector<byte> result;
     this->fileStream.seekg(std::ios::beg);
     result.insert(result.begin(), std::istream_iterator<byte>(this->fileStream), std::istream_iterator<byte>());
@@ -140,15 +140,15 @@ std::vector<byte> BinaryStream::consume_whole_file()
 
 std::vector<byte> BinaryStream::consume_rest_of_file()
 {
-    assert(this->isOpen);
+    always_assert(this->isOpen);
     std::vector<byte> result;
     result.insert(result.begin(), std::istream_iterator<byte>(this->fileStream), std::istream_iterator<byte>());
     return result;
 }
 
-std::vector<byte> BinaryStream::consume_bytes(const long byteCount)
+std::vector<byte> BinaryStream::consume_bytes(const ulong byteCount)
 {
-    assert(this->isOpen);
+    always_assert(this->isOpen);
 
     //TODO: Can this be made faster?
     std::vector<byte> result;
@@ -170,7 +170,7 @@ std::vector<byte> BinaryStream::consume_bytes(const long byteCount)
 
 std::vector<byte> BinaryStream::move_and_consume_bytes(const long position, const long byteCount)
 {
-    assert(this->isOpen);
+    always_assert(this->isOpen);
     move_to(position);
     return consume_bytes(byteCount);
 }
\ No newline at end of file
diff --git a/czi-format/czi-parser/binary_stream.h b/czi-format/czi-parser/binary_stream.h
index 5bf281f..9a92d51 100644
--- a/czi-format/czi-parser/binary_stream.h
+++ b/czi-format/czi-parser/binary_stream.h
@@ -38,7 +38,7 @@ public:
   // Read one byte.
   byte consume_byte();
   // Read specified number of bytes are converts them into bool.
-  bool consume_bool(const short byteCount);
+  bool consume_bool(const ushort byteCount);
   // Read two bytes and converts them into short.
   short consume_short();
   // Read four bytes and converts them into int.
@@ -55,7 +55,7 @@ public:
   // Read rest of the file, from current position to end, into memory.
   std::vector<byte> consume_rest_of_file();
   // Read specified number of bytes.
-  std::vector<byte> consume_bytes(const long byteCount);
+  std::vector<byte> consume_bytes(const ulong byteCount);
   // Move file stream to requested position and read specified number of bytes.
   std::vector<byte> move_and_consume_bytes(const long position, const long byteCount);
 };
diff --git a/czi-format/czi-parser/custom_types.h b/czi-format/czi-parser/custom_types.h
index ee6df34..e064b54 100644
--- a/czi-format/czi-parser/custom_types.h
+++ b/czi-format/czi-parser/custom_types.h
@@ -4,7 +4,7 @@
 #define VERBOSE_PARSER 0
 
 #include <vector>
-#include <assert.h>
+#include "always_on_assert.h"
 
 constexpr bool NOT_IMPLEMENTED_YET = false;
 
diff --git a/czi-format/czi-parser/czi_file.cpp b/czi-format/czi-parser/czi_file.cpp
index 7bcb35d..d183a10 100644
--- a/czi-format/czi-parser/czi_file.cpp
+++ b/czi-format/czi-parser/czi_file.cpp
@@ -42,9 +42,11 @@ const char *pixel_type_str(const PixelType px)
     case PixelType::Gray64:
         return "Gray64";
     default:
-        assert("Bad pixel type." && false);
+        always_assert("Bad pixel type." && false);
         break;
     }
+
+    return nullptr;
 }
 
 const char *pyramid_type_str(const PyramidType pt)
@@ -60,10 +62,11 @@ const char *pyramid_type_str(const PyramidType pt)
         break;
     default:
     {
-        assert("Bad pyramid type." && false);
+        always_assert("Bad pyramid type." && false);
         break;
     }
     }
+    return nullptr;
 }
 
 const char *compression_type_str(const CompressionType ct)
@@ -85,10 +88,11 @@ const char *compression_type_str(const CompressionType ct)
         break;
     default:
     {
-        assert("Bad compression type." && false);
+        always_assert("Bad compression type." && false);
         break;
     }
     }
+    return nullptr;
 }
 
 const char *dimension_type_str(const Dimension d)
@@ -123,10 +127,11 @@ const char *dimension_type_str(const Dimension d)
         break;
     default:
     {
-        assert("Bad dimension type." && false);
+        always_assert("Bad dimension type." && false);
         break;
     }
     }
+    return nullptr;
 }
 
 void CziFile::report_verbose() const
@@ -198,7 +203,10 @@ void CziFile::report() const
     printf("%-25s %15i\n", "SubBlockCount", subBlockDirectory.entryCount);
 
     if (subBlockDirectory.entryCount > 0)
+    {
         printf("%-25s %15i\n", "DimensionCount", subBlockDirectory.entries[0].dimensionCount);
+        printf("%-25s %15s\n", "PixelType", pixel_type_str(subBlockDirectory.entries[0].pixelType));
+    }
 
     printf("%-25s %15i\n", "AttachmentCount", attachmentDirectory.entryCount);
 
@@ -211,10 +219,10 @@ void CziFile::extract_images(const std::string &baseName) const
     int imageIndex = 0;
     for (const DirectoryEntryDV &entry : subBlockDirectory.entries)
     {
-        assert(entry.width > 0 && entry.height > 0);
+        always_assert(entry.width > 0 && entry.height > 0);
 
         auto imageBytes = cziStream.move_and_consume_bytes(entry.subBlock.dataLocation, entry.subBlock.dataSize);
-        std::string imageFileName = baseName + std::to_string(imageIndex++) + ".bpm";
+        std::string imageFileName = baseName + std::to_string(imageIndex++) + ".pnm";
         create_image_file(imageFileName.c_str(), imageBytes, entry.pixelType, entry.width, entry.height);
     }
 }
@@ -225,12 +233,12 @@ void CziFile::dump_image_data(const std::string &baseName) const
     int imageIndex = 0;
     for (const DirectoryEntryDV &entry : subBlockDirectory.entries)
     {
-        assert(entry.width > 0 && entry.height > 0);
+        always_assert(entry.width > 0 && entry.height > 0);
         auto imageBytes = cziStream.move_and_consume_bytes(entry.subBlock.dataLocation, entry.subBlock.dataSize);
         std::string binaryFileName = baseName + std::to_string(imageIndex++) + ".bin";
 
         std::ofstream binaryStream(binaryFileName, std::ios::binary | std::ios::out);
-        assert(binaryStream.is_open());
+        always_assert(binaryStream.is_open());
         binaryStream.write(reinterpret_cast<const char *>(imageBytes.data()), imageBytes.size());
         printf("Wrote %s\n", binaryFileName.c_str());
     }
diff --git a/czi-format/czi-parser/czi_parser.cpp b/czi-format/czi-parser/czi_parser.cpp
index 3286dd7..6d34c83 100644
--- a/czi-format/czi-parser/czi_parser.cpp
+++ b/czi-format/czi-parser/czi_parser.cpp
@@ -21,8 +21,9 @@ CziFile CziParser::parse_czi_file(const std::string &file)
 
     for (size_t subBlockId = 0; subBlockId < parsedFile.subBlockDirectory.entryCount; subBlockId++)
     {
+
         int filePart = parsedFile.subBlockDirectory.entries[subBlockId].filePart;
-        assert(filePart == 0 && "We are currently supporting only single-file scenario.");
+        always_assert(filePart == 0 && "We are currently supporting only single-file scenario.");
         long subBlockPosition = parsedFile.subBlockDirectory.entries[subBlockId].filePosition;
         int entrySize = parsedFile.subBlockDirectory.entries[subBlockId].entrySize;
 
@@ -62,7 +63,7 @@ FileHeaderSegment CziParser::parse_file_header(BinaryStream &cziStream)
 {
     FileHeaderSegment result;
     result.header = parse_segment_header(cziStream);
-    assert(result.header.sId == FileHeaderSegmentSID);
+    always_assert(result.header.sId == FileHeaderSegmentSID);
 
     result.fileVersion = {};
     result.fileVersion.major = cziStream.consume_int();
@@ -88,12 +89,12 @@ FileHeaderSegment CziParser::parse_file_header(BinaryStream &cziStream)
 
 MetadataSegment CziParser::parse_metadata(BinaryStream &cziStream, const long position)
 {
-    assert(position > 0);
+    always_assert(position > 0);
     cziStream.move_to(position);
 
     MetadataSegment result = {};
     result.header = parse_segment_header(cziStream);
-    assert(result.header.sId == MetadataSegmentSID);
+    always_assert(result.header.sId == MetadataSegmentSID);
 
     result.xmlSize = cziStream.consume_int();
     result.attachmentSize = cziStream.consume_int();
@@ -114,12 +115,12 @@ MetadataSegment CziParser::parse_metadata(BinaryStream &cziStream, const long po
 
 SubBlockDirectorySegment CziParser::parse_subblock_directory(BinaryStream &cziStream, const long position)
 {
-    assert(position > 0);
+    always_assert(position > 0);
     cziStream.move_to(position);
 
     SubBlockDirectorySegment result = {};
     result.header = parse_segment_header(cziStream);
-    assert(result.header.sId == SubBlockDirectorySegmentSID);
+    always_assert(result.header.sId == SubBlockDirectorySegmentSID);
 
     result.entryCount = cziStream.consume_int();
     // 124 B are reserved, skipping.
@@ -143,7 +144,7 @@ DirectoryEntryDV CziParser::parse_subblock_directory_entry(BinaryStream &cziStre
 
     result.schemaType = cziStream.consume_bytes(2);
 
-    assert(result.schemaType.size() == 2 && result.schemaType[0] == 'D' && result.schemaType[1] == 'V');
+    always_assert(result.schemaType.size() == 2 && result.schemaType[0] == 'D' && result.schemaType[1] == 'V');
 
     result.pixelType = to_pixel_type(cziStream.consume_int());
     result.filePosition = cziStream.consume_long();
@@ -155,7 +156,7 @@ DirectoryEntryDV CziParser::parse_subblock_directory_entry(BinaryStream &cziStre
     cziStream.move_by(5);
 
     result.dimensionCount = cziStream.consume_int();
-    assert(result.dimensionCount > 0);
+    always_assert(result.dimensionCount > 0);
     result.dimensions.reserve(result.dimensionCount);
 
     for (size_t dim = 0; dim < result.dimensionCount; dim++)
@@ -179,12 +180,12 @@ DirectoryEntryDV CziParser::parse_subblock_directory_entry(BinaryStream &cziStre
 
 AttachmentDirectorySegment CziParser::parse_attachment_directory(BinaryStream &cziStream, const long position)
 {
-    assert(position > 0);
+    always_assert(position > 0);
     cziStream.move_to(position);
 
     AttachmentDirectorySegment result = {};
     result.header = parse_segment_header(cziStream);
-    assert(result.header.sId == AttachmentDirectorySegmentSID);
+    always_assert(result.header.sId == AttachmentDirectorySegmentSID);
 
     result.entryCount = cziStream.consume_int();
 
@@ -208,7 +209,7 @@ AttachmentEntryA1 CziParser::parse_attachment_entry(BinaryStream &cziStream)
 {
     AttachmentEntryA1 result = {};
     result.schemaType = cziStream.consume_bytes(2);
-    assert(result.schemaType.size() == 2 && result.schemaType[0] == 'A' && result.schemaType[1] == '1');
+    always_assert(result.schemaType.size() == 2 && result.schemaType[0] == 'A' && result.schemaType[1] == '1');
 
     // Next 10 bytes are reserved.
     cziStream.move_by(10);
@@ -248,12 +249,12 @@ DimensionEntryDV1 CziParser::parse_dimension_entry(BinaryStream &cziStream)
 
 SubBlockSegment CziParser::parse_subblock(BinaryStream &cziStream, const long position, const int entryIndex, const int entrySize)
 {
-    assert(position > 0);
+    always_assert(position > 0);
     cziStream.move_to(position);
 
     SubBlockSegment result = {};
     result.header = parse_segment_header(cziStream);
-    assert(result.header.sId == SubBlockSegmentSID);
+    always_assert(result.header.sId == SubBlockSegmentSID);
 
     result.metadataSize = cziStream.consume_int();
     result.attachmentSize = cziStream.consume_int();
@@ -288,13 +289,13 @@ SubBlockSegment CziParser::parse_subblock(BinaryStream &cziStream, const long po
 
 AttachmentSegment CziParser::parse_attachment_segment(BinaryStream &cziStream, const long position, const int entryIndex)
 {
-    assert(position > 0);
+    always_assert(position > 0);
     cziStream.move_to(position);
 
     AttachmentSegment result = {};
     result.directoryEntryIndex = entryIndex;
     result.header = parse_segment_header(cziStream);
-    assert(result.header.sId == AttachmentSegmentSID);
+    always_assert(result.header.sId == AttachmentSegmentSID);
 
     result.dataSize = cziStream.consume_int();
     // 12 B reserved next 128 B are for AttachmentEntry which is saved under 'entryIndex' in
@@ -331,7 +332,7 @@ PixelType CziParser::to_pixel_type(const int value)
         break;
     }
     default:
-        assert("Bad pixel type." && false);
+        always_assert("Bad pixel type." && false);
         break;
     }
     return result;
@@ -348,7 +349,7 @@ PyramidType CziParser::to_pyramid_type(const byte value)
         break;
     default:
     {
-        assert("Bad pyramid type." && false);
+        always_assert("Bad pyramid type." && false);
         break;
     }
     }
@@ -369,7 +370,7 @@ CompressionType CziParser::to_compression_type(const int value)
         break;
     default:
     {
-        assert("Bad compression type." && false);
+        always_assert("Bad compression type." && false);
         break;
     }
     }
@@ -378,7 +379,7 @@ CompressionType CziParser::to_compression_type(const int value)
 
 Dimension CziParser::to_dimension_type(const std::vector<byte> &bytes)
 {
-    assert(bytes.size() == 4);
+    always_assert(bytes.size() == 4);
     Dimension result = static_cast<Dimension>((char)bytes[0]);
     switch (result)
     {
@@ -397,7 +398,7 @@ Dimension CziParser::to_dimension_type(const std::vector<byte> &bytes)
         break;
     default:
     {
-        assert("Bad dimension type." && false);
+        always_assert("Bad dimension type." && false);
         break;
     }
     }
diff --git a/czi-format/czi-parser/czi_parts/attachment_directory_segment.h b/czi-format/czi-parser/czi_parts/attachment_directory_segment.h
index 2b80d34..5b9bd9c 100644
--- a/czi-format/czi-parser/czi_parts/attachment_directory_segment.h
+++ b/czi-format/czi-parser/czi_parts/attachment_directory_segment.h
@@ -9,7 +9,7 @@ struct AttachmentDirectorySegment
     // Segment header of attachment directory.
     SegmentHeader header;
     // Number of entries in directory.
-    int entryCount;
+    uint entryCount;
     // Attachment directory entries.
     std::vector<AttachmentEntryA1> entries;
 };
diff --git a/czi-format/czi-parser/czi_parts/directory_entry_dv.h b/czi-format/czi-parser/czi_parts/directory_entry_dv.h
index 15ae296..ad1c25a 100644
--- a/czi-format/czi-parser/czi_parts/directory_entry_dv.h
+++ b/czi-format/czi-parser/czi_parts/directory_entry_dv.h
@@ -20,7 +20,7 @@ struct DirectoryEntryDV
     // Type of image pyramid.
     PyramidType pyramidType;
     // Number of dimension entries. Minimally one.
-    int dimensionCount;
+    uint dimensionCount;
     // Dimensions.
     std::vector<DimensionEntryDV1> dimensions;
     // Referenced SubBlock.
diff --git a/czi-format/czi-parser/czi_parts/subblock_directory_segment.h b/czi-format/czi-parser/czi_parts/subblock_directory_segment.h
index 98209d5..224fcf6 100644
--- a/czi-format/czi-parser/czi_parts/subblock_directory_segment.h
+++ b/czi-format/czi-parser/czi_parts/subblock_directory_segment.h
@@ -9,7 +9,7 @@ struct SubBlockDirectorySegment
     // SubBlock directory segment header.
     SegmentHeader header;
     // Number of entries in directory.
-    int entryCount;
+    uint entryCount;
     // Collection of DirectoryEntryDV, they are the exact same copy as in SubBlock segment.
     std::vector<DirectoryEntryDV> entries;
 };
\ No newline at end of file
diff --git a/czi-format/czi-parser/file_system.h b/czi-format/czi-parser/file_system.h
new file mode 100644
index 0000000..d833dcd
--- /dev/null
+++ b/czi-format/czi-parser/file_system.h
@@ -0,0 +1,102 @@
+#pragma once
+/*
+* Copyright Moravec Vojtech 2019.
+* Distributed under the Boost Software License, Version 1.0.
+* (See accompanying file LICENSE or copy at https://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#include "boost/filesystem.hpp"
+#include "boost/algorithm/string.hpp"
+
+namespace fs = boost::filesystem;
+
+// CZI file extension.
+constexpr char CziExtUpperCase[] = ".CZI";
+
+struct SmallFileInfo
+{
+    // Name of the file.
+    std::string name;
+    // Whole path to file.
+    std::string path;
+};
+
+// Check if given path points to file.
+bool is_file(const std::string &pathToCheck)
+{
+    auto file = fs::path(pathToCheck);
+    return (fs::exists(file) && fs::is_regular_file(file));
+}
+
+// Check if given path points to directory.
+bool is_directory(const std::string &pathToCheck)
+{
+    return fs::is_directory(fs::path(pathToCheck));
+}
+
+// Create all missing directories in path.
+bool create_directory_path(const std::string &desiredPath)
+{
+    return fs::create_directories(fs::path(desiredPath));
+}
+
+// Get name of the file, specified by its path.
+std::string get_filename(const std::string &selectedPath)
+{
+    return fs::path(selectedPath).filename().string();
+}
+
+// Get name, without extension, of the file, specified by its path.
+std::string get_filename_without_extension(const std::string &selectedPath)
+{
+    fs::path file(selectedPath);
+    auto name = file.filename().string();
+    auto ext = file.extension().string();
+    return name.substr(0, name.length() - ext.length());
+}
+
+// Get files, whose names begin with prefix.
+std::vector<SmallFileInfo> get_files_with_same_prefix(const std::vector<SmallFileInfo> &files, const std::string &prefix)
+{
+    std::vector<SmallFileInfo> result;
+
+    for (const SmallFileInfo &file : files)
+    {
+        if (boost::algorithm::starts_with(file.name, prefix))
+        {
+            result.push_back(file);
+        }
+    }
+
+    return result;
+}
+
+// Get all regular files from parent directory of given file.
+std::vector<SmallFileInfo> get_files_in_parent_directory(const std::string &filePath, const bool onlyCziFiles)
+{
+    fs::path refFile(filePath);
+    always_assert(fs::is_regular_file(refFile));
+    always_assert(refFile.has_parent_path());
+
+    fs::path dir = refFile.parent_path();
+
+    std::vector<SmallFileInfo> files;
+
+    fs::path entryPath;
+    for (fs::directory_entry &entry : fs::directory_iterator(dir))
+    {
+        entryPath = entry.path();
+        if (fs::is_regular_file(entryPath))
+        {
+            if (!onlyCziFiles || (boost::to_upper_copy(fs::extension(entryPath)) == CziExtUpperCase))
+            {
+                SmallFileInfo fi = {};
+                fi.name = entryPath.filename().string();
+                fi.path = entryPath.string();
+                files.push_back(fi);
+            }
+        }
+    }
+
+    return files;
+}
\ No newline at end of file
diff --git a/czi-format/czi-parser/image_writer.h b/czi-format/czi-parser/image_writer.h
index 6d23ed6..5bcad62 100644
--- a/czi-format/czi-parser/image_writer.h
+++ b/czi-format/czi-parser/image_writer.h
@@ -26,5 +26,6 @@ void create_image_file(const char *fileName, const std::vector<byte> &bytes, con
     }
     //set_pixel()
 
-    img.save_bmp(fileName);
+    img.save_pnm(fileName);
+    
 }
\ No newline at end of file
diff --git a/czi-format/czi-parser/main.cpp b/czi-format/czi-parser/main.cpp
index 1b93255..402f849 100644
--- a/czi-format/czi-parser/main.cpp
+++ b/czi-format/czi-parser/main.cpp
@@ -1,10 +1,13 @@
 #include "czi_parser.h"
+#include "file_system.h"
 
 int main(int argc, char **argv)
 {
     std::string cziFile;
 
     cziFile = (argc > 1) ? argv[1] : "/home/mor0146/Downloads/cziFiles/TESTIMAGES/CZT-Stack-Anno.czi";
+    always_assert(is_file(cziFile));
+
     std::string method = argc > 2 ? argv[2] : "";
     std::string dumpName = argc > 3 ? argv[3] : "";
 
@@ -13,6 +16,10 @@ int main(int argc, char **argv)
     bool dumpRawImageData = method == "--dump-raw-image-data";
     bool dumpImageData = method == "--dump-image-data";
 
+    auto name = get_filename_without_extension(cziFile);
+    auto x = get_files_in_parent_directory(cziFile, true);
+    auto y = get_files_with_same_prefix(x, name);
+
     CziParser parser;
     auto parseResult = parser.parse_czi_file(cziFile);
 
-- 
GitLab