BVB Source Codes

CRYENGINE Show MetadataRecorder.cpp Source code

Return Download CRYENGINE: download MetadataRecorder.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. #include "StdAfx.h"
  4. #include "IMetadataRecorder.h"
  5.  
  6. enum EBasicKeywords4CC
  7. {
  8.         eBK_void = 0, // end of meta data block, or invalid fcc
  9.         eBK_meta = 'meta',
  10.  
  11.         eBK_tags = 'tags', // begin of list of tags
  12.         eBK_typs = 'typs', // begin of list of typs
  13. };
  14.  
  15. class CMetadata : public IMetadata
  16. {
  17.         friend class CMetadataRecorder;
  18.  
  19. public:
  20.         CMetadata() : m_tag(0), m_type(eBK_void), m_size(0) {}
  21.  
  22.         ~CMetadata() {}
  23.  
  24.         void SetTag(uint32 tag)
  25.         {
  26.                 if (tag == eBK_meta)
  27.                         return;
  28.  
  29.                 m_tag = tag;
  30.         }
  31.  
  32.         bool SetValue(uint32 type, const uint8* data, uint8 size)
  33.         {
  34.                 if (type == eBK_void || type == eBK_meta || data == NULL || size == 0)
  35.                         return false;
  36.  
  37.                 if (m_tag == 0 || m_type != 0 && m_type != type)
  38.                         // tag not set or changing set type
  39.                         return false;
  40.  
  41.                 m_type = type;
  42.                 memcpy(m_data, data, size);
  43.                 m_size = size;
  44.                 return true;
  45.         }
  46.  
  47.         bool AddField(const IMetadata* metadata)
  48.         {
  49.                 if (m_tag == eBK_void || m_type != eBK_void && m_type != eBK_meta || metadata == NULL)
  50.                         // tag not set or set type is not meta
  51.                         return false;
  52.  
  53.                 m_type = eBK_meta;
  54.  
  55.                 m_fields.push_back(*static_cast<const CMetadata*>(metadata));
  56.                 return true;
  57.         }
  58.  
  59.         bool AddField(uint32 tag, uint32 type, const uint8* data, uint8 size)
  60.         {
  61.                 if (tag == eBK_void || type == eBK_void || type == eBK_meta || data == NULL || size == 0)
  62.                         return false;
  63.  
  64.                 if (m_tag == eBK_void || m_type != eBK_void && m_type != eBK_meta)
  65.                         // tag not set or set type is not meta
  66.                         return false;
  67.  
  68.                 m_type = eBK_meta;
  69.  
  70.                 CMetadata metadata;
  71.                 metadata.SetTag(tag);
  72.                 if (!metadata.SetValue(type, data, size))
  73.                         return false;
  74.                 m_fields.push_back(metadata);
  75.                 return true;
  76.         }
  77.  
  78.         void Reset()
  79.         {
  80.                 m_tag = eBK_void;
  81.                 m_type = eBK_void;
  82.                 m_size = 0;
  83.                 m_fields.resize(0);
  84.         }
  85.  
  86.         IMetadata* Clone() const
  87.         {
  88.                 CMetadata* pMetadata = new CMetadata();
  89.                 *pMetadata = *this;
  90.                 return pMetadata;
  91.         }
  92.  
  93.         uint32 GetTag() const
  94.         {
  95.                 return m_tag;
  96.         }
  97.  
  98.         size_t GetNumFields() const
  99.         {
  100.                 if (m_tag == eBK_void || m_type != eBK_meta)
  101.                         return 0;
  102.  
  103.                 return m_fields.size();
  104.         }
  105.  
  106.         const IMetadata* GetFieldByIndex(size_t i) const
  107.         {
  108.                 if (m_tag == eBK_void || m_type != eBK_meta)
  109.                         return NULL;
  110.  
  111.                 if (i >= m_fields.size())
  112.                         return NULL;
  113.  
  114.                 return &m_fields[i];
  115.         }
  116.  
  117.         uint32 GetValueType() const
  118.         {
  119.                 if (m_tag == eBK_void)
  120.                         return eBK_void;
  121.  
  122.                 return m_type;
  123.         }
  124.  
  125.         uint8 GetValueSize() const
  126.         {
  127.                 if (m_tag == eBK_void || m_type == eBK_void || m_type == eBK_meta)
  128.                         return 0;
  129.  
  130.                 return m_size;
  131.         }
  132.  
  133.         bool GetValue(uint8* data /*[out]*/, uint8* size /*[in|out]*/) const
  134.         {
  135.                 if (size == NULL)
  136.                         return false;
  137.  
  138.                 if (m_tag == eBK_void || m_type == eBK_void || m_type == eBK_meta)
  139.                 {
  140.                         *size = 0;
  141.                         return false;
  142.                 }
  143.  
  144.                 if (data == NULL || *size < m_size)
  145.                 {
  146.                         *size = m_size;
  147.                         return false;
  148.                 }
  149.  
  150.                 memcpy(data, m_data, m_size);
  151.                 *size = m_size;
  152.                 return true;
  153.         }
  154.  
  155.         CMetadata& operator=(const CMetadata& rhs)
  156.         {
  157.                 Reset();
  158.  
  159.                 m_tag = rhs.m_tag;
  160.                 m_type = rhs.m_type;
  161.  
  162.                 uint8 nsize = rhs.m_size;
  163.                 memcpy(m_data, rhs.m_data, nsize);
  164.                 m_size = rhs.m_size;
  165.                 for (size_t i = 0; i < rhs.m_fields.size(); ++i)
  166.                         m_fields.push_back(rhs.m_fields[i]);
  167.  
  168.                 return *this;
  169.         }
  170.  
  171.         bool operator==(const CMetadata& rhs) const
  172.         {
  173.                 if (m_tag == rhs.m_tag && m_type == rhs.m_type && m_size == rhs.m_size && 0 == memcmp(m_data, rhs.m_data, m_size) && m_fields.size() == rhs.m_fields.size())
  174.                 {
  175.                         for (size_t i = 0; i < m_fields.size(); ++i)
  176.                                 if (!(m_fields[i] == rhs.m_fields[i]))
  177.                                         return false;
  178.                         return true;
  179.                 }
  180.  
  181.                 return false;
  182.         }
  183.  
  184.         // needed when MetadataRecorder is saving - it writes a list of tags and a list types used in this metadata structure
  185.         void ExtractTagsAndTypes(std::set<uint32>& tags, std::set<uint32>& types) const // a stream of 4CC's
  186.         {
  187.                 if (m_tag == eBK_void || m_type == eBK_void)
  188.                         // incomplete metadata definition
  189.                         return;
  190.  
  191.                 tags.insert(m_tag);
  192.                 types.insert(m_type);
  193.                 if (m_type == eBK_meta)
  194.                         for (size_t i = 0; i < m_fields.size(); ++i)
  195.                                 m_fields[i].ExtractTagsAndTypes(tags, types);
  196.         }
  197.  
  198.         // serialize tag/type/data to the output stream
  199.         // MetadataRecorder will write the 32bit size for each toplevel metadata recorded
  200.         void SerializeTo(std::vector<uint8>& to) const
  201.         {
  202.                 if (m_tag == eBK_void || m_type == eBK_void)
  203.                         // incomplete
  204.                         return;
  205.  
  206.                 to.insert(to.end(), (uint8*)&m_tag, (uint8*)&m_tag + sizeof(m_tag));
  207.                 to.insert(to.end(), (uint8*)&m_type, (uint8*)&m_type + sizeof(m_type));
  208.  
  209.                 if (m_type == eBK_meta)
  210.                 {
  211.                         for (size_t i = 0; i < m_fields.size(); ++i)
  212.                                 m_fields[i].SerializeTo(to);
  213.                         uint32 mend = eBK_void;
  214.                         to.insert(to.end(), (uint8*)&mend, (uint8*)&mend + sizeof(mend));
  215.                 }
  216.                 else
  217.                 {
  218.                         to.push_back(m_size); // since we are trying to be very general here, so we have to prefix the size always (although not so memory friendly)
  219.                         to.insert(to.end(), m_data, m_data + m_size);
  220.                 }
  221.         }
  222.  
  223.         // deserialize tag/type/data from the input stream
  224.         // MetadataRecorder will first read the 32bit size for this toplevel metadata, so it can form the input stream
  225.         bool SerializeFrom(const std::vector<uint8>& from, size_t& offset, const std::set<uint32>& tags, const std::set<uint32>& types)
  226.         {
  227.                 Reset();
  228.  
  229.                 if (offset + sizeof(m_tag) > from.size())
  230.                         goto L_error;
  231.                 memcpy(&m_tag, &from[offset], sizeof(m_tag));
  232.                 if (tags.find(m_tag) == tags.end())
  233.                         goto L_error;
  234.                 offset += sizeof(m_tag);
  235.                 if (offset + sizeof(m_type) > from.size())
  236.                         goto L_error;
  237.                 memcpy(&m_type, &from[offset], sizeof(m_type));
  238.                 if (types.find(m_type) == types.end())
  239.                         goto L_error;
  240.                 offset += sizeof(m_type);
  241.                 if (m_type == eBK_meta)
  242.                 {
  243.                         while (true)
  244.                         {
  245.                                 CMetadata metadata;
  246.                                 if (!metadata.SerializeFrom(from, offset, tags, types))
  247.                                         goto L_error;
  248.                                 m_fields.push_back(metadata);
  249.                                 uint32 fcc = eBK_void;
  250.                                 if (offset + sizeof(fcc) > from.size())
  251.                                         goto L_error;
  252.                                 memcpy(&fcc, &from[offset], sizeof(fcc));
  253.                                 if (fcc == eBK_void)
  254.                                 {
  255.                                         offset += sizeof(fcc);
  256.                                         break; // end of this metadata block
  257.                                 }
  258.                         }
  259.                 }
  260.                 else
  261.                 {
  262.                         if (offset + 1 > from.size())
  263.                                 goto L_error;
  264.                         m_size = from[offset++];
  265.                         if (offset + m_size > from.size())
  266.                                 goto L_error;
  267.                         memcpy(m_data, &from[offset], m_size);
  268.                         offset += m_size;
  269.                 }
  270.  
  271.                 return true;
  272.  
  273. L_error:
  274.                 Reset();
  275.                 return false;
  276.         }
  277.  
  278. private:
  279.         uint32                 m_tag;
  280.         uint32                 m_type;
  281.  
  282.         uint8                  m_data[256]; // 255 big enough buffer to hold any basic type value
  283.         uint8                  m_size;
  284.  
  285.         std::vector<CMetadata> m_fields;
  286. };
  287.  
  288. IMetadata* IMetadata::CreateInstance()
  289. {
  290.         return new CMetadata();
  291. }
  292.  
  293. void IMetadata::Delete()
  294. {
  295.         delete this;
  296. }
  297.  
  298. static const char* TopLevelMetadataFolder = "%USER%/!Metadata/";
  299.  
  300. class CMetadataRecorder : public IMetadataRecorder
  301. {
  302. public:
  303.         CMetadataRecorder() : m_mode(eM_None) {}
  304.         ~CMetadataRecorder() {}
  305.  
  306.         bool InitSave(const char* filename)
  307.         {
  308.                 if (m_file.GetHandle())
  309.                         return false; // need to call Reset()
  310.                 Reset();        // safe to do it here (data/file/mode)
  311.                 if (!m_file.Open(string(TopLevelMetadataFolder) + filename, "wb"))
  312.                         return false;
  313.                 m_mode = eM_Saving;
  314.                 return true;
  315.         }
  316.  
  317.         bool InitLoad(const char* filename)
  318.         {
  319.                 if (m_file.GetHandle())
  320.                         return false;
  321.                 Reset(); // data/file/mode (just for safty)
  322.                 if (!m_file.Open(string(TopLevelMetadataFolder) + filename, "rb"))
  323.                         return false;
  324.                 m_mode = eM_Loading;
  325.                 return true;
  326.         }
  327.  
  328.         void RecordIt(const IMetadata* metadata)
  329.         {
  330.                 if (m_mode != eM_Saving || !metadata)
  331.                         return;
  332.  
  333.                 const CMetadata* pMetadata = static_cast<const CMetadata*>(metadata);
  334.                 pMetadata->ExtractTagsAndTypes(m_tags, m_types);
  335.                 m_metadata.push_back(*pMetadata);
  336.         }
  337.  
  338.         void Flush()
  339.         {
  340.                 if (m_mode != eM_Saving)
  341.                         return;
  342.  
  343.                 // write tags and types ending with 0
  344.                 WriteFccCodes(m_file, m_tags, eBK_tags);
  345.                 WriteFccCodes(m_file, m_types, eBK_typs);
  346.  
  347.                 // write toplevel metadata prefixed with data size
  348.                 for (size_t i = 0; i < m_metadata.size(); ++i)
  349.                 {
  350.                         std::vector<uint8> stm;
  351.                         m_metadata[i].SerializeTo(stm);
  352.                         uint32 sz = stm.size();
  353.                         if (sz == 0)
  354.                                 continue;
  355.                         m_file.Write(&sz, sizeof(sz));
  356.                         m_file.Write(&stm[0], sz);
  357.                 }
  358.  
  359.                 // a seperator between flushes
  360.                 uint32 seperator = eBK_void;
  361.                 m_file.Write(&seperator, sizeof(seperator));
  362.  
  363.                 ResetData();
  364.         }
  365.  
  366.         bool Playback(IMetadataListener* pListener)
  367.         {
  368.                 if (m_mode != eM_Loading || !pListener)
  369.                         return false;
  370.  
  371.                 ResetData();
  372.  
  373.                 // read tags and types
  374.                 if (!ReadFccCodes(m_file, m_tags, eBK_tags))
  375.                         return false;
  376.                 if (!ReadFccCodes(m_file, m_types, eBK_typs))
  377.                         return false;
  378.  
  379.                 // read data
  380.                 while (true)
  381.                 {
  382.                         uint32 sz = 0;
  383.                         if (m_file.ReadRaw(&sz, sizeof(sz)) != sizeof(sz))
  384.                                 return false;
  385.                         if (sz == 0)
  386.                                 break; // flush seperator encountered
  387.                         std::vector<uint8> stm;
  388.                         stm.resize(sz);
  389.                         if (m_file.ReadRaw(&stm[0], sz) != sz)
  390.                                 return false;
  391.                         CMetadata metadata;
  392.                         size_t offset = 0;
  393.                         if (!metadata.SerializeFrom(stm, offset, m_tags, m_types))
  394.                                 return false;
  395.                         CRY_ASSERT(offset == stm.size());
  396.                         m_metadata.push_back(metadata);
  397.                 }
  398.  
  399.                 for (size_t i = 0; i < m_metadata.size(); ++i)
  400.                         pListener->OnData(&m_metadata[i]);
  401.                 return true;
  402.         }
  403.  
  404.         void Reset()
  405.         {
  406.                 ResetData();
  407.                 m_file.Close();
  408.                 m_mode = eM_None;
  409.         }
  410.  
  411. private:
  412.         typedef std::vector<CMetadata> TTopLevelMetadataVector;
  413.         TTopLevelMetadataVector m_metadata;
  414.  
  415.         typedef std::set<uint32> TFourCCSet;
  416.         TFourCCSet m_tags, m_types;
  417.  
  418.         CCryFile   m_file;
  419.  
  420.         enum EMode { eM_None, eM_Saving, eM_Loading };
  421.         EMode m_mode;
  422.  
  423.         void ResetData()
  424.         {
  425.                 m_metadata.resize(0);
  426.                 m_tags.clear();
  427.                 m_types.clear();
  428.         }
  429.  
  430.         static inline void WriteFccCodes(CCryFile& file, const TFourCCSet& fccs, uint32 keyword)
  431.         {
  432.                 uint32 fcc = keyword;
  433.                 file.Write(&fcc, sizeof(fcc));
  434.                 for (TFourCCSet::const_iterator it = fccs.begin(); it != fccs.end(); ++it)
  435.                 {
  436.                         fcc = *it;
  437.                         file.Write(&fcc, sizeof(fcc));
  438.                 }
  439.                 fcc = eBK_void;
  440.                 file.Write(&fcc, sizeof(fcc));
  441.         }
  442.  
  443.         static inline bool ReadFccCodes(CCryFile& file, TFourCCSet& fccs, uint32 keyword)
  444.         {
  445.                 uint32 fcc = 0;
  446.                 if (file.ReadRaw(&fcc, sizeof(fcc)) != sizeof(fcc))
  447.                         return false;
  448.                 if (fcc != keyword)
  449.                         return false;
  450.                 while (true)
  451.                 {
  452.                         if (file.ReadRaw(&fcc, sizeof(fcc)) != sizeof(fcc))
  453.                                 return false;
  454.                         if (fcc == eBK_tags || fcc == eBK_typs)
  455.                                 return false;
  456.                         if (fcc == eBK_void)
  457.                                 break;
  458.                         fccs.insert(fcc);
  459.                 }
  460.                 return true;
  461.         }
  462.  
  463. };
  464.  
  465. IMetadataRecorder* IMetadataRecorder::CreateInstance()
  466. {
  467.         return new CMetadataRecorder();
  468. }
  469.  
  470. void IMetadataRecorder::Delete()
  471. {
  472.         delete this;
  473. }
  474.  
downloadMetadataRecorder.cpp Source code - Download CRYENGINE Source code
Related Source Codes/Software:
postal - 2017-06-11
reactide - Reactide is the first dedicated IDE for React web ... 2017-06-11
rkt - rkt is a pod-native container engine for Linux. It... 2017-06-11
uWebSockets - Tiny WebSockets https://for... 2017-06-11
realworld - TodoMVC for the RealWorld - Exemplary fullstack Me... 2017-06-11
CRYENGINE - CRYENGINE is a powerful real-time game development... 2017-06-11
goreplay - GoReplay is an open-source tool for capturing and ... 2017-06-10
pyenv - Simple Python version management 2017-06-10
redux-saga - An alternative side effect model for Redux apps ... 2017-06-10
angular-starter - 2017-06-10

 Back to top