Home | History | Annotate | Download | only in bindings
      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 <stddef.h>
      9 
     10 #include <string>
     11 
     12 #include "base/logging.h"
     13 #include "mojo/public/cpp/bindings/lib/array_internal.h"
     14 #include "mojo/public/cpp/bindings/type_converter.h"
     15 
     16 namespace mojo {
     17 
     18 // A UTF-8 encoded character string that can be null. Provides functions that
     19 // are similar to std::string, along with access to the underlying std::string
     20 // object.
     21 class String {
     22  public:
     23   // Constructs an empty string.
     24   String() : is_null_(false) {}
     25   String(const std::string& str) : value_(str), is_null_(false) {}
     26   String(const char* chars) : is_null_(!chars) {
     27     if (chars)
     28       value_ = chars;
     29   }
     30   String(const char* chars, size_t num_chars)
     31       : value_(chars, num_chars), is_null_(false) {}
     32   String(const mojo::String& str)
     33       : value_(str.value_), is_null_(str.is_null_) {}
     34 
     35   template <size_t N>
     36   String(const char chars[N])
     37       : value_(chars, N - 1), is_null_(false) {}
     38 
     39   String(std::string&& other) : value_(std::move(other)), is_null_(false) {}
     40   String(String&& other) : is_null_(true) { Swap(&other); }
     41 
     42   template <typename U>
     43   static String From(const U& other) {
     44     return TypeConverter<String, U>::Convert(other);
     45   }
     46 
     47   template <typename U>
     48   U To() const {
     49     return TypeConverter<U, String>::Convert(*this);
     50   }
     51 
     52   String& operator=(const mojo::String& str) {
     53     value_ = str.value_;
     54     is_null_ = str.is_null_;
     55     return *this;
     56   }
     57   String& operator=(const std::string& str) {
     58     value_ = str;
     59     is_null_ = false;
     60     return *this;
     61   }
     62   String& operator=(const char* chars) {
     63     is_null_ = !chars;
     64     if (chars) {
     65       value_ = chars;
     66     } else {
     67       value_.clear();
     68     }
     69     return *this;
     70   }
     71 
     72   String& operator=(std::string&& other) {
     73     value_ = std::move(other);
     74     is_null_ = false;
     75     return *this;
     76   }
     77   String& operator=(String&& other) {
     78     is_null_ = true;
     79     value_.clear();
     80     Swap(&other);
     81     return *this;
     82   }
     83 
     84   bool is_null() const { return is_null_; }
     85 
     86   size_t size() const { return value_.size(); }
     87 
     88   const char* data() const { return value_.data(); }
     89 
     90   const char& at(size_t offset) const { return value_.at(offset); }
     91   const char& operator[](size_t offset) const { return value_[offset]; }
     92 
     93   const std::string& get() const { return value_; }
     94   operator const std::string&() const { return value_; }
     95 
     96   // Returns a const reference to the |std::string| managed by this class. If
     97   // the string is null, this will be an empty std::string.
     98   const std::string& storage() const { return value_; }
     99 
    100   // Passes the underlying storage and resets this string to null.
    101   std::string PassStorage() {
    102     is_null_ = true;
    103     return std::move(value_);
    104   }
    105 
    106   void Swap(String* other) {
    107     std::swap(is_null_, other->is_null_);
    108     value_.swap(other->value_);
    109   }
    110 
    111   void Swap(std::string* other) {
    112     is_null_ = false;
    113     value_.swap(*other);
    114   }
    115 
    116  private:
    117   typedef std::string String::*Testable;
    118 
    119  public:
    120   operator Testable() const { return is_null_ ? 0 : &String::value_; }
    121 
    122  private:
    123   std::string value_;
    124   bool is_null_;
    125 };
    126 
    127 inline bool operator==(const String& a, const String& b) {
    128   return a.is_null() == b.is_null() && a.get() == b.get();
    129 }
    130 inline bool operator==(const char* a, const String& b) {
    131   return !b.is_null() && a == b.get();
    132 }
    133 inline bool operator==(const String& a, const char* b) {
    134   return !a.is_null() && a.get() == b;
    135 }
    136 inline bool operator!=(const String& a, const String& b) {
    137   return !(a == b);
    138 }
    139 inline bool operator!=(const char* a, const String& b) {
    140   return !(a == b);
    141 }
    142 inline bool operator!=(const String& a, const char* b) {
    143   return !(a == b);
    144 }
    145 
    146 inline std::ostream& operator<<(std::ostream& out, const String& s) {
    147   return out << s.get();
    148 }
    149 
    150 inline bool operator<(const String& a, const String& b) {
    151   if (a.is_null())
    152     return !b.is_null();
    153   if (b.is_null())
    154     return false;
    155 
    156   return a.get() < b.get();
    157 }
    158 
    159 // TODO(darin): Add similar variants of operator<,<=,>,>=
    160 
    161 template <>
    162 struct TypeConverter<String, std::string> {
    163   static String Convert(const std::string& input) { return String(input); }
    164 };
    165 
    166 template <>
    167 struct TypeConverter<std::string, String> {
    168   static std::string Convert(const String& input) { return input; }
    169 };
    170 
    171 template <size_t N>
    172 struct TypeConverter<String, char[N]> {
    173   static String Convert(const char input[N]) {
    174     DCHECK(input);
    175     return String(input, N - 1);
    176   }
    177 };
    178 
    179 // Appease MSVC.
    180 template <size_t N>
    181 struct TypeConverter<String, const char[N]> {
    182   static String Convert(const char input[N]) {
    183     DCHECK(input);
    184     return String(input, N - 1);
    185   }
    186 };
    187 
    188 template <>
    189 struct TypeConverter<String, const char*> {
    190   // |input| may be null, in which case a null String will be returned.
    191   static String Convert(const char* input) { return String(input); }
    192 };
    193 
    194 }  // namespace mojo
    195 
    196 #endif  // MOJO_PUBLIC_CPP_BINDINGS_STRING_H_
    197