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