from string import Template

TOK_INDENT = '  '  # 2 spaces

TMPL_STRUCT_HEADER = r"""
// generated by pdc (https://github.com/svperbeast/plain_data_companion).
// pdc_XXX_struct.hpp should include this file.
#ifndef PDC_STRUCT_INCLUDED
#define PDC_STRUCT_INCLUDED

#include <iostream>
#include <string>
#include <memory>
#include <limits>

#include <stdlib.h>
#include <string.h>
#include <stddef.h>
#include <stdio.h>

// define PDC_ERR_PRINT to print error messages.

namespace pdc {

template <typename T>
class Struct {};

} // namespace pdc

#endif // !PDC_STRUCT_INCLUDED
"""

TMPL_HEADER_BEGIN = r"""
// generated by pdc (https://github.com/svperbeast/plain_data_companion).
// source header file: ${SOURCE_HDR}
// source struct: ${SOURCE_TYPE}
#ifndef PDC_${SOURCE}_STRUCT_INCLUDED
#define PDC_${SOURCE}_STRUCT_INCLUDED

#include "struct.h"
#include "${SOURCE_HDR}"
#include "pdc_struct.hpp"

namespace pdc {

template <>
struct Struct<${SOURCE_TYPE}>
{"""

TMPL_HEADER_END = r"""
};
} // namespace pdc
#endif // !PDC_${SOURCE}_STRUCT_INCLUDED
"""

# ===== load func =====

TMPL_LOAD_FUNC_BEGIN = r"""
${INDENT}static bool load(void const* pdc_ibuf, std::size_t pdc_buflen,
${INDENT}  ${SOURCE}& pdc_dst)
${INDENT}{
${INDENT}  if (pdc_buflen > std::numeric_limits<int>::max()) {
${INDENT}    return false;
${INDENT}  }
${INDENT}  int ret = 0;
${INDENT}  int totlen = static_cast<int>(pdc_buflen);
${INDENT}  int len = 0;
${INDENT}  char const* p = static_cast<char const*>(pdc_ibuf);
"""

TMPL_LOAD_FUNC_END = r"""
${INDENT}  return (len == totlen);
${INDENT}}
"""

TMPL_DECL_TMP_ELT = r"""
${INDENT}${TYPE} ${VAR};
"""

TMPL_PUSH_BACK_TMP_ELT = r"""
${INDENT}${TARGET}.${VECTOR}.push_back(${VAR});
"""

TMPL_ASSIGN_INT64 = r"""
${INDENT}if ((totlen - len) >= STRUCT_QSIZE) {
${INDENT}  ret = struct_unpack(p, "!q", &(pdc_dst.${FIELD}));
${INDENT}  if (ret > 0) {
${INDENT}    len += ret;
${INDENT}    p += ret;
${INDENT}  } else {
#if defined(PDC_ERR_PRINT)
${INDENT}    std::cout << "error line:" << __LINE__ <<
${INDENT}      " struct_unpack() failure." << std::endl;
#endif
${INDENT}    return false;
${INDENT}  }
${INDENT}} else {
#if defined(PDC_ERR_PRINT)
${INDENT}  std::cout << "error line:" << __LINE__ <<
${INDENT}    " too short buffer." << std::endl;
#endif
${INDENT}  return false;
${INDENT}}
"""

TMPL_ASSIGN_INT32 = r"""
${INDENT}if ((totlen - len) >= STRUCT_ISIZE) {
${INDENT}  ret = struct_unpack(p, "!i", &(pdc_dst.${FIELD}));
${INDENT}  if (ret > 0) {
${INDENT}    len += ret;
${INDENT}    p += ret;
${INDENT}  } else {
#if defined(PDC_ERR_PRINT)
${INDENT}    std::cout << "error line:" << __LINE__ <<
${INDENT}      " struct_unpack() failure." << std::endl;
#endif
${INDENT}    return false;
${INDENT}  }
${INDENT}} else {
#if defined(PDC_ERR_PRINT)
${INDENT}  std::cout << "error line:" << __LINE__ <<
${INDENT}    " too short buffer." << std::endl;
#endif
${INDENT}  return false;
${INDENT}}
"""

TMPL_ASSIGN_INT16 = r"""
${INDENT}if ((totlen - len) >= STRUCT_HSIZE) {
${INDENT}  ret = struct_unpack(p, "!h", &(pdc_dst.${FIELD}));
${INDENT}  if (ret > 0) {
${INDENT}    len += ret;
${INDENT}    p += ret;
${INDENT}  } else {
#if defined(PDC_ERR_PRINT)
${INDENT}    std::cout << "error line:" << __LINE__ <<
${INDENT}      " struct_unpack() failure." << std::endl;
#endif
${INDENT}    return false;
${INDENT}  }
${INDENT}} else {
#if defined(PDC_ERR_PRINT)
${INDENT}  std::cout << "error line:" << __LINE__ <<
${INDENT}    " too short buffer." << std::endl;
#endif
${INDENT}  return false;
${INDENT}}
"""

TMPL_ASSIGN_INT8 = r"""
${INDENT}if ((totlen - len) >= STRUCT_BSIZE) {
${INDENT}  ret = struct_unpack(p, "!b", &(pdc_dst.${FIELD}));
${INDENT}  if (ret > 0) {
${INDENT}    len += ret;
${INDENT}    p += ret;
${INDENT}  } else {
#if defined(PDC_ERR_PRINT)
${INDENT}    std::cout << "error line:" << __LINE__ <<
${INDENT}      " struct_unpack() failure." << std::endl;
#endif
${INDENT}    return false;
${INDENT}  }
${INDENT}} else {
#if defined(PDC_ERR_PRINT)
${INDENT}  std::cout << "error line:" << __LINE__ <<
${INDENT}    " too short buffer." << std::endl;
#endif
${INDENT}  return false;
${INDENT}}
"""

TMPL_ASSIGN_FLOAT = r"""
${INDENT}if ((totlen - len) >= STRUCT_FSIZE) {
${INDENT}  ret = struct_unpack(p, "!f", &(pdc_dst.${FIELD}));
${INDENT}  if (ret > 0) {
${INDENT}    len += ret;
${INDENT}    p += ret;
${INDENT}  } else {
#if defined(PDC_ERR_PRINT)
${INDENT}    std::cout << "error line:" << __LINE__ <<
${INDENT}      " struct_unpack() failure." << std::endl;
#endif
${INDENT}    return false;
${INDENT}  }
${INDENT}} else {
#if defined(PDC_ERR_PRINT)
${INDENT}  std::cout << "error line:" << __LINE__ <<
${INDENT}    " too short buffer." << std::endl;
#endif
${INDENT}  return false;
${INDENT}}
"""

TMPL_ASSIGN_DOUBLE = r"""
${INDENT}if ((totlen - len) >= STRUCT_DSIZE) {
${INDENT}  ret = struct_unpack(p, "!d", &(pdc_dst.${FIELD}));
${INDENT}  if (ret > 0) {
${INDENT}    len += ret;
${INDENT}    p += ret;
${INDENT}  } else {
#if defined(PDC_ERR_PRINT)
${INDENT}    std::cout << "error line:" << __LINE__ <<
${INDENT}      " struct_unpack() failure." << std::endl;
#endif
${INDENT}    return false;
${INDENT}  }
${INDENT}} else {
#if defined(PDC_ERR_PRINT)
${INDENT}  std::cout << "error line:" << __LINE__ <<
${INDENT}    " too short buffer." << std::endl;
#endif
${INDENT}  return false;
${INDENT}}
"""

