You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by am...@apache.org on 2010/11/20 16:17:56 UTC

svn commit: r1037235 [1/2] - /trafficserver/traffic/branches/wccp/proxy/tsconfig/

Author: amc
Date: Sat Nov 20 15:17:55 2010
New Revision: 1037235

URL: http://svn.apache.org/viewvc?rev=1037235&view=rev
Log:
Initial commit of TsConfig library.

Added:
    trafficserver/traffic/branches/wccp/proxy/tsconfig/
    trafficserver/traffic/branches/wccp/proxy/tsconfig/Errata.cc
    trafficserver/traffic/branches/wccp/proxy/tsconfig/Errata.h
    trafficserver/traffic/branches/wccp/proxy/tsconfig/IntrusivePtr.h
    trafficserver/traffic/branches/wccp/proxy/tsconfig/Makefile.am
    trafficserver/traffic/branches/wccp/proxy/tsconfig/NumericType.h
    trafficserver/traffic/branches/wccp/proxy/tsconfig/TsBuffer.h
    trafficserver/traffic/branches/wccp/proxy/tsconfig/TsBuilder.cc
    trafficserver/traffic/branches/wccp/proxy/tsconfig/TsBuilder.h
    trafficserver/traffic/branches/wccp/proxy/tsconfig/TsConfig.flex
    trafficserver/traffic/branches/wccp/proxy/tsconfig/TsConfig.y
    trafficserver/traffic/branches/wccp/proxy/tsconfig/TsConfigLexer.h
    trafficserver/traffic/branches/wccp/proxy/tsconfig/TsConfigParseEvents.h
    trafficserver/traffic/branches/wccp/proxy/tsconfig/TsConfigTypes.h
    trafficserver/traffic/branches/wccp/proxy/tsconfig/TsErrataUtil.cc
    trafficserver/traffic/branches/wccp/proxy/tsconfig/TsErrataUtil.h
    trafficserver/traffic/branches/wccp/proxy/tsconfig/TsValue.cc
    trafficserver/traffic/branches/wccp/proxy/tsconfig/TsValue.h

Added: trafficserver/traffic/branches/wccp/proxy/tsconfig/Errata.cc
URL: http://svn.apache.org/viewvc/trafficserver/traffic/branches/wccp/proxy/tsconfig/Errata.cc?rev=1037235&view=auto
==============================================================================
--- trafficserver/traffic/branches/wccp/proxy/tsconfig/Errata.cc (added)
+++ trafficserver/traffic/branches/wccp/proxy/tsconfig/Errata.cc Sat Nov 20 15:17:55 2010
@@ -0,0 +1,283 @@
+/** @file
+    Errata implementation.
+ */
+/*
+ * Copyright 2005-2010 Network Geographics, Inc.
+ * http://www.network-geographics.com
+ * All rights reserved.
+ * Licensed to Apache Software Foundation.
+ */
+
+# include "Errata.h"
+# include <iostream>
+# include <sstream>
+# include <iomanip>
+# include <algorithm>
+# include <memory.h>
+
+namespace ts {
+
+/** List of sinks for abandoned erratum.
+ */
+namespace {
+  std::deque<Errata::Sink::Handle> Sink_List;
+}
+
+std::string const Errata::DEFAULT_GLUE("\n");
+Errata::Message const Errata::NIL_MESSAGE;
+Errata::Code Errata::Message::Default_Code = 0;
+Errata::Message::SuccessTest const Errata::Message::DEFAULT_SUCCESS_TEST =
+  &Errata::Message::isCodeZero;
+Errata::Message::SuccessTest Errata::Message::Success_Test =
+  Errata::Message::DEFAULT_SUCCESS_TEST;
+
+bool
+Errata::Message::isCodeZero(Message const& msg) {
+  return msg.m_code == 0;
+}
+
+void
+Errata::Data::push(Message const& msg) {
+  m_items.push_back(msg);
+}
+
+Errata::Message const&
+Errata::Data::top() const {
+  return m_items.size() ? m_items.back() : NIL_MESSAGE ;
+}
+
+inline Errata::Errata(ImpPtr const& ptr) 
+  : m_data(ptr) {
+}
+
+Errata::Data::~Data() {
+  if (m_log_on_delete) {
+    Errata tmp(this); // because client API requires a wrapper.
+    std::deque<Errata::Sink::Handle>::iterator spot, limit;
+    for ( spot = Sink_List.begin(), limit = Sink_List.end();
+          spot != limit;
+          ++spot
+    ) {
+      (**spot)(tmp);
+    }
+    tmp.m_data.release(); // don't delete this again.
+  }
+}
+
+Errata::Errata() {
+}
+
+Errata::Errata(self const& that)
+  : m_data(that.m_data) {
+}
+
+Errata::Errata(std::string const& text) {
+  this->push(text);
+}
+
+Errata::Errata(Id id, std::string const& text) {
+  this->push(id, text);
+}
+
+Errata::~Errata() {
+}
+
+/*  This forces the errata to have a data object that only it references.
+    If we're sharing the data, clone. If there's no data, allocate.
+    This is used just before a write operation to have copy on write semantics.
+ */
+Errata::Data*
+Errata::pre_write() {
+  if (m_data) {
+    if (m_data.useCount() > 1) {
+      m_data = new Data(*m_data); // clone current data
+    }
+  } else { // create new data
+    m_data = new Data;
+  }
+  return m_data.get();
+}
+
+// Just create an instance if needed.
+Errata::Data*
+Errata::instance() {
+  if (!m_data) m_data = new Data;
+  return m_data.get();
+}
+
+Errata&
+Errata::push(Message const& msg) {
+  this->pre_write()->push(msg);
+  return *this;
+}
+
+Errata&
+Errata::operator=(self const& that) {
+  m_data = that.m_data;
+  return *this;
+}
+
+Errata&
+Errata::operator = (Message const& msg) {
+  // Avoid copy on write in the case where we discard.
+  if (!m_data || m_data.useCount() > 1) {
+    this->clear();
+    this->push(msg);
+  } else {
+    m_data->m_items.clear();
+    m_data->push(msg);
+  }
+  return *this;
+}
+
+Errata&
+Errata::join(self const& that) {
+  if (that.m_data) {
+    this->pre_write();
+    m_data->m_items.insert(
+      m_data->m_items.end(),
+      that.m_data->m_items.begin(),
+      that.m_data->m_items.end()
+    );
+  }
+  return *this;
+}
+
+void
+Errata::pop() {
+  if (m_data && m_data->size()) {
+    this->pre_write()->m_items.pop_front();
+  }
+  return;
+}
+
+void
+Errata::clear() {
+  m_data.reset(0);
+}
+
+/*  We want to allow iteration on empty / nil containers because that's very
+    convenient for clients. We need only return the same value for begin()
+    and end() and everything works as expected.
+
+    However we need to be a bit more clever for VC 8.  It checks for
+    iterator compatibility, i.e. that the iterators are not
+    invalidated and that they are for the same container.  It appears
+    that default iterators are not compatible with anything.  So we
+    use static container for the nil data case.
+ */
+static Errata::Container NIL_CONTAINER;
+
+Errata::iterator
+Errata::begin() {
+  return m_data ? m_data->m_items.rbegin() : NIL_CONTAINER.rbegin();
+}
+
+Errata::const_iterator
+Errata::begin() const {
+  return m_data ? static_cast<Data const&>(*m_data).m_items.rbegin()
+    : static_cast<Container const&>(NIL_CONTAINER).rbegin();
+}
+
+Errata::iterator
+Errata::end() {
+  return m_data ? m_data->m_items.rend() : NIL_CONTAINER.rend();
+}
+
+Errata::const_iterator
+Errata::end() const {
+  return m_data ? static_cast<Data const&>(*m_data).m_items.rend()
+    : static_cast<Container const&>(NIL_CONTAINER).rend();
+}
+
+void
+Errata::registerSink(Sink::Handle const& s) {
+  Sink_List.push_back(s);
+}
+
+std::ostream&
+Errata::write(
+  std::ostream& out,
+  int offset,
+  int indent,
+  int shift,
+  char const* lead
+) const {
+  for ( const_iterator spot = this->begin(), limit = this->end();
+        spot != limit;
+        ++spot
+  ) {
+    if ((offset + indent) > 0)
+      out << std::setw(indent + offset) << std::setfill(' ')
+          << ((indent > 0 && lead) ? lead : " ");
+
+    out << spot->m_id << " [" << spot->m_code << "]: " << spot->m_text
+        << std::endl
+      ;
+    if (spot->getErrata().size())
+      spot->getErrata().write(out, offset, indent+shift, shift, lead);
+
+  }
+  return out;
+}
+
+size_t
+Errata::write(
+  char *buff,
+  size_t n,
+  int offset,
+  int indent,
+  int shift,
+  char const* lead
+) const {
+  std::ostringstream out;
+  std::string text;
+  this->write(out, offset, indent, shift, lead);
+  text = out.str();
+  memcpy(buff, text.data(), std::min(n, text.size()));
+  return text.size();
+}
+
+std::ostream& operator<< (std::ostream& os, Errata const& err) {
+  return err.write(os, 0, 0, 2, "> ");
+}
+
+# if USING_BOOST
+
+std::ostream&
+errata::format(std::ostream& s, std::string const& fmt, std::string const& glue) const {
+  return this->format(s, boost::format(fmt), glue);
+}
+
+std::ostream&
+errata::format(std::ostream& s, boost::format const& fmt, std::string const& glue) const {
+  if (_data) {
+    bool inside = false;
+    boost::format f(fmt);
+    f.exceptions(boost::io::all_error_bits ^ boost::io::too_many_args_bit);
+    const_iterator spot(this->begin()), limit(this->end());
+    while (spot != limit) {
+      if (inside) s << glue;
+      s << ( f % spot->_id % spot->_text );
+      inside = true;
+      ++spot;
+    }
+  }
+  return s;
+}
+
+std::string
+errata::format(std::string const& fmt, std::string const& glue) const {
+  return this->format(boost::format(fmt), glue);
+}
+
+std::string
+errata::format(boost::format const& fmt, std::string const& glue) const {
+  std::ostringstream s;
+  this->format(s, fmt, glue);
+  return s.str();
+}
+
+# endif
+
+} // namespace ngeo

