File::File(const AnyString& filePath): pFormat(nullptr) { if (filePath.empty()) return; # if LIBAVFORMAT_VERSION_MAJOR < 53 if (::av_open_input_file(&pFormat, filePath.c_str(), nullptr, 0, nullptr)) # else if (::avformat_open_input(&pFormat, filePath.c_str(), nullptr, nullptr)) # endif // LIBAVFORMAT_VERSION_MAJOR < 53 { pFormat = nullptr; return; } // After opening, we must search for the stream information because not // all formats will have it in stream headers (eg. system MPEG streams) # if LIBAVFORMAT_VERSION_MAJOR < 53 if (::av_find_stream_info(pFormat) < 0) # else if (::avformat_find_stream_info(pFormat, nullptr) < 0) # endif // LIBAVFORMAT_VERSION_MAJOR < 53 { # if LIBAVFORMAT_VERSION_MAJOR < 53 ::av_close_input_file(pFormat); # else ::avformat_close_input(&pFormat); # endif // LIBAVFORMAT_VERSION_MAJOR < 53 pFormat = nullptr; return; } }
Yuni::IO::NodeType TypeOf(const AnyString& filename) { if (filename.empty()) return Yuni::IO::typeUnknown; # ifdef YUNI_OS_WINDOWS const char* p = filename.c_str(); unsigned int len = filename.size(); if (p[len - 1] == '\\' or p[len - 1] == '/') { if (!--len) { # ifdef YUNI_OS_WINDOWS return Yuni::IO::typeUnknown; # else // On Unixes, `/` is a valid folder return Yuni::IO::typeFolder; # endif } } // Driver letters if (len == 2 and p[1] == ':') return Yuni::IO::typeFolder; String norm; Yuni::IO::Normalize(norm, AnyString(p, len)); // Conversion into wchar_t Private::WString<true> wstr(norm); if (wstr.empty()) return Yuni::IO::typeUnknown; WIN32_FILE_ATTRIBUTE_DATA infoFile; if (!GetFileAttributesExW(wstr.c_str(), GetFileExInfoStandard, &infoFile)) return Yuni::IO::typeUnknown; return ((infoFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) ? Yuni::IO::typeFolder : Yuni::IO::typeFile; # else // WINDOWS struct stat s; if (stat(filename.c_str(), &s) != 0) return Yuni::IO::typeUnknown; return (S_ISDIR(s.st_mode)) ? Yuni::IO::typeFolder : Yuni::IO::typeFile; # endif }
DBI::Error Transaction::truncate(const AnyString& tablename) { if (YUNI_UNLIKELY(not IsValidIdentifier(tablename))) return errInvalidIdentifier; assert(!(!pChannel)); // the adapter ::yn_dbi_adapter& adapter = pChannel->adapter; // The DBI interface should provide the most appropriate way for // truncating a table (autoincrement / cascade...) if (YUNI_LIKELY(adapter.truncate)) { return (DBI::Error) adapter.truncate(adapter.dbh, tablename.c_str(), tablename.size()); } else { // Fallback to a failsafe method // -- stmt << "TRUNCATE " << tablename << ';'; // The SQL command Truncate is not supported by all databases. `DELETE FROM` // is not the most efficient way for truncating a table // but it should work almost everywhere String stmt; stmt << "DELETE FROM " << tablename << ';'; return perform(stmt); } }
Cursor Transaction::prepare(const AnyString& stmt) { assert(!(!pChannel)); // the adapter ::yn_dbi_adapter& adapter = pChannel->adapter; if (YUNI_UNLIKELY(nullHandle == pTxHandle)) { if (errNone != pChannel->begin(pTxHandle)) return Cursor(adapter, nullptr); } // query handle void* handle = nullptr; if (YUNI_LIKELY(not stmt.empty() and adapter.dbh)) { assert(adapter.query_new != NULL and "invalid adapter query_new"); assert(adapter.query_ref_acquire != NULL and "invalid adapter query_ref_acquire"); assert(adapter.query_ref_release != NULL and "invalid adapter query_ref_release"); adapter.query_new(&handle, adapter.dbh, stmt.c_str(), stmt.size()); } return Cursor(adapter, handle); }
bool Size(const AnyString& filename, uint64& value) { struct stat results; if (not filename.empty() && stat(filename.c_str(), &results) == 0) { value = (uint64) results.st_size; return true; } value = 0u; return false; }
Yuni::IO::Error Delete(const AnyString& filename) { // DeleteFile is actually a macro and will be replaced by DeleteFileW // with Visual Studio. Consequently we can not use the word DeleteFile..... if (filename.empty()) return Yuni::IO::errUnknown; # ifndef YUNI_OS_WINDOWS return (unlink(filename.c_str())) ? Yuni::IO::errUnknown : Yuni::IO::errNone; # else const char* const p = filename.c_str(); uint len = filename.size(); if (p[len - 1] == '\\' or p[len - 1] == '/') --len; // Driver letters if (len == 2 and p[1] == ':') return Yuni::IO::errBadFilename; String norm; Yuni::IO::Normalize(norm, AnyString(p, len)); // Conversion into wchar_t WString wstr(norm, true); if (wstr.empty()) return Yuni::IO::errUnknown; wstr.replace('/', '\\'); return (DeleteFileW(wstr.c_str())) ? Yuni::IO::errNone : Yuni::IO::errUnknown; # endif }
DBI::Error Transaction::perform(const AnyString& script) { assert(!(!pChannel)); // the adapter ::yn_dbi_adapter& adapter = pChannel->adapter; assert(adapter.query_exec != NULL); if (YUNI_LIKELY(nullHandle != pTxHandle)) { return (DBI::Error) adapter.query_exec(adapter.dbh, script.c_str(), script.size()); } else { // start a new transaction DBI::Error error = pChannel->begin(pTxHandle); if (YUNI_LIKELY(error == errNone)) error = (DBI::Error) adapter.query_exec(adapter.dbh, script.c_str(), script.size()); return error; } }
bool Size(const AnyString& filename, uint64& value) { unsigned int len = filename.size(); if (!len) { value = 0u; return false; } const char* const p = filename.c_str(); if (p[len - 1] == '\\' || p[len - 1] == '/') --len; // Driver letters if (len == 2 && p[1] == ':') { value = 0u; return true; } String norm; Yuni::IO::Normalize(norm, p, len); // Conversion into wchar_t Private::WString<true> wstr(norm); if (wstr.empty()) { value = 0u; return false; } HANDLE hndl = CreateFileW(wstr.c_str(), 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hndl == INVALID_HANDLE_VALUE) { value = 0u; return false; } LARGE_INTEGER v; if (!GetFileSizeEx(hndl, &v)) { CloseHandle(hndl); value = 0u; return false; } value = (uint64) v.QuadPart; CloseHandle(hndl); return true; }
sint64 LastModificationTime(const AnyString& filename) { # ifdef YUNI_OS_WINDOWS Private::WString<> wfilenm(filename); if (wfilenm.empty()) return 0; HANDLE hFile = CreateFileW(wfilenm.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if (hFile == INVALID_HANDLE_VALUE) return 0; FILETIME ftCreate, ftAccess, ftWrite; // Retrieve the file times for the file. if (GetFileTime(hFile, &ftCreate, &ftAccess, &ftWrite)) { CloseHandle(hFile); LARGE_INTEGER date, adjust; date.HighPart = ftWrite.dwHighDateTime; date.LowPart = ftWrite.dwLowDateTime; // 100-nanoseconds = milliseconds * 10000 adjust.QuadPart = 11644473600000 * 10000; // removes the diff between 1970 and 1601 date.QuadPart -= adjust.QuadPart; // converts back from 100-nanoseconds to seconds return date.QuadPart / 10000000; } CloseHandle(hFile); return 0; # else // UNIX struct stat st; if (!stat(filename.c_str(), &st)) return st.st_mtime; return 0; # endif }
bool Stream::open(const AnyString& filename, int mode) { // Close the file if already opened if (pFd) (void)::fclose(pFd); # ifdef YUNI_OS_WINDOWS pFd = OpenFileOnWindows(filename, mode); # else // It is mandatory to open file with the flag O_CLOEXEC to avoid race // conditions with fork // fopen should used O_CLOEXEC as one of the option. However, at the current // state, not all operating systems do that. // So we have to do it by ourselves with open and fdopen. /*int flag = O_CLOEXEC; if (0 != (mode & OpenMode::read) and 0 != (mode & OpenMode::write)) flag |= O_RDWR; else if (0 != (mode & OpenMode::read)) flag |= O_RDONLY; else if (0 != (mode & OpenMode::write)) flag |= O_WRONLY; if (0 != (mode & OpenMode::truncate)) flag |= O_TRUNC; else if (0 != (mode & OpenMode::append)) flag |= O_APPEND; if (0 != (mode & ~OpenMode::read)) flag |= O_CREAT; int fd = ::open(filename.c_str(), flag); if (fd < 0) // error pFd = nullptr; else pFd = ::fdopen(fd, OpenMode::ToCString(mode));*/ pFd = ::fopen(filename.c_str(), OpenMode::ToCString(mode)); # endif return (NULL != pFd); }
static bool UnixMake(const AnyString& path, uint mode) { const uint len = path.size(); char* buffer = new char[len + 1]; YUNI_MEMCPY(buffer, len, path.c_str(), len); buffer[len] = '\0'; char* pt = buffer; char tmp; do { if ('\\' == *pt or '/' == *pt or '\0' == *pt) { tmp = *pt; *pt = '\0'; if ('\0' != buffer[0] and '\0' != buffer[1] and '\0' != buffer[2]) { if (mkdir(buffer, static_cast<mode_t>(mode)) < 0) { if (errno != EEXIST and errno != EISDIR and errno != ENOSYS) { delete[] buffer; return false; } } } if ('\0' == tmp) break; *pt = tmp; } ++pt; } while (true); delete[] buffer; return true; }
void WString::prepareWString(const AnyString& string, bool uncprefix) { if (string.empty()) { if (uncprefix) { pSize = 4; pWString = (wchar_t*)::realloc(pWString, sizeof(wchar_t) * 5); pWString[0] = L'\\'; pWString[1] = L'\\'; pWString[2] = L'?'; pWString[3] = L'\\'; pWString[4] = L'\0'; } else clear(); return; } if (string.size() > INT_MAX) { clear(); return; } // Offset according to the presence of the UNC prefix const uint offset = (not uncprefix) ? 0 : 4; #ifdef YUNI_OS_WINDOWS { // Allocate and convert the C-String. Several iterations may be required // for allocating enough room for the conversion. const int sizeRequired = MultiByteToWideChar(CP_UTF8, 0, string.c_str(), string.size(), nullptr, 0); if (sizeRequired <= 0) { clear(); return; } pSize = sizeRequired + offset; pWString = (wchar_t*) realloc(pWString, sizeof(wchar_t) * (pSize + 1)); if (nullptr == pWString) // Impossible to allocate the buffer. Aborting. { clear(); return; } // Converting into Wide String const int n = MultiByteToWideChar(CP_UTF8, 0, string.c_str(), static_cast<int>(string.size()), pWString + offset, static_cast<int>(pSize - offset)); if (n != sizeRequired) { assert(false and "most likely an error"); clear(); return; } } #else { const char* wcstr = string.c_str(); mbstate_t state; memset (&state, '\0', sizeof (state)); size_t sizeRequired = mbsnrtowcs(nullptr, &wcstr, string.size(), 0, &state); if (0 == sizeRequired or (size_t) -1 == sizeRequired) { clear(); return; } pSize = sizeRequired + offset; pWString = (wchar_t*) realloc(pWString, sizeof(wchar_t) * (pSize + 1)); if (nullptr == pWString) // Impossible to allocate the buffer. Aborting. { clear(); return; } memset (&state, '\0', sizeof (state)); size_t written = mbsnrtowcs(pWString + offset, &wcstr, string.size(), pSize - offset, &state); if (0 == written or (size_t) -1 == written) { clear(); return; } } #endif // prepend the Windows UNC prefix if (uncprefix) { pWString[0] = L'\\'; pWString[1] = L'\\'; pWString[2] = L'?'; pWString[3] = L'\\'; } // always ensure that the string is zero terminated pWString[pSize] = L'\0'; }
bool Resize(const AnyString& filename, uint64_t size) { if (not filename.empty()) { if (size < std::numeric_limits<off_t>::max()) { #ifndef YUNI_OS_WINDOWS { assert((filename.c_str())[filename.size()] == '\0'); #ifdef YUNI_OS_MAC int fd = open(filename.c_str(), O_WRONLY|O_CREAT, 0644); #else int fd = open(filename.c_str(), O_WRONLY|O_CREAT|O_LARGEFILE, 0644); #endif if (fd != -1) { bool success = (0 == ftruncate(fd, static_cast<off_t>(size))); close(fd); return success; } } #else { WString wstr(filename, true); if (not wstr.empty()) { HANDLE hndl = CreateFileW(wstr.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hndl) { LARGE_INTEGER li; li.QuadPart = size; DWORD dwPtr = SetFilePointer(hndl, li.LowPart, &li.HighPart, FILE_BEGIN); if (dwPtr != INVALID_SET_FILE_POINTER) SetEndOfFile(hndl); CloseHandle(hndl); return true; } } } #endif } } return false; }