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 
14 bool StaticDataObject::bigEndian{false};
15 
AsFortran(llvm::raw_ostream & o) const16 llvm::raw_ostream &StaticDataObject::AsFortran(llvm::raw_ostream &o) const {
17   if (auto string{AsString()}) {
18     o << parser::QuoteCharacterLiteral(*string);
19   } else if (auto string{AsU16String()}) {
20     o << "2_" << parser::QuoteCharacterLiteral(*string);
21   } else if (auto string{AsU32String()}) {
22     o << "4_" << parser::QuoteCharacterLiteral(*string);
23   } else {
24     CRASH_NO_CASE;
25   }
26   return o;
27 }
28 
Push(const std::string & string)29 StaticDataObject &StaticDataObject::Push(const std::string &string) {
30   for (auto ch : string) {
31     data_.push_back(static_cast<std::uint8_t>(ch));
32   }
33   return *this;
34 }
35 
Push(const std::u16string & string)36 StaticDataObject &StaticDataObject::Push(const std::u16string &string) {
37   int shift{bigEndian * 8};
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)45 StaticDataObject &StaticDataObject::Push(const std::u32string &string) {
46   int shift{bigEndian * 24};
47   for (auto ch : string) {
48     data_.push_back(static_cast<std::uint8_t>(ch >> shift));
49     data_.push_back(static_cast<std::uint8_t>(ch >> (shift ^ 8)));
50     data_.push_back(static_cast<std::uint8_t>(ch >> (shift ^ 16)));
51     data_.push_back(static_cast<std::uint8_t>(ch >> (shift ^ 24)));
52   }
53   return *this;
54 }
55 
AsString() const56 std::optional<std::string> StaticDataObject::AsString() const {
57   if (itemBytes_ <= 1) {
58     std::string result;
59     for (std::uint8_t byte : data_) {
60       result += static_cast<char>(byte);
61     }
62     return {std::move(result)};
63   }
64   return std::nullopt;
65 }
66 
AsU16String() const67 std::optional<std::u16string> StaticDataObject::AsU16String() const {
68   if (itemBytes_ == 2) {
69     int shift{bigEndian * 8};
70     std::u16string result;
71     auto end{data_.cend()};
72     for (auto byte{data_.cbegin()}; byte < end;) {
73       result += static_cast<char16_t>(*byte++) << shift |
74           static_cast<char16_t>(*byte++) << (shift ^ 8);
75     }
76     return {std::move(result)};
77   }
78   return std::nullopt;
79 }
80 
AsU32String() const81 std::optional<std::u32string> StaticDataObject::AsU32String() const {
82   if (itemBytes_ == 4) {
83     int shift{bigEndian * 24};
84     std::u32string result;
85     auto end{data_.cend()};
86     for (auto byte{data_.cbegin()}; byte < end;) {
87       result += static_cast<char32_t>(*byte++) << shift |
88           static_cast<char32_t>(*byte++) << (shift ^ 8) |
89           static_cast<char32_t>(*byte++) << (shift ^ 16) |
90           static_cast<char32_t>(*byte++) << (shift ^ 24);
91     }
92     return {std::move(result)};
93   }
94   return std::nullopt;
95 }
96 } // namespace Fortran::evaluate
97