Added: trafficserver/traffic/branches/wccp/proxy/tsconfig/Errata.h
URL: http://svn.apache.org/viewvc/trafficserver/traffic/branches/wccp/proxy/tsconfig/Errata.h?rev=1037235&view=auto
==============================================================================
--- trafficserver/traffic/branches/wccp/proxy/tsconfig/Errata.h (added)
+++ trafficserver/traffic/branches/wccp/proxy/tsconfig/Errata.h Sat Nov 20 15:17:55 2010
@@ -0,0 +1,928 @@
+# if !defined ATS_ERRATA_HEADER
+# define ATS_ERRATA_HEADER
+
+# include <memory>
+# include <string>
+# include <iosfwd>
+# include <deque>
+# include "NumericType.h"
+# include "IntrusivePtr.h"
+
+# if USING_BOOST
+#   include <boost/function.hpp>
+#   include <boost/format/format_fwd.hpp>
+# endif
+
+namespace ts {
+
+/** @file
+    Stacking error message handling.
+
+    The problem addressed by this library is the ability to pass back
+    detailed error messages from failures. It is hard to get good
+    diagnostics because the specific failures and general context are
+    located in very different stack frames. This library allows local
+    functions to pass back local messages which can be easily
+    augmented as the error travels up the stack frame.
+
+    This could be done with exceptions but
+    - That is more effort to implemention
+    - Generally more expensive.
+
+    Each message on a stack contains text and a numeric identifier.
+    The identifier value zero is reserved for messages that are not
+    errors so that information can be passed back even in the success
+    case.
+
+    The implementation takes the position that success is fast and
+    failure is expensive. Therefore it is optimized for the success
+    path, imposing very little overhead. On the other hand, if an
+    error occurs and is handled, that is generally so expensive that
+    optimizations are pointless (although, of course, one should not
+    be gratuitiously expensive).
+
+    The library also provides the @c Rv ("return value") template to
+    make returning values and status easier. This template allows a
+    function to return a value and status pair with minimal changes.
+    The pair acts like the value type in most situations, while
+    providing access to the status.
+
+    Each instance of an erratum is a wrapper class that emulates value
+    semantics (copy on write). This means passing even large message
+    stacks is inexpensive, involving only a pointer copy and reference
+    counter increment and decrement. A success value is represented by
+    an internal @c NULL so it is even cheaper to copy.
+
+    To further ease use, the library has the ability to define @a
+    sinks.  A sink is a function that acts on an erratum when it
+    becomes unreferenced. The indended use is to send the messages to
+    an output log. This makes reporting errors to a log from even
+    deeply nested functions easy while preserving the ability of the
+    top level logic to control such logging.
+
+ */
+
+/** Class to hold a stack of error messages (the "errata").
+    This is a smart handle class, which wraps the actual data
+    and can therefore be treated a value type with cheap copy
+    semantics. Default construction is very cheap.
+ */
+class Errata {
+protected:
+    /// Implementation class.
+    struct Data;
+    /// Handle for implementation class instance.
+    typedef IntrusivePtr<Data> ImpPtr;
+public:
+    typedef Errata self; /// Self reference type.
+
+    /// Message ID.
+    typedef NumericType<unsigned int, struct MsgIdTag> Id;
+
+    /* Tag / level / code severity.
+       This is intended for clients to use to provide additional
+       classification of a message. A severity code, as for syslog,
+       is a common use.
+
+    */
+    typedef NumericType<unsigned int, struct CodeTag> Code;
+    struct Message;
+
+    typedef std::deque<Message> Container; ///< Storage type for messages.
+    // We iterate backwards to look like a stack.
+//    typedef Container::reverse_iterator iterator; ///< Message iteration.
+    /// Message const iteration.
+//    typedef Container::const_reverse_iterator const_iterator;
+    /// Reverse message iteration.
+//    typedef Container::iterator reverse_iterator;
+    /// Reverse constant message iteration.
+//    typedef Container::const_iterator const_reverse_iterator;
+    
+    /// Default constructor - empty errata, very fast.
+    Errata();
+    /// Copy constructor, very fast.
+    Errata (
+        self const& that ///< Object to copy
+    );
+    /// Construct from string.
+    /// Message Id and Code are default.
+    explicit Errata(
+        std::string const& text ///< Finalized message text.
+    );
+    /// Construct with @a id and @a text.
+    /// Code is default.
+    Errata(
+      Id id, ///< Message id.
+      std::string const& text ///< Message text.
+    );
+    /// Construct with @a id, @a code, and @a text.
+    Errata(
+      Id id, ///< Message text.
+      Code code, ///< Message code.
+      std::string const& text ///< Message text.
+    );
+    /** Construct from a message instance.
+        This is equivalent to default constructing an @c errata and then
+        invoking @c push with an argument of @a msg.
+    */
+    Errata(
+      Message const& msg ///< Message to push
+    );
+
+    /// destructor
+    ~Errata();
+
+    /// Self assignment.
+    /// @return A reference to this object.
+    self& operator = (
+      const self& that ///< Source instance.
+    );
+
+    /** Assign message.
+        All other messages are discarded.
+        @return A reference to this object.
+    */
+    self& operator = (
+      Message const& msg ///< Source message.
+    );
+
+    /** Push @a text as a message.
+        The message is constructed from just the @a text.
+        It becomes the top message.
+        @return A reference to this object.
+    */
+    self& push(std::string const& text);
+    /** Push @a text as a message with message @a id.
+        The message is constructed from @a text and @a id.
+        It becomes the top message.
+        @return A reference to this object.
+    */
+    self& push(Id id, std::string const& text);
+    /** Push @a text as a message with message @a id and @a code.
+        The message is constructed from @a text and @a id.
+        It becomes the top message.
+        @return A reference to this object.
+    */
+    self& push(Id id, Code code, std::string const& text);
+    /** Push a message.
+        @a msg becomes the top message.
+        @return A reference to this object.
+    */
+    self& push(Message const& msg);
+
+    /** Push a nested status.
+        @a err becomes the top item.
+        @return A reference to this object.
+    */
+    self& push(self const& err);
+
+    /** Access top message.
+        @return If the errata is empty, a default constructed message
+        otherwise the most recent message.
+     */
+    Message const& top() const;
+
+    /** Join @a that to @c this errata.
+        Messages from @a that are put on the top of the
+        stack in @c this.
+    */
+    self& join(self const& that);
+
+    /// Remove last message.
+    void pop();
+
+    /// Remove all messages.
+    void clear();
+
+    /** Inhibit logging.
+        @note This only affects @c this as a top level @c errata.
+        It has no effect on this @c this being logged as a nested
+        @c errata.
+    */
+    self& doNotLog();
+
+    friend std::ostream& operator<< (std::ostream&, self const&);
+
+    /// Default glue value (a newline) for text rendering.
+    static std::string const DEFAULT_GLUE;
+
+    /** Test status.
+
+        Equivalent to @c success but more convenient for use in
+        control statements.
+
+        @return @c true if no messages or last message has a zero
+        message ID, @c false otherwise.
+     */
+    operator bool() const;
+
+    /** Test errata for no failure condition.
+
+        Equivalent to @c operator @c bool but easier to invoke.
+
+        @return @c true if no messages or last message has a zero
+        message ID, @c false otherwise.
+     */
+    bool isOK() const;
+
+    /// Number of messages in the errata.
+    size_t size() const;
+
+    /*  Forward declares.
+        We have to make our own iterators as the least bad option. The problem
+        is that we have recursive structures so declaration order is difficult.
+        We can't use the container iterators here because the element type is
+        not yet defined. If we define the element type here, it can't contain
+        an Errata and we have to do funky things to get around that. So we
+        have our own iterators, which are just shadowing sublclasses of the
+        container iterators.
+     */
+    class iterator;
+    class const_iterator;
+
+    /// Reference to top item on the stack.
+    iterator begin();
+    /// Reference to top item on the stack.
+    const_iterator begin() const;
+    //! Reference one past bottom item on the stack.
+    iterator end();
+    //! Reference one past bottom item on the stack.
+    const_iterator end() const;
+
+    // Logging support.
+
+    /** Base class for erratum sink.
+        When an errata is abandoned, this will be called on it to perform
+        any client specific logging. It is passed around by handle so that
+        it doesn't have to support copy semantics (and is not destructed
+        until application shutdown). Clients can subclass this class in order
+        to preserve arbitrary data for the sink or retain a handle to the
+        sink for runtime modifications.
+     */
+    class Sink : public IntrusivePtrCounter {
+    public:
+        typedef Sink self; ///< Self reference type.
+        typedef IntrusivePtr<self> Handle;  ///< Handle type.
+
+        /// Handle an abandoned errata.
+        virtual void operator() (Errata const&) const = 0;
+        /// Force virtual destructor.
+        virtual ~Sink() {}
+    };
+
+    //! Register a sink for discarded erratum.
+    static void registerSink(Sink::Handle const& s);
+
+    /// Register a function as a sink.
+    typedef void (*SinkHandlerFunction)(Errata const&);
+
+    // Wrapper class to support registering functions as sinks.
+    struct SinkFunctionWrapper : public Sink {
+        /// Constructor.
+        SinkFunctionWrapper(SinkHandlerFunction f) : m_f(f) { }
+        /// Operator to invoke the function.
+        virtual void operator() (Errata const& e) const { m_f(e); }
+        SinkHandlerFunction m_f; ///< Client supplied handler.
+    };
+
+    /// Register a sink function for abandonded erratum.
+    static void registerSink(SinkHandlerFunction f) {
+        registerSink(Sink::Handle(new SinkFunctionWrapper(f)));
+    }
+
+    /** Simple formatted output.
+
+        Each message is written to a line. All lines are indented with
+        whitespace @a offset characters. Lines are indented an
+        additional @a indent. This value is increased by @a shift for
+        each level of nesting of an @c Errata. if @a lead is not @c
+        NULL the indentation is overwritten by @a lead if @a indent is
+        non-zero. It acts as a "continuation" marker for nested
+        @c Errata.
+        
+     */
+    std::ostream& write(
+      std::ostream& out, ///< Output stream.
+      int offset, ///< Lead white space for every line.
+      int indent, ///< Additional indention per line for messages.
+      int shift, ///< Additional @a indent for nested @c Errata.
+      char const* lead ///< Leading text for nested @c Errata.
+    ) const;
+    /// Simple formatted output to fixed sized buffer.
+    /// @return Number of characters written to @a buffer.
+    size_t write(
+      char* buffer, ///< Output buffer.
+      size_t n, ///< Buffer size.
+      int offset, ///< Lead white space for every line.
+      int indent, ///< Additional indention per line for messages.
+      int shift, ///< Additional @a indent for nested @c Errata.
+      char const* lead ///< Leading text for nested @c Errata.
+    ) const;
+
+# if USING_BOOST
+    /// Functor type for sink.
+    typedef boost::function<void (Errata const&)> SinkFunctor;
+
+    // Wrapper class to support registering functions as sinks.
+    struct SinkFunctorWrapper : public Sink {
+        /// Constructor.
+        SinkFunctionWrapper(SinkHandlerFunctor f) : m_f(f) { }
+        /// Operator to invoke the function.
+        virtual void operator() (Errata const& e) const { m_f(e); }
+        SinkHandlerFunctor m_f; ///< Client supplied handler.
+    };
+
+    /// Register a sink function for abandonded erratum.
+    static void registerSink(SinkFunctor const& f) {
+        registerSink(Sink::Handle(new SinkFunctorWrapper(f)));
+    }
+
+    /// Generate formatted output.
+    /// For each message in the stack, invoke @c boost::format passing
+    /// @a fmt as the format string and the message ID and message text as
+    /// two values. It is not an error to elide either or both. @a glue is
+    /// sent to the stream @a s between every pair of messages.
+    /// @return The stream @a s.
+    std::ostream& format(
+        std::ostream& s,           ///< Output stream
+        boost::format const& fmt,  ///< Format string
+        std::string const& glue = DEFAULT_GLUE ///< Glue
+    ) const;
+
+    /// Generate formatted output.
+    /// A convenience overload so clients do not have to include the Boost.Format headers.
+    /// @return The formatted output.
+    /// @see std::ostream& format ( std::ostream& s, boost::format const& fmt, std::string const& glue ).
+    std::ostream& format(
+        std::ostream& s,           ///< Output stream
+        std::string const& fmt,    ///< Format string
+        std::string const& glue = DEFAULT_GLUE ///< Glue
+    ) const;
+
+    /// Generate formatted output.
+    /// For each message in the stack, invoke @c boost::format passing
+    /// @a fmt as the format string and the message ID and message text as
+    /// two values. It is not an error to elide either or both. @a glue is
+    /// added between every pair of messages.
+    /// @note This is identical to the stream variant except the output
+    /// is put in a string instead of a stream.
+    /// @return The formatted output.
+    /// @see std::ostream& format ( std::ostream& s, boost::format const& fmt, std::string const& glue ).
+    std::string format(
+        boost::format const& fmt,  ///< Format string
+        std::string const& glue = DEFAULT_GLUE ///< Glue
+    ) const;
+
+    /// Generate formatted output.
+    /// A convenience overload so clients do not have to include the Boost.Format headers.
+    /// @return The formatted output.
+    /// @see std::string format ( boost::format const& fmt, std::string const& glue ).
+    std::string format(
+        std::string const& fmt,  ///< Format string
+        std::string const& glue = DEFAULT_GLUE ///< Glue
+    ) const;
+# endif // USING_BOOST
+
+protected:
+    /// Construct from implementation pointer.
+    /// Used internally by nested classes.
+    Errata(ImpPtr const& ptr);
+    /// Implementation instance.
+    ImpPtr m_data;
+
+    /// Return the implementation instance, allocating and unsharing as needed.
+    Data* pre_write();
+    /// Force and return an implementation instance.
+    /// Does not follow copy on write.
+    Data* instance();
+
+    /// Used for returns when no data is present.
+    static Message const NIL_MESSAGE;
+
+    friend struct Data;
+    friend class Item;
+
+};
+
+extern std::ostream& operator<< (std::ostream& os, Errata const& stat);
+
+/// Storage for a single message.
+struct Errata::Message {
+  typedef Message self; ///< Self reference type.
+
+  /// Default constructor.
+  /// The message has Id = 0, default code,  and empty text.
+  Message();
+
+  /// Construct from text.
+  /// Id is zero and Code is default.
+  Message(
+    std::string const& text ///< Finalized message text.
+  );
+
+  /// Construct with @a id and @a text.
+  /// Code is default.
+  Message(
+    Id id, ///< ID of message in table.
+    std::string const& text ///< Final text for message.
+  );
+
+  /// Construct with @a id, @a code, and @a text.
+  Message(
+    Id id, ///< Message Id.
+    Code code, ///< Message Code.
+    std::string const& text ///< Final text for message.
+  );
+
+  /// Reset to the message to default state.
+  self& clear();
+
+  /// Set the message Id.
+  self& set(
+    Id id ///< New message Id.
+  );
+
+  /// Set the code.
+  self& set(
+    Code code ///< New code for message.
+  );
+
+  /// Set the text.
+  self& set(
+    std::string const& text ///< New message text.
+  );
+
+  /// Set the text.
+  self& set(
+    char const* text ///< New message text.
+  );
+
+  /// Set the errata.
+  self& set(
+    Errata const& err ///< Errata to store.
+  );
+
+  /// Get the text of the message.
+  std::string const& text() const;
+
+  /// Get the code.
+  Code getCode() const;
+  /// Get the nested status.
+  /// @return A status object, which is not @c NULL if there is a
+  /// nested status stored in this item.
+  Errata getErrata() const;
+
+  /** The default message code.
+
+      This value is used as the Code value for constructing and
+      clearing messages. It can be changed to control the value
+      used for empty messages.
+  */
+  static Code Default_Code;
+
+  /// Type for overriding success message test.
+  typedef bool (*SuccessTest)(Message const& m);
+
+  /** Success message test.
+
+      When a message is tested for being "successful", this
+      function is called. It may be overridden by a client.
+      The initial value is @c DEFAULT_SUCCESS_TEST.
+
+      @note This is only called when there are Messages in the
+      Errata. An empty Errata (@c NULL or empty stack) is always
+      a success. Only the @c top Message is checked.
+
+      @return @c true if the message indicates success,
+      @c false otherwise.
+  */
+  static SuccessTest Success_Test;
+
+  /// Indicate success if the message code is zero.
+  /// @note Used as the default success test.
+  static bool isCodeZero(Message const& m);
+
+  static SuccessTest const DEFAULT_SUCCESS_TEST;
+
+  Id m_id; ///< Message ID.
+  Code m_code; ///< Message code.
+  std::string m_text; ///< Final text.
+  Errata m_errata; ///< Nested errata.
+};
+
+/** This is the implementation class for Errata.
+
+    It holds the actual messages and is treated as a passive data
+    object with nice constructors.
+
+    We implement reference counting semantics by hand for two
+    reasons. One is that we need to do some specialized things, but
+    mainly because the client can't see this class so we can't
+*/
+struct Errata::Data : public IntrusivePtrCounter {
+  typedef Data self; ///< Self reference type.
+
+  //! Default constructor.
+  Data();
+
+  /// Destructor, to do logging.
+  ~Data();
+
+  //! Number of messages.
+  size_t size() const;
+
+  /// Get the top message on the stack.
+  Message const& top() const;
+
+  /// Put a message on top of the stack.
+  void push(Message const& msg);
+
+  /// Log this when it is deleted.
+  bool m_log_on_delete;
+
+  //! The message stack.
+  Container m_items;
+};
+
+/// Forward iterator for @c Messages in an @c Errata.
+class Errata::iterator : public Errata::Container::reverse_iterator {
+public:
+    typedef iterator self; ///< Self reference type.
+    typedef Errata::Container::reverse_iterator super; ///< Parent type.
+    iterator(); ///< Default constructor.
+    /// Copy constructor.
+    iterator(
+        self const& that ///< Source instance.
+    );
+    /// Construct from super class.
+    iterator(
+        super const& that ///< Source instance.
+    );
+    /// Assignment.
+    self& operator = (self const& that);
+    /// Assignment from super class.
+    self& operator = (super const& that);
+    /// Prefix increment.
+    self& operator ++ ();
+    /// Prefix decrement.
+    self& operator -- ();
+};
+
+/// Forward constant iterator for @c Messages in an @c Errata.
+class Errata::const_iterator : public Errata::Container::const_reverse_iterator {
+public:
+    typedef const_iterator self; ///< Self reference type.
+    typedef Errata::Container::const_reverse_iterator super; ///< Parent type.
+    const_iterator(); ///< Default constructor.
+    /// Copy constructor.
+    const_iterator(
+        self const& that ///< Source instance.
+    );
+    const_iterator(
+        super const& that ///< Source instance.
+    );
+    /// Assignment.
+    self& operator = (self const& that);
+    /// Assignment from super class.
+    self& operator = (super const& that);
+    /// Prefix increment.
+    self& operator ++ ();
+    /// Prefix decrement.
+    self& operator -- ();
+};
+
+/** Helper class for @c Rv.
+    This class enables us to move the implementation of non-templated methods
+    and members out of the header file for a cleaner API.
+ */
+struct RvBase {
+  Errata _errata;    ///< The status from the function.
+
+  /** Default constructor. */
+  RvBase();
+
+  /** Construct with specific status.
+   */
+  RvBase (
+    Errata const& s ///< Status to copy
+  );
+
+  //! Test the return value for success.
+  bool isOK() const;
+
+  /** Clear any stacked errors.
+      This is useful during shutdown, to silence irrelevant errors caused
+      by the shutdown process.
+  */
+  void clear();
+
+  /// Inhibit logging of the errata.
+  void doNotLog();
+};
+
+/** Return type for returning a value and status (errata).  In
+    general, a method wants to return both a result and a status so
+    that errors are logged properly. This structure is used to do that
+    in way that is more usable than just @c std::pair.  - Simpler and
+    shorter typography - Force use of @c errata rather than having to
+    remember it (and the order) each time - Enable assignment directly
+    to @a R for ease of use and compatibility so clients can upgrade
+    asynchronously.
+ */
+template < typename R >
+struct Rv : public RvBase {
+  typedef Rv self;       ///< Standard self reference type.
+  typedef RvBase super; ///< Standard super class reference type.
+  typedef R Result; ///< Type of result value.
+
+  Result _result;             ///< The actual result of the function.
+
+  /** Default constructor.
+      The default constructor for @a R is used.
+      The status is initialized to SUCCESS.
+  */
+  Rv();
+
+  /** Standard (success) constructor.
+
+      This copies the result and sets the status to SUCCESS.
+
+      @note Not @c explicit so that clients can return just a result
+       and have it be marked as SUCCESS.
+   */
+  Rv(
+    Result const& r  ///< The function result
+  );
+
+  /** Construct from a result and a pre-existing status object.
+
+      @internal No constructor from just an Errata to avoid
+      potential ambiguity with constructing from result type.
+   */
+  Rv(
+    Result const& r,         ///< The function result
+    Errata const& s    ///< A pre-existing status object
+  );
+
+  /** User conversion to the result type.
+
+      This makes it easy to use the function normally or to pass the
+      result only to other functions without having to extract it by
+      hand.
+  */
+  operator Result const& () const;
+
+  /** Assignment from result type.
+
+      This allows the result to be assigned to a pre-declared return
+      value structure.  The return value is a reference to the
+      internal result so that this operator can be chained in other
+      assignments to instances of result type. This is most commonly
+      used when the result is computed in to a local variable to be
+      both returned and stored in a member.
+
+      @code
+      Rv<int> zret;
+      int value;
+      // ... complex computations, result in value
+      this->m_value = zret = value;
+      // ...
+      return zret;
+      @endcode
+
+      @return A reference to the copy of @a r stored in this object.
+  */
+  Result& operator = (
+    Result const& r  ///< Result to assign
+  ) {
+    _result = r;
+    return _result;
+  }
+
+  /** Add the status from another instance to this one.
+      @return A reference to @c this object.
+  */
+  template < typename U >
+  self& push(
+    Rv<U> const& that ///< Source of status messages
+  );
+
+  /** Set the result.
+
+      This differs from assignment of the function result in that the
+      return value is a reference to the @c Rv, not the internal
+      result. This makes it useful for assigning a result local
+      variable and then returning.
+
+      @code
+      Rv<int> zret;
+      int value;
+      // ... complex computation, result in value
+      return zret.set(value);
+      @endcode
+  */
+  self& set(
+    Result const& r  ///< Result to store
+  );
+
+  /** Return the result.
+      @return A reference to the result value in this object.
+  */
+  Result& result();
+
+  /** Return the result.
+      @return A reference to the result value in this object.
+  */
+  Result const& result() const;
+
+  /** Return the status.
+      @return A reference to the @c errata in this object.
+  */
+  Errata& errata();
+
+  /** Return the status.
+      @return A reference to the @c errata in this object.
+  */
+  Errata const& errata() const;
+
+  /// Directly set the errata
+  self& operator = (
+    Errata const& status ///< Errata to assign.
+  );
+
+  /// Push a message on to the status.
+  self& push(
+    Errata::Message const& msg
+  );
+};
+
+/** Combine a function result and status in to an @c Rv.
+    This is useful for clients that want to declare the status object
+    and result independently.
+ */
+template < typename R > Rv<R>
+MakeRv(
+  R const& r,          ///< The function result
+  Errata const& s      ///< The pre-existing status object
+) {
+    return Rv<R>(r, s);
+}
+/* ----------------------------------------------------------------------- */
+/* ----------------------------------------------------------------------- */
+// Inline methods.
+inline Errata::Message::Message()
+  : m_id(0), m_code(Default_Code) {
+}
+inline Errata::Message::Message(std::string const& text)
+  : m_id(0), m_code(Default_Code), m_text(text) {
+}
+inline Errata::Message::Message(Id id, std::string const& text)
+  : m_id(id), m_code(Default_Code), m_text(text) {
+}
+inline Errata::Message::Message(Id id, Code code, std::string const& text)
+  : m_id(id), m_code(code), m_text(text) {
+}
+inline Errata::Message& Errata::Message::clear() {
+  m_id = 0;
+  m_code = Default_Code;
+  m_text.erase();
+  m_errata.clear();
+  return *this;
+}
+
+inline std::string const& Errata::Message::text() const { return m_text; }
+inline Errata::Code Errata::Message::getCode() const { return m_code; }
+inline Errata Errata::Message::getErrata() const { return m_errata; }
+
+inline Errata::Message& Errata::Message::set(Id id) {
+  m_id = id;
+  return *this;
+}
+inline Errata::Message& Errata::Message::set(Code code) {
+  m_code = code;
+  return *this;
+}
+inline Errata::Message& Errata::Message::set(std::string const& text) {
+  m_text = text;
+  return *this;
+}
+inline Errata::Message& Errata::Message::set(char const* text) {
+  m_text = text;
+  return *this;
+}
+inline Errata::Message& Errata::Message::set(Errata const& err) {
+  m_errata = err;
+  m_errata.doNotLog();
+  return *this;
+}
+
+inline Errata::Errata(Id id, Code code, std::string const& text) {
+  this->push(Message(id, code, text));
+}
+inline Errata::Errata(Message const& msg) {
+  this->push(msg);
+}
+
+inline Errata::operator bool() const { return this->isOK(); }
+
+inline size_t Errata::size() const {
+  return m_data ? m_data->m_items.size() : 0;
+}
+
+inline bool Errata::isOK() const {
+  return 0 == m_data
+    || 0 == m_data->size()
+    || Message::Success_Test(this->top())
+    ;
+}
+
+inline Errata&
+Errata::push(std::string const& text) {
+  this->push(Message(text));
+  return *this;
+}
+
+inline Errata&
+Errata::push(Id id, std::string const& text) {
+  this->push(Message(id, text));
+  return *this;
+}
+
+inline Errata&
+Errata::push(Id id, Code code, std::string const& text) {
+  this->push(Message(id, code, text));
+  return *this;
+}
+
+inline Errata::Message const&
+Errata::top() const {
+  return m_data ? m_data->top() : NIL_MESSAGE;
+}
+inline Errata& Errata::doNotLog() {
+  this->instance()->m_log_on_delete = false;
+  return *this;
+}
+
+inline Errata::Data::Data() : m_log_on_delete(true) {}
+inline size_t Errata::Data::size() const { return m_items.size(); }
+
+inline Errata::iterator::iterator() { }
+inline Errata::iterator::iterator(self const& that) : super(that) { }
+inline Errata::iterator::iterator(super const& that) : super(that) { }
+inline Errata::iterator& Errata::iterator::operator = (self const& that) { this->super::operator = (that); return *this; }
+inline Errata::iterator& Errata::iterator::operator = (super const& that) { this->super::operator = (that); return *this; }
+inline Errata::iterator& Errata::iterator::operator ++ () { this->super::operator ++ (); return *this; }
+inline Errata::iterator& Errata::iterator::operator -- () { this->super::operator -- (); return *this; }
+
+inline Errata::const_iterator::const_iterator() { }
+inline Errata::const_iterator::const_iterator(self const& that) : super(that) { }
+inline Errata::const_iterator::const_iterator(super const& that) : super(that) { }
+inline Errata::const_iterator& Errata::const_iterator::operator = (self const& that) { super::operator = (that); return *this; }
+inline Errata::const_iterator& Errata::const_iterator::operator = (super const& that) { super::operator = (that); return *this; }
+inline Errata::const_iterator& Errata::const_iterator::operator ++ () { this->super::operator ++ (); return *this; }
+inline Errata::const_iterator& Errata::const_iterator::operator -- () { this->super::operator -- (); return *this; }
+
+inline RvBase::RvBase() { }
+inline RvBase::RvBase(Errata const& errata) : _errata(errata) { }
+inline bool RvBase::isOK() const { return _errata; }
+inline void RvBase::clear() { _errata.clear(); }
+inline void RvBase::doNotLog() { _errata.doNotLog(); }
+
+template < typename T > Rv<T>::Rv() { }
+template < typename T > Rv<T>::Rv(Result const& r) : _result(r) { }
+template < typename T > Rv<T>::Rv(Result const& r, Errata const& errata)
+  : super(errata)
+  , _result(r) {
+}
+template < typename T > Rv<T>::operator Result const&() const {
+  return _result;
+}
+template < typename T > T const& Rv<T>::result() const { return _result; }
+template < typename T > T& Rv<T>::result() { return _result; }
+template < typename T > Errata const& Rv<T>::errata() const { return _errata; }
+template < typename T > Errata& Rv<T>::errata() { return _errata; }
+template < typename T > Rv<T>&
+Rv<T>::set(Result const& r) {
+  _result = r;
+  return *this;
+}
+template < typename T > Rv<T>&
+Rv<T>::operator = (Errata const& errata) {
+  _errata = errata;
+  return *this;
+}
+template < typename T > Rv<T>&
+Rv<T>::push(Errata::Message const& msg) {
+  _errata.push(msg);
+  return *this;
+}
+template < typename T > template < typename U > Rv<T>&
+Rv<T>::push(Rv<U> const& that) {
+  _errata.push(that.errata());
+  return *this;
+}
+/* ----------------------------------------------------------------------- */
+/* ----------------------------------------------------------------------- */
+} // namespace ats
+
+# endif // ATS_ERRATA_HEADER