TMPL_ASSIGN_BOOL = r"""
${INDENT}if ((totlen - len) >= STRUCT_BSIZE) {
${INDENT}  char boolval;
${INDENT}  ret = struct_unpack(p, "!b", &boolval);
${INDENT}  if (ret > 0) {
${INDENT}    pdc_dst.${FIELD} = boolval ? true : false;
${INDENT}    len += ret;
${INDENT}    p += ret;
${INDENT}  } else {
#if defined(PDC_ERR_PRINT)
${INDENT}    std::cout << "error line:" << __LINE__ <<
${INDENT}      " struct_unpack() failure." << std::endl;
#endif
${INDENT}    return false;
${INDENT}  }
${INDENT}} else {
#if defined(PDC_ERR_PRINT)
${INDENT}  std::cout << "error line:" << __LINE__ <<
${INDENT}    " too short buffer." << std::endl;
#endif
${INDENT}  return false;
${INDENT}}
"""

TMPL_ASSIGN_STRING = r"""
${INDENT}{
${INDENT}  short tmplen;
${INDENT}  std::unique_ptr<char[]> strbuf;
${INDENT}  char fmtbuf[32];
${INDENT}  if ((totlen - len) >= STRUCT_HSIZE) {
${INDENT}    ret = struct_unpack(p, "!h", &tmplen);
${INDENT}    if (ret > 0) {
${INDENT}      len += ret;
${INDENT}      p += ret;
${INDENT}    } else {
#if defined(PDC_ERR_PRINT)
${INDENT}      std::cout << "error line:" << __LINE__ <<
${INDENT}        " struct_unpack() failure." << std::endl;
#endif
${INDENT}      return false;
${INDENT}    }
${INDENT}  } else {
#if defined(PDC_ERR_PRINT)
${INDENT}    std::cout << "error line:" << __LINE__ <<
${INDENT}      " too short buffer." << std::endl;
#endif
${INDENT}    return false;
${INDENT}  }
${INDENT}  strbuf = std::move(std::unique_ptr<char[]>(new char [tmplen]));
${INDENT}  snprintf(fmtbuf, sizeof(fmtbuf), "%his", tmplen);
${INDENT}  if ((totlen - len) >= tmplen) {
${INDENT}    ret = struct_unpack(p, fmtbuf, strbuf.get());
${INDENT}    if (ret > 0) {
${INDENT}      pdc_dst.${FIELD} = std::string(std::move(strbuf.get()), tmplen);
${INDENT}      len += ret;
${INDENT}      p += ret;
${INDENT}    } else {
#if defined(PDC_ERR_PRINT)
${INDENT}      std::cout << "error line:" << __LINE__ <<
${INDENT}        " struct_unpack() failure." << std::endl;
#endif
${INDENT}      return false;
${INDENT}    }
${INDENT}  } else {
#if defined(PDC_ERR_PRINT)
${INDENT}    std::cout << "error line:" << __LINE__ <<
${INDENT}      " too short buffer." << std::endl;
#endif
${INDENT}    return false;
${INDENT}  }
${INDENT}}
"""

TMPL_ASSIGN_INT64_CHLD_VECTOR = r"""
${INDENT}if ((totlen - len) >= STRUCT_QSIZE) {
${INDENT}  ret = struct_unpack(p, "!q", &(${VAR}.${FIELD}));
${INDENT}  if (ret > 0) {
${INDENT}    len += ret;
${INDENT}    p += ret;
${INDENT}  } else {
#if defined(PDC_ERR_PRINT)
${INDENT}    std::cout << "error line:" << __LINE__ <<
${INDENT}      " struct_unpack() failure." << std::endl;
#endif
${INDENT}    return false;
${INDENT}  }
${INDENT}} else {
#if defined(PDC_ERR_PRINT)
${INDENT}  std::cout << "error line:" << __LINE__ <<
${INDENT}    " too short buffer." << std::endl;
#endif
${INDENT}  return false;
${INDENT}}
"""

TMPL_ASSIGN_INT32_CHLD_VECTOR = r"""
${INDENT}if ((totlen - len) >= STRUCT_ISIZE) {
${INDENT}  ret = struct_unpack(p, "!i", &(${VAR}.${FIELD}));
${INDENT}  if (ret > 0) {
${INDENT}    len += ret;
${INDENT}    p += ret;
${INDENT}  } else {
#if defined(PDC_ERR_PRINT)
${INDENT}    std::cout << "error line:" << __LINE__ <<
${INDENT}      " struct_unpack() failure." << std::endl;
#endif
${INDENT}    return false;
${INDENT}  }
${INDENT}} else {
#if defined(PDC_ERR_PRINT)
${INDENT}  std::cout << "error line:" << __LINE__ <<
${INDENT}    " too short buffer." << std::endl;
#endif
${INDENT}  return false;
${INDENT}}
"""

TMPL_ASSIGN_INT16_CHLD_VECTOR = r"""
${INDENT}if ((totlen - len) >= STRUCT_HSIZE) {
${INDENT}  ret = struct_unpack(p, "!h", &(${VAR}.${FIELD}));
${INDENT}  if (ret > 0) {
${INDENT}    len += ret;
${INDENT}    p += ret;
${INDENT}  } else {
#if defined(PDC_ERR_PRINT)
${INDENT}    std::cout << "error line:" << __LINE__ <<
${INDENT}      " struct_unpack() failure." << std::endl;
#endif
${INDENT}    return false;
${INDENT}  }
${INDENT}} else {
#if defined(PDC_ERR_PRINT)
${INDENT}  std::cout << "error line:" << __LINE__ <<
${INDENT}    " too short buffer." << std::endl;
#endif
${INDENT}  return false;
${INDENT}}
"""

TMPL_ASSIGN_INT8_CHLD_VECTOR = r"""
${INDENT}if ((totlen - len) >= STRUCT_BSIZE) {
${INDENT}  ret = struct_unpack(p, "!b", &(${VAR}.${FIELD}));
${INDENT}  if (ret > 0) {
${INDENT}    len += ret;
${INDENT}    p += ret;
${INDENT}  } else {
#if defined(PDC_ERR_PRINT)
${INDENT}    std::cout << "error line:" << __LINE__ <<
${INDENT}      " struct_unpack() failure." << std::endl;
#endif
${INDENT}    return false;
${INDENT}  }
${INDENT}} else {
#if defined(PDC_ERR_PRINT)
${INDENT}  std::cout << "error line:" << __LINE__ <<
${INDENT}    " too short buffer." << std::endl;
#endif
${INDENT}  return false;
${INDENT}}
"""

TMPL_ASSIGN_FLOAT_CHLD_VECTOR = r"""
${INDENT}if ((totlen - len) >= STRUCT_FSIZE) {
${INDENT}  ret = struct_unpack(p, "!f", &(${VAR}.${FIELD}));
${INDENT}  if (ret > 0) {
${INDENT}    len += ret;
${INDENT}    p += ret;
${INDENT}  } else {
#if defined(PDC_ERR_PRINT)
${INDENT}    std::cout << "error line:" << __LINE__ <<
${INDENT}      " struct_unpack() failure." << std::endl;
#endif
${INDENT}    return false;
${INDENT}  }
${INDENT}} else {
#if defined(PDC_ERR_PRINT)
${INDENT}  std::cout << "error line:" << __LINE__ <<
${INDENT}    " too short buffer." << std::endl;
#endif
${INDENT}  return false;
${INDENT}}
"""

