| /** | |
| * Licensed to the Apache Software Foundation (ASF) under one | |
| * or more contributor license agreements. See the NOTICE file | |
| * distributed with this work for additional information | |
| * regarding copyright ownership. The ASF licenses this file | |
| * to you under the Apache License, Version 2.0 (the | |
| * "License"); you may not use this file except in compliance | |
| * with the License. You may obtain a copy of the License at | |
| * | |
| * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, | |
| * software distributed under the License is distributed on an | |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
| * KIND, either express or implied. See the License for the | |
| * specific language governing permissions and limitations | |
| * under the License. | |
| */ | |
| #include "Common.h" | |
| #include <cstring> | |
| #include <ctime> | |
| #include <typeinfo> | |
| LogLevelType LOG_LEVEL = LEVEL_WARN; | |
| std::string extractExceptionMessage(const std::exception& exception) { | |
| const char* what = exception.what(); | |
| if (what != nullptr) { | |
| std::string message(what); | |
| if (!message.empty() && message != "std::exception") { | |
| return message; | |
| } | |
| } | |
| return std::string("Unhandled exception type: ") + typeid(exception).name(); | |
| } | |
| std::string extractExceptionMessage(const std::exception_ptr& exceptionPtr) { | |
| if (exceptionPtr == nullptr) { | |
| return "Unknown exception"; | |
| } | |
| try { | |
| std::rethrow_exception(exceptionPtr); | |
| } catch (const std::exception& exception) { | |
| return extractExceptionMessage(exception); | |
| } catch (...) { | |
| return "Unknown non-std exception"; | |
| } | |
| } | |
| std::string getTimePrecision(int32_t timeFactor) { | |
| if (timeFactor >= 1000000) | |
| return "us"; | |
| if (timeFactor >= 1000) | |
| return "ms"; | |
| return "s"; | |
| } | |
| std::string formatDatetime(const std::string& format, const std::string& precision, | |
| int64_t timestamp, const std::string& zoneId) { | |
| std::time_t time = static_cast<std::time_t>(timestamp); | |
| std::tm* tm = std::localtime(&time); | |
| char buffer[80]; | |
| strftime(buffer, sizeof(buffer), format.c_str(), tm); | |
| return std::string(buffer); | |
| } | |
| std::tm convertToTimestamp(int64_t value, int32_t timeFactor) { | |
| std::time_t time = static_cast<std::time_t>(value / timeFactor); | |
| return *std::localtime(&time); | |
| } | |
| TSDataType::TSDataType getDataTypeByStr(const std::string& typeStr) { | |
| if (typeStr == "BOOLEAN") | |
| return TSDataType::BOOLEAN; | |
| if (typeStr == "INT32") | |
| return TSDataType::INT32; | |
| if (typeStr == "INT64") | |
| return TSDataType::INT64; | |
| if (typeStr == "FLOAT") | |
| return TSDataType::FLOAT; | |
| if (typeStr == "DOUBLE") | |
| return TSDataType::DOUBLE; | |
| if (typeStr == "TEXT") | |
| return TSDataType::TEXT; | |
| if (typeStr == "TIMESTAMP") | |
| return TSDataType::TIMESTAMP; | |
| if (typeStr == "DATE") | |
| return TSDataType::DATE; | |
| if (typeStr == "BLOB") | |
| return TSDataType::BLOB; | |
| if (typeStr == "STRING") | |
| return TSDataType::STRING; | |
| if (typeStr == "OBJECT") | |
| return TSDataType::OBJECT; | |
| return TSDataType::UNKNOWN; | |
| } | |
| std::tm int32ToDate(int32_t value) { | |
| std::time_t time = static_cast<std::time_t>(value) * 86400; | |
| return *std::localtime(&time); | |
| } | |
| MyStringBuffer::MyStringBuffer() : pos(0) { | |
| checkBigEndian(); | |
| } | |
| MyStringBuffer::MyStringBuffer(const std::string& str) : str(str), pos(0) { | |
| checkBigEndian(); | |
| } | |
| void MyStringBuffer::reserve(size_t n) { | |
| str.reserve(n); | |
| } | |
| void MyStringBuffer::clear() { | |
| str.clear(); | |
| pos = 0; | |
| } | |
| bool MyStringBuffer::hasRemaining() { | |
| return pos < str.size(); | |
| } | |
| int MyStringBuffer::getInt() { | |
| return *(int*)getOrderedByte(4); | |
| } | |
| IoTDBDate MyStringBuffer::getDate() { | |
| return parseIntToDate(getInt()); | |
| } | |
| int64_t MyStringBuffer::getInt64() { | |
| #ifdef ARCH32 | |
| const char* buf_addr = getOrderedByte(8); | |
| if (reinterpret_cast<uint32_t>(buf_addr) % 4 == 0) { | |
| return *(int64_t*)buf_addr; | |
| } else { | |
| char tmp_buf[8]; | |
| memcpy(tmp_buf, buf_addr, 8); | |
| return *(int64_t*)tmp_buf; | |
| } | |
| #else | |
| return *(int64_t*)getOrderedByte(8); | |
| #endif | |
| } | |
| float MyStringBuffer::getFloat() { | |
| return *(float*)getOrderedByte(4); | |
| } | |
| double MyStringBuffer::getDouble() { | |
| #ifdef ARCH32 | |
| const char* buf_addr = getOrderedByte(8); | |
| if (reinterpret_cast<uint32_t>(buf_addr) % 4 == 0) { | |
| return *(double*)buf_addr; | |
| } else { | |
| char tmp_buf[8]; | |
| memcpy(tmp_buf, buf_addr, 8); | |
| return *(double*)tmp_buf; | |
| } | |
| #else | |
| return *(double*)getOrderedByte(8); | |
| #endif | |
| } | |
| char MyStringBuffer::getChar() { | |
| if (pos >= str.size()) { | |
| throw IoTDBException("MyStringBuffer::getChar: read past end (pos=" + std::to_string(pos) + | |
| ", size=" + std::to_string(str.size()) + ")"); | |
| } | |
| return str[pos++]; | |
| } | |
| bool MyStringBuffer::getBool() { | |
| return getChar() == 1; | |
| } | |
| std::string MyStringBuffer::getString() { | |
| const int lenInt = getInt(); | |
| if (lenInt < 0) { | |
| throw IoTDBException("MyStringBuffer::getString: negative length"); | |
| } | |
| const size_t len = static_cast<size_t>(lenInt); | |
| if (pos > str.size() || len > str.size() - pos) { | |
| throw IoTDBException( | |
| "MyStringBuffer::getString: length exceeds buffer (pos=" + std::to_string(pos) + | |
| ", len=" + std::to_string(len) + ", size=" + std::to_string(str.size()) + ")"); | |
| } | |
| const size_t tmpPos = pos; | |
| pos += len; | |
| return str.substr(tmpPos, len); | |
| } | |
| void MyStringBuffer::putInt(int ins) { | |
| putOrderedByte((char*)&ins, 4); | |
| } | |
| void MyStringBuffer::putDate(IoTDBDate date) { | |
| putInt(parseDateExpressionToInt(date)); | |
| } | |
| void MyStringBuffer::putInt64(int64_t ins) { | |
| putOrderedByte((char*)&ins, 8); | |
| } | |
| void MyStringBuffer::putFloat(float ins) { | |
| putOrderedByte((char*)&ins, 4); | |
| } | |
| void MyStringBuffer::putDouble(double ins) { | |
| putOrderedByte((char*)&ins, 8); | |
| } | |
| void MyStringBuffer::putChar(char ins) { | |
| str += ins; | |
| } | |
| void MyStringBuffer::putBool(bool ins) { | |
| char tmp = ins ? 1 : 0; | |
| str += tmp; | |
| } | |
| void MyStringBuffer::putString(const std::string& ins) { | |
| putInt((int)(ins.size())); | |
| str += ins; | |
| } | |
| void MyStringBuffer::concat(const std::string& ins) { | |
| str.append(ins); | |
| } | |
| void MyStringBuffer::checkBigEndian() { | |
| static int chk = 0x0201; | |
| isBigEndian = (0x01 != *(char*)(&chk)); | |
| } | |
| const char* MyStringBuffer::getOrderedByte(size_t len) { | |
| if (pos > str.size() || len > str.size() - pos) { | |
| throw IoTDBException( | |
| "MyStringBuffer::getOrderedByte: read past end (pos=" + std::to_string(pos) + | |
| ", len=" + std::to_string(len) + ", size=" + std::to_string(str.size()) + ")"); | |
| } | |
| const char* p = nullptr; | |
| if (isBigEndian) { | |
| p = str.c_str() + pos; | |
| } else { | |
| const char* tmp = str.c_str(); | |
| for (size_t i = pos; i < pos + len; i++) { | |
| numericBuf[pos + len - 1 - i] = tmp[i]; | |
| } | |
| p = numericBuf; | |
| } | |
| pos += len; | |
| return p; | |
| } | |
| void MyStringBuffer::putOrderedByte(char* buf, int len) { | |
| if (isBigEndian) { | |
| str.append(buf, len); | |
| } else { | |
| for (int i = len - 1; i > -1; i--) { | |
| str += buf[i]; | |
| } | |
| } | |
| } | |
| BitMap::BitMap(size_t size) { | |
| resize(size); | |
| } | |
| void BitMap::resize(size_t size) { | |
| this->size = size; | |
| this->bits.resize((size >> 3) + 1); | |
| reset(); | |
| } | |
| bool BitMap::mark(size_t position) { | |
| if (position >= size) | |
| return false; | |
| bits[position >> 3] |= (char)1 << (position % 8); | |
| return true; | |
| } | |
| bool BitMap::unmark(size_t position) { | |
| if (position >= size) | |
| return false; | |
| bits[position >> 3] &= ~((char)1 << (position % 8)); | |
| return true; | |
| } | |
| void BitMap::markAll() { | |
| std::fill(bits.begin(), bits.end(), (char)0XFF); | |
| } | |
| void BitMap::reset() { | |
| std::fill(bits.begin(), bits.end(), (char)0); | |
| } | |
| bool BitMap::isMarked(size_t position) const { | |
| if (position >= size) | |
| return false; | |
| return (bits[position >> 3] & ((char)1 << (position % 8))) != 0; | |
| } | |
| bool BitMap::isAllUnmarked() const { | |
| size_t j; | |
| for (j = 0; j < size >> 3; j++) { | |
| if (bits[j] != (char)0) { | |
| return false; | |
| } | |
| } | |
| for (j = 0; j < size % 8; j++) { | |
| if ((bits[size >> 3] & ((char)1 << j)) != 0) { | |
| return false; | |
| } | |
| } | |
| return true; | |
| } | |
| bool BitMap::isAllMarked() const { | |
| return isRangeAllMarked(0, size); | |
| } | |
| bool BitMap::isRangeAllMarked(size_t start, size_t length) const { | |
| // size_t addition can wrap; short-circuit so `size - start` is only used when | |
| // start <= size. Out-of-range matches mark()/isMarked(): return false. | |
| if (start > size || length > size - start) { | |
| return false; | |
| } | |
| if (length == 0) { | |
| return true; | |
| } | |
| const size_t end = start + length; | |
| const size_t firstByte = start >> 3; | |
| const size_t lastByte = (end - 1) >> 3; | |
| if (firstByte == lastByte) { | |
| const unsigned char mask = static_cast<unsigned char>(((1U << length) - 1U) << (start & 7U)); | |
| return (static_cast<unsigned char>(bits[firstByte]) & mask) == mask; | |
| } | |
| const unsigned char firstMask = static_cast<unsigned char>((0xFFU << (start & 7U)) & 0xFFU); | |
| if ((static_cast<unsigned char>(bits[firstByte]) & firstMask) != firstMask) { | |
| return false; | |
| } | |
| for (size_t index = firstByte + 1; index < lastByte; index++) { | |
| if (static_cast<unsigned char>(bits[index]) != 0xFFU) { | |
| return false; | |
| } | |
| } | |
| const size_t lastBitCount = end & 7U; | |
| const unsigned char lastMask = | |
| lastBitCount == 0 ? 0xFFU : static_cast<unsigned char>((1U << lastBitCount) - 1U); | |
| return (static_cast<unsigned char>(bits[lastByte]) & lastMask) == lastMask; | |
| } | |
| const std::vector<char>& BitMap::getByteArray() const { | |
| return this->bits; | |
| } | |
| size_t BitMap::getSize() const { | |
| return this->size; | |
| } |