Added: trafficserver/traffic/branches/wccp/proxy/tsconfig/IntrusivePtr.h
URL: http://svn.apache.org/viewvc/trafficserver/traffic/branches/wccp/proxy/tsconfig/IntrusivePtr.h?rev=1037235&view=auto
==============================================================================
--- trafficserver/traffic/branches/wccp/proxy/tsconfig/IntrusivePtr.h (added)
+++ trafficserver/traffic/branches/wccp/proxy/tsconfig/IntrusivePtr.h Sat Nov 20 15:17:55 2010
@@ -0,0 +1,600 @@
+/*      Copyright (c) 2006-2010 Network Geographics.
+ *      All rights reserved.
+ *      Licensed to the Apache Software Foundation.
+ */
+/* ----------------------------------------------------------------------- */
+# if !defined(ATS_INTRUSIVE_PTR_HEADER)
+# define ATS_INTRUSIVE_PTR_HEADER
+/* ----------------------------------------------------------------------- */
+# include <sys/types.h>
+# include <assert.h>
+# include <functional>
+
+namespace ts {
+/* ----------------------------------------------------------------------- */
+/* ----------------------------------------------------------------------- */
+/** @file
+
+    This is a simple shared pointer class for restricted use. It is not a
+    completely general class. The most significant missing feature is the
+    lack of thread safety. For its intended use, this is acceptable and
+    provides a performance improvement. However, it does restrict how the
+    class may be used.
+
+    This style of shared pointer also requires explicit support from the
+    target class, which must provide an internal reference counter.
+
+ */
+/* ----------------------------------------------------------------------- */
+/* ----------------------------------------------------------------------- */
+class IntrusivePtrCounter;
+
+/** This class exists solely to be declared a friend of @c IntrusivePtrCounter.
+
+    @internal This is done because we can't declare the template a
+    friend, so rather than burden the client with the declaration we
+    do it here. It provides a single method that allows the smart pointer
+    to get access to the protected reference count.
+
+ */
+class IntrusivePtrBase {
+public:
+  /// Type used for reference counter.
+  typedef long Counter;
+protected:
+  Counter* getCounter(
+    IntrusivePtrCounter* c ///< Cast object with reference counter.
+  ) const;
+};
+/* ----------------------------------------------------------------------- */
+/* ----------------------------------------------------------------------- */
+/** Reference counter mixin.
+
+    To add support for @c IntrusivePtr to class @a T, it
+    should inherit from @c IntrusivePtrCounter<T> in order to
+
+    - provide a reference count member
+    - force the reference count to initialize to zero
+    - define the add and release global functions required by @c IntrusivePtr
+
+    In general this class should be inherited publicly. This will
+    provide methods which mimic the @c Boost.shared_ptr interface ( @c
+    unique() , @c use_count() ).
+
+    If this class is not inherited publically or the destructor is
+    non-public then the host class (@a T) must declare this class ( @c
+    reference_counter<T> ) as a friend.
+
+    @internal Due to changes in the C++ standard and design decisions
+    in gcc, it is no longer possible to declare a template parameter
+    as a friend class.  (Basically, you can't use a typedef in a
+    friend declaration and gcc treats template parameters as
+    typedefs).
+
+    @note You can use this with insulated (by name only) classes. The
+    important thing is to make sure that any such class that uses @c
+    IntrusivePtr has all of its constructors and destructors declared
+    in the header and defined in the implementation translation
+    unit. If the compiler generates any of those, it will not compile
+    due to missing functions or methods
+
+  */
+class IntrusivePtrCounter {
+  friend class IntrusivePtrBase;
+public:
+  /** Copy constructor.
+
+      @internal We have to define this to explicitly _not_ copy the
+      reference count. Otherwise any client that uses a default copy
+      constructor will _copy the ref count into the new object_. That
+      way lies madness.
+  */
+
+  IntrusivePtrCounter(
+    IntrusivePtrCounter const& ///< Source object.
+  );
+  
+  /** Assignment operator.
+
+      @internal We need this for the same reason as the copy
+      constructor. The reference counter must not participate in
+      assignment.
+   */
+  IntrusivePtrCounter& operator = (
+    IntrusivePtrCounter const&
+  );
+
+protected:
+  IntrusivePtrBase::Counter m_intrusive_pointer_reference_count;
+  /// Default constructor (0 init counter).
+  /// @internal Only subclasses can access this.
+  IntrusivePtrCounter();
+};
+/* ----------------------------------------------------------------------- */
+/* ----------------------------------------------------------------------- */
+/** Shared pointer.
+
+    This is a reference counted smart pointer. A single object is jointly
+    ownded by a set of pointers. When the last of the pointers is destructed
+    the target object is also destructed.
+
+    The smart pointer actions can be changed through class specific policy
+    by specializing the @c IntrusivePtrPolicy template class.
+*/
+template < typename T >
+class IntrusivePtr : private IntrusivePtrBase {
+private:	/* don't pollute client with these typedefs */
+  typedef IntrusivePtrBase super; ///< Parent type.
+  typedef IntrusivePtr self; ///< Self reference type.
+
+public:
+  /// Promote type for reference counter.
+  typedef super::Counter Counter;
+
+  /// Default constructor (0 initialized).
+  IntrusivePtr();
+  /// Construct from instance.
+  /// The instance becomes referenced and owned by the pointer.
+  IntrusivePtr(T* obj);
+  /// Destructor.
+  ~IntrusivePtr();
+
+  /// Copy constructor.
+  IntrusivePtr(const self& src);
+  /// Self assignement.
+  self& operator = (const self& src);
+  /** Assign from instance.
+      The instance becomes referenced and owned by the pointer.
+      The reference to the current object is dropped.
+  */
+  self& operator = (
+    T* obj ///< Target instance.
+  );
+
+  /** Assign from instance.
+      The instance becomes referenced and owned by the pointer.
+      The reference to the current object is dropped.
+      @note A synonym for @c operator= for compatibility.
+  */
+  self& assign (
+    T* obj ///< Target instance.
+  );
+
+  /** Assign from instance.
+      The instance becomes referenced and owned by the pointer.
+      The reference to the current object is dropped.
+  */
+  void reset(T* obj);
+  /** Clear reference without cleanup.
+
+      This unsets this smart pointer and decrements the reference
+      count, but does @b not perform any finalization on the
+      target object. This can easily lead to memory leaks and
+      in some sense vitiates the point of this class, but it is
+      occasionally the right thing to do. Use with caution.
+
+      @return @c true if there are no references upon return,
+      @c false if the reference count is not zero.
+   */
+  bool release();
+
+  /// Test if the pointer is zero (@c NULL).
+  bool isNull() const;
+
+  /// Member dereference.
+  T* operator -> () const;
+  /// Dereference.
+  T& operator *  () const;
+  /// Access raw pointer.
+  T* get() const;
+
+  /** User conversion to raw pointer.
+
+      @internal allow implicit conversion to the underlying
+      pointer. This allows for the form "if (handle)" and is not
+      particularly dangerous (as it would be for a scope_ptr or
+      shared_ptr) because the counter is carried with the object and
+      so can't get lost or duplicated.
+
+  */
+  operator T* () const;
+
+  /** Cross type construction.
+      This succeeds if an @a X* can be implicitly converted to a @a T*.
+  */
+  template <
+    typename X ///< Foreign pointer type.
+  > IntrusivePtr(
+    IntrusivePtr<X> const& that ///< Foreign pointer.
+  );
+  
+  /** Cross type assignment.
+      This succeeds if an @a X* can be implicitily converted to a @a T*.
+  */
+  template <
+    typename X ///< Foreign pointer type.
+  > self& operator = (
+    IntrusivePtr<X> const& that ///< Foreign pointer.
+  );
+
+  /// Check for multiple references.
+  /// @return @c true if more than one smart pointer references the object,
+  /// @c false otherwise.
+  bool isShared() const;
+  /// Check for a single reference (@c shared_ptr compatibility)
+  /// @return @c true if this object is not shared. 
+  bool unique() const;
+  /// Reference count.
+  /// @return Number of references.
+  Counter useCount() const;
+private:
+  T* m_obj; ///< Pointer to object.
+
+  /// Reference @a obj.
+  void set(
+    T* obj ///< Target object.
+  );
+  /// Drop the current reference.
+  void unset();
+
+  /// Get a pointer to the reference counter of the target object.
+  Counter* getCounter() const;
+};
+
+/** Pointer dynamic cast.
+    This allows a smart pointer to be cast from one type to another.
+    It must be used when the types do not implicitly convert (generally
+    a downcast).
+
+    @code
+    class A { ... };
+    class B : public A { ... };
+    IntrusivePtr<A> really_b(new B);
+    InstruivePtr<B> the_b;
+    the_b = dynamic_ptr_cast<B>(really_b);
+    @endcode
+*/
+template <
+  typename T, ///< Target type.
+  typename X ///< Source type.
+> IntrusivePtr<T> dynamic_ptr_cast(
+  IntrusivePtr<X> const& src ///< Source pointer.
+) {
+  return IntrusivePtr<T>(dynamic_cast<T*>(src.get()));
+}
+
+/** Pointer cast.
+    This allows a smart pointer to be cast from one type to another.
+    It must be used when the types do not implicitly convert (generally
+    a downcast). This uses @c static_cast and so performs only compile
+    time checks.
+
+    @code
+    class A { ... };
+    class B : public A { ... };
+    IntrusivePtr<A> really_b(new B);
+    IntrusivePtr<B> the_b;
+    the_b = ptr_cast<B>(really_b);
+    @endcode
+*/
+template <
+  typename T, ///< Target type.
+  typename X ///< Source type.
+> IntrusivePtr<T> ptr_cast(
+  IntrusivePtr<X> const& src ///< Source pointer.
+) {
+    return IntrusivePtr<T>(static_cast<T*>(src.get()));
+}
+/* ----------------------------------------------------------------------- */
+/* ----------------------------------------------------------------------- */
+/** Default policy class for intrusive pointers.
+
+    This allows per type policy, although not per target instance.
+    Clients can override policy by specializing this class for the
+    target type.
+
+    @code
+    template <> IntrusivePtrPolicy<SomeType>
+      : IntrusivePtrDefaultPolicy {
+     ... Redefinition of methods and nested types ...
+    };
+    @endcode
+
+    The inherited class will provide the default definitions so you can
+    override only what is different. Although this can be omitted if you
+    override everything, it is more robust for maintenance to inherit
+    anyway.
+*/
+
+template <typename T>
+class IntrusivePtrPolicy {
+public:
+  /// Called when the pointer is dereferenced.
+  /// Default is empty (no action).
+  static void dereferenceCheck(
+    T* ///< Target object.
+  );
+
+  /** Perform clean up on a target object that is no longer referenced.
+
+      Default is calling @c delete. Any specialization that overrides this
+      @b must clean up the object. The primary use of this is to perform
+      a clean up other than @c delete.
+
+      @note When this is called, the target object reference count
+      is zero. If it is necessary to pass a smart pointer to the
+      target object, it will be necessary to call
+      @c IntrusivePtr::release to drop the reference without
+      another finalization. Further care must be taken that none of
+      the called logic keeps a copy of the smart pointer. Use with
+      caution.
+  */
+  static void finalize(
+    T* t ///< Target object.
+  );
+  /// Strict weak order for STL containers.
+  class Order
+    : public std::binary_function< IntrusivePtr<T>, IntrusivePtr<T>, bool> {
+  public:
+    /// Default constructor.
+    Order() {
+    }
+    /// Compare by raw pointer.
+    bool operator() (
+      IntrusivePtr<T> const& lhs, ///< Left hand operand.
+      IntrusivePtr<T> const& rhs ///< Right hand operand.
+    ) const; 
+  };
+};
+
+struct IntrusivePtrDefaultPolicyTag {};
+typedef IntrusivePtrPolicy<IntrusivePtrDefaultPolicyTag> IntrusivePtrDefaultPolicy;
+/* ----------------------------------------------------------------------- */
+/* ----------------------------------------------------------------------- */
+/* Inline Methods */
+inline IntrusivePtrCounter::IntrusivePtrCounter()
+  : m_intrusive_pointer_reference_count(0) {
+}
+
+inline IntrusivePtrCounter::IntrusivePtrCounter(IntrusivePtrCounter const&)
+  : m_intrusive_pointer_reference_count(0) {
+}
+
+inline IntrusivePtrCounter&
+IntrusivePtrCounter::operator = (IntrusivePtrCounter const&) {
+  return *this;
+}
+
+inline IntrusivePtrBase::Counter*
+IntrusivePtrBase::getCounter(IntrusivePtrCounter* c) const {
+  return &(c->m_intrusive_pointer_reference_count);
+}
+/* ----------------------------------------------------------------------- */
+/* ----------------------------------------------------------------------- */
+template < typename T > void
+IntrusivePtrPolicy<T>::dereferenceCheck(T*) {
+}
+
+template < typename T > void
+IntrusivePtrPolicy<T>::finalize(T* obj) {
+  delete obj;
+}
+
+template < typename T > bool
+IntrusivePtrPolicy<T>::Order::operator()(
+  IntrusivePtr<T> const& lhs,
+  IntrusivePtr<T> const& rhs
+) const {
+  return lhs.get() < rhs.get();
+}
+/* ----------------------------------------------------------------------- */
+/* ----------------------------------------------------------------------- */
+template < typename T >
+IntrusivePtr<T>::IntrusivePtr()
+  : m_obj(0) {
+}
+
+template < typename T >
+IntrusivePtr<T>::IntrusivePtr(T* obj) {
+  this->set(obj);
+}
+
+template < typename T >
+IntrusivePtr<T>::~IntrusivePtr() {
+  this->unset();
+}
+
+template < typename T >
+IntrusivePtr<T>::IntrusivePtr(const self& that) {
+  this->set(that.m_obj);
+}
+
+template < typename T >
+template < typename X >
+IntrusivePtr<T>::IntrusivePtr(
+  IntrusivePtr<X> const& that ///< Foreign pointer.
+) : super(that.get()) {
+}
+  
+template < typename T > IntrusivePtr<T>&
+IntrusivePtr<T>::operator = (const self& that) {
+  this->reset(that.m_obj);
+  return *this;
+}
+
+template < typename T >
+template < typename X >
+IntrusivePtr<T>&
+IntrusivePtr<T>::operator = (
+  IntrusivePtr<X> const& that ///< Foreign pointer.
+) { 
+  this->reset(that.get());
+  return *this;
+}
+
+template < typename T > IntrusivePtr<T>&
+IntrusivePtr<T>::operator = (T* obj) {
+  this->reset(obj);
+  return *this;
+}
+
+template < typename T > IntrusivePtr<T>&
+IntrusivePtr<T>::assign (T* obj) {
+  return *this = obj;
+}
+
+template < typename T > T*
+IntrusivePtr<T>::operator -> () const {
+  IntrusivePtrPolicy<T>::dereferenceCheck(m_obj);
+  return m_obj;
+}
+
+template < typename T > T&
+IntrusivePtr<T>::operator * () const {
+  IntrusivePtrPolicy<T>::dereferenceCheck(m_obj);
+  return *m_obj;
+}
+
+template < typename T > T*
+IntrusivePtr<T>::get() const {
+  IntrusivePtrPolicy<T>::dereferenceCheck(m_obj);
+  return m_obj;
+}
+
+template < typename T > typename IntrusivePtr<T>::Counter*
+IntrusivePtr<T>::getCounter() const {
+  return super::getCounter(static_cast<IntrusivePtrCounter*>(m_obj));
+}
+
+/* The Set/Unset methods are the basic implementation of our
+ * reference counting. The Reset method is the standard way
+ * of invoking the pair, although splitting them allows some
+ * additional efficiency in certain situations.
+ */
+
+/* set and unset are two half operations that don't do checks.
+   It is the callers responsibility to do that.
+*/
+
+template < typename T > void
+IntrusivePtr<T>::unset() {
+  if (0 != m_obj) {
+    /* magic: our target is required to inherit from IntrusivePtrCounter,
+     * which provides a protected counter variable and access via our
+     * super class. We call the super class method to get a raw pointer
+     * to the counter variable.
+     */
+    Counter* cp = this->getCounter();
+
+    /* If you hit this assert you've got a cycle of objects that
+       reference each other. A delete in the cycle will eventually
+       result in one of the objects getting deleted twice, which is
+       what this assert indicates.
+    */
+    assert(*cp);
+
+    if (0 == --*cp) {
+      IntrusivePtrPolicy<T>::finalize(m_obj);
+    }
+    m_obj = 0;
+  }
+}
+
+template < typename T > void
+IntrusivePtr<T>::set(T* obj) {
+  m_obj = obj;	/* update to new object */
+  if (0 != m_obj) /* if a real object, bump the ref count */
+    ++(*(this->getCounter()));
+}
+
+template < typename T > void
+IntrusivePtr<T>::reset(T* obj) {
+  if (obj != m_obj) {
+    this->unset();
+    this->set(obj);
+  }
+}
+
+template < typename T > bool
+IntrusivePtr<T>::release() {
+  bool zret = true;
+  if (m_obj) {
+    Counter* cp = this->getCounter();
+    zret = *cp <= 1;
+    // If the client is using this method, they're doing something funky
+    // so be extra careful with the reference count.
+    if (*cp > 0) --*cp;
+    m_obj = 0;
+  }
+  return zret;
+}
+
+/* Simple method to check for invalid pointer */
+template < typename T > bool
+IntrusivePtr<T>::isNull() const {
+  return 0 == m_obj;
+}
+
+/* Pointer comparison */
+template < typename T > bool
+operator == (IntrusivePtr<T> const& lhs, IntrusivePtr<T> const& rhs) {
+  return lhs.get() == rhs.get();
+}
+
+template < typename T > bool
+operator != (IntrusivePtr<T> const& lhs, IntrusivePtr<T> const& rhs) {
+  return lhs.get() != rhs.get();
+}
+
+template < typename T > bool
+operator < (IntrusivePtr<T> const& lhs, IntrusivePtr<T> const& rhs) {
+  return lhs.get() < rhs.get();
+}
+
+template < typename T > bool
+operator == (IntrusivePtr<T> const& lhs, int rhs) {
+  assert(0 == rhs);
+  return lhs.get() == 0;
+}
+
+template < typename T > bool
+operator == (int lhs, IntrusivePtr<T> const& rhs) {
+  assert(0 == lhs);
+  return rhs.get() == 0;
+}
+
+template < typename T > bool
+operator != (int lhs, IntrusivePtr<T> const& rhs) {
+  return !(lhs == rhs);
+}
+
+template < typename T > bool
+operator != (IntrusivePtr<T> const& lhs, int rhs) {
+  return !(lhs == rhs);
+}
+
+template < typename T >
+IntrusivePtr<T>::operator T* () const {
+  return m_obj;
+}
+
+template < typename T> bool
+IntrusivePtr<T>::isShared() const {
+  return m_obj && *(this->getCounter()) > 1;
+}
+
+template < typename T> bool
+IntrusivePtr<T>::unique() const {
+  return 0 == m_obj || *(this->getCounter()) <= 1;
+}
+
+template < typename T> typename IntrusivePtr<T>::Counter
+IntrusivePtr<T>::useCount() const {
+  return m_obj ? *(this->getCounter()) : 0;
+}
+/* ----------------------------------------------------------------------- */
+/* ----------------------------------------------------------------------- */
+} // namespace ats
+/* ----------------------------------------------------------------------- */
+# endif // ATS_INTRUSIVE_PTR_HEADER
+

