/*---------------------------------------------------------------------------* 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(char* pNsUid, size_t size, 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", pNsUid, size); } 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; } const size_t BUF_SIZE = 1024 * 1024; common::HeapManager manager(BUF_SIZE); void* buf = manager.GetAddr(); char* playableDateStr = reinterpret_cast(buf); if(playableDateStr) { nn::xml::simple::SimpleXmlParser parser(common::GetAllocator()); parser.parse(reinterpret_cast(const_cast(xml.c_str())), xml.size()); GetContentOfElement(parser, "playable_date", playableDateStr, BUF_SIZE); // playable_date は YYYY-MM-DD 形式 std::string yearStr(std::string(playableDateStr).substr(0, 4)); std::string monthStr(std::string(playableDateStr).substr(5, 2)); std::string dayStr(std::string(playableDateStr).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); nn::fnd::DateTime playableDate = nn::fnd::DateTime::FromParameters(year, month, day); return playableDate; } return nn::fnd::DateTime::MIN_DATETIME; } 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, char* content, size_t bufSize) { 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, bufSize, found); return found; } return false; } bool NinjaXmlReader::GetElement(nn::xml::simple::SimpleXmlParser& parser, const char* element) { const size_t BUF_SIZE = 1024 * 1024; common::HeapManager manager(BUF_SIZE); void* addr = manager.GetAddr(); if(addr) { return GetContentOfElement(parser, element, reinterpret_cast(addr), BUF_SIZE); } return false; } void NinjaXmlReader::GetNodes( const nn::xml::simple::SimpleXmlParser::Node* topNodes, const char* target, char* content, size_t bufSize, 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, bufSize); } else { GetNodes(pTargetNode, target, content, bufSize, 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, char* content, size_t bufSize ) { 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) { if(pNode->contentSize+1 < bufSize) { std::strlcpy(content, (char*)pNode->content, pNode->contentSize+1); } else { std::strlcpy(content, (char*)pNode->content, bufSize); } } delete pNodeContent; } } } /* namespace ConsoleRestore */