+/**
+ * Extract values stored in the checkpoint, and assign them to the provided
+ * array container.
+ *
+ * @param cp The checkpoint to be parsed.
+ * @param name Name of the container.
+ * @param param The array container.
+ * @param size The expected number of entries to be extracted.
+ */
+template <class T>
+void
+arrayParamIn(CheckpointIn &cp, const std::string &name,
+ T *param, unsigned size)
+{
+ const std::string §ion(Serializable::currentSection());
+ std::string str;
+ if (!cp.find(section, name, str)) {
+ fatal("Can't unserialize '%s:%s'\n", section, name);
+ }
+
+ // code below stolen from VectorParam<T>::parse().
+ // it would be nice to unify these somehow...
+
+ std::vector<std::string> tokens;
+
+ tokenize(tokens, str, ' ');
+
+ // Need this if we were doing a vector
+ // value.resize(tokens.size());
+
+ fatal_if(tokens.size() != size,
+ "Array size mismatch on %s:%s (Got %u, expected %u)'\n",
+ section, name, tokens.size(), size);
+
+ for (std::vector<std::string>::size_type i = 0; i < tokens.size(); i++) {
+ // need to parse into local variable to handle vector<bool>,
+ // for which operator[] returns a special reference class
+ // that's not the same as 'bool&', (since it's a packed
+ // vector)
+ T scalar_value;
+ if (!parseParam(tokens[i], scalar_value)) {
+ std::string err("could not parse \"");
+
+ err += str;
+ err += "\"";
+
+ fatal(err);
+ }
+
+ // assign parsed value to vector
+ param[i] = scalar_value;
+ }
+}
+
+template <class T>
+void
+arrayParamIn(CheckpointIn &cp, const std::string &name, std::vector<T> ¶m)
+{
+ const std::string §ion(Serializable::currentSection());
+ std::string str;
+ if (!cp.find(section, name, str)) {
+ fatal("Can't unserialize '%s:%s'\n", section, name);
+ }
+
+ // code below stolen from VectorParam<T>::parse().
+ // it would be nice to unify these somehow...
+
+ std::vector<std::string> tokens;
+
+ tokenize(tokens, str, ' ');
+
+ // Need this if we were doing a vector
+ // value.resize(tokens.size());
+
+ param.resize(tokens.size());
+
+ for (std::vector<std::string>::size_type i = 0; i < tokens.size(); i++) {
+ // need to parse into local variable to handle vector<bool>,
+ // for which operator[] returns a special reference class
+ // that's not the same as 'bool&', (since it's a packed
+ // vector)
+ T scalar_value;
+ if (!parseParam(tokens[i], scalar_value)) {
+ std::string err("could not parse \"");
+
+ err += str;
+ err += "\"";
+
+ fatal(err);
+ }
+
+ // assign parsed value to vector
+ param[i] = scalar_value;
+ }
+}
+
+template <class T>
+void
+arrayParamIn(CheckpointIn &cp, const std::string &name, std::list<T> ¶m)
+{
+ const std::string §ion(Serializable::currentSection());
+ std::string str;
+ if (!cp.find(section, name, str)) {
+ fatal("Can't unserialize '%s:%s'\n", section, name);
+ }
+ param.clear();
+
+ std::vector<std::string> tokens;
+ tokenize(tokens, str, ' ');
+
+ for (std::vector<std::string>::size_type i = 0; i < tokens.size(); i++) {
+ T scalar_value;
+ if (!parseParam(tokens[i], scalar_value)) {
+ std::string err("could not parse \"");
+
+ err += str;
+ err += "\"";
+
+ fatal(err);
+ }
+
+ // assign parsed value to vector
+ param.push_back(scalar_value);
+ }
+}
+
+template <class T>
+void
+arrayParamIn(CheckpointIn &cp, const std::string &name, std::set<T> ¶m)
+{
+ const std::string §ion(Serializable::currentSection());
+ std::string str;
+ if (!cp.find(section, name, str)) {
+ fatal("Can't unserialize '%s:%s'\n", section, name);
+ }
+ param.clear();
+
+ std::vector<std::string> tokens;
+ tokenize(tokens, str, ' ');
+
+ for (std::vector<std::string>::size_type i = 0; i < tokens.size(); i++) {
+ T scalar_value;
+ if (!parseParam(tokens[i], scalar_value)) {
+ std::string err("could not parse \"");
+
+ err += str;
+ err += "\"";
+
+ fatal(err);
+ }
+
+ // assign parsed value to vector
+ param.insert(scalar_value);
+ }
+}
+
+void
+debug_serialize(const std::string &cpt_dir);
+
+void
+objParamIn(CheckpointIn &cp, const std::string &name, SimObject * ¶m);
+
+//
+// These macros are streamlined to use in serialize/unserialize
+// functions. It's assumed that serialize() has a parameter 'os' for
+// the ostream, and unserialize() has parameters 'cp' and 'section'.
+#define SERIALIZE_SCALAR(scalar) paramOut(cp, #scalar, scalar)
+
+#define UNSERIALIZE_SCALAR(scalar) paramIn(cp, #scalar, scalar)
+#define UNSERIALIZE_OPT_SCALAR(scalar) optParamIn(cp, #scalar, scalar)
+
+// ENUMs are like SCALARs, but we cast them to ints on the way out
+#define SERIALIZE_ENUM(scalar) paramOut(cp, #scalar, (int)scalar)
+
+#define UNSERIALIZE_ENUM(scalar) \
+ do { \
+ int tmp; \
+ paramIn(cp, #scalar, tmp); \
+ scalar = static_cast<decltype(scalar)>(tmp); \
+ } while (0)
+
+#define SERIALIZE_ARRAY(member, size) \
+ arrayParamOut(cp, #member, member, size)
+
+#define UNSERIALIZE_ARRAY(member, size) \
+ arrayParamIn(cp, #member, member, size)
+
+#define SERIALIZE_CONTAINER(member) \
+ arrayParamOut(cp, #member, member)
+
+#define UNSERIALIZE_CONTAINER(member) \
+ arrayParamIn(cp, #member, member)
+
+#define SERIALIZE_EVENT(event) event.serializeSection(cp, #event);
+
+#define UNSERIALIZE_EVENT(event) \
+ do { \
+ event.unserializeSection(cp, #event); \
+ eventQueue()->checkpointReschedule(&event); \
+ } while (0)
+
+#define SERIALIZE_OBJ(obj) obj.serializeSection(cp, #obj)
+#define UNSERIALIZE_OBJ(obj) obj.unserializeSection(cp, #obj)
+
+#define SERIALIZE_OBJPTR(objptr) paramOut(cp, #objptr, (objptr)->name())
+
+#define UNSERIALIZE_OBJPTR(objptr) \
+ do { \
+ SimObject *sptr; \
+ objParamIn(cp, #objptr, sptr); \
+ objptr = dynamic_cast<decltype(objptr)>(sptr); \
+ } while (0)