Added: trafficserver/traffic/branches/wccp/proxy/tsconfig/Makefile.am
URL: http://svn.apache.org/viewvc/trafficserver/traffic/branches/wccp/proxy/tsconfig/Makefile.am?rev=1037235&view=auto
==============================================================================
--- trafficserver/traffic/branches/wccp/proxy/tsconfig/Makefile.am (added)
+++ trafficserver/traffic/branches/wccp/proxy/tsconfig/Makefile.am Sat Nov 20 15:17:55 2010
@@ -0,0 +1,51 @@
+#
+# Makefile.am for TS Config module.
+#
+#  Licensed to the Apache Software Foundation (ASF) under one
+#  or more contributor license agreements.  See the NOTICE file
+#  distributed with this work for additional information
+#  regarding copyright ownership.  The ASF licenses this file
+#  to you under the Apache License, Version 2.0 (the
+#  "License"); you may not use this file except in compliance
+#  with the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+
+AM_CPPFLAGS = \
+  -I$(top_srcdir)/proxy/mgmt2/api2/include \
+  -DPKGSYSUSER=\"$(pkgsysuser)\"
+
+noinst_LIBRARIES = libtsconfig.a
+#noinst_PROGRAMS = test-cache
+
+libtsconfig_a_SOURCES = \
+  Errata.cc \
+  Errata.h \
+  TsErrataUtil.cc \
+  TsErrata.h \
+  TsBuffer.h \
+  NumericType.h \
+  IntrusivePtr.h \
+  TsBuilder.cc \
+  TsBuilder.h \
+  TsValue.cc \
+  TsValue.h \
+  TsConfig.tab.c \
+  TsConfig.lex.c
+
+TsConfig.tab.c: TsConfig.y
+	bison -d --name-prefix tsconfig TsConfig.y
+
+TsConfig.lex.c: TsConfig.flex
+	flex --outfile TsConfig.lex.c TsConfig.flex
+
+#test_cache_SOURCES = \
+#  wccp-test-cache.cc
+
+#test_cache_LDADD = ./libwccp.a -lconfig++ -lcrypto
\ No newline at end of file