TMPL_ASSIGN_DOUBLE_CHLD_VECTOR = r"""
${INDENT}if ((totlen - len) >= STRUCT_DSIZE) {
${INDENT}  ret = struct_unpack(p, "!d", &(${VAR}.${FIELD}));
${INDENT}  if (ret > 0) {
${INDENT}    len += ret;
${INDENT}    p += ret;
${INDENT}  } else {
#if defined(PDC_ERR_PRINT)
${INDENT}    std::cout << "error line:" << __LINE__ <<
${INDENT}      " struct_unpack() failure." << std::endl;
#endif
${INDENT}    return false;
${INDENT}  }
${INDENT}} else {
#if defined(PDC_ERR_PRINT)
${INDENT}  std::cout << "error line:" << __LINE__ <<
${INDENT}    " too short buffer." << std::endl;
#endif
${INDENT}  return false;
${INDENT}}
"""

TMPL_ASSIGN_BOOL_CHLD_VECTOR = r"""
${INDENT}if ((totlen - len) >= STRUCT_BSIZE) {
${INDENT}  char boolval;
${INDENT}  ret = struct_unpack(p, "!b", &boolval);
${INDENT}  if (ret > 0) {
${INDENT}    ${VAR}.${FIELD} = boolval ? true : false;
${INDENT}    len += ret;
${INDENT}    p += ret;
${INDENT}  } else {
#if defined(PDC_ERR_PRINT)
${INDENT}    std::cout << "error line:" << __LINE__ <<
${INDENT}      " struct_unpack() failure." << std::endl;
#endif
${INDENT}    return false;
${INDENT}  }
${INDENT}} else {
#if defined(PDC_ERR_PRINT)
${INDENT}  std::cout << "error line:" << __LINE__ <<
${INDENT}    " too short buffer." << std::endl;
#endif
${INDENT}  return false;
${INDENT}}
"""

TMPL_ASSIGN_STRING_CHLD_VECTOR = r"""
${INDENT}{
${INDENT}  short tmplen;
${INDENT}  std::unique_ptr<char[]> strbuf;
${INDENT}  char fmtbuf[32];
${INDENT}  if ((totlen - len) >= STRUCT_HSIZE) {
${INDENT}    ret = struct_unpack(p, "!h", &tmplen);
${INDENT}    if (ret > 0) {
${INDENT}      len += ret;
${INDENT}      p += ret;
${INDENT}    } else {
#if defined(PDC_ERR_PRINT)
${INDENT}      std::cout << "error line:" << __LINE__ <<
${INDENT}        " struct_unpack() failure." << std::endl;
#endif
${INDENT}      return false;
${INDENT}    }
${INDENT}  } else {
#if defined(PDC_ERR_PRINT)
${INDENT}    std::cout << "error line:" << __LINE__ <<
${INDENT}      " too short buffer." << std::endl;
#endif
${INDENT}    return false;
${INDENT}  }
${INDENT}  strbuf = std::move(std::unique_ptr<char[]>(new char [tmplen]));
${INDENT}  snprintf(fmtbuf, sizeof(fmtbuf), "%his", tmplen);
${INDENT}  if ((totlen - len) >= tmplen) {
${INDENT}    ret = struct_unpack(p, fmtbuf, strbuf.get());
${INDENT}    if (ret > 0) {
${INDENT}      ${VAR}.${FIELD} = std::string(std::move(strbuf.get()), tmplen);
${INDENT}      len += ret;
${INDENT}      p += ret;
${INDENT}    } else {
#if defined(PDC_ERR_PRINT)
${INDENT}      std::cout << "error line:" << __LINE__ <<
${INDENT}        " struct_unpack() failure." << std::endl;
#endif
${INDENT}      return false;
${INDENT}    }
${INDENT}  } else {
#if defined(PDC_ERR_PRINT)
${INDENT}    std::cout << "error line:" << __LINE__ <<
${INDENT}      " too short buffer." << std::endl;
#endif
${INDENT}    return false;
${INDENT}  }
${INDENT}}
"""

TMPL_ASSIGN_INT64_IN_VECTOR = r"""
${INDENT}if ((totlen - len) >= STRUCT_QSIZE) {
${INDENT}  long qval;
${INDENT}  ret = struct_unpack(p, "!q", &qval);
${INDENT}  if (ret > 0) {
${INDENT}    ${TARGET}.${VECTOR}.push_back(qval);
${INDENT}    len += ret;
${INDENT}    p += ret;
${INDENT}  } else {
#if defined(PDC_ERR_PRINT)
${INDENT}    std::cout << "error line:" << __LINE__ <<
${INDENT}      " struct_unpack() failure." << std::endl;
#endif
${INDENT}    return false;
${INDENT}  }
${INDENT}} else {
#if defined(PDC_ERR_PRINT)
${INDENT}  std::cout << "error line:" << __LINE__ <<
${INDENT}    " too short buffer." << std::endl;
#endif
${INDENT}  return false;
${INDENT}}
"""

TMPL_ASSIGN_INT32_IN_VECTOR = r"""
${INDENT}if ((totlen - len) >= STRUCT_ISIZE) {
${INDENT}  int ival;
${INDENT}  ret = struct_unpack(p, "!i", &ival);
${INDENT}  if (ret > 0) {
${INDENT}    ${TARGET}.${VECTOR}.push_back(ival);
${INDENT}    len += ret;
${INDENT}    p += ret;
${INDENT}  } else {
#if defined(PDC_ERR_PRINT)
${INDENT}    std::cout << "error line:" << __LINE__ <<
${INDENT}      " struct_unpack() failure." << std::endl;
#endif
${INDENT}    return false;
${INDENT}  }
${INDENT}} else {
#if defined(PDC_ERR_PRINT)
${INDENT}  std::cout << "error line:" << __LINE__ <<
${INDENT}    " too short buffer." << std::endl;
#endif
${INDENT}  return false;
${INDENT}}
"""

TMPL_ASSIGN_INT16_IN_VECTOR = r"""
${INDENT}if ((totlen - len) >= STRUCT_HSIZE) {
${INDENT}  short hval;
${INDENT}  ret = struct_unpack(p, "!h", &hval);
${INDENT}  if (ret > 0) {
${INDENT}    ${TARGET}.${VECTOR}.push_back(hval);
${INDENT}    len += ret;
${INDENT}    p += ret;
${INDENT}  } else {
#if defined(PDC_ERR_PRINT)
${INDENT}    std::cout << "error line:" << __LINE__ <<
${INDENT}      " struct_unpack() failure." << std::endl;
#endif
${INDENT}    return false;
${INDENT}  }
${INDENT}} else {
#if defined(PDC_ERR_PRINT)
${INDENT}  std::cout << "error line:" << __LINE__ <<
${INDENT}    " too short buffer." << std::endl;
#endif
${INDENT}  return false;
${INDENT}}
"""

