trafficserver-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From bc...@apache.org
Subject [2/2] open sourcing the header rewrite plugin from yahoo
Date Fri, 08 Jun 2012 20:47:20 GMT
http://git-wip-us.apache.org/repos/asf/trafficserver-plugins/blob/e1f38ceb/header_rewrite/regex_helper.cc
----------------------------------------------------------------------
diff --git a/header_rewrite/regex_helper.cc b/header_rewrite/regex_helper.cc
new file mode 100644
index 0000000..578253c
--- /dev/null
+++ b/header_rewrite/regex_helper.cc
@@ -0,0 +1,52 @@
+#include "regex_helper.h"
+
+bool
+regexHelper::setRegexMatch(const std::string& s) 
+{
+
+    const char* errorComp = NULL;
+    const char* errorStudy = NULL;
+    int erroffset;
+
+    regexString = s;
+    regex = pcre_compile(regexString.c_str(), 0, &errorComp, &erroffset, NULL);
+
+    if (regex == NULL) 
+    {
+        return false;
+    }
+    regexExtra = pcre_study(regex, 0, &errorStudy);
+    if ((regexExtra == NULL) && (errorStudy != 0)) 
+    {
+        return false;
+    }
+    if (pcre_fullinfo(regex, regexExtra, PCRE_INFO_CAPTURECOUNT, &regexCcount) != 0)
+        return false;
+    return true;
+  }
+
+const std::string&
+regexHelper::getRegexString() const 
+{
+    return regexString;
+}
+
+int
+regexHelper::getRegexCcount() const 
+{
+    return regexCcount;
+}
+
+int
+regexHelper::regexMatch(const char* str, int len, int ovector[]) const {
+    return pcre_exec(regex,                // the compiled pattern
+          regexExtra,          // Extra data from study (maybe)
+          str,                  // the subject std::string
+          len,                  // the length of the subject
+          0,                    // start at offset 0 in the subject
+          0,                    // default options
+          ovector,              // output vector for substring information
+          OVECCOUNT);           // number of elements in the output vector
+  };
+
+

http://git-wip-us.apache.org/repos/asf/trafficserver-plugins/blob/e1f38ceb/header_rewrite/regex_helper.h
----------------------------------------------------------------------
diff --git a/header_rewrite/regex_helper.h b/header_rewrite/regex_helper.h
new file mode 100644
index 0000000..6b43c31
--- /dev/null
+++ b/header_rewrite/regex_helper.h
@@ -0,0 +1,44 @@
+#ifndef REGEX_HELPER_H
+#define REGEX_HELPER_H
+
+#include <pcre.h>
+
+#include <string>
+
+
+const int OVECCOUNT = 30; // We support $1 - $9 only, and this needs to be 3x that
+
+class regexHelper{
+public:
+    regexHelper():
+        regex(NULL),regexExtra(NULL),regexCcount(0)
+    {
+    
+    }
+
+  ~regexHelper() 
+  {
+      if (regex)
+          pcre_free(regex);
+
+      if (regexExtra)
+          pcre_free(regexExtra);
+  }
+
+
+
+bool setRegexMatch(const std::string &s);
+const std::string& getRegexString() const;
+int getRegexCcount() const;
+int regexMatch(const char*,int,int ovector[]) const;
+
+private:
+  pcre* regex;
+  pcre_extra* regexExtra;
+  std::string regexString;
+  int regexCcount;
+
+};
+
+
+#endif

