summaryrefslogtreecommitdiffstats
path: root/tools/profiler/public/ProfileBufferEntrySerializationGeckoExtensions.h
blob: 1578bd2ddc327c5ca4034d1288a24cbe7ce1223a (plain)
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