TMPL_ASSIGN_INT8_IN_VECTOR = r"""
${INDENT}if ((totlen - len) >= STRUCT_BSIZE) {
${INDENT}  char bval;
${INDENT}  ret = struct_unpack(p, "!b", &bval);
${INDENT}  if (ret > 0) {
${INDENT}    ${TARGET}.${VECTOR}.push_back(bval);
${INDENT}    len += ret;
${INDENT}    p += ret;
${INDENT}  } else {
#if defined(PDC_ERR_PRINT)
${INDENT}    std::cout << "error line:" << __LINE__ <<
${INDENT}      " struct_unpack() failure." << std::endl;
#endif
${INDENT}    return false;
${INDENT}  }
${INDENT}} else {
#if defined(PDC_ERR_PRINT)
${INDENT}  std::cout << "error line:" << __LINE__ <<
${INDENT}    " too short buffer." << std::endl;
#endif
${INDENT}  return false;
${INDENT}}
"""

TMPL_ASSIGN_FLOAT_IN_VECTOR = r"""
${INDENT}if ((totlen - len) >= STRUCT_FSIZE) {
${INDENT}  float fval;
${INDENT}  ret = struct_unpack(p, "!f", &fval);
${INDENT}  if (ret > 0) {
${INDENT}    ${TARGET}.${VECTOR}.push_back(fval);
${INDENT}    len += ret;
${INDENT}    p += ret;
${INDENT}  } else {
#if defined(PDC_ERR_PRINT)
${INDENT}    std::cout << "error line:" << __LINE__ <<
${INDENT}      " struct_unpack() failure." << std::endl;
#endif
${INDENT}    return false;
${INDENT}  }
${INDENT}} else {
#if defined(PDC_ERR_PRINT)
${INDENT}  std::cout << "error line:" << __LINE__ <<
${INDENT}    " too short buffer." << std::endl;
#endif
${INDENT}  return false;
${INDENT}}
"""

TMPL_ASSIGN_DOUBLE_IN_VECTOR = r"""
${INDENT}if ((totlen - len) >= STRUCT_DSIZE) {
${INDENT}  double dval;
${INDENT}  ret = struct_unpack(p, "!d", &dval);
${INDENT}  if (ret > 0) {
${INDENT}    ${TARGET}.${VECTOR}.push_back(dval);
${INDENT}    len += ret;
${INDENT}    p += ret;
${INDENT}  } else {
#if defined(PDC_ERR_PRINT)
${INDENT}    std::cout << "error line:" << __LINE__ <<
${INDENT}      " struct_unpack() failure." << std::endl;
#endif
${INDENT}    return false;
${INDENT}  }
${INDENT}} else {
#if defined(PDC_ERR_PRINT)
${INDENT}  std::cout << "error line:" << __LINE__ <<
${INDENT}    " too short buffer." << std::endl;
#endif
${INDENT}  return false;
${INDENT}}
"""

TMPL_ASSIGN_BOOL_IN_VECTOR = r"""
${INDENT}if ((totlen - len) >= STRUCT_BSIZE) {
${INDENT}  char boolval;
${INDENT}  ret = struct_unpack(p, "!b", &boolval);
${INDENT}  if (ret > 0) {
${INDENT}    ${TARGET}.${VECTOR}.push_back((boolval ? true : false));
${INDENT}    len += ret;
${INDENT}    p += ret;
${INDENT}  } else {
#if defined(PDC_ERR_PRINT)
${INDENT}    std::cout << "error line:" << __LINE__ <<
${INDENT}      " struct_unpack() failure." << std::endl;
#endif
${INDENT}    return false;
${INDENT}  }
${INDENT}} else {
#if defined(PDC_ERR_PRINT)
${INDENT}  std::cout << "error line:" << __LINE__ <<
${INDENT}    " too short buffer." << std::endl;
#endif
${INDENT}  return false;
${INDENT}}
"""

TMPL_ASSIGN_STRING_IN_VECTOR = r"""
${INDENT}{
${INDENT}  short tmplen;
${INDENT}  std::unique_ptr<char[]> strbuf;
${INDENT}  char fmtbuf[32];
${INDENT}  if ((totlen - len) >= STRUCT_HSIZE) {
${INDENT}    ret = struct_unpack(p, "!h", &tmplen);
${INDENT}    if (ret > 0) {
${INDENT}      len += ret;
${INDENT}      p += ret;
${INDENT}    } else {
#if defined(PDC_ERR_PRINT)
${INDENT}      std::cout << "error line:" << __LINE__ <<
${INDENT}        " struct_unpack() failure." << std::endl;
#endif
${INDENT}      return false;
${INDENT}    }
${INDENT}  } else {
#if defined(PDC_ERR_PRINT)
${INDENT}    std::cout << "error line:" << __LINE__ <<
${INDENT}      " too short buffer." << std::endl;
#endif
${INDENT}    return false;
${INDENT}  }
${INDENT}  strbuf = std::move(std::unique_ptr<char[]>(new char [tmplen]));
${INDENT}  snprintf(fmtbuf, sizeof(fmtbuf), "%his", tmplen);
${INDENT}  if ((totlen - len) >= tmplen) {
${INDENT}    ret = struct_unpack(p, fmtbuf, strbuf.get());
${INDENT}    if (ret > 0) {
${INDENT}      ${TARGET}.${VECTOR}.push_back(
${INDENT}        std::string(std::move(strbuf.get()), tmplen));
${INDENT}      len += ret;
${INDENT}      p += ret;
${INDENT}    } else {
#if defined(PDC_ERR_PRINT)
${INDENT}      std::cout << "error line:" << __LINE__ <<
${INDENT}        " struct_unpack() failure." << std::endl;
#endif
${INDENT}      return false;
${INDENT}    }
${INDENT}  } else {
#if defined(PDC_ERR_PRINT)
${INDENT}    std::cout << "error line:" << __LINE__ <<
${INDENT}      " too short buffer." << std::endl;
#endif
${INDENT}    return false;
${INDENT}  }
${INDENT}}
"""

TMPL_STORE_VECTOR_SIZE = r"""
${INDENT}std::size_t ${VECTOR}_size = 0;
${INDENT}if ((totlen - len) >= STRUCT_HSIZE) {
${INDENT}  ret = struct_unpack(p, "!h", &${VECTOR}_size);
${INDENT}  if (ret > 0) {
${INDENT}    len += ret;
${INDENT}    p += ret;
${INDENT}  } else {
#if defined(PDC_ERR_PRINT)
${INDENT}    std::cout << "error line:" << __LINE__ <<
${INDENT}      " struct_unpack() failure." << std::endl;
#endif
${INDENT}    return false;
${INDENT}  }
${INDENT}} else {
#if defined(PDC_ERR_PRINT)
${INDENT}  std::cout << "error line:" << __LINE__ <<
${INDENT}    " too short buffer." << std::endl;
#endif
${INDENT}  return false;
${INDENT}}
"""

"""
INDENT: indentation
VECTOR: vector
"""
TMPL_LOAD_FOR_EACH_VECTOR_ITEMS_BEGIN = r"""
${INDENT}for (std::size_t i = 0;
${INDENT}     i < ${VECTOR}_size;
${INDENT}     i++) {
"""

"""
INDENT: indentation
"""
TMPL_LOAD_FOR_EACH_VECTOR_ITEMS_END = r"""${INDENT}}
"""

