blob: 7f2ca313aacd997d57e971abddc2111e365886d5 [file] [log] [blame]
// 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 <iosfwd>
#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 {
// A UTF-8 encoded character string that can be null. Provides functions that
// are similar to std::string, along with access to the underlying std::string
// object.
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) {}
String(const mojo::String& str)
: value_(str.value_), is_null_(str.is_null_) {}
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 mojo::String& str) {
value_ = str.value_;
is_null_ = str.is_null_;
return *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;
}
// Tests as true if non-null, false if null.
explicit operator bool() const { return !is_null_; }
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); }
char& at(size_t offset) { return value_.at(offset); }
const char& operator[](size_t offset) const { return value_[offset]; }
char& operator[](size_t offset) { 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:
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);
}
// TODO(jeffbrown): Decide whether this should print a sentinel value
// such as "<null>" when formatting null strings.
inline std::ostream& operator<<(std::ostream& out, const String& s) {
return out << s.get();
}
inline bool operator<(const String& a, const String& b) {
if (a.is_null())
return !b.is_null();
if (b.is_null())
return false;
return a.get() < b.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_