1 /* -*- Mode: C++; tab-width: 2; 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 ProfileBufferEntrySerializationGeckoExtensions_h 8 #define ProfileBufferEntrySerializationGeckoExtensions_h 9 10 #include "mozilla/ProfileBufferEntrySerialization.h" 11 12 #include "js/AllocPolicy.h" 13 #include "js/Utility.h" 14 #include "nsString.h" 15 16 namespace mozilla { 17 18 // ---------------------------------------------------------------------------- 19 // ns[C]String 20 21 // nsString or nsCString contents are serialized as the number of bytes (encoded 22 // as ULEB128) and all the characters in the string. The terminal '\0' is 23 // omitted. 24 // Make sure you write and read with the same character type! 25 // 26 // Usage: `nsCString s = ...; aEW.WriteObject(s);` 27 template <typename T> 28 struct ProfileBufferEntryWriter::Serializer<nsTString<T>> { 29 static Length Bytes(const nsTString<T>& aS) { 30 // Note that we store the size in *bytes*, not in number of characters. 31 const auto bytes = aS.Length() * sizeof(T); 32 return ProfileBufferEntryWriter::ULEB128Size(bytes) + 33 static_cast<Length>(bytes); 34 } 35 36 static void Write(ProfileBufferEntryWriter& aEW, const nsTString<T>& aS) { 37 // Note that we store the size in *bytes*, not in number of characters. 38 const auto bytes = aS.Length() * sizeof(T); 39 aEW.WriteULEB128(bytes); 40 // Copy the bytes from the string's buffer. 41 aEW.WriteBytes(reinterpret_cast<const char*>(aS.BeginReading()), bytes); 42 } 43 }; 44 45 template <typename T> 46 struct ProfileBufferEntryReader::Deserializer<nsTString<T>> { 47 static void ReadInto(ProfileBufferEntryReader& aER, nsTString<T>& aS) { 48 aS = Read(aER); 49 } 50 51 static nsTString<T> Read(ProfileBufferEntryReader& aER) { 52 // Note that the stored size is in *bytes*, not in number of characters. 53 const auto bytes = aER.ReadULEB128<Length>(); 54 nsTString<T> s; 55 nsresult rv; 56 // BulkWrite is the most efficient way to copy bytes into the target string. 57 auto writer = s.BulkWrite(bytes / sizeof(T), 0, true, rv); 58 MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv)); 59 aER.ReadBytes(reinterpret_cast<char*>(writer.Elements()), bytes); 60 writer.Finish(bytes / sizeof(T), true); 61 return s; 62 } 63 }; 64 65 // ---------------------------------------------------------------------------- 66 // nsAuto[C]String 67 68 // nsAuto[C]String contents are serialized as the number of bytes (encoded as 69 // ULEB128) and all the characters in the string. The terminal '\0' is omitted. 70 // Make sure you write and read with the same character type! 71 // 72 // Usage: `nsAutoCString s = ...; aEW.WriteObject(s);` 73 template <typename T, size_t N> 74 struct ProfileBufferEntryWriter::Serializer<nsTAutoStringN<T, N>> { 75 static Length Bytes(const nsTAutoStringN<T, N>& aS) { 76 // Note that we store the size in *bytes*, not in number of characters. 77 const auto bytes = aS.Length() * sizeof(T); 78 return ProfileBufferEntryWriter::ULEB128Size(bytes) + 79 static_cast<Length>(bytes); 80 } 81 82 static void Write(ProfileBufferEntryWriter& aEW, 83 const nsTAutoStringN<T, N>& aS) { 84 const auto bytes = aS.Length() * sizeof(T); 85 // Note that we store the size in *bytes*, not in number of characters. 86 aEW.WriteULEB128(bytes); 87 // Copy the bytes from the string's buffer. 88 aEW.WriteBytes(reinterpret_cast<const char*>(aS.BeginReading()), bytes); 89 } 90 }; 91 92 template <typename T, size_t N> 93 struct ProfileBufferEntryReader::Deserializer<nsTAutoStringN<T, N>> { 94 static void ReadInto(ProfileBufferEntryReader& aER, 95 nsTAutoStringN<T, N>& aS) { 96 aS = Read(aER); 97 } 98 99 static nsTAutoStringN<T, N> Read(ProfileBufferEntryReader& aER) { 100 // Note that the stored size is in *bytes*, not in number of characters. 101 const auto bytes = aER.ReadULEB128<Length>(); 102 nsTAutoStringN<T, N> s; 103 nsresult rv; 104 // BulkWrite is the most efficient way to copy bytes into the target string. 105 auto writer = s.BulkWrite(bytes / sizeof(T), 0, true, rv); 106 MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv)); 107 aER.ReadBytes(reinterpret_cast<char*>(writer.Elements()), bytes); 108 writer.Finish(bytes / sizeof(T), true); 109 return s; 110 } 111 }; 112 113 // ---------------------------------------------------------------------------- 114 // JS::UniqueChars 115 116 // JS::UniqueChars contents are serialized as the number of bytes (encoded as 117 // ULEB128) and all the characters in the string. The terminal '\0' is omitted. 118 // Note: A nullptr pointer will be serialized like an empty string, so when 119 // deserializing it will result in an allocated buffer only containing a 120 // single null terminator. 121 // 122 // Usage: `JS::UniqueChars s = ...; aEW.WriteObject(s);` 123 template <> 124 struct ProfileBufferEntryWriter::Serializer<JS::UniqueChars> { 125 static Length Bytes(const JS::UniqueChars& aS) { 126 if (!aS) { 127 return ProfileBufferEntryWriter::ULEB128Size<Length>(0); 128 } 129 const auto len = static_cast<Length>(strlen(aS.get())); 130 return ProfileBufferEntryWriter::ULEB128Size(len) + len; 131 } 132 133 static void Write(ProfileBufferEntryWriter& aEW, const JS::UniqueChars& aS) { 134 if (!aS) { 135 aEW.WriteULEB128<Length>(0); 136 return; 137 } 138 const auto len = static_cast<Length>(strlen(aS.get())); 139 aEW.WriteULEB128(len); 140 aEW.WriteBytes(aS.get(), len); 141 } 142 }; 143 144 template <> 145 struct ProfileBufferEntryReader::Deserializer<JS::UniqueChars> { 146 static void ReadInto(ProfileBufferEntryReader& aER, JS::UniqueChars& aS) { 147 aS = Read(aER); 148 } 149 150 static JS::UniqueChars Read(ProfileBufferEntryReader& aER) { 151 const auto len = aER.ReadULEB128<Length>(); 152 // Use the same allocation policy as JS_smprintf. 153 char* buffer = 154 static_cast<char*>(js::SystemAllocPolicy{}.pod_malloc<char>(len + 1)); 155 aER.ReadBytes(buffer, len); 156 buffer[len] = '\0'; 157 return JS::UniqueChars(buffer); 158 } 159 }; 160 161 } // namespace mozilla 162 163 #endif // ProfileBufferEntrySerializationGeckoExtensions_h 164