TreeValue* FileFormatXMove::Read(const MotionFileHandler& /*context*/, std::istream& is, const BinMemFactory& memfactory, const TreeValue* readoptions) const throw(MotionFileException) { // options FileFormatOptionsXMove xmove_options; if (readoptions) { xmove_options.FromTree(readoptions); } // load XML pugi::xml_document doc; pugi::xml_parse_result result = doc.load(is); if (!result) { throw MotionFileException(MotionFileException::formaterror, result.description()); } std::auto_ptr<XMLReadingMachine> reader; if (xmove_options.LegacyCompoundNames) { // Support legacy version of format in which // elements of time sequence and event groups structures have assumed types // and some naming conventions are different reader = std::auto_ptr<XMLReadingMachine>( new XMLReadingMachineLegacy(memfactory) ); } else { // Standard XML reader reader = std::auto_ptr<XMLReadingMachine>( new XMLReadingMachine(memfactory) ); } // find xmove node pugi::xml_node xmove_node = doc.child("xmove"); // must have xmove node if (!xmove_node) { throw MotionFileException(MotionFileException::formaterror, "XML missing xmove section"); } // parse XML tree TreeValue* trial_tree = reader->ReadValue(xmove_node); TreeCompound* trial_object = TreeValueCast<TreeCompound>( trial_tree ); // optionally replace any float32 info with float64 if (xmove_options.ConvertBinaryFloat32) { for (size_t calclevel = 0; calclevel < trial_object->NumElements(); calclevel++) { TreeCompound* section = TreeValueCast<TreeCompound> ( trial_object->Node(calclevel)->Value() ); ConvertListFloat32To64(section, "Sequences", TimeSequence::StructureName, memfactory); ConvertListFloat32To64(section, "EventGroups", EventGroup::StructureName, memfactory); } } return trial_object; }
TreeValue* MOBLFormatReader::ReadTrial(UInt32 index) throw(MotionFileException) { // move to required trial UInt32 doc_index_needed = index + 1; if (!PositionReader(doc_index_needed)) throw MotionFileException(MotionFileException::formaterror, "invalid trial index"); // auto ptr so it will get released on exception thrown std::auto_ptr<TreeCompound> MOBLresult( new TreeCompound ); // read try { BSONReaderMOBL reader(*stream); reader.ReadDocument(*MOBLresult); } catch (const BSONReadException& e) { throw MotionFileException(MotionFileException::formaterror, e.message.c_str()); } // successful read means now at next doc ++num_docs_read; // the data is actually in 'd' subsections const TreeCompound* MOBLAcq = MOBLresult->GetType<TreeCompound>("Acq"); const TreeCompound* MOBLAcq_d = MOBLAcq ? MOBLAcq->GetType<TreeCompound>("d") : NULL; const TreeCompound* MOBLUserInput = MOBLresult->GetType<TreeCompound>("UserInput"); const TreeCompound* MOBLUserInput_d = MOBLUserInput ? MOBLUserInput->GetType<TreeCompound>("d") : NULL; // copy those parts (should do shallow copy for time sequences anyway) TreeCompound* Acq = new TreeCompound; TreeCompound* UserInput = new TreeCompound; Acq->CopyFrom(MOBLAcq_d); UserInput->CopyFrom(MOBLUserInput_d); // make new item TreeCompound* result = new TreeCompound; result->Set("Acq", Acq); result->Set("UserInput", UserInput); return result; }
bool MOBLFormatReader::PositionReader(UInt32 doc_index_needed) throw(MotionFileException) { // must reset reader if we've already read past this index // or if no reader yet created if ((num_docs_read > doc_index_needed) || (stream == NULL)) { // remove previous reader if any ClearReader(); // clear error bits is->clear(); // skip header (always uncompressed) is->seekg(21, std::ios::beg); // use appropriate decoder if (readoptions.UseGZIP) stream = new BSONInputStreamGZ(*is); else stream = new BSONInputStreamSTL(*is); // reset docs read num_docs_read = 0; } // skip to trial try { while (num_docs_read < doc_index_needed) { UInt32 docsize(0); stream->ReadBinary(&docsize, 4); stream->SkipBytes(docsize-4); ++num_docs_read; } } catch (const BSONReadException& e) { throw MotionFileException(MotionFileException::formaterror, e.message.c_str()); } return stream->HaveMore(); }