diff --git a/src/csds_error.hpp b/src/csds_error.hpp
index 78d27f94b2b614061f180baa940c8da34527e404..c04771b3de442caa292b5f9370e264b692d6e007 100644
--- a/src/csds_error.hpp
+++ b/src/csds_error.hpp
@@ -53,6 +53,23 @@ INLINE static int GetDeltaTime(const high_resolution_clock::time_point init,
   return span.count();
 }
 
+#ifdef CSDS_DEBUG_CHECKS
+/**
+ * @brief Error macro. Prints the message given in argument and aborts.
+ */
+#define csds_error(input)                                                     \
+  {                                                                           \
+    float delta_time_error = GetDeltaTime(INITIAL_TIME);                      \
+    delta_time_error /= 1000; /* into seconds */                              \
+                                                                              \
+    std::cout << std::flush;                                                  \
+    std::cerr << "[" << std::setfill('0') << std::setw(6)                     \
+              << std::setprecision(1) << delta_time_error << "] " << __FILE__ \
+              << ":" << __FUNCTION__ << ":" << __LINE__ << ": " << input      \
+              << std::endl;                                                   \
+    csds_abort(1);                                                            \
+  }
+#else
 /**
  * @brief Error macro. Prints the message given in argument and aborts.
  */
@@ -71,6 +88,7 @@ INLINE static int GetDeltaTime(const high_resolution_clock::time_point init,
     else                                                                      \
       throw std::runtime_error("See above for the description");              \
   }
+#endif
 
 /**
  * @brief Macro to print a localized message with variable arguments.
diff --git a/src/csds_header.cpp b/src/csds_header.cpp
index 162f4c79514b21988d9d17bdcd310e687c9d928e..560d98e5a9c1ef7a7d995869538ba4c865e76693 100644
--- a/src/csds_header.cpp
+++ b/src/csds_header.cpp
@@ -102,8 +102,7 @@ void header_change_offset_direction(struct header *h,
   /* Skip file format and version numbers. */
   size_t offset = CSDS_STRING_SIZE + 2 * sizeof(int);
 
-  csds_mapped_file_write_data(h->log->log, offset, sizeof(unsigned int),
-                              &new_value);
+  h->log->log->WriteData(offset, sizeof(unsigned int), &new_value);
 }
 
 /**
@@ -113,7 +112,7 @@ void header_change_offset_direction(struct header *h,
  * @param log The #csds_logfile.
  * @param verbose The verbose level
  */
