summaryrefslogtreecommitdiffstats
path: root/ue4/mycpu/cmem.h
blob: 3f35a70e1ee760011c14ea671f86834c0322c2f3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/**
 * @module cmem
 * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348)
 * @brief  Memory template and memory definition for CCPU
 * @date   26.05.2009
 */

#ifndef CMEM_H
#define CMEM_H 1

#include <vector>
#include <istream>
#include <sstream>
#include <stdexcept>
#ifdef DEBUG
# include <iostream>
# include <iomanip>
#endif

/**
 * @class CMemError
 *
 * Exception thrown by implemententations of CMem
 */
class CMemError
 : public std::invalid_argument
{
  public:
    /**
     * @method CMemError
     * @brief  Default exception ctor
     * @param  what  message to pass along
     * @return -
     * @globalvars none
     * @exception  none
     * @pre  none
     * @post none
     */
    CMemError(const std::string& what)
      : std::invalid_argument(what)
    {}
};

/**
 * @class CMem
 *
 * Extends std::vector template for use as memory for CCPU.
 */
template <class T>
class CMem
  : public std::vector<T>
{
  typedef std::vector<T> super;
  typedef typename super::iterator iterator;
  using super::size;
  using super::begin;
  using super::end;

  public:
    /**
     * @method initialize
     * @brief  initialize the vector with the content of istream. istream is
     *         read per line. empty lines will add unitialized elements.
     * @param  in        inputstream to read from
     * @param  datatype  reference instance of datatype to copy from
     * @return void
     * @globalvars none
     * @exception  CMemError
     * @pre  none
     * @post none
     */
    void initialize(std::istream& in, T& datatype)
    {
      if (!in.good())
        return;

      std::string line;
      unsigned i = 0;
      while (!in.eof() && in.good())
      {
        ++i;
        std::getline(in, line);

        /* skip last line if it's empty */
        if (line.empty() && in.eof())
          break;

        T value(datatype);
        if (!line.empty())
        {
          /* simple boost::lexical_cast replacement */
          std::stringstream interpreter;
          if(!(interpreter << line && interpreter >> value && interpreter.get() == std::char_traits<char>::eof()))
          {
            std::stringstream sstr;
            sstr << "Unable to convert input (line " << i << ") to datatype";
            throw CMemError(sstr.str());
          }
        }

        push_back(value);
      }
    }

#if DEBUG
    /**
     * @method dump
     * @brief  dumps contents of vector to outputstream
     * @param  out  outputstream to write to
     * @return void
     * @globalvars none
     * @exception  none
     * @pre  none
     * @post none
     */
    void dump(std::ostream& out)
    {
      out << "[MEMORY DUMP]" << std::endl;
      unsigned i = 0;
      for(iterator it = begin(); it != end(); ++it)
      {
        out << "[" << std::setw(4) << std::setfill('0') << i << "]  "
            << *it << std::endl;
        ++i;
      }
    }
#endif
};

#endif

/* vim: set et sw=2 ts=2: */