1 /* 2 * Copyright (c) 2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef ECMASCRIPT_BASE_FILE_HEADER_H 17 #define ECMASCRIPT_BASE_FILE_HEADER_H 18 19 #include "ecmascript/base/string_helper.h" 20 #include "ecmascript/log_wrapper.h" 21 #include <array> 22 #include <stddef.h> 23 #include <stdint.h> 24 25 namespace panda::ecmascript::base { 26 class FileHeader { 27 public: 28 static constexpr size_t MAGIC_SIZE = 8; 29 static constexpr size_t VERSION_SIZE = 4; 30 static constexpr std::array<uint8_t, MAGIC_SIZE> MAGIC = {'P', 'A', 'N', 'D', 'A', '\0', '\0', '\0'}; 31 using VersionType = std::array<uint8_t, VERSION_SIZE>; 32 ToVersion(uint32_t versionNumber)33 static const VersionType ToVersion(uint32_t versionNumber) 34 { 35 VersionUnion helper = {.versionNumber = ReverseBytes(versionNumber)}; 36 return helper.version; 37 } 38 ToVersionNumber(const VersionType & version)39 static uint32_t ToVersionNumber(const VersionType &version) 40 { 41 VersionUnion helper = {.version = version}; 42 return ReverseBytes(helper.versionNumber); 43 } 44 VerifyVersion(const char * fileDesc,uint32_t currVersion,uint32_t lastVersion,bool silent)45 static bool VerifyVersion(const char *fileDesc, uint32_t currVersion, uint32_t lastVersion, bool silent) 46 { 47 return VerifyVersion(fileDesc, ToVersion(currVersion), ToVersion(lastVersion), silent); 48 } 49 50 protected: 51 FileHeader(const VersionType & lastVersion)52 FileHeader(const VersionType &lastVersion) : magic_(MAGIC), version_(lastVersion) {} 53 54 static bool VerifyVersion(const char *fileDesc, const VersionType &currVersion, const VersionType &lastVersion, 55 bool silent = false) 56 { 57 if (currVersion > lastVersion) { 58 if (!silent) { 59 LOG_HOST_TOOL_ERROR << fileDesc << " version error, expected version should be less or equal than " 60 << ConvToStr(lastVersion) << ", but got " << ConvToStr(currVersion); 61 } 62 return false; 63 } 64 return true; 65 } 66 VerifyInner(const char * fileDesc,const VersionType & lastVersion)67 bool VerifyInner(const char* fileDesc, const VersionType &lastVersion) const 68 { 69 if (magic_ != MAGIC) { 70 LOG_HOST_TOOL_ERROR << "Magic mismatch, please make sure " << fileDesc << 71 " and the source code are matched"; 72 LOG_ECMA(ERROR) << "magic error, expected magic is " << ConvToStr(MAGIC) 73 << ", but got " << ConvToStr(magic_); 74 return false; 75 } 76 if (!VerifyVersion(fileDesc, version_, lastVersion)) { 77 return false; 78 } 79 LOG_ECMA(DEBUG) << "Magic:" << ConvToStr(magic_) << ", version:" << GetVersionInner(); 80 return true; 81 } 82 GetVersionInner()83 std::string GetVersionInner() const 84 { 85 return ConvToStr(version_); 86 } 87 SetVersionInner(std::string version)88 bool SetVersionInner(std::string version) 89 { 90 std::vector<std::string> versionNumber = StringHelper::SplitString(version, "."); 91 if (versionNumber.size() != VERSION_SIZE) { 92 LOG_ECMA(ERROR) << "version: " << version << " format error"; 93 return false; 94 } 95 for (uint32_t i = 0; i < VERSION_SIZE; i++) { 96 uint32_t result; 97 if (!StringHelper::StrToUInt32(versionNumber[i].c_str(), &result)) { 98 LOG_ECMA(ERROR) << "version: " << version << " format error"; 99 return false; 100 } 101 version_[i] = static_cast<uint8_t>(result); 102 } 103 return true; 104 } 105 106 private: 107 union VersionUnion { 108 VersionType version; 109 uint32_t versionNumber; 110 static_assert(sizeof(VersionType) == sizeof(uint32_t)); 111 }; 112 113 template <size_t size> ConvToStr(const std::array<uint8_t,size> & array)114 static std::string ConvToStr(const std::array<uint8_t, size> &array) 115 { 116 std::string ret = ""; 117 for (size_t i = 0; i < size; ++i) { 118 if (i) { 119 ret += "."; 120 } 121 ret += std::to_string(array[i]); 122 } 123 return ret; 124 } 125 126 std::array<uint8_t, MAGIC_SIZE> magic_; 127 VersionType version_; 128 }; 129 130 } // namespace panda::ecmascript::base 131 #endif // ECMASCRIPT_BASE_FILE_HEADER_H 132