Added: trafficserver/traffic/branches/wccp/proxy/tsconfig/NumericType.h
URL: http://svn.apache.org/viewvc/trafficserver/traffic/branches/wccp/proxy/tsconfig/NumericType.h?rev=1037235&view=auto
==============================================================================
--- trafficserver/traffic/branches/wccp/proxy/tsconfig/NumericType.h (added)
+++ trafficserver/traffic/branches/wccp/proxy/tsconfig/NumericType.h Sat Nov 20 15:17:55 2010
@@ -0,0 +1,163 @@
+/*      Copyright (c) 2006-2010 Network Geographics.
+ *      All rights reserved.
+ *      Licensed to the Apache Software Foundation.
+ */
+/* ------------------------------------------------------------------------ */
+# if !defined(TS_NUMERIC_TYPE_HEADER)
+# define TS_NUMERIC_TYPE_HEADER
+
+# include <limits>
+/* ----------------------------------------------------------------------- */
+namespace ts {
+/* ----------------------------------------------------------------------- */
+/** @file
+
+    Create a distinct type from a builtin numeric type.
+
+    This template class converts a basic type into a class, so that
+    instances of the class act like the basic type in normal use but
+    as a distinct type when evaluating overloads. This is very handy
+    when one has several distinct value types that map to the same
+    basic type. That means we can have overloads based on the type
+    even though the underlying basic type is the same. The second
+    template argument, X, is used only for distinguishing
+    instantiations of the template with the same base type. It doesn't
+    have to exist. One can declare an instantiation like
+
+    @code
+    typedef NumericType<int, struct some_random_tag_name> some_random_type;
+    @endcode
+
+    It is not necessary to ever mention some_random_tag_name
+    again. All we need is the entry in the symbol table.
+ */
+
+// Forward declare.
+template < typename T, typename X > class NumericType;
+
+/// @cond NOT_DOCUMENTED
+/** Support template for resolving operator ambiguity.
+
+    Not for client use.
+
+    @internal This resolves the problem when @a T is not @c int.
+    In that case, because raw numbers are @c int and the overloading
+    rule changes created an ambiguity, gcc won't distinguish between
+    class methods and builtins because @c NumericType has a user
+    conversion to @a T. So signature <tt>(NumericType, T)</tt>
+    and <tt>(T, int)</tt> are considered equivalent. This defines
+    the @c int operators explicitly. We inherit it so if @a T is
+    @c int, these are silently overridden.
+
+    @internal Note that we don't have to provide an actual implementation
+    for these operators. Funky, isn't it?
+*/
+template <
+  typename T, ///< Base numeric type.
+  typename X ///< Distinguishing tag type.
+> class NumericType_int_operators {
+public:
+    NumericType<T,X>& operator += ( int t );
+    NumericType<T,X>& operator -= ( int t );
+
+    // Must have const and non-const versions.
+    NumericType<T,X> operator +  ( int t );
+    NumericType<T,X> operator -  ( int t );
+    NumericType<T,X> operator +  ( int t ) const;
+    NumericType<T,X> operator -  ( int t ) const;
+};
+
+template < typename T, typename X > NumericType<T,X>
+operator + ( int t, NumericType_int_operators<T,X> const& );
+
+template < typename T, typename X > NumericType<T,X>
+operator - ( int t, NumericType_int_operators<T,X> const& );
+
+/// @endcond
+
+/** Numeric type template.
+ */
+template <
+  typename T, ///< Base numeric type.
+  typename X ///< Distinguishing tag type.
+> class NumericType : public NumericType_int_operators<T,X> {
+public:
+    typedef T raw_type; //!< Base builtin type.
+    typedef NumericType self; //!< Self reference type.
+
+    using NumericType_int_operators<T,X>::operator +=;
+    using NumericType_int_operators<T,X>::operator -=;
+    using NumericType_int_operators<T,X>::operator +;
+    using NumericType_int_operators<T,X>::operator -;
+
+    /// Default constructor, uninitialized.
+    NumericType();
+    //! Construct from implementation type.
+    NumericType(
+      raw_type const t ///< Initialized value.
+    );
+    //! Assignment from implementation type.
+    NumericType & operator = (raw_type const t);
+    //! Self assignment.
+    NumericType & operator = (self const& that);
+
+    /// User conversion to implementation type.
+    /// @internal If we have just a single const method conversion to a copy
+    /// of the @c raw_type then the stream operators don't work. Only a CR
+    /// conversion operator satisifies the argument matching.
+    operator raw_type const& () const { return _t; }
+    /// User conversion to implementation type.
+    operator raw_type& () { return _t; }
+    /// Explicit conversion to host type
+    raw_type raw() const { return _t; }
+
+    // User conversions to raw type provide the standard comparison operators.
+    self& operator += ( self const& that );
+    self& operator -= ( self const& that );
+
+    self& operator += ( raw_type t );
+    self& operator -= ( raw_type t );
+
+    self operator +  ( self const& that );
+    self operator -  ( self const& that );
+
+    self operator +  ( raw_type t );
+    self operator -  ( raw_type t );
+
+    self& operator ++();
+    self operator ++(int);
+    self& operator --();
+    self operator --(int);
+
+private:
+    raw_type   _t;
+};
+
+// Method definitions.
+template < typename T, typename X > NumericType<T,X>::NumericType() { }
+template < typename T, typename X > NumericType<T,X>::NumericType(raw_type const t) : _t(t) { }
+template < typename T, typename X > NumericType<T,X>& NumericType<T,X>::operator = (raw_type const t) { _t = t; return *this; }
+template < typename T, typename X > NumericType<T,X>& NumericType<T,X>::operator = (self const& that) { _t = that._t; return *this; }
+
+template < typename T, typename X > NumericType<T,X>& NumericType<T,X>::operator += ( self const& that ) { _t += that._t; return *this; }
+template < typename T, typename X > NumericType<T,X>& NumericType<T,X>::operator -= ( self const& that ) { _t -= that._t; return *this; }
+template < typename T, typename X > NumericType<T,X> NumericType<T,X>::operator +  ( self const& that ) { return self(_t + that._t); }
+template < typename T, typename X > NumericType<T,X> NumericType<T,X>::operator -  ( self const& that ) { return self(_t - that._t); }
+
+template < typename T, typename X > NumericType<T,X>& NumericType<T,X>::operator += ( raw_type t ) { _t += t; return *this; }
+template < typename T, typename X > NumericType<T,X>& NumericType<T,X>::operator -= ( raw_type t ) { _t -= t; return *this; }
+template < typename T, typename X > NumericType<T,X> NumericType<T,X>::operator +  ( raw_type t ) { return self(_t + t); }
+template < typename T, typename X > NumericType<T,X> NumericType<T,X>::operator -  ( raw_type t ) { return self(_t - t); }
+
+template < typename T, typename X > NumericType<T,X>& NumericType<T,X>::operator ++() { ++_t; return *this; }
+template < typename T, typename X > NumericType<T,X>& NumericType<T,X>::operator --() { --_t; return *this; }
+template < typename T, typename X > NumericType<T,X> NumericType<T,X>::operator ++(int) { self tmp(*this); ++_t; return tmp; }
+template < typename T, typename X > NumericType<T,X> NumericType<T,X>::operator --(int) { self tmp(*this); --_t; return tmp; }
+
+template < typename T, typename X > NumericType<T,X> operator +  ( T const& lhs, NumericType<T,X> const& rhs ) { return rhs + lhs; }
+template < typename T, typename X > NumericType<T,X> operator -  ( T const& lhs, NumericType<T,X> const& rhs ) { return NumericType<T,X>(lhs - rhs.raw()); }
+
+/* ----------------------------------------------------------------------- */
+} /* end namespace ts */
+/* ----------------------------------------------------------------------- */
+# endif // TS_NUMERIC_TYPE_HEADER

