1 /** @file 2 3 This file implements an abstract class to map between numbers of type IntType 4 5 @section license License 6 7 Licensed to the Apache Software Foundation (ASF) under one 8 or more contributor license agreements. See the NOTICE file 9 distributed with this work for additional information 10 regarding copyright ownership. The ASF licenses this file 11 to you under the Apache License, Version 2.0 (the 12 "License"); you may not use this file except in compliance 13 with the License. You may obtain a copy of the License at 14 15 http://www.apache.org/licenses/LICENSE-2.0 16 17 Unless required by applicable law or agreed to in writing, software 18 distributed under the License is distributed on an "AS IS" BASIS, 19 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 See the License for the specific language governing permissions and 21 limitations under the License. 22 23 @section description 24 This file implements an abstract class to map between numbers of type IntType 25 and strings. The purpose is to obtain one representation from the other so that 26 easily remembered names can be used to refer to log fields of integer type. 27 */ 28 29 #pragma once 30 31 #include <cstdarg> 32 #include <cstring> 33 34 #include "tscore/ink_platform.h" 35 #include "tscore/Ptr.h" 36 #include "LogUtils.h" 37 #include "tscore/ink_string.h" 38 39 /***************************************************************************** 40 41 The LogFieldAliasMap class is an abstract class used to provide an 42 interface to map between numbers of type IntType and strings. The 43 purpose is to obtain one representation from the other so that easy to 44 remember names can be used to refer to log fields of integer type. 45 46 The methods that subclasses should implement are: 47 48 1) asInt(char *key, IntType *val) 49 50 This method takes a string and sets the IntType argument to the 51 corresponding value, (unless the string is invalid). It returns an 52 error status. 53 54 2) asString(IntType key, char *buf, size_t bufLen, size_t *numChars=0) 55 56 This method takes an IntType key and writes its equivalent string to a 57 buffer buf of length bufLen. It sets the number of written characters 58 numChars (if numChars is not NULL), and returns an error status. 59 60 The IntType to string conversion is used when unmarshaling data prior to 61 writing to a log file, and the string to IntType conversion is used when 62 building filters (so that the filter value can be specified as a string, 63 but the actual field comparison is done between IntTypes). 64 65 Note that LogFieldAliasMap is derived from RefCountObj, so once a map 66 is constructed a pointer to it can be passed to other objects (e.g., 67 to a LogField object) without the object having to worry about freeing 68 any memory the map may have allocated. 69 70 *****************************************************************************/ 71 72 class LogFieldAliasMap : public RefCountObj 73 { 74 public: 75 // the logging system assumes log entries of type sINT are 76 // unsigned (signed?) integers (int64_t type) so we define IntType 77 // to be unsigned (signed?) 78 // The problem using the correct type is that the init method is 79 // vararg. To make that work, we must use the "generic" int. 80 81 typedef int64_t IntType; 82 enum { 83 ALL_OK = 0, 84 INVALID_INT, 85 INVALID_STRING, 86 BUFFER_TOO_SMALL, 87 }; 88 89 virtual int asInt(char *key, IntType *val, bool case_sensitive = false) const = 0; 90 virtual int asString(IntType key, char *buf, size_t bufLen, size_t *numChars = nullptr) const = 0; 91 }; 92 93 /***************************************************************************** 94 95 A LogFieldAliasTable implements a LogFieldAliasMap through a 96 straightforward table. The entries in the table are input with the 97 init(numPairs, ...) method. Arguments to this method are the number 98 numPairs of table entries, followed by the entries themselves in the 99 form integer, string. For example: 100 101 table->init(3, 1, "one", 2, "two", 7, "seven") 102 103 *****************************************************************************/ 104 105 struct LogFieldAliasTableEntry { 106 bool valid = false; // entry in table is valid 107 char *name = nullptr; // the string equivalent 108 size_t length = 0; // the length of the string 109 LogFieldAliasTableEntryLogFieldAliasTableEntry110 LogFieldAliasTableEntry() {} ~LogFieldAliasTableEntryLogFieldAliasTableEntry111 ~LogFieldAliasTableEntry() 112 { 113 if (name) { 114 free(name); 115 } 116 } 117 }; 118 119 class LogFieldAliasTable : public LogFieldAliasMap 120 { 121 private: 122 IntType m_min = 0; // minimum numeric value 123 IntType m_max = 0; // maximum numeric value 124 IntType m_entries = 0; // number of entries in table 125 LogFieldAliasTableEntry *m_table = nullptr; // array of table entries 126 127 public: LogFieldAliasTable()128 LogFieldAliasTable() {} ~LogFieldAliasTable()129 ~LogFieldAliasTable() override { delete[] m_table; } 130 void init(size_t numPairs, ...); 131 132 int asInt(char * key,IntType * val,bool case_sensitive)133 asInt(char *key, IntType *val, bool case_sensitive) const override 134 { 135 int retVal = INVALID_STRING; 136 137 for (IntType i = 0; i < m_entries; i++) { 138 bool found; 139 if (m_table[i].valid) { 140 if (case_sensitive) { 141 found = (strcmp(key, m_table[i].name) == 0); 142 } else { 143 found = (strcasecmp(key, m_table[i].name) == 0); 144 } 145 } else { 146 found = false; 147 } 148 if (found) { 149 *val = (unsigned int)(i + m_min); 150 retVal = ALL_OK; 151 break; 152 } 153 } 154 155 return retVal; 156 } 157 158 int 159 asString(IntType key, char *buf, size_t bufLen, size_t *numCharsPtr = nullptr) const override 160 { 161 int retVal; 162 size_t numChars; 163 164 size_t i = key - m_min; 165 if (m_entries && key >= m_min && key <= m_max && m_table[i].valid) { 166 size_t l = m_table[i].length; 167 if (l < bufLen) { 168 ink_strlcpy(buf, m_table[key - m_min].name, bufLen); 169 numChars = l; 170 retVal = ALL_OK; 171 } else { 172 numChars = 0; 173 retVal = BUFFER_TOO_SMALL; 174 } 175 } else { 176 numChars = 0; 177 retVal = INVALID_INT; 178 } 179 if (numCharsPtr) { 180 *numCharsPtr = numChars; 181 } 182 return retVal; 183 } 184 }; 185 186 // LOG_FIELD_ALIAS_MAP_H 187