/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * 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.
 */

#ifndef AAPT_STRING_PIECE_H
#define AAPT_STRING_PIECE_H

#include <ostream>
#include <string>
#include <utils/String8.h>
#include <utils/Unicode.h>

namespace aapt {

/**
 * Read only wrapper around basic C strings.
 * Prevents excessive copying.
 *
 * WARNING: When creating from std::basic_string<>, moving the original
 * std::basic_string<> will invalidate the data held in a BasicStringPiece<>.
 * BasicStringPiece<> should only be used transitively.
 */
template <typename TChar>
class BasicStringPiece {
public:
    using const_iterator = const TChar*;

    BasicStringPiece();
    BasicStringPiece(const BasicStringPiece<TChar>& str);
    BasicStringPiece(const std::basic_string<TChar>& str);
    BasicStringPiece(const TChar* str);
    BasicStringPiece(const TChar* str, size_t len);

    BasicStringPiece<TChar>& operator=(const BasicStringPiece<TChar>& rhs);
    BasicStringPiece<TChar>& assign(const TChar* str, size_t len);

    BasicStringPiece<TChar> substr(size_t start, size_t len) const;
    BasicStringPiece<TChar> substr(BasicStringPiece<TChar>::const_iterator begin,
                                   BasicStringPiece<TChar>::const_iterator end) const;

    const TChar* data() const;
    size_t length() const;
    size_t size() const;
    bool empty() const;
    std::basic_string<TChar> toString() const;

    int compare(const BasicStringPiece<TChar>& rhs) const;
    bool operator<(const BasicStringPiece<TChar>& rhs) const;
    bool operator>(const BasicStringPiece<TChar>& rhs) const;
    bool operator==(const BasicStringPiece<TChar>& rhs) const;
    bool operator!=(const BasicStringPiece<TChar>& rhs) const;

    const_iterator begin() const;
    const_iterator end() const;

private:
    const TChar* mData;
    size_t mLength;
};

using StringPiece = BasicStringPiece<char>;
using StringPiece16 = BasicStringPiece<char16_t>;

//
// BasicStringPiece implementation.
//

template <typename TChar>
inline BasicStringPiece<TChar>::BasicStringPiece() : mData(nullptr) , mLength(0) {
}

template <typename TChar>
inline BasicStringPiece<TChar>::BasicStringPiece(const BasicStringPiece<TChar>& str) :
        mData(str.mData), mLength(str.mLength) {
}

template <typename TChar>
inline BasicStringPiece<TChar>::BasicStringPiece(const std::basic_string<TChar>& str) :
        mData(str.data()), mLength(str.length()) {
}

template <>
inline BasicStringPiece<char>::BasicStringPiece(const char* str) :
        mData(str), mLength(str != nullptr ? strlen(str) : 0) {
}

template <>
inline BasicStringPiece<char16_t>::BasicStringPiece(const char16_t* str) :
        mData(str), mLength(str != nullptr ? strlen16(str) : 0) {
}

template <typename TChar>
inline BasicStringPiece<TChar>::BasicStringPiece(const TChar* str, size_t len) :
        mData(str), mLength(len) {
}

template <typename TChar>
inline BasicStringPiece<TChar>& BasicStringPiece<TChar>::operator=(
        const BasicStringPiece<TChar>& rhs) {
    mData = rhs.mData;
    mLength = rhs.mLength;
    return *this;
}

template <typename TChar>
inline BasicStringPiece<TChar>& BasicStringPiece<TChar>::assign(const TChar* str, size_t len) {
    mData = str;
    mLength = len;
    return *this;
}


template <typename TChar>
inline BasicStringPiece<TChar> BasicStringPiece<TChar>::substr(size_t start, size_t len) const {
    if (start + len > mLength) {
        return BasicStringPiece<TChar>();
    }
    return BasicStringPiece<TChar>(mData + start, len);
}

template <typename TChar>
inline BasicStringPiece<TChar> BasicStringPiece<TChar>::substr(
        BasicStringPiece<TChar>::const_iterator begin,
        BasicStringPiece<TChar>::const_iterator end) const {
    return BasicStringPiece<TChar>(begin, end - begin);
}

template <typename TChar>
inline const TChar* BasicStringPiece<TChar>::data() const {
    return mData;
}

template <typename TChar>
inline size_t BasicStringPiece<TChar>::length() const {
    return mLength;
}

template <typename TChar>
inline size_t BasicStringPiece<TChar>::size() const {
    return mLength;
}

template <typename TChar>
inline bool BasicStringPiece<TChar>::empty() const {
    return mLength == 0;
}

template <typename TChar>
inline std::basic_string<TChar> BasicStringPiece<TChar>::toString() const {
    return std::basic_string<TChar>(mData, mLength);
}

template <>
inline int BasicStringPiece<char>::compare(const BasicStringPiece<char>& rhs) const {
    const char nullStr = '\0';
    const char* b1 = mData != nullptr ? mData : &nullStr;
    const char* e1 = b1 + mLength;
    const char* b2 = rhs.mData != nullptr ? rhs.mData : &nullStr;
    const char* e2 = b2 + rhs.mLength;

    while (b1 < e1 && b2 < e2) {
        const int d = static_cast<int>(*b1++) - static_cast<int>(*b2++);
        if (d) {
            return d;
        }
    }
    return static_cast<int>(mLength - rhs.mLength);
}

inline ::std::ostream& operator<<(::std::ostream& out, const BasicStringPiece<char16_t>& str) {
    android::String8 utf8(str.data(), str.size());
    return out.write(utf8.string(), utf8.size());
}


template <>
inline int BasicStringPiece<char16_t>::compare(const BasicStringPiece<char16_t>& rhs) const {
    const char16_t nullStr = u'\0';
    const char16_t* b1 = mData != nullptr ? mData : &nullStr;
    const char16_t* b2 = rhs.mData != nullptr ? rhs.mData : &nullStr;
    return strzcmp16(b1, mLength, b2, rhs.mLength);
}

template <typename TChar>
inline bool BasicStringPiece<TChar>::operator<(const BasicStringPiece<TChar>& rhs) const {
    return compare(rhs) < 0;
}

template <typename TChar>
inline bool BasicStringPiece<TChar>::operator>(const BasicStringPiece<TChar>& rhs) const {
    return compare(rhs) > 0;
}

template <typename TChar>
inline bool BasicStringPiece<TChar>::operator==(const BasicStringPiece<TChar>& rhs) const {
    return compare(rhs) == 0;
}

template <typename TChar>
inline bool BasicStringPiece<TChar>::operator!=(const BasicStringPiece<TChar>& rhs) const {
    return compare(rhs) != 0;
}

template <typename TChar>
inline typename BasicStringPiece<TChar>::const_iterator BasicStringPiece<TChar>::begin() const {
    return mData;
}

template <typename TChar>
inline typename BasicStringPiece<TChar>::const_iterator BasicStringPiece<TChar>::end() const {
    return mData + mLength;
}

inline ::std::ostream& operator<<(::std::ostream& out, const BasicStringPiece<char>& str) {
    return out.write(str.data(), str.size());
}

} // namespace aapt

#endif // AAPT_STRING_PIECE_H