Added: trafficserver/traffic/branches/wccp/proxy/tsconfig/TsBuffer.h
URL: http://svn.apache.org/viewvc/trafficserver/traffic/branches/wccp/proxy/tsconfig/TsBuffer.h?rev=1037235&view=auto
==============================================================================
--- trafficserver/traffic/branches/wccp/proxy/tsconfig/TsBuffer.h (added)
+++ trafficserver/traffic/branches/wccp/proxy/tsconfig/TsBuffer.h Sat Nov 20 15:17:55 2010
@@ -0,0 +1,156 @@
+/** @file
+    Apach Traffic Server commons.
+    Definitions that are standardized across ATS.
+ */
+
+# if defined _MSC_VER
+# include <stddef.h>
+# else
+# include <unistd.h>
+# endif
+# include <memory.h>
+
+/// Apache Traffic Server commons.
+namespace ts {
+  struct ConstBuffer;
+  /** A chunk of writable memory.
+      A convenience class because we pass this kind of pair frequently.
+   */
+  struct Buffer {
+    typedef Buffer self; ///< Self reference type.
+
+    char * _ptr; ///< Pointer to base of memory chunk.
+    size_t _size; ///< Size of memory chunk.
+
+    /// Default constructor.
+    /// Elements are in uninitialized state.
+    Buffer();
+
+    /// Construct from pointer and size.
+    Buffer(
+      char* ptr, ///< Pointer to buffer.
+      size_t n ///< Size of buffer.
+    );
+
+    /** Equality.
+        @return @c true if the @c Buffer instances are identical,
+        @c false otherwise.
+     */
+    bool operator == (self const& that) const;
+    /** Inequality.
+        @return @c true if the @c Buffer instances are different,
+        @c false otherwise.
+     */
+    bool operator != (self const& that) const;
+    /** Equality for a constant buffer.
+        @return @c true if @a that contains identical contents.
+        @c false otherwise.
+     */
+    bool operator == (ConstBuffer const& that) const;
+    /** Inequality.
+        @return @c true if the instances have different content,
+        @c false if they are identical.
+     */
+    bool operator != (ConstBuffer const& that) const;
+
+    /// Set the chunk.
+    /// Any previous values are discarded.
+    /// @return @c this object.
+    self& set(
+      char* ptr, ///< Buffer address.
+      size_t n ///< Buffer size.
+    );
+    /// Reset to empty.
+    self& reset();
+  };
+
+  /** A chunk of read only memory.
+      A convenience class because we pass this kind of pair frequently.
+   */
+  struct ConstBuffer {
+    typedef ConstBuffer self; ///< Self reference type.
+
+    char const * _ptr; ///< Pointer to base of memory chunk.
+    size_t _size; ///< Size of memory chunk.
+
+    /// Default constructor.
+    /// Elements are in uninitialized state.
+    ConstBuffer();
+
+    /// Construct from pointer and size.
+    ConstBuffer(
+      char const * ptr, ///< Pointer to buffer.
+      size_t n ///< Size of buffer.
+    );
+    /// Construct from writable buffer.
+    ConstBuffer(
+        Buffer const& buffer ///< Buffer to copy.
+    );
+
+    /** Equality.
+        @return @c true if the @c Buffer instances are identical,
+        @c false otherwise.
+     */
+    bool operator == (self const& that) const;
+    /** Equality.
+        @return @c true if the @c Buffer instances are identical,
+        @c false otherwise.
+     */
+    bool operator == (Buffer const& that) const;
+    /** Inequality.
+        @return @c true if the @c Buffer instances are different,
+        @c false otherwise.
+     */
+    bool operator != (self const& that) const;
+    /** Inequality.
+        @return @c true if the @c Buffer instances are different,
+        @c false otherwise.
+     */
+    bool operator != (Buffer const& that) const;
+    /// Assign from non-const Buffer.
+    self& operator = (
+        Buffer const& that ///< Source buffer.
+    );
+
+    /// Set the chunk.
+    /// Any previous values are discarded.
+    /// @return @c this object.
+    self& set(
+      char const * ptr, ///< Buffer address.
+      size_t n ///< Buffer size.
+    );
+    /// Reset to empty.
+    self& reset();
+  };
+
+  // ----------------------------------------------------------
+  // Inline implementations.
+
+  inline Buffer::Buffer() { }
+  inline Buffer::Buffer(char* ptr, size_t n) : _ptr(ptr), _size(n) { }
+  inline Buffer& Buffer::set(char* ptr, size_t n) { _ptr = ptr; _size = n; return *this; }
+  inline Buffer& Buffer::reset() { _ptr = 0; _size = 0 ; return *this; }
+  inline bool Buffer::operator != (self const& that) const { return ! (*this == that); }
+  inline bool Buffer::operator != (ConstBuffer const& that) const { return ! (*this == that); }
+  inline bool Buffer::operator == (self const& that) const {
+      return _size == that._size && 0 == memcmp(_ptr, that._ptr, _size);
+  }
+  inline bool Buffer::operator == (ConstBuffer const& that) const {
+      return _size == that._size && 0 == memcmp(_ptr, that._ptr, _size);
+  }
+
+  inline ConstBuffer::ConstBuffer() { }
+  inline ConstBuffer::ConstBuffer(char const* ptr, size_t n) : _ptr(ptr), _size(n) { }
+  inline ConstBuffer::ConstBuffer(Buffer const& that) : _ptr(that._ptr), _size(that._size) { }
+  inline ConstBuffer& ConstBuffer::set(char const* ptr, size_t n) { _ptr = ptr; _size = n; return *this; }
+  inline ConstBuffer& ConstBuffer::reset() { _ptr = 0; _size = 0 ; return *this; }
+  inline bool ConstBuffer::operator != (self const& that) const { return ! (*this == that); }
+  inline bool ConstBuffer::operator != (Buffer const& that) const { return ! (*this == that); }
+  inline bool ConstBuffer::operator == (self const& that) const {
+      return _size == that._size && 0 == memcmp(_ptr, that._ptr, _size);
+  }
+  inline ConstBuffer& ConstBuffer::operator = (Buffer const& that) { _ptr = that._ptr ; _size = that._size; return *this; }
+  inline bool ConstBuffer::operator == (Buffer const& that) const {
+      return _size == that._size && 0 == memcmp(_ptr, that._ptr, _size);
+  }
+}