http://git-wip-us.apache.org/repos/asf/trafficserver-plugins/blob/e1f38ceb/header_rewrite/resources.cc
----------------------------------------------------------------------
diff --git a/header_rewrite/resources.cc b/header_rewrite/resources.cc
new file mode 100644
index 0000000..1e1233e
--- /dev/null
+++ b/header_rewrite/resources.cc
@@ -0,0 +1,110 @@
+//////////////////////////////////////////////////////////////////////////////////////////////
+// resources.cc: Implementation of the resources class.
+//
+//
+
+#define UNUSED __attribute__ ((unused))
+static char UNUSED rcsId__resources_cc[] = "@(#) $Id$ built on " __DATE__ " " __TIME__;
+
+#include <ts/ts.h>
+
+#include "resources.h"
+#include "lulu.h"
+
+void
+Resources::gather(const ResourceIDs ids, TSHttpHookID hook)
+{
+  TSDebug(PLUGIN_NAME, "Building resource structure for hook (%d)", hook);
+
+  // If we need the client request headers, make sure it's also available in the client vars.
+  if (ids & RSRC_CLIENT_REQUEST_HEADERS) {
+    TSDebug(PLUGIN_NAME, "\tAdding TXN client request header buffers");
+    if (TSHttpTxnClientReqGet(txnp, &client_bufp, &client_hdr_loc) != TS_SUCCESS)
{
+      TSDebug(PLUGIN_NAME, "could not gather bufp/hdr_loc for request");
+      return;
+    }
+  }
+
+  switch (hook) {
+  case TS_HTTP_READ_RESPONSE_HDR_HOOK:
+    // Read response headers from server
+    if (ids & RSRC_SERVER_RESPONSE_HEADERS) {
+      TSDebug(PLUGIN_NAME, "\tAdding TXN server response header buffers");
+      if (TSHttpTxnServerRespGet(txnp, &bufp, &hdr_loc) != TS_SUCCESS) {
+        TSDebug(PLUGIN_NAME, "could not gather bufp/hdr_loc for response");
+        return;
+      }
+    }
+    if (ids & RSRC_RESPONSE_STATUS) {
+      TSDebug(PLUGIN_NAME, "\tAdding TXN server response status resource");
+      resp_status = TSHttpHdrStatusGet(bufp, hdr_loc);
+    }
+    break;
+
+  case TS_HTTP_SEND_REQUEST_HDR_HOOK:
+    // Read request headers to server
+    if (ids & RSRC_SERVER_REQUEST_HEADERS) {
+      TSDebug(PLUGIN_NAME, "\tAdding TXN server request header buffers");
+      if (!TSHttpTxnServerReqGet(txnp, &bufp, &hdr_loc)) {
+        TSDebug(PLUGIN_NAME, "could not gather bufp/hdr_loc for request");
+        return;
+      }
+    }
+    break;
+
+  case TS_HTTP_READ_REQUEST_HDR_HOOK:
+  case TS_HTTP_READ_REQUEST_PRE_REMAP_HOOK:
+    // Read request from client
+    if (ids & RSRC_CLIENT_REQUEST_HEADERS) {
+      bufp = client_bufp;
+      hdr_loc = client_hdr_loc;
+    }
+    break;
+
+  case TS_HTTP_SEND_RESPONSE_HDR_HOOK:
+    // Send response headers to client
+    if (ids & RSRC_CLIENT_RESPONSE_HEADERS) {
+      TSDebug(PLUGIN_NAME, "\tAdding TXN client response header buffers");
+      if (TSHttpTxnClientRespGet(txnp, &bufp, &hdr_loc) != TS_SUCCESS) {
+        TSDebug(PLUGIN_NAME, "could not gather bufp/hdr_loc for request");
+        return;
+      }
+      if (ids & RSRC_RESPONSE_STATUS) {
+        TSDebug(PLUGIN_NAME, "\tAdding TXN client esponse status resource");
+        resp_status = TSHttpHdrStatusGet(bufp, hdr_loc);
+      }
+    }
+    break;
+
+  case TS_REMAP_PSEUDO_HOOK:
+    // Pseudo-hook for a remap instance
+    if (client_bufp && client_hdr_loc) {
+      TSDebug(PLUGIN_NAME, "\tAdding TXN client request header buffers for remap instance");
+      bufp = client_bufp;
+      hdr_loc = client_hdr_loc;
+    }
+    break;
+    
+    
+  default:
+    break;
+  }
+
+    _ready  = true;
+}
+
+void
+Resources::destroy()
+{
+  if (bufp) {
+    if (hdr_loc)
+      TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
+  }
+
+  if (client_bufp && (client_bufp != bufp)) {
+    if (client_hdr_loc && (client_hdr_loc != hdr_loc)) // TODO: Is this check really
necessary?
+      TSHandleMLocRelease(client_bufp, TS_NULL_MLOC, client_hdr_loc);
+  }
+
+  _ready = false;
+}

