Files
doris/be/src/util/slice.h
2018-12-03 18:11:47 +08:00

225 lines
6.8 KiB
C++

// 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 DORIS_BE_SRC_OLAP_STRING_SLICE_H
#define DORIS_BE_SRC_OLAP_STRING_SLICE_H
#include <assert.h>
#include <map>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include <string>
#include "olap/olap_define.h"
namespace doris {
/// @brief A wrapper around externally allocated data.
///
/// Slice is a simple structure containing a pointer into some external
/// storage and a size. The user of a Slice must ensure that the slice
/// is not used after the corresponding external storage has been
/// deallocated.
///
/// Multiple threads can invoke const methods on a Slice without
/// external synchronization, but if any of the threads may call a
/// non-const method, all threads accessing the same Slice must use
/// external synchronization.
struct Slice {
public:
char* data;
size_t size;
// Intentionally copyable
/// Create an empty slice.
Slice() : data(const_cast<char*>("")), size(0) { }
/// Create a slice that refers to a @c char byte array.
Slice(const char* d, size_t n) :
data(const_cast<char*>(d)), size(n) { }
// Create a slice that refers to a @c uint8_t byte array.
//
// @param [in] d
// The input array.
// @param [in] n
// Number of bytes in the array.
Slice(const uint8_t* s, size_t n) :
data(const_cast<char*>(reinterpret_cast<const char*>(s))), size(n) { }
/// Create a slice that refers to the contents of the given string.
Slice(const std::string& s) : // NOLINT(runtime/explicit)
data(const_cast<char*>(s.data())), size(s.size()) { }
/// Create a slice that refers to a C-string s[0,strlen(s)-1].
Slice(const char* s) : // NOLINT(runtime/explicit)
data(const_cast<char*>(s)), size(strlen(s)) { }
/*
/// @return A pointer to the beginning of the referenced data.
const char* data() const { return data; }
/// @return A mutable pointer to the beginning of the referenced data.
char* mutable_data() { return const_cast<char*>(data); }
/// @return The length (in bytes) of the referenced data.
size_t size() const { return size; }
*/
/// @return @c true iff the length of the referenced data is zero.
bool empty() const { return size == 0; }
/// @return the n-th byte in the referenced data.
const char operator[](size_t n) const {
assert(n < size);
return data[n];
}
/// Change this slice to refer to an empty array.
void clear() {
data = const_cast<char*>("");
size = 0;
}
/// Drop the first "n" bytes from this slice.
///
/// @pre n <= size
///
/// @note Only the base and bounds of the slice are changed;
/// the data is not modified.
///
/// @param [in] n
/// Number of bytes that should be dropped from the beginning.
void remove_prefix(size_t n) {
assert(n <= size);
data += n;
size -= n;
}
/// Truncate the slice to the given number of bytes.
///
/// @pre n <= size
///
/// @note Only the base and bounds of the slice are changed;
/// the data is not modified.
///
/// @param [in] n
/// The new size of the slice.
void truncate(size_t n) {
assert(n <= size);
size = n;
}
/// @return A string that contains a copy of the referenced data.
std::string to_string() const { return std::string(data, size); }
/// Do a three-way comparison of the slice's data.
int compare(const Slice& b) const;
/// Check whether the slice starts with the given prefix.
bool starts_with(const Slice& x) const {
return ((size >= x.size) &&
(mem_equal(data, x.data, x.size)));
}
/// @brief Comparator struct, useful for ordered collections (like STL maps).
struct Comparator {
/// Compare two slices using Slice::compare()
///
/// @param [in] a
/// The slice to call Slice::compare() at.
/// @param [in] b
/// The slice to use as a parameter for Slice::compare().
/// @return @c true iff @c a is less than @c b by Slice::compare().
bool operator()(const Slice& a, const Slice& b) const {
return a.compare(b) < 0;
}
};
/// Relocate/copy the slice's data into a new location.
///
/// @param [in] d
/// The new location for the data. If it's the same location, then no
/// relocation is done. It is assumed that the new location is
/// large enough to fit the data.
void relocate(char* d) {
if (data != d) {
memcpy(d, data, size);
data = d;
}
}
friend bool operator==(const Slice& x, const Slice& y);
static bool mem_equal(const void* a, const void* b, size_t n) {
return memcmp(a, b, n) == 0;
}
static int mem_compare(const void* a, const void* b, size_t n) {
return memcmp(a, b, n);
}
};
/// Check whether two slices are identical.
inline bool operator==(const Slice& x, const Slice& y) {
return ((x.size == y.size) &&
(Slice::mem_equal(x.data, y.data, x.size)));
}
/// Check whether two slices are not identical.
inline bool operator!=(const Slice& x, const Slice& y) {
return !(x == y);
}
inline int Slice::compare(const Slice& b) const {
const int min_len = (size < b.size) ? size : b.size;
int r = mem_compare(data, b.data, min_len);
if (r == 0) {
if (size < b.size) r = -1;
else if (size > b.size) r = +1;
}
return r;
}
/// @brief STL map whose keys are Slices.
///
/// An example of usage:
/// @code
/// typedef SliceMap<int>::type MySliceMap;
///
/// MySliceMap my_map;
/// my_map.insert(MySliceMap::value_type(a, 1));
/// my_map.insert(MySliceMap::value_type(b, 2));
/// my_map.insert(MySliceMap::value_type(c, 3));
///
/// for (const MySliceMap::value_type& pair : my_map) {
/// ...
/// }
/// @endcode
template <typename T>
struct SliceMap {
/// A handy typedef for the slice map with appropriate comparison operator.
typedef std::map<Slice, T, Slice::Comparator> type;
};
} // namespace doris
#endif // DORIS_BE_SRC_OLAP_STRING_SLICE_H