1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef MOJO_PUBLIC_CPP_BINDINGS_STRING_H_
6#define MOJO_PUBLIC_CPP_BINDINGS_STRING_H_
7
8#include <string>
9
10#include "mojo/public/cpp/bindings/lib/array_internal.h"
11#include "mojo/public/cpp/bindings/type_converter.h"
12#include "mojo/public/cpp/environment/logging.h"
13
14namespace mojo {
15
16class String {
17 public:
18  typedef internal::String_Data Data_;
19
20  String() : is_null_(true) {}
21  String(const std::string& str) : value_(str), is_null_(false) {}
22  String(const char* chars) : is_null_(!chars) {
23    if (chars)
24      value_ = chars;
25  }
26  String(const char* chars, size_t num_chars)
27      : value_(chars, num_chars),
28        is_null_(false) {
29  }
30  template <size_t N>
31  String(const char chars[N]) : value_(chars, N-1), is_null_(false) {}
32
33  template <typename U>
34  static String From(const U& other) {
35    return TypeConverter<String, U>::Convert(other);
36  }
37
38  template <typename U>
39  U To() const {
40    return TypeConverter<U, String>::Convert(*this);
41  }
42
43  String& operator=(const std::string& str) {
44    value_ = str;
45    is_null_ = false;
46    return *this;
47  }
48  String& operator=(const char* chars) {
49    is_null_ = !chars;
50    if (chars) {
51      value_ = chars;
52    } else {
53      value_.clear();
54    }
55    return *this;
56  }
57
58  void reset() {
59    value_.clear();
60    is_null_ = true;
61  }
62
63  bool is_null() const { return is_null_; }
64
65  size_t size() const { return value_.size(); }
66
67  const char* data() const { return value_.data(); }
68
69  const char& at(size_t offset) const { return value_.at(offset); }
70  const char& operator[](size_t offset) const { return value_[offset]; }
71
72  const std::string& get() const { return value_; }
73  operator const std::string&() const { return value_; }
74
75  void Swap(String* other) {
76    std::swap(is_null_, other->is_null_);
77    value_.swap(other->value_);
78  }
79
80  void Swap(std::string* other) {
81    is_null_ = false;
82    value_.swap(*other);
83  }
84
85 private:
86  typedef std::string String::*Testable;
87
88 public:
89  operator Testable() const { return is_null_ ? 0 : &String::value_; }
90
91 private:
92  std::string value_;
93  bool is_null_;
94};
95
96inline bool operator==(const String& a, const String& b) {
97  return a.is_null() == b.is_null() && a.get() == b.get();
98}
99inline bool operator==(const char* a, const String& b) {
100  return !b.is_null() && a == b.get();
101}
102inline bool operator==(const String& a, const char* b) {
103  return !a.is_null() && a.get() == b;
104}
105inline bool operator!=(const String& a, const String& b) { return !(a == b); }
106inline bool operator!=(const char* a, const String& b) { return !(a == b); }
107inline bool operator!=(const String& a, const char* b) { return !(a == b); }
108
109inline std::ostream& operator<<(std::ostream& out, const String& s) {
110  return out << s.get();
111}
112
113// TODO(darin): Add similar variants of operator<,<=,>,>=
114
115template <>
116struct TypeConverter<String, std::string> {
117  static String Convert(const std::string& input) { return String(input); }
118};
119
120template <>
121struct TypeConverter<std::string, String> {
122  static std::string Convert(const String& input) { return input; }
123};
124
125template <size_t N>
126struct TypeConverter<String, char[N]> {
127  static String Convert(const char input[N]) {
128    MOJO_DCHECK(input);
129    return String(input, N-1);
130  }
131};
132
133// Appease MSVC.
134template <size_t N>
135struct TypeConverter<String, const char[N]> {
136  static String Convert(const char input[N]) {
137    MOJO_DCHECK(input);
138    return String(input, N-1);
139  }
140};
141
142template <>
143struct TypeConverter<String, const char*> {
144  // |input| may be null, in which case a null String will be returned.
145  static String Convert(const char* input) { return String(input); }
146};
147
148}  // namespace mojo
149
150#endif  // MOJO_PUBLIC_CPP_BINDINGS_STRING_H_
151