http://git-wip-us.apache.org/repos/asf/trafficserver-plugins/blob/e1f38ceb/header_rewrite/resources.h
----------------------------------------------------------------------
diff --git a/header_rewrite/resources.h b/header_rewrite/resources.h
new file mode 100644
index 0000000..db29170
--- /dev/null
+++ b/header_rewrite/resources.h
@@ -0,0 +1,75 @@
+//////////////////////////////////////////////////////////////////////////////////////////////
+// 
+// Implement the classes for the various types of hash keys we support.
+//
+#ifndef __RESOURCES_H__
+#define __RESOURCES_H__ 1
+
+
+#define UNUSED __attribute__ ((unused))
+static char UNUSED rcsId__resources_h[] = "@(#) $Id$ built on " __DATE__ " " __TIME__;
+
+#include <string>
+#include <ts/ts.h>
+#include <ts/remap.h>
+
+#include "lulu.h"
+
+
+#define TS_REMAP_PSEUDO_HOOK TS_HTTP_LAST_HOOK // Ugly, but use the "last hook" for remap
instances.
+
+enum ResourceIDs {
+  RSRC_NONE = 0,
+  RSRC_SERVER_RESPONSE_HEADERS = 1,
+  RSRC_SERVER_REQUEST_HEADERS = 2,
+  RSRC_CLIENT_REQUEST_HEADERS = 4,
+  RSRC_CLIENT_RESPONSE_HEADERS = 8,
+  RSRC_RESPONSE_STATUS = 16,
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Resources holds the minimum resources required to process a request.
+//
+class Resources
+{
+public:
+  explicit Resources(TSHttpTxn txnptr, TSCont contptr)
+    : txnp(txnptr), contp(contptr), bufp(NULL), hdr_loc(NULL), client_bufp(NULL), client_hdr_loc(NULL),
+      resp_status(TS_HTTP_STATUS_NONE), _rri(NULL), changed_url(false), _ready(false)
+  {
+    TSDebug(PLUGIN_NAME_DBG, "Calling CTOR for Resources (InkAPI)");
+  }
+
+  Resources(TSHttpTxn txnptr, TSRemapRequestInfo *rri) :
+    txnp(txnptr), contp(NULL),
+    bufp(NULL), hdr_loc(NULL), client_bufp(NULL), client_hdr_loc(NULL), resp_status(TS_HTTP_STATUS_NONE),
+    _rri(rri), _ready(false)
+  {
+    TSDebug(PLUGIN_NAME_DBG, "Calling CTOR for Resources (RemapAPI)");
+  }
+
+  ~Resources() { destroy(); }
+
+  void gather(const ResourceIDs ids, TSHttpHookID hook);
+  bool ready() const { return _ready; }
+
+  TSHttpTxn txnp;
+  TSCont contp;
+  TSMBuffer bufp;
+  TSMLoc hdr_loc;
+  TSMBuffer client_bufp;
+  TSMLoc client_hdr_loc;
+  TSHttpStatus resp_status;
+  TSRemapRequestInfo *_rri;
+  bool changed_url;
+
+private:
+  void destroy();
+  DISALLOW_COPY_AND_ASSIGN(Resources);
+
+  bool _ready;
+};
+
+
+#endif // __RESOURCES_H

http://git-wip-us.apache.org/repos/asf/trafficserver-plugins/blob/e1f38ceb/header_rewrite/ruleset.cc
----------------------------------------------------------------------
diff --git a/header_rewrite/ruleset.cc b/header_rewrite/ruleset.cc
new file mode 100644
index 0000000..6dce0fb
--- /dev/null
+++ b/header_rewrite/ruleset.cc
@@ -0,0 +1,75 @@
+//////////////////////////////////////////////////////////////////////////////////////////////
+// ruleset.cc: implementation of the ruleset class
+//
+//
+#define UNUSED __attribute__ ((unused))
+static char UNUSED rcsId__ruleset_cc[] = "@(#) $Id$ built on " __DATE__ " " __TIME__;
+
+#include <string>
+
+#include "ruleset.h"
+#include "factory.h"
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Class implementation (no reason to have these inline)
+//
+void
+RuleSet::append(RuleSet* rule) {
+  RuleSet* tmp = this;
+
+  TSReleaseAssert(rule->next == NULL);
+
+  while (tmp->next)
+    tmp = tmp->next;
+  tmp->next = rule;
+}
+
+
+void
+RuleSet::add_condition(Parser& p) {
+  Condition* c = condition_factory(p.get_op());
+
+  if (NULL != c) {
+    TSDebug(PLUGIN_NAME, "Adding condition: %%{%s} with arg: %s\n", p.get_op().c_str(), p.get_arg().c_str());
+    c->initialize(p);
+    if (!c->set_hook(_hook)) {
+      TSError("header_rewrite: can't use this condition in this hook");
+      return;
+    }
+    if (NULL == _cond) {
+      _cond = c;
+    } else {
+      _cond->append(c);
+    }
+
+    // Update some ruleset state based on this new condition
+    _last |= c->last();
+    _ids = static_cast<ResourceIDs>(_ids | _cond->get_resource_ids());
+  }
+}
+
+
+void
+RuleSet::add_operator(Parser& p) {
+  Operator* o = operator_factory(p.get_op());
+
+  if (NULL != o) {
+    // TODO: This should be extended to show both the "argument" and the "value" (if both
are used)
+    TSDebug(PLUGIN_NAME, "Adding operator: %s(%s)\n", p.get_op().c_str(), p.get_arg().c_str());
+    o->initialize(p);
+    if (!o->set_hook(_hook)) {
+      TSError("header_rewrite: can't use this operator in this hook");
+      return;
+    }
+    if (NULL == _oper) {
+      _oper = o;
+    } else {
+      _oper->append(o);
+    }
+
+    // Update some ruleset state based on this new operator
+    _opermods = static_cast<OperModifiers>(_opermods | _oper->get_oper_modifiers());
+    _ids = static_cast<ResourceIDs>(_ids | _oper->get_resource_ids());
+  }
+}

