summaryrefslogtreecommitdiffstats
path: root/apt-pkg/contrib/string_view.h
blob: 71f47f5638c31261632a4d44650bdae41f98a889 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
/*
 * Basic implementation of string_view
 *
 * (C) 2015 Julian Andres Klode <jak@debian.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 */

#if !defined(APT_STRINGVIEW_H)
#define APT_STRINGVIEW_H
#include <apt-pkg/macros.h>
#include <cstring>
#include <string>

namespace APT {

/**
 * \brief Simple subset of std::string_view from C++17
 *
 * This is an internal implementation of the subset of std::string_view
 * used by APT. It is not meant to be used in programs, only inside the
 * library for performance critical paths.
 */
class StringView {
    const char *data_;
    size_t size_;

public:
    static constexpr size_t npos = static_cast<size_t>(-1);
    static_assert(APT::StringView::npos == std::string::npos, "npos values are different");

    /* Constructors */
    constexpr StringView() : data_(""), size_(0) {}
    constexpr StringView(const char *data, size_t size) : data_(data), size_(size) {}

    StringView(const char *data) : data_(data), size_(strlen(data)) {}
    StringView(std::string const & str): data_(str.data()), size_(str.size()) {}

    /* Modifiers */
    void remove_prefix(size_t n) { data_ += n; size_ -= n; }
    void remove_suffix(size_t n) { size_ -= n; }
    void clear() { size_ = 0; }

    /* Viewers */
    constexpr StringView substr(size_t pos, size_t n = npos) const {
        return StringView(data_ + pos, n > (size_ - pos) ? (size_ - pos) : n);
    }

    size_t find(int c, size_t pos) const {
       if (pos == 0)
	  return find(c);
       size_t const found = substr(pos).find(c);
       if (found == npos)
	  return npos;
       return pos + found;
    }
    size_t find(int c) const {
        const char *found = static_cast<const char*>(memchr(data_, c, size_));

        if (found == NULL)
            return npos;

        return found - data_;
    }

    size_t rfind(int c, size_t pos) const {
       if (pos == npos)
	  return rfind(c);
       return APT::StringView(data_, pos).rfind(c);
    }
    size_t rfind(int c) const {
        const char *found = static_cast<const char*>(memrchr(data_, c, size_));

        if (found == NULL)
            return npos;

        return found - data_;
    }

    size_t find(APT::StringView const needle) const {
       if (needle.empty())
	  return npos;
       if (needle.length() == 1)
	  return find(*needle.data());
       size_t found = 0;
       while ((found = find(*needle.data(), found)) != npos) {
	  if (compare(found, needle.length(), needle) == 0)
	     return found;
	  ++found;
       }
       return found;
    }
    size_t find(APT::StringView const needle, size_t pos) const {
       if (pos == 0)
	  return find(needle);
       size_t const found = substr(pos).find(needle);
       if (found == npos)
	  return npos;
       return pos + found;
    }

    /* Conversions */
    std::string to_string() const {
        return std::string(data_, size_);
    }

    /* Comparisons */
    int compare(size_t pos, size_t n, StringView other) const {
        return substr(pos, n).compare(other);
    }

    int compare(StringView other) const {
        int res;

        res = memcmp(data_, other.data_, std::min(size_, other.size_));
        if (res != 0)
            return res;
        if (size_ == other.size_)
            return res;

        return (size_ > other.size_) ? 1 : -1;
    }

    /* Optimization: If size not equal, string cannot be equal */
    bool operator ==(StringView other) const { return size_ == other.size_ && compare(other) == 0; }
    bool operator !=(StringView other) const { return !(*this == other); }

    /* Accessors */
    constexpr bool empty() const { return size_ == 0; }
    constexpr const char* data() const { return data_; }
    constexpr const char* begin() const { return data_; }
    constexpr const char* end() const { return data_ + size_; }
    constexpr char operator [](size_t i) const { return data_[i]; }
    constexpr size_t size() const { return size_; }
    constexpr size_t length() const { return size_; }
};

/**
 * \brief Faster comparison for string views (compare size before data)
 *
 * Still stable, but faster than the normal ordering. */
static inline int StringViewCompareFast(StringView a, StringView b) {
    if (a.size() != b.size())
        return a.size() - b.size();

    return memcmp(a.data(), b.data(), a.size());
}

static constexpr inline APT::StringView operator""_sv(const char *data, size_t size)
{
   return APT::StringView(data, size);
}
}

inline bool operator ==(const char *other, APT::StringView that);
inline bool operator ==(const char *other, APT::StringView that) { return that.operator==(other); }
inline bool operator ==(std::string const &other, APT::StringView that);
inline bool operator ==(std::string const &other, APT::StringView that) { return that.operator==(other); }

#endif