Index   Main   Namespaces   Classes   Hierarchy   Annotated   Files   Compound   Global   Pages  

SgGameWriter.cpp

Go to the documentation of this file.
00001 //----------------------------------------------------------------------------
00002 /** @file SgGameWriter.cpp */
00003 //----------------------------------------------------------------------------
00004 
00005 #include "SgSystem.h"
00006 #include "SgGameWriter.h"
00007 
00008 #include <iostream>
00009 #include "SgDebug.h"
00010 #include "SgException.h"
00011 #include "SgNode.h"
00012 
00013 using namespace std;
00014 using SgPropUtil::GetPointFmt;
00015 
00016 //----------------------------------------------------------------------------
00017 
00018 SgGameWriter::SgGameWriter(ostream& out)
00019     : m_out(out),
00020       m_fileFormat(4),
00021       m_numPropsOnLine(0)
00022 {
00023 }
00024 
00025 void SgGameWriter::WriteGame(const SgNode& root, bool allProps,
00026                              int fileFormat, int gameNumber, int defaultSize)
00027 {
00028     if (! m_out)
00029         throw SgException("SgGameWriter: write error");
00030     // Add file format property to root. If file format not specified,
00031     // default to file format read in, or FF[4] for new files.
00032     if (fileFormat != 0)
00033         m_fileFormat = fileFormat;
00034     else if (root.HasProp(SG_PROP_FORMAT))
00035         m_fileFormat = root.GetIntProp(SG_PROP_FORMAT);
00036     SgPropPointFmt fmt = GetPointFmt(gameNumber);
00037     WriteSubtree(root, allProps, defaultSize, fmt);
00038     m_out.put('\n');
00039 }
00040 
00041 void SgGameWriter::WriteSubtree(const SgNode& nodeRef, bool allProps,
00042                                 int boardSize, SgPropPointFmt fmt)
00043 {
00044     // Start new sequence on a new line.
00045     StartNewLine();
00046 
00047     // Opening parenthesis.
00048     m_out.put('(');
00049 
00050     // Write out main sequence first.
00051     const SgNode* node = &nodeRef;
00052     do
00053     {
00054         HandleProps(node, boardSize);
00055         m_out.put(';');
00056         WriteNode(*node, allProps, boardSize, fmt);
00057         node = node->LeftMostSon();
00058     } while (node && ! node->HasRightBrother());
00059 
00060     // Now either reached end of branch, or fork in linear sequence. Write out
00061     // each subtree recursively.
00062     while (node)
00063     {
00064         HandleProps(node, boardSize);
00065         WriteSubtree(*node, allProps, boardSize, fmt);
00066         node = node->RightBrother();
00067     }
00068 
00069     // Closing parenthesis.
00070     m_out.put(')');
00071 }
00072 
00073 void SgGameWriter::HandleProps(const SgNode* node, int& boardSize) const
00074 {
00075     int value;
00076     bool hasSizeProp = node->GetIntProp(SG_PROP_SIZE, &value);
00077     if (hasSizeProp)
00078     {
00079         if (value >= SG_MIN_SIZE && value <= SG_MAX_SIZE)
00080             boardSize = value;
00081         else
00082             SgWarning() << "Invalid size " << value;
00083     }
00084 }
00085 
00086 void SgGameWriter::WriteNode(const SgNode& node, bool allProps, int boardSize,
00087                              SgPropPointFmt fmt)
00088 {
00089     for (SgPropListIterator it(node.Props()); it; ++it)
00090     {
00091         SgProp* prop = *it;
00092         vector<string> values;
00093         // Check whether property should be written, and get its value.
00094         if ((allProps || ShouldWriteProperty(*prop))
00095             && prop->ToString(values, boardSize, fmt, m_fileFormat))
00096         {
00097             // Start specific properties on a new line to make file easier
00098             // to read.
00099             if (prop->Flag(SG_PROPCLASS_NEWLINE))
00100                 StartNewLine();
00101             m_out << prop->Label();
00102             for (vector<string>::const_iterator it2 = values.begin();
00103                  it2 != values.end(); ++it2)
00104                 m_out << '[' << (*it2) << ']';
00105             // Limit number of properties per line.
00106             if (++m_numPropsOnLine >= 10)
00107                 StartNewLine();
00108     }   }
00109 
00110     // Start first move node after root node on a new line.
00111     if (node.HasProp(SG_PROP_GAME))
00112         StartNewLine();
00113 }
00114 
00115 void SgGameWriter::StartNewLine()
00116 {
00117     // Start a new line unless we're already at the beginning of a line.
00118     if (m_numPropsOnLine > 0)
00119     {
00120         m_numPropsOnLine = 0;
00121         m_out.put('\n');
00122     }
00123 }
00124 
00125 bool SgGameWriter::ShouldWriteProperty(const SgProp& prop)
00126 {
00127     // Only write out clean properties with FF[3].
00128     // FUTURE: Could make standard adherence a separate option.
00129     if (m_fileFormat == 3 && prop.Flag(SG_PROPCLASS_NOTCLEAN))
00130         return false;
00131 
00132     if (prop.Label() == "")
00133         return false;
00134 
00135     // don't write out time left properties (e.g. problem collections).
00136     if (prop.ID() == SG_PROP_TIME_BLACK || prop.ID() == SG_PROP_TIME_WHITE)
00137         return false;
00138 
00139     // Default: write out all properties.
00140     return true;
00141 }
00142 
00143 //----------------------------------------------------------------------------
00144 


Sun Mar 13 2011 Doxygen 1.7.1