http://git-wip-us.apache.org/repos/asf/trafficserver-plugins/blob/e1f38ceb/header_rewrite/ruleset.h
----------------------------------------------------------------------
diff --git a/header_rewrite/ruleset.h b/header_rewrite/ruleset.h
new file mode 100644
index 0000000..f0e13ad
--- /dev/null
+++ b/header_rewrite/ruleset.h
@@ -0,0 +1,81 @@
+//////////////////////////////////////////////////////////////////////////////////////////////
+// 
+// Implement the classes for the various types of hash keys we support.
+//
+#ifndef __RULESET_H__
+#define __RULESET_H__ 1
+
+
+#define UNUSED __attribute__ ((unused))
+static char UNUSED rcsId__ruleset_h[] = "@(#) $Id$ built on " __DATE__ " " __TIME__;
+
+#include <string>
+
+#include "matcher.h"
+#include "factory.h"
+#include "resources.h"
+#include "parser.h"
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Class holding one ruleset. A ruleset is one (or more) pre-conditions, and
+// one (or more) operators.
+//
+class RuleSet
+{
+public:
+  RuleSet()
+    : next(NULL), _cond(NULL), _oper(NULL), _hook(TS_HTTP_READ_RESPONSE_HDR_HOOK), _ids(RSRC_NONE),
+      _opermods(OPER_NONE), _last(false)
+  { };
+
+  // No reason to inline these
+  void append(RuleSet* rule);
+
+  void add_condition(Parser& p);
+  void add_operator(Parser& p);
+  bool has_operator() const { return NULL != _oper; }
+  bool has_condition() const { return NULL != _cond; }
+
+  void set_hook(TSHttpHookID hook) { _hook = hook; }
+  const TSHttpHookID get_hook() const { return _hook; }
+
+  // Inline
+  const ResourceIDs get_all_resource_ids() const {
+    return _ids;
+  }
+
+  bool eval(const Resources& res) const {
+    if (NULL == _cond) {
+      return true;
+    } else {
+      return _cond->do_eval(res);
+    }
+  }
+
+  bool last() const {
+    return _last;
+  }
+
+  OperModifiers exec(const Resources& res) const {
+    _oper->do_exec(res);
+    return _opermods;
+  }
+
+  RuleSet* next; // Linked list
+
+private:
+  DISALLOW_COPY_AND_ASSIGN(RuleSet);
+
+  Condition* _cond; // First pre-condition (linked list)
+  Operator* _oper; // First operator (linked list)
+  TSHttpHookID _hook; // Which hook is this rule for
+
+  // State values (updated when conds / operators are added)
+  ResourceIDs _ids;
+  OperModifiers _opermods;
+  bool _last;
+};
+
+
+#endif // __RULESET_H

