text: /** @file
  
    A brief file description
  
    @section license License
  
    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.
   */
  
  
  #ifndef LOG_FIELD_H
  #define LOG_FIELD_H
  
  #include "ts/ink_platform.h"
  #include "ts/List.h"
  #include "LogFieldAliasMap.h"
  #include "StatSystem.h"
  
  class LogAccess;
  
  struct LogSlice {
    bool m_enable;
    int m_start;
    int m_end;
  
    LogSlice()
    {
      m_enable = false;
      m_start = 0;
      m_end = INT_MAX;
    }
  
    //
    // Initialize LogSlice by slice notation,
    // the str looks like: "xxx[0:30]".
    //
    LogSlice(char *str);
  
    //
    // Convert slice notation to target string's offset,
    // return the available length belongs to this slice.
    //
    // Use the offset and return value, we can locate the
    // string content indicated by this slice.
    //
    int toStrOffset(int strlen, int *offset);
  };
  
  
  /*-------------------------------------------------------------------------
    LogField
  
    This class represents a field that can be logged.  To construct a new
    field, we need to know its name, its symbol, its datatype, and the
    pointer to its LogAccess marshalling routine.  Example:
  
        LogField ("client_host_ip", "chi", LogField::INT,
                  &LogAccess::marshal_client_host_ip);
    -------------------------------------------------------------------------*/
  
  class LogField
  {
  public:
    typedef int (LogAccess::*MarshalFunc)(char *buf);
    typedef int (*UnmarshalFunc)(char **buf, char *dest, int len);
    typedef int (*UnmarshalFuncWithSlice)(char **buf, char *dest, int len, LogSlice *slice);
    typedef int (*UnmarshalFuncWithMap)(char **buf, char *dest, int len, Ptr<LogFieldAliasMap> map);
    typedef void (LogAccess::*SetFunc)(char *buf, int len);
  
  
    enum Type {
      sINT = 0,
      dINT,
      STRING,
      IP, ///< IP Address.
      N_TYPES
    };
  
    enum Container {
      NO_CONTAINER = 0,
      CQH,
      PSH,
      PQH,
      SSH,
      CSSH,
      ECQH,
      EPSH,
      EPQH,
      ESSH,
      ECSSH,
      ICFG,
      SCFG,
      RECORD,
      MS,
      MSDMS,
      N_CONTAINERS,
    };
  
    enum Aggregate {
      NO_AGGREGATE = 0,
      eCOUNT,
      eSUM,
      eAVG,
      eFIRST,
      eLAST,
      N_AGGREGATES,
    };
  
    LogField(const char *name, const char *symbol, Type type, MarshalFunc marshal, UnmarshalFunc unmarshal, SetFunc _setFunc = NULL);
  
    LogField(const char *name, const char *symbol, Type type, MarshalFunc marshal, UnmarshalFuncWithMap unmarshal,
             Ptr<LogFieldAliasMap> map, SetFunc _setFunc = NULL);
  
    LogField(const char *field, Container container, SetFunc _setFunc = NULL);
    LogField(const LogField &rhs);
    ~LogField();
  
    unsigned marshal_len(LogAccess *lad);
    unsigned marshal(LogAccess *lad, char *buf);
    unsigned marshal_agg(char *buf);
    unsigned unmarshal(char **buf, char *dest, int len);
    void display(FILE *fd = stdout);
    bool operator==(LogField &rhs);
    void updateField(LogAccess *lad, char *val, int len);
  
    char *
    name()
    {
      return m_name;
    }
    char *
    symbol()
    {
      return m_symbol;
    }
    Type
    type()
    {
      return m_type;
    }
    Ptr<LogFieldAliasMap>
    map()
    {
      return m_alias_map;
    };
    Aggregate
    aggregate()
    {
      return m_agg_op;
    }
    bool
    is_time_field()
    {
      return m_time_field;
    }
  
    void set_aggregate_op(Aggregate agg_op);
    void update_aggregate(int64_t val);
  
    static void init_milestone_container(void);
    static Container valid_container_name(char *name);
    static Aggregate valid_aggregate_name(char *name);
    static bool fieldlist_contains_aggregates(char *fieldlist);
  
  private:
    char *m_name;
    char *m_symbol;
    Type m_type;
    Container m_container;
    MarshalFunc m_marshal_func;     // place data into buffer
    UnmarshalFunc m_unmarshal_func; // create a string of the data
    UnmarshalFuncWithMap m_unmarshal_func_map;
    Aggregate m_agg_op;
    int64_t m_agg_cnt;
    int64_t m_agg_val;
    TSMilestonesType m_milestone1; ///< Used for MS and MSDMS as the first (or only) milestone.
    TSMilestonesType m_milestone2; ///< Second milestone for MSDMS
    bool m_time_field;
    Ptr<LogFieldAliasMap> m_alias_map; // map sINT <--> string
    SetFunc m_set_func;
    TSMilestonesType milestone_from_m_name();
    int milestones_from_m_name(TSMilestonesType *m1, TSMilestonesType *m2);
  
  public:
    LINK(LogField, link);
    LogSlice m_slice;
  
  private:
    // luis, check where this is used and what it does
    //    void init (char *name, char *symbol, Type type);
  
    // -- member functions that are not allowed --
    LogField();
    LogField &operator=(const LogField &rhs);
  };
  
  extern const char *container_names[];
  extern const char *aggregate_names[];
  
  /*-------------------------------------------------------------------------
    LogFieldList
  
    This class maintains a list of LogField objects (tah-dah).
    -------------------------------------------------------------------------*/
  
  class LogFieldList
  {
  public:
    LogFieldList();
    ~LogFieldList();
  
    void clear();
    void add(LogField *field, bool copy = true);
    LogField *find_by_name(const char *name) const;
    LogField *find_by_symbol(const char *symbol) const;
    unsigned marshal_len(LogAccess *lad);
    unsigned marshal(LogAccess *lad, char *buf);
    unsigned marshal_agg(char *buf);
  
    LogField *
    first() const
    {
      return m_field_list.head;
    }
    LogField *
    next(LogField *here) const
    {
      return (here->link).next;
    }
    unsigned count();
    void display(FILE *fd = stdout);
  
  private:
    unsigned m_marshal_len;
    Queue<LogField> m_field_list;
  
    // -- member functions that are not allowed --
    LogFieldList(const LogFieldList &rhs);
    LogFieldList &operator=(const LogFieldList &rhs);
  };
  
  /** Base IP address data.
      To unpack an IP address, the generic memory is first cast to
      this type to get the family. That pointer can then be static_cast
      to the appropriate subtype to get the actual address data.
  
      @note We don't use our own enum for the family. Instead we use
      @c AF_INET and @c AF_INET6.
  */
  struct LogFieldIp {
    uint16_t _family; ///< IP address family.
  };
  /// IPv4 address as log field.
  struct LogFieldIp4 : public LogFieldIp {
    in_addr_t _addr; ///< IPv4 address.
  };
  /// IPv6 address as log field.
  struct LogFieldIp6 : public LogFieldIp {
    in6_addr _addr; ///< IPv6 address.
  };
  /// Something big enough to hold any of the IP field types.
  union LogFieldIpStorage {
    LogFieldIp _ip;
    LogFieldIp4 _ip4;
    LogFieldIp6 _ip6;
  };
  
  #endif
  