ScriptDecoding.h (3371B)
1 /* -*- Mode: C++; tab-width: 8; 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 /* Script decoding templates for processing byte data as UTF-8 or UTF-16. */ 8 9 #ifndef mozilla_dom_ScriptDecoding_h 10 #define mozilla_dom_ScriptDecoding_h 11 12 #include <stddef.h> // size_t 13 #include <stdint.h> // uint8_t, uint32_t 14 15 #include <type_traits> // std::is_same 16 17 #include "mozilla/Assertions.h" // MOZ_ASSERT 18 #include "mozilla/CheckedInt.h" // mozilla::CheckedInt 19 #include "mozilla/Encoding.h" // mozilla::Decoder 20 #include "mozilla/Span.h" // mozilla::Span 21 #include "mozilla/UniquePtr.h" // mozilla::UniquePtr 22 23 namespace mozilla::dom { 24 25 template <typename Unit> 26 struct ScriptDecoding { 27 static_assert(std::is_same<Unit, char16_t>::value || 28 std::is_same<Unit, Utf8Unit>::value, 29 "must be either UTF-8 or UTF-16"); 30 }; 31 32 template <> 33 struct ScriptDecoding<char16_t> { 34 static CheckedInt<size_t> MaxBufferLength(const UniquePtr<Decoder>& aDecoder, 35 uint32_t aByteLength) { 36 return aDecoder->MaxUTF16BufferLength(aByteLength); 37 } 38 39 static size_t DecodeInto(const UniquePtr<Decoder>& aDecoder, 40 const Span<const uint8_t>& aSrc, 41 Span<char16_t> aDest, bool aEndOfSource) { 42 uint32_t result; 43 size_t read; 44 size_t written; 45 std::tie(result, read, written, std::ignore) = 46 aDecoder->DecodeToUTF16(aSrc, aDest, aEndOfSource); 47 MOZ_ASSERT(result == kInputEmpty); 48 MOZ_ASSERT(read == aSrc.Length()); 49 MOZ_ASSERT(written <= aDest.Length()); 50 51 return written; 52 } 53 }; 54 55 template <> 56 struct ScriptDecoding<Utf8Unit> { 57 static CheckedInt<size_t> MaxBufferLength(const UniquePtr<Decoder>& aDecoder, 58 uint32_t aByteLength) { 59 return aDecoder->MaxUTF8BufferLength(aByteLength); 60 } 61 62 static size_t DecodeInto(const UniquePtr<Decoder>& aDecoder, 63 const Span<const uint8_t>& aSrc, 64 Span<Utf8Unit> aDest, bool aEndOfSource) { 65 uint32_t result; 66 size_t read; 67 size_t written; 68 // Until C++ char8_t happens, our decoder APIs deal in |uint8_t| while 69 // |Utf8Unit| internally deals with |char|, so there's inevitable impedance 70 // mismatch between |aDest| as |Utf8Unit| and |AsWritableBytes(aDest)| as 71 // |Span<uint8_t>|. :-( The written memory will be interpreted through 72 // |char Utf8Unit::mValue| which is *permissible* because any object's 73 // memory can be interpreted as |char|. Unfortunately, until 74 // twos-complement is mandated, we have to play fast and loose and *hope* 75 // interpreting memory storing |uint8_t| as |char| will pick up the desired 76 // wrapped-around value. ¯\_(ツ)_/¯ 77 std::tie(result, read, written, std::ignore) = 78 aDecoder->DecodeToUTF8(aSrc, AsWritableBytes(aDest), aEndOfSource); 79 MOZ_ASSERT(result == kInputEmpty); 80 MOZ_ASSERT(read == aSrc.Length()); 81 MOZ_ASSERT(written <= aDest.Length()); 82 83 return written; 84 } 85 }; 86 87 } // namespace mozilla::dom 88 89 #endif // mozilla_dom_ScriptDecoding_h