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