博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
UWP平台Taglib编译(2)
阅读量:4613 次
发布时间:2019-06-09

本文共 10547 字,大约阅读时间需要 35 分钟。

此文已由作者郑博授权网易云社区发布。

欢迎访问,了解更多网易技术产品运营经验

#endif  // _WIN32}class FileStream::FileStreamPrivate{public:  FileStreamPrivate(const FileName &fileName)    : file(InvalidFileHandle)    , name(fileName)    , readOnly(true)  {  }  FileHandle file;  FileNameHandle name;  bool readOnly;};// public membersFileStream::FileStream(FileName fileName, bool openReadOnly)  : d(new FileStreamPrivate(fileName)){  // First try with read / write mode, if that fails, fall back to read only.  if(!openReadOnly)    d->file = openFile(fileName, false);  if(d->file != InvalidFileHandle)    d->readOnly = false;  else    d->file = openFile(fileName, true);  if(d->file == InvalidFileHandle)  {# ifdef _WIN32    debug("Could not open file " + fileName.toString());# else    debug("Could not open file " + String(static_cast(d->name)));# endif  }}FileStream::~FileStream(){  if(isOpen())    closeFile(d->file);  delete d;}FileName FileStream::name() const{  return d->name;}ByteVector FileStream::readBlock(ulong length){  if(!isOpen()) {    debug("FileStream::readBlock() -- invalid file.");    return ByteVector::null;  }  if(length == 0)    return ByteVector::null;  const ulong streamLength = static_cast(FileStream::length());  if(length > bufferSize() && length > streamLength)    length = streamLength;  ByteVector buffer(static_cast(length));  const size_t count = readFile(d->file, buffer);  buffer.resize(static_cast(count));  return buffer;}void FileStream::writeBlock(const ByteVector &data){  if(!isOpen()) {    debug("FileStream::writeBlock() -- invalid file.");    return;  }  if(readOnly()) {    debug("FileStream::writeBlock() -- read only file.");    return;  }  writeFile(d->file, data);}void FileStream::insert(const ByteVector &data, ulong start, ulong replace){  if(!isOpen()) {    debug("FileStream::insert() -- invalid file.");    return;  }  if(readOnly()) {    debug("FileStream::insert() -- read only file.");    return;  }  if(data.size() == replace) {    seek(start);    writeBlock(data);    return;  }  else if(data.size() < replace) {    seek(start);    writeBlock(data);    removeBlock(start + data.size(), replace - data.size());    return;  }  // Woohoo!  Faster (about 20%) than id3lib at last.  I had to get hardcore  // and avoid TagLib's high level API for rendering just copying parts of  // the file that don't contain tag data.  //  // Now I'll explain the steps in this ugliness:  // First, make sure that we're working with a buffer that is longer than  // the *differnce* in the tag sizes.  We want to avoid overwriting parts  // that aren't yet in memory, so this is necessary.  ulong bufferLength = bufferSize();  while(data.size() - replace > bufferLength)    bufferLength += bufferSize();  // Set where to start the reading and writing.  long readPosition = start + replace;  long writePosition = start;  ByteVector buffer = data;  ByteVector aboutToOverwrite(static_cast(bufferLength));  while(true)  {    // Seek to the current read position and read the data that we're about    // to overwrite.  Appropriately increment the readPosition.    seek(readPosition);    const size_t bytesRead = readFile(d->file, aboutToOverwrite);    aboutToOverwrite.resize(bytesRead);    readPosition += bufferLength;    // Check to see if we just read the last block.  We need to call clear()    // if we did so that the last write succeeds.    if(bytesRead < bufferLength)      clear();    // Seek to the write position and write our buffer.  Increment the    // writePosition.    seek(writePosition);    writeBlock(buffer);    // We hit the end of the file.    if(bytesRead == 0)      break;    writePosition += buffer.size();    // Make the current buffer the data that we read in the beginning.    buffer = aboutToOverwrite;  }}void FileStream::removeBlock(ulong start, ulong length){  if(!isOpen()) {    debug("FileStream::removeBlock() -- invalid file.");    return;  }  ulong bufferLength = bufferSize();  long readPosition = start + length;  long writePosition = start;  ByteVector buffer(static_cast(bufferLength));  for(size_t bytesRead = -1; bytesRead != 0;)  {    seek(readPosition);    bytesRead = readFile(d->file, buffer);    readPosition += bytesRead;    // Check to see if we just read the last block.  We need to call clear()    // if we did so that the last write succeeds.    if(bytesRead < buffer.size()) {      clear();      buffer.resize(bytesRead);    }    seek(writePosition);    writeFile(d->file, buffer);    writePosition += bytesRead;  }  truncate(writePosition);}bool FileStream::readOnly() const{  return d->readOnly;}bool FileStream::isOpen() const{  return (d->file != InvalidFileHandle);}void FileStream::seek(long offset, Position p){  if(!isOpen()) {    debug("FileStream::seek() -- invalid file.");    return;  }#ifdef _WIN32  DWORD whence;  switch(p) {  case Beginning:    whence = FILE_BEGIN;    break;  case Current:    whence = FILE_CURRENT;    break;  case End:    whence = FILE_END;    break;  default:    debug("FileStream::seek() -- Invalid Position value.");    return;  }#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM)  LARGE_INTEGER distance = { 0 };  distance.QuadPart = offset;  if (!SetFilePointerEx(d->file, distance, NULL, whence))#else  SetLastError(NO_ERROR);  SetFilePointer(d->file, offset, NULL, whence);  const int lastError = GetLastError();  if(lastError != NO_ERROR && lastError != ERROR_NEGATIVE_SEEK)#endif    debug("FileStream::seek() -- Failed to set the file pointer.");#else  int whence;  switch(p) {  case Beginning:    whence = SEEK_SET;    break;  case Current:    whence = SEEK_CUR;    break;  case End:    whence = SEEK_END;    break;  default:    debug("FileStream::seek() -- Invalid Position value.");    return;  }  fseek(d->file, offset, whence);#endif}void FileStream::clear(){#ifdef _WIN32  // NOP#else  clearerr(d->file);#endif}long FileStream::tell() const{#ifdef _WIN32#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM)  LARGE_INTEGER distance = { 0 };  LARGE_INTEGER position = { 0 };  if (SetFilePointerEx(d->file, distance, &position, FILE_CURRENT)) {    return static_cast(position.QuadPart);  }#else  SetLastError(NO_ERROR);  const DWORD position = SetFilePointer(d->file, 0, NULL, FILE_CURRENT);  if(GetLastError() == NO_ERROR) {    return static_cast(position);  }#endif  else {    debug("FileStream::tell() -- Failed to get the file pointer.");    return 0;  }#else  return ftell(d->file);#endif}long FileStream::length(){  if(!isOpen()) {    debug("FileStream::length() -- invalid file.");    return 0;  }#ifdef _WIN32#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM)  LARGE_INTEGER fileSize = { 0 };  if (GetFileSizeEx(d->file, &fileSize)) {	  return static_cast(fileSize.QuadPart);  }#else  SetLastError(NO_ERROR);  const DWORD fileSize = GetFileSize(d->file, NULL);  if (GetLastError() == NO_ERROR) {	  return static_cast(fileSize);  }#endif  else {	  debug("FileStream::length() -- Failed to get the file size.");	  return 0;  }#else  const long curpos = tell();  seek(0, End);  const long endpos = tell();  seek(curpos, Beginning);  return endpos;#endif}// protected membersvoid FileStream::truncate(long length){#ifdef _WIN32  const long currentPos = tell();  seek(length);  SetLastError(NO_ERROR);  SetEndOfFile(d->file);  if(GetLastError() != NO_ERROR) {    debug("FileStream::truncate() -- Failed to truncate the file.");  }  seek(currentPos);#else  const int error = ftruncate(fileno(d->file), length);  if(error != 0) {    debug("FileStream::truncate() -- Coundn't truncate the file.");  }#endif}TagLib::uint FileStream::bufferSize(){  return 1024;}

