// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MOJO_PUBLIC_CPP_BINDINGS_STRING_H_
#define MOJO_PUBLIC_CPP_BINDINGS_STRING_H_
#include <string>
#include "mojo/public/cpp/bindings/lib/array_internal.h"
#include "mojo/public/cpp/bindings/type_converter.h"
#include "mojo/public/cpp/environment/logging.h"
namespace mojo {
class String {
public:
typedef internal::String_Data Data_;
String() : is_null_(true) {}
String(const std::string& str) : value_(str), is_null_(false) {}
String(const char* chars) : is_null_(!chars) {
if (chars)
value_ = chars;
}
String(const char* chars, size_t num_chars)
: value_(chars, num_chars),
is_null_(false) {
}
template <size_t N>
String(const char chars[N]) : value_(chars, N-1), is_null_(false) {}
template <typename U>
static String From(const U& other) {
return TypeConverter<String, U>::Convert(other);
}
template <typename U>
U To() const {
return TypeConverter<U, String>::Convert(*this);
}
String& operator=(const std::string& str) {
value_ = str;
is_null_ = false;
return *this;
}
String& operator=(const char* chars) {
is_null_ = !chars;
if (chars) {
value_ = chars;
} else {
value_.clear();
}
return *this;
}
void reset() {
value_.clear();
is_null_ = true;
}
bool is_null() const { return is_null_; }
size_t size() const { return value_.size(); }
const char* data() const { return value_.data(); }
const char& at(size_t offset) const { return value_.at(offset); }
const char& operator[](size_t offset) const { return value_[offset]; }
const std::string& get() const { return value_; }
operator const std::string&() const { return value_; }
void Swap(String* other) {
std::swap(is_null_, other->is_null_);
value_.swap(other->value_);
}
void Swap(std::string* other) {
is_null_ = false;
value_.swap(*other);
}
private:
typedef std::string String::*Testable;
public:
operator Testable() const { return is_null_ ? 0 : &String::value_; }
private:
std::string value_;
bool is_null_;
};
inline bool operator==(const String& a, const String& b) {
return a.is_null() == b.is_null() && a.get() == b.get();
}
inline bool operator==(const char* a, const String& b) {
return !b.is_null() && a == b.get();
}
inline bool operator==(const String& a, const char* b) {
return !a.is_null() && a.get() == b;
}
inline bool operator!=(const String& a, const String& b) { return !(a == b); }
inline bool operator!=(const char* a, const String& b) { return !(a == b); }
inline bool operator!=(const String& a, const char* b) { return !(a == b); }
inline std::ostream& operator<<(std::ostream& out, const String& s) {
return out << s.get();
}
// TODO(darin): Add similar variants of operator<,<=,>,>=
template <>
struct TypeConverter<String, std::string> {
static String Convert(const std::string& input) { return String(input); }
};
template <>
struct TypeConverter<std::string, String> {
static std::string Convert(const String& input) { return input; }
};
template <size_t N>
struct TypeConverter<String, char[N]> {
static String Convert(const char input[N]) {
MOJO_DCHECK(input);
return String(input, N-1);
}
};
// Appease MSVC.
template <size_t N>
struct TypeConverter<String, const char[N]> {
static String Convert(const char input[N]) {
MOJO_DCHECK(input);
return String(input, N-1);
}
};
template <>
struct TypeConverter<String, const char*> {
// |input| may be null, in which case a null String will be returned.
static String Convert(const char* input) { return String(input); }
};
} // namespace mojo
#endif // MOJO_PUBLIC_CPP_BINDINGS_STRING_H_