00001 /** @file 00002 00003 This file implements an abstract class to map between numbers of type IntType 00004 00005 @section license License 00006 00007 Licensed to the Apache Software Foundation (ASF) under one 00008 or more contributor license agreements. See the NOTICE file 00009 distributed with this work for additional information 00010 regarding copyright ownership. The ASF licenses this file 00011 to you under the Apache License, Version 2.0 (the 00012 "License"); you may not use this file except in compliance 00013 with the License. You may obtain a copy of the License at 00014 00015 http://www.apache.org/licenses/LICENSE-2.0 00016 00017 Unless required by applicable law or agreed to in writing, software 00018 distributed under the License is distributed on an "AS IS" BASIS, 00019 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00020 See the License for the specific language governing permissions and 00021 limitations under the License. 00022 00023 @section description 00024 This file implements an abstract class to map between numbers of type IntType 00025 and strings. The purpose is to obtain one representation from the other so that 00026 easily remembered names can be used to refer to log fields of integer type. 00027 */ 00028 00029 00030 #ifndef LOG_FIELD_ALIAS_MAP_H 00031 #define LOG_FIELD_ALIAS_MAP_H 00032 00033 #include <stdarg.h> 00034 #include <string.h> 00035 00036 #include "libts.h" 00037 #include "Ptr.h" 00038 #include "LogUtils.h" 00039 #include "ink_string.h" 00040 00041 /***************************************************************************** 00042 00043 The LogFieldAliasMap class is an abstract class used to provide an 00044 interface to map between numbers of type IntType and strings. The 00045 purpose is to obtain one representation from the other so that easy to 00046 remember names can be used to refer to log fields of integer type. 00047 00048 The methods that subclasses should implement are: 00049 00050 1) asInt(char *key, IntType *val) 00051 00052 This method takes a string and sets the IntType argument to the 00053 corresponding value, (unless the string is invalid). It returns an 00054 error status. 00055 00056 2) asString(IntType key, char *buf, size_t bufLen, size_t *numChars=0) 00057 00058 This method takes an IntType key and writes its equivalent string to a 00059 bufer buf of length bufLen. It sets the number of written characters 00060 numChars (if numChars is not NULL), and returns an error status. 00061 00062 The IntType to string conversion is used when unmarshaling data prior to 00063 writing to a log file, and the string to IntType conversion is used when 00064 building filters (so that the filter value can be specified as a string, 00065 but the actual field comparison is done between IntTypes). 00066 00067 Note that LogFieldAliasMap is derived from RefCountObj, so once a map 00068 is constructed a pointer to it can be passed to other objects (e.g., 00069 to a LogField object) without the object having to worry about freeing 00070 any memory the map may have allocated. 00071 00072 *****************************************************************************/ 00073 00074 00075 class LogFieldAliasMap:public RefCountObj 00076 { 00077 public: 00078 00079 // the logging system assumes log entries of type sINT are 00080 // unsigned (signed?) integers (int64_t type) so we define IntType 00081 // to be unsigned (signed?) 00082 // The problem using the correct type is that the init method is 00083 // vararg. To make that work, we must use the "generic" int. 00084 00085 typedef int64_t IntType; 00086 enum 00087 { ALL_OK = 0, INVALID_INT, INVALID_STRING, BUFFER_TOO_SMALL }; 00088 00089 virtual int asInt(char *key, IntType * val, bool case_sensitive = 0) const = 0; 00090 virtual int asString(IntType key, char *buf, size_t bufLen, size_t * numChars = 0) const = 0; 00091 }; 00092 00093 /***************************************************************************** 00094 00095 A LogFieldAliasTable implements a LogFieldAliasMap through a 00096 straightforward table. The entries in the table are input with the 00097 init(numPairs, ...) method. Arguments to this method are the number 00098 numPairs of table entries, followed by the entries themselves in the 00099 form integer, string. For example: 00100 00101 table->init(3, 1, "one", 2, "two", 7, "seven") 00102 00103 *****************************************************************************/ 00104 00105 struct LogFieldAliasTableEntry 00106 { 00107 bool valid; // entry in table is valid 00108 char *name; // the string equivalent 00109 size_t length; // the length of the string 00110 00111 LogFieldAliasTableEntry() 00112 : valid(false), name(NULL), length(0) 00113 { } 00114 }; 00115 00116 class LogFieldAliasTable:public LogFieldAliasMap 00117 { 00118 private: 00119 IntType m_min; // minimum numeric value 00120 IntType m_max; // maximum numeric value 00121 IntType m_entries; // number of entries in table 00122 LogFieldAliasTableEntry *m_table; // array of table entries 00123 00124 public: 00125 LogFieldAliasTable() 00126 : m_min(0), m_max(0), m_entries(0), m_table(0) 00127 { } 00128 00129 ~LogFieldAliasTable() { 00130 delete[]m_table; 00131 } 00132 00133 void init(size_t numPairs, ...); 00134 00135 int asInt(char *key, IntType * val, bool case_sensitive) const 00136 { 00137 int retVal = INVALID_STRING; 00138 00139 for (IntType i = 0; i < m_entries; i++) 00140 { 00141 bool found; 00142 if (m_table[i].valid) 00143 { 00144 if (case_sensitive) { 00145 found = (strcmp(key, m_table[i].name) == 0); 00146 } else 00147 { 00148 found = (strcasecmp(key, m_table[i].name) == 0); 00149 } 00150 } else { 00151 found = false; 00152 } 00153 if (found) { 00154 *val = (unsigned int) (i + m_min); 00155 retVal = ALL_OK; 00156 break; 00157 } 00158 } 00159 00160 return retVal; 00161 } 00162 00163 int asString(IntType key, char *buf, size_t bufLen, size_t * numCharsPtr = 0) const 00164 { 00165 int retVal; 00166 size_t numChars; 00167 00168 size_t i = key - m_min; 00169 if (m_entries && key >= m_min && key <= m_max && m_table[i].valid) 00170 { 00171 size_t l = m_table[i].length; 00172 if (l < bufLen) 00173 { 00174 ink_strlcpy(buf, m_table[key - m_min].name, bufLen); 00175 numChars = l; 00176 retVal = ALL_OK; 00177 } else 00178 { 00179 numChars = 0; 00180 retVal = BUFFER_TOO_SMALL; 00181 } 00182 } else { 00183 numChars = 0; 00184 retVal = INVALID_INT; 00185 } 00186 if (numCharsPtr) { 00187 *numCharsPtr = numChars; 00188 } 00189 return retVal; 00190 } 00191 }; 00192 00193 /***************************************************************************** 00194 00195 The LogFieldAliasTimehex class implements a LogFieldAliasMap that converts time 00196 from their integer value to the "hex" notation and back. 00197 00198 *****************************************************************************/ 00199 00200 class LogFieldAliasTimeHex:public LogFieldAliasMap 00201 { 00202 public: 00203 int asInt(char *str, IntType * time, bool /* case_sensitive ATS_UNUSED */) const 00204 { 00205 unsigned long a; 00206 // coverity[secure_coding] 00207 if (sscanf(str, "%lx", (unsigned long *) &a) == 1) { 00208 *time = (IntType) a; 00209 return ALL_OK; 00210 } else 00211 { 00212 return INVALID_STRING; 00213 } 00214 } 00215 00216 int asString(IntType time, char *buf, size_t bufLen, size_t * numCharsPtr = 0) const 00217 { 00218 return (LogUtils::timestamp_to_hex_str(time, buf, bufLen, numCharsPtr) ? BUFFER_TOO_SMALL : ALL_OK); 00219 } 00220 }; 00221 00222 00223 00224 //LOG_FIELD_ALIAS_MAP_H 00225 #endif