为了便于调试,还需要修改taglib\toolkit\tdebuglistener.cpp,以便在调试直接在Output窗口输出调试信息,完整代码如下:

/***************************************************************************    copyright            : (C) 2013 by Tsuda Kageyu    email                : tsuda.kageyu@gmail.com ***************************************************************************//*************************************************************************** *   This library is free software; you can redistribute it and/or modify  * *   it under the terms of the GNU Lesser General Public License version   * *   2.1 as published by the Free Software Foundation.                     * *                                                                         * *   This library is distributed in the hope that it will be useful, but   * *   WITHOUT ANY WARRANTY; without even the implied warranty of            * *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     * *   Lesser General Public License for more details.                       * *                                                                         * *   You should have received a copy of the GNU Lesser General Public      * *   License along with this library; if not, write to the Free Software   * *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA         * *   02110-1301  USA                                                       * *                                                                         * *   Alternatively, this file is available under the Mozilla Public        * *   License Version 1.1.  You may obtain a copy of the License at         * *   http://www.mozilla.org/MPL/                                           * ***************************************************************************/#include "tdebuglistener.h"#include #include #ifdef _WIN32# include #endifusing namespace TagLib;namespace{  class DefaultListener : public DebugListener  {  public:    virtual void printMessage(const String &msg)    {#ifdef _WIN32      const wstring wstr = msg.toWString();#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM)	  OutputDebugStringW(wstr.c_str());#else      const int len = WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), -1, NULL, 0, NULL, NULL);      if(len != 0) {        std::vector buf(len);        WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), -1, &buf[0], len, NULL, NULL);        std::cerr << std::string(&buf[0]);      }#endif#else      std::cerr << msg;#endif     }  };  DefaultListener defaultListener;}namespace TagLib{  DebugListener *debugListener = &defaultListener;  DebugListener::DebugListener()  {  }  DebugListener::~DebugListener()  {  }  void setDebugListener(DebugListener *listener)  {    if(listener)      debugListener = listener;    else      debugListener = &defaultListener;  }}

最后,编译吧,骚年!!!

更多网易技术、产品、运营经验分享请。

相关文章:

【推荐】 

转载于:https://www.cnblogs.com/zyfd/p/10063204.html

你可能感兴趣的文章
java多线程入门学习(一)
查看>>
基于 Web 的 Go 语言 IDE - Wide 1.1.0 公布!
查看>>
nyist oj 138 找球号(二)(hash 表+位运算)
查看>>
Movidius软件手册阅读 2017-09-04
查看>>
ytu 1910:字符统计(水题)
查看>>
201671030110 姜佳宇 实验三作业互评与改进
查看>>
mysql-5.6.15 开启二进制文件
查看>>
python的沙盒环境--virtualenv
查看>>
软件自动化测试——入门、进阶与实战
查看>>
BZOJ1878 [SDOI2009]HH的项链 树状数组 或 莫队
查看>>
BZOJ3675 [Apio2014]序列分割 动态规划 斜率优化
查看>>
2016.10.24 继续学习
查看>>
产品功能对标 - 服务授权管理
查看>>
各地IT薪资待遇讨论
查看>>
splay入门
查看>>
带CookieContainer进行post
查看>>
C语言学习笔记--字符串
查看>>
CSS-上下文选择器
查看>>
ionic repeat 重复最后一个时要执行某个函数
查看>>
1.初识代码审计-基础
查看>>