/*---------------------------------------------------------------------------* Project: Horizon File: NinjaXmlReader.cpp Copyright (C)2015 Nintendo Co., Ltd. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. $Rev$ *---------------------------------------------------------------------------*/ #include "NinjaXmlReader.h" #include "SimpleXmlPreprocessor.h" #include "HeapManager.h" #include #include namespace ConsoleRestore { NinjaXmlReader::NinjaXmlReader() { // TODO 自動生成されたコンストラクター・スタブ } NinjaXmlReader::~NinjaXmlReader() { // TODO Auto-generated destructor stub } void NinjaXmlReader::GetNsUid(std::string& nsUid, std::string xml) { if(!SimpleXmlPreprocessor::Canonicalize(xml)) { return; } nn::xml::simple::SimpleXmlParser parser(common::GetAllocator()); parser.parse(reinterpret_cast(const_cast(xml.c_str())), xml.size()); GetContentOfElement(parser, "ns_uid", nsUid); } bool NinjaXmlReader::HasContentLock(std::string xml) { return HasElement(xml, "content_lock"); } bool NinjaXmlReader::HasExternalSeed(std::string xml) { return HasElement(xml, "external_seed"); } nn::fnd::DateTime NinjaXmlReader::GetPlayableDate(std::string xml) { if(!SimpleXmlPreprocessor::Canonicalize(xml)) { return nn::fnd::DateTime::MIN_DATETIME; } std::string playableDate; nn::xml::simple::SimpleXmlParser parser(common::GetAllocator()); parser.parse(reinterpret_cast(const_cast(xml.c_str())), xml.size()); GetContentOfElement(parser, "playable_date", playableDate); // playable_date は YYYY-MM-DD 形式 std::string yearStr(playableDate.substr(0, 4)); std::string monthStr(playableDate.substr(5, 2)); std::string dayStr(playableDate.substr(8, 2)); char* end = '\0'; s32 year = std::strtol(yearStr.c_str(),&end, 10); s32 month = std::strtol(monthStr.c_str(),&end, 10); s32 day = std::strtol(dayStr.c_str(),&end, 10); return nn::fnd::DateTime::FromParameters(year, month, day); } bool NinjaXmlReader::HasElement(std::string xml, const char* element) { if(!SimpleXmlPreprocessor::Canonicalize(xml)) { return false; } nn::xml::simple::SimpleXmlParser parser(common::GetAllocator()); parser.parse(reinterpret_cast(const_cast(xml.c_str())), xml.size()); return GetElement(parser, element); } bool NinjaXmlReader::GetContentOfElement(nn::xml::simple::SimpleXmlParser& parser, const char* target, std::string& content) { if ( !parser.isError() ) { const nn::xml::simple::SimpleXmlParser::Node* pRootNode = parser.getRootNode(); int rootNameSize = pRootNode->nameSize + 1; char* pRootName = new char[ rootNameSize ]; std::strlcpy( pRootName, (char*)pRootNode->name, rootNameSize ); NN_LOG( "rootNode name: %s\n", pRootName ); delete pRootName; bool found = false; GetNodes(pRootNode, target, content, found); return found; } return false; } bool NinjaXmlReader::GetElement(nn::xml::simple::SimpleXmlParser& parser, const char* element) { std::string content; return GetContentOfElement(parser, element, content); } void NinjaXmlReader::GetNodes( const nn::xml::simple::SimpleXmlParser::Node* topNodes, const char* target, std::string& content, bool& found) { const nn::xml::simple::SimpleXmlParser::Node* pTargetNode = topNodes->firstChild; while ( pTargetNode != NULL ) { // 見つかるまで更新する // 同じ名前の要素が複数ある場合1つ目の要素を見つけた時点でtrueになる bool targetIsCurrentNode = GetNodeName(pTargetNode, target); if(!found) { found = targetIsCurrentNode; } /* * [Point]子ノードのみを持つノードのcontentSizeは0となる。 */ if(pTargetNode->contentSize > 0) { GetNodeContent(pTargetNode, targetIsCurrentNode, content); } else { GetNodes(pTargetNode, target, content, found); } pTargetNode = pTargetNode->next; } } bool NinjaXmlReader::GetNodeName( const nn::xml::simple::SimpleXmlParser::Node* pNode, const char* target) { /* * [Point] Node::nameには、そのノードの名前(タグ名)以外のデータも含まれる。ただしそのノードの名前は必ずデータの先頭に来るため、 * Node::nameSize分のデータをNode::nameの先頭から取得することで、そのノードの名前を取得することができる。 */ char* pNodeName = new char[ pNode->nameSize+1 ]; std::strlcpy( pNodeName, (char*)pNode->name, pNode->nameSize+1 ); NN_LOG( "Node name: %s\n", pNodeName ); if(!std::strcmp(pNodeName, target)) { delete pNodeName; return true; } else { delete pNodeName; return false; } } void NinjaXmlReader::GetNodeContent( const nn::xml::simple::SimpleXmlParser::Node* pNode, bool found, std::string& content) { if(pNode->contentSize > 0) { /* * [Point] Node::contentには、そのノードのコンテンツ以外のデータも含まれる。ただしそのノードのコンテンツは必ずデータの先頭に来るため、 * Node::contentSize分のデータをNode::contentの先頭から取得することで、そのノードのコンテンツを取得することができる。 */ char* pNodeContent = new char[ pNode->contentSize+1 ]; std::strlcpy( pNodeContent, (char*)pNode->content, pNode->contentSize+1); NN_LOG( "Node content: %s\n", pNodeContent ); if(found) { std::string targetContent(reinterpret_cast(const_cast(pNode->content))); content = targetContent.substr(0, pNode->contentSize); } delete pNodeContent; } } } /* namespace ConsoleRestore */