[info] splits InfoSingle/Expression out from InfoBool.h
authorJonathan Marshall <jmarshall@xbmc.org>
Fri, 22 Nov 2013 23:20:43 +0000 (12:20 +1300)
committerJonathan Marshall <jmarshall@xbmc.org>
Fri, 6 Dec 2013 19:35:15 +0000 (08:35 +1300)
XBMC.xcodeproj/project.pbxproj
project/VS2010Express/XBMC.vcxproj
project/VS2010Express/XBMC.vcxproj.filters
xbmc/GUIInfoManager.cpp
xbmc/interfaces/info/InfoBool.cpp [deleted file]
xbmc/interfaces/info/InfoBool.h
xbmc/interfaces/info/InfoExpression.cpp [new file with mode: 0644]
xbmc/interfaces/info/InfoExpression.h [new file with mode: 0644]
xbmc/interfaces/info/Makefile

index 58581da..1c56587 100644 (file)
                7C1409A4183224B8009F9411 /* SettingUpdate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C140987183224B8009F9411 /* SettingUpdate.cpp */; };
                7C1409A5183224B8009F9411 /* SettingUpdate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C140987183224B8009F9411 /* SettingUpdate.cpp */; };
                7C1409A6183224B8009F9411 /* SettingUpdate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C140987183224B8009F9411 /* SettingUpdate.cpp */; };
+               7C1409A9184015C9009F9411 /* InfoExpression.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C1409A7184015C6009F9411 /* InfoExpression.cpp */; };
+               7C1409AA184015C9009F9411 /* InfoExpression.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C1409A7184015C6009F9411 /* InfoExpression.cpp */; };
+               7C1409AB184015C9009F9411 /* InfoExpression.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C1409A7184015C6009F9411 /* InfoExpression.cpp */; };
                7C1A492315A962EE004AF4A4 /* SeekHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C1A492115A962EE004AF4A4 /* SeekHandler.cpp */; };
                7C1A85661520522500C63311 /* TextureCacheJob.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C1A85631520522500C63311 /* TextureCacheJob.cpp */; };
                7C1D682915A7D2FD00658B65 /* DatabaseManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C1D682715A7D2FD00658B65 /* DatabaseManager.cpp */; };
                7C84A59E12FA3C1600CD1714 /* SourcesDirectory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C84A59C12FA3C1600CD1714 /* SourcesDirectory.cpp */; };
                7C87B2CE162CE39600EF897D /* PlayerController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C87B2CC162CE39600EF897D /* PlayerController.cpp */; };
                7C89619213B6A16F003631FE /* GUIWindowScreensaverDim.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C89619013B6A16F003631FE /* GUIWindowScreensaverDim.cpp */; };
-               7C89674613C03B22003631FE /* InfoBool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C89674313C03B22003631FE /* InfoBool.cpp */; };
                7C8A14571154CB2600E5FCFA /* TextureCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C8A14541154CB2600E5FCFA /* TextureCache.cpp */; };
                7C8A187D115B2A8200E5FCFA /* TextureDatabase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C8A187A115B2A8200E5FCFA /* TextureDatabase.cpp */; };
                7C8FC6EE1829A4580045153D /* DirectoryProvider.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C8FC6EC1829A4580045153D /* DirectoryProvider.cpp */; };
                DFF0F2C817528350002DA3A4 /* XBTFReader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 18B7C7A81294222E009E7A26 /* XBTFReader.cpp */; };
                DFF0F2C917528350002DA3A4 /* GenericTouchActionHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4991334174E5E5C00741B6D /* GenericTouchActionHandler.cpp */; };
                DFF0F2CA17528350002DA3A4 /* ITouchInputHandling.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4991342174E5E5C00741B6D /* ITouchInputHandling.cpp */; };
