Program Listing for File container_templates.h

Return to documentation for file (src/container_templates.h)

//
// Created by Zayd Hammoudeh on 10/4/18.
//

#ifndef PROJECT02_CONTAINER_TEMPLATES_H
#define PROJECT02_CONTAINER_TEMPLATES_H

#include <string>
#include <map>
#include <set>
#include <iostream>
#include <stdexcept>

#include "keywords.h"
#include "exceptions.h"

template<typename _T>
class ObjectContainer {
 private:
  virtual bool exists(const std::string &obj_name) = 0;
  virtual void add(_T *new_obj) = 0;
  virtual _T* get(const std::string &str) = 0;
  virtual unsigned long count() = 0;
  virtual void clear() = 0;
 public:
  virtual ~ObjectContainer() = default;
  bool empty() { return count() == 0; };

  virtual const void print_original_src(unsigned int indent_depth) = 0;
};


template <typename _T>
class MapContainer : public ObjectContainer<_T> {
 public:
  MapContainer() = default;
  ~MapContainer() {
    for (const auto &pair : objs_)
      delete pair.second;
  }
  typename std::map<std::string, _T*>::iterator begin() { return objs_.begin(); }
  typename std::map<std::string, _T*>::iterator end() { return objs_.end(); }
  bool exists(const std::string &obj_name) override {
    return objs_.find(obj_name) != objs_.end();
  }
  void add(_T *new_obj) override {
    if (exists(new_obj->name_))
      throw ParserException("Duplicate object: " + new_obj->name_);
    objs_[new_obj->name_] = new_obj;
  }
  _T* get(const std::string &str) override {
    auto itr = objs_.find(str);
    if (itr == objs_.end())
      return OBJECT_NOT_FOUND;
    return itr->second;
  }
  unsigned long count() override { return objs_.size(); }
  void clear() override {
    objs_.clear();
  }
  const void print_original_src_(unsigned int indent_depth, const std::string &print_sep) {
    bool is_first = true;

    for (auto &pair : objs_) {
      if (!is_first)
        std::cout << print_sep;
      is_first = false;
      pair.second->print_original_src(indent_depth);
    }
  }

 protected:
  std::map<std::string,_T*> objs_;
};


template<typename _T>
class VectorContainer : public ObjectContainer<_T> {
 public:
  VectorContainer() = default;

  ~VectorContainer() {
    for (auto const &ptr : objs_)
      delete ptr;
  }
  typename std::vector<_T*>::const_iterator begin() const { return objs_.begin(); }
  typename std::vector<_T*>::iterator begin() { return objs_.begin(); }
  typename std::vector<_T*>::const_iterator end() const { return objs_.end(); }
  typename std::vector<_T*>::iterator end() { return objs_.end(); }
  bool exists(const std::string &name) override { return names_.find(name) != names_.end(); }
  void add(_T* new_obj) override {
    if (exists(new_obj->name_))
      throw DuplicateParamException(new_obj->name_);
    objs_.emplace_back(new_obj);
    names_.emplace(new_obj->name_);
  };
  _T* get(const std::string &name) override {
    if (!exists(name))
      return OBJECT_NOT_FOUND;

    for (auto &obj: objs_)
      if (obj->name_ == name)
        return obj;
    throw std::runtime_error("Unable to get object with key: " + name);
  }
  void clear() override {
    objs_.clear();
    names_.clear();
  }
  unsigned long count() override { return objs_.size(); }
  const void print_original_src_(unsigned int indent_depth, const std::string &print_sep) {
    bool is_first = true;

    for (auto &obj : objs_) {
      if (!is_first)
        std::cout << print_sep;
      is_first = false;
      obj->print_original_src(indent_depth);
    }
  }
  _T* operator [](int i) {
    return objs_[i];
  }

 private:
  const VectorContainer<_T>* get_const() { return static_cast<const VectorContainer<_T>*>(this); }

  std::vector<_T*> objs_;
  std::set<std::string> names_;
};

#endif //PROJECT02_CONTAINER_TEMPLATES_H