-void header_read(struct header *h, struct csds_logfile *log, int verbose) {
+void header_read(struct header *h, LogFile *log, int verbose) {
 
   /* Set pointer to log. */
   h->log = log;
@@ -123,18 +122,15 @@ void header_read(struct header *h, struct csds_logfile *log, int verbose) {
 
   /* read the file format. */
   char file_format[CSDS_STRING_SIZE];
-  offset = csds_mapped_file_read_data(log->log, offset, CSDS_STRING_SIZE,
-                                      &file_format);
+  offset = log->log->ReadData(offset, CSDS_STRING_SIZE, &file_format);
   if (strcmp(file_format, CSDS_FORMAT_STRING))
     csds_error("Wrong file format: " << file_format);
 
   /* Read the major version number. */
-  offset = csds_mapped_file_read_data(log->log, offset, sizeof(int),
-                                      &h->major_version);
+  offset = log->log->ReadData(offset, sizeof(int), &h->major_version);
 
   /* Read the minor version number. */
-  offset = csds_mapped_file_read_data(log->log, offset, sizeof(int),
-                                      &h->minor_version);
+  offset = log->log->ReadData(offset, sizeof(int), &h->minor_version);
 
   /* Check the mask size */
   if (sizeof(mask_type) != CSDS_MASK_SIZE)
@@ -145,8 +141,7 @@ void header_read(struct header *h, struct csds_logfile *log, int verbose) {
     message("File version " << h->major_version << "." << h->minor_version);
 
   /* Read the offset directions. */
-  offset = csds_mapped_file_read_data(log->log, offset, sizeof(int),
-                                      &h->offset_direction);
+  offset = log->log->ReadData(offset, sizeof(int), &h->offset_direction);
 
   if (!header_is_forward(h) && !header_is_backward(h) &&
       !header_is_corrupted(h))
@@ -154,13 +149,12 @@ void header_read(struct header *h, struct csds_logfile *log, int verbose) {
 
   /* Read offset to first record. */
   h->offset_first_record = 0;
-  offset = csds_mapped_file_read_data(log->log, offset, CSDS_OFFSET_SIZE,
-                                      &h->offset_first_record);
+  offset =
+      log->log->ReadData(offset, CSDS_OFFSET_SIZE, &h->offset_first_record);
 
   /* Read the size of the strings. */
   unsigned int string_length = 0;
-  offset = csds_mapped_file_read_data(log->log, offset, sizeof(unsigned int),
-                                      &string_length);
+  offset = log->log->ReadData(offset, sizeof(unsigned int), &string_length);
 
   /* Check if value defined in this file is large enough. */
   if (CSDS_STRING_SIZE < string_length) {
@@ -169,8 +163,7 @@ void header_read(struct header *h, struct csds_logfile *log, int verbose) {
 
   /* Read the number of masks. */
   unsigned int masks_count = 0;
-  offset = csds_mapped_file_read_data(log->log, offset, sizeof(unsigned int),
-                                      &masks_count);
+  offset = log->log->ReadData(offset, sizeof(unsigned int), &masks_count);
 
   /* Allocate the masks memory. */
   struct mask_data *masks =
@@ -182,15 +175,13 @@ void header_read(struct header *h, struct csds_logfile *log, int verbose) {
   /* Loop over all masks. */
   for (unsigned int i = 0; i < masks_count; i++) {
     /* Read the mask name. */
-    offset = csds_mapped_file_read_data(log->log, offset, string_length,
-                                        masks[i].name);
+    offset = log->log->ReadData(offset, string_length, masks[i].name);
 
     /* Set the mask value. */
     masks[i].mask = 1 << i;
 
     /* Read the mask data size. */
-    offset = csds_mapped_file_read_data(log->log, offset, sizeof(unsigned int),
-                                        &masks[i].size);
+    offset = log->log->ReadData(offset, sizeof(unsigned int), &masks[i].size);
 
     /* Print the information. */
     if (verbose > 1) {
@@ -235,8 +226,8 @@ void header_read(struct header *h, struct csds_logfile *log, int verbose) {
   }
 
   /* Read the number of fields per particle  */
-  offset = csds_mapped_file_read_data(
-      log->log, offset, sizeof(h->number_fields), h->number_fields);
+  offset =
+      log->log->ReadData(offset, sizeof(h->number_fields), h->number_fields);
 
   /* Read the order of the fields */
   for (int type = 0; type < csds_type_count; type++) {
@@ -248,7 +239,7 @@ void header_read(struct header *h, struct csds_logfile *log, int verbose) {
     /* Allocate and read the order */
     size_t size = h->number_fields[type] * sizeof(int);
     int *order = (int *)malloc(size);
-    offset = csds_mapped_file_read_data(log->log, offset, size, order);
+    offset = log->log->ReadData(offset, size, order);
 
     /* Add the special flag */
     size = (h->number_fields[type] + 1) * sizeof(struct field_information);
diff --git a/src/csds_header.hpp b/src/csds_header.hpp
index bde9e1f769c54bea3b49a47f5944823864b7e9cf..95ffbe295edae2dd984060b4ee7c91411a27c1e8 100644
--- a/src/csds_header.hpp
+++ b/src/csds_header.hpp
@@ -31,8 +31,6 @@
  */
 extern const char *csds_offset_name[];
 
-struct csds_logfile;
-
 /**
  * @brief This structure contains everything from the file header.
  *
@@ -58,7 +56,8 @@ struct header {
   enum csds_offset_direction offset_direction;
 
   /* The corresponding log. */
-  struct csds_logfile *log;
+  // TODO Remove this dependency
+  LogFile *log;
 
   /* Number of mask per particle type */
   int number_fields[csds_type_count];
@@ -70,7 +69,7 @@ struct header {
 
 void header_print(const struct header *h);
 void header_free(struct header *h);
-void header_read(struct header *h, struct csds_logfile *log, int verbose);
+void header_read(struct header *h, LogFile *log, int verbose);
 size_t header_get_record_size_from_mask(const struct header *h, mask_type mask);
 void header_change_offset_direction(struct header *h,
                                     enum csds_offset_direction new_value);
diff --git a/src/csds_index.cpp b/src/csds_index.cpp
index 881b62b0613ac6d301586c47f6134615c2fe9b3e..2f9c5c3a8ae101c9c62fcd9f4797354fbf87e842 100644
--- a/src/csds_index.cpp
+++ b/src/csds_index.cpp
@@ -56,57 +56,58 @@
  * @param filename The filename of the index file.
  * @param verbose The verbose level
  */
-void csds_index_read_header(struct csds_index *index,
-                            const std::string filename, int verbose) {
+IndexFile::IndexFile(const std::string filename, int verbose) {
+  this->index = NULL;
 
   /* Open the file */
   if (verbose > 1) {
     message("Reading " << filename);
   }
-  csds_index_map_file(index, filename, 0, verbose);
+  csds_index_map_file(this, filename, 0, verbose);
 
   /* Read times */
-  memcpy(&index->time, index->index.map + csds_index_time_offset,
+  memcpy(&this->time, this->index->mMap + csds_index_time_offset,
          csds_index_time_size);
-  memcpy(&index->integer_time,
-         index->index.map + csds_index_integer_time_offset,
+  memcpy(&this->integer_time,
+         this->index->mMap + csds_index_integer_time_offset,
          csds_index_integer_time_size);
 
   /* Read the number of particles. */
-  memcpy(index->nparts, index->index.map + csds_index_npart_offset,
+  memcpy(this->nparts, this->index->mMap + csds_index_npart_offset,
          csds_index_npart_size);
 
   /* Read whether the file is sorted. */
-  memcpy(&index->is_sorted, index->index.map + csds_index_is_sorted_offset,
+  memcpy(&this->is_sorted, this->index->mMap + csds_index_is_sorted_offset,
          csds_index_is_sorted_size);
 
   /* Compute the position of the history of new particles. */
   size_t count = 0;
   for (int i = 0; i < csds_type_count; i++) {
-    count += index->nparts[i];
+    count += this->nparts[i];
   }
   count *= sizeof(struct index_data);
 
   /* Read the number of new particles. */
-  memcpy(index->nparts_created,
-         index->index.map + csds_index_data_offset + count,
+  memcpy(this->nparts_created,
+         this->index->mMap + csds_index_data_offset + count,
          csds_index_npart_size);
 
   /* Compute the position of the history of particles removed. */
   size_t count_new = 0;
   for (int i = 0; i < csds_type_count; i++) {
-    count_new += index->nparts_created[i];
+    count_new += this->nparts_created[i];
   }
   count_new *= sizeof(struct index_data);
 
   /* Read the number of particles removed. */
-  memcpy(index->nparts_removed,
-         index->index.map + csds_index_data_offset + count +
+  memcpy(this->nparts_removed,
+         this->index->mMap + csds_index_data_offset + count +
              csds_index_npart_size + count_new,
          csds_index_npart_size);
 
   /* Close the file */
-  csds_index_free(index);
+  delete this->index;
+  this->index = NULL;
 }
 
 /**
@@ -116,12 +117,15 @@ void csds_index_read_header(struct csds_index *index,
  *
  * @param index The #csds_index.
  */
-void csds_index_write_sorted(struct csds_index *index) {
+void csds_index_write_sorted(IndexFile *index) {
+  if (index->index == NULL) {
+    csds_error("File is not mapped");
+  }
   /* Set the value */
   const char is_sorted = 1;
 
   /* Write the value */
-  memcpy(index->index.map + csds_index_is_sorted_offset, &is_sorted,
+  memcpy(index->index->mMap + csds_index_is_sorted_offset, &is_sorted,
          csds_index_is_sorted_size);
 }
 
@@ -134,7 +138,7 @@ void csds_index_write_sorted(struct csds_index *index) {
  * @param index The #csds_index.
  * @param type The particle type.
  */
-struct index_data *csds_index_get_data(struct csds_index *index, int type) {
+struct index_data *csds_index_get_data(IndexFile *index, int type) {
   /* Get the offset of particles of this type by skipping entries of lower
    * types. */
   size_t count = 0;
@@ -143,7 +147,7 @@ struct index_data *csds_index_get_data(struct csds_index *index, int type) {
   }
   const size_t type_offset = count * sizeof(struct index_data);
 
-  const char *ret = index->index.map + csds_index_data_offset + type_offset;
+  const char *ret = index->index->mMap + csds_index_data_offset + type_offset;
   return (struct index_data *)ret;
 }
 
@@ -156,8 +160,7 @@ struct index_data *csds_index_get_data(struct csds_index *index, int type) {
  * @param index The #csds_index.
  * @param type The particle type.
  */
-struct index_data *csds_index_get_created_history(struct csds_index *index,
-                                                  int type) {
+struct index_data *csds_index_get_created_history(IndexFile *index, int type) {
 
   /* Get the position after the previous array. */
   char *ret = (char *)csds_index_get_data(index, csds_type_count);
@@ -183,8 +186,7 @@ struct index_data *csds_index_get_created_history(struct csds_index *index,
  * @param index The #csds_index.
  * @param type The particle type.
  */
-struct index_data *csds_index_get_removed_history(struct csds_index *index,
-                                                  int type) {
+struct index_data *csds_index_get_removed_history(IndexFile *index, int type) {
 
   /* Get the position after the previous array. */
   char *ret = (char *)csds_index_get_created_history(index, csds_type_count);
@@ -206,18 +208,18 @@ struct index_data *csds_index_get_removed_history(struct csds_index *index,
  *
  * @param index The #csds_index.
  */
-int csds_index_contains_time_array(struct csds_index *index) {
+int csds_index_contains_time_array(IndexFile *index) {
   /* Only the first index file should have a time array */
   if (index->integer_time != 0) {
     csds_error("Only the first index file can have a time array.");
   }
 
   /* Get the file size */
-  const size_t file_size = index->index.mmap_size;
+  const size_t file_size = index->index->mMapSize;
 
   /* Get the position after the previous array. */
   char *ret = (char *)csds_index_get_removed_history(index, csds_type_count);
-  const size_t before_time_array = ret - index->index.map;
+  const size_t before_time_array = ret - index->index->mMap;
 
   return file_size != before_time_array;
 }
@@ -230,10 +232,10 @@ int csds_index_contains_time_array(struct csds_index *index) {
  * @param sorted Does the file needs to be sorted?
  * @param verbose the verbose level
  */
-void csds_index_map_file(struct csds_index *index, const std::string filename,
+void csds_index_map_file(IndexFile *index, const std::string filename,
                          int sorted, int verbose) {
   /* Un-map previous file */
-  if (index->index.map != NULL) {
+  if (index->index != NULL) {
     csds_error("Trying to remap.");
   }
 
@@ -243,8 +245,9 @@ void csds_index_map_file(struct csds_index *index, const std::string filename,
       message("Sorting the index file.");
     }
     /* Map the index file */
-    csds_mapped_file_mmap_file(index->index, filename,
-                               /* read_only */ 0, /* track_mmap */ 0);
+    index->index = new MappedFile(filename,
+                                  /* read_only */ 0,
+                                  /* track_mmap */ 0);
     /* Sort the file */
     for (int i = 0; i < csds_type_count; i++) {
       if (index->nparts[i] != 0) {
@@ -257,7 +260,8 @@ void csds_index_map_file(struct csds_index *index, const std::string filename,
     csds_index_write_sorted(index);
 
     /* Free the index file before opening it again in read only */
-    csds_index_free(index);
+    delete index->index;
+    index->index = NULL;
 
     if (verbose > 1) {
       message("Sorting done.");
@@ -265,8 +269,8 @@ void csds_index_map_file(struct csds_index *index, const std::string filename,
   }
 
   /* Map the index file */
-  csds_mapped_file_mmap_file(index->index, filename,
-                             /* read_only */ 1, /* track_mmap */ 0);
+  index->index = new MappedFile(filename, /* read_only */ 1,
+                                /* track_mmap */ 0);
 }
 
 /**
@@ -274,11 +278,11 @@ void csds_index_map_file(struct csds_index *index, const std::string filename,
  *
  * @param index The #csds_index.
  */
-void csds_index_free(struct csds_index *index) {
-  if (index->index.map == NULL) {
-    csds_error("Trying to unmap an unexisting map");
+IndexFile::~IndexFile() {
+  if (this->index != NULL) {
+    delete this->index;
+    this->index = NULL;
   }
-  csds_mapped_file_munmap_file(index->index);
 }
 
 /**
@@ -290,7 +294,7 @@ void csds_index_free(struct csds_index *index) {
  *
  * @return The offset of the particle or 0 if not found.
  */
-size_t csds_index_get_particle_offset(struct csds_index *index, long long id,
+size_t csds_index_get_particle_offset(IndexFile *index, long long id,
                                       int type) {
   /* Define a few variables */
   const struct index_data *data = csds_index_get_data(index, type);
@@ -312,19 +316,6 @@ size_t csds_index_get_particle_offset(struct csds_index *index, long long id,
   return 0;
 }
 
-/**
- * @brief Initialize the #csds_index.
- *
- * @param index The #csds_index.
- */
-void csds_index_init(struct csds_index *index) {
-  /* Set the mapped file to NULL */
-  index->index.map = NULL;
-
-  /* Set the time to its default value */
-  index->time = -1;
-}
-
 /**
  * @brief Give the offset of a particle given its id.
  *
@@ -335,7 +326,7 @@ void csds_index_init(struct csds_index *index) {
  *
  * @return Did we find the particle?
  */
-int csds_index_get_offset(struct csds_index *index, int64_t id, int type,
+int csds_index_get_offset(IndexFile *index, int64_t id, int type,
                           uint64_t *offset) {
 
   /* Ensure that the file is sorted according to the ids. */
diff --git a/src/csds_index.hpp b/src/csds_index.hpp
index 394746f47bcbdd3a29e7edd21cbdfd60534c4251..7227e19ad666f1bf0f97bca3d13d8367b6f7b79b 100644
--- a/src/csds_index.hpp
+++ b/src/csds_index.hpp
@@ -25,10 +25,9 @@
 #include "csds_tools.hpp"
 
 /**
- * @brief Structure dealing with the index files.
+ * @brief Class dealing with the index files.
  *
- * The structure is initialized with #csds_index_init and
- * then a file can be read with #csds_index_read_header and
+ * A file can be read with #csds_index_read_header and
  * #csds_index_map_file.
  *
  * The functions #csds_index_get_particle_offset and
@@ -37,7 +36,11 @@
  * The first one access a particle through its ids and the second one
  * gives a pointer to the first element that can be looped through.
  */
-struct csds_index {
+class IndexFile {
+ public:
+  IndexFile(const std::string filename, int verbose);
+  ~IndexFile();
+
   /* Time of the index file */
   double time;
 
@@ -51,7 +54,7 @@ struct csds_index {
   char is_sorted;
 
   /* The mapped file */
-  struct mapped_file index;
+  MappedFile *index;
 
   /* Number of particles created. */
   uint64_t nparts_created[csds_type_count];
@@ -60,23 +63,16 @@ struct csds_index {
   uint64_t nparts_removed[csds_type_count];
 };
 
-int csds_index_contains_time_array(struct csds_index *index);
-void csds_index_write_sorted(struct csds_index *index);
-void csds_index_init(struct csds_index *index);
-void csds_index_read_header(struct csds_index *index,
-                            const std::string filename, int verbose);
-void csds_index_map_file(struct csds_index *index, const std::string filename,
+int csds_index_contains_time_array(IndexFile *index);
+void csds_index_write_sorted(IndexFile *index);
+void csds_index_map_file(IndexFile *index, const std::string filename,
                          int sorted, int verbose);
-size_t csds_index_get_particle_offset(struct csds_index *index, long long id,
-                                      int type);
-void csds_index_free(struct csds_index *index);
-void csds_index_sort_file(struct csds_index *index);
-int csds_index_get_offset(struct csds_index *index, int64_t id, int type,
+size_t csds_index_get_particle_offset(IndexFile *index, long long id, int type);
+void csds_index_sort_file(IndexFile *index);
+int csds_index_get_offset(IndexFile *index, int64_t id, int type,
                           uint64_t *offset);
-struct index_data *csds_index_get_data(struct csds_index *index, int type);
-struct index_data *csds_index_get_created_history(struct csds_index *index,
-                                                  int type);
-struct index_data *csds_index_get_removed_history(struct csds_index *index,
-                                                  int type);
+struct index_data *csds_index_get_data(IndexFile *index, int type);
+struct index_data *csds_index_get_created_history(IndexFile *index, int type);
+struct index_data *csds_index_get_removed_history(IndexFile *index, int type);
 
 #endif  // CSDS_INDEX_H
diff --git a/src/csds_logfile.cpp b/src/csds_logfile.cpp
index 6e5af7874f58cd21383b8b2bb358502c4037d2c1..44e19db37ae1870144b9ae78ed5dd712a1c973f6 100644
--- a/src/csds_logfile.cpp
+++ b/src/csds_logfile.cpp
@@ -27,33 +27,30 @@ using namespace std;
  * @brief Initialize the #csds_logfile.
  *
  * If required this function will also reverse the offsets.
- * @param log The #csds_logfile.
  * @param basename The basename.
  * @param verbose The verbose level.
  * @param only_header Read only the header.
  */
-void csds_logfile_init_from_file(struct csds_logfile *log,
-                                 const string basename, int only_header,
-                                 int verbose) {
+LogFile::LogFile(const string basename, int only_header, int verbose) {
 
   /* Set pointers to zero. */
-  time_array_init(&log->times, CSDS_TIME_INIT_SIZE);
+  time_array_init(&this->times, CSDS_TIME_INIT_SIZE);
 
   /* Generate the logfile filename */
   string logfile_name = basename + ".dump";
 
   /* Open file, map it and get its size. */
   if (verbose > 1) message("Mapping the log file.");
-  csds_mapped_file_mmap_file(log->log, logfile_name,
-                             /* read_only */ 1, /* track_mmap */ 1);
+  this->log =
+      new MappedFile(logfile_name, /* read_only */ true, /* track_mmap */ true);
 
   /* Read the header. */
   if (verbose > 1) message("Reading the header.");
-  header_read(&log->header, log, verbose);
+  header_read(&this->header, this, verbose);
 
   /* Print the header. */
   if (verbose > 0) {
-    header_print(&log->header);
+    header_print(&this->header);
   }
 
   /* No need to continue if only the
@@ -61,22 +58,22 @@ void csds_logfile_init_from_file(struct csds_logfile *log,
   if (only_header) return;
 
   /* Check if the offset are corrupted. */
-  if (header_is_corrupted(&log->header)) {
+  if (header_is_corrupted(&this->header)) {
     csds_error("The offsets have been corrupted.");
   }
 
   /* Reverse the offsets direction. */
-  if (header_is_backward(&log->header)) {
-    csds_logfile_reverse_offset(log, logfile_name, verbose);
+  if (header_is_backward(&this->header)) {
+    csds_logfile_reverse_offset(*this, logfile_name, verbose);
   }
 
   /* Initialize the time array. */
   if (verbose > 1) message("Reading the timestamps.");
-  time_array_populate(&log->times, log, basename, verbose);
+  time_array_populate(&this->times, this, basename, verbose);
 
   /* Print the time array. */
   if (verbose > 0) {
-    time_array_print(&log->times);
+    time_array_print(&this->times);
   }
 }
 
@@ -85,12 +82,12 @@ void csds_logfile_init_from_file(struct csds_logfile *log,
  *
  * @param log The #csds_logfile.
  */
-void csds_logfile_free(struct csds_logfile *log) {
-  csds_mapped_file_munmap_file(log->log);
+LogFile::~LogFile() {
+  delete this->log;
 
-  time_array_free(&log->times);
+  time_array_free(&this->times);
 
-  header_free(&log->header);
+  header_free(&this->header);
 }
 
 /**
@@ -103,10 +100,10 @@ void csds_logfile_free(struct csds_logfile *log) {
  * @param log The #csds_logfile
  * @param verbose The verbose level
  */
-void csds_logfile_check_record_consistency(ATTR_UNUSED struct csds_logfile *log,
+void csds_logfile_check_record_consistency(ATTR_UNUSED LogFile &log,
                                            ATTR_UNUSED int verbose) {
 #ifdef CSDS_DEBUG_CHECKS
-  struct header *header = &log->header;
+  struct header *header = &log.header;
 
   if (verbose > 0) {
     message("Check record's headers...");
@@ -119,11 +116,11 @@ void csds_logfile_check_record_consistency(ATTR_UNUSED struct csds_logfile *log,
 
   /* check that the record offset points to another record. */
   for (size_t offset_debug = header->offset_first_record;
-       offset_debug < log->log.mmap_size;
-       offset_debug = tools_check_record_consistency(log, offset_debug)) {
+       offset_debug < log.log->mMapSize;
+       offset_debug = tools_check_record_consistency(&log, offset_debug)) {
 
     /* Check if we should update the progress bar. */
-    float current = 100 * ((float)offset_debug) / log->log.mmap_size;
+    float current = 100 * ((float)offset_debug) / log.log->mMapSize;
     if (verbose > 0 && current > next_percentage) {
       /* Print the bar */
       tools_print_progress(current, init, "Checking offsets");
@@ -151,16 +148,15 @@ void csds_logfile_check_record_consistency(ATTR_UNUSED struct csds_logfile *log,
  * @param log The #csds_logfile
  * @param filename The log's filename.
  */
-void csds_logfile_reverse_offset(struct csds_logfile *log, std::string filename,
+void csds_logfile_reverse_offset(LogFile &log, std::string filename,
                                  int verbose) {
 
   /* Close and reopen the file in write mode. */
-  csds_mapped_file_munmap_file(log->log);
-  csds_mapped_file_mmap_file(log->log, filename,
-                             /* read_only */ 0, /* track_mmap */ 0);
+  delete log.log;
+  log.log = new MappedFile(filename, /* read_only */ 0, /* track_mmap */ 0);
 
   /* Get pointers */
-  struct header *header = &log->header;
+  struct header *header = &log.header;
 
   /* Check if the offsets need to be reversed. */
   if (!header_is_backward(header)) {
@@ -186,10 +182,10 @@ void csds_logfile_reverse_offset(struct csds_logfile *log, std::string filename,
   const high_resolution_clock::time_point init = high_resolution_clock::now();
 
   /* reverse the record's offset. */
-  for (size_t offset = header->offset_first_record; offset < log->log.mmap_size;
-       offset = tools_reverse_offset(header, log->log, offset)) {
+  for (size_t offset = header->offset_first_record; offset < log.log->mMapSize;
+       offset = tools_reverse_offset(header, *log.log, offset)) {
     /* Check if we should update the progress. */
-    float current = 100 * ((float)offset) / log->log.mmap_size;
+    float current = 100 * ((float)offset) / log.log->mMapSize;
     if (verbose > 0 && current > next_percentage) {
 
       /* Print the remaining time */
@@ -217,8 +213,8 @@ void csds_logfile_reverse_offset(struct csds_logfile *log, std::string filename,
 #endif
 
   /* Close and reopen the file in read mode. */
-  csds_mapped_file_munmap_file(log->log);
-  csds_mapped_file_mmap_file(log->log, filename,
-                             /* read_only */ 1,
-                             /* track_mmap */ 1);
+  delete log.log;
+  log.log = new MappedFile(filename,
+                           /* read_only */ 1,
+                           /* track_mmap */ 1);
 }
diff --git a/src/csds_logfile.hpp b/src/csds_logfile.hpp
index 6191d0daed37a2d42d9f7f42ec5f70ebccee5648..f8c8f5d138a6464963f0f0d906353c57aa01c1fe 100644
--- a/src/csds_logfile.hpp
+++ b/src/csds_logfile.hpp
@@ -28,16 +28,12 @@
 #include "csds_time.hpp"
 
 /**
- * @brief This structure deals with the log file.
- *
- * This structure is initialized by the #csds_reader
- * and deals with the log file.
- * It maps it, reverse the offsets (if required) and unmap it.
- *
- * The structure is initialized with #csds_logfile_init_from_file and
- * freed with #csds_logfile_free.
+ * @brief This class deals with the log file.
  */
-struct csds_logfile {
+class LogFile {
+ public:
+  LogFile(const std::string basename, int only_header, int verbose);
+  ~LogFile();
 
   /* Information contained in the file header. */
   struct header header;
@@ -46,14 +42,10 @@ struct csds_logfile {
   struct time_array times;
 
   /* The file. */
-  struct mapped_file log;
+  MappedFile *log;
 };
 
-void csds_logfile_init_from_file(struct csds_logfile *log,
-                                 const std::string basename, int only_header,
-                                 int verbose);
-void csds_logfile_reverse_offset(struct csds_logfile *log, std::string filename,
+void csds_logfile_reverse_offset(LogFile &log, std::string filename,
                                  int verbose);
-void csds_logfile_free(struct csds_logfile *log);
 
 #endif  // CSDS_LOGFILE_H
diff --git a/src/csds_mapped_file.cpp b/src/csds_mapped_file.cpp
index 9aa067aab0d2c1ad51c5c9782487dfd4d9824a4d..a49ebbce50cf60bb952bd546095820ae66efd866 100644
--- a/src/csds_mapped_file.cpp
+++ b/src/csds_mapped_file.cpp
@@ -59,14 +59,13 @@ string strip_ext(string fname) {
  *
  * #csds_loader_io_munmap_file should be called to unmap the file.
  *
- * @param map The #mapped_file.
  * @param filename file to read.
  * @param read_only Open the file in read only mode?
  * @param track_mmap Should we track the memory reading?
  *
  */
-void csds_mapped_file_mmap_file(struct mapped_file &map, const string filename,
-                                int read_only, ATTR_UNUSED int track_mmap) {
+MappedFile::MappedFile(const string filename, bool read_only,
+                       ATTR_UNUSED bool track_mmap) {
   /* open the file. */
   int fd;
 
@@ -80,15 +79,15 @@ void csds_mapped_file_mmap_file(struct mapped_file &map, const string filename,
                                        << ")");
 
   /* get the file size. */
-  map.mmap_size = csds_loader_io_get_file_size(fd);
+  this->mMapSize = csds_loader_io_get_file_size(fd);
 
   /* map the memory. */
   int mode = PROT_READ;
   if (!read_only) mode |= PROT_WRITE;
 
-  map.map = (char *)mmap(NULL, map.mmap_size, mode, MAP_SHARED, fd, 0);
-  if (map.map == MAP_FAILED)
-    csds_error("Failed to allocate map of size " << map.mmap_size << " bytes ("
+  this->mMap = (char *)mmap(NULL, this->mMapSize, mode, MAP_SHARED, fd, 0);
+  if (this->mMap == MAP_FAILED)
+    csds_error("Failed to allocate map of size " << this->mMapSize << " bytes ("
                                                  << strerror(errno) << ")");
 
   /* Close the file. */
@@ -96,9 +95,9 @@ void csds_mapped_file_mmap_file(struct mapped_file &map, const string filename,
 
 #ifdef CSDS_MMAP_TRACKING
   /* Now deal with the mmap tracking */
-  map.tracking.f = NULL;
-  map.tracking.number_elements = 0;
-  map.tracking.size = 0;
+  this->mTracking.number_elements = 0;
+  this->mTracking.size = 0;
+  this->mTracking.use_tracking = track_mmap;
 
   /* Nothing to do without tracking */
   if (!track_mmap) return;
@@ -108,14 +107,12 @@ void csds_mapped_file_mmap_file(struct mapped_file &map, const string filename,
   tracking_filename = strip_ext(tracking_filename);
   tracking_filename += ".track";
 
-  map.tracking.f = fopen(tracking_filename, "w");
-  if (map.tracking.f == NULL)
-    csds_error("Unable to open file " << tracking_filename << " ("
-                                      << strerror(errno) << ")");
+  this->mTracking.stream = std::ofstream(
+      tracking_filename, std::ofstream::out | std::ofstream::binary);
 
   /* Write the header */
-  fprintf(map.tracking.f, "%20s", "CSDS_TRACK");
-  fwrite(&map.tracking.number_elements, 1, sizeof(int64_t), map.tracking.f);
+  this->mTracking.stream << std::setw(20) << std::left << "CSDS_TRACK";
+  this->mTracking.stream << this->mTracking.number_elements;
 #endif
 }
 
@@ -123,25 +120,11 @@ void csds_mapped_file_mmap_file(struct mapped_file &map, const string filename,
  * @brief Unmap a file.
  *
  * @param map The #mapped_file.
- *
  */
-void csds_mapped_file_munmap_file(struct mapped_file &map) {
+MappedFile::~MappedFile() {
   /* unmap the file. */
-  if (munmap(map.map, map.mmap_size) != 0) {
-    csds_error("Unable to unmap the file :" << strerror(errno));
+  if (munmap(this->mMap, this->mMapSize) != 0) {
+    message("Unable to unmap the file :" << strerror(errno));
+    csds_abort(186);
   }
-
-  /* Reset values */
-  map.map = NULL;
-  map.mmap_size = 0;
-
-#ifdef CSDS_MMAP_TRACKING
-  /* Now deal with tracking */
-  if (map.tracking.f == NULL) return;
-
-  fclose(map.tracking.f);
-
-  /* Reset the values */
-  map.tracking.f = NULL;
-#endif
 }
diff --git a/src/csds_mapped_file.hpp b/src/csds_mapped_file.hpp
index dbc879174d4f9cec8e8fc99f9f9107408d7ce690..550ca03b0630fac570be13a8a896e4380220bc9f 100644
--- a/src/csds_mapped_file.hpp
+++ b/src/csds_mapped_file.hpp
@@ -28,6 +28,8 @@
 #include "csds_tools.hpp"
 
 /* Standard headers */
+#include <fstream>
+#include <iostream>
 #include <stdio.h>
 #include <stdlib.h>
 #include <sys/mman.h>
@@ -36,207 +38,200 @@
 #define CSDS_VERBOSE_TIMERS -1
 #define CSDS_TRACKING_SIZE_BYTES (1024 * 1024 * 1024)
 
-/* Structure for mapping a file. */
-struct mapped_file {
-  /* Mapped data. */
-  char *map;
-
-  /* File size. */
-  size_t mmap_size;
-
-#ifdef CSDS_MMAP_TRACKING
-  struct {
-    /* File for the tracking (should not use mmap file) */
-    FILE *f;
-
-    /* Size of the file? */
-    size_t size;
+size_t csds_loader_io_get_file_size(int fd);
 
-    /* Current number of elements  */
-    int64_t number_elements;
-  } tracking;
-#endif
+/** @brief Structure for the record header */
+struct record_header {
+  mask_type mask;
+  size_t offset;
 };
 
 #ifdef CSDS_MMAP_TRACKING
 /**
- * @brief Structure written in the tracking file.
+ * @brief Class for tracking the mmap readings.
  */
-struct mmap_tracking_element {
-  /* Number of ticks for accessing the page */
-  int64_t ticks;
+class MMapTrackingElement {
+
+ public:
+  MMapTrackingElement(size_t offset) : mOffset(offset) {
+    this->mChrono = high_resolution_clock::now();
+  }
+
+  friend std::ostream &operator<<(std::ostream &output,
+                                  const MMapTrackingElement &el) {
+    int64_t time = GetDeltaTime(el.mChrono);
+    output << time << el.mOffset;
+    return output;
+  }
+
+  /* Chrono for measuring the data access */
+  high_resolution_clock::time_point mChrono;
 
   /* Offset accessed */
-  long long offset;
+  long long mOffset;
 };
+#endif
 
-/** @brief Initialize a tracking element */
-INLINE static void mmap_tracking_element_init(struct mmap_tracking_element *el,
-                                              size_t offset) {
-  el->ticks = getticks();
-  el->offset = offset;
-}
-
-/** @brief Write a tracking element into the file */
-INLINE static void mmap_tracking_element_write(struct mmap_tracking_element *el,
-                                               struct mapped_file &file) {
-#pragma omp critical
-  {
-    /* Stop when file becomes too huge */
-    if (file.tracking.size < CSDS_TRACKING_SIZE_BYTES) {
-
-      /* Write the element */
-      fwrite(el, 1, sizeof(struct mmap_tracking_element), file.tracking.f);
-
-      /* Update the counter */
-      file.tracking.number_elements++;
-
-      /* Write it back to the file */
-      const long int pos = ftell(file.tracking.f);
-      /* See csds_mapped_file_mmap_file for the value */
-      fseek(file.tracking.f, 20, SEEK_SET);
-      fwrite(&file.tracking.number_elements, 1,
-             sizeof(file.tracking.number_elements), file.tracking.f);
-      fseek(file.tracking.f, pos, SEEK_SET);
-
-      /* Update the file size */
-      file.tracking.size += sizeof(struct mmap_tracking_element);
-    }
-  }
-}
+/* Structure for mapping a file. */
+class MappedFile {
+
+ public:
+  MappedFile(const std::string filename, bool read_only, bool track_mmap);
+  ~MappedFile();
+
+  /**
+   * @brief read a record header.
+   *
+   * @param offset The offset in the file
+   * @param header (output) header read from the file.
+   *
+   * @return The offset after the record header.
+   */
+  size_t ReadRecordHeader(size_t offset, record_header &header) {
+#ifdef CSDS_MMAP_TRACKING
+    MMapTrackingElement el(offset);
 #endif
 
-size_t csds_loader_io_get_file_size(int fd);
-void csds_mapped_file_mmap_file(struct mapped_file &map,
-                                const std::string filename, int read_only,
-                                int track_mmap);
-void csds_mapped_file_munmap_file(struct mapped_file &map);
+    /* read mask */
+    header.mask = 0;
+    memcpy(&header.mask, this->mMap + offset, CSDS_MASK_SIZE);
+    offset += CSDS_MASK_SIZE;
+
+    /* read offset */
+    header.offset = 0;
+    memcpy(&header.offset, this->mMap + offset, CSDS_OFFSET_SIZE);
+    offset += CSDS_OFFSET_SIZE;
 
-/**
- * @brief read a mask with its offset.
- *
- * @param mmap The #mapped_file.
- * @param offset The offset in the file
- * @param mask (output) mask read from the file.
- * @param diff_offset (output) offset difference to previous/next corresponding
- * record.
- *
- * @return The offset after the record header.
- */
-INLINE static size_t csds_mapped_file_read_mask(struct mapped_file &mmap,
-                                                size_t offset, mask_type *mask,
-                                                size_t *diff_offset) {
 #ifdef CSDS_MMAP_TRACKING
-  struct mmap_tracking_element el;
-  mmap_tracking_element_init(&el, offset);
+    /* Write the result into the file */
+    if (this->mTracking.use_tracking) {
+      this->WriteTracking(el);
+    }
 #endif
 
-  /* read mask */
-  if (mask) {
-    *mask = 0;
-    memcpy(mask, mmap.map + offset, CSDS_MASK_SIZE);
+    return offset;
   }
-  offset += CSDS_MASK_SIZE;
 
-  /* read offset */
-  if (diff_offset) {
-    *diff_offset = 0;
-    memcpy(diff_offset, mmap.map + offset, CSDS_OFFSET_SIZE);
-  }
-  offset += CSDS_OFFSET_SIZE;
+  /**
+   * @brief read a single value from a file.
+   *
+   * @param offset The offset in the file
+   * @param size size of the data to read.
+   * @param p pointer where to store the data.
+   *
+   * @return The offset after the data read.
+   */
+  size_t ReadData(size_t offset, const size_t size, void *p) {
+#ifdef CSDS_MMAP_TRACKING
+    MMapTrackingElement el(offset);
+#endif
+
+    memcpy(p, this->mMap + offset, size);
 
 #ifdef CSDS_MMAP_TRACKING
-  /* Write the result into the file */
-  el.ticks = getticks() - el.ticks;
-  if (mmap.tracking.f) {
-    mmap_tracking_element_write(&el, mmap);
-  }
+    /* Write the result into the file */
+    if (this->mTracking.use_tracking) {
+      this->WriteTracking(el);
+    }
 #endif
 
-  return offset;
-}
+    return offset + size;
+  };
 
-/**
- * @brief read a single value from a file.
- *
- * @param mmap The #mapped_file.
- * @param offset The offset in the file
- * @param size size of the data to read.
- * @param p pointer where to store the data.
+  /**
+   * @brief write a single value in a file.
+   *
+   * @param offset The offset in the file
+   * @param size size of the data to write.
+   * @param p pointer to the data.
+   *
+   * @return memory after the data written.
+   */
+  size_t WriteData(size_t offset, const size_t size, const void *p) {
 
- * @return The offset after the data read.
- */
-INLINE static size_t csds_mapped_file_read_data(struct mapped_file &mmap,
-                                                size_t offset,
-                                                const size_t size, void *p) {
 #ifdef CSDS_MMAP_TRACKING
-  struct mmap_tracking_element el;
-  mmap_tracking_element_init(&el, offset);
+    MMapTrackingElement el(offset);
 #endif
 
-  memcpy(p, mmap.map + offset, size);
+    memcpy(this->mMap + offset, p, size);
 
 #ifdef CSDS_MMAP_TRACKING
-  /* Write the result into the file */
-  el.ticks = getticks() - el.ticks;
-  if (mmap.tracking.f) {
-    mmap_tracking_element_write(&el, mmap);
-  }
+    /* Write the result into the file */
+    if (this->mTracking.use_tracking) {
+      this->WriteTracking(el);
+    }
 #endif
 
-  return offset + size;
-};
+    return offset + size;
+  };
 
-/**
- * @brief write a single value in a file.
- *
- * @param mmap The #mapped_file.
- * @param offset The offset in the file
- * @param size size of the data to write.
- * @param p pointer to the data.
- *
- * @return memory after the data written.
- */
-INLINE static size_t csds_mapped_file_write_data(struct mapped_file &mmap,
-                                                 size_t offset,
-                                                 const size_t size,
-                                                 const void *p) {
+  /* Mapped data. */
+  char *mMap;
+  /* File size. */
+  size_t mMapSize;
 
+ protected:
 #ifdef CSDS_MMAP_TRACKING
-  struct mmap_tracking_element el;
-  mmap_tracking_element_init(&el, offset);
-#endif
+  struct {
+    /* File for the tracking (should not use mmap file) */
+    std::ofstream stream;
 
-  memcpy(mmap.map + offset, p, size);
+    /* Size of the file? */
+    size_t size;
 
-#ifdef CSDS_MMAP_TRACKING
-  /* Write the result into the file */
-  el.ticks = getticks() - el.ticks;
-  if (mmap.tracking.f) {
-    mmap_tracking_element_write(&el, mmap);
+    /* Current number of elements */
+    int64_t number_elements;
+
+    /* Are we tracking the reading? */
+    bool use_tracking;
+  } mTracking;
+
+  /** @brief Write a tracking element into the file */
+  void WriteTracking(const MMapTrackingElement &el) {
+#pragma omp critical
+    {
+      /* Stop when file becomes too huge */
+      if (this->mTracking.size < CSDS_TRACKING_SIZE_BYTES) {
+
+        /* Write the element */
+        this->mTracking.stream << el;
+
+        /* Update the counter */
+        this->mTracking.number_elements++;
+
+        /* Write it back to the file */
+        const std::streampos pos = this->mTracking.stream.tellp();
+
+        /* See MappedFile constructor for the value */
+        this->mTracking.stream.seekp(20);
+        this->mTracking.stream << this->mTracking.number_elements;
+        this->mTracking.stream.seekp(pos);
+
+        /* Update the file size */
+        this->mTracking.size += sizeof(MMapTrackingElement);
+      }
+    }
   }
 #endif
-
-  return offset + size;
 };
 
 /* Defines a few advice for the mmap */
-#define CSDS_ADVICE_SEQUENTIAL(log)                                  \
-  {                                                                  \
-    /* Warn the OS that we will read in a sequential way */          \
-    int test_ret = madvise(log.map, log.mmap_size, MADV_SEQUENTIAL); \
-    if (test_ret != 0) {                                             \
-      csds_error("Failed to advise the mmap");                       \
-    }                                                                \
+#define CSDS_ADVICE_SEQUENTIAL(log)                                    \
+  {                                                                    \
+    /* Warn the OS that we will read in a sequential way */            \
+    int test_ret = madvise(log->mMap, log->mMapSize, MADV_SEQUENTIAL); \
+    if (test_ret != 0) {                                               \
+      csds_error("Failed to advise the mmap");                         \
+    }                                                                  \
   }
 
-#define CSDS_ADVICE_NORMAL(log)                                  \
-  {                                                              \
-    /* Warn the OS that we will read in a normal way */          \
-    int test_ret = madvise(log.map, log.mmap_size, MADV_NORMAL); \
-    if (test_ret != 0) {                                         \
-      csds_error("Failed to advise the mmap");                   \
-    }                                                            \
+#define CSDS_ADVICE_NORMAL(log)                                    \
+  {                                                                \
+    /* Warn the OS that we will read in a normal way */            \
+    int test_ret = madvise(log->mMap, log->mMapSize, MADV_NORMAL); \
+    if (test_ret != 0) {                                           \
+      csds_error("Failed to advise the mmap");                     \
+    }                                                              \
   }
 
 #define CSDS_ADVICE_WILL_NEED(mmap, addr, length)                         \
diff --git a/src/csds_particle.hpp b/src/csds_particle.hpp
index d757333da609dcc682984b539434ff0da5dcb192..00ac57817859c2c7367c4aade36dced79d6c85c7 100644
--- a/src/csds_particle.hpp
+++ b/src/csds_particle.hpp
@@ -40,8 +40,7 @@
  * @param output Buffer for the requested field.
  * @param field_read The field to read.
  * @param derivative The derivative to read (0 for the field).
- * @param mask (out) The mask of the record.
- * @param h_offset (out) Difference of offset with the next record.
+ * @param header (out) The record header.
  * @param fields The list of available fields
  * @param number_fields The number of fields
  * @param log_map The mmap logfile.
@@ -50,19 +49,16 @@
  */
 INLINE static size_t csds_particle_read_field(
     size_t offset, void *output, const struct field_information *field_read,
-    const int derivative, mask_type *mask, size_t *h_offset,
+    const int derivative, struct record_header &header,
     const struct field_information *fields, int number_fields,
-    struct mapped_file &log_map) {
-
-  *mask = 0;
-  *h_offset = 0;
+    MappedFile &log_map) {
 
   /* Read the record's mask. */
-  offset = csds_mapped_file_read_mask(log_map, offset, mask, h_offset);
+  offset = log_map.ReadRecordHeader(offset, header);
 
 #ifdef CSDS_DEBUG_CHECKS
   /* Check if it is not a time record. */
-  if (*mask == CSDS_TIMESTAMP_MASK) {
+  if (header.mask == CSDS_TIMESTAMP_MASK) {
     csds_error("Cannot read a particle from timestep record.");
   }
 
@@ -92,14 +88,13 @@ INLINE static size_t csds_particle_read_field(
   for (int i = 0; i < number_fields; i++) {
 
     /* Is the mask present? */
-    if (!(*mask & fields[i].field.mask)) {
+    if (!(header.mask & fields[i].field.mask)) {
       continue;
     }
 
     if (position == i) {
       /* Read the data. */
-      offset = csds_mapped_file_read_data(log_map, offset, fields[i].field.size,
-                                          output);
+      offset = log_map.ReadData(offset, fields[i].field.size, output);
     } else {
       /* Update the buffer's position. */
       offset += fields[i].field.size;
@@ -142,34 +137,29 @@ INLINE static enum csds_special_flags csds_unpack_flags_and_data(
  * @brief Read the special flag of a particle (of any type) in the log file.
  *
  * @param offset offset of the record to read.
- * @param mask (out) The mask of the record.
- * @param h_offset (out) Difference of offset with the next record.
+ * @param header (out) The header of the record.
  * @param data (out) The data of the flag.
  * @param part_type (out) The type of particle raising this flag.
  *
  * @return The special flag.
  */
 INLINE static enum csds_special_flags csds_particle_read_special_flag(
-    size_t offset, mask_type *mask, size_t *h_offset, int *data, int *part_type,
-    struct mapped_file &map) {
-
-  *mask = 0;
-  *h_offset = 0;
+    size_t offset, struct record_header &header, int *data, int *part_type,
+    MappedFile &map) {
 
   /* Read the record's mask. */
-  offset = csds_mapped_file_read_mask(map, offset, mask, h_offset);
+  offset = map.ReadRecordHeader(offset, header);
 
 #ifdef CSDS_DEBUG_CHECKS
   /* Check if it is not a time record. */
-  if (*mask == CSDS_TIMESTAMP_MASK) {
+  if (header.mask == CSDS_TIMESTAMP_MASK) {
     csds_error("Cannot read a particle from timestep record.");
   }
 #endif
 
   /* Read the special flag */
   uint32_t packed_data = 0;
-  offset = csds_mapped_file_read_data(map, offset, CSDS_SPECIAL_FLAGS_SIZE,
-                                      &packed_data);
+  offset = map.ReadData(offset, CSDS_SPECIAL_FLAGS_SIZE, &packed_data);
 
   return csds_unpack_flags_and_data(packed_data, data, part_type);
 }
diff --git a/src/csds_reader.cpp b/src/csds_reader.cpp
index f70e8bb69031bf5190982ab02f9d1c879826012c..0a751ca942bcbb3d9cad6da5f303e7a8dd4d5fe2 100644
--- a/src/csds_reader.cpp
+++ b/src/csds_reader.cpp
@@ -51,7 +51,8 @@ Reader::Reader(const string basename, int verbose, int number_index,
   this->mTime.time_offset = 0;
   this->mUseCache = use_cache;
   this->mBasename = basename;
-  this->mLog = new struct csds_logfile;
+  this->mIndex.index_prev = NULL;
+  this->mIndex.index_next = NULL;
 
   /* Initialize the reader variables. */
   this->mVerbose = verbose;
@@ -64,8 +65,7 @@ Reader::Reader(const string basename, int verbose, int number_index,
   csds_parameters_init(&this->mParams, params_filename, this->mVerbose);
 
   /* Initialize the log file. */
-  csds_logfile_init_from_file(this->mLog, basename,
-                              /* only_header */ 0, this->mVerbose);
+  this->mLog = new LogFile(basename, /* only_header */ 0, this->mVerbose);
 
   /* Initialize the index files and creates them if needed */
   this->InitIndex(number_index, restart_init);
@@ -86,10 +86,6 @@ Reader::Reader(const string basename, int verbose, int number_index,
  * @param restart Are we restarting the generation of index files?
  */
 void Reader::InitIndex(int number_index, int restart) {
-  /* Initialize the csds_index */
-  csds_index_init(&this->mIndex.index_prev);
-  csds_index_init(&this->mIndex.index_next);
-
   /* Count the number of files */
   int count = 0;
   while (1) {
@@ -139,23 +135,23 @@ void Reader::InitIndex(int number_index, int restart) {
     string filename = this->GetIndexName(i);
 
     /* Read the header */
-    csds_index_read_header(&this->mIndex.index_prev, filename, this->mVerbose);
+    this->mIndex.index_prev = new IndexFile(filename, this->mVerbose);
 
     /* Save the required information */
-    this->mIndex.times[i] = this->mIndex.index_prev.time;
-    this->mIndex.int_times[i] = this->mIndex.index_prev.integer_time;
+    this->mIndex.times[i] = this->mIndex.index_prev->time;
+    this->mIndex.int_times[i] = this->mIndex.index_prev->integer_time;
   }
 }
 
 /** @brief Free the reader. */
 Reader::~Reader() {
   /* Free the log. */
-  csds_logfile_free(this->mLog);
   delete this->mLog;
 
   /* Free the index */
   if (this->mTime.time != -1.) {
-    csds_index_free(&this->mIndex.index_prev);
+    delete this->mIndex.index_prev;
+    delete this->mIndex.index_next;
   }
 
   free(this->mIndex.int_times);
@@ -214,22 +210,22 @@ void Reader::SetTime(double time) {
   string filename_next = this->GetIndexName(left + 1);
 
   /* Check if the file is already mapped */
-  if (this->mIndex.index_prev.index.map != NULL) {
-    csds_index_free(&this->mIndex.index_prev);
+  if (this->mIndex.index_prev != NULL) {
+    delete this->mIndex.index_prev;
+    this->mIndex.index_prev = NULL;
   }
-  if (this->mIndex.index_next.index.map != NULL) {
-    csds_index_free(&this->mIndex.index_next);
+  if (this->mIndex.index_next != NULL) {
+    delete this->mIndex.index_next;
+    this->mIndex.index_next = NULL;
   }
 
   /* Read the file */
-  csds_index_read_header(&this->mIndex.index_prev, filename_prev,
-                         this->mVerbose);
-  csds_index_map_file(&this->mIndex.index_prev, filename_prev,
+  this->mIndex.index_prev = new IndexFile(filename_prev, this->mVerbose);
+  csds_index_map_file(this->mIndex.index_prev, filename_prev,
                       /* sorted */ 1, this->mVerbose);
 
-  csds_index_read_header(&this->mIndex.index_next, filename_next,
-                         this->mVerbose);
-  csds_index_map_file(&this->mIndex.index_next, filename_next,
+  this->mIndex.index_next = new IndexFile(filename_next, this->mVerbose);
+  csds_index_map_file(this->mIndex.index_next, filename_next,
                       /* sorted */ 1, this->mVerbose);
 
   /* Get the offset of the time chunk */
@@ -266,16 +262,16 @@ size_t Reader::CountNumberNewParticles(enum part_type part_type) {
 
   /* Get the history of created particles. */
   struct index_data *data =
-      csds_index_get_created_history(&this->mIndex.index_next, part_type);
+      csds_index_get_created_history(this->mIndex.index_next, part_type);
 
   /* Do we have any new particle? */
-  if (this->mIndex.index_next.nparts_created[part_type] == 0 ||
+  if (this->mIndex.index_next->nparts_created[part_type] == 0 ||
       threshold < data[0].offset) {
     return 0;
   }
 
   /* Perform a binary search */
-  size_t right = this->mIndex.index_next.nparts_created[part_type] - 1;
+  size_t right = this->mIndex.index_next->nparts_created[part_type] - 1;
   size_t left = 0;
   while (left <= right) {
     size_t m = (left + right) / 2;
@@ -315,16 +311,16 @@ size_t Reader::CountNumberRemovedParticles(enum part_type part_type) {
 
   /* Get the history of created particles. */
   struct index_data *data =
-      csds_index_get_removed_history(&this->mIndex.index_next, part_type);
+      csds_index_get_removed_history(this->mIndex.index_next, part_type);
 
   /* Do we have any new particle? */
-  if (this->mIndex.index_next.nparts_removed[part_type] == 0 ||
+  if (this->mIndex.index_next->nparts_removed[part_type] == 0 ||
       threshold < data[0].offset) {
     return 0;
   }
 
   /* Perform a binary search */
-  size_t right = this->mIndex.index_next.nparts_removed[part_type] - 1;
+  size_t right = this->mIndex.index_next->nparts_removed[part_type] - 1;
   size_t left = 0;
   while (left <= right) {
     size_t m = (left + right) / 2;
@@ -367,7 +363,7 @@ void Reader::GetNumberParticles(
     }
 
     /* Count the number of particles present in the last index file. */
-    const uint64_t count_prev = this->mIndex.index_prev.nparts[i];
+    const uint64_t count_prev = this->mIndex.index_prev->nparts[i];
     /* Count the number of particles that have been created since last index. */
     const uint64_t count_new = this->CountNumberNewParticles((enum part_type)i);
     /* Count the number of particles that have been removed since last index. */
@@ -449,8 +445,7 @@ int Reader::ReadParticle(double time,
   }
 
   /* Record's header information */
-  mask_type mask = 0;
-  size_t h_offset;
+  struct record_header header;
 
   /* The offset used for all the manipulations */
   size_t offset = offset_from_index;
@@ -463,14 +458,14 @@ int Reader::ReadParticle(double time,
   while (offset < offset_time) {
     *number_jumps += 1;
     /* Read the particle. */
-    csds_mapped_file_read_mask(this->mLog->log, offset, &mask, &h_offset);
+    this->mLog->log->ReadRecordHeader(offset, header);
 
     /* Is the particle removed from the logfile? */
-    if (mask & CSDS_SPECIAL_FLAGS_MASK) {
+    if (header.mask & CSDS_SPECIAL_FLAGS_MASK) {
       int data = 0;
       int part_type = 0;
       enum csds_special_flags flag = csds_particle_read_special_flag(
-          offset, &mask, &h_offset, &data, &part_type, this->mLog->log);
+          offset, header, &data, &part_type, *this->mLog->log);
 
 #ifdef CSDS_DEBUG_CHECKS
       if (part_type != type) {
@@ -485,18 +480,18 @@ int Reader::ReadParticle(double time,
     }
 
     /* Check if there is a next record (avoid infinite loop). */
-    if (h_offset == 0) {
+    if (header.offset == 0) {
       csds_error("No next record found.");
     }
 
     /* Go to the next record. */
-    offset += h_offset;
+    offset += header.offset;
   }
 
   /* Set the next record */
   size_t offset_next = offset;
   /* Go back before offset_time */
-  offset -= h_offset;
+  offset -= header.offset;
 
   /* Loop over each field. */
   for (size_t field = 0; field < fields_wanted.size(); field++) {
@@ -505,34 +500,31 @@ int Reader::ReadParticle(double time,
 
     /* Read the field */
     csds_particle_read_field(offset, current_output, current_field,
-                             /* derivative */ 0, &mask, &h_offset,
-                             h->fields[type], h->number_fields[type],
-                             this->mLog->log);
+                             /* derivative */ 0, header, h->fields[type],
+                             h->number_fields[type], *this->mLog->log);
 
     /* Deal with the first derivative. */
     int first_found = current_field->first.field != field_enum_none &&
-                      mask & current_field->first.mask;
+                      header.mask & current_field->first.mask;
     char first_deriv[current_field->first.size];
 
     if (first_found) {
       /* Read the first derivative */
       csds_particle_read_field(offset, first_deriv, current_field,
-                               /* derivative */ 1, &mask, &h_offset,
-                               h->fields[type], h->number_fields[type],
-                               this->mLog->log);
+                               /* derivative */ 1, header, h->fields[type],
+                               h->number_fields[type], *this->mLog->log);
     }
 
     /* Deal with the second derivative. */
     int second_found = current_field->second.field != field_enum_none &&
-                       mask & current_field->second.mask;
+                       header.mask & current_field->second.mask;
     char second_deriv[current_field->second.size];
 
     if (second_found) {
       /* Read the first derivative */
       csds_particle_read_field(offset, second_deriv, current_field,
-                               /* derivative */ 2, &mask, &h_offset,
-                               h->fields[type], h->number_fields[type],
-                               this->mLog->log);
+                               /* derivative */ 2, header, h->fields[type],
+                               h->number_fields[type], *this->mLog->log);
     }
 
     /* Get the time. */
@@ -540,29 +532,27 @@ int Reader::ReadParticle(double time,
     double time_before = time_array_get_time(&this->mLog->times, offset);
 
     /* Get the mask */
-    csds_mapped_file_read_mask(this->mLog->log, offset_next, &mask, &h_offset);
+    this->mLog->log->ReadRecordHeader(offset_next, header);
 
     /* Output after the requested time. */
     char output_after[current_field->field.size];
 
     /* Read the field */
     csds_particle_read_field(offset_next, output_after, current_field,
-                             /* derivative */ 0, &mask, &h_offset,
-                             h->fields[type], h->number_fields[type],
-                             this->mLog->log);
+                             /* derivative */ 0, header, h->fields[type],
+                             h->number_fields[type], *this->mLog->log);
 
     /* Deal with the first derivative. */
     char first_deriv_after[current_field->first.size];
 
     /* Did we find the derivative before and in this record? */
     first_found = current_field->first.field != field_enum_none &&
-                  first_found && mask & current_field->first.mask;
+                  first_found && header.mask & current_field->first.mask;
     if (first_found) {
       /* Read the first derivative */
       csds_particle_read_field(offset_next, first_deriv_after, current_field,
-                               /*derivative*/ 1, &mask, &h_offset,
-                               h->fields[type], h->number_fields[type],
-                               this->mLog->log);
+                               /*derivative*/ 1, header, h->fields[type],
+                               h->number_fields[type], *this->mLog->log);
     }
 
     /* Deal with the second derivative. */
@@ -570,13 +560,12 @@ int Reader::ReadParticle(double time,
 
     /* Did we find the derivative before and in this record? */
     second_found = current_field->second.field != field_enum_none &&
-                   second_found && mask & current_field->second.mask;
+                   second_found && header.mask & current_field->second.mask;
     if (second_found) {
       /* Read the second derivative */
       csds_particle_read_field(offset_next, second_deriv_after, current_field,
-                               /* derivative */ 2, &mask, &h_offset,
-                               h->fields[type], h->number_fields[type],
-                               this->mLog->log);
+                               /* derivative */ 2, header, h->fields[type],
+                               h->number_fields[type], *this->mLog->log);
     }
 
     /* Get the time. */
@@ -636,12 +625,12 @@ void Reader::ReadAllParticlesSingleType(
   }
 
   /* Create some information from the index files */
-  const size_t size_index = this->mIndex.index_prev.nparts[type];
+  const size_t size_index = this->mIndex.index_prev->nparts[type];
   const size_t size_history = this->CountNumberNewParticles(type);
 
-  struct index_data *data = csds_index_get_data(&this->mIndex.index_prev, type);
+  struct index_data *data = csds_index_get_data(this->mIndex.index_prev, type);
   struct index_data *data_created =
-      csds_index_get_created_history(&this->mIndex.index_next, type);
+      csds_index_get_created_history(this->mIndex.index_next, type);
 
   /* Current index to read */
   size_t current_index = 0;
@@ -793,7 +782,7 @@ void Reader::ReadParticlesFromIdsSingleType(
 
     /* Get the offset */
     size_t offset = 0;
-    int found = csds_index_get_offset(&this->mIndex.index_prev, (int64_t)ids[i],
+    int found = csds_index_get_offset(this->mIndex.index_prev, (int64_t)ids[i],
                                       type, &offset);
 
     /* Deal with the particles not found */
@@ -924,21 +913,19 @@ size_t Reader::ReadRecord(void **output, double *time, int *is_particle,
   /* Get a few pointers. */
   const struct header *h = &this->mLog->header;
 
-  mask_type mask = 0;
-  size_t h_offset = 0;
-
   /* Read the record's mask. */
-  csds_mapped_file_read_mask(this->mLog->log, offset, &mask, &h_offset);
+  struct record_header header;
+  this->mLog->log->ReadRecordHeader(offset, header);
 
-  *is_particle = !(mask & CSDS_TIMESTAMP_MASK);
+  *is_particle = !(header.mask & CSDS_TIMESTAMP_MASK);
   /* The record is a particle. */
   if (*is_particle) {
     size_t offset_tmp = offset;
     for (int i = 0; i < h->number_fields[csds_type_gas]; i++) {
       offset = csds_particle_read_field(
           offset_tmp, output[i], &h->fields[csds_type_gas][i],
-          /* derivative */ 0, &mask, &h_offset, h->fields[csds_type_gas],
-          h->number_fields[csds_type_gas], this->mLog->log);
+          /* derivative */ 0, header, h->fields[csds_type_gas],
+          h->number_fields[csds_type_gas], *this->mLog->log);
     }
   }
   /* The record is a timestamp. */
@@ -982,21 +969,19 @@ int Reader::UpdateSingleParticle(size_t index, enum part_type type, double time,
 
   /* Update the cache if needed */
   if (offset_next < offset_time) {
-    mask_type mask = 0;
-    size_t h_offset = 0;
+    struct record_header header;
 
     /* Get the new offset */
     while (offset_next < offset_time) {
       /* Read the particle. */
-      csds_mapped_file_read_mask(this->mLog->log, offset_next, &mask,
-                                 &h_offset);
+      this->mLog->log->ReadRecordHeader(offset_next, header);
 
       /* Is the particle removed? */
-      if (mask & CSDS_SPECIAL_FLAGS_MASK) {
+      if (header.mask & CSDS_SPECIAL_FLAGS_MASK) {
         int data = 0;
         int part_type = 0;
         enum csds_special_flags flag = csds_particle_read_special_flag(
-            offset_next, &mask, &h_offset, &data, &part_type, this->mLog->log);
+            offset_next, header, &data, &part_type, *this->mLog->log);
 
 #ifdef CSDS_DEBUG_CHECKS
         if (part_type != type) {
@@ -1011,15 +996,15 @@ int Reader::UpdateSingleParticle(size_t index, enum part_type type, double time,
       }
 
       /* Check if there is a next record (avoid infinite loop). */
-      if (h_offset == 0) {
+      if (header.offset == 0) {
         csds_error("No next record found.");
       }
 
-      offset_next += h_offset;
+      offset_next += header.offset;
     }
 
     /* Get a few variables for later */
-    size_t offset_before = offset_next - h_offset;
+    size_t offset_before = offset_next - header.offset;
     time_before = time_array_get_time(&this->mLog->times, offset_before);
     time_after = time_array_get_time(&this->mLog->times, offset_next);
 
@@ -1041,26 +1026,23 @@ int Reader::UpdateSingleParticle(size_t index, enum part_type type, double time,
                              cache->total_size * index + cache->offset[i];
 
       csds_particle_read_field(offset_next, current_output, info,
-                               /* derivative */ 0, &mask, &h_offset,
-                               h->fields[type], h->number_fields[type],
-                               this->mLog->log);
+                               /* derivative */ 0, header, h->fields[type],
+                               h->number_fields[type], *this->mLog->log);
       current_output += info->field.size;
 
       /* Read the first derivative */
       if (info->first.field != field_enum_none) {
         csds_particle_read_field(offset_next, current_output, info,
-                                 /* derivative */ 1, &mask, &h_offset,
-                                 h->fields[type], h->number_fields[type],
-                                 this->mLog->log);
+                                 /* derivative */ 1, header, h->fields[type],
+                                 h->number_fields[type], *this->mLog->log);
         current_output += info->first.size;
       }
 
       /* Read the second derivative */
       if (info->second.field != field_enum_none) {
         csds_particle_read_field(offset_next, current_output, info,
-                                 /* derivative */ 2, &mask, &h_offset,
-                                 h->fields[type], h->number_fields[type],
-                                 this->mLog->log);
+                                 /* derivative */ 2, header, h->fields[type],
+                                 h->number_fields[type], *this->mLog->log);
       }
     }
   }
@@ -1173,26 +1155,26 @@ void Reader::UpdateParticlesSingleType(
 
   /* Check if the index files are compatible */
   size_t offset_index = time_array_get_index_from_time(
-      &this->mLog->times, this->mIndex.index_prev.time);
+      &this->mLog->times, this->mIndex.index_prev->time);
   offset_index = this->mLog->times.records[offset_index].offset;
   if (offset_index > this->mCache.last_time_offset) {
     csds_error("Requesting an update over more than one index file");
   }
   offset_index = time_array_get_index_from_time(&this->mLog->times,
-                                                this->mIndex.index_next.time);
+                                                this->mIndex.index_next->time);
   offset_index = this->mLog->times.records[offset_index].offset;
   const int do_previous = this->mCache.last_time_offset < offset_index;
 
   /* Get the histories */
   struct index_data *prev_created =
-      csds_index_get_created_history(&this->mIndex.index_prev, type);
+      csds_index_get_created_history(this->mIndex.index_prev, type);
   struct index_data *next_created =
-      csds_index_get_created_history(&this->mIndex.index_next, type);
+      csds_index_get_created_history(this->mIndex.index_next, type);
 
   /* Go to the last particle created */
   struct index_data *index_data = do_previous ? prev_created : next_created;
-  size_t size_max = do_previous ? this->mIndex.index_prev.nparts_created[type]
-                                : this->mIndex.index_next.nparts_created[type];
+  size_t size_max = do_previous ? this->mIndex.index_prev->nparts_created[type]
+                                : this->mIndex.index_next->nparts_created[type];
 
   // TODO use interpolation search
   size_t left = 0;
@@ -1252,7 +1234,7 @@ void Reader::UpdateParticlesSingleType(
   /* Do the same for the next index file */
   if (do_previous) {
     index_data = next_created;
-    size_max = this->mIndex.index_next.nparts_created[type];
+    size_max = this->mIndex.index_next->nparts_created[type];
     for (size_t i = 0; i < size_max; i++) {
       /* Stop as soon as we reach the required offset */
       if (index_data[i].offset > offset_time) break;
@@ -1296,6 +1278,8 @@ void Reader::UpdateParticles(
     csds_error("Cannot update the particles without cache");
   }
 
+  // TODO Set time
+
   /* Prepare the cache */
   csds_cache_reset_current_index(&this->mCache);
 
diff --git a/src/csds_reader.hpp b/src/csds_reader.hpp
index 314b22daa355797a471f11fa01d80d2ca4b86044..2b0ccc03df5b75c4e49e50e2439c9fc08f8c9e45 100644
--- a/src/csds_reader.hpp
+++ b/src/csds_reader.hpp
@@ -107,10 +107,10 @@ class Reader {
 
   struct {
     /* Information contained in the previous index file. */
-    struct csds_index index_prev;
+    IndexFile *index_prev;
 
     /* Information contained in the next index file. */
-    struct csds_index index_next;
+    IndexFile *index_next;
 
     /* Number of index files */
     int n_files;
@@ -123,7 +123,7 @@ class Reader {
   } mIndex;
 
   /* Informations contained in the file header. */
-  struct csds_logfile *mLog;
+  LogFile *mLog;
 
   /* Information about the current time */
   struct {
diff --git a/src/csds_reader_generate_index.cpp b/src/csds_reader_generate_index.cpp
index 08cc2bace51dbb4bd55145cdc3af54f87db02308..5914a8447ec81e0b0b34b1cd4cf5035f9cafcba6 100644
--- a/src/csds_reader_generate_index.cpp
+++ b/src/csds_reader_generate_index.cpp
@@ -288,7 +288,7 @@ size_t Reader::GetInitialState(struct csds_hashmap **current_state,
   const high_resolution_clock::time_point init = high_resolution_clock::now();
 
   /* Get a few variables. */
-  struct csds_logfile *log = this->mLog;
+  LogFile *log = this->mLog;
   const struct header *h = &log->header;
   const int size_record_header = CSDS_MASK_SIZE + CSDS_OFFSET_SIZE;
 
@@ -313,48 +313,38 @@ size_t Reader::GetInitialState(struct csds_hashmap **current_state,
   size_t offset_first = h->offset_first_record;
 
   /* Skip the time record */
-  mask_type time_mask = 0;
-  csds_mapped_file_read_mask(log->log, offset_first, &time_mask, NULL);
-  const int time_size = header_get_record_size_from_mask(h, time_mask);
+  struct record_header header;
+  log->log->ReadRecordHeader(offset_first, header);
+  const int time_size = header_get_record_size_from_mask(h, header.mask);
   offset_first += time_size + size_record_header;
 
   /* Get the initial state */
   float next_percent = 0;
   for (size_t offset = offset_first; offset < offset_max;) {
     /* Get the particle type */
-    mask_type mask = 0;
-    size_t prev_offset = 0;
     int part_type = 0;
     int data = 0;
 
     enum csds_special_flags flag = csds_particle_read_special_flag(
-        offset, &mask, &prev_offset, &data, &part_type, log->log);
+        offset, header, &data, &part_type, *log->log);
     if (flag != csds_flag_create) {
       csds_error("Reading a particle from ICs without the created flag.");
     }
 
-    /* TODO Implement missing particle types */
-    if (part_type == csds_type_neutrino || part_type == csds_type_sink ||
-        part_type == csds_type_black_hole) {
-      csds_error(
-          "Particle type not implemented: " << part_type_names[part_type]);
-    }
-
     /* Get the mask for the IDs */
     const struct field_information *field_id =
         header_get_field_from_name(h, "ParticleIDs", (enum part_type)part_type);
 
     /* Get the particle ID */
-    if (!(mask & field_id->field.mask)) {
+    if (!(header.mask & field_id->field.mask)) {
       csds_error("The particle ID is missing in the first log");
     }
 
     /* Read the particle ID */
     int64_t id = 0;
     csds_particle_read_field(offset, &id, field_id,
-                             /* derivative */ 0, &mask, &prev_offset,
-                             h->fields[part_type], h->number_fields[part_type],
-                             this->mLog->log);
+                             /* derivative */ 0, header, h->fields[part_type],
+                             h->number_fields[part_type], *this->mLog->log);
 
     /* Log the particle */
     struct index_data item = {id, offset};
@@ -364,7 +354,7 @@ size_t Reader::GetInitialState(struct csds_hashmap **current_state,
     }
 
     /* Increment the offset */
-    const int record_size = header_get_record_size_from_mask(h, mask);
+    const int record_size = header_get_record_size_from_mask(h, header.mask);
     offset += record_size + size_record_header;
 
     /* Print the progress */
@@ -407,49 +397,47 @@ size_t Reader::GetLastOffsetBefore(const struct index_data *data,
                                    size_t offset_limit) {
 
   /* Get a the logfile */
-  struct csds_logfile *log = this->mLog;
+  LogFile *log = this->mLog;
 
   size_t current_offset = data->offset;
 
   /* Get the full mask */
-  mask_type full_mask = 0;
-  size_t h_offset = 0;
-  csds_mapped_file_read_mask(log->log, current_offset, &full_mask, &h_offset);
+  struct record_header last_header;
+  log->log->ReadRecordHeader(current_offset, last_header);
 
   /* Ensures that a special flag is present in the mask */
-  full_mask |= CSDS_SPECIAL_FLAGS_MASK;
+  last_header.mask |= CSDS_SPECIAL_FLAGS_MASK;
 
   /* Now remove it */
-  full_mask = full_mask ^ CSDS_SPECIAL_FLAGS_MASK;
+  last_header.mask = last_header.mask ^ CSDS_SPECIAL_FLAGS_MASK;
 
   /* Find the last offset before the current time */
   size_t last_full_offset = current_offset;
-  current_offset += h_offset;
+  current_offset += last_header.offset;
   while (1) {
     /* Get the mask */
-    mask_type mask = 0;
-    h_offset = 0;
-    csds_mapped_file_read_mask(log->log, current_offset, &mask, &h_offset);
+    struct record_header cur_header;
+    log->log->ReadRecordHeader(current_offset, cur_header);
 
     /* update the offset */
-    current_offset += h_offset;
+    current_offset += cur_header.offset;
     if (current_offset > offset_limit) {
       break;
     }
 
     /* The particle should not have a special flag
        due to the previous loop */
-    if (mask & CSDS_SPECIAL_FLAGS_MASK) {
+    if (cur_header.mask & CSDS_SPECIAL_FLAGS_MASK) {
       csds_error("Found a special flag when updating the particles");
     }
 
     /* Update the last full offset */
-    if (full_mask == mask) {
+    if (last_header.mask == cur_header.mask) {
       last_full_offset = current_offset;
     }
 
     /* Are we at the end of the file? */
-    if (h_offset == 0) {
+    if (cur_header.offset == 0) {
       break;
     }
   }
@@ -478,7 +466,7 @@ size_t Reader::UpdateStateToNextIndex(size_t init_offset,
                                       struct csds_hashmap **current_state,
                                       struct index_writer *parts_created,
                                       struct index_writer *parts_removed) {
-  struct csds_logfile *log = this->mLog;
+  LogFile *log = this->mLog;
   const struct header *h = &log->header;
   const int size_record_header = CSDS_MASK_SIZE + CSDS_OFFSET_SIZE;
 
@@ -509,27 +497,27 @@ size_t Reader::UpdateStateToNextIndex(size_t init_offset,
                              "Looking for new or removed particles");
       }
     }
-    mask_type mask = 0;
-    size_t h_offset = 0;
     int part_type = -1;  // only available if the record is flagged.
     int data = 0;
 
     /* Get the mask */
-    csds_mapped_file_read_mask(log->log, offset, &mask, &h_offset);
+    struct record_header header;
+    log->log->ReadRecordHeader(offset, header);
 
     /* Go to the next record */
     const size_t old_offset = offset;
-    offset += header_get_record_size_from_mask(h, mask);
+    offset += header_get_record_size_from_mask(h, header.mask);
     offset += size_record_header;
 
     /* Check if we have a particle with a flag */
-    if (mask & CSDS_TIMESTAMP_MASK || !(mask & CSDS_SPECIAL_FLAGS_MASK)) {
+    if (header.mask & CSDS_TIMESTAMP_MASK ||
+        !(header.mask & CSDS_SPECIAL_FLAGS_MASK)) {
       continue;
     }
 
     /* Get the special flag */
     enum csds_special_flags flag = csds_particle_read_special_flag(
-        old_offset, &mask, &h_offset, &data, &part_type, log->log);
+        old_offset, header, &data, &part_type, *log->log);
 
 #ifdef CSDS_DEBUG_CHECKS
     if (flag == csds_flag_none) {
@@ -550,9 +538,8 @@ size_t Reader::UpdateStateToNextIndex(size_t init_offset,
     /* Read the ID */
     int64_t id = 0;
     csds_particle_read_field(old_offset, &id, field_id,
-                             /* derivative */ 0, &mask, &h_offset,
-                             h->fields[part_type], h->number_fields[part_type],
-                             this->mLog->log);
+                             /* derivative */ 0, header, h->fields[part_type],
+                             h->number_fields[part_type], *this->mLog->log);
 
     /* Add the particle to the arrays */
     if (flag == csds_flag_change_type || flag == csds_flag_mpi_exit ||
@@ -658,7 +645,7 @@ size_t Reader::UpdateStateToNextIndex(size_t init_offset,
  */
 void Reader::GenerateIndexFiles(int number_index, int current_index) {
   /* Get a few pointers */
-  struct csds_logfile *log = this->mLog;
+  LogFile *log = this->mLog;
   const struct header *h = &log->header;
 
   /* Write a quick message */
@@ -722,16 +709,11 @@ void Reader::GenerateIndexFiles(int number_index, int current_index) {
   }
   /* We are restarting => read state from file */
   else {
-
-    /* Initialize the index file */
-    struct csds_index index;
-    csds_index_init(&index);
-
-    /* Get its name */
+    /* Get the index file name */
     string filename = this->GetIndexName(current_index - 1);
 
-    /* Read it */
-    csds_index_read_header(&index, filename, this->mVerbose);
+    /* Initialize the index file */
+    IndexFile index(filename, this->mVerbose);
     csds_index_map_file(&index, filename, /* sorted */ 1, this->mVerbose);
 
     /* Loop over all the particle types */
@@ -771,9 +753,6 @@ void Reader::GenerateIndexFiles(int number_index, int current_index) {
             "The time in the index file and the expected one do not match");
       }
     }
-
-    /* Cleanup */
-    csds_index_free(&index);
   }
 
   /* Compute the state of all the other files and write them. */
diff --git a/src/csds_time.cpp b/src/csds_time.cpp
index 71f0521cb3e78ac0ed178a4485874f9d616cb37e..c269e17b241472e35f2382acca0c99c09dd50718 100644
--- a/src/csds_time.cpp
+++ b/src/csds_time.cpp
@@ -92,27 +92,25 @@ void time_array_append(struct time_array *t, const integertime_t int_time,
  * @return The offset after the time record
  */
 size_t time_read(struct time_record *time_record, size_t offset,
-                 struct csds_logfile *logfile) {
+                 LogFile *logfile) {
 
   /* Initialize variables. */
-  struct mapped_file &log = logfile->log;
+  MappedFile &log = *logfile->log;
 
-  mask_type mask = 0;
-  size_t prev_offset = 0;
   time_record->int_time = 0;
   time_record->time = 0;
 
   /* read record header. */
-  offset = csds_mapped_file_read_mask(log, offset, &mask, &prev_offset);
+  struct record_header header;
+  offset = log.ReadRecordHeader(offset, header);
 
   /* check if reading a time record. */
-  if (CSDS_TIMESTAMP_MASK != mask) csds_error("Not a time record.");
+  if (CSDS_TIMESTAMP_MASK != header.mask) csds_error("Not a time record.");
 
   /* read the record. */
-  offset = csds_mapped_file_read_data(
-      log, offset, sizeof(unsigned long long int), &time_record->int_time);
-  offset = csds_mapped_file_read_data(log, offset, sizeof(double),
-                                      &time_record->time);
+  offset = log.ReadData(offset, sizeof(unsigned long long int),
+                        &time_record->int_time);
+  offset = log.ReadData(offset, sizeof(double), &time_record->time);
 
   return offset;
 }
@@ -128,12 +126,12 @@ size_t time_offset_first_record(const struct header *h) {
 
   /* Initialize a few variables. */
   size_t offset = h->offset_first_record;
-  struct mapped_file &map = h->log->log;
+  MappedFile &map = *h->log->log;
 
-  mask_type mask = 0;
-  csds_mapped_file_read_mask(map, offset, &mask, NULL);
+  struct record_header header;
+  map.ReadRecordHeader(offset, header);
 
-  if (mask != CSDS_TIMESTAMP_MASK)
+  if (header.mask != CSDS_TIMESTAMP_MASK)
     csds_error("Log file should begin by timestep.");
 
   return h->offset_first_record;
@@ -209,7 +207,7 @@ void time_array_save(struct time_array *t, string basename) {
  * @param t The #time_array.
  * @param index The #csds_index that contains the time array.
  */
-void time_array_load(struct time_array *t, struct csds_index *index) {
+void time_array_load(struct time_array *t, IndexFile *index) {
   /* Ensure that the array is empty */
   if (t->capacity != 0) time_array_free(t);
 
@@ -247,9 +245,7 @@ int time_array_restore(struct time_array *t, const string basename,
   if (!savefile) return 0;
 
   /* Initialize the index file that might contain the time array */
-  struct csds_index index;
-  csds_index_init(&index);
-  csds_index_read_header(&index, filename, verbose);
+  IndexFile index(filename, verbose);
   csds_index_map_file(&index, filename, /* sorted */ 1, verbose);
 
   /* Check if the index file contains the time array */
@@ -257,13 +253,9 @@ int time_array_restore(struct time_array *t, const string basename,
 
     /* Load the time array */
     time_array_load(t, &index);
-    csds_index_free(&index);
     return 1;
   }
 
-  /* Free the memory. */
-  csds_index_free(&index);
-
   return 0;
 }
 
@@ -275,7 +267,7 @@ int time_array_restore(struct time_array *t, const string basename,
  * @param basename The basename of the files
  * @param verbose The verbose level
  */
-void time_array_populate(struct time_array *t, struct csds_logfile *log,
+void time_array_populate(struct time_array *t, LogFile *log,
                          const string basename, int verbose) {
 
   /* Try restoring the time array */
@@ -287,7 +279,7 @@ void time_array_populate(struct time_array *t, struct csds_logfile *log,
   }
 
   /* get file size. */
-  size_t file_size = log->log.mmap_size;
+  size_t file_size = log->log->mMapSize;
 
   /* get first timestamp. */
   size_t offset = time_offset_first_record(&log->header);
@@ -299,8 +291,8 @@ void time_array_populate(struct time_array *t, struct csds_logfile *log,
     time_array_append(t, time.int_time, time.time, offset);
 
     /* get next record. */
-    int test = tools_get_next_record(&log->header, log->log, &offset,
-                                     log->log.mmap_size);
+    int test = tools_get_next_record(&log->header, *log->log, &offset,
+                                     log->log->mMapSize);
     if (test == -1) break;
   }
 }
diff --git a/src/csds_time.hpp b/src/csds_time.hpp
index 8a0fc2dcaaf6d507f0dbb7c11b68ca2dbbc1e117..4a7cf3425a919d2ea6ce74ad0b9bb38c8a073eaa 100644
--- a/src/csds_time.hpp
+++ b/src/csds_time.hpp
@@ -26,7 +26,6 @@
 #include "csds_header.hpp"
 #include "csds_tools.hpp"
 
-typedef int8_t timebin_t;
 typedef long long integertime_t;
 
 class Reader;
@@ -75,11 +74,10 @@ struct time_array {
 
 void time_array_append(struct time_array *t, const integertime_t int_time,
                        const double time, const size_t offset);
-size_t time_read(struct time_record *time, size_t offset,
-                 struct csds_logfile *logfile);
+size_t time_read(struct time_record *time, size_t offset, LogFile *logfile);
 
 void time_array_init(struct time_array *t, size_t initial_size);
-void time_array_populate(struct time_array *t, struct csds_logfile *log,
+void time_array_populate(struct time_array *t, LogFile *log,
                          const std::string basename, int verbose);
 
 integertime_t time_array_get_integertime(struct time_array *t,
diff --git a/src/csds_tools.cpp b/src/csds_tools.cpp
index a7c1de69330a0f1cf4ff2c87aab0b838d7b84692..6fd6932ad5ef629f7a42b5a00a57691ef24a7576 100644
--- a/src/csds_tools.cpp
+++ b/src/csds_tools.cpp
@@ -39,7 +39,7 @@
  *
  * @return -1 if no next record, otherwise 0
  */
-int tools_get_next_record(const struct header *h, struct mapped_file &map,
+int tools_get_next_record(const struct header *h, MappedFile &map,
                           size_t *offset, size_t file_size) {
   if (header_is_forward(h)) return _tools_get_next_record_forward(map, offset);
   if (header_is_backward(h))
@@ -57,16 +57,16 @@ int tools_get_next_record(const struct header *h, struct mapped_file &map,
  *
  * @return error code, -1 if no next record
  */
-int _tools_get_next_record_forward(struct mapped_file &map, size_t *offset) {
-  size_t diff_offset = 0;
+int _tools_get_next_record_forward(MappedFile &map, size_t *offset) {
 
   /* Read the offset. */
-  csds_mapped_file_read_mask(map, *offset, NULL, &diff_offset);
+  struct record_header header;
+  map.ReadRecordHeader(*offset, header);
 
-  if (diff_offset == 0) return -1;
+  if (header.offset == 0) return -1;
 
   /* Set the absolute offset. */
-  *offset += diff_offset;
+  *offset += header.offset;
   return 0;
 }
 
@@ -81,9 +81,8 @@ int _tools_get_next_record_forward(struct mapped_file &map, size_t *offset) {
  *
  * @return error code, -1 if no next record
  */
-int _tools_get_next_record_backward(const struct header *h,
-                                    struct mapped_file &map, size_t *offset,
-                                    size_t file_size) {
+int _tools_get_next_record_backward(const struct header *h, MappedFile &map,
+                                    size_t *offset, size_t file_size) {
 #ifndef CSDS_DEBUG_CHECKS
   csds_error("Should not be used, method too slow");
 #endif
@@ -91,17 +90,16 @@ int _tools_get_next_record_backward(const struct header *h,
   size_t record_header = CSDS_MASK_SIZE + CSDS_OFFSET_SIZE;
 
   while (current_offset < file_size) {
-    mask_type mask = 0;
-    size_t prev_offset;
-    csds_mapped_file_read_mask(map, current_offset, &mask, &prev_offset);
+    struct record_header header;
+    map.ReadRecordHeader(current_offset, header);
 
-    prev_offset = current_offset - prev_offset - record_header;
-    if (*offset == prev_offset) {
+    header.offset = current_offset - header.offset - record_header;
+    if (*offset == header.offset) {
       *offset = current_offset - record_header;
       return 0;
     }
 
-    current_offset += header_get_record_size_from_mask(h, mask);
+    current_offset += header_get_record_size_from_mask(h, header.mask);
   }
 
   return -1;
@@ -117,44 +115,45 @@ int _tools_get_next_record_backward(const struct header *h,
  *
  * @return position after the record.
  */
-size_t tools_reverse_offset(const struct header *h, struct mapped_file &map,
+size_t tools_reverse_offset(const struct header *h, MappedFile &map,
                             size_t offset) {
-  mask_type mask = 0;
-  size_t prev_offset = 0;
   const size_t cur_offset = offset;
 
   /* read mask + offset. */
-  offset = csds_mapped_file_read_mask(map, offset, &mask, &prev_offset);
+  struct record_header header;
+  offset = map.ReadRecordHeader(offset, header);
 
   /* write offset of zero (in case it is the last record). */
   const size_t zero = 0;
   offset -= CSDS_OFFSET_SIZE;
-  offset = csds_mapped_file_write_data(map, offset, CSDS_OFFSET_SIZE, &zero);
+  offset = map.WriteData(offset, CSDS_OFFSET_SIZE, &zero);
 
   /* set offset after current record. */
-  offset += header_get_record_size_from_mask(h, mask);
+  offset += header_get_record_size_from_mask(h, header.mask);
   const size_t after_current_record = offset;
 
   /* first records do not have a previous partner. */
-  if (prev_offset == cur_offset) return after_current_record;
-  if (prev_offset > cur_offset)
-    csds_error("Unexpected offset: header " << prev_offset << ", current "
+  if (header.offset == cur_offset) return after_current_record;
+  if (header.offset > cur_offset)
+    csds_error("Unexpected offset: header " << header.offset << ", current "
                                             << cur_offset);
 
   /* modify previous offset. */
-  offset = cur_offset - prev_offset + CSDS_MASK_SIZE;
-  offset =
-      csds_mapped_file_write_data(map, offset, CSDS_OFFSET_SIZE, &prev_offset);
+  offset = cur_offset - header.offset + CSDS_MASK_SIZE;
+  offset = map.WriteData(offset, CSDS_OFFSET_SIZE, &header.offset);
 
 #ifdef CSDS_DEBUG_CHECKS
-  mask_type prev_mask = 0;
+  struct record_header prev_header;
   offset -= CSDS_MASK_SIZE + CSDS_OFFSET_SIZE;
-  csds_mapped_file_read_mask(map, offset, &prev_mask, NULL);
+  map.ReadRecordHeader(offset, prev_header);
 
   /* Check if we are not mixing timestamp and particles */
-  if ((prev_mask != CSDS_TIMESTAMP_MASK && mask == CSDS_TIMESTAMP_MASK) ||
-      (prev_mask == CSDS_TIMESTAMP_MASK && mask != CSDS_TIMESTAMP_MASK))
-    csds_error("Unexpected mask: " << mask << " got " << prev_mask);
+  if ((prev_header.mask != CSDS_TIMESTAMP_MASK &&
+       header.mask == CSDS_TIMESTAMP_MASK) ||
+      (prev_header.mask == CSDS_TIMESTAMP_MASK &&
+       header.mask != CSDS_TIMESTAMP_MASK))
+    csds_error("Unexpected mask: " << header.mask << " got "
+                                   << prev_header.mask);
 
 #endif  // CSDS_DEBUG_CHECKS
 
@@ -172,51 +171,51 @@ size_t tools_reverse_offset(const struct header *h, struct mapped_file &map,
  *
  * @return position after the record.
  */
-size_t tools_check_record_consistency(struct csds_logfile *log, size_t offset) {
+size_t tools_check_record_consistency(LogFile *log, size_t offset) {
 #ifndef CSDS_DEBUG_CHECKS
   csds_error("Should not check in non debug mode.");
 #endif
 
   const struct header *h = &log->header;
-  struct mapped_file &map = log->log;
+  MappedFile &map = *log->log;
   const size_t init_offset = offset;
 
-  mask_type mask;
-  size_t pointed_offset;
-
   /* read mask + offset. */
-  offset = csds_mapped_file_read_mask(map, offset, &mask, &pointed_offset);
+  struct record_header header;
+  offset = map.ReadRecordHeader(offset, header);
 
   /* set offset after current record. */
-  offset += header_get_record_size_from_mask(h, mask);
+  offset += header_get_record_size_from_mask(h, header.mask);
   const size_t offset_ret = offset;
 
   /* If something happened, skip the check. */
-  if (mask & CSDS_SPECIAL_FLAGS_MASK) {
+  if (header.mask & CSDS_SPECIAL_FLAGS_MASK) {
     return offset_ret;
   }
 
   /* get absolute offset. */
   if (header_is_forward(h))
-    pointed_offset += init_offset;
+    header.offset += init_offset;
   else if (header_is_backward(h)) {
-    if (init_offset < pointed_offset)
-      csds_error("Offset too large for mask: " << mask);
-    pointed_offset = init_offset - pointed_offset;
+    if (init_offset < header.offset)
+      csds_error("Offset too large for mask: " << header.mask);
+    header.offset = init_offset - header.offset;
   } else {
     csds_error("Offset are corrupted.");
   }
 
-  if (pointed_offset == init_offset || pointed_offset == 0) return offset_ret;
+  if (header.offset == init_offset || header.offset == 0) return offset_ret;
 
   /* read mask of the pointed record. */
-  mask_type pointed_mask = 0;
-  csds_mapped_file_read_mask(map, pointed_offset, &pointed_mask, NULL);
+  struct record_header pointed_header;
+  map.ReadRecordHeader(header.offset, pointed_header);
 
   /* check if not mixing timestamp and particles. */
-  if ((pointed_mask != CSDS_TIMESTAMP_MASK && mask == CSDS_TIMESTAMP_MASK) ||
-      (pointed_mask == CSDS_TIMESTAMP_MASK && mask != CSDS_TIMESTAMP_MASK))
-    csds_error("Error in the offset for mask: " << mask);
+  if ((pointed_header.mask != CSDS_TIMESTAMP_MASK &&
+       header.mask == CSDS_TIMESTAMP_MASK) ||
+      (pointed_header.mask == CSDS_TIMESTAMP_MASK &&
+       header.mask != CSDS_TIMESTAMP_MASK))
+    csds_error("Error in the offset for mask: " << header.mask);
 
   return offset_ret;
 }
diff --git a/src/csds_tools.hpp b/src/csds_tools.hpp
index 1b946fc33a2c15c10ddcb6f7089ab7b4649e9d5d..9e97a8abb76035b5c23c16cb8dc8dfebd6041df7 100644
--- a/src/csds_tools.hpp
+++ b/src/csds_tools.hpp
@@ -30,13 +30,12 @@
 #include "csds_inline.hpp"
 #include "csds_logfile_writer.h"
 
+class MappedFile;
+class LogFile;
+
 /* Define the size of all the fields. */
 #define member_size(type, member) sizeof(((type *)0)->member)
 
-struct header;
-class Reader;
-struct mapped_file;
-
 /**
  * @brief Structure dealing with reading / interpolating a field.
  */
@@ -51,15 +50,14 @@ struct csds_reader_field {
   void *second_deriv;
 };
 
-int tools_get_next_record(const struct header *h, struct mapped_file &map,
+int tools_get_next_record(const struct header *h, MappedFile &map,
                           size_t *offset, size_t file_size);
-int _tools_get_next_record_backward(const struct header *h,
-                                    struct mapped_file &map, size_t *offset,
-                                    size_t file_size);
-int _tools_get_next_record_forward(struct mapped_file &map, size_t *offset);
-size_t tools_reverse_offset(const struct header *h, struct mapped_file &map,
+int _tools_get_next_record_backward(const struct header *h, MappedFile &map,
+                                    size_t *offset, size_t file_size);
+int _tools_get_next_record_forward(MappedFile &map, size_t *offset);
+size_t tools_reverse_offset(const struct header *h, MappedFile &map,
                             size_t offset);
-size_t tools_check_record_consistency(struct csds_logfile *log, size_t offset);
+size_t tools_check_record_consistency(LogFile *log, size_t offset);
 
 void tools_print_progress(
     float percentage, const std::chrono::high_resolution_clock::time_point init,
diff --git a/tests/testLogfileHeader.cpp b/tests/testLogfileHeader.cpp
index b620f40149f8f3be9333117e1dd4d0218baf3835..74a0483cbf69484a1ce7feef3c77218683523da3 100644
--- a/tests/testLogfileHeader.cpp
+++ b/tests/testLogfileHeader.cpp
@@ -48,12 +48,9 @@ int main(void) {
 
   message("Reading the header.");
   /* Generate required structure for reading. */
-  struct csds_logfile logfile;
-
-  /* Read the header */
-  csds_logfile_init_from_file(&logfile, basename,
-                              /* only_header */ 1,
-                              /* verbose */ 2);
+  LogFile logfile(basename,
+                  /* only_header */ 1,
+                  /* verbose */ 2);
   /*
     Finally check everything.
   */
@@ -77,8 +74,5 @@ int main(void) {
   message("Checking offset direction");
   assert(h->offset_direction == csds_offset_backward);
 
-  /* Cleanup */
-  csds_logfile_free(&logfile);
-
   return 0;
 }
diff --git a/tests/testLogfileReader.cpp b/tests/testLogfileReader.cpp
index 21d27fee16d5a7c59a36e3f11f12da3f041eeb2a..bdc4a48f2df76043253a0fcb1c5a58b81a5baa02 100644
--- a/tests/testLogfileReader.cpp
+++ b/tests/testLogfileReader.cpp
@@ -49,7 +49,7 @@ void check_data(Reader &reader, struct csds_part *parts) {
   /* No need to check the header, this is already done in testHeader.c */
 
   /* Get required structures. */
-  struct csds_logfile *logfile = reader.mLog;
+  LogFile &logfile = *reader.mLog;
   struct header *h = &reader.mLog->header;
 
   /* Create a particle */
@@ -79,8 +79,8 @@ void check_data(Reader &reader, struct csds_part *parts) {
 
   /* Loop over each record. */
   for (size_t offset = reader.ReadRecord(output, &time, &is_particle,
-                                         logfile->header.offset_first_record);
-       offset < logfile->log.mmap_size;
+                                         logfile.header.offset_first_record);
+       offset < logfile.log->mMapSize;
        offset = reader.ReadRecord(output, &time, &is_particle, offset)) {
 
     /* Do the particle case */
diff --git a/tests/testVirtualReality.cpp b/tests/testVirtualReality.cpp
index 706b959dd883c78b829af4cd47c2918769d0c866..8cfab5a1441bba3e62a72d28b9f0c3294b27495e 100644
--- a/tests/testVirtualReality.cpp
+++ b/tests/testVirtualReality.cpp
@@ -100,9 +100,6 @@ int main(void) {
   output.emplace_back(n_tot, field_enum_coordinates);
   output.emplace_back(n_tot, field_enum_particles_ids);
 
-  /* Set the time of the next reading */
-  reader.SetTime(begin);
-
   /* Read the next time */
   reader.ReadAllParticles(begin, required_fields, output, n_parts);