# ===== dump func =====

TMPL_DUMP_FUNC_BEGIN = r"""
${INDENT}static bool dump(${SOURCE} const& pdc_src,
${INDENT}  void* pdc_ibuf, std::size_t* pdc_buflen)
${INDENT}{
${INDENT}  char pdc_fmt[128];
${INDENT}  char* pdc_buf = static_cast<char*>(pdc_ibuf);
${INDENT}  int pdc_n = 0;
${INDENT}  int pdc_left = 0;
${INDENT}  if (*pdc_buflen <=
${INDENT}      static_cast<std::size_t>(std::numeric_limits<int>::max())) {
${INDENT}    pdc_left = static_cast<int>(*pdc_buflen);
${INDENT}  } else {
${INDENT}    return false;
${INDENT}  }
"""

TMPL_DUMP_FUNC_END = r"""
${INDENT}  *pdc_buflen = pdc_buf - static_cast<char*>(pdc_ibuf);
${INDENT}  return true;
${INDENT}}
"""

TMPL_DUMP_FOR_EACH_VECTOR_ITEMS_BEGIN = r"""
${INDENT}std::vector<${VECTOR_TYPE}>::const_iterator pdc_${CIT_NAME}_cit;
${INDENT}for (pdc_${CIT_NAME}_cit = ${SOURCE}.${VECTOR_QNAME}.begin();
${INDENT}     pdc_${CIT_NAME}_cit != ${SOURCE}.${VECTOR_QNAME}.end();
${INDENT}     ++pdc_${CIT_NAME}_cit) {
"""

TMPL_DUMP_FOR_EACH_VECTOR_ITEMS_END = r"""${INDENT}}
"""

TMPL_DUMP_INT64 = r"""
${INDENT}if (pdc_left >= STRUCT_QSIZE) {
${INDENT}  pdc_n = struct_pack(pdc_buf, "!q", ${SOURCE}${FIELD});
${INDENT}  pdc_buf += pdc_n;
${INDENT}  pdc_left -= pdc_n;
${INDENT}} else {
#if defined(PDC_ERR_PRINT)
${INDENT}  std::cout << "error line:" << __LINE__ <<
${INDENT}    " too short buffer." << std::endl;
#endif
${INDENT}  return false;
${INDENT}}
"""

TMPL_DUMP_INT32 = r"""
${INDENT}if (pdc_left >= STRUCT_ISIZE) {
${INDENT}  pdc_n = struct_pack(pdc_buf, "!i", ${SOURCE}${FIELD});
${INDENT}  pdc_buf += pdc_n;
${INDENT}  pdc_left -= pdc_n;
${INDENT}} else {
#if defined(PDC_ERR_PRINT)
${INDENT}  std::cout << "error line:" << __LINE__ <<
${INDENT}    " too short buffer." << std::endl;
#endif
${INDENT}  return false;
${INDENT}}
"""

TMPL_DUMP_INT16 = r"""
${INDENT}if (pdc_left >= STRUCT_HSIZE) {
${INDENT}  pdc_n = struct_pack(pdc_buf, "!h", ${SOURCE}${FIELD});
${INDENT}  pdc_buf += pdc_n;
${INDENT}  pdc_left -= pdc_n;
${INDENT}} else {
#if defined(PDC_ERR_PRINT)
${INDENT}  std::cout << "error line:" << __LINE__ <<
${INDENT}    " too short buffer." << std::endl;
#endif
${INDENT}  return false;
${INDENT}}
"""

TMPL_DUMP_INT8 = r"""
${INDENT}if (pdc_left >= STRUCT_BSIZE) {
${INDENT}  pdc_n = struct_pack(pdc_buf, "!b", ${SOURCE}${FIELD});
${INDENT}  pdc_buf += pdc_n;
${INDENT}  pdc_left -= pdc_n;
${INDENT}} else {
#if defined(PDC_ERR_PRINT)
${INDENT}  std::cout << "error line:" << __LINE__ <<
${INDENT}    " too short buffer." << std::endl;
#endif
${INDENT}  return false;
${INDENT}}
"""

TMPL_DUMP_FLOAT = r"""
${INDENT}if (pdc_left >= STRUCT_FSIZE) {
${INDENT}  pdc_n = struct_pack(pdc_buf, "!f", ${SOURCE}${FIELD});
${INDENT}  pdc_buf += pdc_n;
${INDENT}  pdc_left -= pdc_n;
${INDENT}} else {
#if defined(PDC_ERR_PRINT)
${INDENT}  std::cout << "error line:" << __LINE__ <<
${INDENT}    " too short buffer." << std::endl;
#endif
${INDENT}  return false;
${INDENT}}
"""

TMPL_DUMP_DOUBLE = r"""
${INDENT}if (pdc_left >= STRUCT_DSIZE) {
${INDENT}  pdc_n = struct_pack(pdc_buf, "!d", ${SOURCE}${FIELD});
${INDENT}  pdc_buf += pdc_n;
${INDENT}  pdc_left -= pdc_n;
${INDENT}} else {
#if defined(PDC_ERR_PRINT)
${INDENT}  std::cout << "error line:" << __LINE__ <<
${INDENT}    " too short buffer." << std::endl;
#endif
${INDENT}  return false;
${INDENT}}
"""

TMPL_DUMP_BOOL = r"""
${INDENT}if (pdc_left >= STRUCT_BSIZE) {
${INDENT}  pdc_n = struct_pack(pdc_buf, "!b",
${INDENT}                      (${SOURCE}${FIELD} ? 1 : 0));
${INDENT}  pdc_buf += pdc_n;
${INDENT}  pdc_left -= pdc_n;
${INDENT}} else {
#if defined(PDC_ERR_PRINT)
${INDENT}  std::cout << "error line:" << __LINE__ <<
${INDENT}    " too short buffer." << std::endl;
#endif
${INDENT}  return false;
${INDENT}}
"""

TMPL_DUMP_STRING = r"""
${INDENT}if (pdc_left >= STRUCT_HSIZE &&
${INDENT}    (${SOURCE}${FIELD}.size() <=
${INDENT}     static_cast<std::size_t>(std::numeric_limits<int16_t>::max()))) {
${INDENT}  pdc_n = struct_pack(pdc_buf, "!h", ${SOURCE}${FIELD}.size());
${INDENT}  pdc_buf += pdc_n;
${INDENT}  pdc_left -= pdc_n;
${INDENT}} else {
#if defined(PDC_ERR_PRINT)
${INDENT}  std::cout << "error line:" << __LINE__ <<
${INDENT}    " too long string." << std::endl;
#endif
${INDENT}  return false;
${INDENT}}
${INDENT}if (static_cast<std::size_t>(pdc_left) >= ${SOURCE}${FIELD}.size()) {
${INDENT}  pdc_n = snprintf(pdc_fmt, sizeof(pdc_fmt), "%lus",
${INDENT}                   ${SOURCE}${FIELD}.size());
${INDENT}  if ((0 < pdc_n) &&
${INDENT}      (static_cast<std::size_t>(pdc_n) <= sizeof(pdc_fmt))) {
${INDENT}    pdc_n = struct_pack(pdc_buf, pdc_fmt, ${SOURCE}${FIELD}.c_str());
${INDENT}    pdc_buf += pdc_n;
${INDENT}    pdc_left -= pdc_n;
${INDENT}  } else {
${INDENT}    return false;
${INDENT}  }
${INDENT}} else {
${INDENT}  return false;
${INDENT}}
"""

