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 mozilla_ArenaAllocatorExtensions_h
8 #define mozilla_ArenaAllocatorExtensions_h
9 
10 #include "mozilla/ArenaAllocator.h"
11 #include "mozilla/CheckedInt.h"
12 #include "nsAString.h"
13 
14 /**
15  * Extensions to the ArenaAllocator class.
16  */
17 namespace mozilla {
18 
19 namespace detail {
20 
21 template <typename T, size_t ArenaSize, size_t Alignment>
22 T* DuplicateString(const T* aSrc, const CheckedInt<size_t>& aLen,
23                    ArenaAllocator<ArenaSize, Alignment>& aArena);
24 
25 }  // namespace detail
26 
27 /**
28  * Makes an arena allocated null-terminated copy of the source string. The
29  * source string must be null-terminated.
30  *
31  * @param aSrc String to copy.
32  * @param aArena The arena to allocate the string copy out of.
33  * @return An arena allocated null-terminated string.
34  */
35 template <typename T, size_t ArenaSize, size_t Alignment>
ArenaStrdup(const T * aStr,ArenaAllocator<ArenaSize,Alignment> & aArena)36 T* ArenaStrdup(const T* aStr, ArenaAllocator<ArenaSize, Alignment>& aArena) {
37   return detail::DuplicateString(aStr, nsCharTraits<T>::length(aStr), aArena);
38 }
39 
40 /**
41  * Makes an arena allocated null-terminated copy of the source string.
42  *
43  * @param aSrc String to copy.
44  * @param aArena The arena to allocate the string copy out of.
45  * @return An arena allocated null-terminated string.
46  */
47 template <typename T, size_t ArenaSize, size_t Alignment>
ArenaStrdup(const detail::nsTStringRepr<T> & aStr,ArenaAllocator<ArenaSize,Alignment> & aArena)48 T* ArenaStrdup(const detail::nsTStringRepr<T>& aStr,
49                ArenaAllocator<ArenaSize, Alignment>& aArena) {
50   return detail::DuplicateString(aStr.BeginReading(), aStr.Length(), aArena);
51 }
52 
53 /**
54  * Copies the source string and adds a null terminator. Source string does not
55  * have to be null terminated.
56  */
57 template <typename T, size_t ArenaSize, size_t Alignment>
DuplicateString(const T * aSrc,const CheckedInt<size_t> & aLen,ArenaAllocator<ArenaSize,Alignment> & aArena)58 T* detail::DuplicateString(const T* aSrc, const CheckedInt<size_t>& aLen,
59                            ArenaAllocator<ArenaSize, Alignment>& aArena) {
60   const auto byteLen = (aLen + 1) * sizeof(T);
61   if (!byteLen.isValid()) {
62     return nullptr;
63   }
64 
65   T* p = static_cast<T*>(aArena.Allocate(byteLen.value(), mozilla::fallible));
66   if (p) {
67     memcpy(p, aSrc, byteLen.value() - sizeof(T));
68     p[aLen.value()] = T(0);
69   }
70 
71   return p;
72 }
73 
74 }  // namespace mozilla
75 
76 #endif  // mozilla_ArenaAllocatorExtensions_h
77