Added: trafficserver/traffic/branches/wccp/proxy/tsconfig/TsBuilder.cc
URL: http://svn.apache.org/viewvc/trafficserver/traffic/branches/wccp/proxy/tsconfig/TsBuilder.cc?rev=1037235&view=auto
==============================================================================
--- trafficserver/traffic/branches/wccp/proxy/tsconfig/TsBuilder.cc (added)
+++ trafficserver/traffic/branches/wccp/proxy/tsconfig/TsBuilder.cc Sat Nov 20 15:17:55 2010
@@ -0,0 +1,157 @@
+# include "TsBuilder.h"
+# include <TsErrataUtil.h>
+# include "TsConfigLexer.h"
+
+// Access to terminal token values.
+extern "C" {
+# include "TsConfig.tab.h"
+};
+
+# define PRE "Configuration Parser: "
+
+namespace ts { namespace config {
+
+Builder&
+Builder::init() {
+    // Simple: Resize the vector and then fill in each element to
+    // dispatch through the static method. Callback data is a pointer
+    // to an entry in @c dispatch which contains pointer to this object
+    // and a pointer to the appropriate dispatch method.
+
+    _dispatch.resize(TS_CONFIG_N_EVENT_TYPES);
+
+    for ( size_t i = 0 ; i < TS_CONFIG_N_EVENT_TYPES ; ++i) {
+        _dispatch[i]._ptr = this;
+        _handlers.handler[i]._f = &self::dispatch;
+        _handlers.handler[i]._data = &(_dispatch[i]);
+    }
+
+    _dispatch[TsConfigEventGroupOpen]._method = &self::groupOpen;
+    _dispatch[TsConfigEventGroupName]._method = &self::groupName;
+    _dispatch[TsConfigEventGroupClose]._method = &self::groupClose;
+    _dispatch[TsConfigEventListOpen]._method = &self::listOpen;
+    _dispatch[TsConfigEventListClose]._method = &self::listClose;
+    _dispatch[TsConfigEventPathOpen]._method = &self::pathOpen;
+    _dispatch[TsConfigEventPathTag]._method = &self::pathTag;
+    _dispatch[TsConfigEventPathIndex]._method = &self::pathIndex;
+    _dispatch[TsConfigEventPathClose]._method = &self::pathClose;
+    _dispatch[TsConfigEventLiteralValue]._method = &self::literalValue;
+    _dispatch[TsConfigEventInvalidToken]._method = &self::invalidToken;
+
+    _handlers.error._data = this;
+    _handlers.error._f = &self::syntaxErrorDispatch;
+
+    return *this;
+}
+
+// Error messages here have to just be logged, as they effectively report that
+// the dispatcher can't find the builder object.
+void
+Builder::dispatch(void* data, Token* token) {
+    if (data) {
+        Handler* handler = reinterpret_cast<Handler*>(data);
+        if (handler->_ptr) {
+            if (handler->_method) {
+                ((handler->_ptr)->*(handler->_method))(*token);
+            } else {
+                msg::logf(msg::WARN, PRE "Unable to dispatch event - no method.");
+            }
+        } else {
+            msg::logf(msg::WARN, PRE "Unable to dispatch event - no builder.");
+        }
+    } else {
+        msg::logf(msg::WARN, PRE "Unable to dispatch event - no handler.");
+    }
+}
+
+int
+Builder::syntaxErrorDispatch(void* data, char const* text) {
+    return reinterpret_cast<Builder*>(data)->syntaxError(text);
+}
+
+int
+Builder::syntaxError(char const* text) {
+    msg::logf(_errata, msg::WARN, "Syntax error '%s'.", text);
+    return 0;
+}
+
+Rv<Configuration>
+Builder::build(Buffer const& buffer) {
+    yyscan_t lexer;
+    YY_BUFFER_STATE lexer_buffer_state;
+
+    _v = _config.getRoot();
+    _errata.clear();
+
+    tsconfiglex_init(&lexer);
+    tsconfigset_extra(&_handlers, lexer);
+    lexer_buffer_state = tsconfig_scan_buffer(buffer._ptr, buffer._size, lexer);
+    tsconfigparse(lexer, &_handlers);
+    tsconfig_delete_buffer(lexer_buffer_state, lexer);
+    tsconfiglex_destroy(lexer);
+
+    return MakeRv(_config, _errata);
+}
+
+void
+Builder::groupOpen(Token const&) {
+    _v = _v.makeGroup(_name);
+}
+void Builder::groupClose(Token const&) {
+    _v = _v.getParent();
+}
+void Builder::groupName(Token const& token) {
+    _name.set(token._s, token._n);
+}
+void Builder::listOpen(Token const&) {
+    _v = _v.makeList(_name);
+}
+void Builder::listClose(Token const&) {
+    _v = _v.getParent();
+}
+
+void Builder::pathOpen(Token const&) {
+    _path.reset();
+    _extent.reset();
+}
+void Builder::pathTag(Token const& token) {
+    _path.append(Buffer(token._s, token._n));
+    if (_extent._ptr) _extent._size = token._s - _extent._ptr + token._n;
+    else _extent.set(token._s, token._n);
+}
+void Builder::pathIndex(Token const& token){
+    // We take advantage of the lexer - token will always be a valid digit string
+    // that is followed by a non-digit or the FLEX required double null at the end
+    // of the input buffer.
+    _path.append(Buffer(0, static_cast<size_t>(atol(token._s))));
+    if (_extent._ptr) _extent._size = token._s - _extent._ptr + token._n;
+    else _extent.set(token._s, token._n);
+}
+
+void Builder::pathClose(Token const&) {
+    Rv<Value> cv = _v.makePath(_path, _name);
+    if (cv.isOK()) cv.result().setText(_extent);
+
+    _name.reset();
+    _extent.reset();
+}
+
+void Builder::literalValue(Token const& token) {
+    Rv<Value> cv;
+    ConstBuffer text(token._s, token._n);
+    if (INTEGER == token._type) {
+        cv = _v.makeInteger(text, _name);
+        if (!cv.isOK()) _errata.join(cv.errata());
+    } else if (STRING == token._type) {
+        ++text._ptr, text._size -= 2;
+        cv = _v.makeString(text, _name);
+        // Strip enclosing quotes.
+        if (!cv.isOK()) _errata.join(cv.errata());
+    } else {
+        msg::logf(_errata, msg::WARN, PRE "Unexpected literal type %d.", token._type);
+    }
+    _name.set(0,0); // used, so clear it.
+}
+void Builder::invalidToken(Token const&) { }
+
+}} // namespace ts::config