TMPL_DUMP_VECTOR_SIZE = r"""
${INDENT}if (pdc_left >= STRUCT_HSIZE &&
${INDENT}    (${SOURCE}${FIELD}.size() <=
${INDENT}     static_cast<std::size_t>(std::numeric_limits<int16_t>::max()))) {
${INDENT}  pdc_n = struct_pack(pdc_buf, "!h", ${SOURCE}${FIELD}.size());
${INDENT}  pdc_buf += pdc_n;
${INDENT}  pdc_left -= pdc_n;
${INDENT}} else {
#if defined(PDC_ERR_PRINT)
${INDENT}  std::cout << "error line:" << __LINE__ <<
${INDENT}    " too many elements." << std::endl;
#endif
${INDENT}  return false;
${INDENT}}
"""

# ===== calcsize func =====
# use 'STRUCT_XXXSIZE' macros rather than 'struct_calcsize()',
# because we don't use length prefixed format string like "!3i".

TMPL_CALCSIZE_FUNC_BEGIN = r"""
${INDENT}static std::size_t calcsize(${SOURCE} const& pdc_src)
${INDENT}{
${INDENT}  int pdc_acclen = 0;
"""

TMPL_CALCSIZE_FUNC_END = r"""
${INDENT}  return pdc_acclen;
${INDENT}}
"""

TMPL_CALCSIZE_FOR_EACH_VECTOR_ITEMS_BEGIN = r"""
${INDENT}std::vector<${VECTOR_TYPE}>::const_iterator pdc_${CIT_NAME}_cit;
${INDENT}for (pdc_${CIT_NAME}_cit = ${SOURCE}.${VECTOR_QNAME}.begin();
${INDENT}     pdc_${CIT_NAME}_cit != ${SOURCE}.${VECTOR_QNAME}.end();
${INDENT}     ++pdc_${CIT_NAME}_cit) {
"""

TMPL_CALCSIZE_FOR_EACH_VECTOR_ITEMS_END = r"""${INDENT}}
"""

TMPL_CALCSIZE_INT64 = r"""
${INDENT}pdc_acclen += STRUCT_QSIZE;
"""

TMPL_CALCSIZE_INT32 = r"""
${INDENT}pdc_acclen += STRUCT_ISIZE;
"""

TMPL_CALCSIZE_INT16 = r"""
${INDENT}pdc_acclen += STRUCT_HSIZE;
"""

TMPL_CALCSIZE_INT8 = r"""
${INDENT}pdc_acclen += STRUCT_BSIZE;
"""

TMPL_CALCSIZE_FLOAT = r"""
${INDENT}pdc_acclen += STRUCT_FSIZE;
"""

TMPL_CALCSIZE_DOUBLE = r"""
${INDENT}pdc_acclen += STRUCT_DSIZE;
"""

TMPL_CALCSIZE_BOOL = r"""
${INDENT}pdc_acclen += STRUCT_BSIZE;
"""

TMPL_CALCSIZE_STRING = r"""
${INDENT}if (${SOURCE}${FIELD}.size() <=
${INDENT}    static_cast<std::size_t>(std::numeric_limits<int16_t>::max())) {
${INDENT}  pdc_acclen += (STRUCT_HSIZE + ${SOURCE}${FIELD}.size());
${INDENT}}
"""

TMPL_CALCSIZE_VECTOR_SIZE = r"""
${INDENT}if (${SOURCE}${FIELD}.size() <=
${INDENT}     static_cast<std::size_t>(std::numeric_limits<int16_t>::max())) {
${INDENT}  pdc_acclen += STRUCT_HSIZE;
${INDENT}}
"""


def _indentation(level):
    return TOK_INDENT * level


def _decl_tmp_elt(indent, type_name, var):
    s = Template(TMPL_DECL_TMP_ELT)
    d = dict(INDENT=indent,
             TYPE=type_name,
             VAR=var)
    return s.safe_substitute(d)


def _push_back_tmp_elt(indent, vector, target, var):
    s = Template(TMPL_PUSH_BACK_TMP_ELT)
    d = dict(INDENT=indent,
             VECTOR=vector,
             VAR=var,
             TARGET=target)
    return s.safe_substitute(d)


def _assign_int(indent, field, nbytes):
    if nbytes == 8:
        s = Template(TMPL_ASSIGN_INT64)
    elif nbytes == 4:
        s = Template(TMPL_ASSIGN_INT32)
    elif nbytes == 2:
        s = Template(TMPL_ASSIGN_INT16)
    elif nbytes == 1:
        s = Template(TMPL_ASSIGN_INT8)

    d = dict(INDENT=indent,
             FIELD=field)
    return s.safe_substitute(d)


def _assign_float(indent, field):
    s = Template(TMPL_ASSIGN_FLOAT)
    d = dict(INDENT=indent,
             FIELD=field)
    return s.safe_substitute(d)


def _assign_double(indent, field):
    s = Template(TMPL_ASSIGN_DOUBLE)
    d = dict(INDENT=indent,
             FIELD=field)
    return s.safe_substitute(d)


def _assign_bool(indent, field):
    s = Template(TMPL_ASSIGN_BOOL)
    d = dict(INDENT=indent,
             FIELD=field)
    return s.safe_substitute(d)


def _assign_string(indent, field):
    s = Template(TMPL_ASSIGN_STRING)
    d = dict(INDENT=indent,
             FIELD=field)
    return s.safe_substitute(d)


def _assign_int_chld_vector(indent, field, var, nbytes):
    if nbytes == 8:
        s = Template(TMPL_ASSIGN_INT64_CHLD_VECTOR)
    elif nbytes == 4:
        s = Template(TMPL_ASSIGN_INT32_CHLD_VECTOR)
    elif nbytes == 2:
        s = Template(TMPL_ASSIGN_INT16_CHLD_VECTOR)
    elif nbytes == 1:
        s = Template(TMPL_ASSIGN_INT8_CHLD_VECTOR)

    d = dict(INDENT=indent,
             FIELD=field,
             VAR=var)
    return s.safe_substitute(d)


def _assign_float_chld_vector(indent, field, var):
    s = Template(TMPL_ASSIGN_FLOAT_CHLD_VECTOR)
    d = dict(INDENT=indent,
             FIELD=field,
             VAR=var)
    return s.safe_substitute(d)


def _assign_double_chld_vector(indent, field, var):
    s = Template(TMPL_ASSIGN_DOUBLE_CHLD_VECTOR)
    d = dict(INDENT=indent,
             FIELD=field,
             VAR=var)
    return s.safe_substitute(d)


def _assign_bool_chld_vector(indent, field, var):
    s = Template(TMPL_ASSIGN_BOOL_CHLD_VECTOR)
    d = dict(INDENT=indent,
             FIELD=field,
             VAR=var)
    return s.safe_substitute(d)


def _assign_string_chld_vector(indent, field, var):
    s = Template(TMPL_ASSIGN_STRING_CHLD_VECTOR)
    d = dict(INDENT=indent,
             FIELD=field,
             VAR=var)
    return s.safe_substitute(d)


