~ubuntu-branches/ubuntu/precise/grantlee/precise

« back to all changes in this revision

Viewing changes to defaulttags/if.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Harald Sitter
  • Date: 2010-06-11 23:41:45 UTC
  • Revision ID: james.westby@ubuntu.com-20100611234145-oas7rhdrbwy8j55c
Tags: upstream-0.1.1
ImportĀ upstreamĀ versionĀ 0.1.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
  This file is part of the Grantlee template system.
 
3
 
 
4
  Copyright (c) 2009,2010 Stephen Kelly <steveire@gmail.com>
 
5
 
 
6
  This library is free software; you can redistribute it and/or
 
7
  modify it under the terms of the GNU Lesser General Public
 
8
  License as published by the Free Software Foundation; either version
 
9
  2 of the Licence, or (at your option) any later version.
 
10
 
 
11
  This library is distributed in the hope that it will be useful,
 
12
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
14
  Library General Public License for more details.
 
15
 
 
16
  You should have received a copy of the GNU Lesser General Public
 
17
  License along with this library.  If not, see <http://www.gnu.org/licenses/>.
 
18
 
 
19
*/
 
20
 
 
21
#include "if.h"
 
22
 
 
23
#include <QtCore/QStringList>
 
24
 
 
25
#include "parser.h"
 
26
#include "exception.h"
 
27
 
 
28
 
 
29
IfNodeFactory::IfNodeFactory()
 
30
{
 
31
 
 
32
}
 
33
 
 
34
 
 
35
Node* IfNodeFactory::getNode( const QString &tagContent, Parser *p ) const
 
36
{
 
37
  QStringList expr = smartSplit( tagContent );
 
38
  expr.takeAt( 0 );
 
39
  if ( expr.size() <= 0 ) {
 
40
    throw Grantlee::Exception( TagSyntaxError, "'if' statement requires at least one argument" );
 
41
  }
 
42
 
 
43
  int linkType = IfNode::OrLink;
 
44
 
 
45
  QString exprString = expr.join( QChar( ' ' ) );
 
46
 
 
47
  QStringList boolPairs = exprString.split( " and " );
 
48
 
 
49
  if ( boolPairs.size() == 1 ) {
 
50
    boolPairs = exprString.split( " or " );
 
51
  } else {
 
52
    linkType = IfNode::AndLink;
 
53
    if ( exprString.contains( " or " ) ) {
 
54
      throw Grantlee::Exception( TagSyntaxError, "'if' tags can't mix 'and' and 'or'" );
 
55
    }
 
56
  }
 
57
 
 
58
  QList<QPair<bool, FilterExpression > > boolVars;
 
59
  Q_FOREACH( const QString &boolStr, boolPairs ) {
 
60
    QPair<bool, FilterExpression> pair;
 
61
    if ( boolStr.contains( ' ' ) ) {
 
62
      QStringList bits = boolStr.split( ' ' );
 
63
      if ( bits.size() != 2 ) {
 
64
        throw Grantlee::Exception( TagSyntaxError, "'if' statement improperly formatted" );
 
65
      }
 
66
      if ( bits.at( 0 ) != "not" ) {
 
67
        throw Grantlee::Exception( TagSyntaxError, "Expected 'not' in if statement" );
 
68
      }
 
69
      pair.first = true;
 
70
      pair.second = FilterExpression( bits.at( 1 ).trimmed(), p );
 
71
    } else {
 
72
      pair.first = false;
 
73
      pair.second = FilterExpression( boolStr.trimmed(), p );
 
74
    }
 
75
    boolVars.append( pair );
 
76
  }
 
77
 
 
78
  IfNode *n = new IfNode( boolVars, linkType, p );
 
79
 
 
80
  NodeList trueList = p->parse( n, QStringList() << "else" << "endif" );
 
81
  n->setTrueList( trueList );
 
82
  NodeList falseList;
 
83
  if ( p->takeNextToken().content.trimmed() == "else" ) {
 
84
    falseList = p->parse( n, QStringList() << "endif" );
 
85
    n->setFalseList( falseList );
 
86
    // skip past the endif tag
 
87
    p->removeNextToken();
 
88
  } // else empty falseList.
 
89
 
 
90
  return n;
 
91
}
 
92
 
 
93
 
 
94
IfNode::IfNode( QList<QPair<bool, FilterExpression > > boolVars, int linkType, QObject *parent )
 
95
    : Node( parent ),
 
96
    m_boolVars( boolVars ),
 
97
    m_linkType( linkType )
 
98
{
 
99
 
 
100
}
 
101
 
 
102
void IfNode::setTrueList( NodeList trueList )
 
103
{
 
104
  m_trueList = trueList;
 
105
}
 
106
 
 
107
void IfNode::setFalseList( NodeList falseList )
 
108
{
 
109
  m_falseList = falseList;
 
110
}
 
111
 
 
112
void IfNode::render( OutputStream *stream, Context *c )
 
113
{
 
114
  // Evaluate the expression. rendering variables with the context as needed. and processing nodes recursively
 
115
  // in either trueList or falseList as determined by booleanExpression.
 
116
 
 
117
  if ( m_linkType == OrLink ) {
 
118
    for ( int i = 0; i < m_boolVars.size(); i++ ) {
 
119
      QPair<bool, FilterExpression> pair = m_boolVars.at( i );
 
120
      bool negate = pair.first;
 
121
 
 
122
      bool isTrue = pair.second.isTrue( c );
 
123
 
 
124
      if ( isTrue != negate ) {
 
125
        renderTrueList( stream, c );
 
126
        return;
 
127
      }
 
128
    }
 
129
//     return renderFalseList(c);
 
130
  } else {
 
131
    bool renderTrue = true;
 
132
    for ( int i = 0; i < m_boolVars.size(); i++ ) {
 
133
      QPair<bool, FilterExpression> pair = m_boolVars.at( i );
 
134
      bool negate = pair.first;
 
135
 
 
136
      bool isTrue = pair.second.isTrue( c );
 
137
 
 
138
      // Karnaugh map:
 
139
      //          VariantIsTrue
 
140
      //          \ 0   1
 
141
      //         0| 0 | 1 |
 
142
      // negate  1| 1 | 0 |
 
143
 
 
144
      if (( !isTrue && !negate )
 
145
          || ( isTrue && negate ) ) {
 
146
        renderTrue = false;
 
147
        break;
 
148
      }
 
149
    }
 
150
    if ( renderTrue ) {
 
151
      renderTrueList( stream, c );
 
152
      return;
 
153
    }
 
154
  }
 
155
 
 
156
  renderFalseList( stream, c );
 
157
}
 
158
 
 
159
void IfNode::renderTrueList( OutputStream *stream, Context *c )
 
160
{
 
161
  return m_trueList.render( stream, c );
 
162
}
 
163
 
 
164
void IfNode::renderFalseList( OutputStream *stream, Context *c )
 
165
{
 
166
  return m_falseList.render( stream, c );
 
167
}
 
168