Added: trafficserver/traffic/branches/wccp/proxy/tsconfig/TsBuilder.h
URL: http://svn.apache.org/viewvc/trafficserver/traffic/branches/wccp/proxy/tsconfig/TsBuilder.h?rev=1037235&view=auto
==============================================================================
--- trafficserver/traffic/branches/wccp/proxy/tsconfig/TsBuilder.h (added)
+++ trafficserver/traffic/branches/wccp/proxy/tsconfig/TsBuilder.h Sat Nov 20 15:17:55 2010
@@ -0,0 +1,75 @@
+# if ! defined(TS_CONFIG_BUILDER_HEADER)
+# define TS_CONFIG_BUILDER_HEADER
+
+# include "TsValue.h"
+# include "TsConfigTypes.h"
+# include "TsConfigParseEvents.h"
+
+namespace ts { namespace config {
+
+/** Class to build the configuration table from parser events.
+ */
+class Builder {
+public:
+    typedef Builder self;
+    struct Handler {
+        self* _ptr; ///< Pointer to Builder instance.
+        /// Pointer to method to invoke for this event.
+        void (self::*_method)(Token const& token);
+
+        /// Default constructor.
+        Handler();
+    };
+
+    /// Default constructor.
+    Builder();
+    /// Construct with existing configuration.
+    Builder(Configuration const& config);
+    /// Build the table.
+    /// @return The configuration or error status.
+    Rv<Configuration> build(
+        Buffer const& buffer ///< Input text.
+    );
+protected:
+    /// Dispatch table for parse events.
+    std::vector<Handler> _dispatch;
+    /// Event handler table for the parser.
+    TsConfigHandlers _handlers;
+    /// Dispatch methods
+    virtual void groupOpen(Token const& token);
+    virtual void groupClose(Token const& token);
+    virtual void groupName(Token const& token);
+    virtual void listOpen(Token const& token);
+    virtual void listClose(Token const& token);
+    virtual void pathOpen(Token const& token);
+    virtual void pathTag(Token const& token);
+    virtual void pathIndex(Token const& token);
+    virtual void pathClose(Token const& token);
+    virtual void literalValue(Token const& token);
+    virtual void invalidToken(Token const& token);
+    /// Syntax error handler
+    virtual int syntaxError(char const* text);
+    /// Static method to handle parser event callbacks.
+    static void dispatch(void* data, Token* token);
+    /// Static method for syntax errors.
+    static int syntaxErrorDispatch(void* data, char const* text);
+
+    // Building state.
+    Configuration _config; ///< Configuration to update.
+    Errata _errata; ///< Error accumulator.
+    Value _v; ///< Current value.
+    Buffer _name; ///< Pending group name, if any.
+    Buffer _extent; ///< Accumulator for multi-token text.
+    Path _path; ///< Path accumulator
+
+    /// Initialization, called from constructors.
+    self& init();
+};
+
+inline Builder::Handler::Handler() : _ptr(0), _method(0) { }
+inline Builder::Builder() { this->init(); }
+inline Builder::Builder(Configuration const& config) : _config(config) { this->init(); }
+
+}} // namespace ts::config
+
+# endif // TS_CONFIG_BUILDER_HEADER

Added: trafficserver/traffic/branches/wccp/proxy/tsconfig/TsConfig.flex
URL: http://svn.apache.org/viewvc/trafficserver/traffic/branches/wccp/proxy/tsconfig/TsConfig.flex?rev=1037235&view=auto
==============================================================================
--- trafficserver/traffic/branches/wccp/proxy/tsconfig/TsConfig.flex (added)
+++ trafficserver/traffic/branches/wccp/proxy/tsconfig/TsConfig.flex Sat Nov 20 15:17:55 2010
@@ -0,0 +1,58 @@
+%{
+
+#include "TsConfigTypes.h"
+#include "TsConfig.tab.h"
+#include "TsConfigParseEvents.h"
+
+struct Location Lex_Location = { 0, 1 };
+
+# define YY_USER_ACTION Lex_Location._col += yyleng;
+
+# define FILL yylval->_s = yytext; yylval->_n = yyleng; yylval->_loc = Lex_Location; yylval->_loc._col -= yyleng;
+# define ZRET(t) FILL; yylval->_type = t; return t;
+# define HANDLE_EVENT(x) \
+	if (yyextra) { \
+		struct TsConfigEventHandler* h = &(yyextra->handler[TsConfigEvent##x]); \
+		if (h->_f) h->_f(h->_data, yylval); \
+	}
+%}
+
+%option header-file="TsConfig.lex.h"
+%option never-interactive yylineno reentrant bison-bridge noyywrap
+%option prefix="tsconfig"
+%option nounput noinput
+%option extra-type="struct TsConfigHandlers*"
+
+DSTRING		\"(?:[^\"\\]|\\.)*\"
+SSTRING		'(?:[^'\\]|\\.)*'
+QSTRING		{DSTRING}|{SSTRING}
+IDENT		[[:alpha:]_](?:-*[[:alnum:]_])*
+
+%x		bad
+%%
+\n		    ++(Lex_Location._line); Lex_Location._col = 0;
+(?:[[:space:]]{-}[\n])+
+^[[:space:]]*#.*$
+\/\/.*$
+{QSTRING}	ZRET(STRING);
+{IDENT}		ZRET(IDENT);
+[[:digit:]]+	ZRET(INTEGER);
+\{          ZRET(GROUP_OPEN);
+\}          ZRET(GROUP_CLOSE);
+\(          ZRET(LIST_OPEN);
+\)          ZRET(LIST_CLOSE);
+\<          ZRET(PATH_OPEN);
+\>          ZRET(PATH_CLOSE);
+\.          ZRET(PATH_SEPARATOR);
+=           ZRET(ASSIGN);
+[,;]+		ZRET(SEPARATOR);
+
+.           BEGIN(bad); FILL;
+<bad>\n		{
+		        BEGIN(0); // Terminate bad token mode.
+		        ++(Lex_Location._line); // Must bump line count.
+		        HANDLE_EVENT(InvalidToken);
+            }
+<bad>[[:space:]]  BEGIN(0); HANDLE_EVENT(InvalidToken);
+<bad>.      ++(yylval->_n);
+%%

Added: trafficserver/traffic/branches/wccp/proxy/tsconfig/TsConfig.y
URL: http://svn.apache.org/viewvc/trafficserver/traffic/branches/wccp/proxy/tsconfig/TsConfig.y?rev=1037235&view=auto
==============================================================================
--- trafficserver/traffic/branches/wccp/proxy/tsconfig/TsConfig.y (added)
+++ trafficserver/traffic/branches/wccp/proxy/tsconfig/TsConfig.y Sat Nov 20 15:17:55 2010
@@ -0,0 +1,81 @@
+%code top {
+# include "TsConfigTypes.h"
+
+// Inhibit Bison definitions.
+# define YYMALLOC malloc
+# define YYFREE free
+
+# include "TsConfigParseEvents.h"
+# include "TsConfig.lex.h"
+}
+
+%code {
+# define HANDLE_EVENT(x,y) if (handlers) { \
+                             struct TsConfigEventHandler* h = &(handlers->handler[TsConfigEvent##x]); \
+                             if (h->_f) h->_f(h->_data, &(y)); \
+                           }
+
+int tsconfigerror(yyscan_t lexer, struct TsConfigHandlers* handlers, char const* text) {
+	return (handlers && handlers->error._f) ? handlers->error._f(handlers->error._data, text) : 0;
+}
+
+}
+
+%token STRING
+%token IDENT
+%token INTEGER
+%token LIST_OPEN
+%token LIST_CLOSE
+%token GROUP_OPEN
+%token GROUP_CLOSE
+%token PATH_OPEN
+%token PATH_CLOSE
+%token PATH_SEPARATOR
+%token SEPARATOR
+%token ASSIGN
+
+%error-verbose
+%define api.pure
+%parse-param { yyscan_t lexer }
+%parse-param { struct TsConfigHandlers* handlers }
+%lex-param { yyscan_t lexer }
+
+%%
+
+config: group_items;
+
+group: group_open group_items group_close ;
+
+group_open: GROUP_OPEN { HANDLE_EVENT(GroupOpen, $1); } ;
+
+group_close: GROUP_CLOSE { HANDLE_EVENT(GroupClose, $1); } ;
+
+group_items: /* empty */ | group_items assign separator | group_items error separator ;
+
+assign: IDENT ASSIGN { HANDLE_EVENT(GroupName, $1); } value ;
+
+list: list_open list_items list_close ;
+
+list_open: LIST_OPEN { HANDLE_EVENT(ListOpen, $1); } ;
+
+list_close: LIST_CLOSE { HANDLE_EVENT(ListClose, $1); } ;
+
+list_items: /* empty */ | list_items value separator | list_items error separator;
+
+value: literal { HANDLE_EVENT(LiteralValue, $1); } | list | group | path;
+
+literal: STRING | IDENT | INTEGER ;
+
+separator: /* empty */ | SEPARATOR ;
+
+path: path_open path_item path_close;
+
+path_open: PATH_OPEN { HANDLE_EVENT(PathOpen, $1); }
+
+path_close: PATH_CLOSE { HANDLE_EVENT(PathClose, $1); }
+
+path_item: path_tag | path_item PATH_SEPARATOR path_tag ;
+
+path_tag: IDENT { HANDLE_EVENT(PathTag, $1); } | INTEGER { HANDLE_EVENT(PathIndex, $1); };
+
+%%