def _assign_int_in_vector(indent, vector, target, nbytes):
    if nbytes == 8:
        s = Template(TMPL_ASSIGN_INT64_IN_VECTOR)
    elif nbytes == 4:
        s = Template(TMPL_ASSIGN_INT32_IN_VECTOR)
    elif nbytes == 2:
        s = Template(TMPL_ASSIGN_INT16_IN_VECTOR)
    elif nbytes == 1:
        s = Template(TMPL_ASSIGN_INT8_IN_VECTOR)

    d = dict(INDENT=indent,
             VECTOR=vector,
             TARGET=target)
    return s.safe_substitute(d)


def _assign_float_in_vector(indent, vector, target):
    s = Template(TMPL_ASSIGN_FLOAT_IN_VECTOR)
    d = dict(INDENT=indent,
             VECTOR=vector,
             TARGET=target)
    return s.safe_substitute(d)


def _assign_double_in_vector(indent, vector, target):
    s = Template(TMPL_ASSIGN_DOUBLE_IN_VECTOR)
    d = dict(INDENT=indent,
             VECTOR=vector,
             TARGET=target)
    return s.safe_substitute(d)


def _assign_bool_in_vector(indent, vector, target):
    s = Template(TMPL_ASSIGN_BOOL_IN_VECTOR)
    d = dict(INDENT=indent,
             VECTOR=vector,
             TARGET=target)
    return s.safe_substitute(d)


def _assign_string_in_vector(indent, vector, target):
    s = Template(TMPL_ASSIGN_STRING_IN_VECTOR)
    d = dict(INDENT=indent,
             VECTOR=vector,
             TARGET=target)
    return s.safe_substitute(d)


def get_pdc_struct_header():
    return TMPL_STRUCT_HEADER


def header_begin(source_type, source, source_hdr):
    s = Template(TMPL_HEADER_BEGIN)
    d = dict(
        SOURCE_TYPE=source_type,
        SOURCE=source,
        SOURCE_HDR=source_hdr)
    return s.safe_substitute(d)


def header_end(source_type, source):
    s = Template(TMPL_HEADER_END)
    d = dict(SOURCE_TYPE=source_type,
             SOURCE=source)
    return s.safe_substitute(d)


def load_func_begin(level, source):
    indent = _indentation(level)
    s = Template(TMPL_LOAD_FUNC_BEGIN)
    d = dict(INDENT=indent,
             SOURCE=source)
    return s.safe_substitute(d)


def load_func_end(level):
    indent = _indentation(level)
    s = Template(TMPL_LOAD_FUNC_END)
    d = dict(INDENT=indent)
    return s.safe_substitute(d)


def load_vector_begin(level, qvector, vector):
    indent = _indentation(level)
    ret = ''
    s = Template(TMPL_STORE_VECTOR_SIZE +
                 TMPL_LOAD_FOR_EACH_VECTOR_ITEMS_BEGIN)
    d = dict(INDENT=indent,
             VECTOR=qvector)
    ret += s.safe_substitute(d)
    return ret


def load_vector_end(level):
    indent = _indentation(level)
    s = Template(TMPL_LOAD_FOR_EACH_VECTOR_ITEMS_END)
    d = dict(INDENT=indent)
    return s.safe_substitute(d)


def load_primitive_int(level, qname, nbytes):
    indent = _indentation(level)
    return _assign_int(indent, qname, nbytes)


def load_primitive_float(level, qname):
    indent = _indentation(level)
    return _assign_float(indent, qname)


def load_primitive_double(level, qname):
    indent = _indentation(level)
    return _assign_double(indent, qname)


def load_primitive_bool(level, qname):
    indent = _indentation(level)
    return _assign_bool(indent, qname)


def load_string(level, qname):
    indent = _indentation(level)
    return _assign_string(indent, qname)


def load_userdefined_in_vector_begin(level, typename, var):
    indent = _indentation(level)
    return _decl_tmp_elt(indent, typename, var)


def load_userdefined_in_vector_end(level, vectorname, target, var):
    indent = _indentation(level)
    return _push_back_tmp_elt(indent, vectorname, target, var)


def load_primitive_int_in_vector(level, vectorname, target, nbytes):
    indent = _indentation(level)
    return _assign_int_in_vector(indent, vectorname, target, nbytes)


def load_primitive_float_in_vector(level, vectorname, target):
    indent = _indentation(level)
    return _assign_float_in_vector(indent, vectorname, target)


def load_primitive_double_in_vector(level, vectorname, target):
    indent = _indentation(level)
    return _assign_double_in_vector(indent, vectorname, target)


def load_primitive_bool_in_vector(level, vectorname, target):
    indent = _indentation(level)
    return _assign_bool_in_vector(indent, vectorname, target)


def load_string_in_vector(level, vectorname, target):
    indent = _indentation(level)
    return _assign_string_in_vector(indent, vectorname, target)


def load_primitive_int_chld_vector(level, qname, var, nbytes):
    indent = _indentation(level)
    return _assign_int_chld_vector(indent, qname, var, nbytes)


def load_primitive_float_chld_vector(level, qname, var):
    indent = _indentation(level)
    return _assign_float_chld_vector(indent, qname, var)


def load_primitive_double_chld_vector(level, qname, var):
    indent = _indentation(level)
    return _assign_double_chld_vector(indent, qname, var)


def load_primitive_bool_chld_vector(level, qname, var):
    indent = _indentation(level)
    return _assign_bool_chld_vector(indent, qname, var)


def load_string_chld_vector(level, qname, var):
    indent = _indentation(level)
    return _assign_string_chld_vector(indent, qname, var)


def _dump_int(indent, source, field, nbytes):
    if len(field) > 0:
        source += '.'
    if nbytes == 8:
        s = Template(TMPL_DUMP_INT64)
    elif nbytes == 4:
        s = Template(TMPL_DUMP_INT32)
    elif nbytes == 2:
        s = Template(TMPL_DUMP_INT16)
    elif nbytes == 1:
        s = Template(TMPL_DUMP_INT8)

    d = dict(INDENT=indent,
             SOURCE=source,
             FIELD=field)
    return s.safe_substitute(d)


def _dump_float(indent, source, field):
    if len(field) > 0:
        source += '.'
    s = Template(TMPL_DUMP_FLOAT)
    d = dict(INDENT=indent,
             SOURCE=source,
             FIELD=field)
    return s.safe_substitute(d)


def _dump_double(indent, source, field):
    if len(field) > 0:
        source += '.'
    s = Template(TMPL_DUMP_DOUBLE)
    d = dict(INDENT=indent,
             SOURCE=source,
             FIELD=field)
    return s.safe_substitute(d)


def _dump_bool(indent, source, field):
    if len(field) > 0:
        source += '.'
    s = Template(TMPL_DUMP_BOOL)
    d = dict(INDENT=indent,
             SOURCE=source,
             FIELD=field)
    return s.safe_substitute(d)


def _dump_string(indent, source, field):
    if len(field) > 0:
        source += '.'
    s = Template(TMPL_DUMP_STRING)
    d = dict(INDENT=indent,
             SOURCE=source,
             FIELD=field)
    return s.safe_substitute(d)


def _dump_vector_size(indent, source, field):
    if len(field) > 0:
        source += '.'
    s = Template(TMPL_DUMP_VECTOR_SIZE)
    d = dict(INDENT=indent,
             SOURCE=source,
             FIELD=field)
    return s.safe_substitute(d)


