ConditionalTags.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "StdTagBase.h"
00022 #include <ctype.h>
00023 #include <sstream>
00024 #include <list>
00025
00026 using namespace servlet::taglib;
00027 using namespace std;
00028
00029 namespace csp
00030 {
00031 namespace tags
00032 {
00033
00034
00038 class IfTag: public StdTagBase
00039 {
00040 private:
00041 string m_cond;
00042 public:
00043 IfTag(const string& name)
00044 : StdTagBase(name)
00045 {}
00046 virtual void doStartTag(const attribs_t& attribs);
00047 virtual void doEndTag();
00048 };
00049
00050 void IfTag::doStartTag(const Generator::attribs_t& attribs)
00051 {
00052 get_attr(attribs, "test", m_cond, "csp:if");
00053 *body << "if(" << m_cond << ") {"<<endl;
00054
00055 }
00056
00057 void IfTag::doEndTag()
00058 {
00059 *body<<endl<<"} /* end csp:foreach_attr: "<<m_cond<<" */"<<endl;
00060 }
00061
00073 class ChoiceTag: public StdTagBase
00074 {
00075 private:
00076 stringstream m_my_body;
00077 struct condition
00078 {
00079 string name;
00080 string cond;
00081 string body;
00082 };
00083 list<condition> m_conditions;
00084 condition* m_my_condition;
00085 public:
00086 ChoiceTag(const string& name)
00087 : StdTagBase(name)
00088 , m_my_condition(0)
00089 {}
00090 virtual void doStartTag(const attribs_t& attribs);
00091 virtual void doEndTag();
00092 virtual void initChildBuffers();
00093 private:
00094 void doWhenStartTag(const attribs_t& attribs);
00095 void doTopEndTag();
00096 void doChildEndTag();
00097 };
00098
00099 void ChoiceTag::initChildBuffers()
00100 {
00101 StdTagBase::initChildBuffers();
00102 m_child_body = &m_my_body;
00103 if(getName()!="csp:choice") {
00104 ChoiceTag* parent = (ChoiceTag*)this->parent;
00105 condition c;
00106 parent->m_conditions.push_back(c);
00107 m_my_condition = &parent->m_conditions.back();
00108 m_my_condition->name = getName();
00109 }
00110 }
00111
00112 void ChoiceTag::doWhenStartTag(const Generator::attribs_t& attribs)
00113 {
00114 ChoiceTag* parent = (ChoiceTag*)this->parent;
00115 get_attr(attribs, "test", m_my_condition->cond, "csp:when");
00116 }
00117
00118 void ChoiceTag::doStartTag(const Generator::attribs_t& attribs)
00119 {
00120 if(getName() != "csp:choice") {
00121 if(this->parent->getName()!="csp:choice")
00122 throw runtime_error("<"+getName()+"> must be enclosed in <csp:choice> tag.");
00123 }
00124 if(getName() == "csp:when")
00125 doWhenStartTag(attribs);
00126 }
00127
00128 void ChoiceTag::doEndTag()
00129 {
00130 if(getName() == "csp:choice")
00131 doTopEndTag();
00132 else
00133 doChildEndTag();
00134 }
00135 void ChoiceTag::doChildEndTag()
00136 {
00137 m_my_condition->body.assign(m_my_body.str());
00138 }
00139 void ChoiceTag::doTopEndTag()
00140 {
00142
00143
00144
00145 bool otherwise = false;
00146 bool first = true;
00147 for(list<condition>::iterator it = m_conditions.begin(); it!=m_conditions.end(); it++) {
00148 if(otherwise) {
00149 throw runtime_error("<csp:otherwise> can only be the last child of <csp:choice>");
00150 }
00151 if(it->name == "csp:when") {
00152 *body<<((first)?"":"else ")<<"if("<<it->cond<<") {\n" << it->body << "\n}\n";
00153 first=false;
00154 } else if(it->name == "csp:otherwise") {
00155 otherwise = true;
00156 *body<<"else {\n" << it->body << "\n}\n";
00157 } else {
00158 throw runtime_error("Invalid child of <csp:choice>: "+it->name);
00159 }
00160 }
00161 }
00175 class SwitchTag: public StdTagBase
00176 {
00177 private:
00178 stringstream m_my_body;
00179 string m_test;
00180 struct condition
00181 {
00182 string name;
00183 string cond;
00184 string body;
00185 bool fallthrough;
00186 };
00187 list<condition> m_conditions;
00188 condition* m_my_condition;
00189 public:
00190 SwitchTag(const string& name)
00191 : StdTagBase(name)
00192 , m_my_condition(0)
00193 {}
00194 virtual void doStartTag(const attribs_t& attribs);
00195 virtual void doEndTag();
00196 virtual void initChildBuffers();
00197 private:
00198 void doTopEndTag();
00199 void doChildEndTag();
00200 };
00201
00202 void SwitchTag::initChildBuffers()
00203 {
00204 StdTagBase::initChildBuffers();
00205 m_child_body = &m_my_body;
00206 if(getName()!="csp:switch") {
00207 SwitchTag* parent = (SwitchTag*)this->parent;
00208 condition c;
00209 parent->m_conditions.push_back(c);
00210 m_my_condition = &parent->m_conditions.back();
00211 m_my_condition->name = getName();
00212 m_my_condition->fallthrough = false;
00213 }
00214 }
00215
00216 void SwitchTag::doStartTag(const Generator::attribs_t& attribs)
00217 {
00218 if(getName() != "csp:switch") {
00219 if(this->parent->getName()!="csp:switch")
00220 throw runtime_error("<"+getName()+"> must be enclosed in <csp:switch> tag.");
00221 SwitchTag* parent = (SwitchTag*)this->parent;
00222 if(getName() == "csp:case")
00223 get_attr(attribs, "value", m_my_condition->cond, "csp:case");
00224 string ft;
00225 get_attr(attribs, "fallthrough", ft, getName(), "false");
00226 m_my_condition->fallthrough = (ft == "true");
00227 } else {
00228 get_attr(attribs, "test", m_test, "csp:switch");
00229 }
00230 }
00231
00232 void SwitchTag::doEndTag()
00233 {
00234 if(getName() == "csp:switch")
00235 doTopEndTag();
00236 else
00237 doChildEndTag();
00238 }
00239 void SwitchTag::doChildEndTag()
00240 {
00241 m_my_condition->body.assign(m_my_body.str());
00242 }
00243 void SwitchTag::doTopEndTag()
00244 {
00246
00247
00248
00249 int otherwise = 0;
00250 *body<<"switch ("<<m_test<<") {\n";
00251 for(list<condition>::iterator it = m_conditions.begin(); it!=m_conditions.end(); it++) {
00252 if(it->name == "csp:case") {
00253 *body<<"\tcase "<<it->cond<<":\n\t{" << it->body << "\n\t}\n";
00254 if(!it->fallthrough)
00255 *body<<"\tbreak;\n";
00256 } else if(it->name == "csp:default") {
00257 otherwise++;
00258 *body<<"default:\n\t{\n" << it->body << "\n\t}\n";
00259 if(!it->fallthrough)
00260 *body<<"\tbreak;\n";
00261 } else {
00262 throw runtime_error("Invalid child of <csp:switch>: "+it->name);
00263 }
00264 if(otherwise>1) {
00265 throw runtime_error("<csp:default> can only appear once in <csp:switch>");
00266 }
00267 }
00268 *body<<"} /* end of switch("<<m_test<<") */\n";
00269 }
00270
00271 }
00272 }
00273 DECLARE_COMPILE_TIME_TAGLIB(csp)
00274 EXPORT_COMPILE_TIME_TAG(csp, if, csp::tags::IfTag)
00275 EXPORT_COMPILE_TIME_TAG(csp, choice, csp::tags::ChoiceTag)
00276 EXPORT_COMPILE_TIME_TAG(csp, when, csp::tags::ChoiceTag)
00277 EXPORT_COMPILE_TIME_TAG(csp, otherwise, csp::tags::ChoiceTag)
00278 EXPORT_COMPILE_TIME_TAG(csp, switch, csp::tags::SwitchTag)
00279 EXPORT_COMPILE_TIME_TAG(csp, case, csp::tags::SwitchTag)
00280 EXPORT_COMPILE_TIME_TAG(csp, default, csp::tags::SwitchTag)