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;
00052 }
00053
00054
00055
00056
00057
00058
00059 void SgGameReader::HandleProperties(SgNode* node,
00060 const RawProperties& properties,
00061 int& boardSize, SgPropPointFmt& fmt)
00062 {
00063 int value;
00064 if (GetIntProp(properties, "SZ", value))
00065 {
00066 if (value < SG_MIN_SIZE || value > SG_MAX_SIZE)
00067 m_warnings.set(INVALID_BOARDSIZE);
00068 else
00069 boardSize = value;
00070 }
00071 if (GetIntProp(properties, "GM", value))
00072 fmt = SgPropUtil::GetPointFmt(value);
00073 for (RawProperties::const_iterator it = properties.begin();
00074 it != properties.end(); ++it)
00075 {
00076 const string& label = it->first;
00077 const vector<string>& values = it->second;
00078 if (values.size() == 0)
00079 m_warnings.set(PROPERTY_WITHOUT_VALUE);
00080 SgProp* prop;
00081 SgPropID id = SgProp::GetIDOfLabel(label);
00082 if (id != SG_PROP_NONE)
00083 prop = SgProp::CreateProperty(id);
00084 else
00085 prop =
00086 new SgPropUnknown(SG_PROP_UNKNOWN, label, vector<string>());
00087 if (prop->FromString(values, boardSize, fmt))
00088 node->Add(prop);
00089 }
00090 }
00091
00092 void SgGameReader::PrintWarnings(ostream& out) const
00093 {
00094 Warnings warnings = m_warnings;
00095
00096 PrintWarning(out, warnings, INVALID_BOARDSIZE, "Invalid board size");
00097 PrintWarning(out, warnings, PROPERTY_WITHOUT_VALUE,
00098 "Property withour value");
00099 SG_ASSERT(warnings.none());
00100 }
00101
00102 SgNode* SgGameReader::ReadGame(bool resetWarnings)
00103 {
00104 if (resetWarnings)
00105 m_warnings.reset();
00106 SgNode* root = 0;
00107 int c;
00108 while ((c = m_in.get()) != EOF)
00109 {
00110 while (c != '(' && c != EOF)
00111 c = m_in.get();
00112 if (c == EOF)
00113 break;
00114 root = ReadSubtree(0, m_defaultSize, SG_PROPPOINTFMT_GO);
00115 if (root)
00116 root = root->Root();
00117 if (root)
00118 break;
00119 }
00120 return root;
00121 }
00122
00123 void SgGameReader::ReadGames(SgVectorOf<SgNode>* rootList)
00124 {
00125 m_warnings.reset();
00126 SG_ASSERT(rootList);
00127 rootList->Clear();
00128 while (true)
00129 {
00130 SgNode* root = ReadGame(false);
00131 if (root)
00132 rootList->PushBack(root);
00133 else
00134 break;
00135 }
00136 }
00137
00138 string SgGameReader::ReadLabel(int c)
00139 {
00140
00141
00142
00143 string label;
00144 label += static_cast<char>(c);
00145 while ((c = m_in.get()) != EOF
00146 && (('A' <= c && c <= 'Z')
00147 || ('a' <= c && c <= 'z')
00148 || ('0' <= c && c <= '9')))
00149 label += static_cast<char>(c);
00150 if (c != EOF)
00151 m_in.unget();
00152 return label;
00153 }
00154
00155 SgNode* SgGameReader::ReadSubtree(SgNode* node, int boardSize,
00156 SgPropPointFmt fmt)
00157 {
00158 RawProperties properties;
00159 int c;
00160 while ((c = m_in.get()) != EOF && c != ')')
00161 {
00162 if ('A' <= c && c <= 'Z')
00163 {
00164 string label = ReadLabel(c);
00165 m_in >> ws;
00166 string value;
00167 while (ReadValue(value))
00168 properties[label].push_back(value);
00169 }
00170 else if (c == ';')
00171 {
00172 if (node)
00173 {
00174 HandleProperties(node, properties, boardSize, fmt);
00175 properties.clear();
00176 node = node->NewRightMostSon();
00177 }
00178 else
00179 node = new SgNode();
00180 }
00181 else if (c == '(')
00182 {
00183 HandleProperties(node, properties, boardSize, fmt);
00184 properties.clear();
00185 ReadSubtree(node, boardSize, fmt);
00186 }
00187 }
00188 HandleProperties(node, properties, boardSize, fmt);
00189 return node;
00190 }
00191
00192 bool SgGameReader::ReadValue(string& value)
00193 {
00194 m_in >> ws;
00195 value = "";
00196 int c;
00197 if ((c = m_in.get()) == EOF)
00198 return false;
00199 if (c != '[')
00200 {
00201 m_in.unget();
00202 return false;
00203 }
00204 bool inEscape = false;
00205 while ((c = m_in.get()) != EOF && (c != ']' || inEscape))
00206 {
00207 if (c != '\n')
00208 value += static_cast<char>(c);
00209 if (inEscape)
00210 inEscape = false;
00211 else if (c == '\\')
00212 inEscape = true;
00213 }
00214 return true;
00215 }
00216
00217