aboutsummaryrefslogtreecommitdiffstats
path: root/include/llvm/ADT/StringRef.h
blob: 4e9bfa40a5d0c0e598a905c8b03d0a8d3806d4f3 (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
164
165
166
167
168
169
170
171
172
173
174
175
//===--- StringRef.h - Constant String Reference Wrapper --------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_ADT_STRINGREF_H
#define LLVM_ADT_STRINGREF_H

#include <cstring>
#include <string>

namespace llvm {

  /// StringRef - Represent a constant reference to a string, i.e. a character
  /// array and a length, which need not be null terminated.
  ///
  /// This class does not own the string data, it is expected to be used in
  /// situations where the character data resides in some other buffer, whose
  /// lifetime extends past that of the StringRef. For this reason, it is not in
  /// general safe to store a StringRef.
  class StringRef {
  public:
    typedef const char *iterator;
    static const size_t npos = std::string::npos;

  private:
    /// The start of the string, in an external buffer.
    const char *Data;

    /// The length of the string.
    size_t Length;

  public:
    /// @name Constructors
    /// @{

    /// Construct an empty string ref.
    /*implicit*/ StringRef() : Data(0), Length(0) {}

    /// Construct a string ref from a cstring.
    /*implicit*/ StringRef(const char *Str) 
      : Data(Str), Length(::strlen(Str)) {}
 
    /// Construct a string ref from a pointer and length.
    /*implicit*/ StringRef(const char *_Data, unsigned _Length)
      : Data(_Data), Length(_Length) {}

    /// Construct a string ref from an std::string.
    /*implicit*/ StringRef(const std::string &Str) 
      : Data(Str.c_str()), Length(Str.length()) {}

    /// @}
    /// @name Iterators
    /// @{

    iterator begin() const { return Data; }

    iterator end() const { return Data + Length; }

    /// @}
    /// @name String Operations
    /// @{

    /// data - Get a pointer to the start of the string (which may not be null
    /// terminated).
    const char *data() const { return Data; }

    /// empty - Check if the string is empty.
    bool empty() const { return Length == 0; }

    /// size - Get the string size.
    size_t size() const { return Length; }

    /// equals - Check for string equality, this is more efficient than
    /// compare() in when the relative ordering of inequal strings isn't needed.
    bool equals(const StringRef &RHS) const {
      return (Length == RHS.Length && 
              memcmp(Data, RHS.Data, Length) == 0);
    }

    /// compare - Compare two strings; the result is -1, 0, or 1 if this string
    /// is lexicographically less than, equal to, or greater than the \arg RHS.
    int compare(const StringRef &RHS) const {
      // Check the prefix for a mismatch.
      if (int Res = memcmp(Data, RHS.Data, std::min(Length, RHS.Length)))
        return Res < 0 ? -1 : 1;

      // Otherwise the prefixes match, so we only need to check the lengths.
      if (Length == RHS.Length)
        return 0;
      return Length < RHS.Length ? -1 : 1;
    }

    /// str - Get the contents as an std::string.
    std::string str() const { return std::string(Data, Length); }

    /// @}
    /// @name Operator Overloads
    /// @{

    char operator[](size_t Index) const { 
      assert(Index < Length && "Invalid index!");
      return Data[Index]; 
    }

    /// @}
    /// @name Type Conversions
    /// @{

    operator std::string() const {
      return str();
    }

    /// @}
    /// @name Utility Functions
    /// @{

    /// substr - Return a reference to a substring of this object.
    ///
    /// \param Start - The index of the starting character in the substring; if
    /// the index is greater than the length of the string then the empty
    /// substring will be returned.
    ///
    /// \param N - The number of characters to included in the substring. If N
    /// exceeds the number of characters remaining in the string, the string
    /// suffix (starting with \arg Start) will be returned.
    StringRef substr(size_t Start, size_t N = npos) const {
      Start = std::min(Start, Length);
      return StringRef(Data + Start, std::min(N, Length - Start));
    }

    /// startswith - Check if this string starts with the given \arg Prefix.
    bool startswith(const StringRef &Prefix) const { 
      return substr(0, Prefix.Length).equals(Prefix);
    }

    /// @}
  };

  /// @name StringRef Comparison Operators
  /// @{

  inline bool operator==(const StringRef &LHS, const StringRef &RHS) {
    return LHS.equals(RHS);
  }

  inline bool operator!=(const StringRef &LHS, const StringRef &RHS) { 
    return !(LHS == RHS);
  }
  
  inline bool operator<(const StringRef &LHS, const StringRef &RHS) {
    return LHS.compare(RHS) == -1; 
  }

  inline bool operator<=(const StringRef &LHS, const StringRef &RHS) {
    return LHS.compare(RHS) != 1; 
  }

  inline bool operator>(const StringRef &LHS, const StringRef &RHS) {
    return LHS.compare(RHS) == 1; 
  }

  inline bool operator>=(const StringRef &LHS, const StringRef &RHS) {
    return LHS.compare(RHS) != -1; 
  }

  /// @}

}

#endif