From b159144a48866aec448afdb7004d84d7658daf02 Mon Sep 17 00:00:00 2001 From: execjosh Date: Tue, 26 Mar 2013 21:22:53 +0900 Subject: [PATCH] Teach `File` how to change its encoding If a `File` is in "text" mode, then it has an encoding. This encoding defaults to UTF-8; however, it can be set only at time of construction (by using `fs.open`). This modification allows the user to change the encoding on-the-fly for "text" mode `File` instances. See #11234 https://github.com/ariya/phantomjs/pull/11234 Spin off from #11168 https://github.com/ariya/phantomjs/pull/11168 --- src/filesystem.cpp | 43 +++++++++++++++++++++++++++++ src/filesystem.h | 3 ++ test/fs-spec-01.js | 68 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 114 insertions(+) diff --git a/src/filesystem.cpp b/src/filesystem.cpp index 0998dbb2..ab3fcf0e 100644 --- a/src/filesystem.cpp +++ b/src/filesystem.cpp @@ -216,6 +216,49 @@ void File::close() deleteLater(); } +bool File::setEncoding(const QString &encoding) { + if (encoding.isEmpty() || encoding.isNull()) { + return false; + } + + // "Binary" mode doesn't use/need text codecs + if ((QTextStream *)NULL == m_fileStream) { + // TODO: Should we switch to "text" mode? + return false; + } + + // Since there can be multiple names for the same codec (i.e., "utf8" and + // "utf-8"), we need to get the codec in the system first and use its + // canonical name + QTextCodec *codec = QTextCodec::codecForName(encoding.toAscii()); + if ((QTextCodec *)NULL == codec) { + return false; + } + + // Check whether encoding actually needs to be changed + const QString encodingBeforeUpdate(m_fileStream->codec()->name()); + if (0 == encodingBeforeUpdate.compare(QString(codec->name()), Qt::CaseInsensitive)) { + return false; + } + + m_fileStream->setCodec(codec); + + // Return whether update was successful + const QString encodingAfterUpdate(m_fileStream->codec()->name()); + return 0 != encodingBeforeUpdate.compare(encodingAfterUpdate, Qt::CaseInsensitive); +} + +QString File::getEncoding() const +{ + QString encoding; + + if ((QTextStream *)NULL != m_fileStream) { + encoding = QString(m_fileStream->codec()->name()); + } + + return encoding; +} + // private: bool File::_isUnbuffered() const diff --git a/src/filesystem.h b/src/filesystem.h index f71ed5ad..6d92452d 100644 --- a/src/filesystem.h +++ b/src/filesystem.h @@ -64,6 +64,9 @@ public slots: void flush(); void close(); + QString getEncoding() const; + bool setEncoding(const QString &encoding); + private: bool _isUnbuffered() const; diff --git a/test/fs-spec-01.js b/test/fs-spec-01.js index 71b0c297..86d9b61a 100644 --- a/test/fs-spec-01.js +++ b/test/fs-spec-01.js @@ -59,6 +59,74 @@ describe("Basic Files API (read, write, remove, ...)", function() { expect(content).toEqual("hello\nworld\nasdf\n"); }); + it("should be able to get the encoding (default: UTF-8)", function() { + var encoding = ""; + try { + var f = fs.open(FILENAME, "r"); + encoding = f.getEncoding(); + f.close(); + } catch (e) { + console.log(e); + } + expect(encoding).toEqual("UTF-8"); + }); + + it("should be able to set the encoding via options", function() { + var encoding = ""; + try { + var f = fs.open(FILENAME, { + charset: "UTF-8" + , mode: "r" + }); + encoding = f.getEncoding(); + f.close(); + } catch (e) { + console.log(e); + } + expect(encoding).toEqual("UTF-8"); + + try { + var f = fs.open(FILENAME, { + charset: "SJIS" + , mode: "r" + }); + encoding = f.getEncoding(); + f.close(); + } catch (e) { + console.log(e); + } + expect(encoding).toEqual("Shift_JIS"); + }); + + it("should be able to change the encoding", function() { + var encoding = ""; + try { + var f = fs.open(FILENAME, { + charset: "UTF-8" + , mode: "r" + }); + f.setEncoding("utf8"); + encoding = f.getEncoding(); + f.close(); + } catch (e) { + console.log(e); + } + expect(encoding).toEqual("UTF-8"); + + try { + var f = fs.open(FILENAME, { + charset: "SJIS" + , mode: "r" + }); + f.setEncoding("eucjp"); + encoding = f.getEncoding(); + f.close(); + } catch (e) { + console.log(e); + } + expect(encoding).toEqual("EUC-JP"); + }); + it("should be able to copy a file", function() { expect(fs.exists(FILENAME_COPY)).toBeFalsy(); fs.copy(FILENAME, FILENAME_COPY);