-               DFF0F2CB17528350002DA3A4 /* InfoBool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C89674313C03B22003631FE /* InfoBool.cpp */; };
                DFF0F2CC17528350002DA3A4 /* SkinVariable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF98D98A1434F47D00A6EBE1 /* SkinVariable.cpp */; };
                DFF0F2CD17528350002DA3A4 /* AddonsOperations.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFB0F470161B747500D744F4 /* AddonsOperations.cpp */; };
                DFF0F2CE17528350002DA3A4 /* ApplicationOperations.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 18968DC614155D7C005BA742 /* ApplicationOperations.cpp */; };
                E4991331174E5DAD00741B6D /* XBTFReader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 18B7C7A81294222E009E7A26 /* XBTFReader.cpp */; };
                E4991345174E5E5C00741B6D /* GenericTouchActionHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4991334174E5E5C00741B6D /* GenericTouchActionHandler.cpp */; };
                E499134B174E5E5C00741B6D /* ITouchInputHandling.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4991342174E5E5C00741B6D /* ITouchInputHandling.cpp */; };
-               E499134C174E5EB700741B6D /* InfoBool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C89674313C03B22003631FE /* InfoBool.cpp */; };
                E499134D174E5EB700741B6D /* SkinVariable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF98D98A1434F47D00A6EBE1 /* SkinVariable.cpp */; };
                E499134E174E5EBE00741B6D /* AddonsOperations.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFB0F470161B747500D744F4 /* AddonsOperations.cpp */; };
                E499134F174E5EBE00741B6D /* ApplicationOperations.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 18968DC614155D7C005BA742 /* ApplicationOperations.cpp */; };
                7C140986183224B8009F9411 /* SettingsManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SettingsManager.h; path = lib/SettingsManager.h; sourceTree = "<group>"; };
                7C140987183224B8009F9411 /* SettingUpdate.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SettingUpdate.cpp; path = lib/SettingUpdate.cpp; sourceTree = "<group>"; };
                7C140988183224B8009F9411 /* SettingUpdate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SettingUpdate.h; path = lib/SettingUpdate.h; sourceTree = "<group>"; };
+               7C1409A7184015C6009F9411 /* InfoExpression.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InfoExpression.cpp; sourceTree = "<group>"; };
+               7C1409A8184015C8009F9411 /* InfoExpression.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InfoExpression.h; sourceTree = "<group>"; };
                7C1A492115A962EE004AF4A4 /* SeekHandler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SeekHandler.cpp; sourceTree = "<group>"; };
                7C1A492215A962EE004AF4A4 /* SeekHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SeekHandler.h; sourceTree = "<group>"; };
                7C1A495B15A96918004AF4A4 /* SaveFileStateJob.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SaveFileStateJob.h; sourceTree = "<group>"; };
                7C87B2CD162CE39600EF897D /* PlayerController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlayerController.h; sourceTree = "<group>"; };
                7C89619013B6A16F003631FE /* GUIWindowScreensaverDim.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GUIWindowScreensaverDim.cpp; sourceTree = "<group>"; };
                7C89619113B6A16F003631FE /* GUIWindowScreensaverDim.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GUIWindowScreensaverDim.h; sourceTree = "<group>"; };
-               7C89674313C03B22003631FE /* InfoBool.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InfoBool.cpp; sourceTree = "<group>"; };
                7C89674413C03B22003631FE /* InfoBool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InfoBool.h; sourceTree = "<group>"; };
                7C8A14541154CB2600E5FCFA /* TextureCache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TextureCache.cpp; sourceTree = "<group>"; };
                7C8A14551154CB2600E5FCFA /* TextureCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextureCache.h; sourceTree = "<group>"; };
                7C89674213C03B21003631FE /* info */ = {
                        isa = PBXGroup;
                        children = (
-                               7C89674313C03B22003631FE /* InfoBool.cpp */,
                                7C89674413C03B22003631FE /* InfoBool.h */,
+                               7C1409A7184015C6009F9411 /* InfoExpression.cpp */,
+                               7C1409A8184015C8009F9411 /* InfoExpression.h */,
                                DF98D98A1434F47D00A6EBE1 /* SkinVariable.cpp */,
                                DF98D98B1434F47D00A6EBE1 /* SkinVariable.h */,
                        );
                                38F4E57013CCCB3B00664821 /* Implementation.cpp in Sources */,
                                3802709A13D5A653009493DD /* SystemClock.cpp in Sources */,
                                7CEE2E5B13D6B71E000ABF2A /* TimeSmoother.cpp in Sources */,
-                               7C89674613C03B22003631FE /* InfoBool.cpp in Sources */,
                                DFAB049813F8376700B70BFB /* InertialScrollingHandler.cpp in Sources */,
                                DF3488E713FD958F0026A711 /* GUIAction.cpp in Sources */,
                                DF34892A13FD9C780026A711 /* AirPlayServer.cpp in Sources */,
                                7C1409A1183224B8009F9411 /* SettingsManager.cpp in Sources */,
                                7C1409A4183224B8009F9411 /* SettingUpdate.cpp in Sources */,
                                DF0ABB73183A94A30018445D /* Utf8Utils.cpp in Sources */,
+                               7C1409A9184015C9009F9411 /* InfoExpression.cpp in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                DFF0F2C817528350002DA3A4 /* XBTFReader.cpp in Sources */,
                                DFF0F2C917528350002DA3A4 /* GenericTouchActionHandler.cpp in Sources */,
                                DFF0F2CA17528350002DA3A4 /* ITouchInputHandling.cpp in Sources */,
-                               DFF0F2CB17528350002DA3A4 /* InfoBool.cpp in Sources */,
                                DFF0F2CC17528350002DA3A4 /* SkinVariable.cpp in Sources */,
                                DFF0F2CD17528350002DA3A4 /* AddonsOperations.cpp in Sources */,
                                DFF0F2CE17528350002DA3A4 /* ApplicationOperations.cpp in Sources */,
                                7C1409A3183224B8009F9411 /* SettingsManager.cpp in Sources */,
                                7C1409A6183224B8009F9411 /* SettingUpdate.cpp in Sources */,
                                DF0ABB75183A94A30018445D /* Utf8Utils.cpp in Sources */,
+                               7C1409AB184015C9009F9411 /* InfoExpression.cpp in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                E4991331174E5DAD00741B6D /* XBTFReader.cpp in Sources */,
                                E4991345174E5E5C00741B6D /* GenericTouchActionHandler.cpp in Sources */,
                                E499134B174E5E5C00741B6D /* ITouchInputHandling.cpp in Sources */,
-                               E499134C174E5EB700741B6D /* InfoBool.cpp in Sources */,
                                E499134D174E5EB700741B6D /* SkinVariable.cpp in Sources */,
                                E499134E174E5EBE00741B6D /* AddonsOperations.cpp in Sources */,
                                E499134F174E5EBE00741B6D /* ApplicationOperations.cpp in Sources */,
                                7C1409A2183224B8009F9411 /* SettingsManager.cpp in Sources */,
                                7C1409A5183224B8009F9411 /* SettingUpdate.cpp in Sources */,
                                DF0ABB74183A94A30018445D /* Utf8Utils.cpp in Sources */,
+                               7C1409AA184015C9009F9411 /* InfoExpression.cpp in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
index 96cf3ce..1ab7191 100644 (file)
     <ClCompile Include="..\..\xbmc\interfaces\Builtins.cpp" />
     <ClCompile Include="..\..\xbmc\interfaces\generic\LanguageInvokerThread.cpp" />
     <ClCompile Include="..\..\xbmc\interfaces\generic\ScriptInvocationManager.cpp" />
-    <ClCompile Include="..\..\xbmc\interfaces\info\InfoBool.cpp" />
+    <ClCompile Include="..\..\xbmc\interfaces\info\InfoExpression.cpp" />
     <ClCompile Include="..\..\xbmc\interfaces\info\SkinVariable.cpp" />
     <ClCompile Include="..\..\xbmc\interfaces\json-rpc\AddonsOperations.cpp" />
     <ClCompile Include="..\..\xbmc\interfaces\json-rpc\ApplicationOperations.cpp" />
     <ClInclude Include="..\..\xbmc\interfaces\Builtins.h" />
     <ClInclude Include="..\..\xbmc\interfaces\IAnnouncer.h" />
     <ClInclude Include="..\..\xbmc\interfaces\info\InfoBool.h" />
+    <ClInclude Include="..\..\xbmc\interfaces\info\InfoExpression.h" />
     <ClInclude Include="..\..\xbmc\interfaces\info\SkinVariable.h" />
     <ClInclude Include="..\..\xbmc\interfaces\json-rpc\ApplicationOperations.h" />
     <ClInclude Include="..\..\xbmc\interfaces\json-rpc\AudioLibrary.h" />
     </VisualStudio>
   </ProjectExtensions>
   <Import Project="$(SolutionDir)\$(ProjectFileName).targets.user" Condition="Exists('$(SolutionDir)\$(ProjectFileName).targets.user')" />
-</Project>
\ No newline at end of file
+</Project>
index d35c005..2686e76 100644 (file)
     <ClCompile Include="..\..\xbmc\input\InertialScrollingHandler.cpp">
       <Filter>input</Filter>
     </ClCompile>
-    <ClCompile Include="..\..\xbmc\interfaces\info\InfoBool.cpp">
+    <ClCompile Include="..\..\xbmc\interfaces\info\InfoExpression.cpp">
       <Filter>interfaces\info</Filter>
     </ClCompile>
     <ClCompile Include="..\..\xbmc\guilib\GUIAction.cpp">
     <ClInclude Include="..\..\xbmc\interfaces\info\InfoBool.h">
       <Filter>interfaces\info</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\xbmc\interfaces\info\InfoExpression.h">
+      <Filter>interfaces\info</Filter>
+    </ClInclude>
     <ClInclude Include="..\..\xbmc\guilib\GUIAction.h">
       <Filter>guilib</Filter>
     </ClInclude>
       <Filter>interfaces\swig</Filter>
     </None>
   </ItemGroup>
-</Project>
\ No newline at end of file
+</Project>
index 1f5224d..6b96837 100644 (file)
@@ -85,6 +85,7 @@
 #include "cores/IPlayer.h"
 #include "cores/AudioEngine/Utils/AEUtil.h"
 #include "cores/VideoRenderers/BaseRenderer.h"
+#include "interfaces/info/InfoExpression.h"
 
 #if defined(TARGET_DARWIN_OSX)
 #include "osx/smc.h"
diff --git a/xbmc/interfaces/info/InfoBool.cpp b/xbmc/interfaces/info/InfoBool.cpp
deleted file mode 100644 (file)
index 68da152..0000000
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- *      Copyright (C) 2005-2013 Team XBMC
- *      http://xbmc.org
- *
- *  This Program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2, or (at your option)
- *  any later version.
- *
- *  This Program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with XBMC; see the file COPYING.  If not, see
- *  <http://www.gnu.org/licenses/>.
- *
- */
-
-#include "InfoBool.h"
-#include <stack>
-#include "utils/log.h"
-#include "GUIInfoManager.h"
-
-using namespace std;
-using namespace INFO;
-
-InfoSingle::InfoSingle(const std::string &expression, int context)
-: InfoBool(expression, context)
-{
-  m_condition = g_infoManager.TranslateSingleString(expression);
-}
-
-void InfoSingle::Update(const CGUIListItem *item)
-{
-  m_value = g_infoManager.GetBool(m_condition, m_context, item);
-}
-
-InfoExpression::InfoExpression(const std::string &expression, int context)
-: InfoBool(expression, context)
-{
-  Parse(expression);
-}
-
-void InfoExpression::Update(const CGUIListItem *item)
-{
-  Evaluate(item, m_value);
-}
-
-#define OPERATOR_LB   5
-#define OPERATOR_RB   4
-#define OPERATOR_NOT  3
-#define OPERATOR_AND  2
-#define OPERATOR_OR   1
-
-short InfoExpression::GetOperator(const char ch) const
-{
-  if (ch == '[')
-    return OPERATOR_LB;
-  else if (ch == ']')
-    return OPERATOR_RB;
-  else if (ch == '!')
-    return OPERATOR_NOT;
-  else if (ch == '+')
-    return OPERATOR_AND;
-  else if (ch == '|')
-    return OPERATOR_OR;
-  else
-    return 0;
-}
-
-void InfoExpression::Parse(const std::string &expression)
-{
-  stack<char> operators;
-  std::string operand;
-  for (unsigned int i = 0; i < expression.size(); i++)
-  {
-    if (GetOperator(expression[i]))
-    {
-      // cleanup any operand, translate and put into our expression list
-      if (!operand.empty())
-      {
-        unsigned int info = g_infoManager.Register(operand, m_context);
-        if (info)
-        {
-          m_postfix.push_back(m_operands.size());
-          m_operands.push_back(info);
-        }
-        operand.clear();
-      }
-      // handle closing parenthesis
-      if (expression[i] == ']')
-      {
-        while (!operators.empty())
-        {
-          char oper = operators.top();
-          operators.pop();
-
-          if (oper == '[')
-            break;
-
-          m_postfix.push_back(-GetOperator(oper)); // negative denotes operator
-        }
-      }
-      else
-      {
-        // all other operators we pop off the stack any operator
-        // that has a higher priority than the one we have.
-        while (!operators.empty() && GetOperator(operators.top()) > GetOperator(expression[i]))
-        {
-          // only handle parenthesis once they're closed.
-          if (operators.top() == '[' && expression[i] != ']')
-            break;
-
-          m_postfix.push_back(-GetOperator(operators.top()));  // negative denotes operator
-          operators.pop();
-        }
-        operators.push(expression[i]);
-      }
-    }
-    else
-    {
-      operand += expression[i];
-    }
-  }
-
-  if (!operand.empty())
-  {
-    unsigned int info = g_infoManager.Register(operand, m_context);
-    if (info)
-    {
-      m_postfix.push_back(m_operands.size());
-      m_operands.push_back(info);
-    }
-  }
-
-  // finish up by adding any operators
-  while (!operators.empty())
-  {
-    m_postfix.push_back(-GetOperator(operators.top()));  // negative denotes operator
-    operators.pop();
-  }
-
-  // test evaluate
-  bool test;
-  if (!Evaluate(NULL, test))
-    CLog::Log(LOGERROR, "Error evaluating boolean expression %s", expression.c_str());
-}
-
-bool InfoExpression::Evaluate(const CGUIListItem *item, bool &result)
-{
-  stack<bool> save;
-  for (vector<short>::const_iterator it = m_postfix.begin(); it != m_postfix.end(); ++it)
-  {
-    short expr = *it;
-    if (expr == -OPERATOR_NOT)
-    { // NOT the top item on the stack
-      if (save.empty()) return false;
-      bool expr = save.top();
-      save.pop();
-      save.push(!expr);
-    }
-    else if (expr == -OPERATOR_AND)
-    { // AND the top two items on the stack
-      if (save.size() < 2) return false;
-      bool right = save.top(); save.pop();
-      bool left = save.top(); save.pop();
-      save.push(left && right);
-    }
-    else if (expr == -OPERATOR_OR)
-    { // OR the top two items on the stack
-      if (save.size() < 2) return false;
-      bool right = save.top(); save.pop();
-      bool left = save.top(); save.pop();
-      save.push(left || right);
-    }
-    else  // operand
-      save.push(g_infoManager.GetBoolValue(m_operands[expr], item));
-  }
-  if (save.size() != 1)
-    return false;
-  result = save.top();
-  return true;
-}
-
index 8a5c070..2db59c1 100644 (file)
@@ -20,8 +20,6 @@
 
 #pragma once
 
-#include <vector>
-#include <map>
 #include <string>
 
 class CGUIListItem;
@@ -83,35 +81,4 @@ private:
   unsigned int m_lastUpdate;   ///< last update time (to determine dirty status)
 };
 
