Skip to content

File CoreObject.hpp

File List > core > CoreObject.hpp

Go to the documentation of this file



#pragma once

#include <fstream>
#include <functional>
#include <iostream>
#include <map>
#include <sstream>
#include <string>
#include <unordered_map>

#include "Serialize.hpp"

#ifndef NDEBUG
#define EXPERIMENTAL_FUNCTION __attribute__((annotate("experimental_function")))
#define EXPERIMENTAL_CLASS __attribute__((annotate("experimental_class")))

#else // NDEBUG *not* set, so debug mode.
#define EXPERIMENTAL_CLASS                       \
  __attribute__((annotate("experimental_class"), \
                 warning("This is an experimental class and should be used with caution.")))
#define EXPERIMENTAL_FUNCTION                                              \
  __attribute__((annotate("experimental_function"),                        \
                 warning("This is an experimental function and should be " \
                         "used with caution.")))
#endif

namespace cse491 {

class CoreObject {
protected:
  // -- Required functionality in all core classes --
  // These functions are core functionality that must be implemented in all derived
  // classes.  They will enable the public interface to behave correctly.

  virtual std::string GetTypeName_impl() const = 0;

  virtual void Serialize_impl(std::ostream &) const = 0;

  virtual void Deserialize_impl(std::istream &) = 0;

  // -- Helper functions --
  // The functions below can be used in derived classes to implement above functionality.

  void StartSerialize(std::ostream &os) const { os << ":::START " << GetTypeName() << "\n"; }

  void EndSerialize(std::ostream &os) const { os << ":::END " << GetTypeName() << "\n"; }

  bool StartDeserialize(std::istream &is) {
    std::string line;
    std::getline(is, line);
    std::string expected = ":::START " + GetTypeName();
    if (line != expected) {
      std::cerr << "Deserialization error.  Expected: " << expected << "...Found: " << line;
      return false;
    }
    return true;
  }

  bool EndDeserialize(std::istream &is) {
    std::string line;
    std::getline(is, line);
    std::string expected = ":::END " + GetTypeName();
    if (line != expected) {
      std::cerr << "Deserialization error.  Expected: " << expected << "...Found: " << line;
      return false;
    }
    return true;
  }


public:
  virtual ~CoreObject() {}

  auto operator<=>(const CoreObject &) const = default;

  std::string GetTypeName() const { return GetTypeName_impl(); }

  void Serialize(std::ostream &os) const {
    StartSerialize(os);
    Serialize_impl(os);
    EndSerialize(os);
  }

  void Deserialize(std::istream &is) {
    StartDeserialize(is);
    Deserialize_impl(is);
    EndDeserialize(is);
  }

  bool Serialize(std::string filename) const {
    std::ofstream os(filename);
    if (!os.is_open()) {
      std::cerr << "Could not open file '" << filename << "' for Serialize()." << std::endl;
      return false;
    }
    Serialize(os);
    return true;
  }

  bool Deserialize(std::string filename) {
    std::ifstream is(filename);
    if (!is.is_open()) {
      std::cerr << "Could not open file '" << filename << "' for Serialize()." << std::endl;
      return false;
    }
    Deserialize(is);
    return true;
  }
};

}  // End of namespace cse491