Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/xpcom/string/nsTPromiseFlatString.h
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#ifndef nsTPromiseFlatString_h
8
#define nsTPromiseFlatString_h
9
10
#include "nsTString.h"
11
12
/**
13
 * NOTE:
14
 *
15
 * Try to avoid flat strings.  |PromiseFlat[C]String| will help you as a last
16
 * resort, and this may be necessary when dealing with legacy or OS calls,
17
 * but in general, requiring a null-terminated array of characters kills many
18
 * of the performance wins the string classes offer.  Write your own code to
19
 * use |nsA[C]String&|s for parameters.  Write your string proccessing
20
 * algorithms to exploit iterators.  If you do this, you will benefit from
21
 * being able to chain operations without copying or allocating and your code
22
 * will be significantly more efficient.  Remember, a function that takes an
23
 * |const nsA[C]String&| can always be passed a raw character pointer by
24
 * wrapping it (for free) in a |nsDependent[C]String|.  But a function that
25
 * takes a character pointer always has the potential to force allocation and
26
 * copying.
27
 *
28
 *
29
 * How to use it:
30
 *
31
 * A |nsPromiseFlat[C]String| doesn't necessarily own the characters it
32
 * promises.  You must never use it to promise characters out of a string
33
 * with a shorter lifespan.  The typical use will be something like this:
34
 *
35
 *   SomeOSFunction( PromiseFlatCString(aCSubstring).get() ); // GOOD
36
 *
37
 * Here's a BAD use:
38
 *
39
 *  const char* buffer = PromiseFlatCString(aCSubstring).get();
40
 *  SomeOSFunction(buffer); // BAD!! |buffer| is a dangling pointer
41
 *
42
 * The only way to make one is with the function |PromiseFlat[C]String|,
43
 * which produce a |const| instance.  ``What if I need to keep a promise
44
 * around for a little while?'' you might ask.  In that case, you can keep a
45
 * reference, like so:
46
 *
47
 *   const nsCString& flat = PromiseFlatString(aCSubstring);
48
 *     // Temporaries usually die after the full expression containing the
49
 *     // expression that created the temporary is evaluated.  But when a
50
 *     // temporary is assigned to a local reference, the temporary's lifetime
51
 *     // is extended to the reference's lifetime (C++11 [class.temporary]p5).
52
 *     //
53
 *     // This reference holds the anonymous temporary alive.  But remember: it
54
 *     // must _still_ have a lifetime shorter than that of |aCSubstring|, and
55
 *     // |aCSubstring| must not be changed while the PromiseFlatString lives.
56
 *
57
 *  SomeOSFunction(flat.get());
58
 *  SomeOtherOSFunction(flat.get());
59
 *
60
 *
61
 * How does it work?
62
 *
63
 * A |nsPromiseFlat[C]String| is just a wrapper for another string.  If you
64
 * apply it to a string that happens to be flat, your promise is just a
65
 * dependent reference to the string's data.  If you apply it to a non-flat
66
 * string, then a temporary flat string is created for you, by allocating and
67
 * copying.  In the event that you end up assigning the result into a sharing
68
 * string (e.g., |nsTString|), the right thing happens.
69
 */
70
71
template <typename T>
72
class nsTPromiseFlatString : public nsTString<T>
73
{
74
public:
75
76
  typedef nsTPromiseFlatString<T> self_type;
77
  typedef nsTString<T> base_string_type;
78
  typedef typename base_string_type::substring_type substring_type;
79
  typedef typename base_string_type::string_type string_type;
80
  typedef typename base_string_type::substring_tuple_type substring_tuple_type;
81
  typedef typename base_string_type::char_type char_type;
82
  typedef typename base_string_type::size_type size_type;
83
84
  // These are only for internal use within the string classes:
85
  typedef typename base_string_type::DataFlags DataFlags;
86
  typedef typename base_string_type::ClassFlags ClassFlags;
87
88
private:
89
90
  void Init(const substring_type&);
91
92
  // NOT TO BE IMPLEMENTED
93
  void operator=(const self_type&) = delete;
94
95
  // NOT TO BE IMPLEMENTED
96
  nsTPromiseFlatString() = delete;
97
98
  // NOT TO BE IMPLEMENTED
99
  nsTPromiseFlatString(const string_type& aStr) = delete;
100
101
public:
102
103
  explicit
104
  nsTPromiseFlatString(const substring_type& aStr)
105
    : string_type()
106
130k
  {
107
130k
    Init(aStr);
108
130k
  }
109
110
  explicit
111
  nsTPromiseFlatString(const substring_tuple_type& aTuple)
112
    : string_type()
113
0
  {
114
0
    // nothing else to do here except assign the value of the tuple
115
0
    // into ourselves.
116
0
    this->Assign(aTuple);
117
0
  }
Unexecuted instantiation: nsTPromiseFlatString<char>::nsTPromiseFlatString(nsTSubstringTuple<char> const&)
Unexecuted instantiation: nsTPromiseFlatString<char16_t>::nsTPromiseFlatString(nsTSubstringTuple<char16_t> const&)
118
};
119
120
extern template class nsTPromiseFlatString<char>;
121
extern template class nsTPromiseFlatString<char16_t>;
122
123
// We template this so that the constructor is chosen based on the type of the
124
// parameter. This allows us to reject attempts to promise a flat flat string.
125
template<class T>
126
const nsTPromiseFlatString<T>
127
TPromiseFlatString(const typename nsTPromiseFlatString<T>::substring_type& aString)
128
{
129
  return nsTPromiseFlatString<T>(aString);
130
}
131
132
template<class T>
133
const nsTPromiseFlatString<T>
134
TPromiseFlatString(const typename nsTPromiseFlatString<T>::substring_tuple_type& aString)
135
{
136
  return nsTPromiseFlatString<T>(aString);
137
}
138
139
#ifndef PromiseFlatCString
140
#define PromiseFlatCString TPromiseFlatString<char>
141
#endif
142
143
#ifndef PromiseFlatString
144
#define PromiseFlatString TPromiseFlatString<char16_t>
145
#endif
146
147
#endif