http://git-wip-us.apache.org/repos/asf/trafficserver-plugins/blob/e1f38ceb/header_rewrite/statement.cc
----------------------------------------------------------------------
diff --git a/header_rewrite/statement.cc b/header_rewrite/statement.cc
new file mode 100644
index 0000000..918c910
--- /dev/null
+++ b/header_rewrite/statement.cc
@@ -0,0 +1,84 @@
+//////////////////////////////////////////////////////////////////////////////////////////////
+// statement.cc: Implementation of the statement base class.
+//
+//
+
+#define UNUSED __attribute__ ((unused))
+static char UNUSED rcsId__statement_cc[] = "@(#) $Id$ built on " __DATE__ " " __TIME__;
+
+#include <ts/ts.h>
+
+#include "statement.h"
+
+void
+Statement::append(Statement* stmt)
+{
+  Statement* tmp = this;
+
+  TSReleaseAssert(stmt->_next == NULL);
+  while (tmp->_next)
+    tmp = tmp->_next;
+  tmp->_next = stmt;
+}
+
+
+const ResourceIDs
+Statement::get_resource_ids() const
+{
+  const Statement* stmt = this;
+  ResourceIDs ids = RSRC_NONE;
+
+  while (stmt) {
+    ids = static_cast<ResourceIDs>(ids | stmt->_rsrc);
+    stmt = stmt->_next;
+  }
+
+  return ids;
+}
+
+
+bool
+Statement::set_hook(TSHttpHookID hook) {
+  bool ret = std::find(_allowed_hooks.begin(), _allowed_hooks.end(), hook) != _allowed_hooks.end();
+
+  if (ret)
+    _hook = hook;
+
+  return ret;
+}
+
+
+// This should be overridden for any Statement which only supports some hooks
+void
+Statement::initialize_hooks() {
+  add_allowed_hook(TS_HTTP_READ_RESPONSE_HDR_HOOK);
+  add_allowed_hook(TS_HTTP_READ_REQUEST_PRE_REMAP_HOOK);
+  add_allowed_hook(TS_HTTP_READ_REQUEST_HDR_HOOK);
+  add_allowed_hook(TS_HTTP_SEND_REQUEST_HDR_HOOK);
+  add_allowed_hook(TS_HTTP_SEND_RESPONSE_HDR_HOOK);
+  add_allowed_hook(TS_REMAP_PSEUDO_HOOK);
+}
+
+
+// Parse URL qualifiers
+UrlQualifiers
+Statement::parse_url_qualifier(const std::string& q) {
+  UrlQualifiers qual = URL_QUAL_NONE;
+
+  if (q == "HOST")
+    qual = URL_QUAL_HOST;
+  else if (q == "PORT")
+    qual = URL_QUAL_PORT;
+  else if (q == "PATH")
+    qual = URL_QUAL_PATH;
+  else if (q == "QUERY")
+    qual = URL_QUAL_QUERY;
+  else if (q == "MATRIX")
+    qual = URL_QUAL_MATRIX;
+  else if (q == "SCHEME")
+    qual = URL_QUAL_SCHEME;
+  else if (q == "URL")
+    qual = URL_QUAL_URL;
+
+  return qual;
+}

