File indexing completed on 2024-05-12 03:54:23
0001 /* 0002 This file is part of the KDE libraries 0003 SPDX-FileCopyrightText: 2008 Jakub Stachowski <qbast@go2.pl> 0004 0005 SPDX-License-Identifier: LGPL-2.0-or-later 0006 */ 0007 0008 #ifndef BUFFERFRAGMENT_H 0009 #define BUFFERFRAGMENT_H 0010 0011 #include "kconfigini_p.h" 0012 0013 #define bf_isspace(str) ((str == ' ') || (str == '\t') || (str == '\r')) 0014 0015 // This class provides wrapper around fragment of existing buffer (array of bytes). 0016 // If underlying buffer gets deleted, all BufferFragment objects referencing it become invalid. 0017 // Use toByteArray() to make deep copy of the buffer fragment. 0018 // 0019 // API is designed to subset of QByteArray methods with some changes: 0020 // - trim() is like QByteArray.trimmed(), but it modifies current object 0021 // - truncateLeft() provides way to cut off beginning of the buffer 0022 // - split() works more like strtok_r than QByteArray.split() 0023 // - truncateLeft() and mid() require position argument to be valid 0024 0025 class KConfigIniBackend::BufferFragment 0026 { 0027 public: 0028 BufferFragment() 0029 : d(nullptr) 0030 , len(0) 0031 { 0032 } 0033 0034 BufferFragment(char *buf, int size) 0035 : d(buf) 0036 , len(size) 0037 { 0038 } 0039 0040 int length() const 0041 { 0042 return len; 0043 } 0044 0045 char at(unsigned int i) const 0046 { 0047 Q_ASSERT(i < len); 0048 return d[i]; 0049 } 0050 0051 void clear() 0052 { 0053 len = 0; 0054 } 0055 0056 const char *constData() const 0057 { 0058 return d; 0059 } 0060 0061 char *data() const 0062 { 0063 return d; 0064 } 0065 0066 void trim() 0067 { 0068 while (bf_isspace(*d) && len > 0) { 0069 ++d; 0070 --len; 0071 } 0072 while (len > 0 && bf_isspace(d[len - 1])) { 0073 --len; 0074 } 0075 } 0076 0077 // similar to strtok_r . On first call variable pointed by start should be set to 0. 0078 // Each call will update *start to new starting position. 0079 BufferFragment split(char c, unsigned int *start) 0080 { 0081 if (*start < len) { 0082 int end = indexOf(c, *start); 0083 if (end == -1) { 0084 end = len; 0085 } 0086 BufferFragment line(d + (*start), end - (*start)); 0087 *start = end + 1; 0088 return line; 0089 } 0090 return BufferFragment(); 0091 } 0092 0093 bool isEmpty() const 0094 { 0095 return !len; 0096 } 0097 0098 BufferFragment left(unsigned int size) const 0099 { 0100 return BufferFragment(d, qMin(size, len)); 0101 } 0102 0103 void truncateLeft(unsigned int size) 0104 { 0105 Q_ASSERT(size <= len); 0106 d += size; 0107 len -= size; 0108 } 0109 0110 void truncate(unsigned int pos) 0111 { 0112 if (pos < len) { 0113 len = pos; 0114 } 0115 } 0116 0117 bool isNull() const 0118 { 0119 return !d; 0120 } 0121 0122 BufferFragment mid(unsigned int pos, int length = -1) const 0123 { 0124 Q_ASSERT(pos < len); 0125 int size = length; 0126 if (length == -1 || (pos + length) > len) { 0127 size = len - pos; 0128 } 0129 return BufferFragment(d + pos, size); 0130 } 0131 0132 bool operator==(const QByteArray &other) const 0133 { 0134 return (other.size() == (int)len && memcmp(d, other.constData(), len) == 0); 0135 } 0136 0137 bool operator!=(const QByteArray &other) const 0138 { 0139 return (other.size() != (int)len || memcmp(d, other.constData(), len) != 0); 0140 } 0141 0142 bool operator==(const BufferFragment other) const 0143 { 0144 return other.len == len && !memcmp(d, other.d, len); 0145 } 0146 0147 int indexOf(char c, unsigned int from = 0) const 0148 { 0149 const char *cursor = d + from - 1; 0150 const char *end = d + len; 0151 while (++cursor < end) 0152 if (*cursor == c) { 0153 return cursor - d; 0154 } 0155 return -1; 0156 } 0157 0158 int lastIndexOf(char c) const 0159 { 0160 int from = len - 1; 0161 while (from >= 0) 0162 if (d[from] == c) { 0163 return from; 0164 } else { 0165 --from; 0166 } 0167 return -1; 0168 } 0169 0170 QByteArray toByteArray() const 0171 { 0172 return QByteArray(d, len); 0173 } 0174 0175 // this is faster than toByteArray, but returned QByteArray becomes invalid 0176 // when buffer for this BufferFragment disappears 0177 QByteArray toVolatileByteArray() const 0178 { 0179 return QByteArray::fromRawData(d, len); 0180 } 0181 0182 private: 0183 char *d; 0184 unsigned int len; 0185 }; 0186 0187 size_t qHash(const KConfigIniBackend::BufferFragment fragment, size_t seed = 0) 0188 { 0189 const uchar *p = reinterpret_cast<const uchar *>(fragment.constData()); 0190 const int len = fragment.length(); 0191 0192 if (len == 0) { 0193 return seed; 0194 } 0195 return qHashBits(p, len, seed); 0196 } 0197 0198 #endif