[flang] Accept polymorphic component element in storage_size
[llvm-project.git] / flang / runtime / emit-encoded.h
blob192c7ec068a4e0c143bbb1beb987c088afcaa210
1 //===-- runtime/emit-encoded.h ----------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 // Templates for emitting CHARACTER values with conversion
11 #ifndef FORTRAN_RUNTIME_EMIT_ENCODED_H_
12 #define FORTRAN_RUNTIME_EMIT_ENCODED_H_
14 #include "connection.h"
15 #include "environment.h"
16 #include "utf.h"
18 namespace Fortran::runtime::io {
20 template <typename CONTEXT, typename CHAR>
21 bool EmitEncoded(CONTEXT &to, const CHAR *data, std::size_t chars) {
22 ConnectionState &connection{to.GetConnectionState()};
23 if (connection.useUTF8<CHAR>()) {
24 using UnsignedChar = std::make_unsigned_t<CHAR>;
25 const UnsignedChar *uData{reinterpret_cast<const UnsignedChar *>(data)};
26 char buffer[256];
27 std::size_t at{0};
28 while (chars-- > 0) {
29 auto len{EncodeUTF8(buffer + at, *uData++)};
30 at += len;
31 if (at + maxUTF8Bytes > sizeof buffer) {
32 if (!to.Emit(buffer, at)) {
33 return false;
35 at = 0;
38 return at == 0 || to.Emit(buffer, at);
39 } else {
40 std::size_t internalKind = connection.internalIoCharKind;
41 if (internalKind == 0 || internalKind == sizeof(CHAR)) {
42 const char *rawData{reinterpret_cast<const char *>(data)};
43 return to.Emit(rawData, chars * sizeof(CHAR), sizeof(CHAR));
44 } else {
45 // CHARACTER kind conversion for internal output
46 while (chars-- > 0) {
47 char32_t buffer = *data++;
48 char *p{reinterpret_cast<char *>(&buffer)};
49 if constexpr (!isHostLittleEndian) {
50 p += sizeof(buffer) - internalKind;
52 if (!to.Emit(p, internalKind)) {
53 return false;
56 return true;
61 template <typename CONTEXT>
62 bool EmitAscii(CONTEXT &to, const char *data, std::size_t chars) {
63 ConnectionState &connection{to.GetConnectionState()};
64 if (connection.internalIoCharKind <= 1) {
65 return to.Emit(data, chars);
66 } else {
67 return EmitEncoded(to, data, chars);
71 template <typename CONTEXT>
72 bool EmitRepeated(CONTEXT &to, char ch, std::size_t n) {
73 if (n <= 0) {
74 return true;
76 ConnectionState &connection{to.GetConnectionState()};
77 if (connection.internalIoCharKind <= 1) {
78 while (n-- > 0) {
79 if (!to.Emit(&ch, 1)) {
80 return false;
83 } else {
84 while (n-- > 0) {
85 if (!EmitEncoded(to, &ch, 1)) {
86 return false;
90 return true;
93 } // namespace Fortran::runtime::io
94 #endif // FORTRAN_RUNTIME_EMIT_ENCODED_H_