http://git-wip-us.apache.org/repos/asf/trafficserver-plugins/blob/e1f38ceb/header_rewrite/statement.h
----------------------------------------------------------------------
diff --git a/header_rewrite/statement.h b/header_rewrite/statement.h
new file mode 100644
index 0000000..e42149b
--- /dev/null
+++ b/header_rewrite/statement.h
@@ -0,0 +1,92 @@
+//////////////////////////////////////////////////////////////////////////////////////////////
+// 
+// Base class for all Conditions and Operations. We share the "linked" list, and the
+// resource management / requirements.
+//
+#ifndef __STATEMENT_H__
+#define __STATEMENT_H__ 1
+
+#define UNUSED __attribute__ ((unused))
+static char UNUSED rcsId__statement_h[] = "@(#) $Id$ built on " __DATE__ " " __TIME__;
+
+#include <string>
+#include <vector>
+#include <ts/ts.h>
+
+#include "resources.h"
+#include "parser.h"
+#include "lulu.h"
+
+
+// URL data (both client and server)
+enum UrlQualifiers {
+  URL_QUAL_NONE,
+  URL_QUAL_HOST,
+  URL_QUAL_PORT,
+  URL_QUAL_PATH,
+  URL_QUAL_QUERY,
+  URL_QUAL_MATRIX,
+  URL_QUAL_SCHEME,
+  URL_QUAL_URL
+};
+
+
+class Statement
+{
+ public:
+  Statement()
+    : _next(NULL), _pdata(NULL), _rsrc(RSRC_NONE), _initialized(false), _hook(TS_HTTP_READ_RESPONSE_HDR_HOOK)
+  {
+    TSDebug(PLUGIN_NAME_DBG, "Calling CTOR for Statement");
+  }
+
+  virtual ~Statement() {
+    TSDebug(PLUGIN_NAME_DBG, "Calling DTOR for Statement");
+    free_pdata();
+  }
+
+  // Private data
+  void set_pdata(void* pdata) { _pdata = pdata; }
+  void* get_pdata() const { return(_pdata); }
+  virtual void free_pdata() { TSfree(_pdata); _pdata = NULL; }
+
+  // Which hook are we adding this statement to?
+  bool set_hook(TSHttpHookID hook);
+  const TSHttpHookID get_hook() const { return _hook; }
+
+  // Which hooks are this "statement" applicable for? Used during parsing only.
+  void add_allowed_hook(const TSHttpHookID hook) { _allowed_hooks.push_back(hook); }
+
+  // Linked list.
+  void append(Statement* stmt);
+
+  const ResourceIDs get_resource_ids() const;
+
+  virtual void initialize(Parser& p) {
+    TSReleaseAssert(_initialized == false);
+    initialize_hooks();
+    _initialized = true;
+  }
+  bool initialized() const { return _initialized; }
+
+ protected:
+  virtual void initialize_hooks();
+
+  UrlQualifiers parse_url_qualifier(const std::string& q);
+  void require_resources(const ResourceIDs ids) { _rsrc = static_cast<ResourceIDs>(_rsrc
| ids); }
+
+  Statement* _next; // Linked list
+
+private:
+  DISALLOW_COPY_AND_ASSIGN(Statement);
+
+  void* _pdata;
+  ResourceIDs _rsrc;
+  bool _initialized;
+  std::vector<TSHttpHookID> _allowed_hooks;
+  TSHttpHookID _hook;
+};
+
+
+#endif // __STATEMENT_H
+

http://git-wip-us.apache.org/repos/asf/trafficserver-plugins/blob/e1f38ceb/header_rewrite/value.h
----------------------------------------------------------------------
diff --git a/header_rewrite/value.h b/header_rewrite/value.h
new file mode 100644
index 0000000..81d7792
--- /dev/null
+++ b/header_rewrite/value.h
@@ -0,0 +1,74 @@
+//////////////////////////////////////////////////////////////////////////////////////////////
+// Public interface for creating all values.
+// 
+//
+#ifndef __VALUE_H__
+#define __VALUE_H__ 1
+
+#define UNUSED __attribute__ ((unused))
+static char UNUSED rcsId__value_h[] = "@(#) $Id$ built on " __DATE__ " " __TIME__;
+
+#include <string>
+#include <ts/ts.h>
+
+#include "resources.h"
+#include "statement.h"
+#include "condition.h"
+#include "factory.h"
+#include "parser.h"
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Base class for all Values (this is also the interface).
+//
+// TODO: This is very incomplete, we need to support linked lists of these,
+// which evaluate each component and create a "joined" final string.
+//
+class Value : Statement
+{
+public:
+  Value()
+    : _value(""), _int_value(-1), _cond_val(NULL)
+  {
+    TSDebug(PLUGIN_NAME_DBG, "Calling CTOR for Value");
+  };
+
+  void
+  set_value(const std::string& val)
+  {
+    _value = val;
+    if (_value.substr(0,2) == "%{") {
+      Parser parser(_value);
+
+      _cond_val = condition_factory(parser.get_op());
+      if (_cond_val) {
+        _cond_val->initialize(parser);
+      }
+    }
+    _int_value = strtol(_value.c_str(), NULL, 10);
+  }
+
+  void
+  append_value(std::string& s, const Resources& res) const {
+    if (_cond_val) {
+      _cond_val->append_value(s, res);
+    } else {
+      s += _value;
+    }
+  }
+
+  const std::string& get_value() const { return _value; }
+  int get_int_value() const { return _int_value; }
+
+  bool empty() const { return _value.empty(); }
+
+private:
+  DISALLOW_COPY_AND_ASSIGN(Value);
+
+  std::string _value;
+  int _int_value;
+  Condition* _cond_val;
+};
+
+
+#endif // __VALUE_H


Mime
View raw message