-/*! \brief Class to wrap active boolean conditions
- */
-class InfoSingle : public InfoBool
-{
-public:
-  InfoSingle(const std::string &condition, int context);
-  virtual ~InfoSingle() {};
-
-  virtual void Update(const CGUIListItem *item);
-private:
-  int m_condition;             ///< actual condition this represents
-};
-
-/*! \brief Class to wrap active boolean expressions
- */
-class InfoExpression : public InfoBool
-{
-public:
-  InfoExpression(const std::string &expression, int context);
-  virtual ~InfoExpression() {};
-
-  virtual void Update(const CGUIListItem *item);
-private:
-  void Parse(const std::string &expression);
-  bool Evaluate(const CGUIListItem *item, bool &result);
-  short GetOperator(const char ch) const;
-
-  std::vector<short> m_postfix;         ///< the postfix form of the expression (operators and operand indicies)
-  std::vector<unsigned int> m_operands; ///< the operands in the expression
-};
-
 };
diff --git a/xbmc/interfaces/info/InfoExpression.cpp b/xbmc/interfaces/info/InfoExpression.cpp
new file mode 100644 (file)
index 0000000..e252177
--- /dev/null
@@ -0,0 +1,186 @@
+/*
+ *      Copyright (C) 2005-2013 Team XBMC
+ *      http://xbmc.org
+ *
+ *  This Program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *
+ *  This Program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with XBMC; see the file COPYING.  If not, see
+ *  <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "InfoExpression.h"
+#include <stack>
+#include "utils/log.h"
+#include "GUIInfoManager.h"
+
+using namespace std;
+using namespace INFO;
+
+InfoSingle::InfoSingle(const std::string &expression, int context)
+: InfoBool(expression, context)
+{
+  m_condition = g_infoManager.TranslateSingleString(expression);
+}
+
+void InfoSingle::Update(const CGUIListItem *item)
+{
+  m_value = g_infoManager.GetBool(m_condition, m_context, item);
+}
+
+InfoExpression::InfoExpression(const std::string &expression, int context)
+: InfoBool(expression, context)
+{
+  Parse(expression);
+}
+
+void InfoExpression::Update(const CGUIListItem *item)
+{
+  Evaluate(item, m_value);
+}
+
+#define OPERATOR_LB   5
+#define OPERATOR_RB   4
+#define OPERATOR_NOT  3
+#define OPERATOR_AND  2
+#define OPERATOR_OR   1
+
+short InfoExpression::GetOperator(const char ch) const
+{
+  if (ch == '[')
+    return OPERATOR_LB;
+  else if (ch == ']')
+    return OPERATOR_RB;
+  else if (ch == '!')
+    return OPERATOR_NOT;
+  else if (ch == '+')
+    return OPERATOR_AND;
+  else if (ch == '|')
+    return OPERATOR_OR;
+  else
+    return 0;
+}
+
+void InfoExpression::Parse(const std::string &expression)
+{
+  stack<char> operators;
+  std::string operand;
+  for (unsigned int i = 0; i < expression.size(); i++)
+  {
+    if (GetOperator(expression[i]))
+    {
+      // cleanup any operand, translate and put into our expression list
+      if (!operand.empty())
+      {
+        unsigned int info = g_infoManager.Register(operand, m_context);
+        if (info)
+        {
+          m_postfix.push_back(m_operands.size());
+          m_operands.push_back(info);
+        }
+        operand.clear();
+      }
+      // handle closing parenthesis
+      if (expression[i] == ']')
+      {
+        while (!operators.empty())
+        {
+          char oper = operators.top();
+          operators.pop();
+
+          if (oper == '[')
+            break;
+
+          m_postfix.push_back(-GetOperator(oper)); // negative denotes operator
+        }
+      }
+      else
+      {
+        // all other operators we pop off the stack any operator
+        // that has a higher priority than the one we have.
+        while (!operators.empty() && GetOperator(operators.top()) > GetOperator(expression[i]))
+        {
+          // only handle parenthesis once they're closed.
+          if (operators.top() == '[' && expression[i] != ']')
+            break;
+
+          m_postfix.push_back(-GetOperator(operators.top()));  // negative denotes operator
+          operators.pop();
+        }
+        operators.push(expression[i]);
+      }
+    }
+    else
+    {
+      operand += expression[i];
+    }
+  }
+
+  if (!operand.empty())
+  {
+    unsigned int info = g_infoManager.Register(operand, m_context);
+    if (info)
+    {
+      m_postfix.push_back(m_operands.size());
+      m_operands.push_back(info);
+    }
+  }
+
+  // finish up by adding any operators
+  while (!operators.empty())
+  {
+    m_postfix.push_back(-GetOperator(operators.top()));  // negative denotes operator
+    operators.pop();
+  }
+
+  // test evaluate
+  bool test;
+  if (!Evaluate(NULL, test))
+    CLog::Log(LOGERROR, "Error evaluating boolean expression %s", expression.c_str());
+}
+
+bool InfoExpression::Evaluate(const CGUIListItem *item, bool &result)
+{
+  stack<bool> save;
+  for (vector<short>::const_iterator it = m_postfix.begin(); it != m_postfix.end(); ++it)
+  {
+    short expr = *it;
+    if (expr == -OPERATOR_NOT)
+    { // NOT the top item on the stack
+      if (save.empty()) return false;
+      bool expr = save.top();
+      save.pop();
+      save.push(!expr);
+    }
+    else if (expr == -OPERATOR_AND)
+    { // AND the top two items on the stack
+      if (save.size() < 2) return false;
+      bool right = save.top(); save.pop();
+      bool left = save.top(); save.pop();
+      save.push(left && right);
+    }
+    else if (expr == -OPERATOR_OR)
+    { // OR the top two items on the stack
+      if (save.size() < 2) return false;
+      bool right = save.top(); save.pop();
+      bool left = save.top(); save.pop();
+      save.push(left || right);
+    }
+    else  // operand
+      save.push(g_infoManager.GetBoolValue(m_operands[expr], item));
+  }
+  if (save.size() != 1)
+    return false;
+  result = save.top();
+  return true;
+}
+
diff --git a/xbmc/interfaces/info/InfoExpression.h b/xbmc/interfaces/info/InfoExpression.h
new file mode 100644 (file)
index 0000000..90185bd
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ *      Copyright (C) 2005-2013 Team XBMC
+ *      http://xbmc.org
+ *
+ *  This Program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *
+ *  This Program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with XBMC; see the file COPYING.  If not, see
+ *  <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+#include <vector>
+#include "InfoBool.h"
+
+class CGUIListItem;
+
+namespace INFO
+{
+/*! \brief Class to wrap active boolean conditions
+ */
+class InfoSingle : public InfoBool
+{
+public:
+  InfoSingle(const std::string &condition, int context);
+  virtual ~InfoSingle() {};
+
+  virtual void Update(const CGUIListItem *item);
+private:
+  int m_condition;             ///< actual condition this represents
+};
+
+/*! \brief Class to wrap active boolean expressions
+ */
+class InfoExpression : public InfoBool
+{
+public:
+  InfoExpression(const std::string &expression, int context);
+  virtual ~InfoExpression() {};
+
+  virtual void Update(const CGUIListItem *item);
+private:
+  void Parse(const std::string &expression);
+  bool Evaluate(const CGUIListItem *item, bool &result);
+  short GetOperator(const char ch) const;
+
+  std::vector<short> m_postfix;         ///< the postfix form of the expression (operators and operand indicies)
+  std::vector<unsigned int> m_operands; ///< the operands in the expression
+};
+
+};
index a5a18ca..01fdca7 100644 (file)
@@ -1,4 +1,4 @@
-SRCS=InfoBool.cpp \
+SRCS=InfoExpression.cpp \
      SkinVariable.cpp \
      
 LIB=info.a