Go to the documentation of this file.00001
00002
00003
00004
00005 #include "SgSystem.h"
00006 #include "SgGameReader.h"
00007
00008 #include <cstdio>
00009 #include <iostream>
00010 #include <map>
00011 #include <vector>
00012 #include "SgDebug.h"
00013 #include "SgException.h"
00014 #include "SgNode.h"
00015
00016 using namespace std;
00017
00018
00019
00020 namespace {
00021
00022
00023 void PrintWarning(ostream& out, SgGameReader::Warnings& warnings, int index,
00024 const char* text)
00025 {
00026 if (! warnings.test(index))
00027 return;
00028 out << text << '\n';
00029 warnings.reset(index);
00030 }
00031
00032 }
00033
00034
00035
00036 SgGameReader::SgGameReader(istream& in, int defaultSize)
00037 : m_in(in),
00038 m_defaultSize(defaultSize),
00039 m_fileFormat(4)
00040 {
00041 }
00042
00043 bool SgGameReader::GetIntProp(const SgGameReader::RawProperties& properties,
00044 const string& label, int& value)
00045 {
00046 RawProperties::const_iterator it = properties.find(label);
00047 if (it == properties.end() || it->second.size() == 0)
00048 return false;
00049 istringstream in(it->second[0]);
00050 in >> value;
00051 return ! in.fail();
00052 }
00053
00054
00055
00056
00057
00058 void SgGameReader::HandleProperties(SgNode* node,
00059 const RawProperties& properties,
00060 int& boardSize, SgPropPointFmt& fmt)
00061 {
00062 int value;
00063 if (GetIntProp(properties, "SZ", value))
00064 {
00065 if (value < SG_MIN_SIZE || value > SG_MAX_SIZE)
00066 m_warnings.set(INVALID_BOARDSIZE);
00067 else
00068 boardSize = value;
00069 }
00070 if (GetIntProp(properties, "GM", value))
00071 fmt = SgPropUtil::GetPointFmt(value);
00072 for (RawProperties::const_iterator it = properties.begin();
00073 it != properties.end(); ++it)
00074 {
00075 const string& label = it->first;
00076 const vector<string>& values = it->second;
00077 if (values.size() == 0)
00078 m_warnings.set(PROPERTY_WITHOUT_VALUE);
00079 SgProp* prop;
00080 SgPropID id = SgProp::GetIDOfLabel(label);
00081 if (id != SG_PROP_NONE)
00082 prop = SgProp::CreateProperty(id);
00083 else
00084 prop =
00085 new SgPropUnknown(SG_PROP_UNKNOWN, label, vector<string>());
00086 if (prop->FromString(values, boardSize, fmt))
00087 node->Add(prop);
00088 }
00089 }
00090
00091 void SgGameReader::PrintWarnings(ostream& out) const
00092 {
00093 Warnings warnings = m_warnings;
00094
00095 PrintWarning(out, warnings, INVALID_BOARDSIZE, "Invalid board size");
00096 PrintWarning(out, warnings, PROPERTY_WITHOUT_VALUE,
00097 "Property withour value");
00098 SG_ASSERT(warnings.none());
00099 }
00100
00101 SgNode* SgGameReader::ReadGame(bool resetWarnings)
00102 {
00103 if (resetWarnings)
00104 m_warnings.reset();
00105 SgNode* root = 0;
00106 int c;
00107 while ((c = m_in.get()) != EOF)
00108 {
00109 while (c != '(' && c != EOF)
00110 c = m_in.get();
00111 if (c == EOF)
00112 break;
00113 root = ReadSubtree(0, m_defaultSize, SG_PROPPOINTFMT_GO);
00114 if (root)
00115 root = root->Root();
00116 if (root)
00117 break;
00118 }
00119 return root;
00120 }
00121
00122 void SgGameReader::ReadGames(SgVectorOf<SgNode>* rootList)
00123 {
00124 m_warnings.reset();
00125 SG_ASSERT(rootList);
00126 rootList->Clear();
00127 while (true)
00128 {
00129 SgNode* root = ReadGame(false);
00130 if (root)
00131 rootList->PushBack(root);
00132 else
00133 break;
00134 }
00135 }
00136
00137 string SgGameReader::ReadLabel(int c)
00138 {
00139
00140
00141
00142 string label;
00143 label += static_cast<char>(c);
00144 while ((c = m_in.get()) != EOF
00145 && (('A' <= c && c <= 'Z')
00146 || ('a' <= c && c <= 'z')
00147 || ('0' <= c && c <= '9')))
00148 label += static_cast<char>(c);
00149 if (c != EOF)
00150 m_in.unget();
00151 return label;
00152 }
00153
00154 SgNode* SgGameReader::ReadSubtree(SgNode* node, int boardSize,
00155 SgPropPointFmt fmt)
00156 {
00157 RawProperties properties;
00158 int c;
00159 while ((c = m_in.get()) != EOF && c != ')')
00160 {
00161 if ('A' <= c && c <= 'Z')
00162 {
00163 string label = ReadLabel(c);
00164 m_in >> ws;
00165 string value;
00166 while (ReadValue(value))
00167 properties[label].push_back(value);
00168 }
00169 else if (c == ';')
00170 {
00171 if (node)
00172 {
00173 HandleProperties(node, properties, boardSize, fmt);
00174 properties.clear();
00175 node = node->NewRightMostSon();
00176 }
00177 else
00178 node = new SgNode();
00179 }
00180 else if (c == '(')
00181 {
00182 HandleProperties(node, properties, boardSize, fmt);
00183 properties.clear();
00184 ReadSubtree(node, boardSize, fmt);
00185 }
00186 }
00187 HandleProperties(node, properties, boardSize, fmt);
00188 return node;
00189 }
00190
00191 bool SgGameReader::ReadValue(string& value)
00192 {
00193 m_in >> ws;
00194 value = "";
00195 int c;
00196 if ((c = m_in.get()) == EOF)
00197 return false;
00198 if (c != '[')
00199 {
00200 m_in.unget();
00201 return false;
00202 }
00203 bool inEscape = false;
00204 while ((c = m_in.get()) != EOF && (c != ']' || inEscape))
00205 {
00206 if (c != '\n')
00207 value += static_cast<char>(c);
00208 if (inEscape)
00209 inEscape = false;
00210 else if (c == '\\')
00211 inEscape = true;
00212 }
00213 return true;
00214 }
00215
00216