def dump_func_begin(level, source):
    indent = _indentation(level)
    s = Template(TMPL_DUMP_FUNC_BEGIN)
    d = dict(INDENT=indent,
             SOURCE=source)
    return s.safe_substitute(d)


def dump_func_end(level):
    indent = _indentation(level)
    s = Template(TMPL_DUMP_FUNC_END)
    d = dict(INDENT=indent)
    return s.safe_substitute(d)


def dump_vector_begin(level, source, vector_type, vector_name, cit_name,
                      vector_qname):
    if vector_type == 'string':
        vector_type = 'std::string'
    indent = _indentation(level)
    ret = ''
    ret += _dump_vector_size(indent, source, vector_qname)
    s = Template(TMPL_DUMP_FOR_EACH_VECTOR_ITEMS_BEGIN)
    d = dict(INDENT=indent,
             SOURCE=source,
             VECTOR_TYPE=vector_type,
             VECTOR_NAME=vector_name,
             CIT_NAME=cit_name,
             VECTOR_QNAME=vector_qname)
    ret += s.safe_substitute(d)
    return ret


def dump_vector_end(level):
    indent = _indentation(level)
    s = Template(TMPL_DUMP_FOR_EACH_VECTOR_ITEMS_END)
    d = dict(INDENT=indent,
             LEVEL=level)
    return s.safe_substitute(d)


def dump_primitive_int(level, source, qname, nbytes):
    indent = _indentation(level)
    return _dump_int(indent, source, qname, nbytes)


def dump_primitive_float(level, source, qname):
    indent = _indentation(level)
    return _dump_float(indent, source, qname)


def dump_primitive_double(level, source, qname):
    indent = _indentation(level)
    return _dump_double(indent, source, qname)


def dump_primitive_bool(level, source, qname):
    indent = _indentation(level)
    return _dump_bool(indent, source, qname)


def dump_string(level, source, qname):
    indent = _indentation(level)
    return _dump_string(indent, source, qname)


def dump_primitive_int_in_vector(level, qvectorname, nbytes):
    indent = _indentation(level)
    vectorit = '(*pdc_' + qvectorname + '_cit)'
    return _dump_int(indent, vectorit, '', nbytes)


def dump_primitive_float_in_vector(level, qvectorname):
    indent = _indentation(level)
    vectorit = '(*pdc_' + qvectorname + '_cit)'
    return _dump_float(indent, vectorit, '')


def dump_primitive_double_in_vector(level, qvectorname):
    indent = _indentation(level)
    vectorit = '(*pdc_' + qvectorname + '_cit)'
    return _dump_double(indent, vectorit, '')


def dump_primitive_bool_in_vector(level, qvectorname):
    indent = _indentation(level)
    vectorit = '(*pdc_' + qvectorname + '_cit)'
    return _dump_bool(indent, vectorit, '')


def dump_string_in_vector(level, qvectorname):
    indent = _indentation(level)
    vectorit = '(*pdc_' + qvectorname + '_cit)'
    return _dump_string(indent, vectorit, '')


def _calcsize_int(indent, nbytes):
    if nbytes == 8:
        s = Template(TMPL_CALCSIZE_INT64)
    elif nbytes == 4:
        s = Template(TMPL_CALCSIZE_INT32)
    elif nbytes == 2:
        s = Template(TMPL_CALCSIZE_INT16)
    elif nbytes == 1:
        s = Template(TMPL_CALCSIZE_INT8)

    d = dict(INDENT=indent)
    return s.safe_substitute(d)


def _calcsize_float(indent):
    s = Template(TMPL_CALCSIZE_FLOAT)
    d = dict(INDENT=indent)
    return s.safe_substitute(d)


def _calcsize_double(indent):
    s = Template(TMPL_CALCSIZE_DOUBLE)
    d = dict(INDENT=indent)
    return s.safe_substitute(d)


def _calcsize_bool(indent):
    s = Template(TMPL_CALCSIZE_BOOL)
    d = dict(INDENT=indent)
    return s.safe_substitute(d)


def _calcsize_string(indent, source, field):
    if len(field) > 0:
        source += '.'
    s = Template(TMPL_CALCSIZE_STRING)
    d = dict(INDENT=indent,
             SOURCE=source,
             FIELD=field)
    return s.safe_substitute(d)


def _calcsize_vector_size(indent, source, field):
    if len(field) > 0:
        source += '.'
    s = Template(TMPL_CALCSIZE_VECTOR_SIZE)
    d = dict(INDENT=indent,
             SOURCE=source,
             FIELD=field)
    return s.safe_substitute(d)


def calcsize_func_begin(level, source):
    indent = _indentation(level)
    s = Template(TMPL_CALCSIZE_FUNC_BEGIN)
    d = dict(INDENT=indent,
             SOURCE=source)
    return s.safe_substitute(d)


def calcsize_func_end(level):
    indent = _indentation(level)
    s = Template(TMPL_CALCSIZE_FUNC_END)
    d = dict(INDENT=indent)
    return s.safe_substitute(d)


def calcsize_vector_begin(level, source, vector_type, vector_name, cit_name,
                          vector_qname):
    if vector_type == 'string':
        vector_type = 'std::string'
    indent = _indentation(level)
    ret = ''
    ret += _calcsize_vector_size(indent, source, vector_qname)
    s = Template(TMPL_CALCSIZE_FOR_EACH_VECTOR_ITEMS_BEGIN)
    d = dict(INDENT=indent,
             SOURCE=source,
             VECTOR_TYPE=vector_type,
             VECTOR_NAME=vector_name,
             CIT_NAME=cit_name,
             VECTOR_QNAME=vector_qname)
    ret += s.safe_substitute(d)
    return ret


def calcsize_vector_end(level):
    indent = _indentation(level)
    s = Template(TMPL_CALCSIZE_FOR_EACH_VECTOR_ITEMS_END)
    d = dict(INDENT=indent,
             LEVEL=level)
    return s.safe_substitute(d)


def calcsize_primitive_int(level, nbytes):
    indent = _indentation(level)
    return _calcsize_int(indent, nbytes)


def calcsize_primitive_float(level):
    indent = _indentation(level)
    return _calcsize_float(indent)


def calcsize_primitive_double(level):
    indent = _indentation(level)
    return _calcsize_double(indent)


def calcsize_primitive_bool(level):
    indent = _indentation(level)
    return _calcsize_bool(indent)


def calcsize_string(level, source, qname):
    indent = _indentation(level)
    return _calcsize_string(indent, source, qname)


def calcsize_primitive_int_in_vector(level, nbytes):
    indent = _indentation(level)
    return _calcsize_int(indent, nbytes)


def calcsize_primitive_float_in_vector(level):
    indent = _indentation(level)
    return _calcsize_float(indent)


def calcsize_primitive_double_in_vector(level):
    indent = _indentation(level)
    return _calcsize_double(indent)


def calcsize_primitive_bool_in_vector(level):
    indent = _indentation(level)
    return _calcsize_bool(indent)


def calcsize_string_in_vector(level, qvectorname):
    indent = _indentation(level)
    vectorit = '(*pdc_' + qvectorname + '_cit)'
    return _calcsize_string(indent, vectorit, '')
