/* * Copyright (c) 2021 Huawei Device Co., Ltd. * * HDF is dual licensed: you can use it either under the terms of * the GPL, or the BSD license, at your option. * See the LICENSE file in the root of this repository for complete details. */ #include "util/file.h" #include #include #include #include #include #include #include "util/string_builder.h" namespace OHOS { namespace HDI { #ifdef __MINGW32__ constexpr unsigned int File::READ; constexpr unsigned int File::WRITE; constexpr unsigned int File::APPEND; #endif File::File(const String &path, unsigned int mode) : mode_(mode) { if (path.IsEmpty()) { return; } if (mode_ & READ) { if (!CheckValid(path)) { return; } fd_ = fopen(path.string(), "r"); } else if (mode_ & WRITE) { fd_ = fopen(path.string(), "w+"); } else if (mode_ & APPEND) { fd_ = fopen(path.string(), "a+"); } if (fd_ != nullptr) { #ifndef __MINGW32__ char *absolutePath = realpath(path.string(), nullptr); if (absolutePath != nullptr) { path_ = absolutePath; free(absolutePath); } else { path_ = path; } #else char absolutePath[_MAX_PATH]; _fullpath(absolutePath, path.string(), _MAX_PATH); path_ = absolutePath; #endif } } File::~File() { Close(); } char File::GetChar() { char c = PeekChar(); if (position_ + 1 <= size_) { position_++; if (c != '\n') { columnNo_++; } else { columnNo_ = 1; lineNo_++; } } return c; } char File::PeekChar() { if (position_ + 1 > size_) { int ret = Read(); if (ret == -1) { isEof_ = true; } } return buffer_[position_]; } bool File::IsEof() const { return isEof_ || buffer_[position_] == -1; } int File::Read() { if (isEof_ || isError_) { return -1; } (void)memset(buffer_, 0, BUFFER_SIZE); size_t count = fread(buffer_, 1, BUFFER_SIZE - 1, fd_); if (count < BUFFER_SIZE - 1) { isError_ = ferror(fd_) != 0; buffer_[count] = -1; } size_ = count; position_ = 0; return (count != 0) ? count : -1; } size_t File::ReadData(void *data, size_t size) const { if (data == nullptr || size == 0) { return 0; } if (fd_ == nullptr) { return 0; } return fread(data, 1, size, fd_); } bool File::WriteData(const void *data, size_t size) const { if (data == nullptr || size == 0) { return true; } if (fd_ == nullptr || !(mode_ & (WRITE | APPEND))) { return false; } size_t count = fwrite(data, size, 1, fd_); return count == 1; } void File::Flush() { if ((mode_ & (WRITE | APPEND)) && fd_ != nullptr) { fflush(fd_); } } bool File::Reset() { if (fd_ == nullptr) { return false; } return fseek(fd_, 0, SEEK_SET) == 0; } bool File::Skip(long size) { if (fd_ == nullptr) { return false; } return fseek(fd_, size, SEEK_CUR) == 0; } void File::Close() { if (fd_ != nullptr) { fclose(fd_); fd_ = nullptr; } } bool File::CreateParentDir(const String &path) { if (!access(path.string(), F_OK | R_OK | W_OK)) { return true; } int pos = 1; while ((pos = path.IndexOf(File::separator, pos)) != -1) { String partPath = path.Substring(0, pos); struct stat st; if (stat(partPath.string(), &st) < 0) { if (errno != ENOENT) { return false; } #ifndef __MINGW32__ if (mkdir(partPath.string(), S_IRWXU | S_IRWXG | S_IRWXO) < 0) { #else if (mkdir(partPath.string()) < 0) { #endif return false; } } else if (!S_ISDIR(st.st_mode)) { return false; } pos += 1; } return true; } String File::AdapterPath(const String &path) { #ifndef __MINGW32__ String newPath = path.Replace('\\', '/'); #else String newPath = path.Replace('/', '\\'); #endif // "foo/v1_0//ifoo.h" -> "foo/v1_0/ifoo.h" StringBuilder adapterPath; bool hasSep = false; for (size_t i = 0; i < newPath.GetLength(); i++) { char c = newPath[i]; if (c == File::separator) { if (hasSep) { continue; } adapterPath.Append(c); hasSep = false; } else { adapterPath.Append(c); } } return adapterPath.ToString(); } String File::RealPath(const String &path) { if (path.IsEmpty()) { return ""; } String absPath; String adapterPath = File::AdapterPath(path); #ifdef __MINGW32__ char absolutePath[_MAX_PATH]; _fullpath(absolutePath, adapterPath.string(), _MAX_PATH); absPath = absolutePath; #else char *absolutePath = realpath(adapterPath.string(), nullptr); if (absolutePath != nullptr) { absPath = absolutePath; free(absolutePath); } #endif return absPath; } bool File::CheckValid(const String &path) { if (access(path.string(), F_OK | R_OK | W_OK)) { return false; } struct stat st; if (stat(path.string(), &st) < 0) { return false; } if (S_ISDIR(st.st_mode)) { return false; } return true; } String File::Pascal2UnderScoreCase(const String &name) { if (name.IsNull() || name.IsEmpty()) { return name; } StringBuilder sb; for (int i = 0; i < name.GetLength(); i++) { char c = name[i]; if (isupper(c) != 0) { // 2->Index of the last char array. if (i > 1) { sb.Append('_'); } sb.Append(tolower(c)); } else { sb.Append(c); } } return sb.ToString(); } size_t File::GetHashKey() { StringBuilder fileStr; while (!IsEof()) { fileStr.Append(GetChar()); } return std::hash()(fileStr.ToString().string()); } } // namespace HDI } // namespace OHOS