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