xref: /llvm-project/flang/lib/Evaluate/static-data.cpp (revision 23c2bedfd93cfacc62009425c464e659a34e92e6)
1 //===-- lib/Evaluate/static-data.cpp --------------------------------------===//
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 //===----------------------------------------------------------------------===//
8 
9 #include "flang/Evaluate/static-data.h"
10 #include "flang/Parser/characters.h"
11 
12 namespace Fortran::evaluate {
13 
AsFortran(llvm::raw_ostream & o,bool bigEndian) const14 llvm::raw_ostream &StaticDataObject::AsFortran(
15     llvm::raw_ostream &o, bool bigEndian) const {
16   if (auto string{AsString()}) {
17     o << parser::QuoteCharacterLiteral(*string);
18   } else if (auto string{AsU16String(bigEndian)}) {
19     o << "2_" << parser::QuoteCharacterLiteral(*string);
20   } else if (auto string{AsU32String(bigEndian)}) {
21     o << "4_" << parser::QuoteCharacterLiteral(*string);
22   } else {
23     CRASH_NO_CASE;
24   }
25   return o;
26 }
27 
Push(const std::string & string,bool)28 StaticDataObject &StaticDataObject::Push(const std::string &string, bool) {
29   for (auto ch : string) {
30     data_.push_back(static_cast<std::uint8_t>(ch));
31   }
32   return *this;
33 }
34 
Push(const std::u16string & string,bool bigEndian)35 StaticDataObject &StaticDataObject::Push(
36     const std::u16string &string, bool bigEndian) {
37   int shift{bigEndian ? 8 : 0};
38   for (auto ch : string) {
39     data_.push_back(static_cast<std::uint8_t>(ch >> shift));
40     data_.push_back(static_cast<std::uint8_t>(ch >> (shift ^ 8)));
41   }
42   return *this;
43 }
44 
Push(const std::u32string & string,bool bigEndian)45 StaticDataObject &StaticDataObject::Push(
46     const std::u32string &string, bool bigEndian) {
47   int shift{bigEndian ? 24 : 0};
48   for (auto ch : string) {
49     data_.push_back(static_cast<std::uint8_t>(ch >> shift));
50     data_.push_back(static_cast<std::uint8_t>(ch >> (shift ^ 8)));
51     data_.push_back(static_cast<std::uint8_t>(ch >> (shift ^ 16)));
52     data_.push_back(static_cast<std::uint8_t>(ch >> (shift ^ 24)));
53   }
54   return *this;
55 }
56 
AsString() const57 std::optional<std::string> StaticDataObject::AsString() const {
58   if (itemBytes_ <= 1) {
59     std::string result;
60     for (std::uint8_t byte : data_) {
61       result += static_cast<char>(byte);
62     }
63     return {std::move(result)};
64   }
65   return std::nullopt;
66 }
67 
AsU16String(bool bigEndian) const68 std::optional<std::u16string> StaticDataObject::AsU16String(
69     bool bigEndian) const {
70   if (itemBytes_ == 2) {
71     int shift{bigEndian ? 8 : 0};
72     std::u16string result;
73     auto end{data_.cend()};
74     for (auto byte{data_.cbegin()}; byte < end;) {
75       result += static_cast<char16_t>(*byte++) << shift |
76           static_cast<char16_t>(*byte++) << (shift ^ 8);
77     }
78     return {std::move(result)};
79   }
80   return std::nullopt;
81 }
82 
AsU32String(bool bigEndian) const83 std::optional<std::u32string> StaticDataObject::AsU32String(
84     bool bigEndian) const {
85   if (itemBytes_ == 4) {
86     int shift{bigEndian ? 24 : 0};
87     std::u32string result;
88     auto end{data_.cend()};
89     for (auto byte{data_.cbegin()}; byte < end;) {
90       result += static_cast<char32_t>(*byte++) << shift |
91           static_cast<char32_t>(*byte++) << (shift ^ 8) |
92           static_cast<char32_t>(*byte++) << (shift ^ 16) |
93           static_cast<char32_t>(*byte++) << (shift ^ 24);
94     }
95     return {std::move(result)};
96   }
97   return std::nullopt;
98 }
99 } // namespace Fortran::evaluate
100