summaryrefslogtreecommitdiff
path: root/src/mongo/base/string_data-inl.h
blob: efad95154ea52bfca8b158763683f5e3e37dfd63 (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
// string_data_inline.h

/*    Copyright 2010 10gen Inc.
 *
 *    Licensed 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.
 */

// this should never be included directly

#include <stdexcept>

namespace mongo {

    inline int StringData::compare(const StringData& other) const {
        // Sizes might not have been computed yet.
        size();
        other.size();

        int res = memcmp(_data, other._data, std::min(_size, other._size));
        if (res != 0) {
            return res > 0 ? 1 : -1;
        }
        else if (_size == other._size) {
            return 0;
        }
        else {
            return _size > other._size ? 1 : -1;
        }
    }

    inline bool StringData::equalCaseInsensitive( const StringData& other ) const {
        if ( other.size() != size() )
            return false;

        for ( size_t x = 0; x < size(); x++ ) {
            char a = _data[x];
            char b = other._data[x];
            if ( a == b )
                continue;
            if ( tolower(a) == tolower(b) )
                continue;
            return false;
        }

        return true;
    }

    inline void StringData::copyTo( char* dest, bool includeEndingNull ) const {
        memcpy( dest, _data, size() );
        if ( includeEndingNull )
            dest[size()] = 0;
    }

    inline size_t StringData::find( char c, size_t fromPos ) const {
        if ( fromPos >= size() )
            return string::npos;

        const void* x = memchr( _data + fromPos, c, _size - fromPos );
        if ( x == 0 )
            return string::npos;
        return static_cast<size_t>( static_cast<const char*>(x) - _data );
    }

    inline size_t StringData::find( const StringData& needle ) const {
        size_t mx = size();
        size_t needleSize = needle.size();

        if ( needleSize == 0 )
            return 0;
        else if ( needleSize > mx )
            return string::npos;

        mx -= needleSize;

        for ( size_t i = 0; i <= mx; i++ ) {
            if ( memcmp( _data + i, needle._data, needleSize ) == 0 )
                return i;
        }
        return string::npos;

    }

    inline size_t StringData::rfind( char c, size_t fromPos ) const {
        const size_t sz = size();
        if ( fromPos > sz )
            fromPos = sz;

        for ( const char* cur = _data + fromPos; cur > _data; --cur ) {
            if ( *(cur - 1) == c )
                return (cur - _data) - 1;
        }
        return string::npos;
    }

    inline StringData StringData::substr( size_t pos, size_t n ) const {
        if ( pos > size() )
            throw std::out_of_range( "out of range" );

        // truncate to end of string
        if ( n > size() - pos )
            n = size() - pos;

        return StringData( _data + pos, n );
    }

    inline bool StringData::startsWith( const StringData& prefix ) const {
        // TODO: Investigate an optimized implementation.
        return substr(0, prefix.size()) == prefix;
    }

    inline bool StringData::endsWith( const StringData& suffix ) const {
        // TODO: Investigate an optimized implementation.
        const size_t thisSize = size();
        const size_t suffixSize = suffix.size();
        if (suffixSize > thisSize)
            return false;
        return substr(thisSize - suffixSize) == suffix;
    }

}  // namespace mongo