summaryrefslogtreecommitdiffstats
path: root/libraries
diff options
context:
space:
mode:
Diffstat (limited to 'libraries')
-rw-r--r--libraries/LocalPeer/CMakeLists.txt14
-rw-r--r--libraries/LocalPeer/include/LocalPeer.h58
-rw-r--r--libraries/LocalPeer/src/LocalPeer.cpp248
-rw-r--r--libraries/LocalPeer/src/LockedFile.cpp152
-rw-r--r--libraries/LocalPeer/src/LockedFile.h34
-rw-r--r--libraries/LocalPeer/src/LockedFile_unix.cpp96
-rw-r--r--libraries/LocalPeer/src/LockedFile_win.cpp272
-rw-r--r--libraries/classparser/CMakeLists.txt5
-rw-r--r--libraries/classparser/include/classparser.h2
-rw-r--r--libraries/classparser/include/classparser_config.h2
-rw-r--r--libraries/classparser/src/annotations.cpp132
-rw-r--r--libraries/classparser/src/annotations.h384
-rw-r--r--libraries/classparser/src/classfile.h272
-rw-r--r--libraries/classparser/src/classparser.cpp96
-rw-r--r--libraries/classparser/src/constants.h399
-rw-r--r--libraries/classparser/src/javaendian.h44
-rw-r--r--libraries/classparser/src/membuffer.h94
-rw-r--r--libraries/hoedown/include/hoedown/autolink.h8
-rw-r--r--libraries/hoedown/include/hoedown/buffer.h32
-rw-r--r--libraries/hoedown/include/hoedown/document.h188
-rw-r--r--libraries/hoedown/include/hoedown/html.h40
-rw-r--r--libraries/hoedown/include/hoedown/stack.h6
-rw-r--r--libraries/hoedown/src/autolink.c414
-rw-r--r--libraries/hoedown/src/buffer.c310
-rw-r--r--libraries/hoedown/src/document.c4030
-rw-r--r--libraries/hoedown/src/escape.c218
-rw-r--r--libraries/hoedown/src/html.c914
-rw-r--r--libraries/hoedown/src/html_smartypants.c546
-rw-r--r--libraries/hoedown/src/stack.c56
-rw-r--r--libraries/hoedown/src/version.c6
-rw-r--r--libraries/iconfix/CMakeLists.txt8
-rw-r--r--libraries/iconfix/internal/qhexstring_p.h60
-rw-r--r--libraries/iconfix/internal/qiconloader.cpp934
-rw-r--r--libraries/iconfix/internal/qiconloader_p.h222
-rw-r--r--libraries/iconfix/xdgicon.cpp108
-rw-r--r--libraries/iconfix/xdgicon.h12
-rw-r--r--libraries/javacheck/CMakeLists.txt2
-rw-r--r--libraries/javacheck/JavaCheck.java38
-rw-r--r--libraries/launcher/CMakeLists.txt18
-rw-r--r--libraries/launcher/net/minecraft/Launcher.java270
-rw-r--r--libraries/launcher/org/multimc/EntryPoint.java234
-rw-r--r--libraries/launcher/org/multimc/Launcher.java4
-rw-r--r--libraries/launcher/org/multimc/LegacyFrame.java2
-rw-r--r--libraries/launcher/org/multimc/NotFoundException.java2
-rw-r--r--libraries/launcher/org/multimc/ParamBucket.java110
-rw-r--r--libraries/launcher/org/multimc/ParseException.java7
-rw-r--r--libraries/launcher/org/multimc/Utils.java152
-rw-r--r--libraries/launcher/org/multimc/onesix/OneSixLauncher.java410
-rw-r--r--libraries/pack200/CMakeLists.txt42
-rw-r--r--libraries/pack200/anti200.cpp62
-rw-r--r--libraries/pack200/src/bands.cpp642
-rw-r--r--libraries/pack200/src/bands.h604
-rw-r--r--libraries/pack200/src/bytes.cpp246
-rw-r--r--libraries/pack200/src/bytes.h472
-rw-r--r--libraries/pack200/src/coding.cpp1762
-rw-r--r--libraries/pack200/src/coding.h348
-rw-r--r--libraries/pack200/src/constants.h712
-rw-r--r--libraries/pack200/src/unpack.cpp8363
-rw-r--r--libraries/pack200/src/unpack.h992
-rw-r--r--libraries/pack200/src/unpack200.cpp188
-rw-r--r--libraries/pack200/src/utils.cpp28
-rw-r--r--libraries/pack200/src/utils.h6
-rw-r--r--libraries/pack200/src/zip.cpp838
-rw-r--r--libraries/pack200/src/zip.h136
m---------libraries/quazip0
-rw-r--r--libraries/rainbow/CMakeLists.txt8
-rw-r--r--libraries/rainbow/include/rainbow.h12
-rw-r--r--libraries/rainbow/include/rainbow_config.h14
-rw-r--r--libraries/rainbow/src/rainbow.cpp504
-rw-r--r--libraries/systeminfo/CMakeLists.txt18
-rw-r--r--libraries/systeminfo/include/distroutils.h8
-rw-r--r--libraries/systeminfo/include/sys.h50
-rw-r--r--libraries/systeminfo/src/distroutils.cpp418
-rw-r--r--libraries/systeminfo/src/sys_apple.cpp44
-rw-r--r--libraries/systeminfo/src/sys_test.cpp28
-rw-r--r--libraries/systeminfo/src/sys_unix.cpp98
-rw-r--r--libraries/systeminfo/src/sys_win32.cpp50
-rw-r--r--libraries/xz-embedded/CMakeLists.txt16
-rw-r--r--libraries/xz-embedded/include/xz.h36
-rw-r--r--libraries/xz-embedded/src/xz_config.h24
-rw-r--r--libraries/xz-embedded/src/xz_crc32.c38
-rw-r--r--libraries/xz-embedded/src/xz_crc64.c38
-rw-r--r--libraries/xz-embedded/src/xz_dec_bcj.c902
-rw-r--r--libraries/xz-embedded/src/xz_dec_lzma2.c1810
-rw-r--r--libraries/xz-embedded/src/xz_dec_stream.c1198
-rw-r--r--libraries/xz-embedded/src/xz_lzma2.h46
-rw-r--r--libraries/xz-embedded/src/xz_private.h6
-rw-r--r--libraries/xz-embedded/src/xz_stream.h8
-rw-r--r--libraries/xz-embedded/xzminidec.c216
89 files changed, 16353 insertions, 16343 deletions
diff --git a/libraries/LocalPeer/CMakeLists.txt b/libraries/LocalPeer/CMakeLists.txt
index 99e3fe4d..f476da38 100644
--- a/libraries/LocalPeer/CMakeLists.txt
+++ b/libraries/LocalPeer/CMakeLists.txt
@@ -12,18 +12,18 @@ include/LocalPeer.h
)
if(UNIX)
- list(APPEND SINGLE_SOURCES
- src/LockedFile_unix.cpp
- )
+ list(APPEND SINGLE_SOURCES
+ src/LockedFile_unix.cpp
+ )
endif()
if(WIN32)
- list(APPEND SINGLE_SOURCES
- src/LockedFile_win.cpp
- )
+ list(APPEND SINGLE_SOURCES
+ src/LockedFile_win.cpp
+ )
endif()
add_library(LocalPeer STATIC ${SINGLE_SOURCES})
target_include_directories(LocalPeer PUBLIC include)
-qt5_use_modules(LocalPeer Core Network)
+target_link_libraries(LocalPeer Qt5::Core Qt5::Network)
diff --git a/libraries/LocalPeer/include/LocalPeer.h b/libraries/LocalPeer/include/LocalPeer.h
index 7558f18e..a24e4775 100644
--- a/libraries/LocalPeer/include/LocalPeer.h
+++ b/libraries/LocalPeer/include/LocalPeer.h
@@ -50,51 +50,51 @@ class LockedFile;
class ApplicationId
{
public: /* methods */
- // traditional app = installed system wide and used in a multi-user environment
- static ApplicationId fromTraditionalApp();
- // ID based on a path with all the application data (no two instances with the same data path should run)
- static ApplicationId fromPathAndVersion(const QString & dataPath, const QString & version);
- // custom ID
- static ApplicationId fromCustomId(const QString & id);
- // custom ID, based on a raw string previously acquired from 'toString'
- static ApplicationId fromRawString(const QString & id);
+ // traditional app = installed system wide and used in a multi-user environment
+ static ApplicationId fromTraditionalApp();
+ // ID based on a path with all the application data (no two instances with the same data path should run)
+ static ApplicationId fromPathAndVersion(const QString & dataPath, const QString & version);
+ // custom ID
+ static ApplicationId fromCustomId(const QString & id);
+ // custom ID, based on a raw string previously acquired from 'toString'
+ static ApplicationId fromRawString(const QString & id);
- QString toString()
- {
- return m_id;
- }
+ QString toString()
+ {
+ return m_id;
+ }
private: /* methods */
- ApplicationId(const QString & value)
- {
- m_id = value;
- }
+ ApplicationId(const QString & value)
+ {
+ m_id = value;
+ }
private: /* data */
- QString m_id;
+ QString m_id;
};
class LocalPeer : public QObject
{
- Q_OBJECT
+ Q_OBJECT
public:
- LocalPeer(QObject *parent, const ApplicationId &appId);
- ~LocalPeer();
- bool isClient();
- bool sendMessage(const QString &message, int timeout);
- ApplicationId applicationId() const;
+ LocalPeer(QObject *parent, const ApplicationId &appId);
+ ~LocalPeer();
+ bool isClient();
+ bool sendMessage(const QString &message, int timeout);
+ ApplicationId applicationId() const;
Q_SIGNALS:
- void messageReceived(const QString &message);
+ void messageReceived(const QString &message);
protected Q_SLOTS:
- void receiveConnection();
+ void receiveConnection();
protected:
- ApplicationId id;
- QString socketName;
- std::unique_ptr<QLocalServer> server;
- std::unique_ptr<LockedFile> lockFile;
+ ApplicationId id;
+ QString socketName;
+ std::unique_ptr<QLocalServer> server;
+ std::unique_ptr<LockedFile> lockFile;
};
diff --git a/libraries/LocalPeer/src/LocalPeer.cpp b/libraries/LocalPeer/src/LocalPeer.cpp
index f71c62d8..129f3abc 100644
--- a/libraries/LocalPeer/src/LocalPeer.cpp
+++ b/libraries/LocalPeer/src/LocalPeer.cpp
@@ -67,60 +67,60 @@ static const char* ack = "ack";
ApplicationId ApplicationId::fromTraditionalApp()
{
- QString protoId = QCoreApplication::applicationFilePath();
+ QString protoId = QCoreApplication::applicationFilePath();
#if defined(Q_OS_WIN)
- protoId = protoId.toLower();
+ protoId = protoId.toLower();
#endif
- auto prefix = protoId.section(QLatin1Char('/'), -1);
- prefix.remove(QRegExp("[^a-zA-Z]"));
- prefix.truncate(6);
- QByteArray idc = protoId.toUtf8();
- quint16 idNum = qChecksum(idc.constData(), idc.size());
- auto socketName = QLatin1String("qtsingleapp-") + prefix + QLatin1Char('-') + QString::number(idNum, 16);
+ auto prefix = protoId.section(QLatin1Char('/'), -1);
+ prefix.remove(QRegExp("[^a-zA-Z]"));
+ prefix.truncate(6);
+ QByteArray idc = protoId.toUtf8();
+ quint16 idNum = qChecksum(idc.constData(), idc.size());
+ auto socketName = QLatin1String("qtsingleapp-") + prefix + QLatin1Char('-') + QString::number(idNum, 16);
#if defined(Q_OS_WIN)
- if (!pProcessIdToSessionId)
- {
- QLibrary lib("kernel32");
- pProcessIdToSessionId = (PProcessIdToSessionId)lib.resolve("ProcessIdToSessionId");
- }
- if (pProcessIdToSessionId)
- {
- DWORD sessionId = 0;
- pProcessIdToSessionId(GetCurrentProcessId(), &sessionId);
- socketName += QLatin1Char('-') + QString::number(sessionId, 16);
- }
+ if (!pProcessIdToSessionId)
+ {
+ QLibrary lib("kernel32");
+ pProcessIdToSessionId = (PProcessIdToSessionId)lib.resolve("ProcessIdToSessionId");
+ }
+ if (pProcessIdToSessionId)
+ {
+ DWORD sessionId = 0;
+ pProcessIdToSessionId(GetCurrentProcessId(), &sessionId);
+ socketName += QLatin1Char('-') + QString::number(sessionId, 16);
+ }
#else
- socketName += QLatin1Char('-') + QString::number(::getuid(), 16);
+ socketName += QLatin1Char('-') + QString::number(::getuid(), 16);
#endif
- return ApplicationId(socketName);
+ return ApplicationId(socketName);
}
ApplicationId ApplicationId::fromPathAndVersion(const QString& dataPath, const QString& version)
{
- QCryptographicHash shasum(QCryptographicHash::Algorithm::Sha1);
- QString result = dataPath + QLatin1Char('-') + version;
- shasum.addData(result.toUtf8());
- return ApplicationId(QLatin1String("qtsingleapp-") + QString::fromLatin1(shasum.result().toHex()));
+ QCryptographicHash shasum(QCryptographicHash::Algorithm::Sha1);
+ QString result = dataPath + QLatin1Char('-') + version;
+ shasum.addData(result.toUtf8());
+ return ApplicationId(QLatin1String("qtsingleapp-") + QString::fromLatin1(shasum.result().toHex()));
}
ApplicationId ApplicationId::fromCustomId(const QString& id)
{
- return ApplicationId(QLatin1String("qtsingleapp-") + id);
+ return ApplicationId(QLatin1String("qtsingleapp-") + id);
}
ApplicationId ApplicationId::fromRawString(const QString& id)
{
- return ApplicationId(id);
+ return ApplicationId(id);
}
LocalPeer::LocalPeer(QObject * parent, const ApplicationId &appId)
- : QObject(parent), id(appId)
+ : QObject(parent), id(appId)
{
- socketName = id.toString();
- server.reset(new QLocalServer());
- QString lockName = QDir(QDir::tempPath()).absolutePath() + QLatin1Char('/') + socketName + QLatin1String("-lockfile");
- lockFile.reset(new LockedFile(lockName));
- lockFile->open(QIODevice::ReadWrite);
+ socketName = id.toString();
+ server.reset(new QLocalServer());
+ QString lockName = QDir(QDir::tempPath()).absolutePath() + QLatin1Char('/') + socketName + QLatin1String("-lockfile");
+ lockFile.reset(new LockedFile(lockName));
+ lockFile->open(QIODevice::ReadWrite);
}
LocalPeer::~LocalPeer()
@@ -129,113 +129,113 @@ LocalPeer::~LocalPeer()
ApplicationId LocalPeer::applicationId() const
{
- return id;
+ return id;
}
bool LocalPeer::isClient()
{
- if (lockFile->isLocked())
- return false;
+ if (lockFile->isLocked())
+ return false;
- if (!lockFile->lock(LockedFile::WriteLock, false))
- return true;
+ if (!lockFile->lock(LockedFile::WriteLock, false))
+ return true;
- bool res = server->listen(socketName);
+ bool res = server->listen(socketName);
#if defined(Q_OS_UNIX)
- // ### Workaround
- if (!res && server->serverError() == QAbstractSocket::AddressInUseError) {
- QFile::remove(QDir::cleanPath(QDir::tempPath())+QLatin1Char('/')+socketName);
- res = server->listen(socketName);
- }
+ // ### Workaround
+ if (!res && server->serverError() == QAbstractSocket::AddressInUseError) {
+ QFile::remove(QDir::cleanPath(QDir::tempPath())+QLatin1Char('/')+socketName);
+ res = server->listen(socketName);
+ }
#endif
- if (!res)
- qWarning("QtSingleCoreApplication: listen on local socket failed, %s", qPrintable(server->errorString()));
- QObject::connect(server.get(), SIGNAL(newConnection()), SLOT(receiveConnection()));
- return false;
+ if (!res)
+ qWarning("QtSingleCoreApplication: listen on local socket failed, %s", qPrintable(server->errorString()));
+ QObject::connect(server.get(), SIGNAL(newConnection()), SLOT(receiveConnection()));
+ return false;
}
bool LocalPeer::sendMessage(const QString &message, int timeout)
{
- if (!isClient())
- return false;
-
- QLocalSocket socket;
- bool connOk = false;
- for(int i = 0; i < 2; i++) {
- // Try twice, in case the other instance is just starting up
- socket.connectToServer(socketName);
- connOk = socket.waitForConnected(timeout/2);
- if (connOk || i)
- {
- break;
- }
- std::this_thread::sleep_for(std::chrono::milliseconds(250));
- }
- if (!connOk)
- {
- return false;
- }
-
- QByteArray uMsg(message.toUtf8());
- QDataStream ds(&socket);
-
- ds.writeBytes(uMsg.constData(), uMsg.size());
- if(!socket.waitForBytesWritten(timeout))
- {
- return false;
- }
-
- // wait for 'ack'
- if(!socket.waitForReadyRead(timeout))
- {
- return false;
- }
-
- // make sure we got 'ack'
- if(!(socket.read(qstrlen(ack)) == ack))
- {
- return false;
- }
- return true;
+ if (!isClient())
+ return false;
+
+ QLocalSocket socket;
+ bool connOk = false;
+ for(int i = 0; i < 2; i++) {
+ // Try twice, in case the other instance is just starting up
+ socket.connectToServer(socketName);
+ connOk = socket.waitForConnected(timeout/2);
+ if (connOk || i)
+ {
+ break;
+ }
+ std::this_thread::sleep_for(std::chrono::milliseconds(250));
+ }
+ if (!connOk)
+ {
+ return false;
+ }
+
+ QByteArray uMsg(message.toUtf8());
+ QDataStream ds(&socket);
+
+ ds.writeBytes(uMsg.constData(), uMsg.size());
+ if(!socket.waitForBytesWritten(timeout))
+ {
+ return false;
+ }
+
+ // wait for 'ack'
+ if(!socket.waitForReadyRead(timeout))
+ {
+ return false;
+ }
+
+ // make sure we got 'ack'
+ if(!(socket.read(qstrlen(ack)) == ack))
+ {
+ return false;
+ }
+ return true;
}
void LocalPeer::receiveConnection()
{
- QLocalSocket* socket = server->nextPendingConnection();
- if (!socket)
- {
- return;
- }
-
- while (socket->bytesAvailable() < (int)sizeof(quint32))
- {
- socket->waitForReadyRead();
- }
- QDataStream ds(socket);
- QByteArray uMsg;
- quint32 remaining;
- ds >> remaining;
- uMsg.resize(remaining);
- int got = 0;
- char* uMsgBuf = uMsg.data();
- do
- {
- got = ds.readRawData(uMsgBuf, remaining);
- remaining -= got;
- uMsgBuf += got;
- } while (remaining && got >= 0 && socket->waitForReadyRead(2000));
- if (got < 0)
- {
- qWarning("QtLocalPeer: Message reception failed %s", socket->errorString().toLatin1().constData());
- delete socket;
- return;
- }
- QString message(QString::fromUtf8(uMsg));
- socket->write(ack, qstrlen(ack));
- socket->waitForBytesWritten(1000);
- socket->waitForDisconnected(1000); // make sure client reads ack
- delete socket;
- emit messageReceived(message); //### (might take a long time to return)
+ QLocalSocket* socket = server->nextPendingConnection();
+ if (!socket)
+ {
+ return;
+ }
+
+ while (socket->bytesAvailable() < (int)sizeof(quint32))
+ {
+ socket->waitForReadyRead();
+ }
+ QDataStream ds(socket);
+ QByteArray uMsg;
+ quint32 remaining;
+ ds >> remaining;
+ uMsg.resize(remaining);
+ int got = 0;
+ char* uMsgBuf = uMsg.data();
+ do
+ {
+ got = ds.readRawData(uMsgBuf, remaining);
+ remaining -= got;
+ uMsgBuf += got;
+ } while (remaining && got >= 0 && socket->waitForReadyRead(2000));
+ if (got < 0)
+ {
+ qWarning("QtLocalPeer: Message reception failed %s", socket->errorString().toLatin1().constData());
+ delete socket;
+ return;
+ }
+ QString message(QString::fromUtf8(uMsg));
+ socket->write(ack, qstrlen(ack));
+ socket->waitForBytesWritten(1000);
+ socket->waitForDisconnected(1000); // make sure client reads ack
+ delete socket;
+ emit messageReceived(message); //### (might take a long time to return)
}
diff --git a/libraries/LocalPeer/src/LockedFile.cpp b/libraries/LocalPeer/src/LockedFile.cpp
index a4951bfe..73294a16 100644
--- a/libraries/LocalPeer/src/LockedFile.cpp
+++ b/libraries/LocalPeer/src/LockedFile.cpp
@@ -41,70 +41,70 @@
#include "LockedFile.h"
/*!
- \class QtLockedFile
-
- \brief The QtLockedFile class extends QFile with advisory locking
- functions.
-
- A file may be locked in read or write mode. Multiple instances of
- \e QtLockedFile, created in multiple processes running on the same
- machine, may have a file locked in read mode. Exactly one instance
- may have it locked in write mode. A read and a write lock cannot
- exist simultaneously on the same file.
-
- The file locks are advisory. This means that nothing prevents
- another process from manipulating a locked file using QFile or
- file system functions offered by the OS. Serialization is only
- guaranteed if all processes that access the file use
- QLockedFile. Also, while holding a lock on a file, a process
- must not open the same file again (through any API), or locks
- can be unexpectedly lost.
-
- The lock provided by an instance of \e QtLockedFile is released
- whenever the program terminates. This is true even when the
- program crashes and no destructors are called.
+ \class QtLockedFile
+
+ \brief The QtLockedFile class extends QFile with advisory locking
+ functions.
+
+ A file may be locked in read or write mode. Multiple instances of
+ \e QtLockedFile, created in multiple processes running on the same
+ machine, may have a file locked in read mode. Exactly one instance
+ may have it locked in write mode. A read and a write lock cannot
+ exist simultaneously on the same file.
+
+ The file locks are advisory. This means that nothing prevents
+ another process from manipulating a locked file using QFile or
+ file system functions offered by the OS. Serialization is only
+ guaranteed if all processes that access the file use
+ QLockedFile. Also, while holding a lock on a file, a process
+ must not open the same file again (through any API), or locks
+ can be unexpectedly lost.
+
+ The lock provided by an instance of \e QtLockedFile is released
+ whenever the program terminates. This is true even when the
+ program crashes and no destructors are called.
*/
/*! \enum QtLockedFile::LockMode
- This enum describes the available lock modes.
+ This enum describes the available lock modes.
- \value ReadLock A read lock.
- \value WriteLock A write lock.
- \value NoLock Neither a read lock nor a write lock.
+ \value ReadLock A read lock.
+ \value WriteLock A write lock.
+ \value NoLock Neither a read lock nor a write lock.
*/
/*!
- Constructs an unlocked \e QtLockedFile object. This constructor
- behaves in the same way as \e QFile::QFile().
+ Constructs an unlocked \e QtLockedFile object. This constructor
+ behaves in the same way as \e QFile::QFile().
- \sa QFile::QFile()
+ \sa QFile::QFile()
*/
LockedFile::LockedFile()
- : QFile()
+ : QFile()
{
#ifdef Q_OS_WIN
- wmutex = 0;
- rmutex = 0;
+ wmutex = 0;
+ rmutex = 0;
#endif
- m_lock_mode = NoLock;
+ m_lock_mode = NoLock;
}
/*!
- Constructs an unlocked QtLockedFile object with file \a name. This
- constructor behaves in the same way as \e QFile::QFile(const
- QString&).
+ Constructs an unlocked QtLockedFile object with file \a name. This
+ constructor behaves in the same way as \e QFile::QFile(const
+ QString&).
- \sa QFile::QFile()
+ \sa QFile::QFile()
*/
LockedFile::LockedFile(const QString &name)
- : QFile(name)
+ : QFile(name)
{
#ifdef Q_OS_WIN
- wmutex = 0;
- rmutex = 0;
+ wmutex = 0;
+ rmutex = 0;
#endif
- m_lock_mode = NoLock;
+ m_lock_mode = NoLock;
}
/*!
@@ -122,72 +122,72 @@ Returns true if successful; otherwise false.
*/
bool LockedFile::open(OpenMode mode)
{
- if (mode & QIODevice::Truncate) {
- qWarning("QtLockedFile::open(): Truncate mode not allowed.");
- return false;
- }
- return QFile::open(mode);
+ if (mode & QIODevice::Truncate) {
+ qWarning("QtLockedFile::open(): Truncate mode not allowed.");
+ return false;
+ }
+ return QFile::open(mode);
}
/*!
- Returns \e true if this object has a in read or write lock;
- otherwise returns \e false.
+ Returns \e true if this object has a in read or write lock;
+ otherwise returns \e false.
- \sa lockMode()
+ \sa lockMode()
*/
bool LockedFile::isLocked() const
{
- return m_lock_mode != NoLock;
+ return m_lock_mode != NoLock;
}
/*!
- Returns the type of lock currently held by this object, or \e
- QtLockedFile::NoLock.
+ Returns the type of lock currently held by this object, or \e
+ QtLockedFile::NoLock.
- \sa isLocked()
+ \sa isLocked()
*/
LockedFile::LockMode LockedFile::lockMode() const
{
- return m_lock_mode;
+ return m_lock_mode;
}
/*!
- \fn bool QtLockedFile::lock(LockMode mode, bool block = true)
+ \fn bool QtLockedFile::lock(LockMode mode, bool block = true)
- Obtains a lock of type \a mode. The file must be opened before it
- can be locked.
+ Obtains a lock of type \a mode. The file must be opened before it
+ can be locked.
- If \a block is true, this function will block until the lock is
- aquired. If \a block is false, this function returns \e false
- immediately if the lock cannot be aquired.
+ If \a block is true, this function will block until the lock is
+ aquired. If \a block is false, this function returns \e false
+ immediately if the lock cannot be aquired.
- If this object already has a lock of type \a mode, this function
- returns \e true immediately. If this object has a lock of a
- different type than \a mode, the lock is first released and then a
- new lock is obtained.
+ If this object already has a lock of type \a mode, this function
+ returns \e true immediately. If this object has a lock of a
+ different type than \a mode, the lock is first released and then a
+ new lock is obtained.
- This function returns \e true if, after it executes, the file is
- locked by this object, and \e false otherwise.
+ This function returns \e true if, after it executes, the file is
+ locked by this object, and \e false otherwise.
- \sa unlock(), isLocked(), lockMode()
+ \sa unlock(), isLocked(), lockMode()
*/
/*!
- \fn bool QtLockedFile::unlock()
+ \fn bool QtLockedFile::unlock()
- Releases a lock.
+ Releases a lock.
- If the object has no lock, this function returns immediately.
+ If the object has no lock, this function returns immediately.
- This function returns \e true if, after it executes, the file is
- not locked by this object, and \e false otherwise.
+ This function returns \e true if, after it executes, the file is
+ not locked by this object, and \e false otherwise.
- \sa lock(), isLocked(), lockMode()
+ \sa lock(), isLocked(), lockMode()
*/
/*!
- \fn QtLockedFile::~QtLockedFile()
+ \fn QtLockedFile::~QtLockedFile()
- Destroys the \e QtLockedFile object. If any locks were held, they
- are released.
+ Destroys the \e QtLockedFile object. If any locks were held, they
+ are released.
*/
diff --git a/libraries/LocalPeer/src/LockedFile.h b/libraries/LocalPeer/src/LockedFile.h
index 8c178250..2f29ee20 100644
--- a/libraries/LocalPeer/src/LockedFile.h
+++ b/libraries/LocalPeer/src/LockedFile.h
@@ -48,30 +48,30 @@
class LockedFile : public QFile
{
public:
- enum LockMode { NoLock = 0, ReadLock, WriteLock };
+ enum LockMode { NoLock = 0, ReadLock, WriteLock };
- LockedFile();
- LockedFile(const QString &name);
- ~LockedFile();
+ LockedFile();
+ LockedFile(const QString &name);
+ ~LockedFile();
- bool open(OpenMode mode);
+ bool open(OpenMode mode);
- bool lock(LockMode mode, bool block = true);
- bool unlock();
- bool isLocked() const;
- LockMode lockMode() const;
+ bool lock(LockMode mode, bool block = true);
+ bool unlock();
+ bool isLocked() const;
+ LockMode lockMode() const;
- private:
+ private:
#ifdef Q_OS_WIN
- Qt::HANDLE wmutex;
- Qt::HANDLE rmutex;
- QVector<Qt::HANDLE> rmutexes;
- QString mutexname;
+ Qt::HANDLE wmutex;
+ Qt::HANDLE rmutex;
+ QVector<Qt::HANDLE> rmutexes;
+ QString mutexname;
- Qt::HANDLE getMutexHandle(int idx, bool doCreate);
- bool waitMutex(Qt::HANDLE mutex, bool doBlock);
+ Qt::HANDLE getMutexHandle(int idx, bool doCreate);
+ bool waitMutex(Qt::HANDLE mutex, bool doBlock);
#endif
- LockMode m_lock_mode;
+ LockMode m_lock_mode;
};
diff --git a/libraries/LocalPeer/src/LockedFile_unix.cpp b/libraries/LocalPeer/src/LockedFile_unix.cpp
index 4b68916c..6becc89e 100644
--- a/libraries/LocalPeer/src/LockedFile_unix.cpp
+++ b/libraries/LocalPeer/src/LockedFile_unix.cpp
@@ -47,68 +47,68 @@
bool LockedFile::lock(LockMode mode, bool block)
{
- if (!isOpen()) {
- qWarning("QtLockedFile::lock(): file is not opened");
- return false;
- }
+ if (!isOpen()) {
+ qWarning("QtLockedFile::lock(): file is not opened");
+ return false;
+ }
- if (mode == NoLock)
- return unlock();
+ if (mode == NoLock)
+ return unlock();
- if (mode == m_lock_mode)
- return true;
+ if (mode == m_lock_mode)
+ return true;
- if (m_lock_mode != NoLock)
- unlock();
+ if (m_lock_mode != NoLock)
+ unlock();
- struct flock fl;
- fl.l_whence = SEEK_SET;
- fl.l_start = 0;
- fl.l_len = 0;
- fl.l_type = (mode == ReadLock) ? F_RDLCK : F_WRLCK;
- int cmd = block ? F_SETLKW : F_SETLK;
- int ret = fcntl(handle(), cmd, &fl);
+ struct flock fl;
+ fl.l_whence = SEEK_SET;
+ fl.l_start = 0;
+ fl.l_len = 0;
+ fl.l_type = (mode == ReadLock) ? F_RDLCK : F_WRLCK;
+ int cmd = block ? F_SETLKW : F_SETLK;
+ int ret = fcntl(handle(), cmd, &fl);
- if (ret == -1) {
- if (errno != EINTR && errno != EAGAIN)
- qWarning("QtLockedFile::lock(): fcntl: %s", strerror(errno));
- return false;
- }
+ if (ret == -1) {
+ if (errno != EINTR && errno != EAGAIN)
+ qWarning("QtLockedFile::lock(): fcntl: %s", strerror(errno));
+ return false;
+ }
- m_lock_mode = mode;
- return true;
+ m_lock_mode = mode;
+ return true;
}
bool LockedFile::unlock()
{
- if (!isOpen()) {
- qWarning("QtLockedFile::unlock(): file is not opened");
- return false;
- }
-
- if (!isLocked())
- return true;
-
- struct flock fl;
- fl.l_whence = SEEK_SET;
- fl.l_start = 0;
- fl.l_len = 0;
- fl.l_type = F_UNLCK;
- int ret = fcntl(handle(), F_SETLKW, &fl);
-
- if (ret == -1) {
- qWarning("QtLockedFile::lock(): fcntl: %s", strerror(errno));
- return false;
- }
-
- m_lock_mode = NoLock;
- return true;
+ if (!isOpen()) {
+ qWarning("QtLockedFile::unlock(): file is not opened");
+ return false;
+ }
+
+ if (!isLocked())
+ return true;
+
+ struct flock fl;
+ fl.l_whence = SEEK_SET;
+ fl.l_start = 0;
+ fl.l_len = 0;
+ fl.l_type = F_UNLCK;
+ int ret = fcntl(handle(), F_SETLKW, &fl);
+
+ if (ret == -1) {
+ qWarning("QtLockedFile::lock(): fcntl: %s", strerror(errno));
+ return false;
+ }
+
+ m_lock_mode = NoLock;
+ return true;
}
LockedFile::~LockedFile()
{
- if (isOpen())
- unlock();
+ if (isOpen())
+ unlock();
}
diff --git a/libraries/LocalPeer/src/LockedFile_win.cpp b/libraries/LocalPeer/src/LockedFile_win.cpp
index f93ef27f..93d2c73b 100644
--- a/libraries/LocalPeer/src/LockedFile_win.cpp
+++ b/libraries/LocalPeer/src/LockedFile_win.cpp
@@ -48,158 +48,158 @@
Qt::HANDLE LockedFile::getMutexHandle(int idx, bool doCreate)
{
- if (mutexname.isEmpty()) {
- QFileInfo fi(*this);
- mutexname = QString::fromLatin1(MUTEX_PREFIX)
- + fi.absoluteFilePath().toLower();
- }
- QString mname(mutexname);
- if (idx >= 0)
- mname += QString::number(idx);
-
- Qt::HANDLE mutex;
- if (doCreate) {
- mutex = CreateMutexW(NULL, FALSE, (LPCWSTR)mname.utf16());
- if (!mutex) {
- qErrnoWarning("QtLockedFile::lock(): CreateMutex failed");
- return 0;
- }
- }
- else {
- OpenMutexW(SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, (LPCWSTR)mname.utf16());
- if (!mutex) {
- if (GetLastError() != ERROR_FILE_NOT_FOUND)
- qErrnoWarning("QtLockedFile::lock(): OpenMutex failed");
- return 0;
- }
- }
- return mutex;
+ if (mutexname.isEmpty()) {
+ QFileInfo fi(*this);
+ mutexname = QString::fromLatin1(MUTEX_PREFIX)
+ + fi.absoluteFilePath().toLower();
+ }
+ QString mname(mutexname);
+ if (idx >= 0)
+ mname += QString::number(idx);
+
+ Qt::HANDLE mutex;
+ if (doCreate) {
+ mutex = CreateMutexW(NULL, FALSE, (LPCWSTR)mname.utf16());
+ if (!mutex) {
+ qErrnoWarning("QtLockedFile::lock(): CreateMutex failed");
+ return 0;
+ }
+ }
+ else {
+ mutex = OpenMutexW(SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, (LPCWSTR)mname.utf16());
+ if (!mutex) {
+ if (GetLastError() != ERROR_FILE_NOT_FOUND)
+ qErrnoWarning("QtLockedFile::lock(): OpenMutex failed");
+ return 0;
+ }
+ }
+ return mutex;
}
bool LockedFile::waitMutex(Qt::HANDLE mutex, bool doBlock)
{
- Q_ASSERT(mutex);
- DWORD res = WaitForSingleObject(mutex, doBlock ? INFINITE : 0);
- switch (res) {
- case WAIT_OBJECT_0:
- case WAIT_ABANDONED:
- return true;
- break;
- case WAIT_TIMEOUT:
- break;
- default:
- qErrnoWarning("QtLockedFile::lock(): WaitForSingleObject failed");
- }
- return false;
+ Q_ASSERT(mutex);
+ DWORD res = WaitForSingleObject(mutex, doBlock ? INFINITE : 0);
+ switch (res) {
+ case WAIT_OBJECT_0:
+ case WAIT_ABANDONED:
+ return true;
+ break;
+ case WAIT_TIMEOUT:
+ break;
+ default:
+ qErrnoWarning("QtLockedFile::lock(): WaitForSingleObject failed");
+ }
+ return false;
}
bool LockedFile::lock(LockMode mode, bool block)
{
- if (!isOpen()) {
- qWarning("QtLockedFile::lock(): file is not opened");
- return false;
- }
-
- if (mode == NoLock)
- return unlock();
-
- if (mode == m_lock_mode)
- return true;
-
- if (m_lock_mode != NoLock)
- unlock();
-
- if (!wmutex && !(wmutex = getMutexHandle(-1, true)))
- return false;
-
- if (!waitMutex(wmutex, block))
- return false;
-
- if (mode == ReadLock) {
- int idx = 0;
- for (; idx < MAX_READERS; idx++) {
- rmutex = getMutexHandle(idx, false);
- if (!rmutex || waitMutex(rmutex, false))
- break;
- CloseHandle(rmutex);
- }
- bool ok = true;
- if (idx >= MAX_READERS) {
- qWarning("QtLockedFile::lock(): too many readers");
- rmutex = 0;
- ok = false;
- }
- else if (!rmutex) {
- rmutex = getMutexHandle(idx, true);
- if (!rmutex || !waitMutex(rmutex, false))
- ok = false;
- }
- if (!ok && rmutex) {
- CloseHandle(rmutex);
- rmutex = 0;
- }
- ReleaseMutex(wmutex);
- if (!ok)
- return false;
- }
- else {
- Q_ASSERT(rmutexes.isEmpty());
- for (int i = 0; i < MAX_READERS; i++) {
- Qt::HANDLE mutex = getMutexHandle(i, false);
- if (mutex)
- rmutexes.append(mutex);
- }
- if (rmutexes.size()) {
- DWORD res = WaitForMultipleObjects(rmutexes.size(), rmutexes.constData(),
- TRUE, block ? INFINITE : 0);
- if (res != WAIT_OBJECT_0 && res != WAIT_ABANDONED) {
- if (res != WAIT_TIMEOUT)
- qErrnoWarning("QtLockedFile::lock(): WaitForMultipleObjects failed");
- m_lock_mode = WriteLock; // trick unlock() to clean up - semiyucky
- unlock();
- return false;
- }
- }
- }
-
- m_lock_mode = mode;
- return true;
+ if (!isOpen()) {
+ qWarning("QtLockedFile::lock(): file is not opened");
+ return false;
+ }
+
+ if (mode == NoLock)
+ return unlock();
+
+ if (mode == m_lock_mode)
+ return true;
+
+ if (m_lock_mode != NoLock)
+ unlock();
+
+ if (!wmutex && !(wmutex = getMutexHandle(-1, true)))
+ return false;
+
+ if (!waitMutex(wmutex, block))
+ return false;
+
+ if (mode == ReadLock) {
+ int idx = 0;
+ for (; idx < MAX_READERS; idx++) {
+ rmutex = getMutexHandle(idx, false);
+ if (!rmutex || waitMutex(rmutex, false))
+ break;
+ CloseHandle(rmutex);
+ }
+ bool ok = true;
+ if (idx >= MAX_READERS) {
+ qWarning("QtLockedFile::lock(): too many readers");
+ rmutex = 0;
+ ok = false;
+ }
+ else if (!rmutex) {
+ rmutex = getMutexHandle(idx, true);
+ if (!rmutex || !waitMutex(rmutex, false))
+ ok = false;
+ }
+ if (!ok && rmutex) {
+ CloseHandle(rmutex);
+ rmutex = 0;
+ }
+ ReleaseMutex(wmutex);
+ if (!ok)
+ return false;
+ }
+ else {
+ Q_ASSERT(rmutexes.isEmpty());
+ for (int i = 0; i < MAX_READERS; i++) {
+ Qt::HANDLE mutex = getMutexHandle(i, false);
+ if (mutex)
+ rmutexes.append(mutex);
+ }
+ if (rmutexes.size()) {
+ DWORD res = WaitForMultipleObjects(rmutexes.size(), rmutexes.constData(),
+ TRUE, block ? INFINITE : 0);
+ if (res != WAIT_OBJECT_0 && res != WAIT_ABANDONED) {
+ if (res != WAIT_TIMEOUT)
+ qErrnoWarning("QtLockedFile::lock(): WaitForMultipleObjects failed");
+ m_lock_mode = WriteLock; // trick unlock() to clean up - semiyucky
+ unlock();
+ return false;
+ }
+ }
+ }
+
+ m_lock_mode = mode;
+ return true;
}
bool LockedFile::unlock()
{
- if (!isOpen()) {
- qWarning("QtLockedFile::unlock(): file is not opened");
- return false;
- }
-
- if (!isLocked())
- return true;
-
- if (m_lock_mode == ReadLock) {
- ReleaseMutex(rmutex);
- CloseHandle(rmutex);
- rmutex = 0;
- }
- else {
- foreach(Qt::HANDLE mutex, rmutexes) {
- ReleaseMutex(mutex);
- CloseHandle(mutex);
- }
- rmutexes.clear();
- ReleaseMutex(wmutex);
- }
-
- m_lock_mode = LockedFile::NoLock;
- return true;
+ if (!isOpen()) {
+ qWarning("QtLockedFile::unlock(): file is not opened");
+ return false;
+ }
+
+ if (!isLocked())
+ return true;
+
+ if (m_lock_mode == ReadLock) {
+ ReleaseMutex(rmutex);
+ CloseHandle(rmutex);
+ rmutex = 0;
+ }
+ else {
+ foreach(Qt::HANDLE mutex, rmutexes) {
+ ReleaseMutex(mutex);
+ CloseHandle(mutex);
+ }
+ rmutexes.clear();
+ ReleaseMutex(wmutex);
+ }
+
+ m_lock_mode = LockedFile::NoLock;
+ return true;
}
LockedFile::~LockedFile()
{
- if (isOpen())
- unlock();
- if (wmutex)
- CloseHandle(wmutex);
+ if (isOpen())
+ unlock();
+ if (wmutex)
+ CloseHandle(wmutex);
}
diff --git a/libraries/classparser/CMakeLists.txt b/libraries/classparser/CMakeLists.txt
index db266f53..3fe7591d 100644
--- a/libraries/classparser/CMakeLists.txt
+++ b/libraries/classparser/CMakeLists.txt
@@ -6,7 +6,7 @@ set(CMAKE_AUTOMOC ON)
include(TestBigEndian)
test_big_endian(BIGENDIAN)
if(${BIGENDIAN})
- add_definitions(-DMULTIMC_BIG_ENDIAN)
+ add_definitions(-DMULTIMC_BIG_ENDIAN)
endif(${BIGENDIAN})
# Find Qt
@@ -38,5 +38,4 @@ add_definitions(-DCLASSPARSER_LIBRARY)
add_library(MultiMC_classparser STATIC ${CLASSPARSER_SOURCES} ${CLASSPARSER_HEADERS})
target_include_directories(MultiMC_classparser PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include")
-target_link_libraries(MultiMC_classparser MultiMC_quazip)
-qt5_use_modules(MultiMC_classparser Core)
+target_link_libraries(MultiMC_classparser MultiMC_quazip Qt5::Core)
diff --git a/libraries/classparser/include/classparser.h b/libraries/classparser/include/classparser.h
index 23a65589..6c619e47 100644
--- a/libraries/classparser/include/classparser.h
+++ b/libraries/classparser/include/classparser.h
@@ -1,4 +1,4 @@
-/* Copyright 2013-2018 MultiMC Contributors
+/* Copyright 2013-2019 MultiMC Contributors
*
* Authors: Orochimarufan <orochimarufan.x3@gmail.com>
*
diff --git a/libraries/classparser/include/classparser_config.h b/libraries/classparser/include/classparser_config.h
index db8f40a3..ee053de6 100644
--- a/libraries/classparser/include/classparser_config.h
+++ b/libraries/classparser/include/classparser_config.h
@@ -1,4 +1,4 @@
-/* Copyright 2013-2018 MultiMC Contributors
+/* Copyright 2013-2019 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/libraries/classparser/src/annotations.cpp b/libraries/classparser/src/annotations.cpp
index d1a7c046..18a9e880 100644
--- a/libraries/classparser/src/annotations.cpp
+++ b/libraries/classparser/src/annotations.cpp
@@ -6,80 +6,80 @@ namespace java
{
std::string annotation::toString()
{
- std::ostringstream ss;
- ss << "Annotation type : " << type_index << " - " << pool[type_index].str_data << std::endl;
- ss << "Contains " << name_val_pairs.size() << " pairs:" << std::endl;
- for (unsigned i = 0; i < name_val_pairs.size(); i++)
- {
- std::pair<uint16_t, element_value *> &val = name_val_pairs[i];
- auto name_idx = val.first;
- ss << pool[name_idx].str_data << "(" << name_idx << ")"
- << " = " << val.second->toString() << std::endl;
- }
- return ss.str();
+ std::ostringstream ss;
+ ss << "Annotation type : " << type_index << " - " << pool[type_index].str_data << std::endl;
+ ss << "Contains " << name_val_pairs.size() << " pairs:" << std::endl;
+ for (unsigned i = 0; i < name_val_pairs.size(); i++)
+ {
+ std::pair<uint16_t, element_value *> &val = name_val_pairs[i];
+ auto name_idx = val.first;
+ ss << pool[name_idx].str_data << "(" << name_idx << ")"
+ << " = " << val.second->toString() << std::endl;
+ }
+ return ss.str();
}
annotation *annotation::read(util::membuffer &input, constant_pool &pool)
{
- uint16_t type_index = 0;
- input.read_be(type_index);
- annotation *ann = new annotation(type_index, pool);
+ uint16_t type_index = 0;
+ input.read_be(type_index);
+ annotation *ann = new annotation(type_index, pool);
- uint16_t num_pairs = 0;
- input.read_be(num_pairs);
- while (num_pairs)
- {
- uint16_t name_idx = 0;
- // read name index
- input.read_be(name_idx);
- auto elem = element_value::readElementValue(input, pool);
- // read value
- ann->add_pair(name_idx, elem);
- num_pairs--;
- }
- return ann;
+ uint16_t num_pairs = 0;
+ input.read_be(num_pairs);
+ while (num_pairs)
+ {
+ uint16_t name_idx = 0;
+ // read name index
+ input.read_be(name_idx);
+ auto elem = element_value::readElementValue(input, pool);
+ // read value
+ ann->add_pair(name_idx, elem);
+ num_pairs--;
+ }
+ return ann;
}
element_value *element_value::readElementValue(util::membuffer &input,
- java::constant_pool &pool)
+ java::constant_pool &pool)
{
- element_value_type type = INVALID;
- input.read(type);
- uint16_t index = 0;
- uint16_t index2 = 0;
- std::vector<element_value *> vals;
- switch (type)
- {
- case PRIMITIVE_BYTE:
- case PRIMITIVE_CHAR:
- case PRIMITIVE_DOUBLE:
- case PRIMITIVE_FLOAT:
- case PRIMITIVE_INT:
- case PRIMITIVE_LONG:
- case PRIMITIVE_SHORT:
- case PRIMITIVE_BOOLEAN:
- case STRING:
- input.read_be(index);
- return new element_value_simple(type, index, pool);
- case ENUM_CONSTANT:
- input.read_be(index);
- input.read_be(index2);
- return new element_value_enum(type, index, index2, pool);
- case CLASS: // Class
- input.read_be(index);
- return new element_value_class(type, index, pool);
- case ANNOTATION: // Annotation
- // FIXME: runtime visibility info needs to be passed from parent
- return new element_value_annotation(ANNOTATION, annotation::read(input, pool), pool);
- case ARRAY: // Array
- input.read_be(index);
- for (int i = 0; i < index; i++)
- {
- vals.push_back(element_value::readElementValue(input, pool));
- }
- return new element_value_array(ARRAY, vals, pool);
- default:
- throw new java::classfile_exception();
- }
+ element_value_type type = INVALID;
+ input.read(type);
+ uint16_t index = 0;
+ uint16_t index2 = 0;
+ std::vector<element_value *> vals;
+ switch (type)
+ {
+ case PRIMITIVE_BYTE:
+ case PRIMITIVE_CHAR:
+ case PRIMITIVE_DOUBLE:
+ case PRIMITIVE_FLOAT:
+ case PRIMITIVE_INT:
+ case PRIMITIVE_LONG:
+ case PRIMITIVE_SHORT:
+ case PRIMITIVE_BOOLEAN:
+ case STRING:
+ input.read_be(index);
+ return new element_value_simple(type, index, pool);
+ case ENUM_CONSTANT:
+ input.read_be(index);
+ input.read_be(index2);
+ return new element_value_enum(type, index, index2, pool);
+ case CLASS: // Class
+ input.read_be(index);
+ return new element_value_class(type, index, pool);
+ case ANNOTATION: // Annotation
+ // FIXME: runtime visibility info needs to be passed from parent
+ return new element_value_annotation(ANNOTATION, annotation::read(input, pool), pool);
+ case ARRAY: // Array
+ input.read_be(index);
+ for (int i = 0; i < index; i++)
+ {
+ vals.push_back(element_value::readElementValue(input, pool));
+ }
+ return new element_value_array(ARRAY, vals, pool);
+ default:
+ throw new java::classfile_exception();
+ }
}
} \ No newline at end of file
diff --git a/libraries/classparser/src/annotations.h b/libraries/classparser/src/annotations.h
index dd603af3..15bf05a4 100644
--- a/libraries/classparser/src/annotations.h
+++ b/libraries/classparser/src/annotations.h
@@ -7,21 +7,21 @@ namespace java
{
enum element_value_type : uint8_t
{
- INVALID = 0,
- STRING = 's',
- ENUM_CONSTANT = 'e',
- CLASS = 'c',
- ANNOTATION = '@',
- ARRAY = '[', // one array dimension
- PRIMITIVE_INT = 'I', // integer
- PRIMITIVE_BYTE = 'B', // signed byte
- PRIMITIVE_CHAR = 'C', // Unicode character code point in the Basic Multilingual Plane,
- // encoded with UTF-16
- PRIMITIVE_DOUBLE = 'D', // double-precision floating-point value
- PRIMITIVE_FLOAT = 'F', // single-precision floating-point value
- PRIMITIVE_LONG = 'J', // long integer
- PRIMITIVE_SHORT = 'S', // signed short
- PRIMITIVE_BOOLEAN = 'Z' // true or false
+ INVALID = 0,
+ STRING = 's',
+ ENUM_CONSTANT = 'e',
+ CLASS = 'c',
+ ANNOTATION = '@',
+ ARRAY = '[', // one array dimension
+ PRIMITIVE_INT = 'I', // integer
+ PRIMITIVE_BYTE = 'B', // signed byte
+ PRIMITIVE_CHAR = 'C', // Unicode character code point in the Basic Multilingual Plane,
+ // encoded with UTF-16
+ PRIMITIVE_DOUBLE = 'D', // double-precision floating-point value
+ PRIMITIVE_FLOAT = 'F', // single-precision floating-point value
+ PRIMITIVE_LONG = 'J', // long integer
+ PRIMITIVE_SHORT = 'S', // signed short
+ PRIMITIVE_BOOLEAN = 'Z' // true or false
};
/**
* The element_value structure is a discriminated union representing the value of an
@@ -37,21 +37,21 @@ enum element_value_type : uint8_t
class element_value
{
protected:
- element_value_type type;
- constant_pool &pool;
+ element_value_type type;
+ constant_pool &pool;
public:
- element_value(element_value_type type, constant_pool &pool) : type(type), pool(pool) {};
- virtual ~element_value() {}
+ element_value(element_value_type type, constant_pool &pool) : type(type), pool(pool) {};
+ virtual ~element_value() {}
- element_value_type getElementValueType()
- {
- return type;
- }
+ element_value_type getElementValueType()
+ {
+ return type;
+ }
- virtual std::string toString() = 0;
+ virtual std::string toString() = 0;
- static element_value *readElementValue(util::membuffer &input, constant_pool &pool);
+ static element_value *readElementValue(util::membuffer &input, constant_pool &pool);
};
/**
@@ -62,58 +62,58 @@ public:
class annotation
{
public:
- typedef std::vector<std::pair<uint16_t, element_value *>> value_list;
+ typedef std::vector<std::pair<uint16_t, element_value *>> value_list;
protected:
- /**
- * The value of the type_index item must be a valid index into the constant_pool table.
- * The constant_pool entry at that index must be a CONSTANT_Utf8_info (§4.4.7) structure
- * representing a field descriptor representing the annotation type corresponding
- * to the annotation represented by this annotation structure.
- */
- uint16_t type_index;
- /**
- * map between element_name_index and value.
- *
- * The value of the element_name_index item must be a valid index into the constant_pool
- *table.
- * The constant_pool entry at that index must be a CONSTANT_Utf8_info (§4.4.7) structure
- *representing
- * a valid field descriptor (§4.3.2) that denotes the name of the annotation type element
- *represented
- * by this element_value_pairs entry.
- */
- value_list name_val_pairs;
- /**
- * Reference to the parent constant pool
- */
- constant_pool &pool;
+ /**
+ * The value of the type_index item must be a valid index into the constant_pool table.
+ * The constant_pool entry at that index must be a CONSTANT_Utf8_info (§4.4.7) structure
+ * representing a field descriptor representing the annotation type corresponding
+ * to the annotation represented by this annotation structure.
+ */
+ uint16_t type_index;
+ /**
+ * map between element_name_index and value.
+ *
+ * The value of the element_name_index item must be a valid index into the constant_pool
+ *table.
+ * The constant_pool entry at that index must be a CONSTANT_Utf8_info (§4.4.7) structure
+ *representing
+ * a valid field descriptor (§4.3.2) that denotes the name of the annotation type element
+ *represented
+ * by this element_value_pairs entry.
+ */
+ value_list name_val_pairs;
+ /**
+ * Reference to the parent constant pool
+ */
+ constant_pool &pool;
public:
- annotation(uint16_t type_index, constant_pool &pool)
- : type_index(type_index), pool(pool) {};
- ~annotation()
- {
- for (unsigned i = 0; i < name_val_pairs.size(); i++)
- {
- delete name_val_pairs[i].second;
- }
- }
- void add_pair(uint16_t key, element_value *value)
- {
- name_val_pairs.push_back(std::make_pair(key, value));
- }
- ;
- value_list::const_iterator begin()
- {
- return name_val_pairs.cbegin();
- }
- value_list::const_iterator end()
- {
- return name_val_pairs.cend();
- }
- std::string toString();
- static annotation *read(util::membuffer &input, constant_pool &pool);
+ annotation(uint16_t type_index, constant_pool &pool)
+ : type_index(type_index), pool(pool) {};
+ ~annotation()
+ {
+ for (unsigned i = 0; i < name_val_pairs.size(); i++)
+ {
+ delete name_val_pairs[i].second;
+ }
+ }
+ void add_pair(uint16_t key, element_value *value)
+ {
+ name_val_pairs.push_back(std::make_pair(key, value));
+ }
+ ;
+ value_list::const_iterator begin()
+ {
+ return name_val_pairs.cbegin();
+ }
+ value_list::const_iterator end()
+ {
+ return name_val_pairs.cend();
+ }
+ std::string toString();
+ static annotation *read(util::membuffer &input, constant_pool &pool);
};
typedef std::vector<annotation *> annotation_table;
@@ -121,158 +121,158 @@ typedef std::vector<annotation *> annotation_table;
class element_value_simple : public element_value
{
protected:
- /// index of the constant in the constant pool
- uint16_t index;
+ /// index of the constant in the constant pool
+ uint16_t index;
public:
- element_value_simple(element_value_type type, uint16_t index, constant_pool &pool)
- : element_value(type, pool), index(index) {
- // TODO: verify consistency
- };
- uint16_t getIndex()
- {
- return index;
- }
- virtual std::string toString()
- {
- return pool[index].toString();
- }
- ;
+ element_value_simple(element_value_type type, uint16_t index, constant_pool &pool)
+ : element_value(type, pool), index(index) {
+ // TODO: verify consistency
+ };
+ uint16_t getIndex()
+ {
+ return index;
+ }
+ virtual std::string toString()
+ {
+ return pool[index].toString();
+ }
+ ;
};
/// The enum_const_value item is used if the tag item is 'e'.
class element_value_enum : public element_value
{
protected:
- /**
- * The value of the type_name_index item must be a valid index into the constant_pool table.
- * The constant_pool entry at that index must be a CONSTANT_Utf8_info (§4.4.7) structure
- * representing a valid field descriptor (§4.3.2) that denotes the internal form of the
- * binary
- * name (§4.2.1) of the type of the enum constant represented by this element_value
- * structure.
- */
- uint16_t typeIndex;
- /**
- * The value of the const_name_index item must be a valid index into the constant_pool
- * table.
- * The constant_pool entry at that index must be a CONSTANT_Utf8_info (§4.4.7) structure
- * representing the simple name of the enum constant represented by this element_value
- * structure.
- */
- uint16_t valueIndex;
+ /**
+ * The value of the type_name_index item must be a valid index into the constant_pool table.
+ * The constant_pool entry at that index must be a CONSTANT_Utf8_info (§4.4.7) structure
+ * representing a valid field descriptor (§4.3.2) that denotes the internal form of the
+ * binary
+ * name (§4.2.1) of the type of the enum constant represented by this element_value
+ * structure.
+ */
+ uint16_t typeIndex;
+ /**
+ * The value of the const_name_index item must be a valid index into the constant_pool
+ * table.
+ * The constant_pool entry at that index must be a CONSTANT_Utf8_info (§4.4.7) structure
+ * representing the simple name of the enum constant represented by this element_value
+ * structure.
+ */
+ uint16_t valueIndex;
public:
- element_value_enum(element_value_type type, uint16_t typeIndex, uint16_t valueIndex,
- constant_pool &pool)
- : element_value(type, pool), typeIndex(typeIndex), valueIndex(valueIndex)
- {
- // TODO: verify consistency
- }
- uint16_t getValueIndex()
- {
- return valueIndex;
- }
- uint16_t getTypeIndex()
- {
- return typeIndex;
- }
- virtual std::string toString()
- {
- return "enum value";
- }
- ;
+ element_value_enum(element_value_type type, uint16_t typeIndex, uint16_t valueIndex,
+ constant_pool &pool)
+ : element_value(type, pool), typeIndex(typeIndex), valueIndex(valueIndex)
+ {
+ // TODO: verify consistency
+ }
+ uint16_t getValueIndex()
+ {
+ return valueIndex;
+ }
+ uint16_t getTypeIndex()
+ {
+ return typeIndex;
+ }
+ virtual std::string toString()
+ {
+ return "enum value";
+ }
+ ;
};
class element_value_class : public element_value
{
protected:
- /**
- * The class_info_index item must be a valid index into the constant_pool table.
- * The constant_pool entry at that index must be a CONSTANT_Utf8_info (§4.4.7) structure
- * representing the return descriptor (§4.3.3) of the type that is reified by the class
- * represented by this element_value structure.
- *
- * For example, 'V' for Void.class, 'Ljava/lang/Object;' for Object, etc.
- *
- * Or in plain english, you can store type information in annotations. Yay.
- */
- uint16_t classIndex;
+ /**
+ * The class_info_index item must be a valid index into the constant_pool table.
+ * The constant_pool entry at that index must be a CONSTANT_Utf8_info (§4.4.7) structure
+ * representing the return descriptor (§4.3.3) of the type that is reified by the class
+ * represented by this element_value structure.
+ *
+ * For example, 'V' for Void.class, 'Ljava/lang/Object;' for Object, etc.
+ *
+ * Or in plain english, you can store type information in annotations. Yay.
+ */
+ uint16_t classIndex;
public:
- element_value_class(element_value_type type, uint16_t classIndex, constant_pool &pool)
- : element_value(type, pool), classIndex(classIndex)
- {
- // TODO: verify consistency
- }
- uint16_t getIndex()
- {
- return classIndex;
- }
- virtual std::string toString()
- {
- return "class";
- }
- ;
+ element_value_class(element_value_type type, uint16_t classIndex, constant_pool &pool)
+ : element_value(type, pool), classIndex(classIndex)
+ {
+ // TODO: verify consistency
+ }
+ uint16_t getIndex()
+ {
+ return classIndex;
+ }
+ virtual std::string toString()
+ {
+ return "class";
+ }
+ ;
};
/// nested annotations... yay
class element_value_annotation : public element_value
{
private:
- annotation *nestedAnnotation;
+ annotation *nestedAnnotation;
public:
- element_value_annotation(element_value_type type, annotation *nestedAnnotation,
- constant_pool &pool)
- : element_value(type, pool), nestedAnnotation(nestedAnnotation) {};
- ~element_value_annotation()
- {
- if (nestedAnnotation)
- {
- delete nestedAnnotation;
- nestedAnnotation = nullptr;
- }
- }
- virtual std::string toString()
- {
- return "nested annotation";
- }
- ;
+ element_value_annotation(element_value_type type, annotation *nestedAnnotation,
+ constant_pool &pool)
+ : element_value(type, pool), nestedAnnotation(nestedAnnotation) {};
+ ~element_value_annotation()
+ {
+ if (nestedAnnotation)
+ {
+ delete nestedAnnotation;
+ nestedAnnotation = nullptr;
+ }
+ }
+ virtual std::string toString()
+ {
+ return "nested annotation";
+ }
+ ;
};
/// and arrays!
class element_value_array : public element_value
{
public:
- typedef std::vector<element_value *> elem_vec;
+ typedef std::vector<element_value *> elem_vec;
protected:
- elem_vec values;
+ elem_vec values;
public:
- element_value_array(element_value_type type, std::vector<element_value *> &values,
- constant_pool &pool)
- : element_value(type, pool), values(values) {};
- ~element_value_array()
- {
- for (unsigned i = 0; i < values.size(); i++)
- {
- delete values[i];
- }
- }
- ;
- elem_vec::const_iterator begin()
- {
- return values.cbegin();
- }
- elem_vec::const_iterator end()
- {
- return values.cend();
- }
- virtual std::string toString()
- {
- return "array";
- }
- ;
+ element_value_array(element_value_type type, std::vector<element_value *> &values,
+ constant_pool &pool)
+ : element_value(type, pool), values(values) {};
+ ~element_value_array()
+ {
+ for (unsigned i = 0; i < values.size(); i++)
+ {
+ delete values[i];
+ }
+ }
+ ;
+ elem_vec::const_iterator begin()
+ {
+ return values.cbegin();
+ }
+ elem_vec::const_iterator end()
+ {
+ return values.cend();
+ }
+ virtual std::string toString()
+ {
+ return "array";
+ }
+ ;
};
} \ No newline at end of file
diff --git a/libraries/classparser/src/classfile.h b/libraries/classparser/src/classfile.h
index a5e7ee50..1616a828 100644
--- a/libraries/classparser/src/classfile.h
+++ b/libraries/classparser/src/classfile.h
@@ -11,146 +11,146 @@ namespace java
class classfile : public util::membuffer
{
public:
- classfile(char *data, std::size_t size) : membuffer(data, size)
- {
- valid = false;
- is_synthetic = false;
- read_be(magic);
- if (magic != 0xCAFEBABE)
- throw new classfile_exception();
- read_be(minor_version);
- read_be(major_version);
- constants.load(*this);
- read_be(access_flags);
- read_be(this_class);
- read_be(super_class);
+ classfile(char *data, std::size_t size) : membuffer(data, size)
+ {
+ valid = false;
+ is_synthetic = false;
+ read_be(magic);
+ if (magic != 0xCAFEBABE)
+ throw new classfile_exception();
+ read_be(minor_version);
+ read_be(major_version);
+ constants.load(*this);
+ read_be(access_flags);
+ read_be(this_class);
+ read_be(super_class);
- // Interfaces
- uint16_t iface_count = 0;
- read_be(iface_count);
- while (iface_count)
- {
- uint16_t iface;
- read_be(iface);
- interfaces.push_back(iface);
- iface_count--;
- }
+ // Interfaces
+ uint16_t iface_count = 0;
+ read_be(iface_count);
+ while (iface_count)
+ {
+ uint16_t iface;
+ read_be(iface);
+ interfaces.push_back(iface);
+ iface_count--;
+ }
- // Fields
- // read fields (and attributes from inside fields) (and possible inner classes. yay for
- // recursion!)
- // for now though, we will ignore all attributes
- /*
- * field_info
- * {
- * u2 access_flags;
- * u2 name_index;
- * u2 descriptor_index;
- * u2 attributes_count;
- * attribute_info attributes[attributes_count];
- * }
- */
- uint16_t field_count = 0;
- read_be(field_count);
- while (field_count)
- {
- // skip field stuff
- skip(6);
- // and skip field attributes
- uint16_t attr_count = 0;
- read_be(attr_count);
- while (attr_count)
- {
- skip(2);
- uint32_t attr_length = 0;
- read_be(attr_length);
- skip(attr_length);
- attr_count--;
- }
- field_count--;
- }
+ // Fields
+ // read fields (and attributes from inside fields) (and possible inner classes. yay for
+ // recursion!)
+ // for now though, we will ignore all attributes
+ /*
+ * field_info
+ * {
+ * u2 access_flags;
+ * u2 name_index;
+ * u2 descriptor_index;
+ * u2 attributes_count;
+ * attribute_info attributes[attributes_count];
+ * }
+ */
+ uint16_t field_count = 0;
+ read_be(field_count);
+ while (field_count)
+ {
+ // skip field stuff
+ skip(6);
+ // and skip field attributes
+ uint16_t attr_count = 0;
+ read_be(attr_count);
+ while (attr_count)
+ {
+ skip(2);
+ uint32_t attr_length = 0;
+ read_be(attr_length);
+ skip(attr_length);
+ attr_count--;
+ }
+ field_count--;
+ }
- // class methods
- /*
- * method_info
- * {
- * u2 access_flags;
- * u2 name_index;
- * u2 descriptor_index;
- * u2 attributes_count;
- * attribute_info attributes[attributes_count];
- * }
- */
- uint16_t method_count = 0;
- read_be(method_count);
- while (method_count)
- {
- skip(6);
- // and skip method attributes
- uint16_t attr_count = 0;
- read_be(attr_count);
- while (attr_count)
- {
- skip(2);
- uint32_t attr_length = 0;
- read_be(attr_length);
- skip(attr_length);
- attr_count--;
- }
- method_count--;
- }
+ // class methods
+ /*
+ * method_info
+ * {
+ * u2 access_flags;
+ * u2 name_index;
+ * u2 descriptor_index;
+ * u2 attributes_count;
+ * attribute_info attributes[attributes_count];
+ * }
+ */
+ uint16_t method_count = 0;
+ read_be(method_count);
+ while (method_count)
+ {
+ skip(6);
+ // and skip method attributes
+ uint16_t attr_count = 0;
+ read_be(attr_count);
+ while (attr_count)
+ {
+ skip(2);
+ uint32_t attr_length = 0;
+ read_be(attr_length);
+ skip(attr_length);
+ attr_count--;
+ }
+ method_count--;
+ }
- // class attributes
- // there are many kinds of attributes. this is just the generic wrapper structure.
- // type is decided by attribute name. extensions to the standard are *possible*
- // class annotations are one kind of a attribute (one per class)
- /*
- * attribute_info
- * {
- * u2 attribute_name_index;
- * u4 attribute_length;
- * u1 info[attribute_length];
- * }
- */
- uint16_t class_attr_count = 0;
- read_be(class_attr_count);
- while (class_attr_count)
- {
- uint16_t name_idx = 0;
- read_be(name_idx);
- uint32_t attr_length = 0;
- read_be(attr_length);
+ // class attributes
+ // there are many kinds of attributes. this is just the generic wrapper structure.
+ // type is decided by attribute name. extensions to the standard are *possible*
+ // class annotations are one kind of a attribute (one per class)
+ /*
+ * attribute_info
+ * {
+ * u2 attribute_name_index;
+ * u4 attribute_length;
+ * u1 info[attribute_length];
+ * }
+ */
+ uint16_t class_attr_count = 0;
+ read_be(class_attr_count);
+ while (class_attr_count)
+ {
+ uint16_t name_idx = 0;
+ read_be(name_idx);
+ uint32_t attr_length = 0;
+ read_be(attr_length);
- auto name = constants[name_idx];
- if (name.str_data == "RuntimeVisibleAnnotations")
- {
- uint16_t num_annotations = 0;
- read_be(num_annotations);
- while (num_annotations)
- {
- visible_class_annotations.push_back(annotation::read(*this, constants));
- num_annotations--;
- }
- }
- else
- skip(attr_length);
- class_attr_count--;
- }
- valid = true;
- }
- ;
- bool valid;
- bool is_synthetic;
- uint32_t magic;
- uint16_t minor_version;
- uint16_t major_version;
- constant_pool constants;
- uint16_t access_flags;
- uint16_t this_class;
- uint16_t super_class;
- // interfaces this class implements ? must be. investigate.
- std::vector<uint16_t> interfaces;
- // FIXME: doesn't free up memory on delete
- java::annotation_table visible_class_annotations;
+ auto name = constants[name_idx];
+ if (name.str_data == "RuntimeVisibleAnnotations")
+ {
+ uint16_t num_annotations = 0;
+ read_be(num_annotations);
+ while (num_annotations)
+ {
+ visible_class_annotations.push_back(annotation::read(*this, constants));
+ num_annotations--;
+ }
+ }
+ else
+ skip(attr_length);
+ class_attr_count--;
+ }
+ valid = true;
+ }
+ ;
+ bool valid;
+ bool is_synthetic;
+ uint32_t magic;
+ uint16_t minor_version;
+ uint16_t major_version;
+ constant_pool constants;
+ uint16_t access_flags;
+ uint16_t this_class;
+ uint16_t super_class;
+ // interfaces this class implements ? must be. investigate.
+ std::vector<uint16_t> interfaces;
+ // FIXME: doesn't free up memory on delete
+ java::annotation_table visible_class_annotations;
};
} \ No newline at end of file
diff --git a/libraries/classparser/src/classparser.cpp b/libraries/classparser/src/classparser.cpp
index 8837781f..e0b6728d 100644
--- a/libraries/classparser/src/classparser.cpp
+++ b/libraries/classparser/src/classparser.cpp
@@ -1,4 +1,4 @@
-/* Copyright 2013-2018 MultiMC Contributors
+/* Copyright 2013-2019 MultiMC Contributors
*
* Authors: Orochimarufan <orochimarufan.x3@gmail.com>
*
@@ -26,60 +26,58 @@ namespace classparser
QString GetMinecraftJarVersion(QString jarName)
{
- QString version;
+ QString version;
- // check if minecraft.jar exists
- QFile jar(jarName);
- if (!jar.exists())
- return version;
+ // check if minecraft.jar exists
+ QFile jar(jarName);
+ if (!jar.exists())
+ return version;
- // open minecraft.jar
- QuaZip zip(&jar);
- if (!zip.open(QuaZip::mdUnzip))
- return version;
+ // open minecraft.jar
+ QuaZip zip(&jar);
+ if (!zip.open(QuaZip::mdUnzip))
+ return version;
- // open Minecraft.class
- zip.setCurrentFile("net/minecraft/client/Minecraft.class", QuaZip::csSensitive);
- QuaZipFile Minecraft(&zip);
- if (!Minecraft.open(QuaZipFile::ReadOnly))
- return version;
+ // open Minecraft.class
+ zip.setCurrentFile("net/minecraft/client/Minecraft.class", QuaZip::csSensitive);
+ QuaZipFile Minecraft(&zip);
+ if (!Minecraft.open(QuaZipFile::ReadOnly))
+ return version;
- // read Minecraft.class
- qint64 size = Minecraft.size();
- char *classfile = new char[size];
- Minecraft.read(classfile, size);
+ // read Minecraft.class
+ qint64 size = Minecraft.size();
+ char *classfile = new char[size];
+ Minecraft.read(classfile, size);
- // parse Minecraft.class
- try
- {
- char *temp = classfile;
- java::classfile MinecraftClass(temp, size);
- java::constant_pool constants = MinecraftClass.constants;
- for (java::constant_pool::container_type::const_iterator iter = constants.begin();
- iter != constants.end(); iter++)
- {
- const java::constant &constant = *iter;
- if (constant.type != java::constant::j_string_data)
- continue;
- const std::string &str = constant.str_data;
- qDebug() << QString::fromStdString(str);
- if (str.compare(0, 20, "Minecraft Minecraft ") == 0)
- {
- version = str.substr(20).data();
- break;
- }
- }
- }
- catch (java::classfile_exception &)
- {
- }
+ // parse Minecraft.class
+ try
+ {
+ char *temp = classfile;
+ java::classfile MinecraftClass(temp, size);
+ java::constant_pool constants = MinecraftClass.constants;
+ for (java::constant_pool::container_type::const_iterator iter = constants.begin();
+ iter != constants.end(); iter++)
+ {
+ const java::constant &constant = *iter;
+ if (constant.type != java::constant_type_t::j_string_data)
+ continue;
+ const std::string &str = constant.str_data;
+ qDebug() << QString::fromStdString(str);
+ if (str.compare(0, 20, "Minecraft Minecraft ") == 0)
+ {
+ version = str.substr(20).data();
+ break;
+ }
+ }
+ }
+ catch (const java::classfile_exception &) { }
- // clean up
- delete[] classfile;
- Minecraft.close();
- zip.close();
- jar.close();
+ // clean up
+ delete[] classfile;
+ Minecraft.close();
+ zip.close();
+ jar.close();
- return version;
+ return version;
}
}
diff --git a/libraries/classparser/src/constants.h b/libraries/classparser/src/constants.h
index 9c74ab20..3b6c3b7a 100644
--- a/libraries/classparser/src/constants.h
+++ b/libraries/classparser/src/constants.h
@@ -4,152 +4,161 @@
namespace java
{
+enum class constant_type_t : uint8_t
+{
+ j_hole = 0, // HACK: this is a hole in the array, because java is crazy
+ j_string_data = 1,
+ j_int = 3,
+ j_float = 4,
+ j_long = 5,
+ j_double = 6,
+ j_class = 7,
+ j_string = 8,
+ j_fieldref = 9,
+ j_methodref = 10,
+ j_interface_methodref = 11,
+ j_nameandtype = 12
+ // FIXME: missing some constant types, see https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.4
+};
+
+struct ref_type_t
+{
+ /**
+ * Class reference:
+ * an index within the constant pool to a UTF-8 string containing
+ * the fully qualified class name (in internal format)
+ * Used for j_class, j_fieldref, j_methodref and j_interface_methodref
+ */
+ uint16_t class_idx;
+ // used for j_fieldref, j_methodref and j_interface_methodref
+ uint16_t name_and_type_idx;
+};
+
+struct name_and_type_t
+{
+ uint16_t name_index;
+ uint16_t descriptor_index;
+};
+
class constant
{
public:
- enum type_t : uint8_t
- {
- j_hole = 0, // HACK: this is a hole in the array, because java is crazy
- j_string_data = 1,
- j_int = 3,
- j_float = 4,
- j_long = 5,
- j_double = 6,
- j_class = 7,
- j_string = 8,
- j_fieldref = 9,
- j_methodref = 10,
- j_interface_methodref = 11,
- j_nameandtype = 12
- // FIXME: missing some constant types, see https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.4
- } type;
+ constant_type_t type = constant_type_t::j_hole;
- constant(util::membuffer &buf)
- {
- buf.read(type);
+ constant(util::membuffer &buf)
+ {
+ buf.read(type);
- // load data depending on type
- switch (type)
- {
- case j_float:
- case j_int:
- buf.read_be(int_data); // same as float data really
- break;
- case j_double:
- case j_long:
- buf.read_be(long_data); // same as double
- break;
- case j_class:
- buf.read_be(ref_type.class_idx);
- break;
- case j_fieldref:
- case j_methodref:
- case j_interface_methodref:
- buf.read_be(ref_type.class_idx);
- buf.read_be(ref_type.name_and_type_idx);
- break;
- case j_string:
- buf.read_be(index);
- break;
- case j_string_data:
- // HACK HACK: for now, we call these UTF-8 and do no further processing.
- // Later, we should do some decoding. It's really modified UTF-8
- // * U+0000 is represented as 0xC0,0x80 invalid character
- // * any single zero byte ends the string
- // * characters above U+10000 are encoded like in CESU-8
- buf.read_jstr(str_data);
- break;
- case j_nameandtype:
- buf.read_be(name_and_type.name_index);
- buf.read_be(name_and_type.descriptor_index);
- break;
- default:
- // invalid constant type!
- throw new classfile_exception();
- }
- }
+ // load data depending on type
+ switch (type)
+ {
+ case constant_type_t::j_float:
+ buf.read_be(data.int_data);
+ break;
+ case constant_type_t::j_int:
+ buf.read_be(data.int_data); // same as float data really
+ break;
+ case constant_type_t::j_double:
+ buf.read_be(data.long_data);
+ break;
+ case constant_type_t::j_long:
+ buf.read_be(data.long_data); // same as double
+ break;
+ case constant_type_t::j_class:
+ buf.read_be(data.ref_type.class_idx);
+ break;
+ case constant_type_t::j_fieldref:
+ case constant_type_t::j_methodref:
+ case constant_type_t::j_interface_methodref:
+ buf.read_be(data.ref_type.class_idx);
+ buf.read_be(data.ref_type.name_and_type_idx);
+ break;
+ case constant_type_t::j_string:
+ buf.read_be(data.index);
+ break;
+ case constant_type_t::j_string_data:
+ // HACK HACK: for now, we call these UTF-8 and do no further processing.
+ // Later, we should do some decoding. It's really modified UTF-8
+ // * U+0000 is represented as 0xC0,0x80 invalid character
+ // * any single zero byte ends the string
+ // * characters above U+10000 are encoded like in CESU-8
+ buf.read_jstr(str_data);
+ break;
+ case constant_type_t::j_nameandtype:
+ buf.read_be(data.name_and_type.name_index);
+ buf.read_be(data.name_and_type.descriptor_index);
+ break;
+ default:
+ // invalid constant type!
+ throw new classfile_exception();
+ }
+ }
+ constant(int)
+ {
+ }
- constant(int)
- {
- type = j_hole;
- }
+ std::string toString()
+ {
+ std::ostringstream ss;
+ switch (type)
+ {
+ case constant_type_t::j_hole:
+ ss << "Fake legacy entry";
+ break;
+ case constant_type_t::j_float:
+ ss << "Float: " << data.float_data;
+ break;
+ case constant_type_t::j_double:
+ ss << "Double: " << data.double_data;
+ break;
+ case constant_type_t::j_int:
+ ss << "Int: " << data.int_data;
+ break;
+ case constant_type_t::j_long:
+ ss << "Long: " << data.long_data;
+ break;
+ case constant_type_t::j_string_data:
+ ss << "StrData: " << str_data;
+ break;
+ case constant_type_t::j_string:
+ ss << "Str: " << data.index;
+ break;
+ case constant_type_t::j_fieldref:
+ ss << "FieldRef: " << data.ref_type.class_idx << " " << data.ref_type.name_and_type_idx;
+ break;
+ case constant_type_t::j_methodref:
+ ss << "MethodRef: " << data.ref_type.class_idx << " " << data.ref_type.name_and_type_idx;
+ break;
+ case constant_type_t::j_interface_methodref:
+ ss << "IfMethodRef: " << data.ref_type.class_idx << " " << data.ref_type.name_and_type_idx;
+ break;
+ case constant_type_t::j_class:
+ ss << "Class: " << data.ref_type.class_idx;
+ break;
+ case constant_type_t::j_nameandtype:
+ ss << "NameAndType: " << data.name_and_type.name_index << " "
+ << data.name_and_type.descriptor_index;
+ break;
+ default:
+ ss << "Invalid entry (" << int(type) << ")";
+ break;
+ }
+ return ss.str();
+ }
- std::string toString()
- {
- std::ostringstream ss;
- switch (type)
- {
- case j_hole:
- ss << "Fake legacy entry";
- break;
- case j_float:
- ss << "Float: " << float_data;
- break;
- case j_double:
- ss << "Double: " << double_data;
- break;
- case j_int:
- ss << "Int: " << int_data;
- break;
- case j_long:
- ss << "Long: " << long_data;
- break;
- case j_string_data:
- ss << "StrData: " << str_data;
- break;
- case j_string:
- ss << "Str: " << index;
- break;
- case j_fieldref:
- ss << "FieldRef: " << ref_type.class_idx << " " << ref_type.name_and_type_idx;
- break;
- case j_methodref:
- ss << "MethodRef: " << ref_type.class_idx << " " << ref_type.name_and_type_idx;
- break;
- case j_interface_methodref:
- ss << "IfMethodRef: " << ref_type.class_idx << " " << ref_type.name_and_type_idx;
- break;
- case j_class:
- ss << "Class: " << ref_type.class_idx;
- break;
- case j_nameandtype:
- ss << "NameAndType: " << name_and_type.name_index << " "
- << name_and_type.descriptor_index;
- break;
- default:
- ss << "Invalid entry (" << int(type) << ")";
- break;
- }
- return ss.str();
- }
+ std::string str_data; /** String data in 'modified utf-8'.*/
- std::string str_data; /** String data in 'modified utf-8'.*/
- // store everything here.
- union
- {
- int32_t int_data;
- int64_t long_data;
- float float_data;
- double double_data;
- uint16_t index;
- struct
- {
- /**
- * Class reference:
- * an index within the constant pool to a UTF-8 string containing
- * the fully qualified class name (in internal format)
- * Used for j_class, j_fieldref, j_methodref and j_interface_methodref
- */
- uint16_t class_idx;
- // used for j_fieldref, j_methodref and j_interface_methodref
- uint16_t name_and_type_idx;
- } ref_type;
- struct
- {
- uint16_t name_index;
- uint16_t descriptor_index;
- } name_and_type;
- };
+ // store everything here.
+ union
+ {
+ int32_t int_data;
+ int64_t long_data;
+ float float_data;
+ double double_data;
+ uint16_t index;
+ ref_type_t ref_type;
+ name_and_type_t name_and_type;
+ } data = {0};
};
/**
@@ -159,64 +168,64 @@ public:
class constant_pool
{
public:
- /**
- * Create a pool of constants
- */
- constant_pool()
- {
- }
- /**
- * Load a java constant pool
- */
- void load(util::membuffer &buf)
- {
- // FIXME: @SANITY this should check for the end of buffer.
- uint16_t length = 0;
- buf.read_be(length);
- length--;
- const constant *last_constant = nullptr;
- while (length)
- {
- const constant &cnst = constant(buf);
- constants.push_back(cnst);
- last_constant = &constants[constants.size() - 1];
- if (last_constant->type == constant::j_double ||
- last_constant->type == constant::j_long)
- {
- // push in a fake constant to preserve indexing
- constants.push_back(constant(0));
- length -= 2;
- }
- else
- {
- length--;
- }
- }
- }
- typedef std::vector<java::constant> container_type;
- /**
- * Access constants based on jar file index numbers (index of the first element is 1)
- */
- java::constant &operator[](std::size_t constant_index)
- {
- if (constant_index == 0 || constant_index > constants.size())
- {
- throw new classfile_exception();
- }
- return constants[constant_index - 1];
- }
- ;
- container_type::const_iterator begin() const
- {
- return constants.begin();
- }
- ;
- container_type::const_iterator end() const
- {
- return constants.end();
- }
+ /**
+ * Create a pool of constants
+ */
+ constant_pool()
+ {
+ }
+ /**
+ * Load a java constant pool
+ */
+ void load(util::membuffer &buf)
+ {
+ // FIXME: @SANITY this should check for the end of buffer.
+ uint16_t length = 0;
+ buf.read_be(length);
+ length--;
+ const constant *last_constant = nullptr;
+ while (length)
+ {
+ const constant &cnst = constant(buf);
+ constants.push_back(cnst);
+ last_constant = &constants[constants.size() - 1];
+ if (last_constant->type == constant_type_t::j_double ||
+ last_constant->type == constant_type_t::j_long)
+ {
+ // push in a fake constant to preserve indexing
+ constants.push_back(constant(0));
+ length -= 2;
+ }
+ else
+ {
+ length--;
+ }
+ }
+ }
+ typedef std::vector<java::constant> container_type;
+ /**
+ * Access constants based on jar file index numbers (index of the first element is 1)
+ */
+ java::constant &operator[](std::size_t constant_index)
+ {
+ if (constant_index == 0 || constant_index > constants.size())
+ {
+ throw new classfile_exception();
+ }
+ return constants[constant_index - 1];
+ }
+ ;
+ container_type::const_iterator begin() const
+ {
+ return constants.begin();
+ }
+ ;
+ container_type::const_iterator end() const
+ {
+ return constants.end();
+ }
private:
- container_type constants;
+ container_type constants;
};
}
diff --git a/libraries/classparser/src/javaendian.h b/libraries/classparser/src/javaendian.h
index d488b382..076bff5e 100644
--- a/libraries/classparser/src/javaendian.h
+++ b/libraries/classparser/src/javaendian.h
@@ -9,68 +9,68 @@ namespace util
#ifdef MULTIMC_BIG_ENDIAN
inline uint64_t bigswap(uint64_t x)
{
- return x;
+ return x;
}
;
inline uint32_t bigswap(uint32_t x)
{
- return x;
+ return x;
}
;
inline uint16_t bigswap(uint16_t x)
{
- return x;
+ return x;
}
;
inline int64_t bigswap(int64_t x)
{
- return x;
+ return x;
}
;
inline int32_t bigswap(int32_t x)
{
- return x;
+ return x;
}
;
inline int16_t bigswap(int16_t x)
{
- return x;
+ return x;
}
;
#else
inline uint64_t bigswap(uint64_t x)
{
- return (x >> 56) | ((x << 40) & 0x00FF000000000000) | ((x << 24) & 0x0000FF0000000000) |
- ((x << 8) & 0x000000FF00000000) | ((x >> 8) & 0x00000000FF000000) |
- ((x >> 24) & 0x0000000000FF0000) | ((x >> 40) & 0x000000000000FF00) | (x << 56);
+ return (x >> 56) | ((x << 40) & 0x00FF000000000000) | ((x << 24) & 0x0000FF0000000000) |
+ ((x << 8) & 0x000000FF00000000) | ((x >> 8) & 0x00000000FF000000) |
+ ((x >> 24) & 0x0000000000FF0000) | ((x >> 40) & 0x000000000000FF00) | (x << 56);
}
-;
+
inline uint32_t bigswap(uint32_t x)
{
- return (x >> 24) | ((x << 8) & 0x00FF0000) | ((x >> 8) & 0x0000FF00) | (x << 24);
+ return (x >> 24) | ((x << 8) & 0x00FF0000) | ((x >> 8) & 0x0000FF00) | (x << 24);
}
-;
+
inline uint16_t bigswap(uint16_t x)
{
- return (x >> 8) | (x << 8);
+ return (x >> 8) | (x << 8);
}
-;
+
inline int64_t bigswap(int64_t x)
{
- return (x >> 56) | ((x << 40) & 0x00FF000000000000) | ((x << 24) & 0x0000FF0000000000) |
- ((x << 8) & 0x000000FF00000000) | ((x >> 8) & 0x00000000FF000000) |
- ((x >> 24) & 0x0000000000FF0000) | ((x >> 40) & 0x000000000000FF00) | (x << 56);
+ return (x >> 56) | ((x << 40) & 0x00FF000000000000) | ((x << 24) & 0x0000FF0000000000) |
+ ((x << 8) & 0x000000FF00000000) | ((x >> 8) & 0x00000000FF000000) |
+ ((x >> 24) & 0x0000000000FF0000) | ((x >> 40) & 0x000000000000FF00) | (x << 56);
}
-;
+
inline int32_t bigswap(int32_t x)
{
- return (x >> 24) | ((x << 8) & 0x00FF0000) | ((x >> 8) & 0x0000FF00) | (x << 24);
+ return (x >> 24) | ((x << 8) & 0x00FF0000) | ((x >> 8) & 0x0000FF00) | (x << 24);
}
-;
+
inline int16_t bigswap(int16_t x)
{
- return (x >> 8) | (x << 8);
+ return (x >> 8) | (x << 8);
}
-;
+
#endif
}
diff --git a/libraries/classparser/src/membuffer.h b/libraries/classparser/src/membuffer.h
index ab83412a..f81c9705 100644
--- a/libraries/classparser/src/membuffer.h
+++ b/libraries/classparser/src/membuffer.h
@@ -10,54 +10,54 @@ namespace util
class membuffer
{
public:
- membuffer(char *buffer, std::size_t size)
- {
- current = start = buffer;
- end = start + size;
- }
- ~membuffer()
- {
- // maybe? possibly? left out to avoid confusion. for now.
- // delete start;
- }
- /**
- * Read some value. That's all ;)
- */
- template <class T> void read(T &val)
- {
- val = *(T *)current;
- current += sizeof(T);
- }
- /**
- * Read a big-endian number
- * valid for 2-byte, 4-byte and 8-byte variables
- */
- template <class T> void read_be(T &val)
- {
- val = util::bigswap(*(T *)current);
- current += sizeof(T);
- }
- /**
- * Read a string in the format:
- * 2B length (big endian, unsigned)
- * length bytes data
- */
- void read_jstr(std::string &str)
- {
- uint16_t length = 0;
- read_be(length);
- str.append(current, length);
- current += length;
- }
- /**
- * Skip N bytes
- */
- void skip(std::size_t N)
- {
- current += N;
- }
+ membuffer(char *buffer, std::size_t size)
+ {
+ current = start = buffer;
+ end = start + size;
+ }
+ ~membuffer()
+ {
+ // maybe? possibly? left out to avoid confusion. for now.
+ // delete start;
+ }
+ /**
+ * Read some value. That's all ;)
+ */
+ template <class T> void read(T &val)
+ {
+ val = *(T *)current;
+ current += sizeof(T);
+ }
+ /**
+ * Read a big-endian number
+ * valid for 2-byte, 4-byte and 8-byte variables
+ */
+ template <class T> void read_be(T &val)
+ {
+ val = util::bigswap(*(T *)current);
+ current += sizeof(T);
+ }
+ /**
+ * Read a string in the format:
+ * 2B length (big endian, unsigned)
+ * length bytes data
+ */
+ void read_jstr(std::string &str)
+ {
+ uint16_t length = 0;
+ read_be(length);
+ str.append(current, length);
+ current += length;
+ }
+ /**
+ * Skip N bytes
+ */
+ void skip(std::size_t N)
+ {
+ current += N;
+ }
private:
- char *start, *end, *current;
+ char *start, *end, *current;
};
}
diff --git a/libraries/hoedown/include/hoedown/autolink.h b/libraries/hoedown/include/hoedown/autolink.h
index 528885c9..953e7807 100644
--- a/libraries/hoedown/include/hoedown/autolink.h
+++ b/libraries/hoedown/include/hoedown/autolink.h
@@ -15,7 +15,7 @@ extern "C" {
*************/
typedef enum hoedown_autolink_flags {
- HOEDOWN_AUTOLINK_SHORT_DOMAINS = (1 << 0)
+ HOEDOWN_AUTOLINK_SHORT_DOMAINS = (1 << 0)
} hoedown_autolink_flags;
@@ -28,15 +28,15 @@ int hoedown_autolink_is_safe(const uint8_t *data, size_t size);
/* hoedown_autolink__www: search for the next www link in data */
size_t hoedown_autolink__www(size_t *rewind_p, hoedown_buffer *link,
- uint8_t *data, size_t offset, size_t size, hoedown_autolink_flags flags);
+ uint8_t *data, size_t offset, size_t size, hoedown_autolink_flags flags);
/* hoedown_autolink__email: search for the next email in data */
size_t hoedown_autolink__email(size_t *rewind_p, hoedown_buffer *link,
- uint8_t *data, size_t offset, size_t size, hoedown_autolink_flags flags);
+ uint8_t *data, size_t offset, size_t size, hoedown_autolink_flags flags);
/* hoedown_autolink__url: search for the next URL in data */
size_t hoedown_autolink__url(size_t *rewind_p, hoedown_buffer *link,
- uint8_t *data, size_t offset, size_t size, hoedown_autolink_flags flags);
+ uint8_t *data, size_t offset, size_t size, hoedown_autolink_flags flags);
#ifdef __cplusplus
diff --git a/libraries/hoedown/include/hoedown/buffer.h b/libraries/hoedown/include/hoedown/buffer.h
index d7703f8d..062d86ce 100644
--- a/libraries/hoedown/include/hoedown/buffer.h
+++ b/libraries/hoedown/include/hoedown/buffer.h
@@ -28,14 +28,14 @@ typedef void *(*hoedown_realloc_callback)(void *, size_t);
typedef void (*hoedown_free_callback)(void *);
struct hoedown_buffer {
- uint8_t *data; /* actual character data */
- size_t size; /* size of the string */
- size_t asize; /* allocated size (0 = volatile buffer) */
- size_t unit; /* reallocation unit size (0 = read-only buffer) */
-
- hoedown_realloc_callback data_realloc;
- hoedown_free_callback data_free;
- hoedown_free_callback buffer_free;
+ uint8_t *data; /* actual character data */
+ size_t size; /* size of the string */
+ size_t asize; /* allocated size (0 = volatile buffer) */
+ size_t unit; /* reallocation unit size (0 = read-only buffer) */
+
+ hoedown_realloc_callback data_realloc;
+ hoedown_free_callback data_free;
+ hoedown_free_callback buffer_free;
};
typedef struct hoedown_buffer hoedown_buffer;
@@ -52,11 +52,11 @@ void *hoedown_realloc(void *ptr, size_t size) __attribute__ ((malloc));
/* hoedown_buffer_init: initialize a buffer with custom allocators */
void hoedown_buffer_init(
- hoedown_buffer *buffer,
- size_t unit,
- hoedown_realloc_callback data_realloc,
- hoedown_free_callback data_free,
- hoedown_free_callback buffer_free
+ hoedown_buffer *buffer,
+ size_t unit,
+ hoedown_realloc_callback data_realloc,
+ hoedown_free_callback data_free,
+ hoedown_free_callback buffer_free
);
/* hoedown_buffer_uninit: uninitialize an existing buffer */
@@ -116,15 +116,15 @@ void hoedown_buffer_free(hoedown_buffer *buf);
/* HOEDOWN_BUFPUTSL: optimized hoedown_buffer_puts of a string literal */
#define HOEDOWN_BUFPUTSL(output, literal) \
- hoedown_buffer_put(output, (const uint8_t *)literal, sizeof(literal) - 1)
+ hoedown_buffer_put(output, (const uint8_t *)literal, sizeof(literal) - 1)
/* HOEDOWN_BUFSETSL: optimized hoedown_buffer_sets of a string literal */
#define HOEDOWN_BUFSETSL(output, literal) \
- hoedown_buffer_set(output, (const uint8_t *)literal, sizeof(literal) - 1)
+ hoedown_buffer_set(output, (const uint8_t *)literal, sizeof(literal) - 1)
/* HOEDOWN_BUFEQSL: optimized hoedown_buffer_eqs of a string literal */
#define HOEDOWN_BUFEQSL(output, literal) \
- hoedown_buffer_eq(output, (const uint8_t *)literal, sizeof(literal) - 1)
+ hoedown_buffer_eq(output, (const uint8_t *)literal, sizeof(literal) - 1)
#ifdef __cplusplus
diff --git a/libraries/hoedown/include/hoedown/document.h b/libraries/hoedown/include/hoedown/document.h
index a8178fec..210c565e 100644
--- a/libraries/hoedown/include/hoedown/document.h
+++ b/libraries/hoedown/include/hoedown/document.h
@@ -16,68 +16,68 @@ extern "C" {
*************/
typedef enum hoedown_extensions {
- /* block-level extensions */
- HOEDOWN_EXT_TABLES = (1 << 0),
- HOEDOWN_EXT_FENCED_CODE = (1 << 1),
- HOEDOWN_EXT_FOOTNOTES = (1 << 2),
-
- /* span-level extensions */
- HOEDOWN_EXT_AUTOLINK = (1 << 3),
- HOEDOWN_EXT_STRIKETHROUGH = (1 << 4),
- HOEDOWN_EXT_UNDERLINE = (1 << 5),
- HOEDOWN_EXT_HIGHLIGHT = (1 << 6),
- HOEDOWN_EXT_QUOTE = (1 << 7),
- HOEDOWN_EXT_SUPERSCRIPT = (1 << 8),
- HOEDOWN_EXT_MATH = (1 << 9),
-
- /* other flags */
- HOEDOWN_EXT_NO_INTRA_EMPHASIS = (1 << 11),
- HOEDOWN_EXT_SPACE_HEADERS = (1 << 12),
- HOEDOWN_EXT_MATH_EXPLICIT = (1 << 13),
-
- /* negative flags */
- HOEDOWN_EXT_DISABLE_INDENTED_CODE = (1 << 14)
+ /* block-level extensions */
+ HOEDOWN_EXT_TABLES = (1 << 0),
+ HOEDOWN_EXT_FENCED_CODE = (1 << 1),
+ HOEDOWN_EXT_FOOTNOTES = (1 << 2),
+
+ /* span-level extensions */
+ HOEDOWN_EXT_AUTOLINK = (1 << 3),
+ HOEDOWN_EXT_STRIKETHROUGH = (1 << 4),
+ HOEDOWN_EXT_UNDERLINE = (1 << 5),
+ HOEDOWN_EXT_HIGHLIGHT = (1 << 6),
+ HOEDOWN_EXT_QUOTE = (1 << 7),
+ HOEDOWN_EXT_SUPERSCRIPT = (1 << 8),
+ HOEDOWN_EXT_MATH = (1 << 9),
+
+ /* other flags */
+ HOEDOWN_EXT_NO_INTRA_EMPHASIS = (1 << 11),
+ HOEDOWN_EXT_SPACE_HEADERS = (1 << 12),
+ HOEDOWN_EXT_MATH_EXPLICIT = (1 << 13),
+
+ /* negative flags */
+ HOEDOWN_EXT_DISABLE_INDENTED_CODE = (1 << 14)
} hoedown_extensions;
#define HOEDOWN_EXT_BLOCK (\
- HOEDOWN_EXT_TABLES |\
- HOEDOWN_EXT_FENCED_CODE |\
- HOEDOWN_EXT_FOOTNOTES )
+ HOEDOWN_EXT_TABLES |\
+ HOEDOWN_EXT_FENCED_CODE |\
+ HOEDOWN_EXT_FOOTNOTES )
#define HOEDOWN_EXT_SPAN (\
- HOEDOWN_EXT_AUTOLINK |\
- HOEDOWN_EXT_STRIKETHROUGH |\
- HOEDOWN_EXT_UNDERLINE |\
- HOEDOWN_EXT_HIGHLIGHT |\
- HOEDOWN_EXT_QUOTE |\
- HOEDOWN_EXT_SUPERSCRIPT |\
- HOEDOWN_EXT_MATH )
+ HOEDOWN_EXT_AUTOLINK |\
+ HOEDOWN_EXT_STRIKETHROUGH |\
+ HOEDOWN_EXT_UNDERLINE |\
+ HOEDOWN_EXT_HIGHLIGHT |\
+ HOEDOWN_EXT_QUOTE |\
+ HOEDOWN_EXT_SUPERSCRIPT |\
+ HOEDOWN_EXT_MATH )
#define HOEDOWN_EXT_FLAGS (\
- HOEDOWN_EXT_NO_INTRA_EMPHASIS |\
- HOEDOWN_EXT_SPACE_HEADERS |\
- HOEDOWN_EXT_MATH_EXPLICIT )
+ HOEDOWN_EXT_NO_INTRA_EMPHASIS |\
+ HOEDOWN_EXT_SPACE_HEADERS |\
+ HOEDOWN_EXT_MATH_EXPLICIT )
#define HOEDOWN_EXT_NEGATIVE (\
- HOEDOWN_EXT_DISABLE_INDENTED_CODE )
+ HOEDOWN_EXT_DISABLE_INDENTED_CODE )
typedef enum hoedown_list_flags {
- HOEDOWN_LIST_ORDERED = (1 << 0),
- HOEDOWN_LI_BLOCK = (1 << 1) /* <li> containing block data */
+ HOEDOWN_LIST_ORDERED = (1 << 0),
+ HOEDOWN_LI_BLOCK = (1 << 1) /* <li> containing block data */
} hoedown_list_flags;
typedef enum hoedown_table_flags {
- HOEDOWN_TABLE_ALIGN_LEFT = 1,
- HOEDOWN_TABLE_ALIGN_RIGHT = 2,
- HOEDOWN_TABLE_ALIGN_CENTER = 3,
- HOEDOWN_TABLE_ALIGNMASK = 3,
- HOEDOWN_TABLE_HEADER = 4
+ HOEDOWN_TABLE_ALIGN_LEFT = 1,
+ HOEDOWN_TABLE_ALIGN_RIGHT = 2,
+ HOEDOWN_TABLE_ALIGN_CENTER = 3,
+ HOEDOWN_TABLE_ALIGNMASK = 3,
+ HOEDOWN_TABLE_HEADER = 4
} hoedown_table_flags;
typedef enum hoedown_autolink_type {
- HOEDOWN_AUTOLINK_NONE, /* used internally when it is not an autolink*/
- HOEDOWN_AUTOLINK_NORMAL, /* normal http/http/ftp/mailto/etc link */
- HOEDOWN_AUTOLINK_EMAIL /* e-mail link without explit mailto: */
+ HOEDOWN_AUTOLINK_NONE, /* used internally when it is not an autolink*/
+ HOEDOWN_AUTOLINK_NORMAL, /* normal http/http/ftp/mailto/etc link */
+ HOEDOWN_AUTOLINK_EMAIL /* e-mail link without explit mailto: */
} hoedown_autolink_type;
@@ -89,57 +89,57 @@ struct hoedown_document;
typedef struct hoedown_document hoedown_document;
struct hoedown_renderer_data {
- void *opaque;
+ void *opaque;
};
typedef struct hoedown_renderer_data hoedown_renderer_data;
/* hoedown_renderer - functions for rendering parsed data */
struct hoedown_renderer {
- /* state object */
- void *opaque;
-
- /* block level callbacks - NULL skips the block */
- void (*blockcode)(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_buffer *lang, const hoedown_renderer_data *data);
- void (*blockquote)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
- void (*header)(hoedown_buffer *ob, const hoedown_buffer *content, int level, const hoedown_renderer_data *data);
- void (*hrule)(hoedown_buffer *ob, const hoedown_renderer_data *data);
- void (*list)(hoedown_buffer *ob, const hoedown_buffer *content, hoedown_list_flags flags, const hoedown_renderer_data *data);
- void (*listitem)(hoedown_buffer *ob, const hoedown_buffer *content, hoedown_list_flags flags, const hoedown_renderer_data *data);
- void (*paragraph)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
- void (*table)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
- void (*table_header)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
- void (*table_body)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
- void (*table_row)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
- void (*table_cell)(hoedown_buffer *ob, const hoedown_buffer *content, hoedown_table_flags flags, const hoedown_renderer_data *data);
- void (*footnotes)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
- void (*footnote_def)(hoedown_buffer *ob, const hoedown_buffer *content, unsigned int num, const hoedown_renderer_data *data);
- void (*blockhtml)(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data);
-
- /* span level callbacks - NULL or return 0 prints the span verbatim */
- int (*autolink)(hoedown_buffer *ob, const hoedown_buffer *link, hoedown_autolink_type type, const hoedown_renderer_data *data);
- int (*codespan)(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data);
- int (*double_emphasis)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
- int (*emphasis)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
- int (*underline)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
- int (*highlight)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
- int (*quote)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
- int (*image)(hoedown_buffer *ob, const hoedown_buffer *link, const hoedown_buffer *title, const hoedown_buffer *alt, const hoedown_renderer_data *data);
- int (*linebreak)(hoedown_buffer *ob, const hoedown_renderer_data *data);
- int (*link)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_buffer *link, const hoedown_buffer *title, const hoedown_renderer_data *data);
- int (*triple_emphasis)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
- int (*strikethrough)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
- int (*superscript)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
- int (*footnote_ref)(hoedown_buffer *ob, unsigned int num, const hoedown_renderer_data *data);
- int (*math)(hoedown_buffer *ob, const hoedown_buffer *text, int displaymode, const hoedown_renderer_data *data);
- int (*raw_html)(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data);
-
- /* low level callbacks - NULL copies input directly into the output */
- void (*entity)(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data);
- void (*normal_text)(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data);
-
- /* miscellaneous callbacks */
- void (*doc_header)(hoedown_buffer *ob, int inline_render, const hoedown_renderer_data *data);
- void (*doc_footer)(hoedown_buffer *ob, int inline_render, const hoedown_renderer_data *data);
+ /* state object */
+ void *opaque;
+
+ /* block level callbacks - NULL skips the block */
+ void (*blockcode)(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_buffer *lang, const hoedown_renderer_data *data);
+ void (*blockquote)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
+ void (*header)(hoedown_buffer *ob, const hoedown_buffer *content, int level, const hoedown_renderer_data *data);
+ void (*hrule)(hoedown_buffer *ob, const hoedown_renderer_data *data);
+ void (*list)(hoedown_buffer *ob, const hoedown_buffer *content, hoedown_list_flags flags, const hoedown_renderer_data *data);
+ void (*listitem)(hoedown_buffer *ob, const hoedown_buffer *content, hoedown_list_flags flags, const hoedown_renderer_data *data);
+ void (*paragraph)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
+ void (*table)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
+ void (*table_header)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
+ void (*table_body)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
+ void (*table_row)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
+ void (*table_cell)(hoedown_buffer *ob, const hoedown_buffer *content, hoedown_table_flags flags, const hoedown_renderer_data *data);
+ void (*footnotes)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
+ void (*footnote_def)(hoedown_buffer *ob, const hoedown_buffer *content, unsigned int num, const hoedown_renderer_data *data);
+ void (*blockhtml)(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data);
+
+ /* span level callbacks - NULL or return 0 prints the span verbatim */
+ int (*autolink)(hoedown_buffer *ob, const hoedown_buffer *link, hoedown_autolink_type type, const hoedown_renderer_data *data);
+ int (*codespan)(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data);
+ int (*double_emphasis)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
+ int (*emphasis)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
+ int (*underline)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
+ int (*highlight)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
+ int (*quote)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
+ int (*image)(hoedown_buffer *ob, const hoedown_buffer *link, const hoedown_buffer *title, const hoedown_buffer *alt, const hoedown_renderer_data *data);
+ int (*linebreak)(hoedown_buffer *ob, const hoedown_renderer_data *data);
+ int (*link)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_buffer *link, const hoedown_buffer *title, const hoedown_renderer_data *data);
+ int (*triple_emphasis)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
+ int (*strikethrough)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
+ int (*superscript)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
+ int (*footnote_ref)(hoedown_buffer *ob, unsigned int num, const hoedown_renderer_data *data);
+ int (*math)(hoedown_buffer *ob, const hoedown_buffer *text, int displaymode, const hoedown_renderer_data *data);
+ int (*raw_html)(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data);
+
+ /* low level callbacks - NULL copies input directly into the output */
+ void (*entity)(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data);
+ void (*normal_text)(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data);
+
+ /* miscellaneous callbacks */
+ void (*doc_header)(hoedown_buffer *ob, int inline_render, const hoedown_renderer_data *data);
+ void (*doc_footer)(hoedown_buffer *ob, int inline_render, const hoedown_renderer_data *data);
};
typedef struct hoedown_renderer hoedown_renderer;
@@ -150,9 +150,9 @@ typedef struct hoedown_renderer hoedown_renderer;
/* hoedown_document_new: allocate a new document processor instance */
hoedown_document *hoedown_document_new(
- const hoedown_renderer *renderer,
- hoedown_extensions extensions,
- size_t max_nesting
+ const hoedown_renderer *renderer,
+ hoedown_extensions extensions,
+ size_t max_nesting
) __attribute__ ((malloc));
/* hoedown_document_render: render regular Markdown using the document processor */
diff --git a/libraries/hoedown/include/hoedown/html.h b/libraries/hoedown/include/hoedown/html.h
index e46e7fd6..7c68809a 100644
--- a/libraries/hoedown/include/hoedown/html.h
+++ b/libraries/hoedown/include/hoedown/html.h
@@ -16,16 +16,16 @@ extern "C" {
*************/
typedef enum hoedown_html_flags {
- HOEDOWN_HTML_SKIP_HTML = (1 << 0),
- HOEDOWN_HTML_ESCAPE = (1 << 1),
- HOEDOWN_HTML_HARD_WRAP = (1 << 2),
- HOEDOWN_HTML_USE_XHTML = (1 << 3)
+ HOEDOWN_HTML_SKIP_HTML = (1 << 0),
+ HOEDOWN_HTML_ESCAPE = (1 << 1),
+ HOEDOWN_HTML_HARD_WRAP = (1 << 2),
+ HOEDOWN_HTML_USE_XHTML = (1 << 3)
} hoedown_html_flags;
typedef enum hoedown_html_tag {
- HOEDOWN_HTML_TAG_NONE = 0,
- HOEDOWN_HTML_TAG_OPEN,
- HOEDOWN_HTML_TAG_CLOSE
+ HOEDOWN_HTML_TAG_NONE = 0,
+ HOEDOWN_HTML_TAG_OPEN,
+ HOEDOWN_HTML_TAG_CLOSE
} hoedown_html_tag;
@@ -34,19 +34,19 @@ typedef enum hoedown_html_tag {
*********/
struct hoedown_html_renderer_state {
- void *opaque;
+ void *opaque;
- struct {
- int header_count;
- int current_level;
- int level_offset;
- int nesting_level;
- } toc_data;
+ struct {
+ int header_count;
+ int current_level;
+ int level_offset;
+ int nesting_level;
+ } toc_data;
- hoedown_html_flags flags;
+ hoedown_html_flags flags;
- /* extra callbacks */
- void (*link_attributes)(hoedown_buffer *ob, const hoedown_buffer *url, const hoedown_renderer_data *data);
+ /* extra callbacks */
+ void (*link_attributes)(hoedown_buffer *ob, const hoedown_buffer *url, const hoedown_renderer_data *data);
};
typedef struct hoedown_html_renderer_state hoedown_html_renderer_state;
@@ -64,13 +64,13 @@ hoedown_html_tag hoedown_html_is_tag(const uint8_t *data, size_t size, const cha
/* hoedown_html_renderer_new: allocates a regular HTML renderer */
hoedown_renderer *hoedown_html_renderer_new(
- hoedown_html_flags render_flags,
- int nesting_level
+ hoedown_html_flags render_flags,
+ int nesting_level
) __attribute__ ((malloc));
/* hoedown_html_toc_renderer_new: like hoedown_html_renderer_new, but the returned renderer produces the Table of Contents */
hoedown_renderer *hoedown_html_toc_renderer_new(
- int nesting_level
+ int nesting_level
) __attribute__ ((malloc));
/* hoedown_html_renderer_free: deallocate an HTML renderer */
diff --git a/libraries/hoedown/include/hoedown/stack.h b/libraries/hoedown/include/hoedown/stack.h
index bf9b439b..d1855f4f 100644
--- a/libraries/hoedown/include/hoedown/stack.h
+++ b/libraries/hoedown/include/hoedown/stack.h
@@ -15,9 +15,9 @@ extern "C" {
*********/
struct hoedown_stack {
- void **item;
- size_t size;
- size_t asize;
+ void **item;
+ size_t size;
+ size_t asize;
};
typedef struct hoedown_stack hoedown_stack;
diff --git a/libraries/hoedown/src/autolink.c b/libraries/hoedown/src/autolink.c
index 9bc7fad5..3063b1a0 100644
--- a/libraries/hoedown/src/autolink.c
+++ b/libraries/hoedown/src/autolink.c
@@ -8,274 +8,274 @@
#ifndef _MSC_VER
#include <strings.h>
#else
-#define strncasecmp _strnicmp
+#define strncasecmp _strnicmp
#endif
int
hoedown_autolink_is_safe(const uint8_t *data, size_t size)
{
- static const size_t valid_uris_count = 6;
- static const char *valid_uris[] = {
- "http://", "https://", "/", "#", "ftp://", "mailto:"
- };
- static const size_t valid_uris_size[] = { 7, 8, 1, 1, 6, 7 };
- size_t i;
-
- for (i = 0; i < valid_uris_count; ++i) {
- size_t len = valid_uris_size[i];
-
- if (size > len &&
- strncasecmp((char *)data, valid_uris[i], len) == 0 &&
- isalnum(data[len]))
- return 1;
- }
-
- return 0;
+ static const size_t valid_uris_count = 6;
+ static const char *valid_uris[] = {
+ "http://", "https://", "/", "#", "ftp://", "mailto:"
+ };
+ static const size_t valid_uris_size[] = { 7, 8, 1, 1, 6, 7 };
+ size_t i;
+
+ for (i = 0; i < valid_uris_count; ++i) {
+ size_t len = valid_uris_size[i];
+
+ if (size > len &&
+ strncasecmp((char *)data, valid_uris[i], len) == 0 &&
+ isalnum(data[len]))
+ return 1;
+ }
+
+ return 0;
}
static size_t
autolink_delim(uint8_t *data, size_t link_end, size_t max_rewind, size_t size)
{
- uint8_t cclose, copen = 0;
- size_t i;
-
- for (i = 0; i < link_end; ++i)
- if (data[i] == '<') {
- link_end = i;
- break;
- }
-
- while (link_end > 0) {
- if (strchr("?!.,:", data[link_end - 1]) != NULL)
- link_end--;
-
- else if (data[link_end - 1] == ';') {
- size_t new_end = link_end - 2;
-
- while (new_end > 0 && isalpha(data[new_end]))
- new_end--;
-
- if (new_end < link_end - 2 && data[new_end] == '&')
- link_end = new_end;
- else
- link_end--;
- }
- else break;
- }
-
- if (link_end == 0)
- return 0;
-
- cclose = data[link_end - 1];
-
- switch (cclose) {
- case '"': copen = '"'; break;
- case '\'': copen = '\''; break;
- case ')': copen = '('; break;
- case ']': copen = '['; break;
- case '}': copen = '{'; break;
- }
-
- if (copen != 0) {
- size_t closing = 0;
- size_t opening = 0;
- size_t i = 0;
-
- /* Try to close the final punctuation sign in this same line;
- * if we managed to close it outside of the URL, that means that it's
- * not part of the URL. If it closes inside the URL, that means it
- * is part of the URL.
- *
- * Examples:
- *
- * foo http://www.pokemon.com/Pikachu_(Electric) bar
- * => http://www.pokemon.com/Pikachu_(Electric)
- *
- * foo (http://www.pokemon.com/Pikachu_(Electric)) bar
- * => http://www.pokemon.com/Pikachu_(Electric)
- *
- * foo http://www.pokemon.com/Pikachu_(Electric)) bar
- * => http://www.pokemon.com/Pikachu_(Electric))
- *
- * (foo http://www.pokemon.com/Pikachu_(Electric)) bar
- * => foo http://www.pokemon.com/Pikachu_(Electric)
- */
-
- while (i < link_end) {
- if (data[i] == copen)
- opening++;
- else if (data[i] == cclose)
- closing++;
-
- i++;
- }
-
- if (closing != opening)
- link_end--;
- }
-
- return link_end;
+ uint8_t cclose, copen = 0;
+ size_t i;
+
+ for (i = 0; i < link_end; ++i)
+ if (data[i] == '<') {
+ link_end = i;
+ break;
+ }
+
+ while (link_end > 0) {
+ if (strchr("?!.,:", data[link_end - 1]) != NULL)
+ link_end--;
+
+ else if (data[link_end - 1] == ';') {
+ size_t new_end = link_end - 2;
+
+ while (new_end > 0 && isalpha(data[new_end]))
+ new_end--;
+
+ if (new_end < link_end - 2 && data[new_end] == '&')
+ link_end = new_end;
+ else
+ link_end--;
+ }
+ else break;
+ }
+
+ if (link_end == 0)
+ return 0;
+
+ cclose = data[link_end - 1];
+
+ switch (cclose) {
+ case '"': copen = '"'; break;
+ case '\'': copen = '\''; break;
+ case ')': copen = '('; break;
+ case ']': copen = '['; break;
+ case '}': copen = '{'; break;
+ }
+
+ if (copen != 0) {
+ size_t closing = 0;
+ size_t opening = 0;
+ size_t i = 0;
+
+ /* Try to close the final punctuation sign in this same line;
+ * if we managed to close it outside of the URL, that means that it's
+ * not part of the URL. If it closes inside the URL, that means it
+ * is part of the URL.
+ *
+ * Examples:
+ *
+ * foo http://www.pokemon.com/Pikachu_(Electric) bar
+ * => http://www.pokemon.com/Pikachu_(Electric)
+ *
+ * foo (http://www.pokemon.com/Pikachu_(Electric)) bar
+ * => http://www.pokemon.com/Pikachu_(Electric)
+ *
+ * foo http://www.pokemon.com/Pikachu_(Electric)) bar
+ * => http://www.pokemon.com/Pikachu_(Electric))
+ *
+ * (foo http://www.pokemon.com/Pikachu_(Electric)) bar
+ * => foo http://www.pokemon.com/Pikachu_(Electric)
+ */
+
+ while (i < link_end) {
+ if (data[i] == copen)
+ opening++;
+ else if (data[i] == cclose)
+ closing++;
+
+ i++;
+ }
+
+ if (closing != opening)
+ link_end--;
+ }
+
+ return link_end;
}
static size_t
check_domain(uint8_t *data, size_t size, int allow_short)
{
- size_t i, np = 0;
-
- if (!isalnum(data[0]))
- return 0;
-
- for (i = 1; i < size - 1; ++i) {
- if (strchr(".:", data[i]) != NULL) np++;
- else if (!isalnum(data[i]) && data[i] != '-') break;
- }
-
- if (allow_short) {
- /* We don't need a valid domain in the strict sense (with
- * least one dot; so just make sure it's composed of valid
- * domain characters and return the length of the the valid
- * sequence. */
- return i;
- } else {
- /* a valid domain needs to have at least a dot.
- * that's as far as we get */
- return np ? i : 0;
- }
+ size_t i, np = 0;
+
+ if (!isalnum(data[0]))
+ return 0;
+
+ for (i = 1; i < size - 1; ++i) {
+ if (strchr(".:", data[i]) != NULL) np++;
+ else if (!isalnum(data[i]) && data[i] != '-') break;
+ }
+
+ if (allow_short) {
+ /* We don't need a valid domain in the strict sense (with
+ * least one dot; so just make sure it's composed of valid
+ * domain characters and return the length of the the valid
+ * sequence. */
+ return i;
+ } else {
+ /* a valid domain needs to have at least a dot.
+ * that's as far as we get */
+ return np ? i : 0;
+ }
}
size_t
hoedown_autolink__www(
- size_t *rewind_p,
- hoedown_buffer *link,
- uint8_t *data,
- size_t max_rewind,
- size_t size,
- unsigned int flags)
+ size_t *rewind_p,
+ hoedown_buffer *link,
+ uint8_t *data,
+ size_t max_rewind,
+ size_t size,
+ unsigned int flags)
{
- size_t link_end;
+ size_t link_end;
- if (max_rewind > 0 && !ispunct(data[-1]) && !isspace(data[-1]))
- return 0;
+ if (max_rewind > 0 && !ispunct(data[-1]) && !isspace(data[-1]))
+ return 0;
- if (size < 4 || memcmp(data, "www.", strlen("www.")) != 0)
- return 0;
+ if (size < 4 || memcmp(data, "www.", strlen("www.")) != 0)
+ return 0;
- link_end = check_domain(data, size, 0);
+ link_end = check_domain(data, size, 0);
- if (link_end == 0)
- return 0;
+ if (link_end == 0)
+ return 0;
- while (link_end < size && !isspace(data[link_end]))
- link_end++;
+ while (link_end < size && !isspace(data[link_end]))
+ link_end++;
- link_end = autolink_delim(data, link_end, max_rewind, size);
+ link_end = autolink_delim(data, link_end, max_rewind, size);
- if (link_end == 0)
- return 0;
+ if (link_end == 0)
+ return 0;
- hoedown_buffer_put(link, data, link_end);
- *rewind_p = 0;
+ hoedown_buffer_put(link, data, link_end);
+ *rewind_p = 0;
- return (int)link_end;
+ return (int)link_end;
}
size_t
hoedown_autolink__email(
- size_t *rewind_p,
- hoedown_buffer *link,
- uint8_t *data,
- size_t max_rewind,
- size_t size,
- unsigned int flags)
+ size_t *rewind_p,
+ hoedown_buffer *link,
+ uint8_t *data,
+ size_t max_rewind,
+ size_t size,
+ unsigned int flags)
{
- size_t link_end, rewind;
- int nb = 0, np = 0;
+ size_t link_end, rewind;
+ int nb = 0, np = 0;
- for (rewind = 0; rewind < max_rewind; ++rewind) {
- uint8_t c = data[-1 - rewind];
+ for (rewind = 0; rewind < max_rewind; ++rewind) {
+ uint8_t c = data[-1 - rewind];
- if (isalnum(c))
- continue;
+ if (isalnum(c))
+ continue;
- if (strchr(".+-_", c) != NULL)
- continue;
+ if (strchr(".+-_", c) != NULL)
+ continue;
- break;
- }
+ break;
+ }
- if (rewind == 0)
- return 0;
+ if (rewind == 0)
+ return 0;
- for (link_end = 0; link_end < size; ++link_end) {
- uint8_t c = data[link_end];
+ for (link_end = 0; link_end < size; ++link_end) {
+ uint8_t c = data[link_end];
- if (isalnum(c))
- continue;
+ if (isalnum(c))
+ continue;
- if (c == '@')
- nb++;
- else if (c == '.' && link_end < size - 1)
- np++;
- else if (c != '-' && c != '_')
- break;
- }
+ if (c == '@')
+ nb++;
+ else if (c == '.' && link_end < size - 1)
+ np++;
+ else if (c != '-' && c != '_')
+ break;
+ }
- if (link_end < 2 || nb != 1 || np == 0 ||
- !isalpha(data[link_end - 1]))
- return 0;
+ if (link_end < 2 || nb != 1 || np == 0 ||
+ !isalpha(data[link_end - 1]))
+ return 0;
- link_end = autolink_delim(data, link_end, max_rewind, size);
+ link_end = autolink_delim(data, link_end, max_rewind, size);
- if (link_end == 0)
- return 0;
+ if (link_end == 0)
+ return 0;
- hoedown_buffer_put(link, data - rewind, link_end + rewind);
- *rewind_p = rewind;
+ hoedown_buffer_put(link, data - rewind, link_end + rewind);
+ *rewind_p = rewind;
- return link_end;
+ return link_end;
}
size_t
hoedown_autolink__url(
- size_t *rewind_p,
- hoedown_buffer *link,
- uint8_t *data,
- size_t max_rewind,
- size_t size,
- unsigned int flags)
+ size_t *rewind_p,
+ hoedown_buffer *link,
+ uint8_t *data,
+ size_t max_rewind,
+ size_t size,
+ unsigned int flags)
{
- size_t link_end, rewind = 0, domain_len;
+ size_t link_end, rewind = 0, domain_len;
- if (size < 4 || data[1] != '/' || data[2] != '/')
- return 0;
+ if (size < 4 || data[1] != '/' || data[2] != '/')
+ return 0;
- while (rewind < max_rewind && isalpha(data[-1 - rewind]))
- rewind++;
+ while (rewind < max_rewind && isalpha(data[-1 - rewind]))
+ rewind++;
- if (!hoedown_autolink_is_safe(data - rewind, size + rewind))
- return 0;
+ if (!hoedown_autolink_is_safe(data - rewind, size + rewind))
+ return 0;
- link_end = strlen("://");
+ link_end = strlen("://");
- domain_len = check_domain(
- data + link_end,
- size - link_end,
- flags & HOEDOWN_AUTOLINK_SHORT_DOMAINS);
+ domain_len = check_domain(
+ data + link_end,
+ size - link_end,
+ flags & HOEDOWN_AUTOLINK_SHORT_DOMAINS);
- if (domain_len == 0)
- return 0;
+ if (domain_len == 0)
+ return 0;
- link_end += domain_len;
- while (link_end < size && !isspace(data[link_end]))
- link_end++;
+ link_end += domain_len;
+ while (link_end < size && !isspace(data[link_end]))
+ link_end++;
- link_end = autolink_delim(data, link_end, max_rewind, size);
+ link_end = autolink_delim(data, link_end, max_rewind, size);
- if (link_end == 0)
- return 0;
+ if (link_end == 0)
+ return 0;
- hoedown_buffer_put(link, data - rewind, link_end + rewind);
- *rewind_p = rewind;
+ hoedown_buffer_put(link, data - rewind, link_end + rewind);
+ *rewind_p = rewind;
- return link_end;
+ return link_end;
}
diff --git a/libraries/hoedown/src/buffer.c b/libraries/hoedown/src/buffer.c
index 1c7ba55a..024a8bcc 100644
--- a/libraries/hoedown/src/buffer.c
+++ b/libraries/hoedown/src/buffer.c
@@ -8,301 +8,301 @@
void *
hoedown_malloc(size_t size)
{
- void *ret = malloc(size);
+ void *ret = malloc(size);
- if (!ret) {
- fprintf(stderr, "Allocation failed.\n");
- abort();
- }
+ if (!ret) {
+ fprintf(stderr, "Allocation failed.\n");
+ abort();
+ }
- return ret;
+ return ret;
}
void *
hoedown_calloc(size_t nmemb, size_t size)
{
- void *ret = calloc(nmemb, size);
+ void *ret = calloc(nmemb, size);
- if (!ret) {
- fprintf(stderr, "Allocation failed.\n");
- abort();
- }
+ if (!ret) {
+ fprintf(stderr, "Allocation failed.\n");
+ abort();
+ }
- return ret;
+ return ret;
}
void *
hoedown_realloc(void *ptr, size_t size)
{
- void *ret = realloc(ptr, size);
+ void *ret = realloc(ptr, size);
- if (!ret) {
- fprintf(stderr, "Allocation failed.\n");
- abort();
- }
+ if (!ret) {
+ fprintf(stderr, "Allocation failed.\n");
+ abort();
+ }
- return ret;
+ return ret;
}
void
hoedown_buffer_init(
- hoedown_buffer *buf,
- size_t unit,
- hoedown_realloc_callback data_realloc,
- hoedown_free_callback data_free,
- hoedown_free_callback buffer_free)
+ hoedown_buffer *buf,
+ size_t unit,
+ hoedown_realloc_callback data_realloc,
+ hoedown_free_callback data_free,
+ hoedown_free_callback buffer_free)
{
- assert(buf);
-
- buf->data = NULL;
- buf->size = buf->asize = 0;
- buf->unit = unit;
- buf->data_realloc = data_realloc;
- buf->data_free = data_free;
- buf->buffer_free = buffer_free;
+ assert(buf);
+
+ buf->data = NULL;
+ buf->size = buf->asize = 0;
+ buf->unit = unit;
+ buf->data_realloc = data_realloc;
+ buf->data_free = data_free;
+ buf->buffer_free = buffer_free;
}
void
hoedown_buffer_uninit(hoedown_buffer *buf)
{
- assert(buf && buf->unit);
- buf->data_free(buf->data);
+ assert(buf && buf->unit);
+ buf->data_free(buf->data);
}
hoedown_buffer *
hoedown_buffer_new(size_t unit)
{
- hoedown_buffer *ret = hoedown_malloc(sizeof (hoedown_buffer));
- hoedown_buffer_init(ret, unit, hoedown_realloc, free, free);
- return ret;
+ hoedown_buffer *ret = hoedown_malloc(sizeof (hoedown_buffer));
+ hoedown_buffer_init(ret, unit, hoedown_realloc, free, free);
+ return ret;
}
void
hoedown_buffer_free(hoedown_buffer *buf)
{
- if (!buf) return;
- assert(buf && buf->unit);
+ if (!buf) return;
+ assert(buf && buf->unit);
- buf->data_free(buf->data);
+ buf->data_free(buf->data);
- if (buf->buffer_free)
- buf->buffer_free(buf);
+ if (buf->buffer_free)
+ buf->buffer_free(buf);
}
void
hoedown_buffer_reset(hoedown_buffer *buf)
{
- assert(buf && buf->unit);
+ assert(buf && buf->unit);
- buf->data_free(buf->data);
- buf->data = NULL;
- buf->size = buf->asize = 0;
+ buf->data_free(buf->data);
+ buf->data = NULL;
+ buf->size = buf->asize = 0;
}
void
hoedown_buffer_grow(hoedown_buffer *buf, size_t neosz)
{
- size_t neoasz;
- assert(buf && buf->unit);
+ size_t neoasz;
+ assert(buf && buf->unit);
- if (buf->asize >= neosz)
- return;
+ if (buf->asize >= neosz)
+ return;
- neoasz = buf->asize + buf->unit;
- while (neoasz < neosz)
- neoasz += buf->unit;
+ neoasz = buf->asize + buf->unit;
+ while (neoasz < neosz)
+ neoasz += buf->unit;
- buf->data = (uint8_t *) buf->data_realloc(buf->data, neoasz);
- buf->asize = neoasz;
+ buf->data = (uint8_t *) buf->data_realloc(buf->data, neoasz);
+ buf->asize = neoasz;
}
void
hoedown_buffer_put(hoedown_buffer *buf, const uint8_t *data, size_t size)
{
- assert(buf && buf->unit);
+ assert(buf && buf->unit);
- if (buf->size + size > buf->asize)
- hoedown_buffer_grow(buf, buf->size + size);
+ if (buf->size + size > buf->asize)
+ hoedown_buffer_grow(buf, buf->size + size);
- memcpy(buf->data + buf->size, data, size);
- buf->size += size;
+ memcpy(buf->data + buf->size, data, size);
+ buf->size += size;
}
void
hoedown_buffer_puts(hoedown_buffer *buf, const char *str)
{
- hoedown_buffer_put(buf, (const uint8_t *)str, strlen(str));
+ hoedown_buffer_put(buf, (const uint8_t *)str, strlen(str));
}
void
hoedown_buffer_putc(hoedown_buffer *buf, uint8_t c)
{
- assert(buf && buf->unit);
+ assert(buf && buf->unit);
- if (buf->size >= buf->asize)
- hoedown_buffer_grow(buf, buf->size + 1);
+ if (buf->size >= buf->asize)
+ hoedown_buffer_grow(buf, buf->size + 1);
- buf->data[buf->size] = c;
- buf->size += 1;
+ buf->data[buf->size] = c;
+ buf->size += 1;
}
int
hoedown_buffer_putf(hoedown_buffer *buf, FILE *file)
{
- assert(buf && buf->unit);
+ assert(buf && buf->unit);
- while (!(feof(file) || ferror(file))) {
- hoedown_buffer_grow(buf, buf->size + buf->unit);
- buf->size += fread(buf->data + buf->size, 1, buf->unit, file);
- }
+ while (!(feof(file) || ferror(file))) {
+ hoedown_buffer_grow(buf, buf->size + buf->unit);
+ buf->size += fread(buf->data + buf->size, 1, buf->unit, file);
+ }
- return ferror(file);
+ return ferror(file);
}
void
hoedown_buffer_set(hoedown_buffer *buf, const uint8_t *data, size_t size)
{
- assert(buf && buf->unit);
+ assert(buf && buf->unit);
- if (size > buf->asize)
- hoedown_buffer_grow(buf, size);
+ if (size > buf->asize)
+ hoedown_buffer_grow(buf, size);
- memcpy(buf->data, data, size);
- buf->size = size;
+ memcpy(buf->data, data, size);
+ buf->size = size;
}
void
hoedown_buffer_sets(hoedown_buffer *buf, const char *str)
{
- hoedown_buffer_set(buf, (const uint8_t *)str, strlen(str));
+ hoedown_buffer_set(buf, (const uint8_t *)str, strlen(str));
}
int
hoedown_buffer_eq(const hoedown_buffer *buf, const uint8_t *data, size_t size)
{
- if (buf->size != size) return 0;
- return memcmp(buf->data, data, size) == 0;
+ if (buf->size != size) return 0;
+ return memcmp(buf->data, data, size) == 0;
}
int
hoedown_buffer_eqs(const hoedown_buffer *buf, const char *str)
{
- return hoedown_buffer_eq(buf, (const uint8_t *)str, strlen(str));
+ return hoedown_buffer_eq(buf, (const uint8_t *)str, strlen(str));
}
int
hoedown_buffer_prefix(const hoedown_buffer *buf, const char *prefix)
{
- size_t i;
+ size_t i;
- for (i = 0; i < buf->size; ++i) {
- if (prefix[i] == 0)
- return 0;
+ for (i = 0; i < buf->size; ++i) {
+ if (prefix[i] == 0)
+ return 0;
- if (buf->data[i] != prefix[i])
- return buf->data[i] - prefix[i];
- }
+ if (buf->data[i] != prefix[i])
+ return buf->data[i] - prefix[i];
+ }
- return 0;
+ return 0;
}
void
hoedown_buffer_slurp(hoedown_buffer *buf, size_t size)
{
- assert(buf && buf->unit);
+ assert(buf && buf->unit);
- if (size >= buf->size) {
- buf->size = 0;
- return;
- }
+ if (size >= buf->size) {
+ buf->size = 0;
+ return;
+ }
- buf->size -= size;
- memmove(buf->data, buf->data + size, buf->size);
+ buf->size -= size;
+ memmove(buf->data, buf->data + size, buf->size);
}
const char *
hoedown_buffer_cstr(hoedown_buffer *buf)
{
- assert(buf && buf->unit);
+ assert(buf && buf->unit);
- if (buf->size < buf->asize && buf->data[buf->size] == 0)
- return (char *)buf->data;
+ if (buf->size < buf->asize && buf->data[buf->size] == 0)
+ return (char *)buf->data;
- hoedown_buffer_grow(buf, buf->size + 1);
- buf->data[buf->size] = 0;
+ hoedown_buffer_grow(buf, buf->size + 1);
+ buf->data[buf->size] = 0;
- return (char *)buf->data;
+ return (char *)buf->data;
}
void
hoedown_buffer_printf(hoedown_buffer *buf, const char *fmt, ...)
{
- va_list ap;
- int n;
+ va_list ap;
+ int n;
- assert(buf && buf->unit);
+ assert(buf && buf->unit);
- if (buf->size >= buf->asize)
- hoedown_buffer_grow(buf, buf->size + 1);
+ if (buf->size >= buf->asize)
+ hoedown_buffer_grow(buf, buf->size + 1);
- va_start(ap, fmt);
- n = vsnprintf((char *)buf->data + buf->size, buf->asize - buf->size, fmt, ap);
- va_end(ap);
+ va_start(ap, fmt);
+ n = vsnprintf((char *)buf->data + buf->size, buf->asize - buf->size, fmt, ap);
+ va_end(ap);
- if (n < 0) {
+ if (n < 0) {
#ifndef _MSC_VER
- return;
+ return;
#else
- va_start(ap, fmt);
- n = _vscprintf(fmt, ap);
- va_end(ap);
+ va_start(ap, fmt);
+ n = _vscprintf(fmt, ap);
+ va_end(ap);
#endif
- }
+ }
- if ((size_t)n >= buf->asize - buf->size) {
- hoedown_buffer_grow(buf, buf->size + n + 1);
+ if ((size_t)n >= buf->asize - buf->size) {
+ hoedown_buffer_grow(buf, buf->size + n + 1);
- va_start(ap, fmt);
- n = vsnprintf((char *)buf->data + buf->size, buf->asize - buf->size, fmt, ap);
- va_end(ap);
- }
+ va_start(ap, fmt);
+ n = vsnprintf((char *)buf->data + buf->size, buf->asize - buf->size, fmt, ap);
+ va_end(ap);
+ }
- if (n < 0)
- return;
+ if (n < 0)
+ return;
- buf->size += n;
+ buf->size += n;
}
void hoedown_buffer_put_utf8(hoedown_buffer *buf, unsigned int c) {
- unsigned char unichar[4];
-
- assert(buf && buf->unit);
-
- if (c < 0x80) {
- hoedown_buffer_putc(buf, c);
- }
- else if (c < 0x800) {
- unichar[0] = 192 + (c / 64);
- unichar[1] = 128 + (c % 64);
- hoedown_buffer_put(buf, unichar, 2);
- }
- else if (c - 0xd800u < 0x800) {
- HOEDOWN_BUFPUTSL(buf, "\xef\xbf\xbd");
- }
- else if (c < 0x10000) {
- unichar[0] = 224 + (c / 4096);
- unichar[1] = 128 + (c / 64) % 64;
- unichar[2] = 128 + (c % 64);
- hoedown_buffer_put(buf, unichar, 3);
- }
- else if (c < 0x110000) {
- unichar[0] = 240 + (c / 262144);
- unichar[1] = 128 + (c / 4096) % 64;
- unichar[2] = 128 + (c / 64) % 64;
- unichar[3] = 128 + (c % 64);
- hoedown_buffer_put(buf, unichar, 4);
- }
- else {
- HOEDOWN_BUFPUTSL(buf, "\xef\xbf\xbd");
- }
+ unsigned char unichar[4];
+
+ assert(buf && buf->unit);
+
+ if (c < 0x80) {
+ hoedown_buffer_putc(buf, c);
+ }
+ else if (c < 0x800) {
+ unichar[0] = 192 + (c / 64);
+ unichar[1] = 128 + (c % 64);
+ hoedown_buffer_put(buf, unichar, 2);
+ }
+ else if (c - 0xd800u < 0x800) {
+ HOEDOWN_BUFPUTSL(buf, "\xef\xbf\xbd");
+ }
+ else if (c < 0x10000) {
+ unichar[0] = 224 + (c / 4096);
+ unichar[1] = 128 + (c / 64) % 64;
+ unichar[2] = 128 + (c % 64);
+ hoedown_buffer_put(buf, unichar, 3);
+ }
+ else if (c < 0x110000) {
+ unichar[0] = 240 + (c / 262144);
+ unichar[1] = 128 + (c / 4096) % 64;
+ unichar[2] = 128 + (c / 64) % 64;
+ unichar[3] = 128 + (c % 64);
+ hoedown_buffer_put(buf, unichar, 4);
+ }
+ else {
+ HOEDOWN_BUFPUTSL(buf, "\xef\xbf\xbd");
+ }
}
diff --git a/libraries/hoedown/src/document.c b/libraries/hoedown/src/document.c
index 8ba82e47..e9e2ab11 100644
--- a/libraries/hoedown/src/document.c
+++ b/libraries/hoedown/src/document.c
@@ -10,7 +10,7 @@
#ifndef _MSC_VER
#include <strings.h>
#else
-#define strncasecmp _strnicmp
+#define strncasecmp _strnicmp
#endif
#define REF_TABLE_SIZE 8
@@ -18,7 +18,7 @@
#define BUFFER_BLOCK 0
#define BUFFER_SPAN 1
-#define HOEDOWN_LI_END 8 /* internal list flag */
+#define HOEDOWN_LI_END 8 /* internal list flag */
const char *hoedown_find_block_tag(const char *str, unsigned int len);
@@ -28,35 +28,35 @@ const char *hoedown_find_block_tag(const char *str, unsigned int len);
/* link_ref: reference to a link */
struct link_ref {
- unsigned int id;
+ unsigned int id;
- hoedown_buffer *link;
- hoedown_buffer *title;
+ hoedown_buffer *link;
+ hoedown_buffer *title;
- struct link_ref *next;
+ struct link_ref *next;
};
/* footnote_ref: reference to a footnote */
struct footnote_ref {
- unsigned int id;
+ unsigned int id;
- int is_used;
- unsigned int num;
+ int is_used;
+ unsigned int num;
- hoedown_buffer *contents;
+ hoedown_buffer *contents;
};
/* footnote_item: an item in a footnote_list */
struct footnote_item {
- struct footnote_ref *ref;
- struct footnote_item *next;
+ struct footnote_ref *ref;
+ struct footnote_item *next;
};
/* footnote_list: linked list of footnote_item */
struct footnote_list {
- unsigned int count;
- struct footnote_item *head;
- struct footnote_item *tail;
+ unsigned int count;
+ struct footnote_item *head;
+ struct footnote_item *tail;
};
/* char_trigger: function pointer to render active chars */
@@ -81,51 +81,51 @@ static size_t char_superscript(hoedown_buffer *ob, hoedown_document *doc, uint8_
static size_t char_math(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size);
enum markdown_char_t {
- MD_CHAR_NONE = 0,
- MD_CHAR_EMPHASIS,
- MD_CHAR_CODESPAN,
- MD_CHAR_LINEBREAK,
- MD_CHAR_LINK,
- MD_CHAR_LANGLE,
- MD_CHAR_ESCAPE,
- MD_CHAR_ENTITY,
- MD_CHAR_AUTOLINK_URL,
- MD_CHAR_AUTOLINK_EMAIL,
- MD_CHAR_AUTOLINK_WWW,
- MD_CHAR_SUPERSCRIPT,
- MD_CHAR_QUOTE,
- MD_CHAR_MATH
+ MD_CHAR_NONE = 0,
+ MD_CHAR_EMPHASIS,
+ MD_CHAR_CODESPAN,
+ MD_CHAR_LINEBREAK,
+ MD_CHAR_LINK,
+ MD_CHAR_LANGLE,
+ MD_CHAR_ESCAPE,
+ MD_CHAR_ENTITY,
+ MD_CHAR_AUTOLINK_URL,
+ MD_CHAR_AUTOLINK_EMAIL,
+ MD_CHAR_AUTOLINK_WWW,
+ MD_CHAR_SUPERSCRIPT,
+ MD_CHAR_QUOTE,
+ MD_CHAR_MATH
};
static char_trigger markdown_char_ptrs[] = {
- NULL,
- &char_emphasis,
- &char_codespan,
- &char_linebreak,
- &char_link,
- &char_langle_tag,
- &char_escape,
- &char_entity,
- &char_autolink_url,
- &char_autolink_email,
- &char_autolink_www,
- &char_superscript,
- &char_quote,
- &char_math
+ NULL,
+ &char_emphasis,
+ &char_codespan,
+ &char_linebreak,
+ &char_link,
+ &char_langle_tag,
+ &char_escape,
+ &char_entity,
+ &char_autolink_url,
+ &char_autolink_email,
+ &char_autolink_www,
+ &char_superscript,
+ &char_quote,
+ &char_math
};
struct hoedown_document {
- hoedown_renderer md;
- hoedown_renderer_data data;
-
- struct link_ref *refs[REF_TABLE_SIZE];
- struct footnote_list footnotes_found;
- struct footnote_list footnotes_used;
- uint8_t active_char[256];
- hoedown_stack work_bufs[2];
- hoedown_extensions ext_flags;
- size_t max_nesting;
- int in_link_body;
+ hoedown_renderer md;
+ hoedown_renderer_data data;
+
+ struct link_ref *refs[REF_TABLE_SIZE];
+ struct footnote_list footnotes_found;
+ struct footnote_list footnotes_used;
+ uint8_t active_char[256];
+ hoedown_stack work_bufs[2];
+ hoedown_extensions ext_flags;
+ size_t max_nesting;
+ int in_link_body;
};
/***************************
@@ -135,177 +135,177 @@ struct hoedown_document {
static hoedown_buffer *
newbuf(hoedown_document *doc, int type)
{
- static const size_t buf_size[2] = {256, 64};
- hoedown_buffer *work = NULL;
- hoedown_stack *pool = &doc->work_bufs[type];
+ static const size_t buf_size[2] = {256, 64};
+ hoedown_buffer *work = NULL;
+ hoedown_stack *pool = &doc->work_bufs[type];
- if (pool->size < pool->asize &&
- pool->item[pool->size] != NULL) {
- work = pool->item[pool->size++];
- work->size = 0;
- } else {
- work = hoedown_buffer_new(buf_size[type]);
- hoedown_stack_push(pool, work);
- }
+ if (pool->size < pool->asize &&
+ pool->item[pool->size] != NULL) {
+ work = pool->item[pool->size++];
+ work->size = 0;
+ } else {
+ work = hoedown_buffer_new(buf_size[type]);
+ hoedown_stack_push(pool, work);
+ }
- return work;
+ return work;
}
static void
popbuf(hoedown_document *doc, int type)
{
- doc->work_bufs[type].size--;
+ doc->work_bufs[type].size--;
}
static void
unscape_text(hoedown_buffer *ob, hoedown_buffer *src)
{
- size_t i = 0, org;
- while (i < src->size) {
- org = i;
- while (i < src->size && src->data[i] != '\\')
- i++;
+ size_t i = 0, org;
+ while (i < src->size) {
+ org = i;
+ while (i < src->size && src->data[i] != '\\')
+ i++;
- if (i > org)
- hoedown_buffer_put(ob, src->data + org, i - org);
+ if (i > org)
+ hoedown_buffer_put(ob, src->data + org, i - org);
- if (i + 1 >= src->size)
- break;
+ if (i + 1 >= src->size)
+ break;
- hoedown_buffer_putc(ob, src->data[i + 1]);
- i += 2;
- }
+ hoedown_buffer_putc(ob, src->data[i + 1]);
+ i += 2;
+ }
}
static unsigned int
hash_link_ref(const uint8_t *link_ref, size_t length)
{
- size_t i;
- unsigned int hash = 0;
+ size_t i;
+ unsigned int hash = 0;
- for (i = 0; i < length; ++i)
- hash = tolower(link_ref[i]) + (hash << 6) + (hash << 16) - hash;
+ for (i = 0; i < length; ++i)
+ hash = tolower(link_ref[i]) + (hash << 6) + (hash << 16) - hash;
- return hash;
+ return hash;
}
static struct link_ref *
add_link_ref(
- struct link_ref **references,
- const uint8_t *name, size_t name_size)
+ struct link_ref **references,
+ const uint8_t *name, size_t name_size)
{
- struct link_ref *ref = hoedown_calloc(1, sizeof(struct link_ref));
+ struct link_ref *ref = hoedown_calloc(1, sizeof(struct link_ref));
- ref->id = hash_link_ref(name, name_size);
- ref->next = references[ref->id % REF_TABLE_SIZE];
+ ref->id = hash_link_ref(name, name_size);
+ ref->next = references[ref->id % REF_TABLE_SIZE];
- references[ref->id % REF_TABLE_SIZE] = ref;
- return ref;
+ references[ref->id % REF_TABLE_SIZE] = ref;
+ return ref;
}
static struct link_ref *
find_link_ref(struct link_ref **references, uint8_t *name, size_t length)
{
- unsigned int hash = hash_link_ref(name, length);
- struct link_ref *ref = NULL;
+ unsigned int hash = hash_link_ref(name, length);
+ struct link_ref *ref = NULL;
- ref = references[hash % REF_TABLE_SIZE];
+ ref = references[hash % REF_TABLE_SIZE];
- while (ref != NULL) {
- if (ref->id == hash)
- return ref;
+ while (ref != NULL) {
+ if (ref->id == hash)
+ return ref;
- ref = ref->next;
- }
+ ref = ref->next;
+ }
- return NULL;
+ return NULL;
}
static void
free_link_refs(struct link_ref **references)
{
- size_t i;
+ size_t i;
- for (i = 0; i < REF_TABLE_SIZE; ++i) {
- struct link_ref *r = references[i];
- struct link_ref *next;
+ for (i = 0; i < REF_TABLE_SIZE; ++i) {
+ struct link_ref *r = references[i];
+ struct link_ref *next;
- while (r) {
- next = r->next;
- hoedown_buffer_free(r->link);
- hoedown_buffer_free(r->title);
- free(r);
- r = next;
- }
- }
+ while (r) {
+ next = r->next;
+ hoedown_buffer_free(r->link);
+ hoedown_buffer_free(r->title);
+ free(r);
+ r = next;
+ }
+ }
}
static struct footnote_ref *
create_footnote_ref(struct footnote_list *list, const uint8_t *name, size_t name_size)
{
- struct footnote_ref *ref = hoedown_calloc(1, sizeof(struct footnote_ref));
+ struct footnote_ref *ref = hoedown_calloc(1, sizeof(struct footnote_ref));
- ref->id = hash_link_ref(name, name_size);
+ ref->id = hash_link_ref(name, name_size);
- return ref;
+ return ref;
}
static int
add_footnote_ref(struct footnote_list *list, struct footnote_ref *ref)
{
- struct footnote_item *item = hoedown_calloc(1, sizeof(struct footnote_item));
- if (!item)
- return 0;
- item->ref = ref;
+ struct footnote_item *item = hoedown_calloc(1, sizeof(struct footnote_item));
+ if (!item)
+ return 0;
+ item->ref = ref;
- if (list->head == NULL) {
- list->head = list->tail = item;
- } else {
- list->tail->next = item;
- list->tail = item;
- }
- list->count++;
+ if (list->head == NULL) {
+ list->head = list->tail = item;
+ } else {
+ list->tail->next = item;
+ list->tail = item;
+ }
+ list->count++;
- return 1;
+ return 1;
}
static struct footnote_ref *
find_footnote_ref(struct footnote_list *list, uint8_t *name, size_t length)
{
- unsigned int hash = hash_link_ref(name, length);
- struct footnote_item *item = NULL;
+ unsigned int hash = hash_link_ref(name, length);
+ struct footnote_item *item = NULL;
- item = list->head;
+ item = list->head;
- while (item != NULL) {
- if (item->ref->id == hash)
- return item->ref;
- item = item->next;
- }
+ while (item != NULL) {
+ if (item->ref->id == hash)
+ return item->ref;
+ item = item->next;
+ }
- return NULL;
+ return NULL;
}
static void
free_footnote_ref(struct footnote_ref *ref)
{
- hoedown_buffer_free(ref->contents);
- free(ref);
+ hoedown_buffer_free(ref->contents);
+ free(ref);
}
static void
free_footnote_list(struct footnote_list *list, int free_refs)
{
- struct footnote_item *item = list->head;
- struct footnote_item *next;
+ struct footnote_item *item = list->head;
+ struct footnote_item *next;
- while (item) {
- next = item->next;
- if (free_refs)
- free_footnote_ref(item->ref);
- free(item);
- item = next;
- }
+ while (item) {
+ next = item->next;
+ if (free_refs)
+ free_footnote_ref(item->ref);
+ free(item);
+ item = next;
+ }
}
@@ -323,16 +323,16 @@ free_footnote_list(struct footnote_list *list, int free_refs)
static int
_isspace(int c)
{
- return c == ' ' || c == '\n';
+ return c == ' ' || c == '\n';
}
/* is_empty_all: verify that all the data is spacing */
static int
is_empty_all(const uint8_t *data, size_t size)
{
- size_t i = 0;
- while (i < size && _isspace(data[i])) i++;
- return i == size;
+ size_t i = 0;
+ while (i < size && _isspace(data[i])) i++;
+ return i == size;
}
/*
@@ -342,19 +342,19 @@ is_empty_all(const uint8_t *data, size_t size)
static void
replace_spacing(hoedown_buffer *ob, const uint8_t *data, size_t size)
{
- size_t i = 0, mark;
- hoedown_buffer_grow(ob, size);
- while (1) {
- mark = i;
- while (i < size && data[i] != '\n') i++;
- hoedown_buffer_put(ob, data + mark, i - mark);
+ size_t i = 0, mark;
+ hoedown_buffer_grow(ob, size);
+ while (1) {
+ mark = i;
+ while (i < size && data[i] != '\n') i++;
+ hoedown_buffer_put(ob, data + mark, i - mark);
- if (i >= size) break;
+ if (i >= size) break;
- if (!(i > 0 && data[i-1] == ' '))
- hoedown_buffer_putc(ob, ' ');
- i++;
- }
+ if (!(i > 0 && data[i-1] == ' '))
+ hoedown_buffer_putc(ob, ' ');
+ i++;
+ }
}
/****************************
@@ -366,237 +366,237 @@ replace_spacing(hoedown_buffer *ob, const uint8_t *data, size_t size)
static size_t
is_mail_autolink(uint8_t *data, size_t size)
{
- size_t i = 0, nb = 0;
+ size_t i = 0, nb = 0;
- /* address is assumed to be: [-@._a-zA-Z0-9]+ with exactly one '@' */
- for (i = 0; i < size; ++i) {
- if (isalnum(data[i]))
- continue;
+ /* address is assumed to be: [-@._a-zA-Z0-9]+ with exactly one '@' */
+ for (i = 0; i < size; ++i) {
+ if (isalnum(data[i]))
+ continue;
- switch (data[i]) {
- case '@':
- nb++;
+ switch (data[i]) {
+ case '@':
+ nb++;
- case '-':
- case '.':
- case '_':
- break;
+ case '-':
+ case '.':
+ case '_':
+ break;
- case '>':
- return (nb == 1) ? i + 1 : 0;
+ case '>':
+ return (nb == 1) ? i + 1 : 0;
- default:
- return 0;
- }
- }
+ default:
+ return 0;
+ }
+ }
- return 0;
+ return 0;
}
/* tag_length • returns the length of the given tag, or 0 is it's not valid */
static size_t
tag_length(uint8_t *data, size_t size, hoedown_autolink_type *autolink)
{
- size_t i, j;
+ size_t i, j;
- /* a valid tag can't be shorter than 3 chars */
- if (size < 3) return 0;
+ /* a valid tag can't be shorter than 3 chars */
+ if (size < 3) return 0;
- /* begins with a '<' optionally followed by '/', followed by letter or number */
- if (data[0] != '<') return 0;
- i = (data[1] == '/') ? 2 : 1;
+ /* begins with a '<' optionally followed by '/', followed by letter or number */
+ if (data[0] != '<') return 0;
+ i = (data[1] == '/') ? 2 : 1;
- if (!isalnum(data[i]))
- return 0;
+ if (!isalnum(data[i]))
+ return 0;
- /* scheme test */
- *autolink = HOEDOWN_AUTOLINK_NONE;
+ /* scheme test */
+ *autolink = HOEDOWN_AUTOLINK_NONE;
- /* try to find the beginning of an URI */
- while (i < size && (isalnum(data[i]) || data[i] == '.' || data[i] == '+' || data[i] == '-'))
- i++;
+ /* try to find the beginning of an URI */
+ while (i < size && (isalnum(data[i]) || data[i] == '.' || data[i] == '+' || data[i] == '-'))
+ i++;
- if (i > 1 && data[i] == '@') {
- if ((j = is_mail_autolink(data + i, size - i)) != 0) {
- *autolink = HOEDOWN_AUTOLINK_EMAIL;
- return i + j;
- }
- }
+ if (i > 1 && data[i] == '@') {
+ if ((j = is_mail_autolink(data + i, size - i)) != 0) {
+ *autolink = HOEDOWN_AUTOLINK_EMAIL;
+ return i + j;
+ }
+ }
- if (i > 2 && data[i] == ':') {
- *autolink = HOEDOWN_AUTOLINK_NORMAL;
- i++;
- }
+ if (i > 2 && data[i] == ':') {
+ *autolink = HOEDOWN_AUTOLINK_NORMAL;
+ i++;
+ }
- /* completing autolink test: no spacing or ' or " */
- if (i >= size)
- *autolink = HOEDOWN_AUTOLINK_NONE;
+ /* completing autolink test: no spacing or ' or " */
+ if (i >= size)
+ *autolink = HOEDOWN_AUTOLINK_NONE;
- else if (*autolink) {
- j = i;
+ else if (*autolink) {
+ j = i;
- while (i < size) {
- if (data[i] == '\\') i += 2;
- else if (data[i] == '>' || data[i] == '\'' ||
- data[i] == '"' || data[i] == ' ' || data[i] == '\n')
- break;
- else i++;
- }
+ while (i < size) {
+ if (data[i] == '\\') i += 2;
+ else if (data[i] == '>' || data[i] == '\'' ||
+ data[i] == '"' || data[i] == ' ' || data[i] == '\n')
+ break;
+ else i++;
+ }
- if (i >= size) return 0;
- if (i > j && data[i] == '>') return i + 1;
- /* one of the forbidden chars has been found */
- *autolink = HOEDOWN_AUTOLINK_NONE;
- }
+ if (i >= size) return 0;
+ if (i > j && data[i] == '>') return i + 1;
+ /* one of the forbidden chars has been found */
+ *autolink = HOEDOWN_AUTOLINK_NONE;
+ }
- /* looking for something looking like a tag end */
- while (i < size && data[i] != '>') i++;
- if (i >= size) return 0;
- return i + 1;
+ /* looking for something looking like a tag end */
+ while (i < size && data[i] != '>') i++;
+ if (i >= size) return 0;
+ return i + 1;
}
/* parse_inline • parses inline markdown elements */
static void
parse_inline(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size)
{
- size_t i = 0, end = 0, consumed = 0;
- hoedown_buffer work = { 0, 0, 0, 0, NULL, NULL, NULL };
- uint8_t *active_char = doc->active_char;
-
- if (doc->work_bufs[BUFFER_SPAN].size +
- doc->work_bufs[BUFFER_BLOCK].size > doc->max_nesting)
- return;
-
- while (i < size) {
- /* copying inactive chars into the output */
- while (end < size && active_char[data[end]] == 0)
- end++;
-
- if (doc->md.normal_text) {
- work.data = data + i;
- work.size = end - i;
- doc->md.normal_text(ob, &work, &doc->data);
- }
- else
- hoedown_buffer_put(ob, data + i, end - i);
-
- if (end >= size) break;
- i = end;
-
- end = markdown_char_ptrs[ (int)active_char[data[end]] ](ob, doc, data + i, i - consumed, size - i);
- if (!end) /* no action from the callback */
- end = i + 1;
- else {
- i += end;
- end = i;
- consumed = i;
- }
- }
+ size_t i = 0, end = 0, consumed = 0;
+ hoedown_buffer work = { 0, 0, 0, 0, NULL, NULL, NULL };
+ uint8_t *active_char = doc->active_char;
+
+ if (doc->work_bufs[BUFFER_SPAN].size +
+ doc->work_bufs[BUFFER_BLOCK].size > doc->max_nesting)
+ return;
+
+ while (i < size) {
+ /* copying inactive chars into the output */
+ while (end < size && active_char[data[end]] == 0)
+ end++;
+
+ if (doc->md.normal_text) {
+ work.data = data + i;
+ work.size = end - i;
+ doc->md.normal_text(ob, &work, &doc->data);
+ }
+ else
+ hoedown_buffer_put(ob, data + i, end - i);
+
+ if (end >= size) break;
+ i = end;
+
+ end = markdown_char_ptrs[ (int)active_char[data[end]] ](ob, doc, data + i, i - consumed, size - i);
+ if (!end) /* no action from the callback */
+ end = i + 1;
+ else {
+ i += end;
+ end = i;
+ consumed = i;
+ }
+ }
}
/* is_escaped • returns whether special char at data[loc] is escaped by '\\' */
static int
is_escaped(uint8_t *data, size_t loc)
{
- size_t i = loc;
- while (i >= 1 && data[i - 1] == '\\')
- i--;
+ size_t i = loc;
+ while (i >= 1 && data[i - 1] == '\\')
+ i--;
- /* odd numbers of backslashes escapes data[loc] */
- return (loc - i) % 2;
+ /* odd numbers of backslashes escapes data[loc] */
+ return (loc - i) % 2;
}
/* find_emph_char • looks for the next emph uint8_t, skipping other constructs */
static size_t
find_emph_char(uint8_t *data, size_t size, uint8_t c)
{
- size_t i = 0;
+ size_t i = 0;
- while (i < size) {
- while (i < size && data[i] != c && data[i] != '[' && data[i] != '`')
- i++;
+ while (i < size) {
+ while (i < size && data[i] != c && data[i] != '[' && data[i] != '`')
+ i++;
- if (i == size)
- return 0;
+ if (i == size)
+ return 0;
- /* not counting escaped chars */
- if (is_escaped(data, i)) {
- i++; continue;
- }
+ /* not counting escaped chars */
+ if (is_escaped(data, i)) {
+ i++; continue;
+ }
- if (data[i] == c)
- return i;
+ if (data[i] == c)
+ return i;
- /* skipping a codespan */
- if (data[i] == '`') {
- size_t span_nb = 0, bt;
- size_t tmp_i = 0;
+ /* skipping a codespan */
+ if (data[i] == '`') {
+ size_t span_nb = 0, bt;
+ size_t tmp_i = 0;
- /* counting the number of opening backticks */
- while (i < size && data[i] == '`') {
- i++; span_nb++;
- }
+ /* counting the number of opening backticks */
+ while (i < size && data[i] == '`') {
+ i++; span_nb++;
+ }
- if (i >= size) return 0;
+ if (i >= size) return 0;
- /* finding the matching closing sequence */
- bt = 0;
- while (i < size && bt < span_nb) {
- if (!tmp_i && data[i] == c) tmp_i = i;
- if (data[i] == '`') bt++;
- else bt = 0;
- i++;
- }
+ /* finding the matching closing sequence */
+ bt = 0;
+ while (i < size && bt < span_nb) {
+ if (!tmp_i && data[i] == c) tmp_i = i;
+ if (data[i] == '`') bt++;
+ else bt = 0;
+ i++;
+ }
- /* not a well-formed codespan; use found matching emph char */
- if (i >= size) return tmp_i;
- }
- /* skipping a link */
- else if (data[i] == '[') {
- size_t tmp_i = 0;
- uint8_t cc;
+ /* not a well-formed codespan; use found matching emph char */
+ if (i >= size) return tmp_i;
+ }
+ /* skipping a link */
+ else if (data[i] == '[') {
+ size_t tmp_i = 0;
+ uint8_t cc;
- i++;
- while (i < size && data[i] != ']') {
- if (!tmp_i && data[i] == c) tmp_i = i;
- i++;
- }
+ i++;
+ while (i < size && data[i] != ']') {
+ if (!tmp_i && data[i] == c) tmp_i = i;
+ i++;
+ }
- i++;
- while (i < size && _isspace(data[i]))
- i++;
+ i++;
+ while (i < size && _isspace(data[i]))
+ i++;
- if (i >= size)
- return tmp_i;
+ if (i >= size)
+ return tmp_i;
- switch (data[i]) {
- case '[':
- cc = ']'; break;
+ switch (data[i]) {
+ case '[':
+ cc = ']'; break;
- case '(':
- cc = ')'; break;
+ case '(':
+ cc = ')'; break;
- default:
- if (tmp_i)
- return tmp_i;
- else
- continue;
- }
+ default:
+ if (tmp_i)
+ return tmp_i;
+ else
+ continue;
+ }
- i++;
- while (i < size && data[i] != cc) {
- if (!tmp_i && data[i] == c) tmp_i = i;
- i++;
- }
+ i++;
+ while (i < size && data[i] != cc) {
+ if (!tmp_i && data[i] == c) tmp_i = i;
+ i++;
+ }
- if (i >= size)
- return tmp_i;
+ if (i >= size)
+ return tmp_i;
- i++;
- }
- }
+ i++;
+ }
+ }
- return 0;
+ return 0;
}
/* parse_emph1 • parsing single emphase */
@@ -604,72 +604,72 @@ find_emph_char(uint8_t *data, size_t size, uint8_t c)
static size_t
parse_emph1(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size, uint8_t c)
{
- size_t i = 0, len;
- hoedown_buffer *work = 0;
- int r;
+ size_t i = 0, len;
+ hoedown_buffer *work = 0;
+ int r;
- /* skipping one symbol if coming from emph3 */
- if (size > 1 && data[0] == c && data[1] == c) i = 1;
+ /* skipping one symbol if coming from emph3 */
+ if (size > 1 && data[0] == c && data[1] == c) i = 1;
- while (i < size) {
- len = find_emph_char(data + i, size - i, c);
- if (!len) return 0;
- i += len;
- if (i >= size) return 0;
+ while (i < size) {
+ len = find_emph_char(data + i, size - i, c);
+ if (!len) return 0;
+ i += len;
+ if (i >= size) return 0;
- if (data[i] == c && !_isspace(data[i - 1])) {
+ if (data[i] == c && !_isspace(data[i - 1])) {
- if (doc->ext_flags & HOEDOWN_EXT_NO_INTRA_EMPHASIS) {
- if (i + 1 < size && isalnum(data[i + 1]))
- continue;
- }
+ if (doc->ext_flags & HOEDOWN_EXT_NO_INTRA_EMPHASIS) {
+ if (i + 1 < size && isalnum(data[i + 1]))
+ continue;
+ }
- work = newbuf(doc, BUFFER_SPAN);
- parse_inline(work, doc, data, i);
+ work = newbuf(doc, BUFFER_SPAN);
+ parse_inline(work, doc, data, i);
- if (doc->ext_flags & HOEDOWN_EXT_UNDERLINE && c == '_')
- r = doc->md.underline(ob, work, &doc->data);
- else
- r = doc->md.emphasis(ob, work, &doc->data);
+ if (doc->ext_flags & HOEDOWN_EXT_UNDERLINE && c == '_')
+ r = doc->md.underline(ob, work, &doc->data);
+ else
+ r = doc->md.emphasis(ob, work, &doc->data);
- popbuf(doc, BUFFER_SPAN);
- return r ? i + 1 : 0;
- }
- }
+ popbuf(doc, BUFFER_SPAN);
+ return r ? i + 1 : 0;
+ }
+ }
- return 0;
+ return 0;
}
/* parse_emph2 • parsing single emphase */
static size_t
parse_emph2(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size, uint8_t c)
{
- size_t i = 0, len;
- hoedown_buffer *work = 0;
- int r;
+ size_t i = 0, len;
+ hoedown_buffer *work = 0;
+ int r;
- while (i < size) {
- len = find_emph_char(data + i, size - i, c);
- if (!len) return 0;
- i += len;
+ while (i < size) {
+ len = find_emph_char(data + i, size - i, c);
+ if (!len) return 0;
+ i += len;
- if (i + 1 < size && data[i] == c && data[i + 1] == c && i && !_isspace(data[i - 1])) {
- work = newbuf(doc, BUFFER_SPAN);
- parse_inline(work, doc, data, i);
+ if (i + 1 < size && data[i] == c && data[i + 1] == c && i && !_isspace(data[i - 1])) {
+ work = newbuf(doc, BUFFER_SPAN);
+ parse_inline(work, doc, data, i);
- if (c == '~')
- r = doc->md.strikethrough(ob, work, &doc->data);
- else if (c == '=')
- r = doc->md.highlight(ob, work, &doc->data);
- else
- r = doc->md.double_emphasis(ob, work, &doc->data);
+ if (c == '~')
+ r = doc->md.strikethrough(ob, work, &doc->data);
+ else if (c == '=')
+ r = doc->md.highlight(ob, work, &doc->data);
+ else
+ r = doc->md.double_emphasis(ob, work, &doc->data);
- popbuf(doc, BUFFER_SPAN);
- return r ? i + 2 : 0;
- }
- i++;
- }
- return 0;
+ popbuf(doc, BUFFER_SPAN);
+ return r ? i + 2 : 0;
+ }
+ i++;
+ }
+ return 0;
}
/* parse_emph3 • parsing single emphase */
@@ -677,121 +677,121 @@ parse_emph2(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t siz
static size_t
parse_emph3(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size, uint8_t c)
{
- size_t i = 0, len;
- int r;
+ size_t i = 0, len;
+ int r;
- while (i < size) {
- len = find_emph_char(data + i, size - i, c);
- if (!len) return 0;
- i += len;
+ while (i < size) {
+ len = find_emph_char(data + i, size - i, c);
+ if (!len) return 0;
+ i += len;
- /* skip spacing preceded symbols */
- if (data[i] != c || _isspace(data[i - 1]))
- continue;
+ /* skip spacing preceded symbols */
+ if (data[i] != c || _isspace(data[i - 1]))
+ continue;
- if (i + 2 < size && data[i + 1] == c && data[i + 2] == c && doc->md.triple_emphasis) {
- /* triple symbol found */
- hoedown_buffer *work = newbuf(doc, BUFFER_SPAN);
+ if (i + 2 < size && data[i + 1] == c && data[i + 2] == c && doc->md.triple_emphasis) {
+ /* triple symbol found */
+ hoedown_buffer *work = newbuf(doc, BUFFER_SPAN);
- parse_inline(work, doc, data, i);
- r = doc->md.triple_emphasis(ob, work, &doc->data);
- popbuf(doc, BUFFER_SPAN);
- return r ? i + 3 : 0;
+ parse_inline(work, doc, data, i);
+ r = doc->md.triple_emphasis(ob, work, &doc->data);
+ popbuf(doc, BUFFER_SPAN);
+ return r ? i + 3 : 0;
- } else if (i + 1 < size && data[i + 1] == c) {
- /* double symbol found, handing over to emph1 */
- len = parse_emph1(ob, doc, data - 2, size + 2, c);
- if (!len) return 0;
- else return len - 2;
+ } else if (i + 1 < size && data[i + 1] == c) {
+ /* double symbol found, handing over to emph1 */
+ len = parse_emph1(ob, doc, data - 2, size + 2, c);
+ if (!len) return 0;
+ else return len - 2;
- } else {
- /* single symbol found, handing over to emph2 */
- len = parse_emph2(ob, doc, data - 1, size + 1, c);
- if (!len) return 0;
- else return len - 1;
- }
- }
- return 0;
+ } else {
+ /* single symbol found, handing over to emph2 */
+ len = parse_emph2(ob, doc, data - 1, size + 1, c);
+ if (!len) return 0;
+ else return len - 1;
+ }
+ }
+ return 0;
}
/* parse_math • parses a math span until the given ending delimiter */
static size_t
parse_math(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size, const char *end, size_t delimsz, int displaymode)
{
- hoedown_buffer text = { NULL, 0, 0, 0, NULL, NULL, NULL };
- size_t i = delimsz;
+ hoedown_buffer text = { NULL, 0, 0, 0, NULL, NULL, NULL };
+ size_t i = delimsz;
- if (!doc->md.math)
- return 0;
+ if (!doc->md.math)
+ return 0;
- /* find ending delimiter */
- while (1) {
- while (i < size && data[i] != (uint8_t)end[0])
- i++;
+ /* find ending delimiter */
+ while (1) {
+ while (i < size && data[i] != (uint8_t)end[0])
+ i++;
- if (i >= size)
- return 0;
+ if (i >= size)
+ return 0;
- if (!is_escaped(data, i) && !(i + delimsz > size)
- && memcmp(data + i, end, delimsz) == 0)
- break;
+ if (!is_escaped(data, i) && !(i + delimsz > size)
+ && memcmp(data + i, end, delimsz) == 0)
+ break;
- i++;
- }
+ i++;
+ }
- /* prepare buffers */
- text.data = data + delimsz;
- text.size = i - delimsz;
+ /* prepare buffers */
+ text.data = data + delimsz;
+ text.size = i - delimsz;
- /* if this is a $$ and MATH_EXPLICIT is not active,
- * guess whether displaymode should be enabled from the context */
- i += delimsz;
- if (delimsz == 2 && !(doc->ext_flags & HOEDOWN_EXT_MATH_EXPLICIT))
- displaymode = is_empty_all(data - offset, offset) && is_empty_all(data + i, size - i);
+ /* if this is a $$ and MATH_EXPLICIT is not active,
+ * guess whether displaymode should be enabled from the context */
+ i += delimsz;
+ if (delimsz == 2 && !(doc->ext_flags & HOEDOWN_EXT_MATH_EXPLICIT))
+ displaymode = is_empty_all(data - offset, offset) && is_empty_all(data + i, size - i);
- /* call callback */
- if (doc->md.math(ob, &text, displaymode, &doc->data))
- return i;
+ /* call callback */
+ if (doc->md.math(ob, &text, displaymode, &doc->data))
+ return i;
- return 0;
+ return 0;
}
/* char_emphasis • single and double emphasis parsing */
static size_t
char_emphasis(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size)
{
- uint8_t c = data[0];
- size_t ret;
+ uint8_t c = data[0];
+ size_t ret;
- if (doc->ext_flags & HOEDOWN_EXT_NO_INTRA_EMPHASIS) {
- if (offset > 0 && !_isspace(data[-1]) && data[-1] != '>' && data[-1] != '(')
- return 0;
- }
+ if (doc->ext_flags & HOEDOWN_EXT_NO_INTRA_EMPHASIS) {
+ if (offset > 0 && !_isspace(data[-1]) && data[-1] != '>' && data[-1] != '(')
+ return 0;
+ }
- if (size > 2 && data[1] != c) {
- /* spacing cannot follow an opening emphasis;
- * strikethrough and highlight only takes two characters '~~' */
- if (c == '~' || c == '=' || _isspace(data[1]) || (ret = parse_emph1(ob, doc, data + 1, size - 1, c)) == 0)
- return 0;
+ if (size > 2 && data[1] != c) {
+ /* spacing cannot follow an opening emphasis;
+ * strikethrough and highlight only takes two characters '~~' */
+ if (c == '~' || c == '=' || _isspace(data[1]) || (ret = parse_emph1(ob, doc, data + 1, size - 1, c)) == 0)
+ return 0;
- return ret + 1;
- }
+ return ret + 1;
+ }
- if (size > 3 && data[1] == c && data[2] != c) {
- if (_isspace(data[2]) || (ret = parse_emph2(ob, doc, data + 2, size - 2, c)) == 0)
- return 0;
+ if (size > 3 && data[1] == c && data[2] != c) {
+ if (_isspace(data[2]) || (ret = parse_emph2(ob, doc, data + 2, size - 2, c)) == 0)
+ return 0;
- return ret + 2;
- }
+ return ret + 2;
+ }
- if (size > 4 && data[1] == c && data[2] == c && data[3] != c) {
- if (c == '~' || c == '=' || _isspace(data[3]) || (ret = parse_emph3(ob, doc, data + 3, size - 3, c)) == 0)
- return 0;
+ if (size > 4 && data[1] == c && data[2] == c && data[3] != c) {
+ if (c == '~' || c == '=' || _isspace(data[3]) || (ret = parse_emph3(ob, doc, data + 3, size - 3, c)) == 0)
+ return 0;
- return ret + 3;
- }
+ return ret + 3;
+ }
- return 0;
+ return 0;
}
@@ -799,14 +799,14 @@ char_emphasis(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t o
static size_t
char_linebreak(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size)
{
- if (offset < 2 || data[-1] != ' ' || data[-2] != ' ')
- return 0;
+ if (offset < 2 || data[-1] != ' ' || data[-2] != ' ')
+ return 0;
- /* removing the last space from ob and rendering */
- while (ob->size && ob->data[ob->size - 1] == ' ')
- ob->size--;
+ /* removing the last space from ob and rendering */
+ while (ob->size && ob->data[ob->size - 1] == ' ')
+ ob->size--;
- return doc->md.linebreak(ob, &doc->data) ? 1 : 0;
+ return doc->md.linebreak(ob, &doc->data) ? 1 : 0;
}
@@ -814,91 +814,91 @@ char_linebreak(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t
static size_t
char_codespan(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size)
{
- hoedown_buffer work = { NULL, 0, 0, 0, NULL, NULL, NULL };
- size_t end, nb = 0, i, f_begin, f_end;
+ hoedown_buffer work = { NULL, 0, 0, 0, NULL, NULL, NULL };
+ size_t end, nb = 0, i, f_begin, f_end;
- /* counting the number of backticks in the delimiter */
- while (nb < size && data[nb] == '`')
- nb++;
+ /* counting the number of backticks in the delimiter */
+ while (nb < size && data[nb] == '`')
+ nb++;
- /* finding the next delimiter */
- i = 0;
- for (end = nb; end < size && i < nb; end++) {
- if (data[end] == '`') i++;
- else i = 0;
- }
+ /* finding the next delimiter */
+ i = 0;
+ for (end = nb; end < size && i < nb; end++) {
+ if (data[end] == '`') i++;
+ else i = 0;
+ }
- if (i < nb && end >= size)
- return 0; /* no matching delimiter */
+ if (i < nb && end >= size)
+ return 0; /* no matching delimiter */
- /* trimming outside spaces */
- f_begin = nb;
- while (f_begin < end && data[f_begin] == ' ')
- f_begin++;
+ /* trimming outside spaces */
+ f_begin = nb;
+ while (f_begin < end && data[f_begin] == ' ')
+ f_begin++;
- f_end = end - nb;
- while (f_end > nb && data[f_end-1] == ' ')
- f_end--;
+ f_end = end - nb;
+ while (f_end > nb && data[f_end-1] == ' ')
+ f_end--;
- /* real code span */
- if (f_begin < f_end) {
- work.data = data + f_begin;
- work.size = f_end - f_begin;
+ /* real code span */
+ if (f_begin < f_end) {
+ work.data = data + f_begin;
+ work.size = f_end - f_begin;
- if (!doc->md.codespan(ob, &work, &doc->data))
- end = 0;
- } else {
- if (!doc->md.codespan(ob, 0, &doc->data))
- end = 0;
- }
+ if (!doc->md.codespan(ob, &work, &doc->data))
+ end = 0;
+ } else {
+ if (!doc->md.codespan(ob, 0, &doc->data))
+ end = 0;
+ }
- return end;
+ return end;
}
/* char_quote • '"' parsing a quote */
static size_t
char_quote(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size)
{
- size_t end, nq = 0, i, f_begin, f_end;
+ size_t end, nq = 0, i, f_begin, f_end;
- /* counting the number of quotes in the delimiter */
- while (nq < size && data[nq] == '"')
- nq++;
+ /* counting the number of quotes in the delimiter */
+ while (nq < size && data[nq] == '"')
+ nq++;
- /* finding the next delimiter */
- end = nq;
- while (1) {
- i = end;
- end += find_emph_char(data + end, size - end, '"');
- if (end == i) return 0; /* no matching delimiter */
- i = end;
- while (end < size && data[end] == '"' && end - i < nq) end++;
- if (end - i >= nq) break;
- }
+ /* finding the next delimiter */
+ end = nq;
+ while (1) {
+ i = end;
+ end += find_emph_char(data + end, size - end, '"');
+ if (end == i) return 0; /* no matching delimiter */
+ i = end;
+ while (end < size && data[end] == '"' && end - i < nq) end++;
+ if (end - i >= nq) break;
+ }
- /* trimming outside spaces */
- f_begin = nq;
- while (f_begin < end && data[f_begin] == ' ')
- f_begin++;
+ /* trimming outside spaces */
+ f_begin = nq;
+ while (f_begin < end && data[f_begin] == ' ')
+ f_begin++;
- f_end = end - nq;
- while (f_end > nq && data[f_end-1] == ' ')
- f_end--;
+ f_end = end - nq;
+ while (f_end > nq && data[f_end-1] == ' ')
+ f_end--;
- /* real quote */
- if (f_begin < f_end) {
- hoedown_buffer *work = newbuf(doc, BUFFER_SPAN);
- parse_inline(work, doc, data + f_begin, f_end - f_begin);
+ /* real quote */
+ if (f_begin < f_end) {
+ hoedown_buffer *work = newbuf(doc, BUFFER_SPAN);
+ parse_inline(work, doc, data + f_begin, f_end - f_begin);
- if (!doc->md.quote(ob, work, &doc->data))
- end = 0;
- popbuf(doc, BUFFER_SPAN);
- } else {
- if (!doc->md.quote(ob, 0, &doc->data))
- end = 0;
- }
+ if (!doc->md.quote(ob, work, &doc->data))
+ end = 0;
+ popbuf(doc, BUFFER_SPAN);
+ } else {
+ if (!doc->md.quote(ob, 0, &doc->data))
+ end = 0;
+ }
- return end;
+ return end;
}
@@ -906,32 +906,32 @@ char_quote(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offs
static size_t
char_escape(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size)
{
- static const char *escape_chars = "\\`*_{}[]()#+-.!:|&<>^~=\"$";
- hoedown_buffer work = { 0, 0, 0, 0, NULL, NULL, NULL };
- size_t w;
+ static const char *escape_chars = "\\`*_{}[]()#+-.!:|&<>^~=\"$";
+ hoedown_buffer work = { 0, 0, 0, 0, NULL, NULL, NULL };
+ size_t w;
- if (size > 1) {
- if (data[1] == '\\' && (doc->ext_flags & HOEDOWN_EXT_MATH) &&
- size > 2 && (data[2] == '(' || data[2] == '[')) {
- const char *end = (data[2] == '[') ? "\\\\]" : "\\\\)";
- w = parse_math(ob, doc, data, offset, size, end, 3, data[2] == '[');
- if (w) return w;
- }
+ if (size > 1) {
+ if (data[1] == '\\' && (doc->ext_flags & HOEDOWN_EXT_MATH) &&
+ size > 2 && (data[2] == '(' || data[2] == '[')) {
+ const char *end = (data[2] == '[') ? "\\\\]" : "\\\\)";
+ w = parse_math(ob, doc, data, offset, size, end, 3, data[2] == '[');
+ if (w) return w;
+ }
- if (strchr(escape_chars, data[1]) == NULL)
- return 0;
+ if (strchr(escape_chars, data[1]) == NULL)
+ return 0;
- if (doc->md.normal_text) {
- work.data = data + 1;
- work.size = 1;
- doc->md.normal_text(ob, &work, &doc->data);
- }
- else hoedown_buffer_putc(ob, data[1]);
- } else if (size == 1) {
- hoedown_buffer_putc(ob, data[0]);
- }
+ if (doc->md.normal_text) {
+ work.data = data + 1;
+ work.size = 1;
+ doc->md.normal_text(ob, &work, &doc->data);
+ }
+ else hoedown_buffer_putc(ob, data[1]);
+ } else if (size == 1) {
+ hoedown_buffer_putc(ob, data[0]);
+ }
- return 2;
+ return 2;
}
/* char_entity • '&' escaped when it doesn't belong to an entity */
@@ -939,403 +939,403 @@ char_escape(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t off
static size_t
char_entity(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size)
{
- size_t end = 1;
- hoedown_buffer work = { 0, 0, 0, 0, NULL, NULL, NULL };
+ size_t end = 1;
+ hoedown_buffer work = { 0, 0, 0, 0, NULL, NULL, NULL };
- if (end < size && data[end] == '#')
- end++;
+ if (end < size && data[end] == '#')
+ end++;
- while (end < size && isalnum(data[end]))
- end++;
+ while (end < size && isalnum(data[end]))
+ end++;
- if (end < size && data[end] == ';')
- end++; /* real entity */
- else
- return 0; /* lone '&' */
+ if (end < size && data[end] == ';')
+ end++; /* real entity */
+ else
+ return 0; /* lone '&' */
- if (doc->md.entity) {
- work.data = data;
- work.size = end;
- doc->md.entity(ob, &work, &doc->data);
- }
- else hoedown_buffer_put(ob, data, end);
+ if (doc->md.entity) {
+ work.data = data;
+ work.size = end;
+ doc->md.entity(ob, &work, &doc->data);
+ }
+ else hoedown_buffer_put(ob, data, end);
- return end;
+ return end;
}
/* char_langle_tag • '<' when tags or autolinks are allowed */
static size_t
char_langle_tag(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size)
{
- hoedown_buffer work = { NULL, 0, 0, 0, NULL, NULL, NULL };
- hoedown_autolink_type altype = HOEDOWN_AUTOLINK_NONE;
- size_t end = tag_length(data, size, &altype);
- int ret = 0;
+ hoedown_buffer work = { NULL, 0, 0, 0, NULL, NULL, NULL };
+ hoedown_autolink_type altype = HOEDOWN_AUTOLINK_NONE;
+ size_t end = tag_length(data, size, &altype);
+ int ret = 0;
- work.data = data;
- work.size = end;
+ work.data = data;
+ work.size = end;
- if (end > 2) {
- if (doc->md.autolink && altype != HOEDOWN_AUTOLINK_NONE) {
- hoedown_buffer *u_link = newbuf(doc, BUFFER_SPAN);
- work.data = data + 1;
- work.size = end - 2;
- unscape_text(u_link, &work);
- ret = doc->md.autolink(ob, u_link, altype, &doc->data);
- popbuf(doc, BUFFER_SPAN);
- }
- else if (doc->md.raw_html)
- ret = doc->md.raw_html(ob, &work, &doc->data);
- }
+ if (end > 2) {
+ if (doc->md.autolink && altype != HOEDOWN_AUTOLINK_NONE) {
+ hoedown_buffer *u_link = newbuf(doc, BUFFER_SPAN);
+ work.data = data + 1;
+ work.size = end - 2;
+ unscape_text(u_link, &work);
+ ret = doc->md.autolink(ob, u_link, altype, &doc->data);
+ popbuf(doc, BUFFER_SPAN);
+ }
+ else if (doc->md.raw_html)
+ ret = doc->md.raw_html(ob, &work, &doc->data);
+ }
- if (!ret) return 0;
- else return end;
+ if (!ret) return 0;
+ else return end;
}
static size_t
char_autolink_www(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size)
{
- hoedown_buffer *link, *link_url, *link_text;
- size_t link_len, rewind;
+ hoedown_buffer *link, *link_url, *link_text;
+ size_t link_len, rewind;
- if (!doc->md.link || doc->in_link_body)
- return 0;
+ if (!doc->md.link || doc->in_link_body)
+ return 0;
- link = newbuf(doc, BUFFER_SPAN);
+ link = newbuf(doc, BUFFER_SPAN);
- if ((link_len = hoedown_autolink__www(&rewind, link, data, offset, size, HOEDOWN_AUTOLINK_SHORT_DOMAINS)) > 0) {
- link_url = newbuf(doc, BUFFER_SPAN);
- HOEDOWN_BUFPUTSL(link_url, "http://");
- hoedown_buffer_put(link_url, link->data, link->size);
+ if ((link_len = hoedown_autolink__www(&rewind, link, data, offset, size, HOEDOWN_AUTOLINK_SHORT_DOMAINS)) > 0) {
+ link_url = newbuf(doc, BUFFER_SPAN);
+ HOEDOWN_BUFPUTSL(link_url, "http://");
+ hoedown_buffer_put(link_url, link->data, link->size);
- ob->size -= rewind;
- if (doc->md.normal_text) {
- link_text = newbuf(doc, BUFFER_SPAN);
- doc->md.normal_text(link_text, link, &doc->data);
- doc->md.link(ob, link_text, link_url, NULL, &doc->data);
- popbuf(doc, BUFFER_SPAN);
- } else {
- doc->md.link(ob, link, link_url, NULL, &doc->data);
- }
- popbuf(doc, BUFFER_SPAN);
- }
+ ob->size -= rewind;
+ if (doc->md.normal_text) {
+ link_text = newbuf(doc, BUFFER_SPAN);
+ doc->md.normal_text(link_text, link, &doc->data);
+ doc->md.link(ob, link_text, link_url, NULL, &doc->data);
+ popbuf(doc, BUFFER_SPAN);
+ } else {
+ doc->md.link(ob, link, link_url, NULL, &doc->data);
+ }
+ popbuf(doc, BUFFER_SPAN);
+ }
- popbuf(doc, BUFFER_SPAN);
- return link_len;
+ popbuf(doc, BUFFER_SPAN);
+ return link_len;
}
static size_t
char_autolink_email(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size)
{
- hoedown_buffer *link;
- size_t link_len, rewind;
+ hoedown_buffer *link;
+ size_t link_len, rewind;
- if (!doc->md.autolink || doc->in_link_body)
- return 0;
+ if (!doc->md.autolink || doc->in_link_body)
+ return 0;
- link = newbuf(doc, BUFFER_SPAN);
+ link = newbuf(doc, BUFFER_SPAN);
- if ((link_len = hoedown_autolink__email(&rewind, link, data, offset, size, 0)) > 0) {
- ob->size -= rewind;
- doc->md.autolink(ob, link, HOEDOWN_AUTOLINK_EMAIL, &doc->data);
- }
+ if ((link_len = hoedown_autolink__email(&rewind, link, data, offset, size, 0)) > 0) {
+ ob->size -= rewind;
+ doc->md.autolink(ob, link, HOEDOWN_AUTOLINK_EMAIL, &doc->data);
+ }
- popbuf(doc, BUFFER_SPAN);
- return link_len;
+ popbuf(doc, BUFFER_SPAN);
+ return link_len;
}
static size_t
char_autolink_url(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size)
{
- hoedown_buffer *link;
- size_t link_len, rewind;
+ hoedown_buffer *link;
+ size_t link_len, rewind;
- if (!doc->md.autolink || doc->in_link_body)
- return 0;
+ if (!doc->md.autolink || doc->in_link_body)
+ return 0;
- link = newbuf(doc, BUFFER_SPAN);
+ link = newbuf(doc, BUFFER_SPAN);
- if ((link_len = hoedown_autolink__url(&rewind, link, data, offset, size, 0)) > 0) {
- ob->size -= rewind;
- doc->md.autolink(ob, link, HOEDOWN_AUTOLINK_NORMAL, &doc->data);
- }
+ if ((link_len = hoedown_autolink__url(&rewind, link, data, offset, size, 0)) > 0) {
+ ob->size -= rewind;
+ doc->md.autolink(ob, link, HOEDOWN_AUTOLINK_NORMAL, &doc->data);
+ }
- popbuf(doc, BUFFER_SPAN);
- return link_len;
+ popbuf(doc, BUFFER_SPAN);
+ return link_len;
}
/* char_link • '[': parsing a link, a footnote or an image */
static size_t
char_link(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size)
{
- int is_img = (offset && data[-1] == '!' && !is_escaped(data - offset, offset - 1));
- int is_footnote = (doc->ext_flags & HOEDOWN_EXT_FOOTNOTES && data[1] == '^');
- size_t i = 1, txt_e, link_b = 0, link_e = 0, title_b = 0, title_e = 0;
- hoedown_buffer *content = NULL;
- hoedown_buffer *link = NULL;
- hoedown_buffer *title = NULL;
- hoedown_buffer *u_link = NULL;
- size_t org_work_size = doc->work_bufs[BUFFER_SPAN].size;
- int ret = 0, in_title = 0, qtype = 0;
-
- /* checking whether the correct renderer exists */
- if ((is_footnote && !doc->md.footnote_ref) || (is_img && !doc->md.image)
- || (!is_img && !is_footnote && !doc->md.link))
- goto cleanup;
-
- /* looking for the matching closing bracket */
- i += find_emph_char(data + i, size - i, ']');
- txt_e = i;
-
- if (i < size && data[i] == ']') i++;
- else goto cleanup;
-
- /* footnote link */
- if (is_footnote) {
- hoedown_buffer id = { NULL, 0, 0, 0, NULL, NULL, NULL };
- struct footnote_ref *fr;
-
- if (txt_e < 3)
- goto cleanup;
-
- id.data = data + 2;
- id.size = txt_e - 2;
-
- fr = find_footnote_ref(&doc->footnotes_found, id.data, id.size);
-
- /* mark footnote used */
- if (fr && !fr->is_used) {
- if(!add_footnote_ref(&doc->footnotes_used, fr))
- goto cleanup;
- fr->is_used = 1;
- fr->num = doc->footnotes_used.count;
-
- /* render */
- if (doc->md.footnote_ref)
- ret = doc->md.footnote_ref(ob, fr->num, &doc->data);
- }
-
- goto cleanup;
- }
-
- /* skip any amount of spacing */
- /* (this is much more laxist than original markdown syntax) */
- while (i < size && _isspace(data[i]))
- i++;
-
- /* inline style link */
- if (i < size && data[i] == '(') {
- size_t nb_p;
-
- /* skipping initial spacing */
- i++;
-
- while (i < size && _isspace(data[i]))
- i++;
-
- link_b = i;
-
- /* looking for link end: ' " ) */
- /* Count the number of open parenthesis */
- nb_p = 0;
-
- while (i < size) {
- if (data[i] == '\\') i += 2;
- else if (data[i] == '(' && i != 0) {
- nb_p++; i++;
- }
- else if (data[i] == ')') {
- if (nb_p == 0) break;
- else nb_p--; i++;
- } else if (i >= 1 && _isspace(data[i-1]) && (data[i] == '\'' || data[i] == '"')) break;
- else i++;
- }
-
- if (i >= size) goto cleanup;
- link_e = i;
-
- /* looking for title end if present */
- if (data[i] == '\'' || data[i] == '"') {
- qtype = data[i];
- in_title = 1;
- i++;
- title_b = i;
-
- while (i < size) {
- if (data[i] == '\\') i += 2;
- else if (data[i] == qtype) {in_title = 0; i++;}
- else if ((data[i] == ')') && !in_title) break;
- else i++;
- }
-
- if (i >= size) goto cleanup;
-
- /* skipping spacing after title */
- title_e = i - 1;
- while (title_e > title_b && _isspace(data[title_e]))
- title_e--;
-
- /* checking for closing quote presence */
- if (data[title_e] != '\'' && data[title_e] != '"') {
- title_b = title_e = 0;
- link_e = i;
- }
- }
-
- /* remove spacing at the end of the link */
- while (link_e > link_b && _isspace(data[link_e - 1]))
- link_e--;
-
- /* remove optional angle brackets around the link */
- if (data[link_b] == '<') link_b++;
- if (data[link_e - 1] == '>') link_e--;
-
- /* building escaped link and title */
- if (link_e > link_b) {
- link = newbuf(doc, BUFFER_SPAN);
- hoedown_buffer_put(link, data + link_b, link_e - link_b);
- }
-
- if (title_e > title_b) {
- title = newbuf(doc, BUFFER_SPAN);
- hoedown_buffer_put(title, data + title_b, title_e - title_b);
- }
-
- i++;
- }
-
- /* reference style link */
- else if (i < size && data[i] == '[') {
- hoedown_buffer *id = newbuf(doc, BUFFER_SPAN);
- struct link_ref *lr;
-
- /* looking for the id */
- i++;
- link_b = i;
- while (i < size && data[i] != ']') i++;
- if (i >= size) goto cleanup;
- link_e = i;
-
- /* finding the link_ref */
- if (link_b == link_e)
- replace_spacing(id, data + 1, txt_e - 1);
- else
- hoedown_buffer_put(id, data + link_b, link_e - link_b);
-
- lr = find_link_ref(doc->refs, id->data, id->size);
- if (!lr)
- goto cleanup;
-
- /* keeping link and title from link_ref */
- link = lr->link;
- title = lr->title;
- i++;
- }
-
- /* shortcut reference style link */
- else {
- hoedown_buffer *id = newbuf(doc, BUFFER_SPAN);
- struct link_ref *lr;
-
- /* crafting the id */
- replace_spacing(id, data + 1, txt_e - 1);
-
- /* finding the link_ref */
- lr = find_link_ref(doc->refs, id->data, id->size);
- if (!lr)
- goto cleanup;
-
- /* keeping link and title from link_ref */
- link = lr->link;
- title = lr->title;
-
- /* rewinding the spacing */
- i = txt_e + 1;
- }
-
- /* building content: img alt is kept, only link content is parsed */
- if (txt_e > 1) {
- content = newbuf(doc, BUFFER_SPAN);
- if (is_img) {
- hoedown_buffer_put(content, data + 1, txt_e - 1);
- } else {
- /* disable autolinking when parsing inline the
- * content of a link */
- doc->in_link_body = 1;
- parse_inline(content, doc, data + 1, txt_e - 1);
- doc->in_link_body = 0;
- }
- }
-
- if (link) {
- u_link = newbuf(doc, BUFFER_SPAN);
- unscape_text(u_link, link);
- }
-
- /* calling the relevant rendering function */
- if (is_img) {
- if (ob->size && ob->data[ob->size - 1] == '!')
- ob->size -= 1;
-
- ret = doc->md.image(ob, u_link, title, content, &doc->data);
- } else {
- ret = doc->md.link(ob, content, u_link, title, &doc->data);
- }
-
- /* cleanup */
+ int is_img = (offset && data[-1] == '!' && !is_escaped(data - offset, offset - 1));
+ int is_footnote = (doc->ext_flags & HOEDOWN_EXT_FOOTNOTES && data[1] == '^');
+ size_t i = 1, txt_e, link_b = 0, link_e = 0, title_b = 0, title_e = 0;
+ hoedown_buffer *content = NULL;
+ hoedown_buffer *link = NULL;
+ hoedown_buffer *title = NULL;
+ hoedown_buffer *u_link = NULL;
+ size_t org_work_size = doc->work_bufs[BUFFER_SPAN].size;
+ int ret = 0, in_title = 0, qtype = 0;
+
+ /* checking whether the correct renderer exists */
+ if ((is_footnote && !doc->md.footnote_ref) || (is_img && !doc->md.image)
+ || (!is_img && !is_footnote && !doc->md.link))
+ goto cleanup;
+
+ /* looking for the matching closing bracket */
+ i += find_emph_char(data + i, size - i, ']');
+ txt_e = i;
+
+ if (i < size && data[i] == ']') i++;
+ else goto cleanup;
+
+ /* footnote link */
+ if (is_footnote) {
+ hoedown_buffer id = { NULL, 0, 0, 0, NULL, NULL, NULL };
+ struct footnote_ref *fr;
+
+ if (txt_e < 3)
+ goto cleanup;
+
+ id.data = data + 2;
+ id.size = txt_e - 2;
+
+ fr = find_footnote_ref(&doc->footnotes_found, id.data, id.size);
+
+ /* mark footnote used */
+ if (fr && !fr->is_used) {
+ if(!add_footnote_ref(&doc->footnotes_used, fr))
+ goto cleanup;
+ fr->is_used = 1;
+ fr->num = doc->footnotes_used.count;
+
+ /* render */
+ if (doc->md.footnote_ref)
+ ret = doc->md.footnote_ref(ob, fr->num, &doc->data);
+ }
+
+ goto cleanup;
+ }
+
+ /* skip any amount of spacing */
+ /* (this is much more laxist than original markdown syntax) */
+ while (i < size && _isspace(data[i]))
+ i++;
+
+ /* inline style link */
+ if (i < size && data[i] == '(') {
+ size_t nb_p;
+
+ /* skipping initial spacing */
+ i++;
+
+ while (i < size && _isspace(data[i]))
+ i++;
+
+ link_b = i;
+
+ /* looking for link end: ' " ) */
+ /* Count the number of open parenthesis */
+ nb_p = 0;
+
+ while (i < size) {
+ if (data[i] == '\\') i += 2;
+ else if (data[i] == '(' && i != 0) {
+ nb_p++; i++;
+ }
+ else if (data[i] == ')') {
+ if (nb_p == 0) break;
+ else nb_p--; i++;
+ } else if (i >= 1 && _isspace(data[i-1]) && (data[i] == '\'' || data[i] == '"')) break;
+ else i++;
+ }
+
+ if (i >= size) goto cleanup;
+ link_e = i;
+
+ /* looking for title end if present */
+ if (data[i] == '\'' || data[i] == '"') {
+ qtype = data[i];
+ in_title = 1;
+ i++;
+ title_b = i;
+
+ while (i < size) {
+ if (data[i] == '\\') i += 2;
+ else if (data[i] == qtype) {in_title = 0; i++;}
+ else if ((data[i] == ')') && !in_title) break;
+ else i++;
+ }
+
+ if (i >= size) goto cleanup;
+
+ /* skipping spacing after title */
+ title_e = i - 1;
+ while (title_e > title_b && _isspace(data[title_e]))
+ title_e--;
+
+ /* checking for closing quote presence */
+ if (data[title_e] != '\'' && data[title_e] != '"') {
+ title_b = title_e = 0;
+ link_e = i;
+ }
+ }
+
+ /* remove spacing at the end of the link */
+ while (link_e > link_b && _isspace(data[link_e - 1]))
+ link_e--;
+
+ /* remove optional angle brackets around the link */
+ if (data[link_b] == '<') link_b++;
+ if (data[link_e - 1] == '>') link_e--;
+
+ /* building escaped link and title */
+ if (link_e > link_b) {
+ link = newbuf(doc, BUFFER_SPAN);
+ hoedown_buffer_put(link, data + link_b, link_e - link_b);
+ }
+
+ if (title_e > title_b) {
+ title = newbuf(doc, BUFFER_SPAN);
+ hoedown_buffer_put(title, data + title_b, title_e - title_b);
+ }
+
+ i++;
+ }
+
+ /* reference style link */
+ else if (i < size && data[i] == '[') {
+ hoedown_buffer *id = newbuf(doc, BUFFER_SPAN);
+ struct link_ref *lr;
+
+ /* looking for the id */
+ i++;
+ link_b = i;
+ while (i < size && data[i] != ']') i++;
+ if (i >= size) goto cleanup;
+ link_e = i;
+
+ /* finding the link_ref */
+ if (link_b == link_e)
+ replace_spacing(id, data + 1, txt_e - 1);
+ else
+ hoedown_buffer_put(id, data + link_b, link_e - link_b);
+
+ lr = find_link_ref(doc->refs, id->data, id->size);
+ if (!lr)
+ goto cleanup;
+
+ /* keeping link and title from link_ref */
+ link = lr->link;
+ title = lr->title;
+ i++;
+ }
+
+ /* shortcut reference style link */
+ else {
+ hoedown_buffer *id = newbuf(doc, BUFFER_SPAN);
+ struct link_ref *lr;
+
+ /* crafting the id */
+ replace_spacing(id, data + 1, txt_e - 1);
+
+ /* finding the link_ref */
+ lr = find_link_ref(doc->refs, id->data, id->size);
+ if (!lr)
+ goto cleanup;
+
+ /* keeping link and title from link_ref */
+ link = lr->link;
+ title = lr->title;
+
+ /* rewinding the spacing */
+ i = txt_e + 1;
+ }
+
+ /* building content: img alt is kept, only link content is parsed */
+ if (txt_e > 1) {
+ content = newbuf(doc, BUFFER_SPAN);
+ if (is_img) {
+ hoedown_buffer_put(content, data + 1, txt_e - 1);
+ } else {
+ /* disable autolinking when parsing inline the
+ * content of a link */
+ doc->in_link_body = 1;
+ parse_inline(content, doc, data + 1, txt_e - 1);
+ doc->in_link_body = 0;
+ }
+ }
+
+ if (link) {
+ u_link = newbuf(doc, BUFFER_SPAN);
+ unscape_text(u_link, link);
+ }
+
+ /* calling the relevant rendering function */
+ if (is_img) {
+ if (ob->size && ob->data[ob->size - 1] == '!')
+ ob->size -= 1;
+
+ ret = doc->md.image(ob, u_link, title, content, &doc->data);
+ } else {
+ ret = doc->md.link(ob, content, u_link, title, &doc->data);
+ }
+
+ /* cleanup */
cleanup:
- doc->work_bufs[BUFFER_SPAN].size = (int)org_work_size;
- return ret ? i : 0;
+ doc->work_bufs[BUFFER_SPAN].size = (int)org_work_size;
+ return ret ? i : 0;
}
static size_t
char_superscript(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size)
{
- size_t sup_start, sup_len;
- hoedown_buffer *sup;
+ size_t sup_start, sup_len;
+ hoedown_buffer *sup;
- if (!doc->md.superscript)
- return 0;
+ if (!doc->md.superscript)
+ return 0;
- if (size < 2)
- return 0;
+ if (size < 2)
+ return 0;
- if (data[1] == '(') {
- sup_start = 2;
- sup_len = find_emph_char(data + 2, size - 2, ')') + 2;
+ if (data[1] == '(') {
+ sup_start = 2;
+ sup_len = find_emph_char(data + 2, size - 2, ')') + 2;
- if (sup_len == size)
- return 0;
- } else {
- sup_start = sup_len = 1;
+ if (sup_len == size)
+ return 0;
+ } else {
+ sup_start = sup_len = 1;
- while (sup_len < size && !_isspace(data[sup_len]))
- sup_len++;
- }
+ while (sup_len < size && !_isspace(data[sup_len]))
+ sup_len++;
+ }
- if (sup_len - sup_start == 0)
- return (sup_start == 2) ? 3 : 0;
+ if (sup_len - sup_start == 0)
+ return (sup_start == 2) ? 3 : 0;
- sup = newbuf(doc, BUFFER_SPAN);
- parse_inline(sup, doc, data + sup_start, sup_len - sup_start);
- doc->md.superscript(ob, sup, &doc->data);
- popbuf(doc, BUFFER_SPAN);
+ sup = newbuf(doc, BUFFER_SPAN);
+ parse_inline(sup, doc, data + sup_start, sup_len - sup_start);
+ doc->md.superscript(ob, sup, &doc->data);
+ popbuf(doc, BUFFER_SPAN);
- return (sup_start == 2) ? sup_len + 1 : sup_len;
+ return (sup_start == 2) ? sup_len + 1 : sup_len;
}
static size_t
char_math(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size)
{
- /* double dollar */
- if (size > 1 && data[1] == '$')
- return parse_math(ob, doc, data, offset, size, "$$", 2, 1);
+ /* double dollar */
+ if (size > 1 && data[1] == '$')
+ return parse_math(ob, doc, data, offset, size, "$$", 2, 1);
- /* single dollar allowed only with MATH_EXPLICIT flag */
- if (doc->ext_flags & HOEDOWN_EXT_MATH_EXPLICIT)
- return parse_math(ob, doc, data, offset, size, "$", 1, 0);
+ /* single dollar allowed only with MATH_EXPLICIT flag */
+ if (doc->ext_flags & HOEDOWN_EXT_MATH_EXPLICIT)
+ return parse_math(ob, doc, data, offset, size, "$", 1, 0);
- return 0;
+ return 0;
}
/*********************************
@@ -1346,44 +1346,44 @@ char_math(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offse
static size_t
is_empty(const uint8_t *data, size_t size)
{
- size_t i;
+ size_t i;
- for (i = 0; i < size && data[i] != '\n'; i++)
- if (data[i] != ' ')
- return 0;
+ for (i = 0; i < size && data[i] != '\n'; i++)
+ if (data[i] != ' ')
+ return 0;
- return i + 1;
+ return i + 1;
}
/* is_hrule • returns whether a line is a horizontal rule */
static int
is_hrule(uint8_t *data, size_t size)
{
- size_t i = 0, n = 0;
- uint8_t c;
+ size_t i = 0, n = 0;
+ uint8_t c;
- /* skipping initial spaces */
- if (size < 3) return 0;
- if (data[0] == ' ') { i++;
- if (data[1] == ' ') { i++;
- if (data[2] == ' ') { i++; } } }
+ /* skipping initial spaces */
+ if (size < 3) return 0;
+ if (data[0] == ' ') { i++;
+ if (data[1] == ' ') { i++;
+ if (data[2] == ' ') { i++; } } }
- /* looking at the hrule uint8_t */
- if (i + 2 >= size
- || (data[i] != '*' && data[i] != '-' && data[i] != '_'))
- return 0;
- c = data[i];
+ /* looking at the hrule uint8_t */
+ if (i + 2 >= size
+ || (data[i] != '*' && data[i] != '-' && data[i] != '_'))
+ return 0;
+ c = data[i];
- /* the whole line must be the char or space */
- while (i < size && data[i] != '\n') {
- if (data[i] == c) n++;
- else if (data[i] != ' ')
- return 0;
+ /* the whole line must be the char or space */
+ while (i < size && data[i] != '\n') {
+ if (data[i] == c) n++;
+ else if (data[i] != ' ')
+ return 0;
- i++;
- }
+ i++;
+ }
- return n >= 3;
+ return n >= 3;
}
/* check if a line is a code fence; return the
@@ -1392,239 +1392,239 @@ is_hrule(uint8_t *data, size_t size)
static size_t
is_codefence(uint8_t *data, size_t size, size_t *width, uint8_t *chr)
{
- size_t i = 0, n = 1;
- uint8_t c;
+ size_t i = 0, n = 1;
+ uint8_t c;
- /* skipping initial spaces */
- if (size < 3)
- return 0;
+ /* skipping initial spaces */
+ if (size < 3)
+ return 0;
- if (data[0] == ' ') { i++;
- if (data[1] == ' ') { i++;
- if (data[2] == ' ') { i++; } } }
+ if (data[0] == ' ') { i++;
+ if (data[1] == ' ') { i++;
+ if (data[2] == ' ') { i++; } } }
- /* looking at the hrule uint8_t */
- c = data[i];
- if (i + 2 >= size || !(c=='~' || c=='`'))
- return 0;
+ /* looking at the hrule uint8_t */
+ c = data[i];
+ if (i + 2 >= size || !(c=='~' || c=='`'))
+ return 0;
- /* the fence must be that same character */
- while (++i < size && data[i] == c)
- ++n;
+ /* the fence must be that same character */
+ while (++i < size && data[i] == c)
+ ++n;
- if (n < 3)
- return 0;
+ if (n < 3)
+ return 0;
- if (width) *width = n;
- if (chr) *chr = c;
- return i;
+ if (width) *width = n;
+ if (chr) *chr = c;
+ return i;
}
/* expects single line, checks if it's a codefence and extracts language */
static size_t
parse_codefence(uint8_t *data, size_t size, hoedown_buffer *lang, size_t *width, uint8_t *chr)
{
- size_t i, w, lang_start;
+ size_t i, w, lang_start;
- i = w = is_codefence(data, size, width, chr);
- if (i == 0)
- return 0;
+ i = w = is_codefence(data, size, width, chr);
+ if (i == 0)
+ return 0;
- while (i < size && _isspace(data[i]))
- i++;
+ while (i < size && _isspace(data[i]))
+ i++;
- lang_start = i;
+ lang_start = i;
- while (i < size && !_isspace(data[i]))
- i++;
+ while (i < size && !_isspace(data[i]))
+ i++;
- lang->data = data + lang_start;
- lang->size = i - lang_start;
+ lang->data = data + lang_start;
+ lang->size = i - lang_start;
- /* Avoid parsing a codespan as a fence */
- i = lang_start + 2;
- while (i < size && !(data[i] == *chr && data[i-1] == *chr && data[i-2] == *chr)) i++;
- if (i < size) return 0;
+ /* Avoid parsing a codespan as a fence */
+ i = lang_start + 2;
+ while (i < size && !(data[i] == *chr && data[i-1] == *chr && data[i-2] == *chr)) i++;
+ if (i < size) return 0;
- return w;
+ return w;
}
/* is_atxheader • returns whether the line is a hash-prefixed header */
static int
is_atxheader(hoedown_document *doc, uint8_t *data, size_t size)
{
- if (data[0] != '#')
- return 0;
+ if (data[0] != '#')
+ return 0;
- if (doc->ext_flags & HOEDOWN_EXT_SPACE_HEADERS) {
- size_t level = 0;
+ if (doc->ext_flags & HOEDOWN_EXT_SPACE_HEADERS) {
+ size_t level = 0;
- while (level < size && level < 6 && data[level] == '#')
- level++;
+ while (level < size && level < 6 && data[level] == '#')
+ level++;
- if (level < size && data[level] != ' ')
- return 0;
- }
+ if (level < size && data[level] != ' ')
+ return 0;
+ }
- return 1;
+ return 1;
}
/* is_headerline • returns whether the line is a setext-style hdr underline */
static int
is_headerline(uint8_t *data, size_t size)
{
- size_t i = 0;
+ size_t i = 0;
- /* test of level 1 header */
- if (data[i] == '=') {
- for (i = 1; i < size && data[i] == '='; i++);
- while (i < size && data[i] == ' ') i++;
- return (i >= size || data[i] == '\n') ? 1 : 0; }
+ /* test of level 1 header */
+ if (data[i] == '=') {
+ for (i = 1; i < size && data[i] == '='; i++);
+ while (i < size && data[i] == ' ') i++;
+ return (i >= size || data[i] == '\n') ? 1 : 0; }
- /* test of level 2 header */
- if (data[i] == '-') {
- for (i = 1; i < size && data[i] == '-'; i++);
- while (i < size && data[i] == ' ') i++;
- return (i >= size || data[i] == '\n') ? 2 : 0; }
+ /* test of level 2 header */
+ if (data[i] == '-') {
+ for (i = 1; i < size && data[i] == '-'; i++);
+ while (i < size && data[i] == ' ') i++;
+ return (i >= size || data[i] == '\n') ? 2 : 0; }
- return 0;
+ return 0;
}
static int
is_next_headerline(uint8_t *data, size_t size)
{
- size_t i = 0;
+ size_t i = 0;
- while (i < size && data[i] != '\n')
- i++;
+ while (i < size && data[i] != '\n')
+ i++;
- if (++i >= size)
- return 0;
+ if (++i >= size)
+ return 0;
- return is_headerline(data + i, size - i);
+ return is_headerline(data + i, size - i);
}
/* prefix_quote • returns blockquote prefix length */
static size_t
prefix_quote(uint8_t *data, size_t size)
{
- size_t i = 0;
- if (i < size && data[i] == ' ') i++;
- if (i < size && data[i] == ' ') i++;
- if (i < size && data[i] == ' ') i++;
+ size_t i = 0;
+ if (i < size && data[i] == ' ') i++;
+ if (i < size && data[i] == ' ') i++;
+ if (i < size && data[i] == ' ') i++;
- if (i < size && data[i] == '>') {
- if (i + 1 < size && data[i + 1] == ' ')
- return i + 2;
+ if (i < size && data[i] == '>') {
+ if (i + 1 < size && data[i + 1] == ' ')
+ return i + 2;
- return i + 1;
- }
+ return i + 1;
+ }
- return 0;
+ return 0;
}
/* prefix_code • returns prefix length for block code*/
static size_t
prefix_code(uint8_t *data, size_t size)
{
- if (size > 3 && data[0] == ' ' && data[1] == ' '
- && data[2] == ' ' && data[3] == ' ') return 4;
+ if (size > 3 && data[0] == ' ' && data[1] == ' '
+ && data[2] == ' ' && data[3] == ' ') return 4;
- return 0;
+ return 0;
}
/* prefix_oli • returns ordered list item prefix */
static size_t
prefix_oli(uint8_t *data, size_t size)
{
- size_t i = 0;
+ size_t i = 0;
- if (i < size && data[i] == ' ') i++;
- if (i < size && data[i] == ' ') i++;
- if (i < size && data[i] == ' ') i++;
+ if (i < size && data[i] == ' ') i++;
+ if (i < size && data[i] == ' ') i++;
+ if (i < size && data[i] == ' ') i++;
- if (i >= size || data[i] < '0' || data[i] > '9')
- return 0;
+ if (i >= size || data[i] < '0' || data[i] > '9')
+ return 0;
- while (i < size && data[i] >= '0' && data[i] <= '9')
- i++;
+ while (i < size && data[i] >= '0' && data[i] <= '9')
+ i++;
- if (i + 1 >= size || data[i] != '.' || data[i + 1] != ' ')
- return 0;
+ if (i + 1 >= size || data[i] != '.' || data[i + 1] != ' ')
+ return 0;
- if (is_next_headerline(data + i, size - i))
- return 0;
+ if (is_next_headerline(data + i, size - i))
+ return 0;
- return i + 2;
+ return i + 2;
}
/* prefix_uli • returns ordered list item prefix */
static size_t
prefix_uli(uint8_t *data, size_t size)
{
- size_t i = 0;
+ size_t i = 0;
- if (i < size && data[i] == ' ') i++;
- if (i < size && data[i] == ' ') i++;
- if (i < size && data[i] == ' ') i++;
+ if (i < size && data[i] == ' ') i++;
+ if (i < size && data[i] == ' ') i++;
+ if (i < size && data[i] == ' ') i++;
- if (i + 1 >= size ||
- (data[i] != '*' && data[i] != '+' && data[i] != '-') ||
- data[i + 1] != ' ')
- return 0;
+ if (i + 1 >= size ||
+ (data[i] != '*' && data[i] != '+' && data[i] != '-') ||
+ data[i + 1] != ' ')
+ return 0;
- if (is_next_headerline(data + i, size - i))
- return 0;
+ if (is_next_headerline(data + i, size - i))
+ return 0;
- return i + 2;
+ return i + 2;
}
/* parse_block • parsing of one block, returning next uint8_t to parse */
static void parse_block(hoedown_buffer *ob, hoedown_document *doc,
- uint8_t *data, size_t size);
+ uint8_t *data, size_t size);
/* parse_blockquote • handles parsing of a blockquote fragment */
static size_t
parse_blockquote(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size)
{
- size_t beg, end = 0, pre, work_size = 0;
- uint8_t *work_data = 0;
- hoedown_buffer *out = 0;
+ size_t beg, end = 0, pre, work_size = 0;
+ uint8_t *work_data = 0;
+ hoedown_buffer *out = 0;
- out = newbuf(doc, BUFFER_BLOCK);
- beg = 0;
- while (beg < size) {
- for (end = beg + 1; end < size && data[end - 1] != '\n'; end++);
+ out = newbuf(doc, BUFFER_BLOCK);
+ beg = 0;
+ while (beg < size) {
+ for (end = beg + 1; end < size && data[end - 1] != '\n'; end++);
- pre = prefix_quote(data + beg, end - beg);
+ pre = prefix_quote(data + beg, end - beg);
- if (pre)
- beg += pre; /* skipping prefix */
+ if (pre)
+ beg += pre; /* skipping prefix */
- /* empty line followed by non-quote line */
- else if (is_empty(data + beg, end - beg) &&
- (end >= size || (prefix_quote(data + end, size - end) == 0 &&
- !is_empty(data + end, size - end))))
- break;
+ /* empty line followed by non-quote line */
+ else if (is_empty(data + beg, end - beg) &&
+ (end >= size || (prefix_quote(data + end, size - end) == 0 &&
+ !is_empty(data + end, size - end))))
+ break;
- if (beg < end) { /* copy into the in-place working buffer */
- /* hoedown_buffer_put(work, data + beg, end - beg); */
- if (!work_data)
- work_data = data + beg;
- else if (data + beg != work_data + work_size)
- memmove(work_data + work_size, data + beg, end - beg);
- work_size += end - beg;
- }
- beg = end;
- }
+ if (beg < end) { /* copy into the in-place working buffer */
+ /* hoedown_buffer_put(work, data + beg, end - beg); */
+ if (!work_data)
+ work_data = data + beg;
+ else if (data + beg != work_data + work_size)
+ memmove(work_data + work_size, data + beg, end - beg);
+ work_size += end - beg;
+ }
+ beg = end;
+ }
- parse_block(out, doc, work_data, work_size);
- if (doc->md.blockquote)
- doc->md.blockquote(ob, out, &doc->data);
- popbuf(doc, BUFFER_BLOCK);
- return end;
+ parse_block(out, doc, work_data, work_size);
+ if (doc->md.blockquote)
+ doc->md.blockquote(ob, out, &doc->data);
+ popbuf(doc, BUFFER_BLOCK);
+ return end;
}
static size_t
@@ -1634,301 +1634,301 @@ parse_htmlblock(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t
static size_t
parse_paragraph(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size)
{
- hoedown_buffer work = { NULL, 0, 0, 0, NULL, NULL, NULL };
- size_t i = 0, end = 0;
- int level = 0;
+ hoedown_buffer work = { NULL, 0, 0, 0, NULL, NULL, NULL };
+ size_t i = 0, end = 0;
+ int level = 0;
- work.data = data;
+ work.data = data;
- while (i < size) {
- for (end = i + 1; end < size && data[end - 1] != '\n'; end++) /* empty */;
+ while (i < size) {
+ for (end = i + 1; end < size && data[end - 1] != '\n'; end++) /* empty */;
- if (is_empty(data + i, size - i))
- break;
+ if (is_empty(data + i, size - i))
+ break;
- if ((level = is_headerline(data + i, size - i)) != 0)
- break;
+ if ((level = is_headerline(data + i, size - i)) != 0)
+ break;
- if (is_atxheader(doc, data + i, size - i) ||
- is_hrule(data + i, size - i) ||
- prefix_quote(data + i, size - i)) {
- end = i;
- break;
- }
+ if (is_atxheader(doc, data + i, size - i) ||
+ is_hrule(data + i, size - i) ||
+ prefix_quote(data + i, size - i)) {
+ end = i;
+ break;
+ }
- i = end;
- }
+ i = end;
+ }
- work.size = i;
- while (work.size && data[work.size - 1] == '\n')
- work.size--;
+ work.size = i;
+ while (work.size && data[work.size - 1] == '\n')
+ work.size--;
- if (!level) {
- hoedown_buffer *tmp = newbuf(doc, BUFFER_BLOCK);
- parse_inline(tmp, doc, work.data, work.size);
- if (doc->md.paragraph)
- doc->md.paragraph(ob, tmp, &doc->data);
- popbuf(doc, BUFFER_BLOCK);
- } else {
- hoedown_buffer *header_work;
+ if (!level) {
+ hoedown_buffer *tmp = newbuf(doc, BUFFER_BLOCK);
+ parse_inline(tmp, doc, work.data, work.size);
+ if (doc->md.paragraph)
+ doc->md.paragraph(ob, tmp, &doc->data);
+ popbuf(doc, BUFFER_BLOCK);
+ } else {
+ hoedown_buffer *header_work;
- if (work.size) {
- size_t beg;
- i = work.size;
- work.size -= 1;
+ if (work.size) {
+ size_t beg;
+ i = work.size;
+ work.size -= 1;
- while (work.size && data[work.size] != '\n')
- work.size -= 1;
+ while (work.size && data[work.size] != '\n')
+ work.size -= 1;
- beg = work.size + 1;
- while (work.size && data[work.size - 1] == '\n')
- work.size -= 1;
+ beg = work.size + 1;
+ while (work.size && data[work.size - 1] == '\n')
+ work.size -= 1;
- if (work.size > 0) {
- hoedown_buffer *tmp = newbuf(doc, BUFFER_BLOCK);
- parse_inline(tmp, doc, work.data, work.size);
+ if (work.size > 0) {
+ hoedown_buffer *tmp = newbuf(doc, BUFFER_BLOCK);
+ parse_inline(tmp, doc, work.data, work.size);
- if (doc->md.paragraph)
- doc->md.paragraph(ob, tmp, &doc->data);
+ if (doc->md.paragraph)
+ doc->md.paragraph(ob, tmp, &doc->data);
- popbuf(doc, BUFFER_BLOCK);
- work.data += beg;
- work.size = i - beg;
- }
- else work.size = i;
- }
+ popbuf(doc, BUFFER_BLOCK);
+ work.data += beg;
+ work.size = i - beg;
+ }
+ else work.size = i;
+ }
- header_work = newbuf(doc, BUFFER_SPAN);
- parse_inline(header_work, doc, work.data, work.size);
+ header_work = newbuf(doc, BUFFER_SPAN);
+ parse_inline(header_work, doc, work.data, work.size);
- if (doc->md.header)
- doc->md.header(ob, header_work, (int)level, &doc->data);
+ if (doc->md.header)
+ doc->md.header(ob, header_work, (int)level, &doc->data);
- popbuf(doc, BUFFER_SPAN);
- }
+ popbuf(doc, BUFFER_SPAN);
+ }
- return end;
+ return end;
}
/* parse_fencedcode • handles parsing of a block-level code fragment */
static size_t
parse_fencedcode(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size)
{
- hoedown_buffer text = { 0, 0, 0, 0, NULL, NULL, NULL };
- hoedown_buffer lang = { 0, 0, 0, 0, NULL, NULL, NULL };
- size_t i = 0, text_start, line_start;
- size_t w, w2;
- size_t width, width2;
- uint8_t chr, chr2;
+ hoedown_buffer text = { 0, 0, 0, 0, NULL, NULL, NULL };
+ hoedown_buffer lang = { 0, 0, 0, 0, NULL, NULL, NULL };
+ size_t i = 0, text_start, line_start;
+ size_t w, w2;
+ size_t width, width2;
+ uint8_t chr, chr2;
- /* parse codefence line */
- while (i < size && data[i] != '\n')
- i++;
+ /* parse codefence line */
+ while (i < size && data[i] != '\n')
+ i++;
- w = parse_codefence(data, i, &lang, &width, &chr);
- if (!w)
- return 0;
+ w = parse_codefence(data, i, &lang, &width, &chr);
+ if (!w)
+ return 0;
- /* search for end */
- i++;
- text_start = i;
- while ((line_start = i) < size) {
- while (i < size && data[i] != '\n')
- i++;
+ /* search for end */
+ i++;
+ text_start = i;
+ while ((line_start = i) < size) {
+ while (i < size && data[i] != '\n')
+ i++;
- w2 = is_codefence(data + line_start, i - line_start, &width2, &chr2);
- if (w == w2 && width == width2 && chr == chr2 &&
- is_empty(data + (line_start+w), i - (line_start+w)))
- break;
+ w2 = is_codefence(data + line_start, i - line_start, &width2, &chr2);
+ if (w == w2 && width == width2 && chr == chr2 &&
+ is_empty(data + (line_start+w), i - (line_start+w)))
+ break;
- i++;
- }
+ i++;
+ }
- text.data = data + text_start;
- text.size = line_start - text_start;
+ text.data = data + text_start;
+ text.size = line_start - text_start;
- if (doc->md.blockcode)
- doc->md.blockcode(ob, text.size ? &text : NULL, lang.size ? &lang : NULL, &doc->data);
+ if (doc->md.blockcode)
+ doc->md.blockcode(ob, text.size ? &text : NULL, lang.size ? &lang : NULL, &doc->data);
- return i;
+ return i;
}
static size_t
parse_blockcode(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size)
{
- size_t beg, end, pre;
- hoedown_buffer *work = 0;
+ size_t beg, end, pre;
+ hoedown_buffer *work = 0;
- work = newbuf(doc, BUFFER_BLOCK);
+ work = newbuf(doc, BUFFER_BLOCK);
- beg = 0;
- while (beg < size) {
- for (end = beg + 1; end < size && data[end - 1] != '\n'; end++) {};
- pre = prefix_code(data + beg, end - beg);
+ beg = 0;
+ while (beg < size) {
+ for (end = beg + 1; end < size && data[end - 1] != '\n'; end++) {};
+ pre = prefix_code(data + beg, end - beg);
- if (pre)
- beg += pre; /* skipping prefix */
- else if (!is_empty(data + beg, end - beg))
- /* non-empty non-prefixed line breaks the pre */
- break;
+ if (pre)
+ beg += pre; /* skipping prefix */
+ else if (!is_empty(data + beg, end - beg))
+ /* non-empty non-prefixed line breaks the pre */
+ break;
- if (beg < end) {
- /* verbatim copy to the working buffer,
- escaping entities */
- if (is_empty(data + beg, end - beg))
- hoedown_buffer_putc(work, '\n');
- else hoedown_buffer_put(work, data + beg, end - beg);
- }
- beg = end;
- }
+ if (beg < end) {
+ /* verbatim copy to the working buffer,
+ escaping entities */
+ if (is_empty(data + beg, end - beg))
+ hoedown_buffer_putc(work, '\n');
+ else hoedown_buffer_put(work, data + beg, end - beg);
+ }
+ beg = end;
+ }
- while (work->size && work->data[work->size - 1] == '\n')
- work->size -= 1;
+ while (work->size && work->data[work->size - 1] == '\n')
+ work->size -= 1;
- hoedown_buffer_putc(work, '\n');
+ hoedown_buffer_putc(work, '\n');
- if (doc->md.blockcode)
- doc->md.blockcode(ob, work, NULL, &doc->data);
+ if (doc->md.blockcode)
+ doc->md.blockcode(ob, work, NULL, &doc->data);
- popbuf(doc, BUFFER_BLOCK);
- return beg;
+ popbuf(doc, BUFFER_BLOCK);
+ return beg;
}
/* parse_listitem • parsing of a single list item */
-/* assuming initial prefix is already removed */
+/* assuming initial prefix is already removed */
static size_t
parse_listitem(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size, hoedown_list_flags *flags)
{
- hoedown_buffer *work = 0, *inter = 0;
- size_t beg = 0, end, pre, sublist = 0, orgpre = 0, i;
- int in_empty = 0, has_inside_empty = 0, in_fence = 0;
-
- /* keeping track of the first indentation prefix */
- while (orgpre < 3 && orgpre < size && data[orgpre] == ' ')
- orgpre++;
-
- beg = prefix_uli(data, size);
- if (!beg)
- beg = prefix_oli(data, size);
-
- if (!beg)
- return 0;
-
- /* skipping to the beginning of the following line */
- end = beg;
- while (end < size && data[end - 1] != '\n')
- end++;
-
- /* getting working buffers */
- work = newbuf(doc, BUFFER_SPAN);
- inter = newbuf(doc, BUFFER_SPAN);
-
- /* putting the first line into the working buffer */
- hoedown_buffer_put(work, data + beg, end - beg);
- beg = end;
-
- /* process the following lines */
- while (beg < size) {
- size_t has_next_uli = 0, has_next_oli = 0;
-
- end++;
-
- while (end < size && data[end - 1] != '\n')
- end++;
-
- /* process an empty line */
- if (is_empty(data + beg, end - beg)) {
- in_empty = 1;
- beg = end;
- continue;
- }
-
- /* calculating the indentation */
- i = 0;
- while (i < 4 && beg + i < end && data[beg + i] == ' ')
- i++;
-
- pre = i;
-
- if (doc->ext_flags & HOEDOWN_EXT_FENCED_CODE) {
- if (is_codefence(data + beg + i, end - beg - i, NULL, NULL))
- in_fence = !in_fence;
- }
-
- /* Only check for new list items if we are **not** inside
- * a fenced code block */
- if (!in_fence) {
- has_next_uli = prefix_uli(data + beg + i, end - beg - i);
- has_next_oli = prefix_oli(data + beg + i, end - beg - i);
- }
-
- /* checking for a new item */
- if ((has_next_uli && !is_hrule(data + beg + i, end - beg - i)) || has_next_oli) {
- if (in_empty)
- has_inside_empty = 1;
-
- /* the following item must have the same (or less) indentation */
- if (pre <= orgpre) {
- /* if the following item has different list type, we end this list */
- if (in_empty && (
- ((*flags & HOEDOWN_LIST_ORDERED) && has_next_uli) ||
- (!(*flags & HOEDOWN_LIST_ORDERED) && has_next_oli)))
- *flags |= HOEDOWN_LI_END;
-
- break;
- }
-
- if (!sublist)
- sublist = work->size;
- }
- /* joining only indented stuff after empty lines;
- * note that now we only require 1 space of indentation
- * to continue a list */
- else if (in_empty && pre == 0) {
- *flags |= HOEDOWN_LI_END;
- break;
- }
-
- if (in_empty) {
- hoedown_buffer_putc(work, '\n');
- has_inside_empty = 1;
- in_empty = 0;
- }
-
- /* adding the line without prefix into the working buffer */
- hoedown_buffer_put(work, data + beg + i, end - beg - i);
- beg = end;
- }
-
- /* render of li contents */
- if (has_inside_empty)
- *flags |= HOEDOWN_LI_BLOCK;
-
- if (*flags & HOEDOWN_LI_BLOCK) {
- /* intermediate render of block li */
- if (sublist && sublist < work->size) {
- parse_block(inter, doc, work->data, sublist);
- parse_block(inter, doc, work->data + sublist, work->size - sublist);
- }
- else
- parse_block(inter, doc, work->data, work->size);
- } else {
- /* intermediate render of inline li */
- if (sublist && sublist < work->size) {
- parse_inline(inter, doc, work->data, sublist);
- parse_block(inter, doc, work->data + sublist, work->size - sublist);
- }
- else
- parse_inline(inter, doc, work->data, work->size);
- }
-
- /* render of li itself */
- if (doc->md.listitem)
- doc->md.listitem(ob, inter, *flags, &doc->data);
-
- popbuf(doc, BUFFER_SPAN);
- popbuf(doc, BUFFER_SPAN);
- return beg;
+ hoedown_buffer *work = 0, *inter = 0;
+ size_t beg = 0, end, pre, sublist = 0, orgpre = 0, i;
+ int in_empty = 0, has_inside_empty = 0, in_fence = 0;
+
+ /* keeping track of the first indentation prefix */
+ while (orgpre < 3 && orgpre < size && data[orgpre] == ' ')
+ orgpre++;
+
+ beg = prefix_uli(data, size);
+ if (!beg)
+ beg = prefix_oli(data, size);
+
+ if (!beg)
+ return 0;
+
+ /* skipping to the beginning of the following line */
+ end = beg;
+ while (end < size && data[end - 1] != '\n')
+ end++;
+
+ /* getting working buffers */
+ work = newbuf(doc, BUFFER_SPAN);
+ inter = newbuf(doc, BUFFER_SPAN);
+
+ /* putting the first line into the working buffer */
+ hoedown_buffer_put(work, data + beg, end - beg);
+ beg = end;
+
+ /* process the following lines */
+ while (beg < size) {
+ size_t has_next_uli = 0, has_next_oli = 0;
+
+ end++;
+
+ while (end < size && data[end - 1] != '\n')
+ end++;
+
+ /* process an empty line */
+ if (is_empty(data + beg, end - beg)) {
+ in_empty = 1;
+ beg = end;
+ continue;
+ }
+
+ /* calculating the indentation */
+ i = 0;
+ while (i < 4 && beg + i < end && data[beg + i] == ' ')
+ i++;
+
+ pre = i;
+
+ if (doc->ext_flags & HOEDOWN_EXT_FENCED_CODE) {
+ if (is_codefence(data + beg + i, end - beg - i, NULL, NULL))
+ in_fence = !in_fence;
+ }
+
+ /* Only check for new list items if we are **not** inside
+ * a fenced code block */
+ if (!in_fence) {
+ has_next_uli = prefix_uli(data + beg + i, end - beg - i);
+ has_next_oli = prefix_oli(data + beg + i, end - beg - i);
+ }
+
+ /* checking for a new item */
+ if ((has_next_uli && !is_hrule(data + beg + i, end - beg - i)) || has_next_oli) {
+ if (in_empty)
+ has_inside_empty = 1;
+
+ /* the following item must have the same (or less) indentation */
+ if (pre <= orgpre) {
+ /* if the following item has different list type, we end this list */
+ if (in_empty && (
+ ((*flags & HOEDOWN_LIST_ORDERED) && has_next_uli) ||
+ (!(*flags & HOEDOWN_LIST_ORDERED) && has_next_oli)))
+ *flags |= HOEDOWN_LI_END;
+
+ break;
+ }
+
+ if (!sublist)
+ sublist = work->size;
+ }
+ /* joining only indented stuff after empty lines;
+ * note that now we only require 1 space of indentation
+ * to continue a list */
+ else if (in_empty && pre == 0) {
+ *flags |= HOEDOWN_LI_END;
+ break;
+ }
+
+ if (in_empty) {
+ hoedown_buffer_putc(work, '\n');
+ has_inside_empty = 1;
+ in_empty = 0;
+ }
+
+ /* adding the line without prefix into the working buffer */
+ hoedown_buffer_put(work, data + beg + i, end - beg - i);
+ beg = end;
+ }
+
+ /* render of li contents */
+ if (has_inside_empty)
+ *flags |= HOEDOWN_LI_BLOCK;
+
+ if (*flags & HOEDOWN_LI_BLOCK) {
+ /* intermediate render of block li */
+ if (sublist && sublist < work->size) {
+ parse_block(inter, doc, work->data, sublist);
+ parse_block(inter, doc, work->data + sublist, work->size - sublist);
+ }
+ else
+ parse_block(inter, doc, work->data, work->size);
+ } else {
+ /* intermediate render of inline li */
+ if (sublist && sublist < work->size) {
+ parse_inline(inter, doc, work->data, sublist);
+ parse_block(inter, doc, work->data + sublist, work->size - sublist);
+ }
+ else
+ parse_inline(inter, doc, work->data, work->size);
+ }
+
+ /* render of li itself */
+ if (doc->md.listitem)
+ doc->md.listitem(ob, inter, *flags, &doc->data);
+
+ popbuf(doc, BUFFER_SPAN);
+ popbuf(doc, BUFFER_SPAN);
+ return beg;
}
@@ -1936,460 +1936,460 @@ parse_listitem(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t
static size_t
parse_list(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size, hoedown_list_flags flags)
{
- hoedown_buffer *work = 0;
- size_t i = 0, j;
+ hoedown_buffer *work = 0;
+ size_t i = 0, j;
- work = newbuf(doc, BUFFER_BLOCK);
+ work = newbuf(doc, BUFFER_BLOCK);
- while (i < size) {
- j = parse_listitem(work, doc, data + i, size - i, &flags);
- i += j;
+ while (i < size) {
+ j = parse_listitem(work, doc, data + i, size - i, &flags);
+ i += j;
- if (!j || (flags & HOEDOWN_LI_END))
- break;
- }
+ if (!j || (flags & HOEDOWN_LI_END))
+ break;
+ }
- if (doc->md.list)
- doc->md.list(ob, work, flags, &doc->data);
- popbuf(doc, BUFFER_BLOCK);
- return i;
+ if (doc->md.list)
+ doc->md.list(ob, work, flags, &doc->data);
+ popbuf(doc, BUFFER_BLOCK);
+ return i;
}
/* parse_atxheader • parsing of atx-style headers */
static size_t
parse_atxheader(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size)
{
- size_t level = 0;
- size_t i, end, skip;
+ size_t level = 0;
+ size_t i, end, skip;
- while (level < size && level < 6 && data[level] == '#')
- level++;
+ while (level < size && level < 6 && data[level] == '#')
+ level++;
- for (i = level; i < size && data[i] == ' '; i++);
+ for (i = level; i < size && data[i] == ' '; i++);
- for (end = i; end < size && data[end] != '\n'; end++);
- skip = end;
+ for (end = i; end < size && data[end] != '\n'; end++);
+ skip = end;
- while (end && data[end - 1] == '#')
- end--;
+ while (end && data[end - 1] == '#')
+ end--;
- while (end && data[end - 1] == ' ')
- end--;
+ while (end && data[end - 1] == ' ')
+ end--;
- if (end > i) {
- hoedown_buffer *work = newbuf(doc, BUFFER_SPAN);
+ if (end > i) {
+ hoedown_buffer *work = newbuf(doc, BUFFER_SPAN);
- parse_inline(work, doc, data + i, end - i);
+ parse_inline(work, doc, data + i, end - i);
- if (doc->md.header)
- doc->md.header(ob, work, (int)level, &doc->data);
+ if (doc->md.header)
+ doc->md.header(ob, work, (int)level, &doc->data);
- popbuf(doc, BUFFER_SPAN);
- }
+ popbuf(doc, BUFFER_SPAN);
+ }
- return skip;
+ return skip;
}
/* parse_footnote_def • parse a single footnote definition */
static void
parse_footnote_def(hoedown_buffer *ob, hoedown_document *doc, unsigned int num, uint8_t *data, size_t size)
{
- hoedown_buffer *work = 0;
- work = newbuf(doc, BUFFER_SPAN);
+ hoedown_buffer *work = 0;
+ work = newbuf(doc, BUFFER_SPAN);
- parse_block(work, doc, data, size);
+ parse_block(work, doc, data, size);
- if (doc->md.footnote_def)
- doc->md.footnote_def(ob, work, num, &doc->data);
- popbuf(doc, BUFFER_SPAN);
+ if (doc->md.footnote_def)
+ doc->md.footnote_def(ob, work, num, &doc->data);
+ popbuf(doc, BUFFER_SPAN);
}
/* parse_footnote_list • render the contents of the footnotes */
static void
parse_footnote_list(hoedown_buffer *ob, hoedown_document *doc, struct footnote_list *footnotes)
{
- hoedown_buffer *work = 0;
- struct footnote_item *item;
- struct footnote_ref *ref;
+ hoedown_buffer *work = 0;
+ struct footnote_item *item;
+ struct footnote_ref *ref;
- if (footnotes->count == 0)
- return;
+ if (footnotes->count == 0)
+ return;
- work = newbuf(doc, BUFFER_BLOCK);
+ work = newbuf(doc, BUFFER_BLOCK);
- item = footnotes->head;
- while (item) {
- ref = item->ref;
- parse_footnote_def(work, doc, ref->num, ref->contents->data, ref->contents->size);
- item = item->next;
- }
+ item = footnotes->head;
+ while (item) {
+ ref = item->ref;
+ parse_footnote_def(work, doc, ref->num, ref->contents->data, ref->contents->size);
+ item = item->next;
+ }
- if (doc->md.footnotes)
- doc->md.footnotes(ob, work, &doc->data);
- popbuf(doc, BUFFER_BLOCK);
+ if (doc->md.footnotes)
+ doc->md.footnotes(ob, work, &doc->data);
+ popbuf(doc, BUFFER_BLOCK);
}
/* htmlblock_is_end • check for end of HTML block : </tag>( *)\n */
-/* returns tag length on match, 0 otherwise */
-/* assumes data starts with "<" */
+/* returns tag length on match, 0 otherwise */
+/* assumes data starts with "<" */
static size_t
htmlblock_is_end(
- const char *tag,
- size_t tag_len,
- hoedown_document *doc,
- uint8_t *data,
- size_t size)
+ const char *tag,
+ size_t tag_len,
+ hoedown_document *doc,
+ uint8_t *data,
+ size_t size)
{
- size_t i = tag_len + 3, w;
+ size_t i = tag_len + 3, w;
- /* try to match the end tag */
- /* note: we're not considering tags like "</tag >" which are still valid */
- if (i > size ||
- data[1] != '/' ||
- strncasecmp((char *)data + 2, tag, tag_len) != 0 ||
- data[tag_len + 2] != '>')
- return 0;
+ /* try to match the end tag */
+ /* note: we're not considering tags like "</tag >" which are still valid */
+ if (i > size ||
+ data[1] != '/' ||
+ strncasecmp((char *)data + 2, tag, tag_len) != 0 ||
+ data[tag_len + 2] != '>')
+ return 0;
- /* rest of the line must be empty */
- if ((w = is_empty(data + i, size - i)) == 0 && i < size)
- return 0;
+ /* rest of the line must be empty */
+ if ((w = is_empty(data + i, size - i)) == 0 && i < size)
+ return 0;
- return i + w;
+ return i + w;
}
/* htmlblock_find_end • try to find HTML block ending tag */
-/* returns the length on match, 0 otherwise */
+/* returns the length on match, 0 otherwise */
static size_t
htmlblock_find_end(
- const char *tag,
- size_t tag_len,
- hoedown_document *doc,
- uint8_t *data,
- size_t size)
+ const char *tag,
+ size_t tag_len,
+ hoedown_document *doc,
+ uint8_t *data,
+ size_t size)
{
- size_t i = 0, w;
+ size_t i = 0, w;
- while (1) {
- while (i < size && data[i] != '<') i++;
- if (i >= size) return 0;
+ while (1) {
+ while (i < size && data[i] != '<') i++;
+ if (i >= size) return 0;
- w = htmlblock_is_end(tag, tag_len, doc, data + i, size - i);
- if (w) return i + w;
- i++;
- }
+ w = htmlblock_is_end(tag, tag_len, doc, data + i, size - i);
+ if (w) return i + w;
+ i++;
+ }
}
/* htmlblock_find_end_strict • try to find end of HTML block in strict mode */
-/* (it must be an unindented line, and have a blank line afterwads) */
-/* returns the length on match, 0 otherwise */
+/* (it must be an unindented line, and have a blank line afterwads) */
+/* returns the length on match, 0 otherwise */
static size_t
htmlblock_find_end_strict(
- const char *tag,
- size_t tag_len,
- hoedown_document *doc,
- uint8_t *data,
- size_t size)
+ const char *tag,
+ size_t tag_len,
+ hoedown_document *doc,
+ uint8_t *data,
+ size_t size)
{
- size_t i = 0, mark;
+ size_t i = 0, mark;
- while (1) {
- mark = i;
- while (i < size && data[i] != '\n') i++;
- if (i < size) i++;
- if (i == mark) return 0;
+ while (1) {
+ mark = i;
+ while (i < size && data[i] != '\n') i++;
+ if (i < size) i++;
+ if (i == mark) return 0;
- if (data[mark] == ' ' && mark > 0) continue;
- mark += htmlblock_find_end(tag, tag_len, doc, data + mark, i - mark);
- if (mark == i && (is_empty(data + i, size - i) || i >= size)) break;
- }
+ if (data[mark] == ' ' && mark > 0) continue;
+ mark += htmlblock_find_end(tag, tag_len, doc, data + mark, i - mark);
+ if (mark == i && (is_empty(data + i, size - i) || i >= size)) break;
+ }
- return i;
+ return i;
}
/* parse_htmlblock • parsing of inline HTML block */
static size_t
parse_htmlblock(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size, int do_render)
{
- hoedown_buffer work = { NULL, 0, 0, 0, NULL, NULL, NULL };
- size_t i, j = 0, tag_len, tag_end;
- const char *curtag = NULL;
+ hoedown_buffer work = { NULL, 0, 0, 0, NULL, NULL, NULL };
+ size_t i, j = 0, tag_len, tag_end;
+ const char *curtag = NULL;
- work.data = data;
+ work.data = data;
- /* identification of the opening tag */
- if (size < 2 || data[0] != '<')
- return 0;
+ /* identification of the opening tag */
+ if (size < 2 || data[0] != '<')
+ return 0;
- i = 1;
- while (i < size && data[i] != '>' && data[i] != ' ')
- i++;
+ i = 1;
+ while (i < size && data[i] != '>' && data[i] != ' ')
+ i++;
- if (i < size)
- curtag = hoedown_find_block_tag((char *)data + 1, (int)i - 1);
+ if (i < size)
+ curtag = hoedown_find_block_tag((char *)data + 1, (int)i - 1);
- /* handling of special cases */
- if (!curtag) {
+ /* handling of special cases */
+ if (!curtag) {
- /* HTML comment, laxist form */
- if (size > 5 && data[1] == '!' && data[2] == '-' && data[3] == '-') {
- i = 5;
+ /* HTML comment, laxist form */
+ if (size > 5 && data[1] == '!' && data[2] == '-' && data[3] == '-') {
+ i = 5;
- while (i < size && !(data[i - 2] == '-' && data[i - 1] == '-' && data[i] == '>'))
- i++;
+ while (i < size && !(data[i - 2] == '-' && data[i - 1] == '-' && data[i] == '>'))
+ i++;
- i++;
+ i++;
- if (i < size)
- j = is_empty(data + i, size - i);
+ if (i < size)
+ j = is_empty(data + i, size - i);
- if (j) {
- work.size = i + j;
- if (do_render && doc->md.blockhtml)
- doc->md.blockhtml(ob, &work, &doc->data);
- return work.size;
- }
- }
+ if (j) {
+ work.size = i + j;
+ if (do_render && doc->md.blockhtml)
+ doc->md.blockhtml(ob, &work, &doc->data);
+ return work.size;
+ }
+ }
- /* HR, which is the only self-closing block tag considered */
- if (size > 4 && (data[1] == 'h' || data[1] == 'H') && (data[2] == 'r' || data[2] == 'R')) {
- i = 3;
- while (i < size && data[i] != '>')
- i++;
+ /* HR, which is the only self-closing block tag considered */
+ if (size > 4 && (data[1] == 'h' || data[1] == 'H') && (data[2] == 'r' || data[2] == 'R')) {
+ i = 3;
+ while (i < size && data[i] != '>')
+ i++;
- if (i + 1 < size) {
- i++;
- j = is_empty(data + i, size - i);
- if (j) {
- work.size = i + j;
- if (do_render && doc->md.blockhtml)
- doc->md.blockhtml(ob, &work, &doc->data);
- return work.size;
- }
- }
- }
+ if (i + 1 < size) {
+ i++;
+ j = is_empty(data + i, size - i);
+ if (j) {
+ work.size = i + j;
+ if (do_render && doc->md.blockhtml)
+ doc->md.blockhtml(ob, &work, &doc->data);
+ return work.size;
+ }
+ }
+ }
- /* no special case recognised */
- return 0;
- }
+ /* no special case recognised */
+ return 0;
+ }
- /* looking for a matching closing tag in strict mode */
- tag_len = strlen(curtag);
- tag_end = htmlblock_find_end_strict(curtag, tag_len, doc, data, size);
+ /* looking for a matching closing tag in strict mode */
+ tag_len = strlen(curtag);
+ tag_end = htmlblock_find_end_strict(curtag, tag_len, doc, data, size);
- /* if not found, trying a second pass looking for indented match */
- /* but not if tag is "ins" or "del" (following original Markdown.pl) */
- if (!tag_end && strcmp(curtag, "ins") != 0 && strcmp(curtag, "del") != 0)
- tag_end = htmlblock_find_end(curtag, tag_len, doc, data, size);
+ /* if not found, trying a second pass looking for indented match */
+ /* but not if tag is "ins" or "del" (following original Markdown.pl) */
+ if (!tag_end && strcmp(curtag, "ins") != 0 && strcmp(curtag, "del") != 0)
+ tag_end = htmlblock_find_end(curtag, tag_len, doc, data, size);
- if (!tag_end)
- return 0;
+ if (!tag_end)
+ return 0;
- /* the end of the block has been found */
- work.size = tag_end;
- if (do_render && doc->md.blockhtml)
- doc->md.blockhtml(ob, &work, &doc->data);
+ /* the end of the block has been found */
+ work.size = tag_end;
+ if (do_render && doc->md.blockhtml)
+ doc->md.blockhtml(ob, &work, &doc->data);
- return tag_end;
+ return tag_end;
}
static void
parse_table_row(
- hoedown_buffer *ob,
- hoedown_document *doc,
- uint8_t *data,
- size_t size,
- size_t columns,
- hoedown_table_flags *col_data,
- hoedown_table_flags header_flag)
+ hoedown_buffer *ob,
+ hoedown_document *doc,
+ uint8_t *data,
+ size_t size,
+ size_t columns,
+ hoedown_table_flags *col_data,
+ hoedown_table_flags header_flag)
{
- size_t i = 0, col, len;
- hoedown_buffer *row_work = 0;
+ size_t i = 0, col, len;
+ hoedown_buffer *row_work = 0;
- if (!doc->md.table_cell || !doc->md.table_row)
- return;
+ if (!doc->md.table_cell || !doc->md.table_row)
+ return;
- row_work = newbuf(doc, BUFFER_SPAN);
+ row_work = newbuf(doc, BUFFER_SPAN);
- if (i < size && data[i] == '|')
- i++;
+ if (i < size && data[i] == '|')
+ i++;
- for (col = 0; col < columns && i < size; ++col) {
- size_t cell_start, cell_end;
- hoedown_buffer *cell_work;
+ for (col = 0; col < columns && i < size; ++col) {
+ size_t cell_start, cell_end;
+ hoedown_buffer *cell_work;
- cell_work = newbuf(doc, BUFFER_SPAN);
+ cell_work = newbuf(doc, BUFFER_SPAN);
- while (i < size && _isspace(data[i]))
- i++;
+ while (i < size && _isspace(data[i]))
+ i++;
- cell_start = i;
+ cell_start = i;
- len = find_emph_char(data + i, size - i, '|');
- i += len ? len : size - i;
+ len = find_emph_char(data + i, size - i, '|');
+ i += len ? len : size - i;
- cell_end = i - 1;
+ cell_end = i - 1;
- while (cell_end > cell_start && _isspace(data[cell_end]))
- cell_end--;
+ while (cell_end > cell_start && _isspace(data[cell_end]))
+ cell_end--;
- parse_inline(cell_work, doc, data + cell_start, 1 + cell_end - cell_start);
- doc->md.table_cell(row_work, cell_work, col_data[col] | header_flag, &doc->data);
+ parse_inline(cell_work, doc, data + cell_start, 1 + cell_end - cell_start);
+ doc->md.table_cell(row_work, cell_work, col_data[col] | header_flag, &doc->data);
- popbuf(doc, BUFFER_SPAN);
- i++;
- }
+ popbuf(doc, BUFFER_SPAN);
+ i++;
+ }
- for (; col < columns; ++col) {
- hoedown_buffer empty_cell = { 0, 0, 0, 0, NULL, NULL, NULL };
- doc->md.table_cell(row_work, &empty_cell, col_data[col] | header_flag, &doc->data);
- }
+ for (; col < columns; ++col) {
+ hoedown_buffer empty_cell = { 0, 0, 0, 0, NULL, NULL, NULL };
+ doc->md.table_cell(row_work, &empty_cell, col_data[col] | header_flag, &doc->data);
+ }
- doc->md.table_row(ob, row_work, &doc->data);
+ doc->md.table_row(ob, row_work, &doc->data);
- popbuf(doc, BUFFER_SPAN);
+ popbuf(doc, BUFFER_SPAN);
}
static size_t
parse_table_header(
- hoedown_buffer *ob,
- hoedown_document *doc,
- uint8_t *data,
- size_t size,
- size_t *columns,
- hoedown_table_flags **column_data)
+ hoedown_buffer *ob,
+ hoedown_document *doc,
+ uint8_t *data,
+ size_t size,
+ size_t *columns,
+ hoedown_table_flags **column_data)
{
- int pipes;
- size_t i = 0, col, header_end, under_end;
+ int pipes;
+ size_t i = 0, col, header_end, under_end;
- pipes = 0;
- while (i < size && data[i] != '\n')
- if (data[i++] == '|')
- pipes++;
+ pipes = 0;
+ while (i < size && data[i] != '\n')
+ if (data[i++] == '|')
+ pipes++;
- if (i == size || pipes == 0)
- return 0;
+ if (i == size || pipes == 0)
+ return 0;
- header_end = i;
+ header_end = i;
- while (header_end > 0 && _isspace(data[header_end - 1]))
- header_end--;
+ while (header_end > 0 && _isspace(data[header_end - 1]))
+ header_end--;
- if (data[0] == '|')
- pipes--;
+ if (data[0] == '|')
+ pipes--;
- if (header_end && data[header_end - 1] == '|')
- pipes--;
+ if (header_end && data[header_end - 1] == '|')
+ pipes--;
- if (pipes < 0)
- return 0;
+ if (pipes < 0)
+ return 0;
- *columns = pipes + 1;
- *column_data = hoedown_calloc(*columns, sizeof(hoedown_table_flags));
+ *columns = pipes + 1;
+ *column_data = hoedown_calloc(*columns, sizeof(hoedown_table_flags));
- /* Parse the header underline */
- i++;
- if (i < size && data[i] == '|')
- i++;
+ /* Parse the header underline */
+ i++;
+ if (i < size && data[i] == '|')
+ i++;
- under_end = i;
- while (under_end < size && data[under_end] != '\n')
- under_end++;
+ under_end = i;
+ while (under_end < size && data[under_end] != '\n')
+ under_end++;
- for (col = 0; col < *columns && i < under_end; ++col) {
- size_t dashes = 0;
+ for (col = 0; col < *columns && i < under_end; ++col) {
+ size_t dashes = 0;
- while (i < under_end && data[i] == ' ')
- i++;
+ while (i < under_end && data[i] == ' ')
+ i++;
- if (data[i] == ':') {
- i++; (*column_data)[col] |= HOEDOWN_TABLE_ALIGN_LEFT;
- dashes++;
- }
+ if (data[i] == ':') {
+ i++; (*column_data)[col] |= HOEDOWN_TABLE_ALIGN_LEFT;
+ dashes++;
+ }
- while (i < under_end && data[i] == '-') {
- i++; dashes++;
- }
+ while (i < under_end && data[i] == '-') {
+ i++; dashes++;
+ }
- if (i < under_end && data[i] == ':') {
- i++; (*column_data)[col] |= HOEDOWN_TABLE_ALIGN_RIGHT;
- dashes++;
- }
+ if (i < under_end && data[i] == ':') {
+ i++; (*column_data)[col] |= HOEDOWN_TABLE_ALIGN_RIGHT;
+ dashes++;
+ }
- while (i < under_end && data[i] == ' ')
- i++;
+ while (i < under_end && data[i] == ' ')
+ i++;
- if (i < under_end && data[i] != '|' && data[i] != '+')
- break;
+ if (i < under_end && data[i] != '|' && data[i] != '+')
+ break;
- if (dashes < 3)
- break;
+ if (dashes < 3)
+ break;
- i++;
- }
+ i++;
+ }
- if (col < *columns)
- return 0;
+ if (col < *columns)
+ return 0;
- parse_table_row(
- ob, doc, data,
- header_end,
- *columns,
- *column_data,
- HOEDOWN_TABLE_HEADER
- );
+ parse_table_row(
+ ob, doc, data,
+ header_end,
+ *columns,
+ *column_data,
+ HOEDOWN_TABLE_HEADER
+ );
- return under_end + 1;
+ return under_end + 1;
}
static size_t
parse_table(
- hoedown_buffer *ob,
- hoedown_document *doc,
- uint8_t *data,
- size_t size)
+ hoedown_buffer *ob,
+ hoedown_document *doc,
+ uint8_t *data,
+ size_t size)
{
- size_t i;
+ size_t i;
- hoedown_buffer *work = 0;
- hoedown_buffer *header_work = 0;
- hoedown_buffer *body_work = 0;
+ hoedown_buffer *work = 0;
+ hoedown_buffer *header_work = 0;
+ hoedown_buffer *body_work = 0;
- size_t columns;
- hoedown_table_flags *col_data = NULL;
+ size_t columns;
+ hoedown_table_flags *col_data = NULL;
- work = newbuf(doc, BUFFER_BLOCK);
- header_work = newbuf(doc, BUFFER_SPAN);
- body_work = newbuf(doc, BUFFER_BLOCK);
+ work = newbuf(doc, BUFFER_BLOCK);
+ header_work = newbuf(doc, BUFFER_SPAN);
+ body_work = newbuf(doc, BUFFER_BLOCK);
- i = parse_table_header(header_work, doc, data, size, &columns, &col_data);
- if (i > 0) {
+ i = parse_table_header(header_work, doc, data, size, &columns, &col_data);
+ if (i > 0) {
- while (i < size) {
- size_t row_start;
- int pipes = 0;
+ while (i < size) {
+ size_t row_start;
+ int pipes = 0;
- row_start = i;
+ row_start = i;
- while (i < size && data[i] != '\n')
- if (data[i++] == '|')
- pipes++;
+ while (i < size && data[i] != '\n')
+ if (data[i++] == '|')
+ pipes++;
- if (pipes == 0 || i == size) {
- i = row_start;
- break;
- }
+ if (pipes == 0 || i == size) {
+ i = row_start;
+ break;
+ }
- parse_table_row(
- body_work,
- doc,
- data + row_start,
- i - row_start,
- columns,
- col_data, 0
- );
+ parse_table_row(
+ body_work,
+ doc,
+ data + row_start,
+ i - row_start,
+ columns,
+ col_data, 0
+ );
- i++;
- }
+ i++;
+ }
if (doc->md.table_header)
doc->md.table_header(work, header_work, &doc->data);
@@ -2397,76 +2397,76 @@ parse_table(
if (doc->md.table_body)
doc->md.table_body(work, body_work, &doc->data);
- if (doc->md.table)
- doc->md.table(ob, work, &doc->data);
- }
+ if (doc->md.table)
+ doc->md.table(ob, work, &doc->data);
+ }
- free(col_data);
- popbuf(doc, BUFFER_SPAN);
- popbuf(doc, BUFFER_BLOCK);
- popbuf(doc, BUFFER_BLOCK);
- return i;
+ free(col_data);
+ popbuf(doc, BUFFER_SPAN);
+ popbuf(doc, BUFFER_BLOCK);
+ popbuf(doc, BUFFER_BLOCK);
+ return i;
}
/* parse_block • parsing of one block, returning next uint8_t to parse */
static void
parse_block(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size)
{
- size_t beg, end, i;
- uint8_t *txt_data;
- beg = 0;
+ size_t beg, end, i;
+ uint8_t *txt_data;
+ beg = 0;
- if (doc->work_bufs[BUFFER_SPAN].size +
- doc->work_bufs[BUFFER_BLOCK].size > doc->max_nesting)
- return;
+ if (doc->work_bufs[BUFFER_SPAN].size +
+ doc->work_bufs[BUFFER_BLOCK].size > doc->max_nesting)
+ return;
- while (beg < size) {
- txt_data = data + beg;
- end = size - beg;
+ while (beg < size) {
+ txt_data = data + beg;
+ end = size - beg;
- if (is_atxheader(doc, txt_data, end))
- beg += parse_atxheader(ob, doc, txt_data, end);
+ if (is_atxheader(doc, txt_data, end))
+ beg += parse_atxheader(ob, doc, txt_data, end);
- else if (data[beg] == '<' && doc->md.blockhtml &&
- (i = parse_htmlblock(ob, doc, txt_data, end, 1)) != 0)
- beg += i;
+ else if (data[beg] == '<' && doc->md.blockhtml &&
+ (i = parse_htmlblock(ob, doc, txt_data, end, 1)) != 0)
+ beg += i;
- else if ((i = is_empty(txt_data, end)) != 0)
- beg += i;
+ else if ((i = is_empty(txt_data, end)) != 0)
+ beg += i;
- else if (is_hrule(txt_data, end)) {
- if (doc->md.hrule)
- doc->md.hrule(ob, &doc->data);
+ else if (is_hrule(txt_data, end)) {
+ if (doc->md.hrule)
+ doc->md.hrule(ob, &doc->data);
- while (beg < size && data[beg] != '\n')
- beg++;
+ while (beg < size && data[beg] != '\n')
+ beg++;
- beg++;
- }
+ beg++;
+ }
- else if ((doc->ext_flags & HOEDOWN_EXT_FENCED_CODE) != 0 &&
- (i = parse_fencedcode(ob, doc, txt_data, end)) != 0)
- beg += i;
+ else if ((doc->ext_flags & HOEDOWN_EXT_FENCED_CODE) != 0 &&
+ (i = parse_fencedcode(ob, doc, txt_data, end)) != 0)
+ beg += i;
- else if ((doc->ext_flags & HOEDOWN_EXT_TABLES) != 0 &&
- (i = parse_table(ob, doc, txt_data, end)) != 0)
- beg += i;
+ else if ((doc->ext_flags & HOEDOWN_EXT_TABLES) != 0 &&
+ (i = parse_table(ob, doc, txt_data, end)) != 0)
+ beg += i;
- else if (prefix_quote(txt_data, end))
- beg += parse_blockquote(ob, doc, txt_data, end);
+ else if (prefix_quote(txt_data, end))
+ beg += parse_blockquote(ob, doc, txt_data, end);
- else if (!(doc->ext_flags & HOEDOWN_EXT_DISABLE_INDENTED_CODE) && prefix_code(txt_data, end))
- beg += parse_blockcode(ob, doc, txt_data, end);
+ else if (!(doc->ext_flags & HOEDOWN_EXT_DISABLE_INDENTED_CODE) && prefix_code(txt_data, end))
+ beg += parse_blockcode(ob, doc, txt_data, end);
- else if (prefix_uli(txt_data, end))
- beg += parse_list(ob, doc, txt_data, end, 0);
+ else if (prefix_uli(txt_data, end))
+ beg += parse_list(ob, doc, txt_data, end, 0);
- else if (prefix_oli(txt_data, end))
- beg += parse_list(ob, doc, txt_data, end, HOEDOWN_LIST_ORDERED);
+ else if (prefix_oli(txt_data, end))
+ beg += parse_list(ob, doc, txt_data, end, HOEDOWN_LIST_ORDERED);
- else
- beg += parse_paragraph(ob, doc, txt_data, end);
- }
+ else
+ beg += parse_paragraph(ob, doc, txt_data, end);
+ }
}
@@ -2479,253 +2479,253 @@ parse_block(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t siz
static int
is_footnote(const uint8_t *data, size_t beg, size_t end, size_t *last, struct footnote_list *list)
{
- size_t i = 0;
- hoedown_buffer *contents = 0;
- size_t ind = 0;
- int in_empty = 0;
- size_t start = 0;
-
- size_t id_offset, id_end;
-
- /* up to 3 optional leading spaces */
- if (beg + 3 >= end) return 0;
- if (data[beg] == ' ') { i = 1;
- if (data[beg + 1] == ' ') { i = 2;
- if (data[beg + 2] == ' ') { i = 3;
- if (data[beg + 3] == ' ') return 0; } } }
- i += beg;
-
- /* id part: caret followed by anything between brackets */
- if (data[i] != '[') return 0;
- i++;
- if (i >= end || data[i] != '^') return 0;
- i++;
- id_offset = i;
- while (i < end && data[i] != '\n' && data[i] != '\r' && data[i] != ']')
- i++;
- if (i >= end || data[i] != ']') return 0;
- id_end = i;
-
- /* spacer: colon (space | tab)* newline? (space | tab)* */
- i++;
- if (i >= end || data[i] != ':') return 0;
- i++;
-
- /* getting content buffer */
- contents = hoedown_buffer_new(64);
-
- start = i;
-
- /* process lines similar to a list item */
- while (i < end) {
- while (i < end && data[i] != '\n' && data[i] != '\r') i++;
-
- /* process an empty line */
- if (is_empty(data + start, i - start)) {
- in_empty = 1;
- if (i < end && (data[i] == '\n' || data[i] == '\r')) {
- i++;
- if (i < end && data[i] == '\n' && data[i - 1] == '\r') i++;
- }
- start = i;
- continue;
- }
-
- /* calculating the indentation */
- ind = 0;
- while (ind < 4 && start + ind < end && data[start + ind] == ' ')
- ind++;
-
- /* joining only indented stuff after empty lines;
- * note that now we only require 1 space of indentation
- * to continue, just like lists */
- if (ind == 0) {
- if (start == id_end + 2 && data[start] == '\t') {}
- else break;
- }
- else if (in_empty) {
- hoedown_buffer_putc(contents, '\n');
- }
-
- in_empty = 0;
-
- /* adding the line into the content buffer */
- hoedown_buffer_put(contents, data + start + ind, i - start - ind);
- /* add carriage return */
- if (i < end) {
- hoedown_buffer_putc(contents, '\n');
- if (i < end && (data[i] == '\n' || data[i] == '\r')) {
- i++;
- if (i < end && data[i] == '\n' && data[i - 1] == '\r') i++;
- }
- }
- start = i;
- }
-
- if (last)
- *last = start;
-
- if (list) {
- struct footnote_ref *ref;
- ref = create_footnote_ref(list, data + id_offset, id_end - id_offset);
- if (!ref)
- return 0;
- if (!add_footnote_ref(list, ref)) {
- free_footnote_ref(ref);
- return 0;
- }
- ref->contents = contents;
- }
-
- return 1;
+ size_t i = 0;
+ hoedown_buffer *contents = 0;
+ size_t ind = 0;
+ int in_empty = 0;
+ size_t start = 0;
+
+ size_t id_offset, id_end;
+
+ /* up to 3 optional leading spaces */
+ if (beg + 3 >= end) return 0;
+ if (data[beg] == ' ') { i = 1;
+ if (data[beg + 1] == ' ') { i = 2;
+ if (data[beg + 2] == ' ') { i = 3;
+ if (data[beg + 3] == ' ') return 0; } } }
+ i += beg;
+
+ /* id part: caret followed by anything between brackets */
+ if (data[i] != '[') return 0;
+ i++;
+ if (i >= end || data[i] != '^') return 0;
+ i++;
+ id_offset = i;
+ while (i < end && data[i] != '\n' && data[i] != '\r' && data[i] != ']')
+ i++;
+ if (i >= end || data[i] != ']') return 0;
+ id_end = i;
+
+ /* spacer: colon (space | tab)* newline? (space | tab)* */
+ i++;
+ if (i >= end || data[i] != ':') return 0;
+ i++;
+
+ /* getting content buffer */
+ contents = hoedown_buffer_new(64);
+
+ start = i;
+
+ /* process lines similar to a list item */
+ while (i < end) {
+ while (i < end && data[i] != '\n' && data[i] != '\r') i++;
+
+ /* process an empty line */
+ if (is_empty(data + start, i - start)) {
+ in_empty = 1;
+ if (i < end && (data[i] == '\n' || data[i] == '\r')) {
+ i++;
+ if (i < end && data[i] == '\n' && data[i - 1] == '\r') i++;
+ }
+ start = i;
+ continue;
+ }
+
+ /* calculating the indentation */
+ ind = 0;
+ while (ind < 4 && start + ind < end && data[start + ind] == ' ')
+ ind++;
+
+ /* joining only indented stuff after empty lines;
+ * note that now we only require 1 space of indentation
+ * to continue, just like lists */
+ if (ind == 0) {
+ if (start == id_end + 2 && data[start] == '\t') {}
+ else break;
+ }
+ else if (in_empty) {
+ hoedown_buffer_putc(contents, '\n');
+ }
+
+ in_empty = 0;
+
+ /* adding the line into the content buffer */
+ hoedown_buffer_put(contents, data + start + ind, i - start - ind);
+ /* add carriage return */
+ if (i < end) {
+ hoedown_buffer_putc(contents, '\n');
+ if (i < end && (data[i] == '\n' || data[i] == '\r')) {
+ i++;
+ if (i < end && data[i] == '\n' && data[i - 1] == '\r') i++;
+ }
+ }
+ start = i;
+ }
+
+ if (last)
+ *last = start;
+
+ if (list) {
+ struct footnote_ref *ref;
+ ref = create_footnote_ref(list, data + id_offset, id_end - id_offset);
+ if (!ref)
+ return 0;
+ if (!add_footnote_ref(list, ref)) {
+ free_footnote_ref(ref);
+ return 0;
+ }
+ ref->contents = contents;
+ }
+
+ return 1;
}
/* is_ref • returns whether a line is a reference or not */
static int
is_ref(const uint8_t *data, size_t beg, size_t end, size_t *last, struct link_ref **refs)
{
-/* int n; */
- size_t i = 0;
- size_t id_offset, id_end;
- size_t link_offset, link_end;
- size_t title_offset, title_end;
- size_t line_end;
-
- /* up to 3 optional leading spaces */
- if (beg + 3 >= end) return 0;
- if (data[beg] == ' ') { i = 1;
- if (data[beg + 1] == ' ') { i = 2;
- if (data[beg + 2] == ' ') { i = 3;
- if (data[beg + 3] == ' ') return 0; } } }
- i += beg;
-
- /* id part: anything but a newline between brackets */
- if (data[i] != '[') return 0;
- i++;
- id_offset = i;
- while (i < end && data[i] != '\n' && data[i] != '\r' && data[i] != ']')
- i++;
- if (i >= end || data[i] != ']') return 0;
- id_end = i;
-
- /* spacer: colon (space | tab)* newline? (space | tab)* */
- i++;
- if (i >= end || data[i] != ':') return 0;
- i++;
- while (i < end && data[i] == ' ') i++;
- if (i < end && (data[i] == '\n' || data[i] == '\r')) {
- i++;
- if (i < end && data[i] == '\r' && data[i - 1] == '\n') i++; }
- while (i < end && data[i] == ' ') i++;
- if (i >= end) return 0;
-
- /* link: spacing-free sequence, optionally between angle brackets */
- if (data[i] == '<')
- i++;
-
- link_offset = i;
-
- while (i < end && data[i] != ' ' && data[i] != '\n' && data[i] != '\r')
- i++;
-
- if (data[i - 1] == '>') link_end = i - 1;
- else link_end = i;
-
- /* optional spacer: (space | tab)* (newline | '\'' | '"' | '(' ) */
- while (i < end && data[i] == ' ') i++;
- if (i < end && data[i] != '\n' && data[i] != '\r'
- && data[i] != '\'' && data[i] != '"' && data[i] != '(')
- return 0;
- line_end = 0;
- /* computing end-of-line */
- if (i >= end || data[i] == '\r' || data[i] == '\n') line_end = i;
- if (i + 1 < end && data[i] == '\n' && data[i + 1] == '\r')
- line_end = i + 1;
-
- /* optional (space|tab)* spacer after a newline */
- if (line_end) {
- i = line_end + 1;
- while (i < end && data[i] == ' ') i++; }
-
- /* optional title: any non-newline sequence enclosed in '"()
- alone on its line */
- title_offset = title_end = 0;
- if (i + 1 < end
- && (data[i] == '\'' || data[i] == '"' || data[i] == '(')) {
- i++;
- title_offset = i;
- /* looking for EOL */
- while (i < end && data[i] != '\n' && data[i] != '\r') i++;
- if (i + 1 < end && data[i] == '\n' && data[i + 1] == '\r')
- title_end = i + 1;
- else title_end = i;
- /* stepping back */
- i -= 1;
- while (i > title_offset && data[i] == ' ')
- i -= 1;
- if (i > title_offset
- && (data[i] == '\'' || data[i] == '"' || data[i] == ')')) {
- line_end = title_end;
- title_end = i; } }
-
- if (!line_end || link_end == link_offset)
- return 0; /* garbage after the link empty link */
-
- /* a valid ref has been found, filling-in return structures */
- if (last)
- *last = line_end;
-
- if (refs) {
- struct link_ref *ref;
-
- ref = add_link_ref(refs, data + id_offset, id_end - id_offset);
- if (!ref)
- return 0;
-
- ref->link = hoedown_buffer_new(link_end - link_offset);
- hoedown_buffer_put(ref->link, data + link_offset, link_end - link_offset);
-
- if (title_end > title_offset) {
- ref->title = hoedown_buffer_new(title_end - title_offset);
- hoedown_buffer_put(ref->title, data + title_offset, title_end - title_offset);
- }
- }
-
- return 1;
+/* int n; */
+ size_t i = 0;
+ size_t id_offset, id_end;
+ size_t link_offset, link_end;
+ size_t title_offset, title_end;
+ size_t line_end;
+
+ /* up to 3 optional leading spaces */
+ if (beg + 3 >= end) return 0;
+ if (data[beg] == ' ') { i = 1;
+ if (data[beg + 1] == ' ') { i = 2;
+ if (data[beg + 2] == ' ') { i = 3;
+ if (data[beg + 3] == ' ') return 0; } } }
+ i += beg;
+
+ /* id part: anything but a newline between brackets */
+ if (data[i] != '[') return 0;
+ i++;
+ id_offset = i;
+ while (i < end && data[i] != '\n' && data[i] != '\r' && data[i] != ']')
+ i++;
+ if (i >= end || data[i] != ']') return 0;
+ id_end = i;
+
+ /* spacer: colon (space | tab)* newline? (space | tab)* */
+ i++;
+ if (i >= end || data[i] != ':') return 0;
+ i++;
+ while (i < end && data[i] == ' ') i++;
+ if (i < end && (data[i] == '\n' || data[i] == '\r')) {
+ i++;
+ if (i < end && data[i] == '\r' && data[i - 1] == '\n') i++; }
+ while (i < end && data[i] == ' ') i++;
+ if (i >= end) return 0;
+
+ /* link: spacing-free sequence, optionally between angle brackets */
+ if (data[i] == '<')
+ i++;
+
+ link_offset = i;
+
+ while (i < end && data[i] != ' ' && data[i] != '\n' && data[i] != '\r')
+ i++;
+
+ if (data[i - 1] == '>') link_end = i - 1;
+ else link_end = i;
+
+ /* optional spacer: (space | tab)* (newline | '\'' | '"' | '(' ) */
+ while (i < end && data[i] == ' ') i++;
+ if (i < end && data[i] != '\n' && data[i] != '\r'
+ && data[i] != '\'' && data[i] != '"' && data[i] != '(')
+ return 0;
+ line_end = 0;
+ /* computing end-of-line */
+ if (i >= end || data[i] == '\r' || data[i] == '\n') line_end = i;
+ if (i + 1 < end && data[i] == '\n' && data[i + 1] == '\r')
+ line_end = i + 1;
+
+ /* optional (space|tab)* spacer after a newline */
+ if (line_end) {
+ i = line_end + 1;
+ while (i < end && data[i] == ' ') i++; }
+
+ /* optional title: any non-newline sequence enclosed in '"()
+ alone on its line */
+ title_offset = title_end = 0;
+ if (i + 1 < end
+ && (data[i] == '\'' || data[i] == '"' || data[i] == '(')) {
+ i++;
+ title_offset = i;
+ /* looking for EOL */
+ while (i < end && data[i] != '\n' && data[i] != '\r') i++;
+ if (i + 1 < end && data[i] == '\n' && data[i + 1] == '\r')
+ title_end = i + 1;
+ else title_end = i;
+ /* stepping back */
+ i -= 1;
+ while (i > title_offset && data[i] == ' ')
+ i -= 1;
+ if (i > title_offset
+ && (data[i] == '\'' || data[i] == '"' || data[i] == ')')) {
+ line_end = title_end;
+ title_end = i; } }
+
+ if (!line_end || link_end == link_offset)
+ return 0; /* garbage after the link empty link */
+
+ /* a valid ref has been found, filling-in return structures */
+ if (last)
+ *last = line_end;
+
+ if (refs) {
+ struct link_ref *ref;
+
+ ref = add_link_ref(refs, data + id_offset, id_end - id_offset);
+ if (!ref)
+ return 0;
+
+ ref->link = hoedown_buffer_new(link_end - link_offset);
+ hoedown_buffer_put(ref->link, data + link_offset, link_end - link_offset);
+
+ if (title_end > title_offset) {
+ ref->title = hoedown_buffer_new(title_end - title_offset);
+ hoedown_buffer_put(ref->title, data + title_offset, title_end - title_offset);
+ }
+ }
+
+ return 1;
}
static void expand_tabs(hoedown_buffer *ob, const uint8_t *line, size_t size)
{
- /* This code makes two assumptions:
- * - Input is valid UTF-8. (Any byte with top two bits 10 is skipped,
- * whether or not it is a valid UTF-8 continuation byte.)
- * - Input contains no combining characters. (Combining characters
- * should be skipped but are not.)
- */
- size_t i = 0, tab = 0;
+ /* This code makes two assumptions:
+ * - Input is valid UTF-8. (Any byte with top two bits 10 is skipped,
+ * whether or not it is a valid UTF-8 continuation byte.)
+ * - Input contains no combining characters. (Combining characters
+ * should be skipped but are not.)
+ */
+ size_t i = 0, tab = 0;
- while (i < size) {
- size_t org = i;
+ while (i < size) {
+ size_t org = i;
- while (i < size && line[i] != '\t') {
- /* ignore UTF-8 continuation bytes */
- if ((line[i] & 0xc0) != 0x80)
- tab++;
- i++;
- }
+ while (i < size && line[i] != '\t') {
+ /* ignore UTF-8 continuation bytes */
+ if ((line[i] & 0xc0) != 0x80)
+ tab++;
+ i++;
+ }
- if (i > org)
- hoedown_buffer_put(ob, line + org, i - org);
+ if (i > org)
+ hoedown_buffer_put(ob, line + org, i - org);
- if (i >= size)
- break;
+ if (i >= size)
+ break;
- do {
- hoedown_buffer_putc(ob, ' '); tab++;
- } while (tab % 4);
+ do {
+ hoedown_buffer_putc(ob, ' '); tab++;
+ } while (tab % 4);
- i++;
- }
+ i++;
+ }
}
/**********************
@@ -2734,225 +2734,225 @@ static void expand_tabs(hoedown_buffer *ob, const uint8_t *line, size_t size)
hoedown_document *
hoedown_document_new(
- const hoedown_renderer *renderer,
- hoedown_extensions extensions,
- size_t max_nesting)
+ const hoedown_renderer *renderer,
+ hoedown_extensions extensions,
+ size_t max_nesting)
{
- hoedown_document *doc = NULL;
+ hoedown_document *doc = NULL;
- assert(max_nesting > 0 && renderer);
+ assert(max_nesting > 0 && renderer);
- doc = hoedown_malloc(sizeof(hoedown_document));
- memcpy(&doc->md, renderer, sizeof(hoedown_renderer));
+ doc = hoedown_malloc(sizeof(hoedown_document));
+ memcpy(&doc->md, renderer, sizeof(hoedown_renderer));
- doc->data.opaque = renderer->opaque;
+ doc->data.opaque = renderer->opaque;
- hoedown_stack_init(&doc->work_bufs[BUFFER_BLOCK], 4);
- hoedown_stack_init(&doc->work_bufs[BUFFER_SPAN], 8);
+ hoedown_stack_init(&doc->work_bufs[BUFFER_BLOCK], 4);
+ hoedown_stack_init(&doc->work_bufs[BUFFER_SPAN], 8);
- memset(doc->active_char, 0x0, 256);
+ memset(doc->active_char, 0x0, 256);
- if (extensions & HOEDOWN_EXT_UNDERLINE && doc->md.underline) {
- doc->active_char['_'] = MD_CHAR_EMPHASIS;
- }
+ if (extensions & HOEDOWN_EXT_UNDERLINE && doc->md.underline) {
+ doc->active_char['_'] = MD_CHAR_EMPHASIS;
+ }
- if (doc->md.emphasis || doc->md.double_emphasis || doc->md.triple_emphasis) {
- doc->active_char['*'] = MD_CHAR_EMPHASIS;
- doc->active_char['_'] = MD_CHAR_EMPHASIS;
- if (extensions & HOEDOWN_EXT_STRIKETHROUGH)
- doc->active_char['~'] = MD_CHAR_EMPHASIS;
- if (extensions & HOEDOWN_EXT_HIGHLIGHT)
- doc->active_char['='] = MD_CHAR_EMPHASIS;
- }
+ if (doc->md.emphasis || doc->md.double_emphasis || doc->md.triple_emphasis) {
+ doc->active_char['*'] = MD_CHAR_EMPHASIS;
+ doc->active_char['_'] = MD_CHAR_EMPHASIS;
+ if (extensions & HOEDOWN_EXT_STRIKETHROUGH)
+ doc->active_char['~'] = MD_CHAR_EMPHASIS;
+ if (extensions & HOEDOWN_EXT_HIGHLIGHT)
+ doc->active_char['='] = MD_CHAR_EMPHASIS;
+ }
- if (doc->md.codespan)
- doc->active_char['`'] = MD_CHAR_CODESPAN;
+ if (doc->md.codespan)
+ doc->active_char['`'] = MD_CHAR_CODESPAN;
- if (doc->md.linebreak)
- doc->active_char['\n'] = MD_CHAR_LINEBREAK;
+ if (doc->md.linebreak)
+ doc->active_char['\n'] = MD_CHAR_LINEBREAK;
- if (doc->md.image || doc->md.link || doc->md.footnotes || doc->md.footnote_ref)
- doc->active_char['['] = MD_CHAR_LINK;
+ if (doc->md.image || doc->md.link || doc->md.footnotes || doc->md.footnote_ref)
+ doc->active_char['['] = MD_CHAR_LINK;
- doc->active_char['<'] = MD_CHAR_LANGLE;
- doc->active_char['\\'] = MD_CHAR_ESCAPE;
- doc->active_char['&'] = MD_CHAR_ENTITY;
+ doc->active_char['<'] = MD_CHAR_LANGLE;
+ doc->active_char['\\'] = MD_CHAR_ESCAPE;
+ doc->active_char['&'] = MD_CHAR_ENTITY;
- if (extensions & HOEDOWN_EXT_AUTOLINK) {
- doc->active_char[':'] = MD_CHAR_AUTOLINK_URL;
- doc->active_char['@'] = MD_CHAR_AUTOLINK_EMAIL;
- doc->active_char['w'] = MD_CHAR_AUTOLINK_WWW;
- }
+ if (extensions & HOEDOWN_EXT_AUTOLINK) {
+ doc->active_char[':'] = MD_CHAR_AUTOLINK_URL;
+ doc->active_char['@'] = MD_CHAR_AUTOLINK_EMAIL;
+ doc->active_char['w'] = MD_CHAR_AUTOLINK_WWW;
+ }
- if (extensions & HOEDOWN_EXT_SUPERSCRIPT)
- doc->active_char['^'] = MD_CHAR_SUPERSCRIPT;
+ if (extensions & HOEDOWN_EXT_SUPERSCRIPT)
+ doc->active_char['^'] = MD_CHAR_SUPERSCRIPT;
- if (extensions & HOEDOWN_EXT_QUOTE)
- doc->active_char['"'] = MD_CHAR_QUOTE;
+ if (extensions & HOEDOWN_EXT_QUOTE)
+ doc->active_char['"'] = MD_CHAR_QUOTE;
- if (extensions & HOEDOWN_EXT_MATH)
- doc->active_char['$'] = MD_CHAR_MATH;
+ if (extensions & HOEDOWN_EXT_MATH)
+ doc->active_char['$'] = MD_CHAR_MATH;
- /* Extension data */
- doc->ext_flags = extensions;
- doc->max_nesting = max_nesting;
- doc->in_link_body = 0;
+ /* Extension data */
+ doc->ext_flags = extensions;
+ doc->max_nesting = max_nesting;
+ doc->in_link_body = 0;
- return doc;
+ return doc;
}
void
hoedown_document_render(hoedown_document *doc, hoedown_buffer *ob, const uint8_t *data, size_t size)
{
- static const uint8_t UTF8_BOM[] = {0xEF, 0xBB, 0xBF};
+ static const uint8_t UTF8_BOM[] = {0xEF, 0xBB, 0xBF};
- hoedown_buffer *text;
- size_t beg, end;
+ hoedown_buffer *text;
+ size_t beg, end;
- int footnotes_enabled;
+ int footnotes_enabled;
- text = hoedown_buffer_new(64);
+ text = hoedown_buffer_new(64);
- /* Preallocate enough space for our buffer to avoid expanding while copying */
- hoedown_buffer_grow(text, size);
+ /* Preallocate enough space for our buffer to avoid expanding while copying */
+ hoedown_buffer_grow(text, size);
- /* reset the references table */
- memset(&doc->refs, 0x0, REF_TABLE_SIZE * sizeof(void *));
+ /* reset the references table */
+ memset(&doc->refs, 0x0, REF_TABLE_SIZE * sizeof(void *));
- footnotes_enabled = doc->ext_flags & HOEDOWN_EXT_FOOTNOTES;
+ footnotes_enabled = doc->ext_flags & HOEDOWN_EXT_FOOTNOTES;
- /* reset the footnotes lists */
- if (footnotes_enabled) {
- memset(&doc->footnotes_found, 0x0, sizeof(doc->footnotes_found));
- memset(&doc->footnotes_used, 0x0, sizeof(doc->footnotes_used));
- }
+ /* reset the footnotes lists */
+ if (footnotes_enabled) {
+ memset(&doc->footnotes_found, 0x0, sizeof(doc->footnotes_found));
+ memset(&doc->footnotes_used, 0x0, sizeof(doc->footnotes_used));
+ }
- /* first pass: looking for references, copying everything else */
- beg = 0;
+ /* first pass: looking for references, copying everything else */
+ beg = 0;
- /* Skip a possible UTF-8 BOM, even though the Unicode standard
- * discourages having these in UTF-8 documents */
- if (size >= 3 && memcmp(data, UTF8_BOM, 3) == 0)
- beg += 3;
+ /* Skip a possible UTF-8 BOM, even though the Unicode standard
+ * discourages having these in UTF-8 documents */
+ if (size >= 3 && memcmp(data, UTF8_BOM, 3) == 0)
+ beg += 3;
- while (beg < size) /* iterating over lines */
- if (footnotes_enabled && is_footnote(data, beg, size, &end, &doc->footnotes_found))
- beg = end;
- else if (is_ref(data, beg, size, &end, doc->refs))
- beg = end;
- else { /* skipping to the next line */
- end = beg;
- while (end < size && data[end] != '\n' && data[end] != '\r')
- end++;
+ while (beg < size) /* iterating over lines */
+ if (footnotes_enabled && is_footnote(data, beg, size, &end, &doc->footnotes_found))
+ beg = end;
+ else if (is_ref(data, beg, size, &end, doc->refs))
+ beg = end;
+ else { /* skipping to the next line */
+ end = beg;
+ while (end < size && data[end] != '\n' && data[end] != '\r')
+ end++;
- /* adding the line body if present */
- if (end > beg)
- expand_tabs(text, data + beg, end - beg);
+ /* adding the line body if present */
+ if (end > beg)
+ expand_tabs(text, data + beg, end - beg);
- while (end < size && (data[end] == '\n' || data[end] == '\r')) {
- /* add one \n per newline */
- if (data[end] == '\n' || (end + 1 < size && data[end + 1] != '\n'))
- hoedown_buffer_putc(text, '\n');
- end++;
- }
+ while (end < size && (data[end] == '\n' || data[end] == '\r')) {
+ /* add one \n per newline */
+ if (data[end] == '\n' || (end + 1 < size && data[end + 1] != '\n'))
+ hoedown_buffer_putc(text, '\n');
+ end++;
+ }
- beg = end;
- }
+ beg = end;
+ }
- /* pre-grow the output buffer to minimize allocations */
- hoedown_buffer_grow(ob, text->size + (text->size >> 1));
+ /* pre-grow the output buffer to minimize allocations */
+ hoedown_buffer_grow(ob, text->size + (text->size >> 1));
- /* second pass: actual rendering */
- if (doc->md.doc_header)
- doc->md.doc_header(ob, 0, &doc->data);
+ /* second pass: actual rendering */
+ if (doc->md.doc_header)
+ doc->md.doc_header(ob, 0, &doc->data);
- if (text->size) {
- /* adding a final newline if not already present */
- if (text->data[text->size - 1] != '\n' && text->data[text->size - 1] != '\r')
- hoedown_buffer_putc(text, '\n');
+ if (text->size) {
+ /* adding a final newline if not already present */
+ if (text->data[text->size - 1] != '\n' && text->data[text->size - 1] != '\r')
+ hoedown_buffer_putc(text, '\n');
- parse_block(ob, doc, text->data, text->size);
- }
+ parse_block(ob, doc, text->data, text->size);
+ }
- /* footnotes */
- if (footnotes_enabled)
- parse_footnote_list(ob, doc, &doc->footnotes_used);
+ /* footnotes */
+ if (footnotes_enabled)
+ parse_footnote_list(ob, doc, &doc->footnotes_used);
- if (doc->md.doc_footer)
- doc->md.doc_footer(ob, 0, &doc->data);
+ if (doc->md.doc_footer)
+ doc->md.doc_footer(ob, 0, &doc->data);
- /* clean-up */
- hoedown_buffer_free(text);
- free_link_refs(doc->refs);
- if (footnotes_enabled) {
- free_footnote_list(&doc->footnotes_found, 1);
- free_footnote_list(&doc->footnotes_used, 0);
- }
+ /* clean-up */
+ hoedown_buffer_free(text);
+ free_link_refs(doc->refs);
+ if (footnotes_enabled) {
+ free_footnote_list(&doc->footnotes_found, 1);
+ free_footnote_list(&doc->footnotes_used, 0);
+ }
- assert(doc->work_bufs[BUFFER_SPAN].size == 0);
- assert(doc->work_bufs[BUFFER_BLOCK].size == 0);
+ assert(doc->work_bufs[BUFFER_SPAN].size == 0);
+ assert(doc->work_bufs[BUFFER_BLOCK].size == 0);
}
void
hoedown_document_render_inline(hoedown_document *doc, hoedown_buffer *ob, const uint8_t *data, size_t size)
{
- size_t i = 0, mark;
- hoedown_buffer *text = hoedown_buffer_new(64);
+ size_t i = 0, mark;
+ hoedown_buffer *text = hoedown_buffer_new(64);
- /* reset the references table */
- memset(&doc->refs, 0x0, REF_TABLE_SIZE * sizeof(void *));
+ /* reset the references table */
+ memset(&doc->refs, 0x0, REF_TABLE_SIZE * sizeof(void *));
- /* first pass: expand tabs and process newlines */
- hoedown_buffer_grow(text, size);
- while (1) {
- mark = i;
- while (i < size && data[i] != '\n' && data[i] != '\r')
- i++;
+ /* first pass: expand tabs and process newlines */
+ hoedown_buffer_grow(text, size);
+ while (1) {
+ mark = i;
+ while (i < size && data[i] != '\n' && data[i] != '\r')
+ i++;
- expand_tabs(text, data + mark, i - mark);
+ expand_tabs(text, data + mark, i - mark);
- if (i >= size)
- break;
+ if (i >= size)
+ break;
- while (i < size && (data[i] == '\n' || data[i] == '\r')) {
- /* add one \n per newline */
- if (data[i] == '\n' || (i + 1 < size && data[i + 1] != '\n'))
- hoedown_buffer_putc(text, '\n');
- i++;
- }
- }
+ while (i < size && (data[i] == '\n' || data[i] == '\r')) {
+ /* add one \n per newline */
+ if (data[i] == '\n' || (i + 1 < size && data[i + 1] != '\n'))
+ hoedown_buffer_putc(text, '\n');
+ i++;
+ }
+ }
- /* second pass: actual rendering */
- hoedown_buffer_grow(ob, text->size + (text->size >> 1));
+ /* second pass: actual rendering */
+ hoedown_buffer_grow(ob, text->size + (text->size >> 1));
- if (doc->md.doc_header)
- doc->md.doc_header(ob, 1, &doc->data);
+ if (doc->md.doc_header)
+ doc->md.doc_header(ob, 1, &doc->data);
- parse_inline(ob, doc, text->data, text->size);
+ parse_inline(ob, doc, text->data, text->size);
- if (doc->md.doc_footer)
- doc->md.doc_footer(ob, 1, &doc->data);
+ if (doc->md.doc_footer)
+ doc->md.doc_footer(ob, 1, &doc->data);
- /* clean-up */
- hoedown_buffer_free(text);
+ /* clean-up */
+ hoedown_buffer_free(text);
- assert(doc->work_bufs[BUFFER_SPAN].size == 0);
- assert(doc->work_bufs[BUFFER_BLOCK].size == 0);
+ assert(doc->work_bufs[BUFFER_SPAN].size == 0);
+ assert(doc->work_bufs[BUFFER_BLOCK].size == 0);
}
void
hoedown_document_free(hoedown_document *doc)
{
- size_t i;
+ size_t i;
- for (i = 0; i < (size_t)doc->work_bufs[BUFFER_SPAN].asize; ++i)
- hoedown_buffer_free(doc->work_bufs[BUFFER_SPAN].item[i]);
+ for (i = 0; i < (size_t)doc->work_bufs[BUFFER_SPAN].asize; ++i)
+ hoedown_buffer_free(doc->work_bufs[BUFFER_SPAN].item[i]);
- for (i = 0; i < (size_t)doc->work_bufs[BUFFER_BLOCK].asize; ++i)
- hoedown_buffer_free(doc->work_bufs[BUFFER_BLOCK].item[i]);
+ for (i = 0; i < (size_t)doc->work_bufs[BUFFER_BLOCK].asize; ++i)
+ hoedown_buffer_free(doc->work_bufs[BUFFER_BLOCK].item[i]);
- hoedown_stack_uninit(&doc->work_bufs[BUFFER_SPAN]);
- hoedown_stack_uninit(&doc->work_bufs[BUFFER_BLOCK]);
+ hoedown_stack_uninit(&doc->work_bufs[BUFFER_SPAN]);
+ hoedown_stack_uninit(&doc->work_bufs[BUFFER_BLOCK]);
- free(doc);
+ free(doc);
}
diff --git a/libraries/hoedown/src/escape.c b/libraries/hoedown/src/escape.c
index b4a275ba..ce25dd54 100644
--- a/libraries/hoedown/src/escape.c
+++ b/libraries/hoedown/src/escape.c
@@ -12,13 +12,13 @@
/*
* The following characters will not be escaped:
*
- * -_.+!*'(),%#@?=;:/,+&$ alphanum
+ * -_.+!*'(),%#@?=;:/,+&$ alphanum
*
* Note that this character set is the addition of:
*
- * - The characters which are safe to be in an URL
- * - The characters which are *not* safe to be in
- * an URL because they are RESERVED characters.
+ * - The characters which are safe to be in an URL
+ * - The characters which are *not* safe to be in
+ * an URL because they are RESERVED characters.
*
* We assume (lazily) that any RESERVED char that
* appears inside an URL is actually meant to
@@ -35,84 +35,84 @@
*
*/
static const uint8_t HREF_SAFE[UINT8_MAX+1] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
void
hoedown_escape_href(hoedown_buffer *ob, const uint8_t *data, size_t size)
{
- static const char hex_chars[] = "0123456789ABCDEF";
- size_t i = 0, mark;
- char hex_str[3];
-
- hex_str[0] = '%';
-
- while (i < size) {
- mark = i;
- while (i < size && HREF_SAFE[data[i]]) i++;
-
- /* Optimization for cases where there's nothing to escape */
- if (mark == 0 && i >= size) {
- hoedown_buffer_put(ob, data, size);
- return;
- }
-
- if (likely(i > mark)) {
- hoedown_buffer_put(ob, data + mark, i - mark);
- }
-
- /* escaping */
- if (i >= size)
- break;
-
- switch (data[i]) {
- /* amp appears all the time in URLs, but needs
- * HTML-entity escaping to be inside an href */
- case '&':
- HOEDOWN_BUFPUTSL(ob, "&amp;");
- break;
-
- /* the single quote is a valid URL character
- * according to the standard; it needs HTML
- * entity escaping too */
- case '\'':
- HOEDOWN_BUFPUTSL(ob, "&#x27;");
- break;
-
- /* the space can be escaped to %20 or a plus
- * sign. we're going with the generic escape
- * for now. the plus thing is more commonly seen
- * when building GET strings */
+ static const char hex_chars[] = "0123456789ABCDEF";
+ size_t i = 0, mark;
+ char hex_str[3];
+
+ hex_str[0] = '%';
+
+ while (i < size) {
+ mark = i;
+ while (i < size && HREF_SAFE[data[i]]) i++;
+
+ /* Optimization for cases where there's nothing to escape */
+ if (mark == 0 && i >= size) {
+ hoedown_buffer_put(ob, data, size);
+ return;
+ }
+
+ if (likely(i > mark)) {
+ hoedown_buffer_put(ob, data + mark, i - mark);
+ }
+
+ /* escaping */
+ if (i >= size)
+ break;
+
+ switch (data[i]) {
+ /* amp appears all the time in URLs, but needs
+ * HTML-entity escaping to be inside an href */
+ case '&':
+ HOEDOWN_BUFPUTSL(ob, "&amp;");
+ break;
+
+ /* the single quote is a valid URL character
+ * according to the standard; it needs HTML
+ * entity escaping too */
+ case '\'':
+ HOEDOWN_BUFPUTSL(ob, "&#x27;");
+ break;
+
+ /* the space can be escaped to %20 or a plus
+ * sign. we're going with the generic escape
+ * for now. the plus thing is more commonly seen
+ * when building GET strings */
#if 0
- case ' ':
- hoedown_buffer_putc(ob, '+');
- break;
+ case ' ':
+ hoedown_buffer_putc(ob, '+');
+ break;
#endif
- /* every other character goes with a %XX escaping */
- default:
- hex_str[1] = hex_chars[(data[i] >> 4) & 0xF];
- hex_str[2] = hex_chars[data[i] & 0xF];
- hoedown_buffer_put(ob, (uint8_t *)hex_str, 3);
- }
+ /* every other character goes with a %XX escaping */
+ default:
+ hex_str[1] = hex_chars[(data[i] >> 4) & 0xF];
+ hex_str[2] = hex_chars[data[i] & 0xF];
+ hoedown_buffer_put(ob, (uint8_t *)hex_str, 3);
+ }
- i++;
- }
+ i++;
+ }
}
@@ -128,22 +128,22 @@ hoedown_escape_href(hoedown_buffer *ob, const uint8_t *data, size_t size)
*
*/
static const uint8_t HTML_ESCAPE_TABLE[UINT8_MAX+1] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 1, 0, 0, 0, 2, 3, 0, 0, 0, 0, 0, 0, 0, 4,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 6, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 2, 3, 0, 0, 0, 0, 0, 0, 0, 4,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 6, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
static const char *HTML_ESCAPES[] = {
@@ -159,30 +159,30 @@ static const char *HTML_ESCAPES[] = {
void
hoedown_escape_html(hoedown_buffer *ob, const uint8_t *data, size_t size, int secure)
{
- size_t i = 0, mark;
+ size_t i = 0, mark;
- while (1) {
- mark = i;
- while (i < size && HTML_ESCAPE_TABLE[data[i]] == 0) i++;
+ while (1) {
+ mark = i;
+ while (i < size && HTML_ESCAPE_TABLE[data[i]] == 0) i++;
- /* Optimization for cases where there's nothing to escape */
- if (mark == 0 && i >= size) {
- hoedown_buffer_put(ob, data, size);
- return;
- }
+ /* Optimization for cases where there's nothing to escape */
+ if (mark == 0 && i >= size) {
+ hoedown_buffer_put(ob, data, size);
+ return;
+ }
- if (likely(i > mark))
- hoedown_buffer_put(ob, data + mark, i - mark);
+ if (likely(i > mark))
+ hoedown_buffer_put(ob, data + mark, i - mark);
- if (i >= size) break;
+ if (i >= size) break;
- /* The forward slash is only escaped in secure mode */
- if (!secure && data[i] == '/') {
- hoedown_buffer_putc(ob, '/');
- } else {
- hoedown_buffer_puts(ob, HTML_ESCAPES[HTML_ESCAPE_TABLE[data[i]]]);
- }
+ /* The forward slash is only escaped in secure mode */
+ if (!secure && data[i] == '/') {
+ hoedown_buffer_putc(ob, '/');
+ } else {
+ hoedown_buffer_puts(ob, HTML_ESCAPES[HTML_ESCAPE_TABLE[data[i]]]);
+ }
- i++;
- }
+ i++;
+ }
}
diff --git a/libraries/hoedown/src/html.c b/libraries/hoedown/src/html.c
index 4b18d804..8bf3358e 100644
--- a/libraries/hoedown/src/html.c
+++ b/libraries/hoedown/src/html.c
@@ -12,44 +12,44 @@
hoedown_html_tag
hoedown_html_is_tag(const uint8_t *data, size_t size, const char *tagname)
{
- size_t i;
- int closed = 0;
+ size_t i;
+ int closed = 0;
- if (size < 3 || data[0] != '<')
- return HOEDOWN_HTML_TAG_NONE;
+ if (size < 3 || data[0] != '<')
+ return HOEDOWN_HTML_TAG_NONE;
- i = 1;
+ i = 1;
- if (data[i] == '/') {
- closed = 1;
- i++;
- }
+ if (data[i] == '/') {
+ closed = 1;
+ i++;
+ }
- for (; i < size; ++i, ++tagname) {
- if (*tagname == 0)
- break;
+ for (; i < size; ++i, ++tagname) {
+ if (*tagname == 0)
+ break;
- if (data[i] != *tagname)
- return HOEDOWN_HTML_TAG_NONE;
- }
+ if (data[i] != *tagname)
+ return HOEDOWN_HTML_TAG_NONE;
+ }
- if (i == size)
- return HOEDOWN_HTML_TAG_NONE;
+ if (i == size)
+ return HOEDOWN_HTML_TAG_NONE;
- if (isspace(data[i]) || data[i] == '>')
- return closed ? HOEDOWN_HTML_TAG_CLOSE : HOEDOWN_HTML_TAG_OPEN;
+ if (isspace(data[i]) || data[i] == '>')
+ return closed ? HOEDOWN_HTML_TAG_CLOSE : HOEDOWN_HTML_TAG_OPEN;
- return HOEDOWN_HTML_TAG_NONE;
+ return HOEDOWN_HTML_TAG_NONE;
}
static void escape_html(hoedown_buffer *ob, const uint8_t *source, size_t length)
{
- hoedown_escape_html(ob, source, length, 0);
+ hoedown_escape_html(ob, source, length, 0);
}
static void escape_href(hoedown_buffer *ob, const uint8_t *source, size_t length)
{
- hoedown_escape_href(ob, source, length);
+ hoedown_escape_href(ob, source, length);
}
/********************
@@ -58,353 +58,353 @@ static void escape_href(hoedown_buffer *ob, const uint8_t *source, size_t length
static int
rndr_autolink(hoedown_buffer *ob, const hoedown_buffer *link, hoedown_autolink_type type, const hoedown_renderer_data *data)
{
- hoedown_html_renderer_state *state = data->opaque;
+ hoedown_html_renderer_state *state = data->opaque;
- if (!link || !link->size)
- return 0;
+ if (!link || !link->size)
+ return 0;
- HOEDOWN_BUFPUTSL(ob, "<a href=\"");
- if (type == HOEDOWN_AUTOLINK_EMAIL)
- HOEDOWN_BUFPUTSL(ob, "mailto:");
- escape_href(ob, link->data, link->size);
+ HOEDOWN_BUFPUTSL(ob, "<a href=\"");
+ if (type == HOEDOWN_AUTOLINK_EMAIL)
+ HOEDOWN_BUFPUTSL(ob, "mailto:");
+ escape_href(ob, link->data, link->size);
- if (state->link_attributes) {
- hoedown_buffer_putc(ob, '\"');
- state->link_attributes(ob, link, data);
- hoedown_buffer_putc(ob, '>');
- } else {
- HOEDOWN_BUFPUTSL(ob, "\">");
- }
+ if (state->link_attributes) {
+ hoedown_buffer_putc(ob, '\"');
+ state->link_attributes(ob, link, data);
+ hoedown_buffer_putc(ob, '>');
+ } else {
+ HOEDOWN_BUFPUTSL(ob, "\">");
+ }
- /*
- * Pretty printing: if we get an email address as
- * an actual URI, e.g. `mailto:foo@bar.com`, we don't
- * want to print the `mailto:` prefix
- */
- if (hoedown_buffer_prefix(link, "mailto:") == 0) {
- escape_html(ob, link->data + 7, link->size - 7);
- } else {
- escape_html(ob, link->data, link->size);
- }
+ /*
+ * Pretty printing: if we get an email address as
+ * an actual URI, e.g. `mailto:foo@bar.com`, we don't
+ * want to print the `mailto:` prefix
+ */
+ if (hoedown_buffer_prefix(link, "mailto:") == 0) {
+ escape_html(ob, link->data + 7, link->size - 7);
+ } else {
+ escape_html(ob, link->data, link->size);
+ }
- HOEDOWN_BUFPUTSL(ob, "</a>");
+ HOEDOWN_BUFPUTSL(ob, "</a>");
- return 1;
+ return 1;
}
static void
rndr_blockcode(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_buffer *lang, const hoedown_renderer_data *data)
{
- if (ob->size) hoedown_buffer_putc(ob, '\n');
+ if (ob->size) hoedown_buffer_putc(ob, '\n');
- if (lang) {
- HOEDOWN_BUFPUTSL(ob, "<pre><code class=\"language-");
- escape_html(ob, lang->data, lang->size);
- HOEDOWN_BUFPUTSL(ob, "\">");
- } else {
- HOEDOWN_BUFPUTSL(ob, "<pre><code>");
- }
+ if (lang) {
+ HOEDOWN_BUFPUTSL(ob, "<pre><code class=\"language-");
+ escape_html(ob, lang->data, lang->size);
+ HOEDOWN_BUFPUTSL(ob, "\">");
+ } else {
+ HOEDOWN_BUFPUTSL(ob, "<pre><code>");
+ }
- if (text)
- escape_html(ob, text->data, text->size);
+ if (text)
+ escape_html(ob, text->data, text->size);
- HOEDOWN_BUFPUTSL(ob, "</code></pre>\n");
+ HOEDOWN_BUFPUTSL(ob, "</code></pre>\n");
}
static void
rndr_blockquote(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)
{
- if (ob->size) hoedown_buffer_putc(ob, '\n');
- HOEDOWN_BUFPUTSL(ob, "<blockquote>\n");
- if (content) hoedown_buffer_put(ob, content->data, content->size);
- HOEDOWN_BUFPUTSL(ob, "</blockquote>\n");
+ if (ob->size) hoedown_buffer_putc(ob, '\n');
+ HOEDOWN_BUFPUTSL(ob, "<blockquote>\n");
+ if (content) hoedown_buffer_put(ob, content->data, content->size);
+ HOEDOWN_BUFPUTSL(ob, "</blockquote>\n");
}
static int
rndr_codespan(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data)
{
- HOEDOWN_BUFPUTSL(ob, "<code>");
- if (text) escape_html(ob, text->data, text->size);
- HOEDOWN_BUFPUTSL(ob, "</code>");
- return 1;
+ HOEDOWN_BUFPUTSL(ob, "<code>");
+ if (text) escape_html(ob, text->data, text->size);
+ HOEDOWN_BUFPUTSL(ob, "</code>");
+ return 1;
}
static int
rndr_strikethrough(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)
{
- if (!content || !content->size)
- return 0;
+ if (!content || !content->size)
+ return 0;
- HOEDOWN_BUFPUTSL(ob, "<del>");
- hoedown_buffer_put(ob, content->data, content->size);
- HOEDOWN_BUFPUTSL(ob, "</del>");
- return 1;
+ HOEDOWN_BUFPUTSL(ob, "<del>");
+ hoedown_buffer_put(ob, content->data, content->size);
+ HOEDOWN_BUFPUTSL(ob, "</del>");
+ return 1;
}
static int
rndr_double_emphasis(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)
{
- if (!content || !content->size)
- return 0;
+ if (!content || !content->size)
+ return 0;
- HOEDOWN_BUFPUTSL(ob, "<strong>");
- hoedown_buffer_put(ob, content->data, content->size);
- HOEDOWN_BUFPUTSL(ob, "</strong>");
+ HOEDOWN_BUFPUTSL(ob, "<strong>");
+ hoedown_buffer_put(ob, content->data, content->size);
+ HOEDOWN_BUFPUTSL(ob, "</strong>");
- return 1;
+ return 1;
}
static int
rndr_emphasis(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)
{
- if (!content || !content->size) return 0;
- HOEDOWN_BUFPUTSL(ob, "<em>");
- if (content) hoedown_buffer_put(ob, content->data, content->size);
- HOEDOWN_BUFPUTSL(ob, "</em>");
- return 1;
+ if (!content || !content->size) return 0;
+ HOEDOWN_BUFPUTSL(ob, "<em>");
+ if (content) hoedown_buffer_put(ob, content->data, content->size);
+ HOEDOWN_BUFPUTSL(ob, "</em>");
+ return 1;
}
static int
rndr_underline(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)
{
- if (!content || !content->size)
- return 0;
+ if (!content || !content->size)
+ return 0;
- HOEDOWN_BUFPUTSL(ob, "<u>");
- hoedown_buffer_put(ob, content->data, content->size);
- HOEDOWN_BUFPUTSL(ob, "</u>");
+ HOEDOWN_BUFPUTSL(ob, "<u>");
+ hoedown_buffer_put(ob, content->data, content->size);
+ HOEDOWN_BUFPUTSL(ob, "</u>");
- return 1;
+ return 1;
}
static int
rndr_highlight(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)
{
- if (!content || !content->size)
- return 0;
+ if (!content || !content->size)
+ return 0;
- HOEDOWN_BUFPUTSL(ob, "<mark>");
- hoedown_buffer_put(ob, content->data, content->size);
- HOEDOWN_BUFPUTSL(ob, "</mark>");
+ HOEDOWN_BUFPUTSL(ob, "<mark>");
+ hoedown_buffer_put(ob, content->data, content->size);
+ HOEDOWN_BUFPUTSL(ob, "</mark>");
- return 1;
+ return 1;
}
static int
rndr_quote(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)
{
- if (!content || !content->size)
- return 0;
+ if (!content || !content->size)
+ return 0;
- HOEDOWN_BUFPUTSL(ob, "<q>");
- hoedown_buffer_put(ob, content->data, content->size);
- HOEDOWN_BUFPUTSL(ob, "</q>");
+ HOEDOWN_BUFPUTSL(ob, "<q>");
+ hoedown_buffer_put(ob, content->data, content->size);
+ HOEDOWN_BUFPUTSL(ob, "</q>");
- return 1;
+ return 1;
}
static int
rndr_linebreak(hoedown_buffer *ob, const hoedown_renderer_data *data)
{
- hoedown_html_renderer_state *state = data->opaque;
- hoedown_buffer_puts(ob, USE_XHTML(state) ? "<br/>\n" : "<br>\n");
- return 1;
+ hoedown_html_renderer_state *state = data->opaque;
+ hoedown_buffer_puts(ob, USE_XHTML(state) ? "<br/>\n" : "<br>\n");
+ return 1;
}
static void
rndr_header(hoedown_buffer *ob, const hoedown_buffer *content, int level, const hoedown_renderer_data *data)
{
- hoedown_html_renderer_state *state = data->opaque;
+ hoedown_html_renderer_state *state = data->opaque;
- if (ob->size)
- hoedown_buffer_putc(ob, '\n');
+ if (ob->size)
+ hoedown_buffer_putc(ob, '\n');
- if (level <= state->toc_data.nesting_level)
- hoedown_buffer_printf(ob, "<h%d id=\"toc_%d\">", level, state->toc_data.header_count++);
- else
- hoedown_buffer_printf(ob, "<h%d>", level);
+ if (level <= state->toc_data.nesting_level)
+ hoedown_buffer_printf(ob, "<h%d id=\"toc_%d\">", level, state->toc_data.header_count++);
+ else
+ hoedown_buffer_printf(ob, "<h%d>", level);
- if (content) hoedown_buffer_put(ob, content->data, content->size);
- hoedown_buffer_printf(ob, "</h%d>\n", level);
+ if (content) hoedown_buffer_put(ob, content->data, content->size);
+ hoedown_buffer_printf(ob, "</h%d>\n", level);
}
static int
rndr_link(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_buffer *link, const hoedown_buffer *title, const hoedown_renderer_data *data)
{
- hoedown_html_renderer_state *state = data->opaque;
+ hoedown_html_renderer_state *state = data->opaque;
- HOEDOWN_BUFPUTSL(ob, "<a href=\"");
+ HOEDOWN_BUFPUTSL(ob, "<a href=\"");
- if (link && link->size)
- escape_href(ob, link->data, link->size);
+ if (link && link->size)
+ escape_href(ob, link->data, link->size);
- if (title && title->size) {
- HOEDOWN_BUFPUTSL(ob, "\" title=\"");
- escape_html(ob, title->data, title->size);
- }
+ if (title && title->size) {
+ HOEDOWN_BUFPUTSL(ob, "\" title=\"");
+ escape_html(ob, title->data, title->size);
+ }
- if (state->link_attributes) {
- hoedown_buffer_putc(ob, '\"');
- state->link_attributes(ob, link, data);
- hoedown_buffer_putc(ob, '>');
- } else {
- HOEDOWN_BUFPUTSL(ob, "\">");
- }
+ if (state->link_attributes) {
+ hoedown_buffer_putc(ob, '\"');
+ state->link_attributes(ob, link, data);
+ hoedown_buffer_putc(ob, '>');
+ } else {
+ HOEDOWN_BUFPUTSL(ob, "\">");
+ }
- if (content && content->size) hoedown_buffer_put(ob, content->data, content->size);
- HOEDOWN_BUFPUTSL(ob, "</a>");
- return 1;
+ if (content && content->size) hoedown_buffer_put(ob, content->data, content->size);
+ HOEDOWN_BUFPUTSL(ob, "</a>");
+ return 1;
}
static void
rndr_list(hoedown_buffer *ob, const hoedown_buffer *content, hoedown_list_flags flags, const hoedown_renderer_data *data)
{
- if (ob->size) hoedown_buffer_putc(ob, '\n');
- hoedown_buffer_put(ob, (const uint8_t *)(flags & HOEDOWN_LIST_ORDERED ? "<ol>\n" : "<ul>\n"), 5);
- if (content) hoedown_buffer_put(ob, content->data, content->size);
- hoedown_buffer_put(ob, (const uint8_t *)(flags & HOEDOWN_LIST_ORDERED ? "</ol>\n" : "</ul>\n"), 6);
+ if (ob->size) hoedown_buffer_putc(ob, '\n');
+ hoedown_buffer_put(ob, (const uint8_t *)(flags & HOEDOWN_LIST_ORDERED ? "<ol>\n" : "<ul>\n"), 5);
+ if (content) hoedown_buffer_put(ob, content->data, content->size);
+ hoedown_buffer_put(ob, (const uint8_t *)(flags & HOEDOWN_LIST_ORDERED ? "</ol>\n" : "</ul>\n"), 6);
}
static void
rndr_listitem(hoedown_buffer *ob, const hoedown_buffer *content, hoedown_list_flags flags, const hoedown_renderer_data *data)
{
- HOEDOWN_BUFPUTSL(ob, "<li>");
- if (content) {
- size_t size = content->size;
- while (size && content->data[size - 1] == '\n')
- size--;
+ HOEDOWN_BUFPUTSL(ob, "<li>");
+ if (content) {
+ size_t size = content->size;
+ while (size && content->data[size - 1] == '\n')
+ size--;
- hoedown_buffer_put(ob, content->data, size);
- }
- HOEDOWN_BUFPUTSL(ob, "</li>\n");
+ hoedown_buffer_put(ob, content->data, size);
+ }
+ HOEDOWN_BUFPUTSL(ob, "</li>\n");
}
static void
rndr_paragraph(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)
{
- hoedown_html_renderer_state *state = data->opaque;
- size_t i = 0;
+ hoedown_html_renderer_state *state = data->opaque;
+ size_t i = 0;
- if (ob->size) hoedown_buffer_putc(ob, '\n');
+ if (ob->size) hoedown_buffer_putc(ob, '\n');
- if (!content || !content->size)
- return;
+ if (!content || !content->size)
+ return;
- while (i < content->size && isspace(content->data[i])) i++;
+ while (i < content->size && isspace(content->data[i])) i++;
- if (i == content->size)
- return;
+ if (i == content->size)
+ return;
- HOEDOWN_BUFPUTSL(ob, "<p>");
- if (state->flags & HOEDOWN_HTML_HARD_WRAP) {
- size_t org;
- while (i < content->size) {
- org = i;
- while (i < content->size && content->data[i] != '\n')
- i++;
+ HOEDOWN_BUFPUTSL(ob, "<p>");
+ if (state->flags & HOEDOWN_HTML_HARD_WRAP) {
+ size_t org;
+ while (i < content->size) {
+ org = i;
+ while (i < content->size && content->data[i] != '\n')
+ i++;
- if (i > org)
- hoedown_buffer_put(ob, content->data + org, i - org);
+ if (i > org)
+ hoedown_buffer_put(ob, content->data + org, i - org);
- /*
- * do not insert a line break if this newline
- * is the last character on the paragraph
- */
- if (i >= content->size - 1)
- break;
+ /*
+ * do not insert a line break if this newline
+ * is the last character on the paragraph
+ */
+ if (i >= content->size - 1)
+ break;
- rndr_linebreak(ob, data);
- i++;
- }
- } else {
- hoedown_buffer_put(ob, content->data + i, content->size - i);
- }
- HOEDOWN_BUFPUTSL(ob, "</p>\n");
+ rndr_linebreak(ob, data);
+ i++;
+ }
+ } else {
+ hoedown_buffer_put(ob, content->data + i, content->size - i);
+ }
+ HOEDOWN_BUFPUTSL(ob, "</p>\n");
}
static void
rndr_raw_block(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data)
{
- size_t org, sz;
+ size_t org, sz;
- if (!text)
- return;
+ if (!text)
+ return;
- /* FIXME: Do we *really* need to trim the HTML? How does that make a difference? */
- sz = text->size;
- while (sz > 0 && text->data[sz - 1] == '\n')
- sz--;
+ /* FIXME: Do we *really* need to trim the HTML? How does that make a difference? */
+ sz = text->size;
+ while (sz > 0 && text->data[sz - 1] == '\n')
+ sz--;
- org = 0;
- while (org < sz && text->data[org] == '\n')
- org++;
+ org = 0;
+ while (org < sz && text->data[org] == '\n')
+ org++;
- if (org >= sz)
- return;
+ if (org >= sz)
+ return;
- if (ob->size)
- hoedown_buffer_putc(ob, '\n');
+ if (ob->size)
+ hoedown_buffer_putc(ob, '\n');
- hoedown_buffer_put(ob, text->data + org, sz - org);
- hoedown_buffer_putc(ob, '\n');
+ hoedown_buffer_put(ob, text->data + org, sz - org);
+ hoedown_buffer_putc(ob, '\n');
}
static int
rndr_triple_emphasis(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)
{
- if (!content || !content->size) return 0;
- HOEDOWN_BUFPUTSL(ob, "<strong><em>");
- hoedown_buffer_put(ob, content->data, content->size);
- HOEDOWN_BUFPUTSL(ob, "</em></strong>");
- return 1;
+ if (!content || !content->size) return 0;
+ HOEDOWN_BUFPUTSL(ob, "<strong><em>");
+ hoedown_buffer_put(ob, content->data, content->size);
+ HOEDOWN_BUFPUTSL(ob, "</em></strong>");
+ return 1;
}
static void
rndr_hrule(hoedown_buffer *ob, const hoedown_renderer_data *data)
{
- hoedown_html_renderer_state *state = data->opaque;
- if (ob->size) hoedown_buffer_putc(ob, '\n');
- hoedown_buffer_puts(ob, USE_XHTML(state) ? "<hr/>\n" : "<hr>\n");
+ hoedown_html_renderer_state *state = data->opaque;
+ if (ob->size) hoedown_buffer_putc(ob, '\n');
+ hoedown_buffer_puts(ob, USE_XHTML(state) ? "<hr/>\n" : "<hr>\n");
}
static int
rndr_image(hoedown_buffer *ob, const hoedown_buffer *link, const hoedown_buffer *title, const hoedown_buffer *alt, const hoedown_renderer_data *data)
{
- hoedown_html_renderer_state *state = data->opaque;
- if (!link || !link->size) return 0;
+ hoedown_html_renderer_state *state = data->opaque;
+ if (!link || !link->size) return 0;
- HOEDOWN_BUFPUTSL(ob, "<img src=\"");
- escape_href(ob, link->data, link->size);
- HOEDOWN_BUFPUTSL(ob, "\" alt=\"");
+ HOEDOWN_BUFPUTSL(ob, "<img src=\"");
+ escape_href(ob, link->data, link->size);
+ HOEDOWN_BUFPUTSL(ob, "\" alt=\"");
- if (alt && alt->size)
- escape_html(ob, alt->data, alt->size);
+ if (alt && alt->size)
+ escape_html(ob, alt->data, alt->size);
- if (title && title->size) {
- HOEDOWN_BUFPUTSL(ob, "\" title=\"");
- escape_html(ob, title->data, title->size); }
+ if (title && title->size) {
+ HOEDOWN_BUFPUTSL(ob, "\" title=\"");
+ escape_html(ob, title->data, title->size); }
- hoedown_buffer_puts(ob, USE_XHTML(state) ? "\"/>" : "\">");
- return 1;
+ hoedown_buffer_puts(ob, USE_XHTML(state) ? "\"/>" : "\">");
+ return 1;
}
static int
rndr_raw_html(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data)
{
- hoedown_html_renderer_state *state = data->opaque;
+ hoedown_html_renderer_state *state = data->opaque;
- /* ESCAPE overrides SKIP_HTML. It doesn't look to see if
- * there are any valid tags, just escapes all of them. */
- if((state->flags & HOEDOWN_HTML_ESCAPE) != 0) {
- escape_html(ob, text->data, text->size);
- return 1;
- }
+ /* ESCAPE overrides SKIP_HTML. It doesn't look to see if
+ * there are any valid tags, just escapes all of them. */
+ if((state->flags & HOEDOWN_HTML_ESCAPE) != 0) {
+ escape_html(ob, text->data, text->size);
+ return 1;
+ }
- if ((state->flags & HOEDOWN_HTML_SKIP_HTML) != 0)
- return 1;
+ if ((state->flags & HOEDOWN_HTML_SKIP_HTML) != 0)
+ return 1;
- hoedown_buffer_put(ob, text->data, text->size);
- return 1;
+ hoedown_buffer_put(ob, text->data, text->size);
+ return 1;
}
static void
@@ -437,318 +437,318 @@ rndr_table_body(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown
static void
rndr_tablerow(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)
{
- HOEDOWN_BUFPUTSL(ob, "<tr>\n");
- if (content) hoedown_buffer_put(ob, content->data, content->size);
- HOEDOWN_BUFPUTSL(ob, "</tr>\n");
+ HOEDOWN_BUFPUTSL(ob, "<tr>\n");
+ if (content) hoedown_buffer_put(ob, content->data, content->size);
+ HOEDOWN_BUFPUTSL(ob, "</tr>\n");
}
static void
rndr_tablecell(hoedown_buffer *ob, const hoedown_buffer *content, hoedown_table_flags flags, const hoedown_renderer_data *data)
{
- if (flags & HOEDOWN_TABLE_HEADER) {
- HOEDOWN_BUFPUTSL(ob, "<th");
- } else {
- HOEDOWN_BUFPUTSL(ob, "<td");
- }
+ if (flags & HOEDOWN_TABLE_HEADER) {
+ HOEDOWN_BUFPUTSL(ob, "<th");
+ } else {
+ HOEDOWN_BUFPUTSL(ob, "<td");
+ }
- switch (flags & HOEDOWN_TABLE_ALIGNMASK) {
- case HOEDOWN_TABLE_ALIGN_CENTER:
- HOEDOWN_BUFPUTSL(ob, " style=\"text-align: center\">");
- break;
+ switch (flags & HOEDOWN_TABLE_ALIGNMASK) {
+ case HOEDOWN_TABLE_ALIGN_CENTER:
+ HOEDOWN_BUFPUTSL(ob, " style=\"text-align: center\">");
+ break;
- case HOEDOWN_TABLE_ALIGN_LEFT:
- HOEDOWN_BUFPUTSL(ob, " style=\"text-align: left\">");
- break;
+ case HOEDOWN_TABLE_ALIGN_LEFT:
+ HOEDOWN_BUFPUTSL(ob, " style=\"text-align: left\">");
+ break;
- case HOEDOWN_TABLE_ALIGN_RIGHT:
- HOEDOWN_BUFPUTSL(ob, " style=\"text-align: right\">");
- break;
+ case HOEDOWN_TABLE_ALIGN_RIGHT:
+ HOEDOWN_BUFPUTSL(ob, " style=\"text-align: right\">");
+ break;
- default:
- HOEDOWN_BUFPUTSL(ob, ">");
- }
+ default:
+ HOEDOWN_BUFPUTSL(ob, ">");
+ }
- if (content)
- hoedown_buffer_put(ob, content->data, content->size);
+ if (content)
+ hoedown_buffer_put(ob, content->data, content->size);
- if (flags & HOEDOWN_TABLE_HEADER) {
- HOEDOWN_BUFPUTSL(ob, "</th>\n");
- } else {
- HOEDOWN_BUFPUTSL(ob, "</td>\n");
- }
+ if (flags & HOEDOWN_TABLE_HEADER) {
+ HOEDOWN_BUFPUTSL(ob, "</th>\n");
+ } else {
+ HOEDOWN_BUFPUTSL(ob, "</td>\n");
+ }
}
static int
rndr_superscript(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)
{
- if (!content || !content->size) return 0;
- HOEDOWN_BUFPUTSL(ob, "<sup>");
- hoedown_buffer_put(ob, content->data, content->size);
- HOEDOWN_BUFPUTSL(ob, "</sup>");
- return 1;
+ if (!content || !content->size) return 0;
+ HOEDOWN_BUFPUTSL(ob, "<sup>");
+ hoedown_buffer_put(ob, content->data, content->size);
+ HOEDOWN_BUFPUTSL(ob, "</sup>");
+ return 1;
}
static void
rndr_normal_text(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)
{
- if (content)
- escape_html(ob, content->data, content->size);
+ if (content)
+ escape_html(ob, content->data, content->size);
}
static void
rndr_footnotes(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)
{
- hoedown_html_renderer_state *state = data->opaque;
+ hoedown_html_renderer_state *state = data->opaque;
- if (ob->size) hoedown_buffer_putc(ob, '\n');
- HOEDOWN_BUFPUTSL(ob, "<div class=\"footnotes\">\n");
- hoedown_buffer_puts(ob, USE_XHTML(state) ? "<hr/>\n" : "<hr>\n");
- HOEDOWN_BUFPUTSL(ob, "<ol>\n");
+ if (ob->size) hoedown_buffer_putc(ob, '\n');
+ HOEDOWN_BUFPUTSL(ob, "<div class=\"footnotes\">\n");
+ hoedown_buffer_puts(ob, USE_XHTML(state) ? "<hr/>\n" : "<hr>\n");
+ HOEDOWN_BUFPUTSL(ob, "<ol>\n");
- if (content) hoedown_buffer_put(ob, content->data, content->size);
+ if (content) hoedown_buffer_put(ob, content->data, content->size);
- HOEDOWN_BUFPUTSL(ob, "\n</ol>\n</div>\n");
+ HOEDOWN_BUFPUTSL(ob, "\n</ol>\n</div>\n");
}
static void
rndr_footnote_def(hoedown_buffer *ob, const hoedown_buffer *content, unsigned int num, const hoedown_renderer_data *data)
{
- size_t i = 0;
- int pfound = 0;
-
- /* insert anchor at the end of first paragraph block */
- if (content) {
- while ((i+3) < content->size) {
- if (content->data[i++] != '<') continue;
- if (content->data[i++] != '/') continue;
- if (content->data[i++] != 'p' && content->data[i] != 'P') continue;
- if (content->data[i] != '>') continue;
- i -= 3;
- pfound = 1;
- break;
- }
- }
-
- hoedown_buffer_printf(ob, "\n<li id=\"fn%d\">\n", num);
- if (pfound) {
- hoedown_buffer_put(ob, content->data, i);
- hoedown_buffer_printf(ob, "&nbsp;<a href=\"#fnref%d\" rev=\"footnote\">&#8617;</a>", num);
- hoedown_buffer_put(ob, content->data + i, content->size - i);
- } else if (content) {
- hoedown_buffer_put(ob, content->data, content->size);
- }
- HOEDOWN_BUFPUTSL(ob, "</li>\n");
+ size_t i = 0;
+ int pfound = 0;
+
+ /* insert anchor at the end of first paragraph block */
+ if (content) {
+ while ((i+3) < content->size) {
+ if (content->data[i++] != '<') continue;
+ if (content->data[i++] != '/') continue;
+ if (content->data[i++] != 'p' && content->data[i] != 'P') continue;
+ if (content->data[i] != '>') continue;
+ i -= 3;
+ pfound = 1;
+ break;
+ }
+ }
+
+ hoedown_buffer_printf(ob, "\n<li id=\"fn%d\">\n", num);
+ if (pfound) {
+ hoedown_buffer_put(ob, content->data, i);
+ hoedown_buffer_printf(ob, "&nbsp;<a href=\"#fnref%d\" rev=\"footnote\">&#8617;</a>", num);
+ hoedown_buffer_put(ob, content->data + i, content->size - i);
+ } else if (content) {
+ hoedown_buffer_put(ob, content->data, content->size);
+ }
+ HOEDOWN_BUFPUTSL(ob, "</li>\n");
}
static int
rndr_footnote_ref(hoedown_buffer *ob, unsigned int num, const hoedown_renderer_data *data)
{
- hoedown_buffer_printf(ob, "<sup id=\"fnref%d\"><a href=\"#fn%d\" rel=\"footnote\">%d</a></sup>", num, num, num);
- return 1;
+ hoedown_buffer_printf(ob, "<sup id=\"fnref%d\"><a href=\"#fn%d\" rel=\"footnote\">%d</a></sup>", num, num, num);
+ return 1;
}
static int
rndr_math(hoedown_buffer *ob, const hoedown_buffer *text, int displaymode, const hoedown_renderer_data *data)
{
- hoedown_buffer_put(ob, (const uint8_t *)(displaymode ? "\\[" : "\\("), 2);
- escape_html(ob, text->data, text->size);
- hoedown_buffer_put(ob, (const uint8_t *)(displaymode ? "\\]" : "\\)"), 2);
- return 1;
+ hoedown_buffer_put(ob, (const uint8_t *)(displaymode ? "\\[" : "\\("), 2);
+ escape_html(ob, text->data, text->size);
+ hoedown_buffer_put(ob, (const uint8_t *)(displaymode ? "\\]" : "\\)"), 2);
+ return 1;
}
static void
toc_header(hoedown_buffer *ob, const hoedown_buffer *content, int level, const hoedown_renderer_data *data)
{
- hoedown_html_renderer_state *state = data->opaque;
-
- if (level <= state->toc_data.nesting_level) {
- /* set the level offset if this is the first header
- * we're parsing for the document */
- if (state->toc_data.current_level == 0)
- state->toc_data.level_offset = level - 1;
-
- level -= state->toc_data.level_offset;
-
- if (level > state->toc_data.current_level) {
- while (level > state->toc_data.current_level) {
- HOEDOWN_BUFPUTSL(ob, "<ul>\n<li>\n");
- state->toc_data.current_level++;
- }
- } else if (level < state->toc_data.current_level) {
- HOEDOWN_BUFPUTSL(ob, "</li>\n");
- while (level < state->toc_data.current_level) {
- HOEDOWN_BUFPUTSL(ob, "</ul>\n</li>\n");
- state->toc_data.current_level--;
- }
- HOEDOWN_BUFPUTSL(ob,"<li>\n");
- } else {
- HOEDOWN_BUFPUTSL(ob,"</li>\n<li>\n");
- }
-
- hoedown_buffer_printf(ob, "<a href=\"#toc_%d\">", state->toc_data.header_count++);
- if (content) hoedown_buffer_put(ob, content->data, content->size);
- HOEDOWN_BUFPUTSL(ob, "</a>\n");
- }
+ hoedown_html_renderer_state *state = data->opaque;
+
+ if (level <= state->toc_data.nesting_level) {
+ /* set the level offset if this is the first header
+ * we're parsing for the document */
+ if (state->toc_data.current_level == 0)
+ state->toc_data.level_offset = level - 1;
+
+ level -= state->toc_data.level_offset;
+
+ if (level > state->toc_data.current_level) {
+ while (level > state->toc_data.current_level) {
+ HOEDOWN_BUFPUTSL(ob, "<ul>\n<li>\n");
+ state->toc_data.current_level++;
+ }
+ } else if (level < state->toc_data.current_level) {
+ HOEDOWN_BUFPUTSL(ob, "</li>\n");
+ while (level < state->toc_data.current_level) {
+ HOEDOWN_BUFPUTSL(ob, "</ul>\n</li>\n");
+ state->toc_data.current_level--;
+ }
+ HOEDOWN_BUFPUTSL(ob,"<li>\n");
+ } else {
+ HOEDOWN_BUFPUTSL(ob,"</li>\n<li>\n");
+ }
+
+ hoedown_buffer_printf(ob, "<a href=\"#toc_%d\">", state->toc_data.header_count++);
+ if (content) hoedown_buffer_put(ob, content->data, content->size);
+ HOEDOWN_BUFPUTSL(ob, "</a>\n");
+ }
}
static int
toc_link(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_buffer *link, const hoedown_buffer *title, const hoedown_renderer_data *data)
{
- if (content && content->size) hoedown_buffer_put(ob, content->data, content->size);
- return 1;
+ if (content && content->size) hoedown_buffer_put(ob, content->data, content->size);
+ return 1;
}
static void
toc_finalize(hoedown_buffer *ob, int inline_render, const hoedown_renderer_data *data)
{
- hoedown_html_renderer_state *state;
+ hoedown_html_renderer_state *state;
- if (inline_render)
- return;
+ if (inline_render)
+ return;
- state = data->opaque;
+ state = data->opaque;
- while (state->toc_data.current_level > 0) {
- HOEDOWN_BUFPUTSL(ob, "</li>\n</ul>\n");
- state->toc_data.current_level--;
- }
+ while (state->toc_data.current_level > 0) {
+ HOEDOWN_BUFPUTSL(ob, "</li>\n</ul>\n");
+ state->toc_data.current_level--;
+ }
- state->toc_data.header_count = 0;
+ state->toc_data.header_count = 0;
}
hoedown_renderer *
hoedown_html_toc_renderer_new(int nesting_level)
{
- static const hoedown_renderer cb_default = {
- NULL,
-
- NULL,
- NULL,
- toc_header,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
-
- NULL,
- rndr_codespan,
- rndr_double_emphasis,
- rndr_emphasis,
- rndr_underline,
- rndr_highlight,
- rndr_quote,
- NULL,
- NULL,
- toc_link,
- rndr_triple_emphasis,
- rndr_strikethrough,
- rndr_superscript,
- NULL,
- NULL,
- NULL,
-
- NULL,
- rndr_normal_text,
-
- NULL,
- toc_finalize
- };
-
- hoedown_html_renderer_state *state;
- hoedown_renderer *renderer;
-
- /* Prepare the state pointer */
- state = hoedown_malloc(sizeof(hoedown_html_renderer_state));
- memset(state, 0x0, sizeof(hoedown_html_renderer_state));
-
- state->toc_data.nesting_level = nesting_level;
-
- /* Prepare the renderer */
- renderer = hoedown_malloc(sizeof(hoedown_renderer));
- memcpy(renderer, &cb_default, sizeof(hoedown_renderer));
-
- renderer->opaque = state;
- return renderer;
+ static const hoedown_renderer cb_default = {
+ NULL,
+
+ NULL,
+ NULL,
+ toc_header,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+
+ NULL,
+ rndr_codespan,
+ rndr_double_emphasis,
+ rndr_emphasis,
+ rndr_underline,
+ rndr_highlight,
+ rndr_quote,
+ NULL,
+ NULL,
+ toc_link,
+ rndr_triple_emphasis,
+ rndr_strikethrough,
+ rndr_superscript,
+ NULL,
+ NULL,
+ NULL,
+
+ NULL,
+ rndr_normal_text,
+
+ NULL,
+ toc_finalize
+ };
+
+ hoedown_html_renderer_state *state;
+ hoedown_renderer *renderer;
+
+ /* Prepare the state pointer */
+ state = hoedown_malloc(sizeof(hoedown_html_renderer_state));
+ memset(state, 0x0, sizeof(hoedown_html_renderer_state));
+
+ state->toc_data.nesting_level = nesting_level;
+
+ /* Prepare the renderer */
+ renderer = hoedown_malloc(sizeof(hoedown_renderer));
+ memcpy(renderer, &cb_default, sizeof(hoedown_renderer));
+
+ renderer->opaque = state;
+ return renderer;
}
hoedown_renderer *
hoedown_html_renderer_new(hoedown_html_flags render_flags, int nesting_level)
{
- static const hoedown_renderer cb_default = {
- NULL,
-
- rndr_blockcode,
- rndr_blockquote,
- rndr_header,
- rndr_hrule,
- rndr_list,
- rndr_listitem,
- rndr_paragraph,
- rndr_table,
- rndr_table_header,
- rndr_table_body,
- rndr_tablerow,
- rndr_tablecell,
- rndr_footnotes,
- rndr_footnote_def,
- rndr_raw_block,
-
- rndr_autolink,
- rndr_codespan,
- rndr_double_emphasis,
- rndr_emphasis,
- rndr_underline,
- rndr_highlight,
- rndr_quote,
- rndr_image,
- rndr_linebreak,
- rndr_link,
- rndr_triple_emphasis,
- rndr_strikethrough,
- rndr_superscript,
- rndr_footnote_ref,
- rndr_math,
- rndr_raw_html,
-
- NULL,
- rndr_normal_text,
-
- NULL,
- NULL
- };
-
- hoedown_html_renderer_state *state;
- hoedown_renderer *renderer;
-
- /* Prepare the state pointer */
- state = hoedown_malloc(sizeof(hoedown_html_renderer_state));
- memset(state, 0x0, sizeof(hoedown_html_renderer_state));
-
- state->flags = render_flags;
- state->toc_data.nesting_level = nesting_level;
-
- /* Prepare the renderer */
- renderer = hoedown_malloc(sizeof(hoedown_renderer));
- memcpy(renderer, &cb_default, sizeof(hoedown_renderer));
-
- if (render_flags & HOEDOWN_HTML_SKIP_HTML || render_flags & HOEDOWN_HTML_ESCAPE)
- renderer->blockhtml = NULL;
-
- renderer->opaque = state;
- return renderer;
+ static const hoedown_renderer cb_default = {
+ NULL,
+
+ rndr_blockcode,
+ rndr_blockquote,
+ rndr_header,
+ rndr_hrule,
+ rndr_list,
+ rndr_listitem,
+ rndr_paragraph,
+ rndr_table,
+ rndr_table_header,
+ rndr_table_body,
+ rndr_tablerow,
+ rndr_tablecell,
+ rndr_footnotes,
+ rndr_footnote_def,
+ rndr_raw_block,
+
+ rndr_autolink,
+ rndr_codespan,
+ rndr_double_emphasis,
+ rndr_emphasis,
+ rndr_underline,
+ rndr_highlight,
+ rndr_quote,
+ rndr_image,
+ rndr_linebreak,
+ rndr_link,
+ rndr_triple_emphasis,
+ rndr_strikethrough,
+ rndr_superscript,
+ rndr_footnote_ref,
+ rndr_math,
+ rndr_raw_html,
+
+ NULL,
+ rndr_normal_text,
+
+ NULL,
+ NULL
+ };
+
+ hoedown_html_renderer_state *state;
+ hoedown_renderer *renderer;
+
+ /* Prepare the state pointer */
+ state = hoedown_malloc(sizeof(hoedown_html_renderer_state));
+ memset(state, 0x0, sizeof(hoedown_html_renderer_state));
+
+ state->flags = render_flags;
+ state->toc_data.nesting_level = nesting_level;
+
+ /* Prepare the renderer */
+ renderer = hoedown_malloc(sizeof(hoedown_renderer));
+ memcpy(renderer, &cb_default, sizeof(hoedown_renderer));
+
+ if (render_flags & HOEDOWN_HTML_SKIP_HTML || render_flags & HOEDOWN_HTML_ESCAPE)
+ renderer->blockhtml = NULL;
+
+ renderer->opaque = state;
+ return renderer;
}
void
hoedown_html_renderer_free(hoedown_renderer *renderer)
{
- free(renderer->opaque);
- free(renderer);
+ free(renderer->opaque);
+ free(renderer);
}
diff --git a/libraries/hoedown/src/html_smartypants.c b/libraries/hoedown/src/html_smartypants.c
index e24b6bf0..d89624f3 100644
--- a/libraries/hoedown/src/html_smartypants.c
+++ b/libraries/hoedown/src/html_smartypants.c
@@ -10,8 +10,8 @@
#endif
struct smartypants_data {
- int in_squote;
- int in_dquote;
+ int in_squote;
+ int in_dquote;
};
static size_t smartypants_cb__ltag(hoedown_buffer *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size);
@@ -26,353 +26,353 @@ static size_t smartypants_cb__backtick(hoedown_buffer *ob, struct smartypants_da
static size_t smartypants_cb__escape(hoedown_buffer *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size);
static size_t (*smartypants_cb_ptrs[])
- (hoedown_buffer *, struct smartypants_data *, uint8_t, const uint8_t *, size_t) =
+ (hoedown_buffer *, struct smartypants_data *, uint8_t, const uint8_t *, size_t) =
{
- NULL, /* 0 */
- smartypants_cb__dash, /* 1 */
- smartypants_cb__parens, /* 2 */
- smartypants_cb__squote, /* 3 */
- smartypants_cb__dquote, /* 4 */
- smartypants_cb__amp, /* 5 */
- smartypants_cb__period, /* 6 */
- smartypants_cb__number, /* 7 */
- smartypants_cb__ltag, /* 8 */
- smartypants_cb__backtick, /* 9 */
- smartypants_cb__escape, /* 10 */
+ NULL, /* 0 */
+ smartypants_cb__dash, /* 1 */
+ smartypants_cb__parens, /* 2 */
+ smartypants_cb__squote, /* 3 */
+ smartypants_cb__dquote, /* 4 */
+ smartypants_cb__amp, /* 5 */
+ smartypants_cb__period, /* 6 */
+ smartypants_cb__number, /* 7 */
+ smartypants_cb__ltag, /* 8 */
+ smartypants_cb__backtick, /* 9 */
+ smartypants_cb__escape, /* 10 */
};
static const uint8_t smartypants_cb_chars[UINT8_MAX+1] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 4, 0, 0, 0, 5, 3, 2, 0, 0, 0, 0, 1, 6, 0,
- 0, 7, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0,
- 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 4, 0, 0, 0, 5, 3, 2, 0, 0, 0, 0, 1, 6, 0,
+ 0, 7, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0,
+ 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
static int
word_boundary(uint8_t c)
{
- return c == 0 || isspace(c) || ispunct(c);
+ return c == 0 || isspace(c) || ispunct(c);
}
/*
- If 'text' begins with any kind of single quote (e.g. "'" or "&apos;" etc.),
- returns the length of the sequence of characters that makes up the single-
- quote. Otherwise, returns zero.
+ If 'text' begins with any kind of single quote (e.g. "'" or "&apos;" etc.),
+ returns the length of the sequence of characters that makes up the single-
+ quote. Otherwise, returns zero.
*/
static size_t
squote_len(const uint8_t *text, size_t size)
{
- static char* single_quote_list[] = { "'", "&#39;", "&#x27;", "&apos;", NULL };
- char** p;
+ static char* single_quote_list[] = { "'", "&#39;", "&#x27;", "&apos;", NULL };
+ char** p;
- for (p = single_quote_list; *p; ++p) {
- size_t len = strlen(*p);
- if (size >= len && memcmp(text, *p, len) == 0) {
- return len;
- }
- }
+ for (p = single_quote_list; *p; ++p) {
+ size_t len = strlen(*p);
+ if (size >= len && memcmp(text, *p, len) == 0) {
+ return len;
+ }
+ }
- return 0;
+ return 0;
}
/* Converts " or ' at very beginning or end of a word to left or right quote */
static int
smartypants_quotes(hoedown_buffer *ob, uint8_t previous_char, uint8_t next_char, uint8_t quote, int *is_open)
{
- char ent[8];
+ char ent[8];
- if (*is_open && !word_boundary(next_char))
- return 0;
+ if (*is_open && !word_boundary(next_char))
+ return 0;
- if (!(*is_open) && !word_boundary(previous_char))
- return 0;
+ if (!(*is_open) && !word_boundary(previous_char))
+ return 0;
- snprintf(ent, sizeof(ent), "&%c%cquo;", (*is_open) ? 'r' : 'l', quote);
- *is_open = !(*is_open);
- hoedown_buffer_puts(ob, ent);
- return 1;
+ snprintf(ent, sizeof(ent), "&%c%cquo;", (*is_open) ? 'r' : 'l', quote);
+ *is_open = !(*is_open);
+ hoedown_buffer_puts(ob, ent);
+ return 1;
}
/*
- Converts ' to left or right single quote; but the initial ' might be in
- different forms, e.g. &apos; or &#39; or &#x27;.
- 'squote_text' points to the original single quote, and 'squote_size' is its length.
- 'text' points at the last character of the single-quote, e.g. ' or ;
+ Converts ' to left or right single quote; but the initial ' might be in
+ different forms, e.g. &apos; or &#39; or &#x27;.
+ 'squote_text' points to the original single quote, and 'squote_size' is its length.
+ 'text' points at the last character of the single-quote, e.g. ' or ;
*/
static size_t
smartypants_squote(hoedown_buffer *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size,
- const uint8_t *squote_text, size_t squote_size)
+ const uint8_t *squote_text, size_t squote_size)
{
- if (size >= 2) {
- uint8_t t1 = tolower(text[1]);
- size_t next_squote_len = squote_len(text+1, size-1);
-
- /* convert '' to &ldquo; or &rdquo; */
- if (next_squote_len > 0) {
- uint8_t next_char = (size > 1+next_squote_len) ? text[1+next_squote_len] : 0;
- if (smartypants_quotes(ob, previous_char, next_char, 'd', &smrt->in_dquote))
- return next_squote_len;
- }
-
- /* Tom's, isn't, I'm, I'd */
- if ((t1 == 's' || t1 == 't' || t1 == 'm' || t1 == 'd') &&
- (size == 3 || word_boundary(text[2]))) {
- HOEDOWN_BUFPUTSL(ob, "&rsquo;");
- return 0;
- }
-
- /* you're, you'll, you've */
- if (size >= 3) {
- uint8_t t2 = tolower(text[2]);
-
- if (((t1 == 'r' && t2 == 'e') ||
- (t1 == 'l' && t2 == 'l') ||
- (t1 == 'v' && t2 == 'e')) &&
- (size == 4 || word_boundary(text[3]))) {
- HOEDOWN_BUFPUTSL(ob, "&rsquo;");
- return 0;
- }
- }
- }
-
- if (smartypants_quotes(ob, previous_char, size > 0 ? text[1] : 0, 's', &smrt->in_squote))
- return 0;
-
- hoedown_buffer_put(ob, squote_text, squote_size);
- return 0;
+ if (size >= 2) {
+ uint8_t t1 = tolower(text[1]);
+ size_t next_squote_len = squote_len(text+1, size-1);
+
+ /* convert '' to &ldquo; or &rdquo; */
+ if (next_squote_len > 0) {
+ uint8_t next_char = (size > 1+next_squote_len) ? text[1+next_squote_len] : 0;
+ if (smartypants_quotes(ob, previous_char, next_char, 'd', &smrt->in_dquote))
+ return next_squote_len;
+ }
+
+ /* Tom's, isn't, I'm, I'd */
+ if ((t1 == 's' || t1 == 't' || t1 == 'm' || t1 == 'd') &&
+ (size == 3 || word_boundary(text[2]))) {
+ HOEDOWN_BUFPUTSL(ob, "&rsquo;");
+ return 0;
+ }
+
+ /* you're, you'll, you've */
+ if (size >= 3) {
+ uint8_t t2 = tolower(text[2]);
+
+ if (((t1 == 'r' && t2 == 'e') ||
+ (t1 == 'l' && t2 == 'l') ||
+ (t1 == 'v' && t2 == 'e')) &&
+ (size == 4 || word_boundary(text[3]))) {
+ HOEDOWN_BUFPUTSL(ob, "&rsquo;");
+ return 0;
+ }
+ }
+ }
+
+ if (smartypants_quotes(ob, previous_char, size > 0 ? text[1] : 0, 's', &smrt->in_squote))
+ return 0;
+
+ hoedown_buffer_put(ob, squote_text, squote_size);
+ return 0;
}
/* Converts ' to left or right single quote. */
static size_t
smartypants_cb__squote(hoedown_buffer *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size)
{
- return smartypants_squote(ob, smrt, previous_char, text, size, text, 1);
+ return smartypants_squote(ob, smrt, previous_char, text, size, text, 1);
}
/* Converts (c), (r), (tm) */
static size_t
smartypants_cb__parens(hoedown_buffer *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size)
{
- if (size >= 3) {
- uint8_t t1 = tolower(text[1]);
- uint8_t t2 = tolower(text[2]);
-
- if (t1 == 'c' && t2 == ')') {
- HOEDOWN_BUFPUTSL(ob, "&copy;");
- return 2;
- }
-
- if (t1 == 'r' && t2 == ')') {
- HOEDOWN_BUFPUTSL(ob, "&reg;");
- return 2;
- }
-
- if (size >= 4 && t1 == 't' && t2 == 'm' && text[3] == ')') {
- HOEDOWN_BUFPUTSL(ob, "&trade;");
- return 3;
- }
- }
-
- hoedown_buffer_putc(ob, text[0]);
- return 0;
+ if (size >= 3) {
+ uint8_t t1 = tolower(text[1]);
+ uint8_t t2 = tolower(text[2]);
+
+ if (t1 == 'c' && t2 == ')') {
+ HOEDOWN_BUFPUTSL(ob, "&copy;");
+ return 2;
+ }
+
+ if (t1 == 'r' && t2 == ')') {
+ HOEDOWN_BUFPUTSL(ob, "&reg;");
+ return 2;
+ }
+
+ if (size >= 4 && t1 == 't' && t2 == 'm' && text[3] == ')') {
+ HOEDOWN_BUFPUTSL(ob, "&trade;");
+ return 3;
+ }
+ }
+
+ hoedown_buffer_putc(ob, text[0]);
+ return 0;
}
/* Converts "--" to em-dash, etc. */
static size_t
smartypants_cb__dash(hoedown_buffer *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size)
{
- if (size >= 3 && text[1] == '-' && text[2] == '-') {
- HOEDOWN_BUFPUTSL(ob, "&mdash;");
- return 2;
- }
-
- if (size >= 2 && text[1] == '-') {
- HOEDOWN_BUFPUTSL(ob, "&ndash;");
- return 1;
- }
-
- hoedown_buffer_putc(ob, text[0]);
- return 0;
+ if (size >= 3 && text[1] == '-' && text[2] == '-') {
+ HOEDOWN_BUFPUTSL(ob, "&mdash;");
+ return 2;
+ }
+
+ if (size >= 2 && text[1] == '-') {
+ HOEDOWN_BUFPUTSL(ob, "&ndash;");
+ return 1;
+ }
+
+ hoedown_buffer_putc(ob, text[0]);
+ return 0;
}
/* Converts &quot; etc. */
static size_t
smartypants_cb__amp(hoedown_buffer *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size)
{
- size_t len;
- if (size >= 6 && memcmp(text, "&quot;", 6) == 0) {
- if (smartypants_quotes(ob, previous_char, size >= 7 ? text[6] : 0, 'd', &smrt->in_dquote))
- return 5;
- }
-
- len = squote_len(text, size);
- if (len > 0) {
- return (len-1) + smartypants_squote(ob, smrt, previous_char, text+(len-1), size-(len-1), text, len);
- }
-
- if (size >= 4 && memcmp(text, "&#0;", 4) == 0)
- return 3;
-
- hoedown_buffer_putc(ob, '&');
- return 0;
+ size_t len;
+ if (size >= 6 && memcmp(text, "&quot;", 6) == 0) {
+ if (smartypants_quotes(ob, previous_char, size >= 7 ? text[6] : 0, 'd', &smrt->in_dquote))
+ return 5;
+ }
+
+ len = squote_len(text, size);
+ if (len > 0) {
+ return (len-1) + smartypants_squote(ob, smrt, previous_char, text+(len-1), size-(len-1), text, len);
+ }
+
+ if (size >= 4 && memcmp(text, "&#0;", 4) == 0)
+ return 3;
+
+ hoedown_buffer_putc(ob, '&');
+ return 0;
}
/* Converts "..." to ellipsis */
static size_t
smartypants_cb__period(hoedown_buffer *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size)
{
- if (size >= 3 && text[1] == '.' && text[2] == '.') {
- HOEDOWN_BUFPUTSL(ob, "&hellip;");
- return 2;
- }
-
- if (size >= 5 && text[1] == ' ' && text[2] == '.' && text[3] == ' ' && text[4] == '.') {
- HOEDOWN_BUFPUTSL(ob, "&hellip;");
- return 4;
- }
-
- hoedown_buffer_putc(ob, text[0]);
- return 0;
+ if (size >= 3 && text[1] == '.' && text[2] == '.') {
+ HOEDOWN_BUFPUTSL(ob, "&hellip;");
+ return 2;
+ }
+
+ if (size >= 5 && text[1] == ' ' && text[2] == '.' && text[3] == ' ' && text[4] == '.') {
+ HOEDOWN_BUFPUTSL(ob, "&hellip;");
+ return 4;
+ }
+
+ hoedown_buffer_putc(ob, text[0]);
+ return 0;
}
/* Converts `` to opening double quote */
static size_t
smartypants_cb__backtick(hoedown_buffer *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size)
{
- if (size >= 2 && text[1] == '`') {
- if (smartypants_quotes(ob, previous_char, size >= 3 ? text[2] : 0, 'd', &smrt->in_dquote))
- return 1;
- }
+ if (size >= 2 && text[1] == '`') {
+ if (smartypants_quotes(ob, previous_char, size >= 3 ? text[2] : 0, 'd', &smrt->in_dquote))
+ return 1;
+ }
- hoedown_buffer_putc(ob, text[0]);
- return 0;
+ hoedown_buffer_putc(ob, text[0]);
+ return 0;
}
/* Converts 1/2, 1/4, 3/4 */
static size_t
smartypants_cb__number(hoedown_buffer *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size)
{
- if (word_boundary(previous_char) && size >= 3) {
- if (text[0] == '1' && text[1] == '/' && text[2] == '2') {
- if (size == 3 || word_boundary(text[3])) {
- HOEDOWN_BUFPUTSL(ob, "&frac12;");
- return 2;
- }
- }
-
- if (text[0] == '1' && text[1] == '/' && text[2] == '4') {
- if (size == 3 || word_boundary(text[3]) ||
- (size >= 5 && tolower(text[3]) == 't' && tolower(text[4]) == 'h')) {
- HOEDOWN_BUFPUTSL(ob, "&frac14;");
- return 2;
- }
- }
-
- if (text[0] == '3' && text[1] == '/' && text[2] == '4') {
- if (size == 3 || word_boundary(text[3]) ||
- (size >= 6 && tolower(text[3]) == 't' && tolower(text[4]) == 'h' && tolower(text[5]) == 's')) {
- HOEDOWN_BUFPUTSL(ob, "&frac34;");
- return 2;
- }
- }
- }
-
- hoedown_buffer_putc(ob, text[0]);
- return 0;
+ if (word_boundary(previous_char) && size >= 3) {
+ if (text[0] == '1' && text[1] == '/' && text[2] == '2') {
+ if (size == 3 || word_boundary(text[3])) {
+ HOEDOWN_BUFPUTSL(ob, "&frac12;");
+ return 2;
+ }
+ }
+
+ if (text[0] == '1' && text[1] == '/' && text[2] == '4') {
+ if (size == 3 || word_boundary(text[3]) ||
+ (size >= 5 && tolower(text[3]) == 't' && tolower(text[4]) == 'h')) {
+ HOEDOWN_BUFPUTSL(ob, "&frac14;");
+ return 2;
+ }
+ }
+
+ if (text[0] == '3' && text[1] == '/' && text[2] == '4') {
+ if (size == 3 || word_boundary(text[3]) ||
+ (size >= 6 && tolower(text[3]) == 't' && tolower(text[4]) == 'h' && tolower(text[5]) == 's')) {
+ HOEDOWN_BUFPUTSL(ob, "&frac34;");
+ return 2;
+ }
+ }
+ }
+
+ hoedown_buffer_putc(ob, text[0]);
+ return 0;
}
/* Converts " to left or right double quote */
static size_t
smartypants_cb__dquote(hoedown_buffer *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size)
{
- if (!smartypants_quotes(ob, previous_char, size > 0 ? text[1] : 0, 'd', &smrt->in_dquote))
- HOEDOWN_BUFPUTSL(ob, "&quot;");
+ if (!smartypants_quotes(ob, previous_char, size > 0 ? text[1] : 0, 'd', &smrt->in_dquote))
+ HOEDOWN_BUFPUTSL(ob, "&quot;");
- return 0;
+ return 0;
}
static size_t
smartypants_cb__ltag(hoedown_buffer *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size)
{
- static const char *skip_tags[] = {
- "pre", "code", "var", "samp", "kbd", "math", "script", "style"
- };
- static const size_t skip_tags_count = 8;
-
- size_t tag, i = 0;
-
- /* This is a comment. Copy everything verbatim until --> or EOF is seen. */
- if (i + 4 < size && memcmp(text, "<!--", 4) == 0) {
- i += 4;
- while (i + 3 < size && memcmp(text + i, "-->", 3) != 0)
- i++;
- i += 3;
- hoedown_buffer_put(ob, text, i + 1);
- return i;
- }
-
- while (i < size && text[i] != '>')
- i++;
-
- for (tag = 0; tag < skip_tags_count; ++tag) {
- if (hoedown_html_is_tag(text, size, skip_tags[tag]) == HOEDOWN_HTML_TAG_OPEN)
- break;
- }
-
- if (tag < skip_tags_count) {
- for (;;) {
- while (i < size && text[i] != '<')
- i++;
-
- if (i == size)
- break;
-
- if (hoedown_html_is_tag(text + i, size - i, skip_tags[tag]) == HOEDOWN_HTML_TAG_CLOSE)
- break;
-
- i++;
- }
-
- while (i < size && text[i] != '>')
- i++;
- }
-
- hoedown_buffer_put(ob, text, i + 1);
- return i;
+ static const char *skip_tags[] = {
+ "pre", "code", "var", "samp", "kbd", "math", "script", "style"
+ };
+ static const size_t skip_tags_count = 8;
+
+ size_t tag, i = 0;
+
+ /* This is a comment. Copy everything verbatim until --> or EOF is seen. */
+ if (i + 4 < size && memcmp(text, "<!--", 4) == 0) {
+ i += 4;
+ while (i + 3 < size && memcmp(text + i, "-->", 3) != 0)
+ i++;
+ i += 3;
+ hoedown_buffer_put(ob, text, i + 1);
+ return i;
+ }
+
+ while (i < size && text[i] != '>')
+ i++;
+
+ for (tag = 0; tag < skip_tags_count; ++tag) {
+ if (hoedown_html_is_tag(text, size, skip_tags[tag]) == HOEDOWN_HTML_TAG_OPEN)
+ break;
+ }
+
+ if (tag < skip_tags_count) {
+ for (;;) {
+ while (i < size && text[i] != '<')
+ i++;
+
+ if (i == size)
+ break;
+
+ if (hoedown_html_is_tag(text + i, size - i, skip_tags[tag]) == HOEDOWN_HTML_TAG_CLOSE)
+ break;
+
+ i++;
+ }
+
+ while (i < size && text[i] != '>')
+ i++;
+ }
+
+ hoedown_buffer_put(ob, text, i + 1);
+ return i;
}
static size_t
smartypants_cb__escape(hoedown_buffer *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size)
{
- if (size < 2)
- return 0;
-
- switch (text[1]) {
- case '\\':
- case '"':
- case '\'':
- case '.':
- case '-':
- case '`':
- hoedown_buffer_putc(ob, text[1]);
- return 1;
-
- default:
- hoedown_buffer_putc(ob, '\\');
- return 0;
- }
+ if (size < 2)
+ return 0;
+
+ switch (text[1]) {
+ case '\\':
+ case '"':
+ case '\'':
+ case '.':
+ case '-':
+ case '`':
+ hoedown_buffer_putc(ob, text[1]);
+ return 1;
+
+ default:
+ hoedown_buffer_putc(ob, '\\');
+ return 0;
+ }
}
#if 0
@@ -408,28 +408,28 @@ static struct {
void
hoedown_html_smartypants(hoedown_buffer *ob, const uint8_t *text, size_t size)
{
- size_t i;
- struct smartypants_data smrt = {0, 0};
+ size_t i;
+ struct smartypants_data smrt = {0, 0};
- if (!text)
- return;
+ if (!text)
+ return;
- hoedown_buffer_grow(ob, size);
+ hoedown_buffer_grow(ob, size);
- for (i = 0; i < size; ++i) {
- size_t org;
- uint8_t action = 0;
+ for (i = 0; i < size; ++i) {
+ size_t org;
+ uint8_t action = 0;
- org = i;
- while (i < size && (action = smartypants_cb_chars[text[i]]) == 0)
- i++;
+ org = i;
+ while (i < size && (action = smartypants_cb_chars[text[i]]) == 0)
+ i++;
- if (i > org)
- hoedown_buffer_put(ob, text + org, i - org);
+ if (i > org)
+ hoedown_buffer_put(ob, text + org, i - org);
- if (i < size) {
- i += smartypants_cb_ptrs[(int)action]
- (ob, &smrt, i ? text[i - 1] : 0, text + i, size - i);
- }
- }
+ if (i < size) {
+ i += smartypants_cb_ptrs[(int)action]
+ (ob, &smrt, i ? text[i - 1] : 0, text + i, size - i);
+ }
+ }
}
diff --git a/libraries/hoedown/src/stack.c b/libraries/hoedown/src/stack.c
index 46ead232..0523c11b 100644
--- a/libraries/hoedown/src/stack.c
+++ b/libraries/hoedown/src/stack.c
@@ -9,71 +9,71 @@
void
hoedown_stack_init(hoedown_stack *st, size_t initial_size)
{
- assert(st);
+ assert(st);
- st->item = NULL;
- st->size = st->asize = 0;
+ st->item = NULL;
+ st->size = st->asize = 0;
- if (!initial_size)
- initial_size = 8;
+ if (!initial_size)
+ initial_size = 8;
- hoedown_stack_grow(st, initial_size);
+ hoedown_stack_grow(st, initial_size);
}
void
hoedown_stack_uninit(hoedown_stack *st)
{
- assert(st);
+ assert(st);
- free(st->item);
+ free(st->item);
}
void
hoedown_stack_grow(hoedown_stack *st, size_t neosz)
{
- assert(st);
+ assert(st);
- if (st->asize >= neosz)
- return;
+ if (st->asize >= neosz)
+ return;
- st->item = hoedown_realloc(st->item, neosz * sizeof(void *));
- memset(st->item + st->asize, 0x0, (neosz - st->asize) * sizeof(void *));
+ st->item = hoedown_realloc(st->item, neosz * sizeof(void *));
+ memset(st->item + st->asize, 0x0, (neosz - st->asize) * sizeof(void *));
- st->asize = neosz;
+ st->asize = neosz;
- if (st->size > neosz)
- st->size = neosz;
+ if (st->size > neosz)
+ st->size = neosz;
}
void
hoedown_stack_push(hoedown_stack *st, void *item)
{
- assert(st);
+ assert(st);
- if (st->size >= st->asize)
- hoedown_stack_grow(st, st->size * 2);
+ if (st->size >= st->asize)
+ hoedown_stack_grow(st, st->size * 2);
- st->item[st->size++] = item;
+ st->item[st->size++] = item;
}
void *
hoedown_stack_pop(hoedown_stack *st)
{
- assert(st);
+ assert(st);
- if (!st->size)
- return NULL;
+ if (!st->size)
+ return NULL;
- return st->item[--st->size];
+ return st->item[--st->size];
}
void *
hoedown_stack_top(const hoedown_stack *st)
{
- assert(st);
+ assert(st);
- if (!st->size)
- return NULL;
+ if (!st->size)
+ return NULL;
- return st->item[st->size - 1];
+ return st->item[st->size - 1];
}
diff --git a/libraries/hoedown/src/version.c b/libraries/hoedown/src/version.c
index 625ed196..10d36cb9 100644
--- a/libraries/hoedown/src/version.c
+++ b/libraries/hoedown/src/version.c
@@ -3,7 +3,7 @@
void
hoedown_version(int *major, int *minor, int *revision)
{
- *major = HOEDOWN_VERSION_MAJOR;
- *minor = HOEDOWN_VERSION_MINOR;
- *revision = HOEDOWN_VERSION_REVISION;
+ *major = HOEDOWN_VERSION_MAJOR;
+ *minor = HOEDOWN_VERSION_MINOR;
+ *revision = HOEDOWN_VERSION_REVISION;
}
diff --git a/libraries/iconfix/CMakeLists.txt b/libraries/iconfix/CMakeLists.txt
index 93bfdd06..ccf0edea 100644
--- a/libraries/iconfix/CMakeLists.txt
+++ b/libraries/iconfix/CMakeLists.txt
@@ -15,14 +15,14 @@ internal/qiconloader_p.h
add_library(MultiMC_iconfix SHARED ${ICONFIX_SOURCES})
target_include_directories(MultiMC_iconfix PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} "${CMAKE_CURRENT_BINARY_DIR}" )
-qt5_use_modules(MultiMC_iconfix Core Widgets)
+target_link_libraries(MultiMC_iconfix Qt5::Core Qt5::Widgets)
set_target_properties(MultiMC_iconfix PROPERTIES CXX_VISIBILITY_PRESET hidden VISIBILITY_INLINES_HIDDEN 1)
generate_export_header(MultiMC_iconfix)
# Install it
install(
- TARGETS MultiMC_iconfix
- RUNTIME DESTINATION ${LIBRARY_DEST_DIR}
- LIBRARY DESTINATION ${LIBRARY_DEST_DIR}
+ TARGETS MultiMC_iconfix
+ RUNTIME DESTINATION ${LIBRARY_DEST_DIR}
+ LIBRARY DESTINATION ${LIBRARY_DEST_DIR}
) \ No newline at end of file
diff --git a/libraries/iconfix/internal/qhexstring_p.h b/libraries/iconfix/internal/qhexstring_p.h
index f01b4cdd..c81904e5 100644
--- a/libraries/iconfix/internal/qhexstring_p.h
+++ b/libraries/iconfix/internal/qhexstring_p.h
@@ -61,40 +61,40 @@
// internal helper. Converts an integer value to an unique string token
template <typename T> struct HexString
{
- inline HexString(const T t) : val(t)
- {
- }
+ inline HexString(const T t) : val(t)
+ {
+ }
- inline void write(QChar *&dest) const
- {
- const ushort hexChars[] = {'0', '1', '2', '3', '4', '5', '6', '7',
- '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
- const char *c = reinterpret_cast<const char *>(&val);
- for (uint i = 0; i < sizeof(T); ++i)
- {
- *dest++ = hexChars[*c & 0xf];
- *dest++ = hexChars[(*c & 0xf0) >> 4];
- ++c;
- }
- }
- const T val;
+ inline void write(QChar *&dest) const
+ {
+ const ushort hexChars[] = {'0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
+ const char *c = reinterpret_cast<const char *>(&val);
+ for (uint i = 0; i < sizeof(T); ++i)
+ {
+ *dest++ = hexChars[*c & 0xf];
+ *dest++ = hexChars[(*c & 0xf0) >> 4];
+ ++c;
+ }
+ }
+ const T val;
};
// specialization to enable fast concatenating of our string tokens to a string
template <typename T> struct QConcatenable<HexString<T>>
{
- typedef HexString<T> type;
- enum
- {
- ExactSize = true
- };
- static int size(const HexString<T> &)
- {
- return sizeof(T) * 2;
- }
- static inline void appendTo(const HexString<T> &str, QChar *&out)
- {
- str.write(out);
- }
- typedef QString ConvertTo;
+ typedef HexString<T> type;
+ enum
+ {
+ ExactSize = true
+ };
+ static int size(const HexString<T> &)
+ {
+ return sizeof(T) * 2;
+ }
+ static inline void appendTo(const HexString<T> &str, QChar *&out)
+ {
+ str.write(out);
+ }
+ typedef QString ConvertTo;
};
diff --git a/libraries/iconfix/internal/qiconloader.cpp b/libraries/iconfix/internal/qiconloader.cpp
index b1195893..41cf3d50 100644
--- a/libraries/iconfix/internal/qiconloader.cpp
+++ b/libraries/iconfix/internal/qiconloader.cpp
@@ -55,7 +55,7 @@ Q_GLOBAL_STATIC(QIconLoader, iconLoaderInstance)
static QString fallbackTheme()
{
- return QString("hicolor");
+ return QString("hicolor");
}
QIconLoader::QIconLoader() : m_themeKey(1), m_supportsSvg(false), m_initialized(false)
@@ -67,403 +67,403 @@ QIconLoader::QIconLoader() : m_themeKey(1), m_supportsSvg(false), m_initialized(
static inline QString systemThemeName()
{
- return QIcon::themeName();
+ return QIcon::themeName();
}
static inline QStringList systemIconSearchPaths()
{
- auto paths = QIcon::themeSearchPaths();
- paths.push_front(":/icons");
- return paths;
+ auto paths = QIcon::themeSearchPaths();
+ paths.push_front(":/icons");
+ return paths;
}
void QIconLoader::ensureInitialized()
{
- if (!m_initialized)
- {
- m_initialized = true;
+ if (!m_initialized)
+ {
+ m_initialized = true;
- Q_ASSERT(qApp);
+ Q_ASSERT(qApp);
- m_systemTheme = QIcon::themeName();
+ m_systemTheme = QIcon::themeName();
- if (m_systemTheme.isEmpty())
- m_systemTheme = fallbackTheme();
- m_supportsSvg = true;
- }
+ if (m_systemTheme.isEmpty())
+ m_systemTheme = fallbackTheme();
+ m_supportsSvg = true;
+ }
}
QIconLoader *QIconLoader::instance()
{
- iconLoaderInstance()->ensureInitialized();
- return iconLoaderInstance();
+ iconLoaderInstance()->ensureInitialized();
+ return iconLoaderInstance();
}
// Queries the system theme and invalidates existing
// icons if the theme has changed.
void QIconLoader::updateSystemTheme()
{
- // Only change if this is not explicitly set by the user
- if (m_userTheme.isEmpty())
- {
- QString theme = systemThemeName();
- if (theme.isEmpty())
- theme = fallbackTheme();
- if (theme != m_systemTheme)
- {
- m_systemTheme = theme;
- invalidateKey();
- }
- }
+ // Only change if this is not explicitly set by the user
+ if (m_userTheme.isEmpty())
+ {
+ QString theme = systemThemeName();
+ if (theme.isEmpty())
+ theme = fallbackTheme();
+ if (theme != m_systemTheme)
+ {
+ m_systemTheme = theme;
+ invalidateKey();
+ }
+ }
}
void QIconLoader::setThemeName(const QString &themeName)
{
- m_userTheme = themeName;
- invalidateKey();
+ m_userTheme = themeName;
+ invalidateKey();
}
void QIconLoader::setThemeSearchPath(const QStringList &searchPaths)
{
- m_iconDirs = searchPaths;
- themeList.clear();
- invalidateKey();
+ m_iconDirs = searchPaths;
+ themeList.clear();
+ invalidateKey();
}
QStringList QIconLoader::themeSearchPaths() const
{
- if (m_iconDirs.isEmpty())
- {
- m_iconDirs = systemIconSearchPaths();
- }
- return m_iconDirs;
+ if (m_iconDirs.isEmpty())
+ {
+ m_iconDirs = systemIconSearchPaths();
+ }
+ return m_iconDirs;
}
QIconTheme::QIconTheme(const QString &themeName) : m_valid(false)
{
- QFile themeIndex;
-
- QStringList iconDirs = systemIconSearchPaths();
- for (int i = 0; i < iconDirs.size(); ++i)
- {
- QDir iconDir(iconDirs[i]);
- QString themeDir = iconDir.path() + QLatin1Char('/') + themeName;
- themeIndex.setFileName(themeDir + QLatin1String("/index.theme"));
- if (themeIndex.exists())
- {
- m_contentDir = themeDir;
- m_valid = true;
-
- foreach (QString path, iconDirs)
- {
- if (QFileInfo(path).isDir())
- m_contentDirs.append(path + QLatin1Char('/') + themeName);
- }
-
- break;
- }
- }
-
- // if there is no index file, abscond.
- if (!themeIndex.exists())
- return;
-
- // otherwise continue reading index file
- const QSettings indexReader(themeIndex.fileName(), QSettings::IniFormat);
- QStringListIterator keyIterator(indexReader.allKeys());
- while (keyIterator.hasNext())
- {
- const QString key = keyIterator.next();
- if (!key.endsWith(QLatin1String("/Size")))
- continue;
-
- // Note the QSettings ini-format does not accept
- // slashes in key names, hence we have to cheat
- int size = indexReader.value(key).toInt();
- if (!size)
- continue;
-
- QString directoryKey = key.left(key.size() - 5);
- QIconDirInfo dirInfo(directoryKey);
- dirInfo.size = size;
- QString type =
- indexReader.value(directoryKey + QLatin1String("/Type")).toString();
-
- if (type == QLatin1String("Fixed"))
- dirInfo.type = QIconDirInfo::Fixed;
- else if (type == QLatin1String("Scalable"))
- dirInfo.type = QIconDirInfo::Scalable;
- else
- dirInfo.type = QIconDirInfo::Threshold;
-
- dirInfo.threshold =
- indexReader.value(directoryKey + QLatin1String("/Threshold"), 2)
- .toInt();
-
- dirInfo.minSize =
- indexReader.value(directoryKey + QLatin1String("/MinSize"), size)
- .toInt();
-
- dirInfo.maxSize =
- indexReader.value(directoryKey + QLatin1String("/MaxSize"), size)
- .toInt();
- m_keyList.append(dirInfo);
- }
-
- // Parent themes provide fallbacks for missing icons
- m_parents = indexReader.value(QLatin1String("Icon Theme/Inherits")).toStringList();
- m_parents.removeAll(QString());
-
- // Ensure a default platform fallback for all themes
- if (m_parents.isEmpty())
- {
- const QString fallback = fallbackTheme();
- if (!fallback.isEmpty())
- m_parents.append(fallback);
- }
-
- // Ensure that all themes fall back to hicolor
- if (!m_parents.contains(QLatin1String("hicolor")))
- m_parents.append(QLatin1String("hicolor"));
+ QFile themeIndex;
+
+ QStringList iconDirs = systemIconSearchPaths();
+ for (int i = 0; i < iconDirs.size(); ++i)
+ {
+ QDir iconDir(iconDirs[i]);
+ QString themeDir = iconDir.path() + QLatin1Char('/') + themeName;
+ themeIndex.setFileName(themeDir + QLatin1String("/index.theme"));
+ if (themeIndex.exists())
+ {
+ m_contentDir = themeDir;
+ m_valid = true;
+
+ foreach (QString path, iconDirs)
+ {
+ if (QFileInfo(path).isDir())
+ m_contentDirs.append(path + QLatin1Char('/') + themeName);
+ }
+
+ break;
+ }
+ }
+
+ // if there is no index file, abscond.
+ if (!themeIndex.exists())
+ return;
+
+ // otherwise continue reading index file
+ const QSettings indexReader(themeIndex.fileName(), QSettings::IniFormat);
+ QStringListIterator keyIterator(indexReader.allKeys());
+ while (keyIterator.hasNext())
+ {
+ const QString key = keyIterator.next();
+ if (!key.endsWith(QLatin1String("/Size")))
+ continue;
+
+ // Note the QSettings ini-format does not accept
+ // slashes in key names, hence we have to cheat
+ int size = indexReader.value(key).toInt();
+ if (!size)
+ continue;
+
+ QString directoryKey = key.left(key.size() - 5);
+ QIconDirInfo dirInfo(directoryKey);
+ dirInfo.size = size;
+ QString type =
+ indexReader.value(directoryKey + QLatin1String("/Type")).toString();
+
+ if (type == QLatin1String("Fixed"))
+ dirInfo.type = QIconDirInfo::Fixed;
+ else if (type == QLatin1String("Scalable"))
+ dirInfo.type = QIconDirInfo::Scalable;
+ else
+ dirInfo.type = QIconDirInfo::Threshold;
+
+ dirInfo.threshold =
+ indexReader.value(directoryKey + QLatin1String("/Threshold"), 2)
+ .toInt();
+
+ dirInfo.minSize =
+ indexReader.value(directoryKey + QLatin1String("/MinSize"), size)
+ .toInt();
+
+ dirInfo.maxSize =
+ indexReader.value(directoryKey + QLatin1String("/MaxSize"), size)
+ .toInt();
+ m_keyList.append(dirInfo);
+ }
+
+ // Parent themes provide fallbacks for missing icons
+ m_parents = indexReader.value(QLatin1String("Icon Theme/Inherits")).toStringList();
+ m_parents.removeAll(QString());
+
+ // Ensure a default platform fallback for all themes
+ if (m_parents.isEmpty())
+ {
+ const QString fallback = fallbackTheme();
+ if (!fallback.isEmpty())
+ m_parents.append(fallback);
+ }
+
+ // Ensure that all themes fall back to hicolor
+ if (!m_parents.contains(QLatin1String("hicolor")))
+ m_parents.append(QLatin1String("hicolor"));
}
QThemeIconEntries QIconLoader::findIconHelper(const QString &themeName, const QString &iconName,
- QStringList &visited) const
-{
- QThemeIconEntries entries;
- Q_ASSERT(!themeName.isEmpty());
-
- QPixmap pixmap;
-
- // Used to protect against potential recursions
- visited << themeName;
-
- QIconTheme theme = themeList.value(themeName);
- if (!theme.isValid())
- {
- theme = QIconTheme(themeName);
- if (!theme.isValid())
- theme = QIconTheme(fallbackTheme());
-
- themeList.insert(themeName, theme);
- }
-
- QStringList contentDirs = theme.contentDirs();
- const QVector<QIconDirInfo> subDirs = theme.keyList();
-
- const QString svgext(QLatin1String(".svg"));
- const QString pngext(QLatin1String(".png"));
- const QString xpmext(QLatin1String(".xpm"));
-
- // Add all relevant files
- for (int i = 0; i < subDirs.size(); ++i)
- {
- const QIconDirInfo &dirInfo = subDirs.at(i);
- QString subdir = dirInfo.path;
-
- foreach (QString contentDir, contentDirs)
- {
- QDir currentDir(contentDir + '/' + subdir);
-
- if (currentDir.exists(iconName + pngext))
- {
- PixmapEntry *iconEntry = new PixmapEntry;
- iconEntry->dir = dirInfo;
- iconEntry->filename = currentDir.filePath(iconName + pngext);
- // Notice we ensure that pixmap entries always come before
- // scalable to preserve search order afterwards
- entries.prepend(iconEntry);
- }
- else if (m_supportsSvg && currentDir.exists(iconName + svgext))
- {
- ScalableEntry *iconEntry = new ScalableEntry;
- iconEntry->dir = dirInfo;
- iconEntry->filename = currentDir.filePath(iconName + svgext);
- entries.append(iconEntry);
- break;
- }
- else if (currentDir.exists(iconName + xpmext))
- {
- PixmapEntry *iconEntry = new PixmapEntry;
- iconEntry->dir = dirInfo;
- iconEntry->filename = currentDir.filePath(iconName + xpmext);
- // Notice we ensure that pixmap entries always come before
- // scalable to preserve search order afterwards
- entries.append(iconEntry);
- break;
- }
- }
- }
-
- if (entries.isEmpty())
- {
- const QStringList parents = theme.parents();
- // Search recursively through inherited themes
- for (int i = 0; i < parents.size(); ++i)
- {
-
- const QString parentTheme = parents.at(i).trimmed();
-
- if (!visited.contains(parentTheme)) // guard against recursion
- entries = findIconHelper(parentTheme, iconName, visited);
-
- if (!entries.isEmpty()) // success
- break;
- }
- }
+ QStringList &visited) const
+{
+ QThemeIconEntries entries;
+ Q_ASSERT(!themeName.isEmpty());
+
+ QPixmap pixmap;
+
+ // Used to protect against potential recursions
+ visited << themeName;
+
+ QIconTheme theme = themeList.value(themeName);
+ if (!theme.isValid())
+ {
+ theme = QIconTheme(themeName);
+ if (!theme.isValid())
+ theme = QIconTheme(fallbackTheme());
+
+ themeList.insert(themeName, theme);
+ }
+
+ QStringList contentDirs = theme.contentDirs();
+ const QVector<QIconDirInfo> subDirs = theme.keyList();
+
+ const QString svgext(QLatin1String(".svg"));
+ const QString pngext(QLatin1String(".png"));
+ const QString xpmext(QLatin1String(".xpm"));
+
+ // Add all relevant files
+ for (int i = 0; i < subDirs.size(); ++i)
+ {
+ const QIconDirInfo &dirInfo = subDirs.at(i);
+ QString subdir = dirInfo.path;
+
+ foreach (QString contentDir, contentDirs)
+ {
+ QDir currentDir(contentDir + '/' + subdir);
+
+ if (currentDir.exists(iconName + pngext))
+ {
+ PixmapEntry *iconEntry = new PixmapEntry;
+ iconEntry->dir = dirInfo;
+ iconEntry->filename = currentDir.filePath(iconName + pngext);
+ // Notice we ensure that pixmap entries always come before
+ // scalable to preserve search order afterwards
+ entries.prepend(iconEntry);
+ }
+ else if (m_supportsSvg && currentDir.exists(iconName + svgext))
+ {
+ ScalableEntry *iconEntry = new ScalableEntry;
+ iconEntry->dir = dirInfo;
+ iconEntry->filename = currentDir.filePath(iconName + svgext);
+ entries.append(iconEntry);
+ break;
+ }
+ else if (currentDir.exists(iconName + xpmext))
+ {
+ PixmapEntry *iconEntry = new PixmapEntry;
+ iconEntry->dir = dirInfo;
+ iconEntry->filename = currentDir.filePath(iconName + xpmext);
+ // Notice we ensure that pixmap entries always come before
+ // scalable to preserve search order afterwards
+ entries.append(iconEntry);
+ break;
+ }
+ }
+ }
+
+ if (entries.isEmpty())
+ {
+ const QStringList parents = theme.parents();
+ // Search recursively through inherited themes
+ for (int i = 0; i < parents.size(); ++i)
+ {
+
+ const QString parentTheme = parents.at(i).trimmed();
+
+ if (!visited.contains(parentTheme)) // guard against recursion
+ entries = findIconHelper(parentTheme, iconName, visited);
+
+ if (!entries.isEmpty()) // success
+ break;
+ }
+ }
/*********************************************************************
Author: Kaitlin Rupert <kaitlin.rupert@intel.com>
Date: Aug 12, 2010
Description: Make it so that the QIcon loader honors /usr/share/pixmaps
- directory. This is a valid directory per the Freedesktop.org
- icon theme specification.
+ directory. This is a valid directory per the Freedesktop.org
+ icon theme specification.
Bug: https://bugreports.qt.nokia.com/browse/QTBUG-12874
*********************************************************************/
#ifdef Q_OS_LINUX
- /* Freedesktop standard says to look in /usr/share/pixmaps last */
- if (entries.isEmpty())
- {
- const QString pixmaps(QLatin1String("/usr/share/pixmaps"));
-
- QDir currentDir(pixmaps);
- QIconDirInfo dirInfo(pixmaps);
- if (currentDir.exists(iconName + pngext))
- {
- PixmapEntry *iconEntry = new PixmapEntry;
- iconEntry->dir = dirInfo;
- iconEntry->filename = currentDir.filePath(iconName + pngext);
- // Notice we ensure that pixmap entries always come before
- // scalable to preserve search order afterwards
- entries.prepend(iconEntry);
- }
- else if (m_supportsSvg && currentDir.exists(iconName + svgext))
- {
- ScalableEntry *iconEntry = new ScalableEntry;
- iconEntry->dir = dirInfo;
- iconEntry->filename = currentDir.filePath(iconName + svgext);
- entries.append(iconEntry);
- }
- else if (currentDir.exists(iconName + xpmext))
- {
- PixmapEntry *iconEntry = new PixmapEntry;
- iconEntry->dir = dirInfo;
- iconEntry->filename = currentDir.filePath(iconName + xpmext);
- // Notice we ensure that pixmap entries always come before
- // scalable to preserve search order afterwards
- entries.append(iconEntry);
- }
- }
+ /* Freedesktop standard says to look in /usr/share/pixmaps last */
+ if (entries.isEmpty())
+ {
+ const QString pixmaps(QLatin1String("/usr/share/pixmaps"));
+
+ QDir currentDir(pixmaps);
+ QIconDirInfo dirInfo(pixmaps);
+ if (currentDir.exists(iconName + pngext))
+ {
+ PixmapEntry *iconEntry = new PixmapEntry;
+ iconEntry->dir = dirInfo;
+ iconEntry->filename = currentDir.filePath(iconName + pngext);
+ // Notice we ensure that pixmap entries always come before
+ // scalable to preserve search order afterwards
+ entries.prepend(iconEntry);
+ }
+ else if (m_supportsSvg && currentDir.exists(iconName + svgext))
+ {
+ ScalableEntry *iconEntry = new ScalableEntry;
+ iconEntry->dir = dirInfo;
+ iconEntry->filename = currentDir.filePath(iconName + svgext);
+ entries.append(iconEntry);
+ }
+ else if (currentDir.exists(iconName + xpmext))
+ {
+ PixmapEntry *iconEntry = new PixmapEntry;
+ iconEntry->dir = dirInfo;
+ iconEntry->filename = currentDir.filePath(iconName + xpmext);
+ // Notice we ensure that pixmap entries always come before
+ // scalable to preserve search order afterwards
+ entries.append(iconEntry);
+ }
+ }
#endif
- if (entries.isEmpty())
- {
- // Search for unthemed icons in main dir of search paths
- QStringList themeSearchPaths = QIcon::themeSearchPaths();
- foreach (QString contentDir, themeSearchPaths)
- {
- QDir currentDir(contentDir);
-
- if (currentDir.exists(iconName + pngext))
- {
- PixmapEntry *iconEntry = new PixmapEntry;
- iconEntry->filename = currentDir.filePath(iconName + pngext);
- // Notice we ensure that pixmap entries always come before
- // scalable to preserve search order afterwards
- entries.prepend(iconEntry);
- }
- else if (m_supportsSvg && currentDir.exists(iconName + svgext))
- {
- ScalableEntry *iconEntry = new ScalableEntry;
- iconEntry->filename = currentDir.filePath(iconName + svgext);
- entries.append(iconEntry);
- break;
- }
- else if (currentDir.exists(iconName + xpmext))
- {
- PixmapEntry *iconEntry = new PixmapEntry;
- iconEntry->filename = currentDir.filePath(iconName + xpmext);
- // Notice we ensure that pixmap entries always come before
- // scalable to preserve search order afterwards
- entries.append(iconEntry);
- break;
- }
- }
- }
- return entries;
+ if (entries.isEmpty())
+ {
+ // Search for unthemed icons in main dir of search paths
+ QStringList themeSearchPaths = QIcon::themeSearchPaths();
+ foreach (QString contentDir, themeSearchPaths)
+ {
+ QDir currentDir(contentDir);
+
+ if (currentDir.exists(iconName + pngext))
+ {
+ PixmapEntry *iconEntry = new PixmapEntry;
+ iconEntry->filename = currentDir.filePath(iconName + pngext);
+ // Notice we ensure that pixmap entries always come before
+ // scalable to preserve search order afterwards
+ entries.prepend(iconEntry);
+ }
+ else if (m_supportsSvg && currentDir.exists(iconName + svgext))
+ {
+ ScalableEntry *iconEntry = new ScalableEntry;
+ iconEntry->filename = currentDir.filePath(iconName + svgext);
+ entries.append(iconEntry);
+ break;
+ }
+ else if (currentDir.exists(iconName + xpmext))
+ {
+ PixmapEntry *iconEntry = new PixmapEntry;
+ iconEntry->filename = currentDir.filePath(iconName + xpmext);
+ // Notice we ensure that pixmap entries always come before
+ // scalable to preserve search order afterwards
+ entries.append(iconEntry);
+ break;
+ }
+ }
+ }
+ return entries;
}
QThemeIconEntries QIconLoader::loadIcon(const QString &name) const
{
- if (!themeName().isEmpty())
- {
- QStringList visited;
- return findIconHelper(themeName(), name, visited);
- }
+ if (!themeName().isEmpty())
+ {
+ QStringList visited;
+ return findIconHelper(themeName(), name, visited);
+ }
- return QThemeIconEntries();
+ return QThemeIconEntries();
}
// -------- Icon Loader Engine -------- //
QIconLoaderEngineFixed::QIconLoaderEngineFixed(const QString &iconName)
- : m_iconName(iconName), m_key(0)
+ : m_iconName(iconName), m_key(0)
{
}
QIconLoaderEngineFixed::~QIconLoaderEngineFixed()
{
- qDeleteAll(m_entries);
+ qDeleteAll(m_entries);
}
QIconLoaderEngineFixed::QIconLoaderEngineFixed(const QIconLoaderEngineFixed &other)
- : QIconEngine(other), m_iconName(other.m_iconName), m_key(0)
+ : QIconEngine(other), m_iconName(other.m_iconName), m_key(0)
{
}
QIconEngine *QIconLoaderEngineFixed::clone() const
{
- return new QIconLoaderEngineFixed(*this);
+ return new QIconLoaderEngineFixed(*this);
}
bool QIconLoaderEngineFixed::read(QDataStream &in)
{
- in >> m_iconName;
- return true;
+ in >> m_iconName;
+ return true;
}
bool QIconLoaderEngineFixed::write(QDataStream &out) const
{
- out << m_iconName;
- return true;
+ out << m_iconName;
+ return true;
}
bool QIconLoaderEngineFixed::hasIcon() const
{
- return !(m_entries.isEmpty());
+ return !(m_entries.isEmpty());
}
// Lazily load the icon
void QIconLoaderEngineFixed::ensureLoaded()
{
- if (!(QIconLoader::instance()->themeKey() == m_key))
- {
+ if (!(QIconLoader::instance()->themeKey() == m_key))
+ {
- qDeleteAll(m_entries);
+ qDeleteAll(m_entries);
- m_entries = QIconLoader::instance()->loadIcon(m_iconName);
- m_key = QIconLoader::instance()->themeKey();
- }
+ m_entries = QIconLoader::instance()->loadIcon(m_iconName);
+ m_key = QIconLoader::instance()->themeKey();
+ }
}
void QIconLoaderEngineFixed::paint(QPainter *painter, const QRect &rect, QIcon::Mode mode,
- QIcon::State state)
+ QIcon::State state)
{
- QSize pixmapSize = rect.size();
+ QSize pixmapSize = rect.size();
#if defined(Q_WS_MAC)
- pixmapSize *= qt_mac_get_scalefactor();
+ pixmapSize *= qt_mac_get_scalefactor();
#endif
- painter->drawPixmap(rect, pixmap(pixmapSize, mode, state));
+ painter->drawPixmap(rect, pixmap(pixmapSize, mode, state));
}
/*
@@ -472,21 +472,21 @@ void QIconLoaderEngineFixed::paint(QPainter *painter, const QRect &rect, QIcon::
*/
static bool directoryMatchesSize(const QIconDirInfo &dir, int iconsize)
{
- if (dir.type == QIconDirInfo::Fixed)
- {
- return dir.size == iconsize;
- }
- else if (dir.type == QIconDirInfo::Scalable)
- {
- return dir.size <= dir.maxSize && iconsize >= dir.minSize;
- }
- else if (dir.type == QIconDirInfo::Threshold)
- {
- return iconsize >= dir.size - dir.threshold && iconsize <= dir.size + dir.threshold;
- }
-
- Q_ASSERT(1); // Not a valid value
- return false;
+ if (dir.type == QIconDirInfo::Fixed)
+ {
+ return dir.size == iconsize;
+ }
+ else if (dir.type == QIconDirInfo::Scalable)
+ {
+ return dir.size <= dir.maxSize && iconsize >= dir.minSize;
+ }
+ else if (dir.type == QIconDirInfo::Threshold)
+ {
+ return iconsize >= dir.size - dir.threshold && iconsize <= dir.size + dir.threshold;
+ }
+
+ Q_ASSERT(1); // Not a valid value
+ return false;
}
/*
@@ -495,66 +495,66 @@ static bool directoryMatchesSize(const QIconDirInfo &dir, int iconsize)
*/
static int directorySizeDistance(const QIconDirInfo &dir, int iconsize)
{
- if (dir.type == QIconDirInfo::Fixed)
- {
- return qAbs(dir.size - iconsize);
- }
- else if (dir.type == QIconDirInfo::Scalable)
- {
- if (iconsize < dir.minSize)
- return dir.minSize - iconsize;
- else if (iconsize > dir.maxSize)
- return iconsize - dir.maxSize;
- else
- return 0;
- }
- else if (dir.type == QIconDirInfo::Threshold)
- {
- if (iconsize < dir.size - dir.threshold)
- return dir.minSize - iconsize;
- else if (iconsize > dir.size + dir.threshold)
- return iconsize - dir.maxSize;
- else
- return 0;
- }
-
- Q_ASSERT(1); // Not a valid value
- return INT_MAX;
+ if (dir.type == QIconDirInfo::Fixed)
+ {
+ return qAbs(dir.size - iconsize);
+ }
+ else if (dir.type == QIconDirInfo::Scalable)
+ {
+ if (iconsize < dir.minSize)
+ return dir.minSize - iconsize;
+ else if (iconsize > dir.maxSize)
+ return iconsize - dir.maxSize;
+ else
+ return 0;
+ }
+ else if (dir.type == QIconDirInfo::Threshold)
+ {
+ if (iconsize < dir.size - dir.threshold)
+ return dir.minSize - iconsize;
+ else if (iconsize > dir.size + dir.threshold)
+ return iconsize - dir.maxSize;
+ else
+ return 0;
+ }
+
+ Q_ASSERT(1); // Not a valid value
+ return INT_MAX;
}
QIconLoaderEngineEntry *QIconLoaderEngineFixed::entryForSize(const QSize &size)
{
- int iconsize = qMin(size.width(), size.height());
-
- // Note that m_entries are sorted so that png-files
- // come first
-
- const int numEntries = m_entries.size();
-
- // Search for exact matches first
- for (int i = 0; i < numEntries; ++i)
- {
- QIconLoaderEngineEntry *entry = m_entries.at(i);
- if (directoryMatchesSize(entry->dir, iconsize))
- {
- return entry;
- }
- }
-
- // Find the minimum distance icon
- int minimalSize = INT_MAX;
- QIconLoaderEngineEntry *closestMatch = 0;
- for (int i = 0; i < numEntries; ++i)
- {
- QIconLoaderEngineEntry *entry = m_entries.at(i);
- int distance = directorySizeDistance(entry->dir, iconsize);
- if (distance < minimalSize)
- {
- minimalSize = distance;
- closestMatch = entry;
- }
- }
- return closestMatch;
+ int iconsize = qMin(size.width(), size.height());
+
+ // Note that m_entries are sorted so that png-files
+ // come first
+
+ const int numEntries = m_entries.size();
+
+ // Search for exact matches first
+ for (int i = 0; i < numEntries; ++i)
+ {
+ QIconLoaderEngineEntry *entry = m_entries.at(i);
+ if (directoryMatchesSize(entry->dir, iconsize))
+ {
+ return entry;
+ }
+ }
+
+ // Find the minimum distance icon
+ int minimalSize = INT_MAX;
+ QIconLoaderEngineEntry *closestMatch = 0;
+ for (int i = 0; i < numEntries; ++i)
+ {
+ QIconLoaderEngineEntry *entry = m_entries.at(i);
+ int distance = directorySizeDistance(entry->dir, iconsize);
+ if (distance < minimalSize)
+ {
+ minimalSize = distance;
+ closestMatch = entry;
+ }
+ }
+ return closestMatch;
}
/*
@@ -564,125 +564,125 @@ QIconLoaderEngineEntry *QIconLoaderEngineFixed::entryForSize(const QSize &size)
*
*/
QSize QIconLoaderEngineFixed::actualSize(const QSize &size, QIcon::Mode mode,
- QIcon::State state)
-{
- ensureLoaded();
-
- QIconLoaderEngineEntry *entry = entryForSize(size);
- if (entry)
- {
- const QIconDirInfo &dir = entry->dir;
- if (dir.type == QIconDirInfo::Scalable)
- return size;
- else
- {
- int result = qMin<int>(dir.size, qMin(size.width(), size.height()));
- return QSize(result, result);
- }
- }
- return QIconEngine::actualSize(size, mode, state);
+ QIcon::State state)
+{
+ ensureLoaded();
+
+ QIconLoaderEngineEntry *entry = entryForSize(size);
+ if (entry)
+ {
+ const QIconDirInfo &dir = entry->dir;
+ if (dir.type == QIconDirInfo::Scalable)
+ return size;
+ else
+ {
+ int result = qMin<int>(dir.size, qMin(size.width(), size.height()));
+ return QSize(result, result);
+ }
+ }
+ return QIconEngine::actualSize(size, mode, state);
}
QPixmap PixmapEntry::pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state)
{
- Q_UNUSED(state);
-
- // Ensure that basePixmap is lazily initialized before generating the
- // key, otherwise the cache key is not unique
- if (basePixmap.isNull())
- basePixmap.load(filename);
-
- QSize actualSize = basePixmap.size();
- if (!actualSize.isNull() &&
- (actualSize.width() > size.width() || actualSize.height() > size.height()))
- actualSize.scale(size, Qt::KeepAspectRatio);
-
- QString key = QLatin1String("$qt_theme_") % HexString<qint64>(basePixmap.cacheKey()) %
- HexString<int>(mode) %
- HexString<qint64>(QGuiApplication::palette().cacheKey()) %
- HexString<int>(actualSize.width()) % HexString<int>(actualSize.height());
-
- QPixmap cachedPixmap;
- if (QPixmapCache::find(key, &cachedPixmap))
- {
- return cachedPixmap;
- }
- else
- {
- if (basePixmap.size() != actualSize)
- {
- cachedPixmap = basePixmap.scaled(actualSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
- }
- else
- {
- cachedPixmap = basePixmap;
- }
- QPixmapCache::insert(key, cachedPixmap);
- }
- return cachedPixmap;
+ Q_UNUSED(state);
+
+ // Ensure that basePixmap is lazily initialized before generating the
+ // key, otherwise the cache key is not unique
+ if (basePixmap.isNull())
+ basePixmap.load(filename);
+
+ QSize actualSize = basePixmap.size();
+ if (!actualSize.isNull() &&
+ (actualSize.width() > size.width() || actualSize.height() > size.height()))
+ actualSize.scale(size, Qt::KeepAspectRatio);
+
+ QString key = QLatin1String("$qt_theme_") % HexString<qint64>(basePixmap.cacheKey()) %
+ HexString<int>(mode) %
+ HexString<qint64>(QGuiApplication::palette().cacheKey()) %
+ HexString<int>(actualSize.width()) % HexString<int>(actualSize.height());
+
+ QPixmap cachedPixmap;
+ if (QPixmapCache::find(key, &cachedPixmap))
+ {
+ return cachedPixmap;
+ }
+ else
+ {
+ if (basePixmap.size() != actualSize)
+ {
+ cachedPixmap = basePixmap.scaled(actualSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
+ }
+ else
+ {
+ cachedPixmap = basePixmap;
+ }
+ QPixmapCache::insert(key, cachedPixmap);
+ }
+ return cachedPixmap;
}
QPixmap ScalableEntry::pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state)
{
- if (svgIcon.isNull())
- {
- svgIcon = QIcon(filename);
- }
+ if (svgIcon.isNull())
+ {
+ svgIcon = QIcon(filename);
+ }
- // Simply reuse svg icon engine
- return svgIcon.pixmap(size, mode, state);
+ // Simply reuse svg icon engine
+ return svgIcon.pixmap(size, mode, state);
}
QPixmap QIconLoaderEngineFixed::pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state)
{
- ensureLoaded();
+ ensureLoaded();
- QIconLoaderEngineEntry *entry = entryForSize(size);
- if (entry)
- {
- return entry->pixmap(size, mode, state);
- }
+ QIconLoaderEngineEntry *entry = entryForSize(size);
+ if (entry)
+ {
+ return entry->pixmap(size, mode, state);
+ }
- return QPixmap();
+ return QPixmap();
}
QString QIconLoaderEngineFixed::key() const
{
- return QLatin1String("QIconLoaderEngineFixed");
+ return QLatin1String("QIconLoaderEngineFixed");
}
void QIconLoaderEngineFixed::virtual_hook(int id, void *data)
{
- ensureLoaded();
-
- switch (id)
- {
- case QIconEngine::AvailableSizesHook:
- {
- QIconEngine::AvailableSizesArgument &arg =
- *reinterpret_cast<QIconEngine::AvailableSizesArgument *>(data);
- const int N = m_entries.size();
- QList<QSize> sizes;
- sizes.reserve(N);
-
- // Gets all sizes from the DirectoryInfo entries
- for (int i = 0; i < N; ++i)
- {
- int size = m_entries.at(i)->dir.size;
- sizes.append(QSize(size, size));
- }
- arg.sizes.swap(sizes); // commit
- }
- break;
- case QIconEngine::IconNameHook:
- {
- QString &name = *reinterpret_cast<QString *>(data);
- name = m_iconName;
- }
- break;
- default:
- QIconEngine::virtual_hook(id, data);
- }
+ ensureLoaded();
+
+ switch (id)
+ {
+ case QIconEngine::AvailableSizesHook:
+ {
+ QIconEngine::AvailableSizesArgument &arg =
+ *reinterpret_cast<QIconEngine::AvailableSizesArgument *>(data);
+ const int N = m_entries.size();
+ QList<QSize> sizes;
+ sizes.reserve(N);
+
+ // Gets all sizes from the DirectoryInfo entries
+ for (int i = 0; i < N; ++i)
+ {
+ int size = m_entries.at(i)->dir.size;
+ sizes.append(QSize(size, size));
+ }
+ arg.sizes.swap(sizes); // commit
+ }
+ break;
+ case QIconEngine::IconNameHook:
+ {
+ QString &name = *reinterpret_cast<QString *>(data);
+ name = m_iconName;
+ }
+ break;
+ default:
+ QIconEngine::virtual_hook(id, data);
+ }
}
} // QtXdg
diff --git a/libraries/iconfix/internal/qiconloader_p.h b/libraries/iconfix/internal/qiconloader_p.h
index b71bdd83..e45a08d6 100644
--- a/libraries/iconfix/internal/qiconloader_p.h
+++ b/libraries/iconfix/internal/qiconloader_p.h
@@ -61,46 +61,46 @@ class QIconLoader;
struct QIconDirInfo
{
- enum Type
- {
- Fixed,
- Scalable,
- Threshold
- };
- QIconDirInfo(const QString &_path = QString())
- : path(_path), size(0), maxSize(0), minSize(0), threshold(0), type(Threshold)
- {
- }
- QString path;
- short size;
- short maxSize;
- short minSize;
- short threshold;
- Type type : 4;
+ enum Type
+ {
+ Fixed,
+ Scalable,
+ Threshold
+ };
+ QIconDirInfo(const QString &_path = QString())
+ : path(_path), size(0), maxSize(0), minSize(0), threshold(0), type(Threshold)
+ {
+ }
+ QString path;
+ short size;
+ short maxSize;
+ short minSize;
+ short threshold;
+ Type type : 4;
};
class QIconLoaderEngineEntry
{
public:
- virtual ~QIconLoaderEngineEntry()
- {
- }
- virtual QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) = 0;
- QString filename;
- QIconDirInfo dir;
- static int count;
+ virtual ~QIconLoaderEngineEntry()
+ {
+ }
+ virtual QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) = 0;
+ QString filename;
+ QIconDirInfo dir;
+ static int count;
};
struct ScalableEntry : public QIconLoaderEngineEntry
{
- QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) Q_DECL_OVERRIDE;
- QIcon svgIcon;
+ QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) Q_DECL_OVERRIDE;
+ QIcon svgIcon;
};
struct PixmapEntry : public QIconLoaderEngineEntry
{
- QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) Q_DECL_OVERRIDE;
- QPixmap basePixmap;
+ QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) Q_DECL_OVERRIDE;
+ QPixmap basePixmap;
};
typedef QList<QIconLoaderEngineEntry *> QThemeIconEntries;
@@ -109,107 +109,107 @@ typedef QList<QIconLoaderEngineEntry *> QThemeIconEntries;
class QIconLoaderEngineFixed : public QIconEngine
{
public:
- QIconLoaderEngineFixed(const QString &iconName = QString());
- ~QIconLoaderEngineFixed();
+ QIconLoaderEngineFixed(const QString &iconName = QString());
+ ~QIconLoaderEngineFixed();
- void paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state);
- QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state);
- QSize actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state);
- QIconEngine *clone() const;
- bool read(QDataStream &in);
- bool write(QDataStream &out) const;
+ void paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state);
+ QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state);
+ QSize actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state);
+ QIconEngine *clone() const;
+ bool read(QDataStream &in);
+ bool write(QDataStream &out) const;
private:
- QString key() const;
- bool hasIcon() const;
- void ensureLoaded();
- void virtual_hook(int id, void *data);
- QIconLoaderEngineEntry *entryForSize(const QSize &size);
- QIconLoaderEngineFixed(const QIconLoaderEngineFixed &other);
- QThemeIconEntries m_entries;
- QString m_iconName;
- uint m_key;
-
- friend class QIconLoader;
+ QString key() const;
+ bool hasIcon() const;
+ void ensureLoaded();
+ void virtual_hook(int id, void *data);
+ QIconLoaderEngineEntry *entryForSize(const QSize &size);
+ QIconLoaderEngineFixed(const QIconLoaderEngineFixed &other);
+ QThemeIconEntries m_entries;
+ QString m_iconName;
+ uint m_key;
+
+ friend class QIconLoader;
};
class QIconTheme
{
public:
- QIconTheme(const QString &name);
- QIconTheme() : m_valid(false)
- {
- }
- QStringList parents()
- {
- return m_parents;
- }
- QVector<QIconDirInfo> keyList()
- {
- return m_keyList;
- }
- QString contentDir()
- {
- return m_contentDir;
- }
- QStringList contentDirs()
- {
- return m_contentDirs;
- }
- bool isValid()
- {
- return m_valid;
- }
+ QIconTheme(const QString &name);
+ QIconTheme() : m_valid(false)
+ {
+ }
+ QStringList parents()
+ {
+ return m_parents;
+ }
+ QVector<QIconDirInfo> keyList()
+ {
+ return m_keyList;
+ }
+ QString contentDir()
+ {
+ return m_contentDir;
+ }
+ QStringList contentDirs()
+ {
+ return m_contentDirs;
+ }
+ bool isValid()
+ {
+ return m_valid;
+ }
private:
- QString m_contentDir;
- QStringList m_contentDirs;
- QVector<QIconDirInfo> m_keyList;
- QStringList m_parents;
- bool m_valid;
+ QString m_contentDir;
+ QStringList m_contentDirs;
+ QVector<QIconDirInfo> m_keyList;
+ QStringList m_parents;
+ bool m_valid;
};
class QIconLoader
{
public:
- QIconLoader();
- QThemeIconEntries loadIcon(const QString &iconName) const;
- uint themeKey() const
- {
- return m_themeKey;
- }
-
- QString themeName() const
- {
- return m_userTheme.isEmpty() ? m_systemTheme : m_userTheme;
- }
- void setThemeName(const QString &themeName);
- QIconTheme theme()
- {
- return themeList.value(themeName());
- }
- void setThemeSearchPath(const QStringList &searchPaths);
- QStringList themeSearchPaths() const;
- QIconDirInfo dirInfo(int dirindex);
- static QIconLoader *instance();
- void updateSystemTheme();
- void invalidateKey()
- {
- m_themeKey++;
- }
- void ensureInitialized();
+ QIconLoader();
+ QThemeIconEntries loadIcon(const QString &iconName) const;
+ uint themeKey() const
+ {
+ return m_themeKey;
+ }
+
+ QString themeName() const
+ {
+ return m_userTheme.isEmpty() ? m_systemTheme : m_userTheme;
+ }
+ void setThemeName(const QString &themeName);
+ QIconTheme theme()
+ {
+ return themeList.value(themeName());
+ }
+ void setThemeSearchPath(const QStringList &searchPaths);
+ QStringList themeSearchPaths() const;
+ QIconDirInfo dirInfo(int dirindex);
+ static QIconLoader *instance();
+ void updateSystemTheme();
+ void invalidateKey()
+ {
+ m_themeKey++;
+ }
+ void ensureInitialized();
private:
- QThemeIconEntries findIconHelper(const QString &themeName, const QString &iconName,
- QStringList &visited) const;
- uint m_themeKey;
- bool m_supportsSvg;
- bool m_initialized;
-
- mutable QString m_userTheme;
- mutable QString m_systemTheme;
- mutable QStringList m_iconDirs;
- mutable QHash<QString, QIconTheme> themeList;
+ QThemeIconEntries findIconHelper(const QString &themeName, const QString &iconName,
+ QStringList &visited) const;
+ uint m_themeKey;
+ bool m_supportsSvg;
+ bool m_initialized;
+
+ mutable QString m_userTheme;
+ mutable QString m_systemTheme;
+ mutable QStringList m_iconDirs;
+ mutable QHash<QString, QIconTheme> themeList;
};
} // QtXdg
diff --git a/libraries/iconfix/xdgicon.cpp b/libraries/iconfix/xdgicon.cpp
index a36d80a9..36fb7d42 100644
--- a/libraries/iconfix/xdgicon.cpp
+++ b/libraries/iconfix/xdgicon.cpp
@@ -46,17 +46,17 @@ namespace
{
struct QtIconCache : public IconCache
{
- QtIconCache()
- {
- qAddPostRoutine(qt_cleanup_icon_cache);
- }
+ QtIconCache()
+ {
+ qAddPostRoutine(qt_cleanup_icon_cache);
+ }
};
}
-Q_GLOBAL_STATIC(IconCache, qtIconCache);
+Q_GLOBAL_STATIC(IconCache, qtIconCache)
static void qt_cleanup_icon_cache()
{
- qtIconCache()->clear();
+ qtIconCache()->clear();
}
/************************************************
@@ -78,7 +78,7 @@ XdgIcon::~XdgIcon()
************************************************/
QString XdgIcon::themeName()
{
- return QIcon::themeName();
+ return QIcon::themeName();
}
/************************************************
@@ -86,8 +86,8 @@ QString XdgIcon::themeName()
************************************************/
void XdgIcon::setThemeName(const QString &themeName)
{
- QIcon::setThemeName(themeName);
- QtXdg::QIconLoader::instance()->updateSystemTheme();
+ QIcon::setThemeName(themeName);
+ QtXdg::QIconLoader::instance()->updateSystemTheme();
}
/************************************************
@@ -96,43 +96,43 @@ void XdgIcon::setThemeName(const QString &themeName)
************************************************/
QIcon XdgIcon::fromTheme(const QString &iconName, const QIcon &fallback)
{
- if (iconName.isEmpty())
- return fallback;
-
- bool isAbsolute = (iconName[0] == '/');
-
- QString name = QFileInfo(iconName).fileName();
- if (name.endsWith(".png", Qt::CaseInsensitive) ||
- name.endsWith(".svg", Qt::CaseInsensitive) ||
- name.endsWith(".xpm", Qt::CaseInsensitive))
- {
- name.truncate(name.length() - 4);
- }
-
- QIcon icon;
-
- if (qtIconCache()->contains(name))
- {
- icon = *qtIconCache()->object(name);
- }
- else
- {
- QIcon *cachedIcon;
- if (!isAbsolute)
- cachedIcon = new QIcon(new QtXdg::QIconLoaderEngineFixed(name));
- else
- cachedIcon = new QIcon(iconName);
- qtIconCache()->insert(name, cachedIcon);
- icon = *cachedIcon;
- }
-
- // Note the qapp check is to allow lazy loading of static icons
- // Supporting fallbacks will not work for this case.
- if (qApp && !isAbsolute && icon.availableSizes().isEmpty())
- {
- return fallback;
- }
- return icon;
+ if (iconName.isEmpty())
+ return fallback;
+
+ bool isAbsolute = (iconName[0] == '/');
+
+ QString name = QFileInfo(iconName).fileName();
+ if (name.endsWith(".png", Qt::CaseInsensitive) ||
+ name.endsWith(".svg", Qt::CaseInsensitive) ||
+ name.endsWith(".xpm", Qt::CaseInsensitive))
+ {
+ name.truncate(name.length() - 4);
+ }
+
+ QIcon icon;
+
+ if (qtIconCache()->contains(name))
+ {
+ icon = *qtIconCache()->object(name);
+ }
+ else
+ {
+ QIcon *cachedIcon;
+ if (!isAbsolute)
+ cachedIcon = new QIcon(new QtXdg::QIconLoaderEngineFixed(name));
+ else
+ cachedIcon = new QIcon(iconName);
+ qtIconCache()->insert(name, cachedIcon);
+ icon = *cachedIcon;
+ }
+
+ // Note the qapp check is to allow lazy loading of static icons
+ // Supporting fallbacks will not work for this case.
+ if (qApp && !isAbsolute && icon.availableSizes().isEmpty())
+ {
+ return fallback;
+ }
+ return icon;
}
/************************************************
@@ -141,12 +141,12 @@ QIcon XdgIcon::fromTheme(const QString &iconName, const QIcon &fallback)
************************************************/
QIcon XdgIcon::fromTheme(const QStringList &iconNames, const QIcon &fallback)
{
- foreach (QString iconName, iconNames)
- {
- QIcon icon = fromTheme(iconName);
- if (!icon.isNull())
- return icon;
- }
-
- return fallback;
+ foreach (QString iconName, iconNames)
+ {
+ QIcon icon = fromTheme(iconName);
+ if (!icon.isNull())
+ return icon;
+ }
+
+ return fallback;
}
diff --git a/libraries/iconfix/xdgicon.h b/libraries/iconfix/xdgicon.h
index df8f026e..1380607c 100644
--- a/libraries/iconfix/xdgicon.h
+++ b/libraries/iconfix/xdgicon.h
@@ -36,13 +36,13 @@
class MULTIMC_ICONFIX_EXPORT XdgIcon
{
public:
- static QIcon fromTheme(const QString &iconName, const QIcon &fallback = QIcon());
- static QIcon fromTheme(const QStringList &iconNames, const QIcon &fallback = QIcon());
+ static QIcon fromTheme(const QString &iconName, const QIcon &fallback = QIcon());
+ static QIcon fromTheme(const QStringList &iconNames, const QIcon &fallback = QIcon());
- static QString themeName();
- static void setThemeName(const QString &themeName);
+ static QString themeName();
+ static void setThemeName(const QString &themeName);
protected:
- explicit XdgIcon();
- virtual ~XdgIcon();
+ explicit XdgIcon();
+ virtual ~XdgIcon();
};
diff --git a/libraries/javacheck/CMakeLists.txt b/libraries/javacheck/CMakeLists.txt
index 381efe08..dba5a1ae 100644
--- a/libraries/javacheck/CMakeLists.txt
+++ b/libraries/javacheck/CMakeLists.txt
@@ -7,7 +7,7 @@ set(CMAKE_JAVA_JAR_ENTRY_POINT JavaCheck)
set(CMAKE_JAVA_COMPILE_FLAGS -target 1.6 -source 1.6 -Xlint:deprecation -Xlint:unchecked)
set(SRC
- JavaCheck.java
+ JavaCheck.java
)
add_jar(JavaCheck ${SRC})
diff --git a/libraries/javacheck/JavaCheck.java b/libraries/javacheck/JavaCheck.java
index 11420b86..69933040 100644
--- a/libraries/javacheck/JavaCheck.java
+++ b/libraries/javacheck/JavaCheck.java
@@ -2,23 +2,23 @@ import java.lang.Integer;
public class JavaCheck
{
- private static final String[] keys = {"os.arch", "java.version"};
- public static void main (String [] args)
- {
- int ret = 0;
- for(String key : keys)
- {
- String property = System.getProperty(key);
- if(property != null)
- {
- System.out.println(key + "=" + property);
- }
- else
- {
- ret = 1;
- }
- }
-
- System.exit(ret);
- }
+ private static final String[] keys = {"os.arch", "java.version"};
+ public static void main (String [] args)
+ {
+ int ret = 0;
+ for(String key : keys)
+ {
+ String property = System.getProperty(key);
+ if(property != null)
+ {
+ System.out.println(key + "=" + property);
+ }
+ else
+ {
+ ret = 1;
+ }
+ }
+
+ System.exit(ret);
+ }
}
diff --git a/libraries/launcher/CMakeLists.txt b/libraries/launcher/CMakeLists.txt
index a4f52edb..a64c601d 100644
--- a/libraries/launcher/CMakeLists.txt
+++ b/libraries/launcher/CMakeLists.txt
@@ -7,15 +7,15 @@ set(CMAKE_JAVA_JAR_ENTRY_POINT org.multimc.EntryPoint)
set(CMAKE_JAVA_COMPILE_FLAGS -target 1.6 -source 1.6 -Xlint:deprecation -Xlint:unchecked)
set(SRC
- org/multimc/EntryPoint.java
- org/multimc/Launcher.java
- org/multimc/LegacyFrame.java
- org/multimc/NotFoundException.java
- org/multimc/ParamBucket.java
- org/multimc/ParseException.java
- org/multimc/Utils.java
- org/multimc/onesix/OneSixLauncher.java
- net/minecraft/Launcher.java
+ org/multimc/EntryPoint.java
+ org/multimc/Launcher.java
+ org/multimc/LegacyFrame.java
+ org/multimc/NotFoundException.java
+ org/multimc/ParamBucket.java
+ org/multimc/ParseException.java
+ org/multimc/Utils.java
+ org/multimc/onesix/OneSixLauncher.java
+ net/minecraft/Launcher.java
)
add_jar(NewLaunch ${SRC})
install_jar(NewLaunch "${JARS_DEST_DIR}")
diff --git a/libraries/launcher/net/minecraft/Launcher.java b/libraries/launcher/net/minecraft/Launcher.java
index 0c991cf5..dd704484 100644
--- a/libraries/launcher/net/minecraft/Launcher.java
+++ b/libraries/launcher/net/minecraft/Launcher.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-2018 MultiMC Contributors
+ * Copyright 2012-2019 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -28,138 +28,138 @@ import java.net.MalformedURLException;
public class Launcher extends Applet implements AppletStub
{
- private Applet wrappedApplet;
- private URL documentBase;
- private boolean active = false;
- private final Map<String, String> params;
-
- public Launcher(Applet applet, URL documentBase)
- {
- params = new TreeMap<String, String>();
-
- this.setLayout(new BorderLayout());
- this.add(applet, "Center");
- this.wrappedApplet = applet;
- this.documentBase = documentBase;
- }
-
- public void setParameter(String name, String value)
- {
- params.put(name, value);
- }
-
- public void replace(Applet applet)
- {
- this.wrappedApplet = applet;
-
- applet.setStub(this);
- applet.setSize(getWidth(), getHeight());
-
- this.setLayout(new BorderLayout());
- this.add(applet, "Center");
-
- applet.init();
- active = true;
- applet.start();
- validate();
- }
-
- @Override
- public String getParameter(String name)
- {
- String param = params.get(name);
- if (param != null)
- return param;
- try
- {
- return super.getParameter(name);
- } catch (Exception ignore){}
- return null;
- }
-
- @Override
- public boolean isActive()
- {
- return active;
- }
-
- @Override
- public void appletResize(int width, int height)
- {
- wrappedApplet.resize(width, height);
- }
-
- @Override
- public void resize(int width, int height)
- {
- wrappedApplet.resize(width, height);
- }
-
- @Override
- public void resize(Dimension d)
- {
- wrappedApplet.resize(d);
- }
-
- @Override
- public void init()
- {
- if (wrappedApplet != null)
- {
- wrappedApplet.init();
- }
- }
-
- @Override
- public void start()
- {
- wrappedApplet.start();
- active = true;
- }
-
- @Override
- public void stop()
- {
- wrappedApplet.stop();
- active = false;
- }
-
- public void destroy()
- {
- wrappedApplet.destroy();
- }
-
- @Override
- public URL getCodeBase() {
- try {
- return new URL("http://www.minecraft.net/game/");
- } catch (MalformedURLException e) {
- e.printStackTrace();
- }
- return null;
- }
-
- @Override
- public URL getDocumentBase()
- {
- try {
- return new URL("http://www.minecraft.net/game/");
- } catch (MalformedURLException e) {
- e.printStackTrace();
- }
- return null;
- }
-
- @Override
- public void setVisible(boolean b)
- {
- super.setVisible(b);
- wrappedApplet.setVisible(b);
- }
- public void update(Graphics paramGraphics)
- {
- }
- public void paint(Graphics paramGraphics)
- {
- }
+ private Applet wrappedApplet;
+ private URL documentBase;
+ private boolean active = false;
+ private final Map<String, String> params;
+
+ public Launcher(Applet applet, URL documentBase)
+ {
+ params = new TreeMap<String, String>();
+
+ this.setLayout(new BorderLayout());
+ this.add(applet, "Center");
+ this.wrappedApplet = applet;
+ this.documentBase = documentBase;
+ }
+
+ public void setParameter(String name, String value)
+ {
+ params.put(name, value);
+ }
+
+ public void replace(Applet applet)
+ {
+ this.wrappedApplet = applet;
+
+ applet.setStub(this);
+ applet.setSize(getWidth(), getHeight());
+
+ this.setLayout(new BorderLayout());
+ this.add(applet, "Center");
+
+ applet.init();
+ active = true;
+ applet.start();
+ validate();
+ }
+
+ @Override
+ public String getParameter(String name)
+ {
+ String param = params.get(name);
+ if (param != null)
+ return param;
+ try
+ {
+ return super.getParameter(name);
+ } catch (Exception ignore){}
+ return null;
+ }
+
+ @Override
+ public boolean isActive()
+ {
+ return active;
+ }
+
+ @Override
+ public void appletResize(int width, int height)
+ {
+ wrappedApplet.resize(width, height);
+ }
+
+ @Override
+ public void resize(int width, int height)
+ {
+ wrappedApplet.resize(width, height);
+ }
+
+ @Override
+ public void resize(Dimension d)
+ {
+ wrappedApplet.resize(d);
+ }
+
+ @Override
+ public void init()
+ {
+ if (wrappedApplet != null)
+ {
+ wrappedApplet.init();
+ }
+ }
+
+ @Override
+ public void start()
+ {
+ wrappedApplet.start();
+ active = true;
+ }
+
+ @Override
+ public void stop()
+ {
+ wrappedApplet.stop();
+ active = false;
+ }
+
+ public void destroy()
+ {
+ wrappedApplet.destroy();
+ }
+
+ @Override
+ public URL getCodeBase() {
+ try {
+ return new URL("http://www.minecraft.net/game/");
+ } catch (MalformedURLException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ @Override
+ public URL getDocumentBase()
+ {
+ try {
+ return new URL("http://www.minecraft.net/game/");
+ } catch (MalformedURLException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ @Override
+ public void setVisible(boolean b)
+ {
+ super.setVisible(b);
+ wrappedApplet.setVisible(b);
+ }
+ public void update(Graphics paramGraphics)
+ {
+ }
+ public void paint(Graphics paramGraphics)
+ {
+ }
} \ No newline at end of file
diff --git a/libraries/launcher/org/multimc/EntryPoint.java b/libraries/launcher/org/multimc/EntryPoint.java
index 8c9b8074..12a494b9 100644
--- a/libraries/launcher/org/multimc/EntryPoint.java
+++ b/libraries/launcher/org/multimc/EntryPoint.java
@@ -1,5 +1,5 @@
package org.multimc;/*
- * Copyright 2012-2018 MultiMC Contributors
+ * Copyright 2012-2019 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,131 +21,131 @@ import java.nio.charset.Charset;
public class EntryPoint
{
- private enum Action
- {
- Proceed,
- Launch,
- Abort
- }
+ private enum Action
+ {
+ Proceed,
+ Launch,
+ Abort
+ }
- public static void main(String[] args)
- {
- EntryPoint listener = new EntryPoint();
- int retCode = listener.listen();
- if (retCode != 0)
- {
- System.out.println("Exiting with " + retCode);
- System.exit(retCode);
- }
- }
+ public static void main(String[] args)
+ {
+ EntryPoint listener = new EntryPoint();
+ int retCode = listener.listen();
+ if (retCode != 0)
+ {
+ System.out.println("Exiting with " + retCode);
+ System.exit(retCode);
+ }
+ }
- private Action parseLine(String inData) throws ParseException
- {
- String[] pair = inData.split(" ", 2);
+ private Action parseLine(String inData) throws ParseException
+ {
+ String[] pair = inData.split(" ", 2);
- if(pair.length == 1)
- {
- String command = pair[0];
- if (pair[0].equals("launch"))
- return Action.Launch;
+ if(pair.length == 1)
+ {
+ String command = pair[0];
+ if (pair[0].equals("launch"))
+ return Action.Launch;
- else if (pair[0].equals("abort"))
- return Action.Abort;
+ else if (pair[0].equals("abort"))
+ return Action.Abort;
- else throw new ParseException();
- }
+ else throw new ParseException("Error while parsing:" + pair[0]);
+ }
- if(pair.length != 2)
- throw new ParseException();
+ if(pair.length != 2)
+ throw new ParseException("Pair length is not 2.");
- String command = pair[0];
- String param = pair[1];
+ String command = pair[0];
+ String param = pair[1];
- if(command.equals("launcher"))
- {
- if(param.equals("onesix"))
- {
- m_launcher = new OneSixLauncher();
- Utils.log("Using onesix launcher.");
- Utils.log();
- return Action.Proceed;
- }
- else
- throw new ParseException();
- }
+ if(command.equals("launcher"))
+ {
+ if(param.equals("onesix"))
+ {
+ m_launcher = new OneSixLauncher();
+ Utils.log("Using onesix launcher.");
+ Utils.log();
+ return Action.Proceed;
+ }
+ else
+ throw new ParseException("Invalid launcher type: " + param);
+ }
- m_params.add(command, param);
- //System.out.println(command + " : " + param);
- return Action.Proceed;
- }
+ m_params.add(command, param);
+ //System.out.println(command + " : " + param);
+ return Action.Proceed;
+ }
- public int listen()
- {
- BufferedReader buffer;
- try
- {
- buffer = new BufferedReader(new InputStreamReader(System.in, "UTF-8"));
- } catch (UnsupportedEncodingException e)
- {
- System.err.println("For some reason, your java does not support UTF-8. Consider living in the current century.");
- e.printStackTrace();
- return 1;
- }
- boolean isListening = true;
- boolean isAborted = false;
- // Main loop
- while (isListening)
- {
- String inData;
- try
- {
- // Read from the pipe one line at a time
- inData = buffer.readLine();
- if (inData != null)
- {
- Action a = parseLine(inData);
- if(a == Action.Abort)
- {
- isListening = false;
- isAborted = true;
- }
- if(a == Action.Launch)
- {
- isListening = false;
- }
- }
- else
- {
- isListening = false;
- isAborted = true;
- }
- }
- catch (IOException e)
- {
- System.err.println("Launcher ABORT due to IO exception:");
- e.printStackTrace();
- return 1;
- }
- catch (ParseException e)
- {
- System.err.println("Launcher ABORT due to PARSE exception:");
- e.printStackTrace();
- return 1;
- }
- }
- if(isAborted)
- {
- System.err.println("Launch aborted by MultiMC.");
- return 1;
- }
- if(m_launcher != null)
- {
- return m_launcher.launch(m_params);
- }
- System.err.println("No valid launcher implementation specified.");
- return 1;
- }
+ public int listen()
+ {
+ BufferedReader buffer;
+ try
+ {
+ buffer = new BufferedReader(new InputStreamReader(System.in, "UTF-8"));
+ } catch (UnsupportedEncodingException e)
+ {
+ System.err.println("For some reason, your java does not support UTF-8. Consider living in the current century.");
+ e.printStackTrace();
+ return 1;
+ }
+ boolean isListening = true;
+ boolean isAborted = false;
+ // Main loop
+ while (isListening)
+ {
+ String inData;
+ try
+ {
+ // Read from the pipe one line at a time
+ inData = buffer.readLine();
+ if (inData != null)
+ {
+ Action a = parseLine(inData);
+ if(a == Action.Abort)
+ {
+ isListening = false;
+ isAborted = true;
+ }
+ if(a == Action.Launch)
+ {
+ isListening = false;
+ }
+ }
+ else
+ {
+ isListening = false;
+ isAborted = true;
+ }
+ }
+ catch (IOException e)
+ {
+ System.err.println("Launcher ABORT due to IO exception:");
+ e.printStackTrace();
+ return 1;
+ }
+ catch (ParseException e)
+ {
+ System.err.println("Launcher ABORT due to PARSE exception:");
+ e.printStackTrace();
+ return 1;
+ }
+ }
+ if(isAborted)
+ {
+ System.err.println("Launch aborted by MultiMC.");
+ return 1;
+ }
+ if(m_launcher != null)
+ {
+ return m_launcher.launch(m_params);
+ }
+ System.err.println("No valid launcher implementation specified.");
+ return 1;
+ }
- private ParamBucket m_params = new ParamBucket();
- private org.multimc.Launcher m_launcher;
+ private ParamBucket m_params = new ParamBucket();
+ private org.multimc.Launcher m_launcher;
}
diff --git a/libraries/launcher/org/multimc/Launcher.java b/libraries/launcher/org/multimc/Launcher.java
index 2e851d18..8f9b043f 100644
--- a/libraries/launcher/org/multimc/Launcher.java
+++ b/libraries/launcher/org/multimc/Launcher.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-2018 MultiMC Contributors
+ * Copyright 2012-2019 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,5 +18,5 @@ package org.multimc;
public interface Launcher
{
- abstract int launch(ParamBucket params);
+ abstract int launch(ParamBucket params);
}
diff --git a/libraries/launcher/org/multimc/LegacyFrame.java b/libraries/launcher/org/multimc/LegacyFrame.java
index 9842eb0e..19cfdfb7 100644
--- a/libraries/launcher/org/multimc/LegacyFrame.java
+++ b/libraries/launcher/org/multimc/LegacyFrame.java
@@ -1,5 +1,5 @@
package org.multimc;/*
- * Copyright 2012-2018 MultiMC Contributors
+ * Copyright 2012-2019 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/libraries/launcher/org/multimc/NotFoundException.java b/libraries/launcher/org/multimc/NotFoundException.java
index 2c5da6de..c1084fe6 100644
--- a/libraries/launcher/org/multimc/NotFoundException.java
+++ b/libraries/launcher/org/multimc/NotFoundException.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-2018 MultiMC Contributors
+ * Copyright 2012-2019 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/libraries/launcher/org/multimc/ParamBucket.java b/libraries/launcher/org/multimc/ParamBucket.java
index 5e9c3ff6..f5b40c40 100644
--- a/libraries/launcher/org/multimc/ParamBucket.java
+++ b/libraries/launcher/org/multimc/ParamBucket.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-2018 MultiMC Contributors
+ * Copyright 2012-2019 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,65 +22,65 @@ import java.util.List;
public class ParamBucket
{
- public void add(String key, String value)
- {
- List<String> coll = null;
- if(!m_params.containsKey(key))
- {
- coll = new ArrayList<String>();
- m_params.put(key, coll);
- }
- else
- {
- coll = m_params.get(key);
- }
- coll.add(value);
- }
+ public void add(String key, String value)
+ {
+ List<String> coll = null;
+ if(!m_params.containsKey(key))
+ {
+ coll = new ArrayList<String>();
+ m_params.put(key, coll);
+ }
+ else
+ {
+ coll = m_params.get(key);
+ }
+ coll.add(value);
+ }
- public List<String> all(String key) throws NotFoundException
- {
- if(!m_params.containsKey(key))
- throw new NotFoundException();
- return m_params.get(key);
- }
+ public List<String> all(String key) throws NotFoundException
+ {
+ if(!m_params.containsKey(key))
+ throw new NotFoundException();
+ return m_params.get(key);
+ }
- public List<String> allSafe(String key, List<String> def)
- {
- if(!m_params.containsKey(key) || m_params.get(key).size() < 1)
- {
- return def;
- }
- return m_params.get(key);
- }
+ public List<String> allSafe(String key, List<String> def)
+ {
+ if(!m_params.containsKey(key) || m_params.get(key).size() < 1)
+ {
+ return def;
+ }
+ return m_params.get(key);
+ }
- public List<String> allSafe(String key)
- {
- return allSafe(key, new ArrayList<String>());
- }
+ public List<String> allSafe(String key)
+ {
+ return allSafe(key, new ArrayList<String>());
+ }
- public String first(String key) throws NotFoundException
- {
- List<String> list = all(key);
- if(list.size() < 1)
- {
- throw new NotFoundException();
- }
- return list.get(0);
- }
+ public String first(String key) throws NotFoundException
+ {
+ List<String> list = all(key);
+ if(list.size() < 1)
+ {
+ throw new NotFoundException();
+ }
+ return list.get(0);
+ }
- public String firstSafe(String key, String def)
- {
- if(!m_params.containsKey(key) || m_params.get(key).size() < 1)
- {
- return def;
- }
- return m_params.get(key).get(0);
- }
+ public String firstSafe(String key, String def)
+ {
+ if(!m_params.containsKey(key) || m_params.get(key).size() < 1)
+ {
+ return def;
+ }
+ return m_params.get(key).get(0);
+ }
- public String firstSafe(String key)
- {
- return firstSafe(key, "");
- }
+ public String firstSafe(String key)
+ {
+ return firstSafe(key, "");
+ }
- private HashMap<String, List<String>> m_params = new HashMap<String, List<String>>();
+ private HashMap<String, List<String>> m_params = new HashMap<String, List<String>>();
}
diff --git a/libraries/launcher/org/multimc/ParseException.java b/libraries/launcher/org/multimc/ParseException.java
index 9a8fe521..e9c84f6e 100644
--- a/libraries/launcher/org/multimc/ParseException.java
+++ b/libraries/launcher/org/multimc/ParseException.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-2018 MultiMC Contributors
+ * Copyright 2012-2019 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,5 +18,8 @@ package org.multimc;
public class ParseException extends java.lang.Exception
{
-
+ public ParseException() { super(); }
+ public ParseException(String message) {
+ super(message);
+ }
}
diff --git a/libraries/launcher/org/multimc/Utils.java b/libraries/launcher/org/multimc/Utils.java
index c5292eaf..b0a2d5b0 100644
--- a/libraries/launcher/org/multimc/Utils.java
+++ b/libraries/launcher/org/multimc/Utils.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-2018 MultiMC Contributors
+ * Copyright 2012-2019 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -34,86 +34,86 @@ import java.util.zip.ZipFile;
public class Utils
{
- /**
- * Combine two parts of a path.
- *
- * @param path1
- * @param path2
- * @return the paths, combined
- */
- public static String combine(String path1, String path2)
- {
- File file1 = new File(path1);
- File file2 = new File(file1, path2);
- return file2.getPath();
- }
+ /**
+ * Combine two parts of a path.
+ *
+ * @param path1
+ * @param path2
+ * @return the paths, combined
+ */
+ public static String combine(String path1, String path2)
+ {
+ File file1 = new File(path1);
+ File file2 = new File(file1, path2);
+ return file2.getPath();
+ }
- /**
- * Join a list of strings into a string using a separator!
- *
- * @param strings the string list to join
- * @param separator the glue
- * @return the result.
- */
- public static String join(List<String> strings, String separator)
- {
- StringBuilder sb = new StringBuilder();
- String sep = "";
- for (String s : strings)
- {
- sb.append(sep).append(s);
- sep = separator;
- }
- return sb.toString();
- }
+ /**
+ * Join a list of strings into a string using a separator!
+ *
+ * @param strings the string list to join
+ * @param separator the glue
+ * @return the result.
+ */
+ public static String join(List<String> strings, String separator)
+ {
+ StringBuilder sb = new StringBuilder();
+ String sep = "";
+ for (String s : strings)
+ {
+ sb.append(sep).append(s);
+ sep = separator;
+ }
+ return sb.toString();
+ }
- /**
- * Finds a field that looks like a Minecraft base folder in a supplied class
- *
- * @param mc the class to scan
- */
- public static Field getMCPathField(Class<?> mc)
- {
- Field[] fields = mc.getDeclaredFields();
+ /**
+ * Finds a field that looks like a Minecraft base folder in a supplied class
+ *
+ * @param mc the class to scan
+ */
+ public static Field getMCPathField(Class<?> mc)
+ {
+ Field[] fields = mc.getDeclaredFields();
- for (Field f : fields)
- {
- if (f.getType() != File.class)
- {
- // Has to be File
- continue;
- }
- if (f.getModifiers() != (Modifier.PRIVATE + Modifier.STATIC))
- {
- // And Private Static.
- continue;
- }
- return f;
- }
- return null;
- }
+ for (Field f : fields)
+ {
+ if (f.getType() != File.class)
+ {
+ // Has to be File
+ continue;
+ }
+ if (f.getModifiers() != (Modifier.PRIVATE + Modifier.STATIC))
+ {
+ // And Private Static.
+ continue;
+ }
+ return f;
+ }
+ return null;
+ }
- /**
- * Log to the MultiMC console
- *
- * @param message A String containing the message
- * @param level A String containing the level name. See MinecraftLauncher::getLevel()
- */
- public static void log(String message, String level)
- {
- // Kinda dirty
- String tag = "!![" + level + "]!";
- System.out.println(tag + message.replace("\n", "\n" + tag));
- }
+ /**
+ * Log to the MultiMC console
+ *
+ * @param message A String containing the message
+ * @param level A String containing the level name. See MinecraftLauncher::getLevel()
+ */
+ public static void log(String message, String level)
+ {
+ // Kinda dirty
+ String tag = "!![" + level + "]!";
+ System.out.println(tag + message.replace("\n", "\n" + tag));
+ }
- public static void log(String message)
- {
- log(message, "MultiMC");
- }
+ public static void log(String message)
+ {
+ log(message, "MultiMC");
+ }
- public static void log()
- {
- System.out.println();
- }
+ public static void log()
+ {
+ System.out.println();
+ }
}
diff --git a/libraries/launcher/org/multimc/onesix/OneSixLauncher.java b/libraries/launcher/org/multimc/onesix/OneSixLauncher.java
index 9667297d..ec688ee3 100644
--- a/libraries/launcher/org/multimc/onesix/OneSixLauncher.java
+++ b/libraries/launcher/org/multimc/onesix/OneSixLauncher.java
@@ -1,4 +1,4 @@
-/* Copyright 2012-2018 MultiMC Contributors
+/* Copyright 2012-2019 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -27,208 +27,208 @@ import java.util.List;
public class OneSixLauncher implements Launcher
{
- // parameters, separated from ParamBucket
- private List<String> libraries;
- private List<String> mcparams;
- private List<String> mods;
- private List<String> jarmods;
- private List<String> coremods;
- private List<String> traits;
- private String appletClass;
- private String mainClass;
- private String nativePath;
- private String userName, sessionId;
- private String windowTitle;
- private String windowParams;
-
- // secondary parameters
- private int winSizeW;
- private int winSizeH;
- private boolean maximize;
- private String cwd;
-
- // the much abused system classloader, for convenience (for further abuse)
- private ClassLoader cl;
-
- private void processParams(ParamBucket params) throws NotFoundException
- {
- libraries = params.all("cp");
- mcparams = params.allSafe("param", new ArrayList<String>() );
- mainClass = params.firstSafe("mainClass", "net.minecraft.client.Minecraft");
- appletClass = params.firstSafe("appletClass", "net.minecraft.client.MinecraftApplet");
- traits = params.allSafe("traits", new ArrayList<String>());
- nativePath = params.first("natives");
-
- userName = params.first("userName");
- sessionId = params.first("sessionId");
- windowTitle = params.firstSafe("windowTitle", "Minecraft");
- windowParams = params.firstSafe("windowParams", "854x480");
-
- cwd = System.getProperty("user.dir");
-
- winSizeW = 854;
- winSizeH = 480;
- maximize = false;
-
- String[] dimStrings = windowParams.split("x");
-
- if (windowParams.equalsIgnoreCase("max"))
- {
- maximize = true;
- }
- else if (dimStrings.length == 2)
- {
- try
- {
- winSizeW = Integer.parseInt(dimStrings[0]);
- winSizeH = Integer.parseInt(dimStrings[1]);
- } catch (NumberFormatException ignored) {}
- }
- }
-
- int legacyLaunch()
- {
- // Get the Minecraft Class and set the base folder
- Class<?> mc;
- try
- {
- mc = cl.loadClass(mainClass);
-
- Field f = Utils.getMCPathField(mc);
-
- if (f == null)
- {
- System.err.println("Could not find Minecraft path field.");
- }
- else
- {
- f.setAccessible(true);
- f.set(null, new File(cwd));
- }
- } catch (Exception e)
- {
- System.err.println("Could not set base folder. Failed to find/access Minecraft main class:");
- e.printStackTrace(System.err);
- return -1;
- }
-
- System.setProperty("minecraft.applet.TargetDirectory", cwd);
-
- if(!traits.contains("noapplet"))
- {
- Utils.log("Launching with applet wrapper...");
- try
- {
- Class<?> MCAppletClass = cl.loadClass(appletClass);
- Applet mcappl = (Applet) MCAppletClass.newInstance();
- LegacyFrame mcWindow = new LegacyFrame(windowTitle);
- mcWindow.start(mcappl, userName, sessionId, winSizeW, winSizeH, maximize);
- return 0;
- } catch (Exception e)
- {
- Utils.log("Applet wrapper failed:", "Error");
- e.printStackTrace(System.err);
- Utils.log();
- Utils.log("Falling back to using main class.");
- }
- }
-
- // init params for the main method to chomp on.
- String[] paramsArray = mcparams.toArray(new String[mcparams.size()]);
- try
- {
- mc.getMethod("main", String[].class).invoke(null, (Object) paramsArray);
- return 0;
- } catch (Exception e)
- {
- Utils.log("Failed to invoke the Minecraft main class:", "Fatal");
- e.printStackTrace(System.err);
- return -1;
- }
- }
-
- int launchWithMainClass()
- {
- // window size, title and state, onesix
- if (maximize)
- {
- // FIXME: there is no good way to maximize the minecraft window in onesix.
- // the following often breaks linux screen setups
- // mcparams.add("--fullscreen");
- }
- else
- {
- mcparams.add("--width");
- mcparams.add(Integer.toString(winSizeW));
- mcparams.add("--height");
- mcparams.add(Integer.toString(winSizeH));
- }
-
- // Get the Minecraft Class.
- Class<?> mc;
- try
- {
- mc = cl.loadClass(mainClass);
- } catch (ClassNotFoundException e)
- {
- System.err.println("Failed to find Minecraft main class:");
- e.printStackTrace(System.err);
- return -1;
- }
-
- // get the main method.
- Method meth;
- try
- {
- meth = mc.getMethod("main", String[].class);
- } catch (NoSuchMethodException e)
- {
- System.err.println("Failed to acquire the main method:");
- e.printStackTrace(System.err);
- return -1;
- }
-
- // init params for the main method to chomp on.
- String[] paramsArray = mcparams.toArray(new String[mcparams.size()]);
- try
- {
- // static method doesn't have an instance
- meth.invoke(null, (Object) paramsArray);
- } catch (Exception e)
- {
- System.err.println("Failed to start Minecraft:");
- e.printStackTrace(System.err);
- return -1;
- }
- return 0;
- }
-
- @Override
- public int launch(ParamBucket params)
- {
- // get and process the launch script params
- try
- {
- processParams(params);
- } catch (NotFoundException e)
- {
- System.err.println("Not enough arguments.");
- e.printStackTrace(System.err);
- return -1;
- }
-
- // grab the system classloader and ...
- cl = ClassLoader.getSystemClassLoader();
-
- if (traits.contains("legacyLaunch") || traits.contains("alphaLaunch") )
- {
- // legacy launch uses the applet wrapper
- return legacyLaunch();
- }
- else
- {
- // normal launch just calls main()
- return launchWithMainClass();
- }
- }
+ // parameters, separated from ParamBucket
+ private List<String> libraries;
+ private List<String> mcparams;
+ private List<String> mods;
+ private List<String> jarmods;
+ private List<String> coremods;
+ private List<String> traits;
+ private String appletClass;
+ private String mainClass;
+ private String nativePath;
+ private String userName, sessionId;
+ private String windowTitle;
+ private String windowParams;
+
+ // secondary parameters
+ private int winSizeW;
+ private int winSizeH;
+ private boolean maximize;
+ private String cwd;
+
+ // the much abused system classloader, for convenience (for further abuse)
+ private ClassLoader cl;
+
+ private void processParams(ParamBucket params) throws NotFoundException
+ {
+ libraries = params.all("cp");
+ mcparams = params.allSafe("param", new ArrayList<String>() );
+ mainClass = params.firstSafe("mainClass", "net.minecraft.client.Minecraft");
+ appletClass = params.firstSafe("appletClass", "net.minecraft.client.MinecraftApplet");
+ traits = params.allSafe("traits", new ArrayList<String>());
+ nativePath = params.first("natives");
+
+ userName = params.first("userName");
+ sessionId = params.first("sessionId");
+ windowTitle = params.firstSafe("windowTitle", "Minecraft");
+ windowParams = params.firstSafe("windowParams", "854x480");
+
+ cwd = System.getProperty("user.dir");
+
+ winSizeW = 854;
+ winSizeH = 480;
+ maximize = false;
+
+ String[] dimStrings = windowParams.split("x");
+
+ if (windowParams.equalsIgnoreCase("max"))
+ {
+ maximize = true;
+ }
+ else if (dimStrings.length == 2)
+ {
+ try
+ {
+ winSizeW = Integer.parseInt(dimStrings[0]);
+ winSizeH = Integer.parseInt(dimStrings[1]);
+ } catch (NumberFormatException ignored) {}
+ }
+ }
+
+ int legacyLaunch()
+ {
+ // Get the Minecraft Class and set the base folder
+ Class<?> mc;
+ try
+ {
+ mc = cl.loadClass(mainClass);
+
+ Field f = Utils.getMCPathField(mc);
+
+ if (f == null)
+ {
+ System.err.println("Could not find Minecraft path field.");
+ }
+ else
+ {
+ f.setAccessible(true);
+ f.set(null, new File(cwd));
+ }
+ } catch (Exception e)
+ {
+ System.err.println("Could not set base folder. Failed to find/access Minecraft main class:");
+ e.printStackTrace(System.err);
+ return -1;
+ }
+
+ System.setProperty("minecraft.applet.TargetDirectory", cwd);
+
+ if(!traits.contains("noapplet"))
+ {
+ Utils.log("Launching with applet wrapper...");
+ try
+ {
+ Class<?> MCAppletClass = cl.loadClass(appletClass);
+ Applet mcappl = (Applet) MCAppletClass.newInstance();
+ LegacyFrame mcWindow = new LegacyFrame(windowTitle);
+ mcWindow.start(mcappl, userName, sessionId, winSizeW, winSizeH, maximize);
+ return 0;
+ } catch (Exception e)
+ {
+ Utils.log("Applet wrapper failed:", "Error");
+ e.printStackTrace(System.err);
+ Utils.log();
+ Utils.log("Falling back to using main class.");
+ }
+ }
+
+ // init params for the main method to chomp on.
+ String[] paramsArray = mcparams.toArray(new String[mcparams.size()]);
+ try
+ {
+ mc.getMethod("main", String[].class).invoke(null, (Object) paramsArray);
+ return 0;
+ } catch (Exception e)
+ {
+ Utils.log("Failed to invoke the Minecraft main class:", "Fatal");
+ e.printStackTrace(System.err);
+ return -1;
+ }
+ }
+
+ int launchWithMainClass()
+ {
+ // window size, title and state, onesix
+ if (maximize)
+ {
+ // FIXME: there is no good way to maximize the minecraft window in onesix.
+ // the following often breaks linux screen setups
+ // mcparams.add("--fullscreen");
+ }
+ else
+ {
+ mcparams.add("--width");
+ mcparams.add(Integer.toString(winSizeW));
+ mcparams.add("--height");
+ mcparams.add(Integer.toString(winSizeH));
+ }
+
+ // Get the Minecraft Class.
+ Class<?> mc;
+ try
+ {
+ mc = cl.loadClass(mainClass);
+ } catch (ClassNotFoundException e)
+ {
+ System.err.println("Failed to find Minecraft main class:");
+ e.printStackTrace(System.err);
+ return -1;
+ }
+
+ // get the main method.
+ Method meth;
+ try
+ {
+ meth = mc.getMethod("main", String[].class);
+ } catch (NoSuchMethodException e)
+ {
+ System.err.println("Failed to acquire the main method:");
+ e.printStackTrace(System.err);
+ return -1;
+ }
+
+ // init params for the main method to chomp on.
+ String[] paramsArray = mcparams.toArray(new String[mcparams.size()]);
+ try
+ {
+ // static method doesn't have an instance
+ meth.invoke(null, (Object) paramsArray);
+ } catch (Exception e)
+ {
+ System.err.println("Failed to start Minecraft:");
+ e.printStackTrace(System.err);
+ return -1;
+ }
+ return 0;
+ }
+
+ @Override
+ public int launch(ParamBucket params)
+ {
+ // get and process the launch script params
+ try
+ {
+ processParams(params);
+ } catch (NotFoundException e)
+ {
+ System.err.println("Not enough arguments.");
+ e.printStackTrace(System.err);
+ return -1;
+ }
+
+ // grab the system classloader and ...
+ cl = ClassLoader.getSystemClassLoader();
+
+ if (traits.contains("legacyLaunch") || traits.contains("alphaLaunch") )
+ {
+ // legacy launch uses the applet wrapper
+ return legacyLaunch();
+ }
+ else
+ {
+ // normal launch just calls main()
+ return launchWithMainClass();
+ }
+ }
}
diff --git a/libraries/pack200/CMakeLists.txt b/libraries/pack200/CMakeLists.txt
index b568e506..31eb0f73 100644
--- a/libraries/pack200/CMakeLists.txt
+++ b/libraries/pack200/CMakeLists.txt
@@ -8,22 +8,22 @@ option(PACK200_BUILD_BINARY "Build a tiny utility that decompresses pack200 stre
find_package(ZLIB REQUIRED)
set(PACK200_SRC
- include/unpack200.h
- src/bands.cpp
- src/bands.h
- src/bytes.cpp
- src/bytes.h
- src/coding.cpp
- src/coding.h
- src/constants.h
- src/defines.h
- src/unpack200.cpp
- src/unpack.cpp
- src/unpack.h
- src/utils.cpp
- src/utils.h
- src/zip.cpp
- src/zip.h
+ include/unpack200.h
+ src/bands.cpp
+ src/bands.h
+ src/bytes.cpp
+ src/bytes.h
+ src/coding.cpp
+ src/coding.h
+ src/constants.h
+ src/defines.h
+ src/unpack200.cpp
+ src/unpack.cpp
+ src/unpack.h
+ src/utils.cpp
+ src/utils.h
+ src/zip.cpp
+ src/zip.h
)
if (Qt5_POSITION_INDEPENDENT_CODE)
@@ -39,12 +39,12 @@ generate_export_header(MultiMC_unpack200)
# Install it
install(
- TARGETS MultiMC_unpack200
- RUNTIME DESTINATION ${LIBRARY_DEST_DIR}
- LIBRARY DESTINATION ${LIBRARY_DEST_DIR}
+ TARGETS MultiMC_unpack200
+ RUNTIME DESTINATION ${LIBRARY_DEST_DIR}
+ LIBRARY DESTINATION ${LIBRARY_DEST_DIR}
)
if(PACK200_BUILD_BINARY)
- add_executable(anti200 anti200.cpp)
- target_link_libraries(anti200 MultiMC_unpack200)
+ add_executable(anti200 anti200.cpp)
+ target_link_libraries(anti200 MultiMC_unpack200)
endif()
diff --git a/libraries/pack200/anti200.cpp b/libraries/pack200/anti200.cpp
index 944e80e5..1e672847 100644
--- a/libraries/pack200/anti200.cpp
+++ b/libraries/pack200/anti200.cpp
@@ -8,36 +8,36 @@
int main(int argc, char **argv)
{
- if (argc != 3)
- {
- std::cerr << "Simple pack200 unpacker!" << std::endl << "Run like this:" << std::endl
- << " " << argv[0] << " input.jar.lzma output.jar" << std::endl;
- return EXIT_FAILURE;
- }
+ if (argc != 3)
+ {
+ std::cerr << "Simple pack200 unpacker!" << std::endl << "Run like this:" << std::endl
+ << " " << argv[0] << " input.jar.lzma output.jar" << std::endl;
+ return EXIT_FAILURE;
+ }
- FILE *input = fopen(argv[1], "rb");
- if (!input)
- {
- std::cerr << "Can't open input file";
- return EXIT_FAILURE;
- }
- FILE *output = fopen(argv[2], "wb");
- if (!output)
- {
- fclose(input);
- std::cerr << "Can't open output file";
- return EXIT_FAILURE;
- }
- try
- {
- unpack_200(input, output);
- }
- catch (std::runtime_error &e)
- {
- std::cerr << "Bad things happened: " << e.what() << std::endl;
- fclose(input);
- fclose(output);
- return EXIT_FAILURE;
- }
- return EXIT_SUCCESS;
+ FILE *input = fopen(argv[1], "rb");
+ if (!input)
+ {
+ std::cerr << "Can't open input file";
+ return EXIT_FAILURE;
+ }
+ FILE *output = fopen(argv[2], "wb");
+ if (!output)
+ {
+ fclose(input);
+ std::cerr << "Can't open output file";
+ return EXIT_FAILURE;
+ }
+ try
+ {
+ unpack_200(input, output);
+ }
+ catch (const std::runtime_error &e)
+ {
+ std::cerr << "Bad things happened: " << e.what() << std::endl;
+ fclose(input);
+ fclose(output);
+ return EXIT_FAILURE;
+ }
+ return EXIT_SUCCESS;
}
diff --git a/libraries/pack200/src/bands.cpp b/libraries/pack200/src/bands.cpp
index 1608d838..e82613b5 100644
--- a/libraries/pack200/src/bands.cpp
+++ b/libraries/pack200/src/bands.cpp
@@ -47,188 +47,188 @@
void band::readData(int expectedLength)
{
- assert(expectedLength >= 0);
- assert(vs[0].cmk == cmk_ERROR);
- if (expectedLength != 0)
- {
- assert(length == 0);
- length = expectedLength;
- }
- if (length == 0)
- {
- assert((rplimit = cm.vs0.rp = u->rp) != nullptr);
- return;
- }
- assert(length > 0);
+ assert(expectedLength >= 0);
+ assert(vs[0].cmk == cmk_ERROR);
+ if (expectedLength != 0)
+ {
+ assert(length == 0);
+ length = expectedLength;
+ }
+ if (length == 0)
+ {
+ assert((rplimit = cm.vs0.rp = u->rp) != nullptr);
+ return;
+ }
+ assert(length > 0);
- bool is_BYTE1 = (defc->spec == BYTE1_spec);
+ bool is_BYTE1 = (defc->spec == BYTE1_spec);
- if (is_BYTE1)
- {
- // No possibility of coding change. Sizing is exact.
- u->ensure_input(length);
- }
- else
- {
- // Make a conservatively generous estimate of band size in bytes.
- // Assume B == 5 everywhere.
- // Assume awkward pop with all {U} values (2*5 per value)
- int64_t generous = (int64_t)length * (B_MAX * 3 + 1) + C_SLOP;
- u->ensure_input(generous);
- }
+ if (is_BYTE1)
+ {
+ // No possibility of coding change. Sizing is exact.
+ u->ensure_input(length);
+ }
+ else
+ {
+ // Make a conservatively generous estimate of band size in bytes.
+ // Assume B == 5 everywhere.
+ // Assume awkward pop with all {U} values (2*5 per value)
+ int64_t generous = (int64_t)length * (B_MAX * 3 + 1) + C_SLOP;
+ u->ensure_input(generous);
+ }
- // Read one value to see what it might be.
- int XB = _meta_default;
- if (!is_BYTE1)
- {
- // must be a variable-length coding
- assert(defc->B() > 1 && defc->L() > 0);
+ // Read one value to see what it might be.
+ int XB = _meta_default;
+ if (!is_BYTE1)
+ {
+ // must be a variable-length coding
+ assert(defc->B() > 1 && defc->L() > 0);
- value_stream xvs;
- coding *valc = defc;
- if (valc->D() != 0)
- {
- valc = coding::findBySpec(defc->B(), defc->H(), defc->S());
- assert(!valc->isMalloc);
- }
- xvs.init(u->rp, u->rplimit, valc);
- int X = xvs.getInt();
- if (valc->S() != 0)
- {
- assert(valc->min <= -256);
- XB = -1 - X;
- }
- else
- {
- int L = valc->L();
- assert(valc->max >= L + 255);
- XB = X - L;
- }
- if (0 <= XB && XB < 256)
- {
- // Skip over the escape value.
- u->rp = xvs.rp;
- }
- else
- {
- // No, it's still default.
- XB = _meta_default;
- }
- }
+ value_stream xvs;
+ coding *valc = defc;
+ if (valc->D() != 0)
+ {
+ valc = coding::findBySpec(defc->B(), defc->H(), defc->S());
+ assert(!valc->isMalloc);
+ }
+ xvs.init(u->rp, u->rplimit, valc);
+ int X = xvs.getInt();
+ if (valc->S() != 0)
+ {
+ assert(valc->min <= -256);
+ XB = -1 - X;
+ }
+ else
+ {
+ int L = valc->L();
+ assert(valc->max >= L + 255);
+ XB = X - L;
+ }
+ if (0 <= XB && XB < 256)
+ {
+ // Skip over the escape value.
+ u->rp = xvs.rp;
+ }
+ else
+ {
+ // No, it's still default.
+ XB = _meta_default;
+ }
+ }
- if (XB <= _meta_canon_max)
- {
- byte XB_byte = (byte)XB;
- byte *XB_ptr = &XB_byte;
- cm.init(u->rp, u->rplimit, XB_ptr, 0, defc, length, nullptr);
- }
- else
- {
- assert(u->meta_rp != nullptr);
- // Scribble the initial byte onto the band.
- byte *save_meta_rp = --u->meta_rp;
- byte save_meta_xb = (*save_meta_rp);
- (*save_meta_rp) = (byte)XB;
- cm.init(u->rp, u->rplimit, u->meta_rp, 0, defc, length, nullptr);
- (*save_meta_rp) = save_meta_xb; // put it back, just to be tidy
- }
- rplimit = u->rp;
+ if (XB <= _meta_canon_max)
+ {
+ byte XB_byte = (byte)XB;
+ byte *XB_ptr = &XB_byte;
+ cm.init(u->rp, u->rplimit, XB_ptr, 0, defc, length, nullptr);
+ }
+ else
+ {
+ assert(u->meta_rp != nullptr);
+ // Scribble the initial byte onto the band.
+ byte *save_meta_rp = --u->meta_rp;
+ byte save_meta_xb = (*save_meta_rp);
+ (*save_meta_rp) = (byte)XB;
+ cm.init(u->rp, u->rplimit, u->meta_rp, 0, defc, length, nullptr);
+ (*save_meta_rp) = save_meta_xb; // put it back, just to be tidy
+ }
+ rplimit = u->rp;
- rewind();
+ rewind();
}
void band::setIndex(cpindex *ix_)
{
- assert(ix_ == nullptr || ixTag == ix_->ixTag);
- ix = ix_;
+ assert(ix_ == nullptr || ixTag == ix_->ixTag);
+ ix = ix_;
}
void band::setIndexByTag(byte tag)
{
- setIndex(u->cp.getIndex(tag));
+ setIndex(u->cp.getIndex(tag));
}
entry *band::getRefCommon(cpindex *ix_, bool nullOKwithCaller)
{
- assert(ix_->ixTag == ixTag ||
- (ixTag == CONSTANT_Literal && ix_->ixTag >= CONSTANT_Integer &&
- ix_->ixTag <= CONSTANT_String));
- int n = vs[0].getInt() - nullOK;
- // Note: band-local nullOK means nullptr encodes as 0.
- // But nullOKwithCaller means caller is willing to tolerate a nullptr.
- entry *ref = ix_->get(n);
- if (ref == nullptr && !(nullOKwithCaller && n == -1))
- unpack_abort(n == -1 ? "nullptr ref" : "bad ref");
- return ref;
+ assert(ix_->ixTag == ixTag ||
+ (ixTag == CONSTANT_Literal && ix_->ixTag >= CONSTANT_Integer &&
+ ix_->ixTag <= CONSTANT_String));
+ int n = vs[0].getInt() - nullOK;
+ // Note: band-local nullOK means nullptr encodes as 0.
+ // But nullOKwithCaller means caller is willing to tolerate a nullptr.
+ entry *ref = ix_->get(n);
+ if (ref == nullptr && !(nullOKwithCaller && n == -1))
+ unpack_abort(n == -1 ? "nullptr ref" : "bad ref");
+ return ref;
}
int64_t band::getLong(band &lo_band, bool have_hi)
{
- band &hi_band = (*this);
- assert(lo_band.bn == hi_band.bn + 1);
- uint32_t lo = lo_band.getInt();
- if (!have_hi)
- {
- assert(hi_band.length == 0);
- return makeLong(0, lo);
- }
- uint32_t hi = hi_band.getInt();
- return makeLong(hi, lo);
+ band &hi_band = (*this);
+ assert(lo_band.bn == hi_band.bn + 1);
+ uint32_t lo = lo_band.getInt();
+ if (!have_hi)
+ {
+ assert(hi_band.length == 0);
+ return makeLong(0, lo);
+ }
+ uint32_t hi = hi_band.getInt();
+ return makeLong(hi, lo);
}
int band::getIntTotal()
{
- if (length == 0)
- return 0;
- if (total_memo > 0)
- return total_memo - 1;
- int total = getInt();
- // overflow checks require that none of the addends are <0,
- // and that the partial sums never overflow (wrap negative)
- if (total < 0)
- {
- unpack_abort("overflow detected");
- }
- for (int k = length - 1; k > 0; k--)
- {
- int prev_total = total;
- total += vs[0].getInt();
- if (total < prev_total)
- {
- unpack_abort("overflow detected");
- }
- }
- rewind();
- total_memo = total + 1;
- return total;
+ if (length == 0)
+ return 0;
+ if (total_memo > 0)
+ return total_memo - 1;
+ int total = getInt();
+ // overflow checks require that none of the addends are <0,
+ // and that the partial sums never overflow (wrap negative)
+ if (total < 0)
+ {
+ unpack_abort("overflow detected");
+ }
+ for (int k = length - 1; k > 0; k--)
+ {
+ int prev_total = total;
+ total += vs[0].getInt();
+ if (total < prev_total)
+ {
+ unpack_abort("overflow detected");
+ }
+ }
+ rewind();
+ total_memo = total + 1;
+ return total;
}
int band::getIntCount(int tag)
{
- if (length == 0)
- return 0;
- if (tag >= HIST0_MIN && tag <= HIST0_MAX)
- {
- if (hist0 == nullptr)
- {
- // Lazily calculate an approximate histogram.
- hist0 = U_NEW(int, (HIST0_MAX - HIST0_MIN) + 1);
- for (int k = length; k > 0; k--)
- {
- int x = vs[0].getInt();
- if (x >= HIST0_MIN && x <= HIST0_MAX)
- hist0[x - HIST0_MIN] += 1;
- }
- rewind();
- }
- return hist0[tag - HIST0_MIN];
- }
- int total = 0;
- for (int k = length; k > 0; k--)
- {
- total += (vs[0].getInt() == tag) ? 1 : 0;
- }
- rewind();
- return total;
+ if (length == 0)
+ return 0;
+ if (tag >= HIST0_MIN && tag <= HIST0_MAX)
+ {
+ if (hist0 == nullptr)
+ {
+ // Lazily calculate an approximate histogram.
+ hist0 = U_NEW(int, (HIST0_MAX - HIST0_MIN) + 1);
+ for (int k = length; k > 0; k--)
+ {
+ int x = vs[0].getInt();
+ if (x >= HIST0_MIN && x <= HIST0_MAX)
+ hist0[x - HIST0_MIN] += 1;
+ }
+ rewind();
+ }
+ return hist0[tag - HIST0_MIN];
+ }
+ int total = 0;
+ for (int k = length; k > 0; k--)
+ {
+ total += (vs[0].getInt() == tag) ? 1 : 0;
+ }
+ rewind();
+ return total;
}
#define INDEX_INIT(tag, nullOK, subindex) ((tag) + (subindex) * SUBINDEX_BIT + (nullOK) * 256)
@@ -240,184 +240,184 @@ int band::getIntCount(int tag)
struct band_init
{
- int defc;
- int index;
+ int defc;
+ int index;
};
#define BAND_INIT(name, cspec, ix) \
- { \
- cspec, ix \
- }
+ { \
+ cspec, ix \
+ }
const band_init all_band_inits[] =
- {
- // BAND_INIT(archive_magic, BYTE1_spec, 0),
- // BAND_INIT(archive_header, UNSIGNED5_spec, 0),
- // BAND_INIT(band_headers, BYTE1_spec, 0),
- BAND_INIT(cp_Utf8_prefix, DELTA5_spec, 0), BAND_INIT(cp_Utf8_suffix, UNSIGNED5_spec, 0),
- BAND_INIT(cp_Utf8_chars, CHAR3_spec, 0), BAND_INIT(cp_Utf8_big_suffix, DELTA5_spec, 0),
- BAND_INIT(cp_Utf8_big_chars, DELTA5_spec, 0), BAND_INIT(cp_Int, UDELTA5_spec, 0),
- BAND_INIT(cp_Float, UDELTA5_spec, 0), BAND_INIT(cp_Long_hi, UDELTA5_spec, 0),
- BAND_INIT(cp_Long_lo, DELTA5_spec, 0), BAND_INIT(cp_Double_hi, UDELTA5_spec, 0),
- BAND_INIT(cp_Double_lo, DELTA5_spec, 0),
- BAND_INIT(cp_String, UDELTA5_spec, INDEX(CONSTANT_Utf8)),
- BAND_INIT(cp_Class, UDELTA5_spec, INDEX(CONSTANT_Utf8)),
- BAND_INIT(cp_Signature_form, DELTA5_spec, INDEX(CONSTANT_Utf8)),
- BAND_INIT(cp_Signature_classes, UDELTA5_spec, INDEX(CONSTANT_Class)),
- BAND_INIT(cp_Descr_name, DELTA5_spec, INDEX(CONSTANT_Utf8)),
- BAND_INIT(cp_Descr_type, UDELTA5_spec, INDEX(CONSTANT_Signature)),
- BAND_INIT(cp_Field_class, DELTA5_spec, INDEX(CONSTANT_Class)),
- BAND_INIT(cp_Field_desc, UDELTA5_spec, INDEX(CONSTANT_NameandType)),
- BAND_INIT(cp_Method_class, DELTA5_spec, INDEX(CONSTANT_Class)),
- BAND_INIT(cp_Method_desc, UDELTA5_spec, INDEX(CONSTANT_NameandType)),
- BAND_INIT(cp_Imethod_class, DELTA5_spec, INDEX(CONSTANT_Class)),
- BAND_INIT(cp_Imethod_desc, UDELTA5_spec, INDEX(CONSTANT_NameandType)),
- BAND_INIT(attr_definition_headers, BYTE1_spec, 0),
- BAND_INIT(attr_definition_name, UNSIGNED5_spec, INDEX(CONSTANT_Utf8)),
- BAND_INIT(attr_definition_layout, UNSIGNED5_spec, INDEX(CONSTANT_Utf8)),
- BAND_INIT(ic_this_class, UDELTA5_spec, INDEX(CONSTANT_Class)),
- BAND_INIT(ic_flags, UNSIGNED5_spec, 0),
- BAND_INIT(ic_outer_class, DELTA5_spec, NULL_OR_INDEX(CONSTANT_Class)),
- BAND_INIT(ic_name, DELTA5_spec, NULL_OR_INDEX(CONSTANT_Utf8)),
- BAND_INIT(class_this, DELTA5_spec, INDEX(CONSTANT_Class)),
- BAND_INIT(class_super, DELTA5_spec, INDEX(CONSTANT_Class)),
- BAND_INIT(class_interface_count, DELTA5_spec, 0),
- BAND_INIT(class_interface, DELTA5_spec, INDEX(CONSTANT_Class)),
- BAND_INIT(class_field_count, DELTA5_spec, 0),
- BAND_INIT(class_method_count, DELTA5_spec, 0),
- BAND_INIT(field_descr, DELTA5_spec, INDEX(CONSTANT_NameandType)),
- BAND_INIT(field_flags_hi, UNSIGNED5_spec, 0),
- BAND_INIT(field_flags_lo, UNSIGNED5_spec, 0),
- BAND_INIT(field_attr_count, UNSIGNED5_spec, 0),
- BAND_INIT(field_attr_indexes, UNSIGNED5_spec, 0),
- BAND_INIT(field_attr_calls, UNSIGNED5_spec, 0),
- BAND_INIT(field_ConstantValue_KQ, UNSIGNED5_spec, INDEX(CONSTANT_Literal)),
- BAND_INIT(field_Signature_RS, UNSIGNED5_spec, INDEX(CONSTANT_Signature)),
- BAND_INIT(field_metadata_bands, -1, -1), BAND_INIT(field_attr_bands, -1, -1),
- BAND_INIT(method_descr, MDELTA5_spec, INDEX(CONSTANT_NameandType)),
- BAND_INIT(method_flags_hi, UNSIGNED5_spec, 0),
- BAND_INIT(method_flags_lo, UNSIGNED5_spec, 0),
- BAND_INIT(method_attr_count, UNSIGNED5_spec, 0),
- BAND_INIT(method_attr_indexes, UNSIGNED5_spec, 0),
- BAND_INIT(method_attr_calls, UNSIGNED5_spec, 0),
- BAND_INIT(method_Exceptions_N, UNSIGNED5_spec, 0),
- BAND_INIT(method_Exceptions_RC, UNSIGNED5_spec, INDEX(CONSTANT_Class)),
- BAND_INIT(method_Signature_RS, UNSIGNED5_spec, INDEX(CONSTANT_Signature)),
- BAND_INIT(method_metadata_bands, -1, -1), BAND_INIT(method_attr_bands, -1, -1),
- BAND_INIT(class_flags_hi, UNSIGNED5_spec, 0),
- BAND_INIT(class_flags_lo, UNSIGNED5_spec, 0),
- BAND_INIT(class_attr_count, UNSIGNED5_spec, 0),
- BAND_INIT(class_attr_indexes, UNSIGNED5_spec, 0),
- BAND_INIT(class_attr_calls, UNSIGNED5_spec, 0),
- BAND_INIT(class_SourceFile_RUN, UNSIGNED5_spec, NULL_OR_INDEX(CONSTANT_Utf8)),
- BAND_INIT(class_EnclosingMethod_RC, UNSIGNED5_spec, INDEX(CONSTANT_Class)),
- BAND_INIT(class_EnclosingMethod_RDN, UNSIGNED5_spec,
- NULL_OR_INDEX(CONSTANT_NameandType)),
- BAND_INIT(class_Signature_RS, UNSIGNED5_spec, INDEX(CONSTANT_Signature)),
- BAND_INIT(class_metadata_bands, -1, -1),
- BAND_INIT(class_InnerClasses_N, UNSIGNED5_spec, 0),
- BAND_INIT(class_InnerClasses_RC, UNSIGNED5_spec, INDEX(CONSTANT_Class)),
- BAND_INIT(class_InnerClasses_F, UNSIGNED5_spec, 0),
- BAND_INIT(class_InnerClasses_outer_RCN, UNSIGNED5_spec, NULL_OR_INDEX(CONSTANT_Class)),
- BAND_INIT(class_InnerClasses_name_RUN, UNSIGNED5_spec, NULL_OR_INDEX(CONSTANT_Utf8)),
- BAND_INIT(class_ClassFile_version_minor_H, UNSIGNED5_spec, 0),
- BAND_INIT(class_ClassFile_version_major_H, UNSIGNED5_spec, 0),
- BAND_INIT(class_attr_bands, -1, -1), BAND_INIT(code_headers, BYTE1_spec, 0),
- BAND_INIT(code_max_stack, UNSIGNED5_spec, 0),
- BAND_INIT(code_max_na_locals, UNSIGNED5_spec, 0),
- BAND_INIT(code_handler_count, UNSIGNED5_spec, 0),
- BAND_INIT(code_handler_start_P, BCI5_spec, 0),
- BAND_INIT(code_handler_end_PO, BRANCH5_spec, 0),
- BAND_INIT(code_handler_catch_PO, BRANCH5_spec, 0),
- BAND_INIT(code_handler_class_RCN, UNSIGNED5_spec, NULL_OR_INDEX(CONSTANT_Class)),
- BAND_INIT(code_flags_hi, UNSIGNED5_spec, 0),
- BAND_INIT(code_flags_lo, UNSIGNED5_spec, 0),
- BAND_INIT(code_attr_count, UNSIGNED5_spec, 0),
- BAND_INIT(code_attr_indexes, UNSIGNED5_spec, 0),
- BAND_INIT(code_attr_calls, UNSIGNED5_spec, 0),
- BAND_INIT(code_StackMapTable_N, UNSIGNED5_spec, 0),
- BAND_INIT(code_StackMapTable_frame_T, BYTE1_spec, 0),
- BAND_INIT(code_StackMapTable_local_N, UNSIGNED5_spec, 0),
- BAND_INIT(code_StackMapTable_stack_N, UNSIGNED5_spec, 0),
- BAND_INIT(code_StackMapTable_offset, UNSIGNED5_spec, 0),
- BAND_INIT(code_StackMapTable_T, BYTE1_spec, 0),
- BAND_INIT(code_StackMapTable_RC, UNSIGNED5_spec, INDEX(CONSTANT_Class)),
- BAND_INIT(code_StackMapTable_P, BCI5_spec, 0),
- BAND_INIT(code_LineNumberTable_N, UNSIGNED5_spec, 0),
- BAND_INIT(code_LineNumberTable_bci_P, BCI5_spec, 0),
- BAND_INIT(code_LineNumberTable_line, UNSIGNED5_spec, 0),
- BAND_INIT(code_LocalVariableTable_N, UNSIGNED5_spec, 0),
- BAND_INIT(code_LocalVariableTable_bci_P, BCI5_spec, 0),
- BAND_INIT(code_LocalVariableTable_span_O, BRANCH5_spec, 0),
- BAND_INIT(code_LocalVariableTable_name_RU, UNSIGNED5_spec, INDEX(CONSTANT_Utf8)),
- BAND_INIT(code_LocalVariableTable_type_RS, UNSIGNED5_spec, INDEX(CONSTANT_Signature)),
- BAND_INIT(code_LocalVariableTable_slot, UNSIGNED5_spec, 0),
- BAND_INIT(code_LocalVariableTypeTable_N, UNSIGNED5_spec, 0),
- BAND_INIT(code_LocalVariableTypeTable_bci_P, BCI5_spec, 0),
- BAND_INIT(code_LocalVariableTypeTable_span_O, BRANCH5_spec, 0),
- BAND_INIT(code_LocalVariableTypeTable_name_RU, UNSIGNED5_spec, INDEX(CONSTANT_Utf8)),
- BAND_INIT(code_LocalVariableTypeTable_type_RS, UNSIGNED5_spec,
- INDEX(CONSTANT_Signature)),
- BAND_INIT(code_LocalVariableTypeTable_slot, UNSIGNED5_spec, 0),
- BAND_INIT(code_attr_bands, -1, -1), BAND_INIT(bc_codes, BYTE1_spec, 0),
- BAND_INIT(bc_case_count, UNSIGNED5_spec, 0), BAND_INIT(bc_case_value, DELTA5_spec, 0),
- BAND_INIT(bc_byte, BYTE1_spec, 0), BAND_INIT(bc_short, DELTA5_spec, 0),
- BAND_INIT(bc_local, UNSIGNED5_spec, 0), BAND_INIT(bc_label, BRANCH5_spec, 0),
- BAND_INIT(bc_intref, DELTA5_spec, INDEX(CONSTANT_Integer)),
- BAND_INIT(bc_floatref, DELTA5_spec, INDEX(CONSTANT_Float)),
- BAND_INIT(bc_longref, DELTA5_spec, INDEX(CONSTANT_Long)),
- BAND_INIT(bc_doubleref, DELTA5_spec, INDEX(CONSTANT_Double)),
- BAND_INIT(bc_stringref, DELTA5_spec, INDEX(CONSTANT_String)),
- BAND_INIT(bc_classref, UNSIGNED5_spec, NULL_OR_INDEX(CONSTANT_Class)),
- BAND_INIT(bc_fieldref, DELTA5_spec, INDEX(CONSTANT_Fieldref)),
- BAND_INIT(bc_methodref, UNSIGNED5_spec, INDEX(CONSTANT_Methodref)),
- BAND_INIT(bc_imethodref, DELTA5_spec, INDEX(CONSTANT_InterfaceMethodref)),
- BAND_INIT(bc_thisfield, UNSIGNED5_spec, SUB_INDEX(CONSTANT_Fieldref)),
- BAND_INIT(bc_superfield, UNSIGNED5_spec, SUB_INDEX(CONSTANT_Fieldref)),
- BAND_INIT(bc_thismethod, UNSIGNED5_spec, SUB_INDEX(CONSTANT_Methodref)),
- BAND_INIT(bc_supermethod, UNSIGNED5_spec, SUB_INDEX(CONSTANT_Methodref)),
- BAND_INIT(bc_initref, UNSIGNED5_spec, SUB_INDEX(CONSTANT_Methodref)),
- BAND_INIT(bc_escref, UNSIGNED5_spec, INDEX(CONSTANT_All)),
- BAND_INIT(bc_escrefsize, UNSIGNED5_spec, 0), BAND_INIT(bc_escsize, UNSIGNED5_spec, 0),
- BAND_INIT(bc_escbyte, BYTE1_spec, 0),
- BAND_INIT(file_name, UNSIGNED5_spec, INDEX(CONSTANT_Utf8)),
- BAND_INIT(file_size_hi, UNSIGNED5_spec, 0), BAND_INIT(file_size_lo, UNSIGNED5_spec, 0),
- BAND_INIT(file_modtime, DELTA5_spec, 0), BAND_INIT(file_options, UNSIGNED5_spec, 0),
- // BAND_INIT(file_bits, BYTE1_spec, 0),
- {0, 0}};
+ {
+ // BAND_INIT(archive_magic, BYTE1_spec, 0),
+ // BAND_INIT(archive_header, UNSIGNED5_spec, 0),
+ // BAND_INIT(band_headers, BYTE1_spec, 0),
+ BAND_INIT(cp_Utf8_prefix, DELTA5_spec, 0), BAND_INIT(cp_Utf8_suffix, UNSIGNED5_spec, 0),
+ BAND_INIT(cp_Utf8_chars, CHAR3_spec, 0), BAND_INIT(cp_Utf8_big_suffix, DELTA5_spec, 0),
+ BAND_INIT(cp_Utf8_big_chars, DELTA5_spec, 0), BAND_INIT(cp_Int, UDELTA5_spec, 0),
+ BAND_INIT(cp_Float, UDELTA5_spec, 0), BAND_INIT(cp_Long_hi, UDELTA5_spec, 0),
+ BAND_INIT(cp_Long_lo, DELTA5_spec, 0), BAND_INIT(cp_Double_hi, UDELTA5_spec, 0),
+ BAND_INIT(cp_Double_lo, DELTA5_spec, 0),
+ BAND_INIT(cp_String, UDELTA5_spec, INDEX(CONSTANT_Utf8)),
+ BAND_INIT(cp_Class, UDELTA5_spec, INDEX(CONSTANT_Utf8)),
+ BAND_INIT(cp_Signature_form, DELTA5_spec, INDEX(CONSTANT_Utf8)),
+ BAND_INIT(cp_Signature_classes, UDELTA5_spec, INDEX(CONSTANT_Class)),
+ BAND_INIT(cp_Descr_name, DELTA5_spec, INDEX(CONSTANT_Utf8)),
+ BAND_INIT(cp_Descr_type, UDELTA5_spec, INDEX(CONSTANT_Signature)),
+ BAND_INIT(cp_Field_class, DELTA5_spec, INDEX(CONSTANT_Class)),
+ BAND_INIT(cp_Field_desc, UDELTA5_spec, INDEX(CONSTANT_NameandType)),
+ BAND_INIT(cp_Method_class, DELTA5_spec, INDEX(CONSTANT_Class)),
+ BAND_INIT(cp_Method_desc, UDELTA5_spec, INDEX(CONSTANT_NameandType)),
+ BAND_INIT(cp_Imethod_class, DELTA5_spec, INDEX(CONSTANT_Class)),
+ BAND_INIT(cp_Imethod_desc, UDELTA5_spec, INDEX(CONSTANT_NameandType)),
+ BAND_INIT(attr_definition_headers, BYTE1_spec, 0),
+ BAND_INIT(attr_definition_name, UNSIGNED5_spec, INDEX(CONSTANT_Utf8)),
+ BAND_INIT(attr_definition_layout, UNSIGNED5_spec, INDEX(CONSTANT_Utf8)),
+ BAND_INIT(ic_this_class, UDELTA5_spec, INDEX(CONSTANT_Class)),
+ BAND_INIT(ic_flags, UNSIGNED5_spec, 0),
+ BAND_INIT(ic_outer_class, DELTA5_spec, NULL_OR_INDEX(CONSTANT_Class)),
+ BAND_INIT(ic_name, DELTA5_spec, NULL_OR_INDEX(CONSTANT_Utf8)),
+ BAND_INIT(class_this, DELTA5_spec, INDEX(CONSTANT_Class)),
+ BAND_INIT(class_super, DELTA5_spec, INDEX(CONSTANT_Class)),
+ BAND_INIT(class_interface_count, DELTA5_spec, 0),
+ BAND_INIT(class_interface, DELTA5_spec, INDEX(CONSTANT_Class)),
+ BAND_INIT(class_field_count, DELTA5_spec, 0),
+ BAND_INIT(class_method_count, DELTA5_spec, 0),
+ BAND_INIT(field_descr, DELTA5_spec, INDEX(CONSTANT_NameandType)),
+ BAND_INIT(field_flags_hi, UNSIGNED5_spec, 0),
+ BAND_INIT(field_flags_lo, UNSIGNED5_spec, 0),
+ BAND_INIT(field_attr_count, UNSIGNED5_spec, 0),
+ BAND_INIT(field_attr_indexes, UNSIGNED5_spec, 0),
+ BAND_INIT(field_attr_calls, UNSIGNED5_spec, 0),
+ BAND_INIT(field_ConstantValue_KQ, UNSIGNED5_spec, INDEX(CONSTANT_Literal)),
+ BAND_INIT(field_Signature_RS, UNSIGNED5_spec, INDEX(CONSTANT_Signature)),
+ BAND_INIT(field_metadata_bands, -1, -1), BAND_INIT(field_attr_bands, -1, -1),
+ BAND_INIT(method_descr, MDELTA5_spec, INDEX(CONSTANT_NameandType)),
+ BAND_INIT(method_flags_hi, UNSIGNED5_spec, 0),
+ BAND_INIT(method_flags_lo, UNSIGNED5_spec, 0),
+ BAND_INIT(method_attr_count, UNSIGNED5_spec, 0),
+ BAND_INIT(method_attr_indexes, UNSIGNED5_spec, 0),
+ BAND_INIT(method_attr_calls, UNSIGNED5_spec, 0),
+ BAND_INIT(method_Exceptions_N, UNSIGNED5_spec, 0),
+ BAND_INIT(method_Exceptions_RC, UNSIGNED5_spec, INDEX(CONSTANT_Class)),
+ BAND_INIT(method_Signature_RS, UNSIGNED5_spec, INDEX(CONSTANT_Signature)),
+ BAND_INIT(method_metadata_bands, -1, -1), BAND_INIT(method_attr_bands, -1, -1),
+ BAND_INIT(class_flags_hi, UNSIGNED5_spec, 0),
+ BAND_INIT(class_flags_lo, UNSIGNED5_spec, 0),
+ BAND_INIT(class_attr_count, UNSIGNED5_spec, 0),
+ BAND_INIT(class_attr_indexes, UNSIGNED5_spec, 0),
+ BAND_INIT(class_attr_calls, UNSIGNED5_spec, 0),
+ BAND_INIT(class_SourceFile_RUN, UNSIGNED5_spec, NULL_OR_INDEX(CONSTANT_Utf8)),
+ BAND_INIT(class_EnclosingMethod_RC, UNSIGNED5_spec, INDEX(CONSTANT_Class)),
+ BAND_INIT(class_EnclosingMethod_RDN, UNSIGNED5_spec,
+ NULL_OR_INDEX(CONSTANT_NameandType)),
+ BAND_INIT(class_Signature_RS, UNSIGNED5_spec, INDEX(CONSTANT_Signature)),
+ BAND_INIT(class_metadata_bands, -1, -1),
+ BAND_INIT(class_InnerClasses_N, UNSIGNED5_spec, 0),
+ BAND_INIT(class_InnerClasses_RC, UNSIGNED5_spec, INDEX(CONSTANT_Class)),
+ BAND_INIT(class_InnerClasses_F, UNSIGNED5_spec, 0),
+ BAND_INIT(class_InnerClasses_outer_RCN, UNSIGNED5_spec, NULL_OR_INDEX(CONSTANT_Class)),
+ BAND_INIT(class_InnerClasses_name_RUN, UNSIGNED5_spec, NULL_OR_INDEX(CONSTANT_Utf8)),
+ BAND_INIT(class_ClassFile_version_minor_H, UNSIGNED5_spec, 0),
+ BAND_INIT(class_ClassFile_version_major_H, UNSIGNED5_spec, 0),
+ BAND_INIT(class_attr_bands, -1, -1), BAND_INIT(code_headers, BYTE1_spec, 0),
+ BAND_INIT(code_max_stack, UNSIGNED5_spec, 0),
+ BAND_INIT(code_max_na_locals, UNSIGNED5_spec, 0),
+ BAND_INIT(code_handler_count, UNSIGNED5_spec, 0),
+ BAND_INIT(code_handler_start_P, BCI5_spec, 0),
+ BAND_INIT(code_handler_end_PO, BRANCH5_spec, 0),
+ BAND_INIT(code_handler_catch_PO, BRANCH5_spec, 0),
+ BAND_INIT(code_handler_class_RCN, UNSIGNED5_spec, NULL_OR_INDEX(CONSTANT_Class)),
+ BAND_INIT(code_flags_hi, UNSIGNED5_spec, 0),
+ BAND_INIT(code_flags_lo, UNSIGNED5_spec, 0),
+ BAND_INIT(code_attr_count, UNSIGNED5_spec, 0),
+ BAND_INIT(code_attr_indexes, UNSIGNED5_spec, 0),
+ BAND_INIT(code_attr_calls, UNSIGNED5_spec, 0),
+ BAND_INIT(code_StackMapTable_N, UNSIGNED5_spec, 0),
+ BAND_INIT(code_StackMapTable_frame_T, BYTE1_spec, 0),
+ BAND_INIT(code_StackMapTable_local_N, UNSIGNED5_spec, 0),
+ BAND_INIT(code_StackMapTable_stack_N, UNSIGNED5_spec, 0),
+ BAND_INIT(code_StackMapTable_offset, UNSIGNED5_spec, 0),
+ BAND_INIT(code_StackMapTable_T, BYTE1_spec, 0),
+ BAND_INIT(code_StackMapTable_RC, UNSIGNED5_spec, INDEX(CONSTANT_Class)),
+ BAND_INIT(code_StackMapTable_P, BCI5_spec, 0),
+ BAND_INIT(code_LineNumberTable_N, UNSIGNED5_spec, 0),
+ BAND_INIT(code_LineNumberTable_bci_P, BCI5_spec, 0),
+ BAND_INIT(code_LineNumberTable_line, UNSIGNED5_spec, 0),
+ BAND_INIT(code_LocalVariableTable_N, UNSIGNED5_spec, 0),
+ BAND_INIT(code_LocalVariableTable_bci_P, BCI5_spec, 0),
+ BAND_INIT(code_LocalVariableTable_span_O, BRANCH5_spec, 0),
+ BAND_INIT(code_LocalVariableTable_name_RU, UNSIGNED5_spec, INDEX(CONSTANT_Utf8)),
+ BAND_INIT(code_LocalVariableTable_type_RS, UNSIGNED5_spec, INDEX(CONSTANT_Signature)),
+ BAND_INIT(code_LocalVariableTable_slot, UNSIGNED5_spec, 0),
+ BAND_INIT(code_LocalVariableTypeTable_N, UNSIGNED5_spec, 0),
+ BAND_INIT(code_LocalVariableTypeTable_bci_P, BCI5_spec, 0),
+ BAND_INIT(code_LocalVariableTypeTable_span_O, BRANCH5_spec, 0),
+ BAND_INIT(code_LocalVariableTypeTable_name_RU, UNSIGNED5_spec, INDEX(CONSTANT_Utf8)),
+ BAND_INIT(code_LocalVariableTypeTable_type_RS, UNSIGNED5_spec,
+ INDEX(CONSTANT_Signature)),
+ BAND_INIT(code_LocalVariableTypeTable_slot, UNSIGNED5_spec, 0),
+ BAND_INIT(code_attr_bands, -1, -1), BAND_INIT(bc_codes, BYTE1_spec, 0),
+ BAND_INIT(bc_case_count, UNSIGNED5_spec, 0), BAND_INIT(bc_case_value, DELTA5_spec, 0),
+ BAND_INIT(bc_byte, BYTE1_spec, 0), BAND_INIT(bc_short, DELTA5_spec, 0),
+ BAND_INIT(bc_local, UNSIGNED5_spec, 0), BAND_INIT(bc_label, BRANCH5_spec, 0),
+ BAND_INIT(bc_intref, DELTA5_spec, INDEX(CONSTANT_Integer)),
+ BAND_INIT(bc_floatref, DELTA5_spec, INDEX(CONSTANT_Float)),
+ BAND_INIT(bc_longref, DELTA5_spec, INDEX(CONSTANT_Long)),
+ BAND_INIT(bc_doubleref, DELTA5_spec, INDEX(CONSTANT_Double)),
+ BAND_INIT(bc_stringref, DELTA5_spec, INDEX(CONSTANT_String)),
+ BAND_INIT(bc_classref, UNSIGNED5_spec, NULL_OR_INDEX(CONSTANT_Class)),
+ BAND_INIT(bc_fieldref, DELTA5_spec, INDEX(CONSTANT_Fieldref)),
+ BAND_INIT(bc_methodref, UNSIGNED5_spec, INDEX(CONSTANT_Methodref)),
+ BAND_INIT(bc_imethodref, DELTA5_spec, INDEX(CONSTANT_InterfaceMethodref)),
+ BAND_INIT(bc_thisfield, UNSIGNED5_spec, SUB_INDEX(CONSTANT_Fieldref)),
+ BAND_INIT(bc_superfield, UNSIGNED5_spec, SUB_INDEX(CONSTANT_Fieldref)),
+ BAND_INIT(bc_thismethod, UNSIGNED5_spec, SUB_INDEX(CONSTANT_Methodref)),
+ BAND_INIT(bc_supermethod, UNSIGNED5_spec, SUB_INDEX(CONSTANT_Methodref)),
+ BAND_INIT(bc_initref, UNSIGNED5_spec, SUB_INDEX(CONSTANT_Methodref)),
+ BAND_INIT(bc_escref, UNSIGNED5_spec, INDEX(CONSTANT_All)),
+ BAND_INIT(bc_escrefsize, UNSIGNED5_spec, 0), BAND_INIT(bc_escsize, UNSIGNED5_spec, 0),
+ BAND_INIT(bc_escbyte, BYTE1_spec, 0),
+ BAND_INIT(file_name, UNSIGNED5_spec, INDEX(CONSTANT_Utf8)),
+ BAND_INIT(file_size_hi, UNSIGNED5_spec, 0), BAND_INIT(file_size_lo, UNSIGNED5_spec, 0),
+ BAND_INIT(file_modtime, DELTA5_spec, 0), BAND_INIT(file_options, UNSIGNED5_spec, 0),
+ // BAND_INIT(file_bits, BYTE1_spec, 0),
+ {0, 0}};
band *band::makeBands(unpacker *u)
{
- band *tmp_all_bands = U_NEW(band, BAND_LIMIT);
- for (int i = 0; i < BAND_LIMIT; i++)
- {
- assert((byte *)&all_band_inits[i + 1] <
- (byte *)all_band_inits + sizeof(all_band_inits));
- const band_init &bi = all_band_inits[i];
- band &b = tmp_all_bands[i];
- coding *defc = coding::findBySpec(bi.defc);
- assert((defc == nullptr) == (bi.defc == -1)); // no garbage, please
- assert(defc == nullptr || !defc->isMalloc);
- b.init(u, i, defc);
- if (bi.index > 0)
- {
- b.nullOK = ((bi.index >> 8) & 1);
- b.ixTag = (bi.index & 0xFF);
- }
- }
- return tmp_all_bands;
+ band *tmp_all_bands = U_NEW(band, BAND_LIMIT);
+ for (int i = 0; i < BAND_LIMIT; i++)
+ {
+ assert((byte *)&all_band_inits[i + 1] <
+ (byte *)all_band_inits + sizeof(all_band_inits));
+ const band_init &bi = all_band_inits[i];
+ band &b = tmp_all_bands[i];
+ coding *defc = coding::findBySpec(bi.defc);
+ assert((defc == nullptr) == (bi.defc == -1)); // no garbage, please
+ assert(defc == nullptr || !defc->isMalloc);
+ b.init(u, i, defc);
+ if (bi.index > 0)
+ {
+ b.nullOK = ((bi.index >> 8) & 1);
+ b.ixTag = (bi.index & 0xFF);
+ }
+ }
+ return tmp_all_bands;
}
void band::initIndexes(unpacker *u)
{
- band *tmp_all_bands = u->all_bands;
- for (int i = 0; i < BAND_LIMIT; i++)
- {
- band *scan = &tmp_all_bands[i];
- uint32_t tag = scan->ixTag; // Cf. #define INDEX(tag) above
- if (tag != 0 && tag != CONSTANT_Literal && (tag & SUBINDEX_BIT) == 0)
- {
- scan->setIndex(u->cp.getIndex(tag));
- }
- }
+ band *tmp_all_bands = u->all_bands;
+ for (int i = 0; i < BAND_LIMIT; i++)
+ {
+ band *scan = &tmp_all_bands[i];
+ uint32_t tag = scan->ixTag; // Cf. #define INDEX(tag) above
+ if (tag != 0 && tag != CONSTANT_Literal && (tag & SUBINDEX_BIT) == 0)
+ {
+ scan->setIndex(u->cp.getIndex(tag));
+ }
+ }
}
diff --git a/libraries/pack200/src/bands.h b/libraries/pack200/src/bands.h
index a56cd7d5..66c5aec4 100644
--- a/libraries/pack200/src/bands.h
+++ b/libraries/pack200/src/bands.h
@@ -30,138 +30,138 @@ struct unpacker;
struct band
{
- int bn; // band_number of this band
- coding *defc; // default coding method
- cpindex *ix; // CP entry mapping, if CPRefBand
- byte ixTag; // 0 or 1; nullptr is coded as (nullOK?0:-1)
- byte nullOK; // 0 or 1; nullptr is coded as (nullOK?0:-1)
- int length; // expected # values
- unpacker *u; // back pointer
-
- value_stream vs[2]; // source of values
- coding_method cm; // method used for initial state of vs[0]
- byte *rplimit; // end of band (encoded, transmitted)
-
- int total_memo; // cached value of getIntTotal, or -1
- int *hist0; // approximate. histogram
- enum
- {
- HIST0_MIN = 0,
- HIST0_MAX = 255
- }; // catches the usual cases
-
- // properties for attribute layout elements:
- byte le_kind; // EK_XXX
- byte le_bci; // 0,EK_BCI,EK_BCD,EK_BCO
- byte le_back; // ==EF_BACK
- byte le_len; // 0,1,2,4 (size in classfile), or call addr
- band **le_body; // body of repl, union, call (nullptr-terminated)
+ int bn; // band_number of this band
+ coding *defc; // default coding method
+ cpindex *ix; // CP entry mapping, if CPRefBand
+ byte ixTag; // 0 or 1; nullptr is coded as (nullOK?0:-1)
+ byte nullOK; // 0 or 1; nullptr is coded as (nullOK?0:-1)
+ int length; // expected # values
+ unpacker *u; // back pointer
+
+ value_stream vs[2]; // source of values
+ coding_method cm; // method used for initial state of vs[0]
+ byte *rplimit; // end of band (encoded, transmitted)
+
+ int total_memo; // cached value of getIntTotal, or -1
+ int *hist0; // approximate. histogram
+ enum
+ {
+ HIST0_MIN = 0,
+ HIST0_MAX = 255
+ }; // catches the usual cases
+
+ // properties for attribute layout elements:
+ byte le_kind; // EK_XXX
+ byte le_bci; // 0,EK_BCI,EK_BCD,EK_BCO
+ byte le_back; // ==EF_BACK
+ byte le_len; // 0,1,2,4 (size in classfile), or call addr
+ band **le_body; // body of repl, union, call (nullptr-terminated)
// Note: EK_CASE elements use hist0 to record union tags.
#define le_casetags hist0
- band &nextBand()
- {
- return this[1];
- }
- band &prevBand()
- {
- return this[-1];
- }
-
- void init(unpacker *u_, int bn_, coding *defc_)
- {
- u = u_;
- cm.u = u_;
- bn = bn_;
- defc = defc_;
- }
- void init(unpacker *u_, int bn_, int defcSpec)
- {
- init(u_, bn_, coding::findBySpec(defcSpec));
- }
- void initRef(int ixTag_ = 0, bool nullOK_ = false)
- {
- ixTag = ixTag_;
- nullOK = nullOK_;
- setIndexByTag(ixTag);
- }
-
- void expectMoreLength(int l)
- {
- assert(length >= 0); // able to accept a length
- assert((int)l >= 0); // no overflow
- assert(rplimit == nullptr); // readData not yet called
- length += l;
- assert(length >= l); // no overflow
- }
-
- void setIndex(cpindex *ix_);
- void setIndexByTag(byte tag);
-
- // Parse the band and its meta-coding header.
- void readData(int expectedLength = 0);
-
- // Reset the band for another pass (Cf. Java Band.resetForSecondPass.)
- void rewind()
- {
- cm.reset(&vs[0]);
- }
-
- byte *&curRP()
- {
- return vs[0].rp;
- }
- byte *minRP()
- {
- return cm.vs0.rp;
- }
- byte *maxRP()
- {
- return rplimit;
- }
- size_t size()
- {
- return maxRP() - minRP();
- }
-
- int getByte()
- {
- assert(ix == nullptr);
- return vs[0].getByte();
- }
- int getInt()
- {
- assert(ix == nullptr);
- return vs[0].getInt();
- }
- entry *getRefN()
- {
- assert(ix != nullptr);
- return getRefCommon(ix, true);
- }
- entry *getRef()
- {
- assert(ix != nullptr);
- return getRefCommon(ix, false);
- }
- entry *getRefUsing(cpindex *ix2)
- {
- assert(ix == nullptr);
- return getRefCommon(ix2, true);
- }
- entry *getRefCommon(cpindex *ix, bool nullOK);
- int64_t getLong(band &lo_band, bool have_hi);
-
- static int64_t makeLong(uint32_t hi, uint32_t lo)
- {
- return ((uint64_t)hi << 32) + (((uint64_t)lo << 32) >> 32);
- }
-
- int getIntTotal();
- int getIntCount(int tag);
-
- static band *makeBands(unpacker *u);
- static void initIndexes(unpacker *u);
+ band &nextBand()
+ {
+ return this[1];
+ }
+ band &prevBand()
+ {
+ return this[-1];
+ }
+
+ void init(unpacker *u_, int bn_, coding *defc_)
+ {
+ u = u_;
+ cm.u = u_;
+ bn = bn_;
+ defc = defc_;
+ }
+ void init(unpacker *u_, int bn_, int defcSpec)
+ {
+ init(u_, bn_, coding::findBySpec(defcSpec));
+ }
+ void initRef(int ixTag_ = 0, bool nullOK_ = false)
+ {
+ ixTag = ixTag_;
+ nullOK = nullOK_;
+ setIndexByTag(ixTag);
+ }
+
+ void expectMoreLength(int l)
+ {
+ assert(length >= 0); // able to accept a length
+ assert((int)l >= 0); // no overflow
+ assert(rplimit == nullptr); // readData not yet called
+ length += l;
+ assert(length >= l); // no overflow
+ }
+
+ void setIndex(cpindex *ix_);
+ void setIndexByTag(byte tag);
+
+ // Parse the band and its meta-coding header.
+ void readData(int expectedLength = 0);
+
+ // Reset the band for another pass (Cf. Java Band.resetForSecondPass.)
+ void rewind()
+ {
+ cm.reset(&vs[0]);
+ }
+
+ byte *&curRP()
+ {
+ return vs[0].rp;
+ }
+ byte *minRP()
+ {
+ return cm.vs0.rp;
+ }
+ byte *maxRP()
+ {
+ return rplimit;
+ }
+ size_t size()
+ {
+ return maxRP() - minRP();
+ }
+
+ int getByte()
+ {
+ assert(ix == nullptr);
+ return vs[0].getByte();
+ }
+ int getInt()
+ {
+ assert(ix == nullptr);
+ return vs[0].getInt();
+ }
+ entry *getRefN()
+ {
+ assert(ix != nullptr);
+ return getRefCommon(ix, true);
+ }
+ entry *getRef()
+ {
+ assert(ix != nullptr);
+ return getRefCommon(ix, false);
+ }
+ entry *getRefUsing(cpindex *ix2)
+ {
+ assert(ix == nullptr);
+ return getRefCommon(ix2, true);
+ }
+ entry *getRefCommon(cpindex *ix, bool nullOK);
+ int64_t getLong(band &lo_band, bool have_hi);
+
+ static int64_t makeLong(uint32_t hi, uint32_t lo)
+ {
+ return ((uint64_t)hi << 32) + (((uint64_t)lo << 32) >> 32);
+ }
+
+ int getIntTotal();
+ int getIntCount(int tag);
+
+ static band *makeBands(unpacker *u);
+ static void initIndexes(unpacker *u);
};
extern band all_bands[];
@@ -173,179 +173,179 @@ extern band all_bands[];
// Band schema:
enum band_number
{
- // e_archive_magic,
- // e_archive_header,
- // e_band_headers,
-
- // constant pool contents
- e_cp_Utf8_prefix,
- e_cp_Utf8_suffix,
- e_cp_Utf8_chars,
- e_cp_Utf8_big_suffix,
- e_cp_Utf8_big_chars,
- e_cp_Int,
- e_cp_Float,
- e_cp_Long_hi,
- e_cp_Long_lo,
- e_cp_Double_hi,
- e_cp_Double_lo,
- e_cp_String,
- e_cp_Class,
- e_cp_Signature_form,
- e_cp_Signature_classes,
- e_cp_Descr_name,
- e_cp_Descr_type,
- e_cp_Field_class,
- e_cp_Field_desc,
- e_cp_Method_class,
- e_cp_Method_desc,
- e_cp_Imethod_class,
- e_cp_Imethod_desc,
-
- // bands which define transmission of attributes
- e_attr_definition_headers,
- e_attr_definition_name,
- e_attr_definition_layout,
-
- // band for hardwired InnerClasses attribute (shared across the package)
- e_ic_this_class,
- e_ic_flags,
- // These bands contain data only where flags sets ACC_IC_LONG_FORM:
- e_ic_outer_class,
- e_ic_name,
-
- // bands for carrying class schema information:
- e_class_this,
- e_class_super,
- e_class_interface_count,
- e_class_interface,
-
- // bands for class members
- e_class_field_count,
- e_class_method_count,
- e_field_descr,
- e_field_flags_hi,
- e_field_flags_lo,
- e_field_attr_count,
- e_field_attr_indexes,
- e_field_attr_calls,
- e_field_ConstantValue_KQ,
- e_field_Signature_RS,
- e_field_metadata_bands,
- e_field_attr_bands,
- e_method_descr,
- e_method_flags_hi,
- e_method_flags_lo,
- e_method_attr_count,
- e_method_attr_indexes,
- e_method_attr_calls,
- e_method_Exceptions_N,
- e_method_Exceptions_RC,
- e_method_Signature_RS,
- e_method_metadata_bands,
- e_method_attr_bands,
- e_class_flags_hi,
- e_class_flags_lo,
- e_class_attr_count,
- e_class_attr_indexes,
- e_class_attr_calls,
- e_class_SourceFile_RUN,
- e_class_EnclosingMethod_RC,
- e_class_EnclosingMethod_RDN,
- e_class_Signature_RS,
- e_class_metadata_bands,
- e_class_InnerClasses_N,
- e_class_InnerClasses_RC,
- e_class_InnerClasses_F,
- e_class_InnerClasses_outer_RCN,
- e_class_InnerClasses_name_RUN,
- e_class_ClassFile_version_minor_H,
- e_class_ClassFile_version_major_H,
- e_class_attr_bands,
- e_code_headers,
- e_code_max_stack,
- e_code_max_na_locals,
- e_code_handler_count,
- e_code_handler_start_P,
- e_code_handler_end_PO,
- e_code_handler_catch_PO,
- e_code_handler_class_RCN,
-
- // code attributes
- e_code_flags_hi,
- e_code_flags_lo,
- e_code_attr_count,
- e_code_attr_indexes,
- e_code_attr_calls,
- e_code_StackMapTable_N,
- e_code_StackMapTable_frame_T,
- e_code_StackMapTable_local_N,
- e_code_StackMapTable_stack_N,
- e_code_StackMapTable_offset,
- e_code_StackMapTable_T,
- e_code_StackMapTable_RC,
- e_code_StackMapTable_P,
- e_code_LineNumberTable_N,
- e_code_LineNumberTable_bci_P,
- e_code_LineNumberTable_line,
- e_code_LocalVariableTable_N,
- e_code_LocalVariableTable_bci_P,
- e_code_LocalVariableTable_span_O,
- e_code_LocalVariableTable_name_RU,
- e_code_LocalVariableTable_type_RS,
- e_code_LocalVariableTable_slot,
- e_code_LocalVariableTypeTable_N,
- e_code_LocalVariableTypeTable_bci_P,
- e_code_LocalVariableTypeTable_span_O,
- e_code_LocalVariableTypeTable_name_RU,
- e_code_LocalVariableTypeTable_type_RS,
- e_code_LocalVariableTypeTable_slot,
- e_code_attr_bands,
-
- // bands for bytecodes
- e_bc_codes,
- // remaining bands provide typed opcode fields required by the bc_codes
- e_bc_case_count,
- e_bc_case_value,
- e_bc_byte,
- e_bc_short,
- e_bc_local,
- e_bc_label,
-
- // ldc* operands:
- e_bc_intref,
- e_bc_floatref,
- e_bc_longref,
- e_bc_doubleref,
- e_bc_stringref,
- e_bc_classref,
- e_bc_fieldref,
- e_bc_methodref,
- e_bc_imethodref,
-
- // _self_linker_op family
- e_bc_thisfield,
- e_bc_superfield,
- e_bc_thismethod,
- e_bc_supermethod,
-
- // bc_invokeinit family:
- e_bc_initref,
-
- // bytecode escape sequences
- e_bc_escref,
- e_bc_escrefsize,
- e_bc_escsize,
- e_bc_escbyte,
-
- // file attributes and contents
- e_file_name,
- e_file_size_hi,
- e_file_size_lo,
- e_file_modtime,
- e_file_options,
- // e_file_bits, // handled specially as an appendix
- BAND_LIMIT
+ // e_archive_magic,
+ // e_archive_header,
+ // e_band_headers,
+
+ // constant pool contents
+ e_cp_Utf8_prefix,
+ e_cp_Utf8_suffix,
+ e_cp_Utf8_chars,
+ e_cp_Utf8_big_suffix,
+ e_cp_Utf8_big_chars,
+ e_cp_Int,
+ e_cp_Float,
+ e_cp_Long_hi,
+ e_cp_Long_lo,
+ e_cp_Double_hi,
+ e_cp_Double_lo,
+ e_cp_String,
+ e_cp_Class,
+ e_cp_Signature_form,
+ e_cp_Signature_classes,
+ e_cp_Descr_name,
+ e_cp_Descr_type,
+ e_cp_Field_class,
+ e_cp_Field_desc,
+ e_cp_Method_class,
+ e_cp_Method_desc,
+ e_cp_Imethod_class,
+ e_cp_Imethod_desc,
+
+ // bands which define transmission of attributes
+ e_attr_definition_headers,
+ e_attr_definition_name,
+ e_attr_definition_layout,
+
+ // band for hardwired InnerClasses attribute (shared across the package)
+ e_ic_this_class,
+ e_ic_flags,
+ // These bands contain data only where flags sets ACC_IC_LONG_FORM:
+ e_ic_outer_class,
+ e_ic_name,
+
+ // bands for carrying class schema information:
+ e_class_this,
+ e_class_super,
+ e_class_interface_count,
+ e_class_interface,
+
+ // bands for class members
+ e_class_field_count,
+ e_class_method_count,
+ e_field_descr,
+ e_field_flags_hi,
+ e_field_flags_lo,
+ e_field_attr_count,
+ e_field_attr_indexes,
+ e_field_attr_calls,
+ e_field_ConstantValue_KQ,
+ e_field_Signature_RS,
+ e_field_metadata_bands,
+ e_field_attr_bands,
+ e_method_descr,
+ e_method_flags_hi,
+ e_method_flags_lo,
+ e_method_attr_count,
+ e_method_attr_indexes,
+ e_method_attr_calls,
+ e_method_Exceptions_N,
+ e_method_Exceptions_RC,
+ e_method_Signature_RS,
+ e_method_metadata_bands,
+ e_method_attr_bands,
+ e_class_flags_hi,
+ e_class_flags_lo,
+ e_class_attr_count,
+ e_class_attr_indexes,
+ e_class_attr_calls,
+ e_class_SourceFile_RUN,
+ e_class_EnclosingMethod_RC,
+ e_class_EnclosingMethod_RDN,
+ e_class_Signature_RS,
+ e_class_metadata_bands,
+ e_class_InnerClasses_N,
+ e_class_InnerClasses_RC,
+ e_class_InnerClasses_F,
+ e_class_InnerClasses_outer_RCN,
+ e_class_InnerClasses_name_RUN,
+ e_class_ClassFile_version_minor_H,
+ e_class_ClassFile_version_major_H,
+ e_class_attr_bands,
+ e_code_headers,
+ e_code_max_stack,
+ e_code_max_na_locals,
+ e_code_handler_count,
+ e_code_handler_start_P,
+ e_code_handler_end_PO,
+ e_code_handler_catch_PO,
+ e_code_handler_class_RCN,
+
+ // code attributes
+ e_code_flags_hi,
+ e_code_flags_lo,
+ e_code_attr_count,
+ e_code_attr_indexes,
+ e_code_attr_calls,
+ e_code_StackMapTable_N,
+ e_code_StackMapTable_frame_T,
+ e_code_StackMapTable_local_N,
+ e_code_StackMapTable_stack_N,
+ e_code_StackMapTable_offset,
+ e_code_StackMapTable_T,
+ e_code_StackMapTable_RC,
+ e_code_StackMapTable_P,
+ e_code_LineNumberTable_N,
+ e_code_LineNumberTable_bci_P,
+ e_code_LineNumberTable_line,
+ e_code_LocalVariableTable_N,
+ e_code_LocalVariableTable_bci_P,
+ e_code_LocalVariableTable_span_O,
+ e_code_LocalVariableTable_name_RU,
+ e_code_LocalVariableTable_type_RS,
+ e_code_LocalVariableTable_slot,
+ e_code_LocalVariableTypeTable_N,
+ e_code_LocalVariableTypeTable_bci_P,
+ e_code_LocalVariableTypeTable_span_O,
+ e_code_LocalVariableTypeTable_name_RU,
+ e_code_LocalVariableTypeTable_type_RS,
+ e_code_LocalVariableTypeTable_slot,
+ e_code_attr_bands,
+
+ // bands for bytecodes
+ e_bc_codes,
+ // remaining bands provide typed opcode fields required by the bc_codes
+ e_bc_case_count,
+ e_bc_case_value,
+ e_bc_byte,
+ e_bc_short,
+ e_bc_local,
+ e_bc_label,
+
+ // ldc* operands:
+ e_bc_intref,
+ e_bc_floatref,
+ e_bc_longref,
+ e_bc_doubleref,
+ e_bc_stringref,
+ e_bc_classref,
+ e_bc_fieldref,
+ e_bc_methodref,
+ e_bc_imethodref,
+
+ // _self_linker_op family
+ e_bc_thisfield,
+ e_bc_superfield,
+ e_bc_thismethod,
+ e_bc_supermethod,
+
+ // bc_invokeinit family:
+ e_bc_initref,
+
+ // bytecode escape sequences
+ e_bc_escref,
+ e_bc_escrefsize,
+ e_bc_escsize,
+ e_bc_escbyte,
+
+ // file attributes and contents
+ e_file_name,
+ e_file_size_hi,
+ e_file_size_lo,
+ e_file_modtime,
+ e_file_options,
+ // e_file_bits, // handled specially as an appendix
+ BAND_LIMIT
};
// Symbolic names for bands, as if in a giant global struct:
diff --git a/libraries/pack200/src/bytes.cpp b/libraries/pack200/src/bytes.cpp
index d3808afa..767fe0a5 100644
--- a/libraries/pack200/src/bytes.cpp
+++ b/libraries/pack200/src/bytes.cpp
@@ -36,182 +36,182 @@ static byte dummy[1 << 10];
bool bytes::inBounds(const void *p)
{
- return p >= ptr && p < limit();
+ return p >= ptr && p < limit();
}
void bytes::malloc(size_t len_)
{
- len = len_;
- ptr = NEW(byte, add_size(len_, 1)); // add trailing zero byte always
- if (ptr == nullptr)
- {
- // set ptr to some victim memory, to ease escape
- set(dummy, sizeof(dummy) - 1);
- unpack_abort(ERROR_ENOMEM);
- }
+ len = len_;
+ ptr = NEW(byte, add_size(len_, 1)); // add trailing zero byte always
+ if (ptr == nullptr)
+ {
+ // set ptr to some victim memory, to ease escape
+ set(dummy, sizeof(dummy) - 1);
+ unpack_abort(ERROR_ENOMEM);
+ }
}
void bytes::realloc(size_t len_)
{
- if (len == len_)
- return; // nothing to do
- if (ptr == dummy)
- return; // escaping from an error
- if (ptr == nullptr)
- {
- malloc(len_);
- return;
- }
- byte *oldptr = ptr;
- ptr = (len_ >= PSIZE_MAX) ? nullptr : (byte *)::realloc(ptr, add_size(len_, 1));
- if (ptr != nullptr)
- {
- if (len < len_)
- memset(ptr + len, 0, len_ - len);
- ptr[len_] = 0;
- len = len_;
- }
- else
- {
- ptr = oldptr; // ease our escape
- unpack_abort(ERROR_ENOMEM);
- }
+ if (len == len_)
+ return; // nothing to do
+ if (ptr == dummy)
+ return; // escaping from an error
+ if (ptr == nullptr)
+ {
+ malloc(len_);
+ return;
+ }
+ byte *oldptr = ptr;
+ ptr = (len_ >= PSIZE_MAX) ? nullptr : (byte *)::realloc(ptr, add_size(len_, 1));
+ if (ptr != nullptr)
+ {
+ if (len < len_)
+ memset(ptr + len, 0, len_ - len);
+ ptr[len_] = 0;
+ len = len_;
+ }
+ else
+ {
+ ptr = oldptr; // ease our escape
+ unpack_abort(ERROR_ENOMEM);
+ }
}
void bytes::free()
{
- if (ptr == dummy)
- return; // escaping from an error
- if (ptr != nullptr)
- {
- ::free(ptr);
- }
- len = 0;
- ptr = 0;
+ if (ptr == dummy)
+ return; // escaping from an error
+ if (ptr != nullptr)
+ {
+ ::free(ptr);
+ }
+ len = 0;
+ ptr = 0;
}
int bytes::indexOf(byte c)
{
- byte *p = (byte *)memchr(ptr, c, len);
- return (p == 0) ? -1 : (int)(p - ptr);
+ byte *p = (byte *)memchr(ptr, c, len);
+ return (p == 0) ? -1 : (int)(p - ptr);
}
byte *bytes::writeTo(byte *bp)
{
- memcpy(bp, ptr, len);
- return bp + len;
+ memcpy(bp, ptr, len);
+ return bp + len;
}
int bytes::compareTo(bytes &other)
{
- size_t l1 = len;
- size_t l2 = other.len;
- int cmp = memcmp(ptr, other.ptr, (l1 < l2) ? l1 : l2);
- if (cmp != 0)
- return cmp;
- return (l1 < l2) ? -1 : (l1 > l2) ? 1 : 0;
+ size_t l1 = len;
+ size_t l2 = other.len;
+ int cmp = memcmp(ptr, other.ptr, (l1 < l2) ? l1 : l2);
+ if (cmp != 0)
+ return cmp;
+ return (l1 < l2) ? -1 : (l1 > l2) ? 1 : 0;
}
void bytes::saveFrom(const void *ptr_, size_t len_)
{
- malloc(len_);
- // Save as much as possible.
- if (len_ > len)
- {
- assert(ptr == dummy); // error recovery
- len_ = len;
- }
- copyFrom(ptr_, len_);
+ malloc(len_);
+ // Save as much as possible.
+ if (len_ > len)
+ {
+ assert(ptr == dummy); // error recovery
+ len_ = len;
+ }
+ copyFrom(ptr_, len_);
}
//#TODO: Need to fix for exception handling
void bytes::copyFrom(const void *ptr_, size_t len_, size_t offset)
{
- assert(len_ == 0 || inBounds(ptr + offset));
- assert(len_ == 0 || inBounds(ptr + offset + len_ - 1));
- memcpy(ptr + offset, ptr_, len_);
+ assert(len_ == 0 || inBounds(ptr + offset));
+ assert(len_ == 0 || inBounds(ptr + offset + len_ - 1));
+ memcpy(ptr + offset, ptr_, len_);
}
// Make sure there are 'o' bytes beyond the fill pointer,
// advance the fill pointer, and return the old fill pointer.
byte *fillbytes::grow(size_t s)
{
- size_t nlen = add_size(b.len, s);
- if (nlen <= allocated)
- {
- b.len = nlen;
- return limit() - s;
- }
- size_t maxlen = nlen;
- if (maxlen < 128)
- maxlen = 128;
- if (maxlen < allocated * 2)
- maxlen = allocated * 2;
- if (allocated == 0)
- {
- // Initial buffer was not malloced. Do not reallocate it.
- bytes old = b;
- b.malloc(maxlen);
- if (b.len == maxlen)
- old.writeTo(b.ptr);
- }
- else
- {
- b.realloc(maxlen);
- }
- allocated = b.len;
- if (allocated != maxlen)
- {
- b.len = nlen - s; // back up
- return dummy; // scribble during error recov.
- }
- // after realloc, recompute pointers
- b.len = nlen;
- assert(b.len <= allocated);
- return limit() - s;
+ size_t nlen = add_size(b.len, s);
+ if (nlen <= allocated)
+ {
+ b.len = nlen;
+ return limit() - s;
+ }
+ size_t maxlen = nlen;
+ if (maxlen < 128)
+ maxlen = 128;
+ if (maxlen < allocated * 2)
+ maxlen = allocated * 2;
+ if (allocated == 0)
+ {
+ // Initial buffer was not malloced. Do not reallocate it.
+ bytes old = b;
+ b.malloc(maxlen);
+ if (b.len == maxlen)
+ old.writeTo(b.ptr);
+ }
+ else
+ {
+ b.realloc(maxlen);
+ }
+ allocated = b.len;
+ if (allocated != maxlen)
+ {
+ b.len = nlen - s; // back up
+ return dummy; // scribble during error recov.
+ }
+ // after realloc, recompute pointers
+ b.len = nlen;
+ assert(b.len <= allocated);
+ return limit() - s;
}
void fillbytes::ensureSize(size_t s)
{
- if (allocated >= s)
- return;
- size_t len0 = b.len;
- grow(s - size());
- b.len = len0; // put it back
+ if (allocated >= s)
+ return;
+ size_t len0 = b.len;
+ grow(s - size());
+ b.len = len0; // put it back
}
int ptrlist::indexOf(const void *x)
{
- int len = length();
- for (int i = 0; i < len; i++)
- {
- if (get(i) == x)
- return i;
- }
- return -1;
+ int len = length();
+ for (int i = 0; i < len; i++)
+ {
+ if (get(i) == x)
+ return i;
+ }
+ return -1;
}
void ptrlist::freeAll()
{
- int len = length();
- for (int i = 0; i < len; i++)
- {
- void *p = (void *)get(i);
- if (p != nullptr)
- {
- ::free(p);
- }
- }
- free();
+ int len = length();
+ for (int i = 0; i < len; i++)
+ {
+ void *p = (void *)get(i);
+ if (p != nullptr)
+ {
+ ::free(p);
+ }
+ }
+ free();
}
int intlist::indexOf(int x)
{
- int len = length();
- for (int i = 0; i < len; i++)
- {
- if (get(i) == x)
- return i;
- }
- return -1;
+ int len = length();
+ for (int i = 0; i < len; i++)
+ {
+ if (get(i) == x)
+ return i;
+ }
+ return -1;
}
diff --git a/libraries/pack200/src/bytes.h b/libraries/pack200/src/bytes.h
index b116efda..2ce1f7f4 100644
--- a/libraries/pack200/src/bytes.h
+++ b/libraries/pack200/src/bytes.h
@@ -27,225 +27,225 @@
struct bytes
{
- int8_t *ptr;
- size_t len;
- int8_t *limit()
- {
- return ptr + len;
- }
+ int8_t *ptr;
+ size_t len;
+ int8_t *limit()
+ {
+ return ptr + len;
+ }
- void set(int8_t *ptr_, size_t len_)
- {
- ptr = ptr_;
- len = len_;
- }
- void set(const char *str)
- {
- ptr = (int8_t *)str;
- len = strlen(str);
- }
- bool inBounds(const void *p); // p in [ptr, limit)
- void malloc(size_t len_);
- void realloc(size_t len_);
- void free();
- void copyFrom(const void *ptr_, size_t len_, size_t offset = 0);
- void saveFrom(const void *ptr_, size_t len_);
- void saveFrom(const char *str)
- {
- saveFrom(str, strlen(str));
- }
- void copyFrom(bytes &other, size_t offset = 0)
- {
- copyFrom(other.ptr, other.len, offset);
- }
- void saveFrom(bytes &other)
- {
- saveFrom(other.ptr, other.len);
- }
- void clear(int fill_byte = 0)
- {
- memset(ptr, fill_byte, len);
- }
- int8_t *writeTo(int8_t *bp);
- bool equals(bytes &other)
- {
- return 0 == compareTo(other);
- }
- int compareTo(bytes &other);
- bool contains(int8_t c)
- {
- return indexOf(c) >= 0;
- }
- int indexOf(int8_t c);
- // substrings:
- static bytes of(int8_t *ptr, size_t len)
- {
- bytes res;
- res.set(ptr, len);
- return res;
- }
- bytes slice(size_t beg, size_t end)
- {
- bytes res;
- res.ptr = ptr + beg;
- res.len = end - beg;
- assert(res.len == 0 ||(inBounds(res.ptr) && inBounds(res.limit() - 1)));
- return res;
- }
- // building C strings inside byte buffers:
- bytes &strcat(const char *str)
- {
- ::strcat((char *)ptr, str);
- return *this;
- }
- bytes &strcat(bytes &other)
- {
- ::strncat((char *)ptr, (char *)other.ptr, other.len);
- return *this;
- }
- char *strval()
- {
- assert(strlen((char *)ptr) == len);
- return (char *)ptr;
- }
+ void set(int8_t *ptr_, size_t len_)
+ {
+ ptr = ptr_;
+ len = len_;
+ }
+ void set(const char *str)
+ {
+ ptr = (int8_t *)str;
+ len = strlen(str);
+ }
+ bool inBounds(const void *p); // p in [ptr, limit)
+ void malloc(size_t len_);
+ void realloc(size_t len_);
+ void free();
+ void copyFrom(const void *ptr_, size_t len_, size_t offset = 0);
+ void saveFrom(const void *ptr_, size_t len_);
+ void saveFrom(const char *str)
+ {
+ saveFrom(str, strlen(str));
+ }
+ void copyFrom(bytes &other, size_t offset = 0)
+ {
+ copyFrom(other.ptr, other.len, offset);
+ }
+ void saveFrom(bytes &other)
+ {
+ saveFrom(other.ptr, other.len);
+ }
+ void clear(int fill_byte = 0)
+ {
+ memset(ptr, fill_byte, len);
+ }
+ int8_t *writeTo(int8_t *bp);
+ bool equals(bytes &other)
+ {
+ return 0 == compareTo(other);
+ }
+ int compareTo(bytes &other);
+ bool contains(int8_t c)
+ {
+ return indexOf(c) >= 0;
+ }
+ int indexOf(int8_t c);
+ // substrings:
+ static bytes of(int8_t *ptr, size_t len)
+ {
+ bytes res;
+ res.set(ptr, len);
+ return res;
+ }
+ bytes slice(size_t beg, size_t end)
+ {
+ bytes res;
+ res.ptr = ptr + beg;
+ res.len = end - beg;
+ assert(res.len == 0 ||(inBounds(res.ptr) && inBounds(res.limit() - 1)));
+ return res;
+ }
+ // building C strings inside byte buffers:
+ bytes &strcat(const char *str)
+ {
+ ::strcat((char *)ptr, str);
+ return *this;
+ }
+ bytes &strcat(bytes &other)
+ {
+ ::strncat((char *)ptr, (char *)other.ptr, other.len);
+ return *this;
+ }
+ char *strval()
+ {
+ assert(strlen((char *)ptr) == len);
+ return (char *)ptr;
+ }
};
#define BYTES_OF(var) (bytes::of((int8_t *)&(var), sizeof(var)))
struct fillbytes
{
- bytes b;
- size_t allocated;
+ bytes b;
+ size_t allocated;
- int8_t *base()
- {
- return b.ptr;
- }
- size_t size()
- {
- return b.len;
- }
- int8_t *limit()
- {
- return b.limit();
- } // logical limit
- void setLimit(int8_t *lp)
- {
- assert(isAllocated(lp));
- b.len = lp - b.ptr;
- }
- int8_t *end()
- {
- return b.ptr + allocated;
- } // physical limit
- int8_t *loc(size_t o)
- {
- assert(o < b.len);
- return b.ptr + o;
- }
- void init()
- {
- allocated = 0;
- b.set(nullptr, 0);
- }
- void init(size_t s)
- {
- init();
- ensureSize(s);
- }
- void free()
- {
- if (allocated != 0)
- b.free();
- allocated = 0;
- }
- void empty()
- {
- b.len = 0;
- }
- int8_t *grow(size_t s); // grow so that limit() += s
- int getByte(uint32_t i)
- {
- return *loc(i) & 0xFF;
- }
- void addByte(int8_t x)
- {
- *grow(1) = x;
- }
- void ensureSize(size_t s); // make sure allocated >= s
- void trimToSize()
- {
- if (allocated > size())
- b.realloc(allocated = size());
- }
- bool canAppend(size_t s)
- {
- return allocated > b.len + s;
- }
- bool isAllocated(int8_t *p)
- {
- return p >= base() && p <= end();
- } // asserts
- void set(bytes &src)
- {
- set(src.ptr, src.len);
- }
+ int8_t *base()
+ {
+ return b.ptr;
+ }
+ size_t size()
+ {
+ return b.len;
+ }
+ int8_t *limit()
+ {
+ return b.limit();
+ } // logical limit
+ void setLimit(int8_t *lp)
+ {
+ assert(isAllocated(lp));
+ b.len = lp - b.ptr;
+ }
+ int8_t *end()
+ {
+ return b.ptr + allocated;
+ } // physical limit
+ int8_t *loc(size_t o)
+ {
+ assert(o < b.len);
+ return b.ptr + o;
+ }
+ void init()
+ {
+ allocated = 0;
+ b.set(nullptr, 0);
+ }
+ void init(size_t s)
+ {
+ init();
+ ensureSize(s);
+ }
+ void free()
+ {
+ if (allocated != 0)
+ b.free();
+ allocated = 0;
+ }
+ void empty()
+ {
+ b.len = 0;
+ }
+ int8_t *grow(size_t s); // grow so that limit() += s
+ int getByte(uint32_t i)
+ {
+ return *loc(i) & 0xFF;
+ }
+ void addByte(int8_t x)
+ {
+ *grow(1) = x;
+ }
+ void ensureSize(size_t s); // make sure allocated >= s
+ void trimToSize()
+ {
+ if (allocated > size())
+ b.realloc(allocated = size());
+ }
+ bool canAppend(size_t s)
+ {
+ return allocated > b.len + s;
+ }
+ bool isAllocated(int8_t *p)
+ {
+ return p >= base() && p <= end();
+ } // asserts
+ void set(bytes &src)
+ {
+ set(src.ptr, src.len);
+ }
- void set(int8_t *ptr, size_t len)
- {
- b.set(ptr, len);
- allocated = 0; // mark as not reallocatable
- }
+ void set(int8_t *ptr, size_t len)
+ {
+ b.set(ptr, len);
+ allocated = 0; // mark as not reallocatable
+ }
- // block operations on resizing byte buffer:
- fillbytes &append(const void *ptr_, size_t len_)
- {
- memcpy(grow(len_), ptr_, len_);
- return (*this);
- }
- fillbytes &append(bytes &other)
- {
- return append(other.ptr, other.len);
- }
- fillbytes &append(const char *str)
- {
- return append(str, strlen(str));
- }
+ // block operations on resizing byte buffer:
+ fillbytes &append(const void *ptr_, size_t len_)
+ {
+ memcpy(grow(len_), ptr_, len_);
+ return (*this);
+ }
+ fillbytes &append(bytes &other)
+ {
+ return append(other.ptr, other.len);
+ }
+ fillbytes &append(const char *str)
+ {
+ return append(str, strlen(str));
+ }
};
struct ptrlist : fillbytes
{
- typedef const void *cvptr;
- int length()
- {
- return (int)(size() / sizeof(cvptr));
- }
- cvptr *base()
- {
- return (cvptr *)fillbytes::base();
- }
- cvptr &get(int i)
- {
- return *(cvptr *)loc(i * sizeof(cvptr));
- }
- cvptr *limit()
- {
- return (cvptr *)fillbytes::limit();
- }
- void add(cvptr x)
- {
- *(cvptr *)grow(sizeof(x)) = x;
- }
- void popTo(int l)
- {
- assert(l <= length());
- b.len = l * sizeof(cvptr);
- }
- int indexOf(cvptr x);
- bool contains(cvptr x)
- {
- return indexOf(x) >= 0;
- }
- void freeAll(); // frees every ptr on the list, plus the list itself
+ typedef const void *cvptr;
+ int length()
+ {
+ return (int)(size() / sizeof(cvptr));
+ }
+ cvptr *base()
+ {
+ return (cvptr *)fillbytes::base();
+ }
+ cvptr &get(int i)
+ {
+ return *(cvptr *)loc(i * sizeof(cvptr));
+ }
+ cvptr *limit()
+ {
+ return (cvptr *)fillbytes::limit();
+ }
+ void add(cvptr x)
+ {
+ *(cvptr *)grow(sizeof(x)) = x;
+ }
+ void popTo(int l)
+ {
+ assert(l <= length());
+ b.len = l * sizeof(cvptr);
+ }
+ int indexOf(cvptr x);
+ bool contains(cvptr x)
+ {
+ return indexOf(x) >= 0;
+ }
+ void freeAll(); // frees every ptr on the list, plus the list itself
};
// Use a macro rather than mess with subtle mismatches
// between member and non-member function pointers.
@@ -253,34 +253,34 @@ struct ptrlist : fillbytes
struct intlist : fillbytes
{
- int length()
- {
- return (int)(size() / sizeof(int));
- }
- int *base()
- {
- return (int *)fillbytes::base();
- }
- int &get(int i)
- {
- return *(int *)loc(i * sizeof(int));
- }
- int *limit()
- {
- return (int *)fillbytes::limit();
- }
- void add(int x)
- {
- *(int *)grow(sizeof(x)) = x;
- }
- void popTo(int l)
- {
- assert(l <= length());
- b.len = l * sizeof(int);
- }
- int indexOf(int x);
- bool contains(int x)
- {
- return indexOf(x) >= 0;
- }
+ int length()
+ {
+ return (int)(size() / sizeof(int));
+ }
+ int *base()
+ {
+ return (int *)fillbytes::base();
+ }
+ int &get(int i)
+ {
+ return *(int *)loc(i * sizeof(int));
+ }
+ int *limit()
+ {
+ return (int *)fillbytes::limit();
+ }
+ void add(int x)
+ {
+ *(int *)grow(sizeof(x)) = x;
+ }
+ void popTo(int l)
+ {
+ assert(l <= length());
+ b.len = l * sizeof(int);
+ }
+ int indexOf(int x);
+ bool contains(int x)
+ {
+ return indexOf(x) >= 0;
+ }
};
diff --git a/libraries/pack200/src/coding.cpp b/libraries/pack200/src/coding.cpp
index 6bd17a3c..8e872013 100644
--- a/libraries/pack200/src/coding.cpp
+++ b/libraries/pack200/src/coding.cpp
@@ -48,12 +48,12 @@ extern coding basic_codings[];
#pragma GCC diagnostic ignored "-Wunused-variable"
#define CODING_PRIVATE(spec) \
- int spec_ = spec; \
- int B = CODING_B(spec_); \
- int H = CODING_H(spec_); \
- int L = 256 - H; \
- int S = CODING_S(spec_); \
- int D = CODING_D(spec_)
+ int spec_ = spec; \
+ int B = CODING_B(spec_); \
+ int H = CODING_H(spec_); \
+ int L = 256 - H; \
+ int S = CODING_S(spec_); \
+ int D = CODING_D(spec_)
#define IS_NEG_CODE(S, codeVal) ((((int)(codeVal) + 1) & ((1 << S) - 1)) == 0)
@@ -61,568 +61,568 @@ extern coding basic_codings[];
static int decode_sign(int S, uint32_t ux)
{ // == Coding.decodeSign32
- assert(S > 0);
- uint32_t sigbits = (ux >> S);
- if (IS_NEG_CODE(S, ux))
- return (int)(~sigbits);
- else
- return (int)(ux - sigbits);
- // Note that (int)(ux-sigbits) can be negative, if ux is large enough.
+ assert(S > 0);
+ uint32_t sigbits = (ux >> S);
+ if (IS_NEG_CODE(S, ux))
+ return (int)(~sigbits);
+ else
+ return (int)(ux - sigbits);
+ // Note that (int)(ux-sigbits) can be negative, if ux is large enough.
}
coding *coding::init()
{
- if (umax > 0)
- return this; // already done
- assert(spec != 0); // sanity
-
- // fill in derived fields
- CODING_PRIVATE(spec);
-
- // Return nullptr if 'arb(BHSD)' parameter constraints are not met:
- if (B < 1 || B > B_MAX)
- return nullptr;
- if (H < 1 || H > 256)
- return nullptr;
- if (S < 0 || S > 2)
- return nullptr;
- if (D < 0 || D > 1)
- return nullptr;
- if (B == 1 && H != 256)
- return nullptr; // 1-byte coding must be fixed-size
- if (B >= 5 && H == 256)
- return nullptr; // no 5-byte fixed-size coding
-
- // first compute the range of the coding, in 64 bits
- int64_t range = 0;
- {
- int64_t H_i = 1;
- for (int i = 0; i < B; i++)
- {
- range += H_i;
- H_i *= H;
- }
- range *= L;
- range += H_i;
- }
- assert(range > 0); // no useless codings, please
-
- int this_umax;
-
- // now, compute min and max
- if (range >= ((int64_t)1 << 32))
- {
- this_umax = INT_MAX_VALUE;
- this->umin = INT_MIN_VALUE;
- this->max = INT_MAX_VALUE;
- this->min = INT_MIN_VALUE;
- }
- else
- {
- this_umax = (range > INT_MAX_VALUE) ? INT_MAX_VALUE : (int)range - 1;
- this->max = this_umax;
- this->min = this->umin = 0;
- if (S != 0 && range != 0)
- {
- int64_t maxPosCode = range - 1;
- int64_t maxNegCode = range - 1;
- while (IS_NEG_CODE(S, maxPosCode))
- --maxPosCode;
- while (!IS_NEG_CODE(S, maxNegCode))
- --maxNegCode;
- int maxPos = decode_sign(S, (uint32_t)maxPosCode);
- if (maxPos < 0)
- this->max = INT_MAX_VALUE; // 32-bit wraparound
- else
- this->max = maxPos;
- if (maxNegCode < 0)
- this->min = 0; // No negative codings at all.
- else
- this->min = decode_sign(S, (uint32_t)maxNegCode);
- }
- }
-
- assert(!(isFullRange | isSigned | isSubrange)); // init
- if (min < 0)
- this->isSigned = true;
- if (max < INT_MAX_VALUE && range <= INT_MAX_VALUE)
- this->isSubrange = true;
- if (max == INT_MAX_VALUE && min == INT_MIN_VALUE)
- this->isFullRange = true;
-
- // do this last, to reduce MT exposure (should have a membar too)
- this->umax = this_umax;
-
- return this;
+ if (umax > 0)
+ return this; // already done
+ assert(spec != 0); // sanity
+
+ // fill in derived fields
+ CODING_PRIVATE(spec);
+
+ // Return nullptr if 'arb(BHSD)' parameter constraints are not met:
+ if (B < 1 || B > B_MAX)
+ return nullptr;
+ if (H < 1 || H > 256)
+ return nullptr;
+ if (S < 0 || S > 2)
+ return nullptr;
+ if (D < 0 || D > 1)
+ return nullptr;
+ if (B == 1 && H != 256)
+ return nullptr; // 1-byte coding must be fixed-size
+ if (B >= 5 && H == 256)
+ return nullptr; // no 5-byte fixed-size coding
+
+ // first compute the range of the coding, in 64 bits
+ int64_t range = 0;
+ {
+ int64_t H_i = 1;
+ for (int i = 0; i < B; i++)
+ {
+ range += H_i;
+ H_i *= H;
+ }
+ range *= L;
+ range += H_i;
+ }
+ assert(range > 0); // no useless codings, please
+
+ int this_umax;
+
+ // now, compute min and max
+ if (range >= ((int64_t)1 << 32))
+ {
+ this_umax = INT_MAX_VALUE;
+ this->umin = INT_MIN_VALUE;
+ this->max = INT_MAX_VALUE;
+ this->min = INT_MIN_VALUE;
+ }
+ else
+ {
+ this_umax = (range > INT_MAX_VALUE) ? INT_MAX_VALUE : (int)range - 1;
+ this->max = this_umax;
+ this->min = this->umin = 0;
+ if (S != 0 && range != 0)
+ {
+ int64_t maxPosCode = range - 1;
+ int64_t maxNegCode = range - 1;
+ while (IS_NEG_CODE(S, maxPosCode))
+ --maxPosCode;
+ while (!IS_NEG_CODE(S, maxNegCode))
+ --maxNegCode;
+ int maxPos = decode_sign(S, (uint32_t)maxPosCode);
+ if (maxPos < 0)
+ this->max = INT_MAX_VALUE; // 32-bit wraparound
+ else
+ this->max = maxPos;
+ if (maxNegCode < 0)
+ this->min = 0; // No negative codings at all.
+ else
+ this->min = decode_sign(S, (uint32_t)maxNegCode);
+ }
+ }
+
+ assert(!(isFullRange | isSigned | isSubrange)); // init
+ if (min < 0)
+ this->isSigned = true;
+ if (max < INT_MAX_VALUE && range <= INT_MAX_VALUE)
+ this->isSubrange = true;
+ if (max == INT_MAX_VALUE && min == INT_MIN_VALUE)
+ this->isFullRange = true;
+
+ // do this last, to reduce MT exposure (should have a membar too)
+ this->umax = this_umax;
+
+ return this;
}
coding *coding::findBySpec(int spec)
{
- for (coding *scan = &basic_codings[0];; scan++)
- {
- if (scan->spec == spec)
- return scan->init();
- if (scan->spec == 0)
- break;
- }
- coding *ptr = NEW(coding, 1);
- if (!ptr)
- return nullptr;
- coding *c = ptr->initFrom(spec);
- if (c == nullptr)
- {
- ::free(ptr);
- }
- else
- // else caller should free it...
- c->isMalloc = true;
- return c;
+ for (coding *scan = &basic_codings[0];; scan++)
+ {
+ if (scan->spec == spec)
+ return scan->init();
+ if (scan->spec == 0)
+ break;
+ }
+ coding *ptr = NEW(coding, 1);
+ if (!ptr)
+ return nullptr;
+ coding *c = ptr->initFrom(spec);
+ if (c == nullptr)
+ {
+ ::free(ptr);
+ }
+ else
+ // else caller should free it...
+ c->isMalloc = true;
+ return c;
}
coding *coding::findBySpec(int B, int H, int S, int D)
{
- if (B < 1 || B > B_MAX)
- return nullptr;
- if (H < 1 || H > 256)
- return nullptr;
- if (S < 0 || S > 2)
- return nullptr;
- if (D < 0 || D > 1)
- return nullptr;
- return findBySpec(CODING_SPEC(B, H, S, D));
+ if (B < 1 || B > B_MAX)
+ return nullptr;
+ if (H < 1 || H > 256)
+ return nullptr;
+ if (S < 0 || S > 2)
+ return nullptr;
+ if (D < 0 || D > 1)
+ return nullptr;
+ return findBySpec(CODING_SPEC(B, H, S, D));
}
void coding::free()
{
- if (isMalloc)
- {
- ::free(this);
- }
+ if (isMalloc)
+ {
+ ::free(this);
+ }
}
void coding_method::reset(value_stream *state)
{
- assert(state->rp == state->rplimit); // not in mid-stream, please
- // assert(this == vs0.cm);
- state[0] = vs0;
- if (uValues != nullptr)
- {
- uValues->reset(state->helper());
- }
+ assert(state->rp == state->rplimit); // not in mid-stream, please
+ // assert(this == vs0.cm);
+ state[0] = vs0;
+ if (uValues != nullptr)
+ {
+ uValues->reset(state->helper());
+ }
}
uint32_t coding::parse(byte *&rp, int B, int H)
{
- int L = 256 - H;
- byte *ptr = rp;
- // hand peel the i==0 part of the loop:
- uint32_t b_i = *ptr++ & 0xFF;
- if (B == 1 || b_i < (uint32_t)L)
- {
- rp = ptr;
- return b_i;
- }
- uint32_t sum = b_i;
- uint32_t H_i = H;
- assert(B <= B_MAX);
- for (int i = 2; i <= B_MAX; i++)
- { // easy for compilers to unroll if desired
- b_i = *ptr++ & 0xFF;
- sum += b_i * H_i;
- if (i == B || b_i < (uint32_t)L)
- {
- rp = ptr;
- return sum;
- }
- H_i *= H;
- }
- assert(false);
- return 0;
+ int L = 256 - H;
+ byte *ptr = rp;
+ // hand peel the i==0 part of the loop:
+ uint32_t b_i = *ptr++ & 0xFF;
+ if (B == 1 || b_i < (uint32_t)L)
+ {
+ rp = ptr;
+ return b_i;
+ }
+ uint32_t sum = b_i;
+ uint32_t H_i = H;
+ assert(B <= B_MAX);
+ for (int i = 2; i <= B_MAX; i++)
+ { // easy for compilers to unroll if desired
+ b_i = *ptr++ & 0xFF;
+ sum += b_i * H_i;
+ if (i == B || b_i < (uint32_t)L)
+ {
+ rp = ptr;
+ return sum;
+ }
+ H_i *= H;
+ }
+ assert(false);
+ return 0;
}
uint32_t coding::parse_lgH(byte *&rp, int B, int H, int lgH)
{
- assert(H == (1 << lgH));
- int L = 256 - (1 << lgH);
- byte *ptr = rp;
- // hand peel the i==0 part of the loop:
- uint32_t b_i = *ptr++ & 0xFF;
- if (B == 1 || b_i < (uint32_t)L)
- {
- rp = ptr;
- return b_i;
- }
- uint32_t sum = b_i;
- uint32_t lg_H_i = lgH;
- assert(B <= B_MAX);
- for (int i = 2; i <= B_MAX; i++)
- { // easy for compilers to unroll if desired
- b_i = *ptr++ & 0xFF;
- sum += b_i << lg_H_i;
- if (i == B || b_i < (uint32_t)L)
- {
- rp = ptr;
- return sum;
- }
- lg_H_i += lgH;
- }
- assert(false);
- return 0;
+ assert(H == (1 << lgH));
+ int L = 256 - (1 << lgH);
+ byte *ptr = rp;
+ // hand peel the i==0 part of the loop:
+ uint32_t b_i = *ptr++ & 0xFF;
+ if (B == 1 || b_i < (uint32_t)L)
+ {
+ rp = ptr;
+ return b_i;
+ }
+ uint32_t sum = b_i;
+ uint32_t lg_H_i = lgH;
+ assert(B <= B_MAX);
+ for (int i = 2; i <= B_MAX; i++)
+ { // easy for compilers to unroll if desired
+ b_i = *ptr++ & 0xFF;
+ sum += b_i << lg_H_i;
+ if (i == B || b_i < (uint32_t)L)
+ {
+ rp = ptr;
+ return sum;
+ }
+ lg_H_i += lgH;
+ }
+ assert(false);
+ return 0;
}
static const char ERB[] = "EOF reading band";
void coding::parseMultiple(byte *&rp, int N, byte *limit, int B, int H)
{
- if (N < 0)
- {
- unpack_abort("bad value count");
- return;
- }
- byte *ptr = rp;
- if (B == 1 || H == 256)
- {
- size_t len = (size_t)N * B;
- if (len / B != (size_t)N || ptr + len > limit)
- {
- unpack_abort(ERB);
- return;
- }
- rp = ptr + len;
- return;
- }
- // Note: We assume rp has enough zero-padding.
- int L = 256 - H;
- int n = B;
- while (N > 0)
- {
- ptr += 1;
- if (--n == 0)
- {
- // end of encoding at B bytes, regardless of byte value
- }
- else
- {
- int b = (ptr[-1] & 0xFF);
- if (b >= L)
- {
- // keep going, unless we find a byte < L
- continue;
- }
- }
- // found the last byte
- N -= 1;
- n = B; // reset length counter
- // do an error check here
- if (ptr > limit)
- {
- unpack_abort(ERB);
- return;
- }
- }
- rp = ptr;
- return;
+ if (N < 0)
+ {
+ unpack_abort("bad value count");
+ return;
+ }
+ byte *ptr = rp;
+ if (B == 1 || H == 256)
+ {
+ size_t len = (size_t)N * B;
+ if (len / B != (size_t)N || ptr + len > limit)
+ {
+ unpack_abort(ERB);
+ return;
+ }
+ rp = ptr + len;
+ return;
+ }
+ // Note: We assume rp has enough zero-padding.
+ int L = 256 - H;
+ int n = B;
+ while (N > 0)
+ {
+ ptr += 1;
+ if (--n == 0)
+ {
+ // end of encoding at B bytes, regardless of byte value
+ }
+ else
+ {
+ int b = (ptr[-1] & 0xFF);
+ if (b >= L)
+ {
+ // keep going, unless we find a byte < L
+ continue;
+ }
+ }
+ // found the last byte
+ N -= 1;
+ n = B; // reset length counter
+ // do an error check here
+ if (ptr > limit)
+ {
+ unpack_abort(ERB);
+ return;
+ }
+ }
+ rp = ptr;
+ return;
}
bool value_stream::hasHelper()
{
- // If my coding method is a pop-style method,
- // then I need a second value stream to transmit
- // unfavored values.
- // This can be determined by examining fValues.
- return cm->fValues != nullptr;
+ // If my coding method is a pop-style method,
+ // then I need a second value stream to transmit
+ // unfavored values.
+ // This can be determined by examining fValues.
+ return cm->fValues != nullptr;
}
void value_stream::init(byte *rp_, byte *rplimit_, coding *defc)
{
- rp = rp_;
- rplimit = rplimit_;
- sum = 0;
- cm = nullptr; // no need in the simple case
- setCoding(defc);
+ rp = rp_;
+ rplimit = rplimit_;
+ sum = 0;
+ cm = nullptr; // no need in the simple case
+ setCoding(defc);
}
void value_stream::setCoding(coding *defc)
{
- if (defc == nullptr)
- {
- unpack_abort("bad coding");
- defc = coding::findByIndex(_meta_canon_min); // random pick for recovery
- }
-
- c = (*defc);
-
- // choose cmk
- cmk = cmk_ERROR;
- switch (c.spec)
- {
- case BYTE1_spec:
- cmk = cmk_BYTE1;
- break;
- case CHAR3_spec:
- cmk = cmk_CHAR3;
- break;
- case UNSIGNED5_spec:
- cmk = cmk_UNSIGNED5;
- break;
- case DELTA5_spec:
- cmk = cmk_DELTA5;
- break;
- case BCI5_spec:
- cmk = cmk_BCI5;
- break;
- case BRANCH5_spec:
- cmk = cmk_BRANCH5;
- break;
- default:
- if (c.D() == 0)
- {
- switch (c.S())
- {
- case 0:
- cmk = cmk_BHS0;
- break;
- case 1:
- cmk = cmk_BHS1;
- break;
- default:
- cmk = cmk_BHS;
- break;
- }
- }
- else
- {
- if (c.S() == 1)
- {
- if (c.isFullRange)
- cmk = cmk_BHS1D1full;
- if (c.isSubrange)
- cmk = cmk_BHS1D1sub;
- }
- if (cmk == cmk_ERROR)
- cmk = cmk_BHSD1;
- }
- }
+ if (defc == nullptr)
+ {
+ unpack_abort("bad coding");
+ defc = coding::findByIndex(_meta_canon_min); // random pick for recovery
+ }
+
+ c = (*defc);
+
+ // choose cmk
+ cmk = cmk_ERROR;
+ switch (c.spec)
+ {
+ case BYTE1_spec:
+ cmk = cmk_BYTE1;
+ break;
+ case CHAR3_spec:
+ cmk = cmk_CHAR3;
+ break;
+ case UNSIGNED5_spec:
+ cmk = cmk_UNSIGNED5;
+ break;
+ case DELTA5_spec:
+ cmk = cmk_DELTA5;
+ break;
+ case BCI5_spec:
+ cmk = cmk_BCI5;
+ break;
+ case BRANCH5_spec:
+ cmk = cmk_BRANCH5;
+ break;
+ default:
+ if (c.D() == 0)
+ {
+ switch (c.S())
+ {
+ case 0:
+ cmk = cmk_BHS0;
+ break;
+ case 1:
+ cmk = cmk_BHS1;
+ break;
+ default:
+ cmk = cmk_BHS;
+ break;
+ }
+ }
+ else
+ {
+ if (c.S() == 1)
+ {
+ if (c.isFullRange)
+ cmk = cmk_BHS1D1full;
+ if (c.isSubrange)
+ cmk = cmk_BHS1D1sub;
+ }
+ if (cmk == cmk_ERROR)
+ cmk = cmk_BHSD1;
+ }
+ }
}
static int getPopValue(value_stream *self, uint32_t uval)
{
- if (uval > 0)
- {
- // note that the initial parse performed a range check
- assert(uval <= (uint32_t)self->cm->fVlength);
- return self->cm->fValues[uval - 1];
- }
- else
- {
- // take an unfavored value
- return self->helper()->getInt();
- }
+ if (uval > 0)
+ {
+ // note that the initial parse performed a range check
+ assert(uval <= (uint32_t)self->cm->fVlength);
+ return self->cm->fValues[uval - 1];
+ }
+ else
+ {
+ // take an unfavored value
+ return self->helper()->getInt();
+ }
}
int coding::sumInUnsignedRange(int x, int y)
{
- assert(isSubrange);
- int range = (int)(umax + 1);
- assert(range > 0);
- x += y;
- if (x != (int)((int64_t)(x - y) + (int64_t)y))
- {
- // 32-bit overflow interferes with range reduction.
- // Back off from the overflow by adding a multiple of range:
- if (x < 0)
- {
- x -= range;
- assert(x >= 0);
- }
- else
- {
- x += range;
- assert(x < 0);
- }
- }
- if (x < 0)
- {
- x += range;
- if (x >= 0)
- return x;
- }
- else if (x >= range)
- {
- x -= range;
- if (x < range)
- return x;
- }
- else
- {
- // in range
- return x;
- }
- // do it the hard way
- x %= range;
- if (x < 0)
- x += range;
- return x;
+ assert(isSubrange);
+ int range = (int)(umax + 1);
+ assert(range > 0);
+ x += y;
+ if (x != (int)((int64_t)(x - y) + (int64_t)y))
+ {
+ // 32-bit overflow interferes with range reduction.
+ // Back off from the overflow by adding a multiple of range:
+ if (x < 0)
+ {
+ x -= range;
+ assert(x >= 0);
+ }
+ else
+ {
+ x += range;
+ assert(x < 0);
+ }
+ }
+ if (x < 0)
+ {
+ x += range;
+ if (x >= 0)
+ return x;
+ }
+ else if (x >= range)
+ {
+ x -= range;
+ if (x < range)
+ return x;
+ }
+ else
+ {
+ // in range
+ return x;
+ }
+ // do it the hard way
+ x %= range;
+ if (x < 0)
+ x += range;
+ return x;
}
static int getDeltaValue(value_stream *self, uint32_t uval, bool isSubrange)
{
- assert((uint32_t)(self->c.isSubrange) == (uint32_t)isSubrange);
- assert(self->c.isSubrange | self->c.isFullRange);
- if (isSubrange)
- return self->sum = self->c.sumInUnsignedRange(self->sum, (int)uval);
- else
- return self->sum += (int)uval;
+ assert((uint32_t)(self->c.isSubrange) == (uint32_t)isSubrange);
+ assert(self->c.isSubrange | self->c.isFullRange);
+ if (isSubrange)
+ return self->sum = self->c.sumInUnsignedRange(self->sum, (int)uval);
+ else
+ return self->sum += (int)uval;
}
bool value_stream::hasValue()
{
- if (rp < rplimit)
- return true;
- if (cm == nullptr)
- return false;
- if (cm->next == nullptr)
- return false;
- cm->next->reset(this);
- return hasValue();
+ if (rp < rplimit)
+ return true;
+ if (cm == nullptr)
+ return false;
+ if (cm->next == nullptr)
+ return false;
+ cm->next->reset(this);
+ return hasValue();
}
int value_stream::getInt()
{
- if (rp >= rplimit)
- {
- // Advance to next coding segment.
- if (rp > rplimit || cm == nullptr || cm->next == nullptr)
- {
- // Must perform this check and throw an exception on bad input.
- unpack_abort(ERB);
- return 0;
- }
- cm->next->reset(this);
- return getInt();
- }
-
- CODING_PRIVATE(c.spec);
- uint32_t uval;
- enum
- {
- B5 = 5,
- B3 = 3,
- H128 = 128,
- H64 = 64,
- H4 = 4
- };
- switch (cmk)
- {
- case cmk_BHS:
- assert(D == 0);
- uval = coding::parse(rp, B, H);
- if (S == 0)
- return (int)uval;
- return decode_sign(S, uval);
-
- case cmk_BHS0:
- assert(S == 0 && D == 0);
- uval = coding::parse(rp, B, H);
- return (int)uval;
-
- case cmk_BHS1:
- assert(S == 1 && D == 0);
- uval = coding::parse(rp, B, H);
- return DECODE_SIGN_S1(uval);
-
- case cmk_BYTE1:
- assert(c.spec == BYTE1_spec);
- assert(B == 1 && H == 256 && S == 0 && D == 0);
- return *rp++ & 0xFF;
-
- case cmk_CHAR3:
- assert(c.spec == CHAR3_spec);
- assert(B == B3 && H == H128 && S == 0 && D == 0);
- return coding::parse_lgH(rp, B3, H128, 7);
-
- case cmk_UNSIGNED5:
- assert(c.spec == UNSIGNED5_spec);
- assert(B == B5 && H == H64 && S == 0 && D == 0);
- return coding::parse_lgH(rp, B5, H64, 6);
-
- case cmk_BHSD1:
- assert(D == 1);
- uval = coding::parse(rp, B, H);
- if (S != 0)
- uval = (uint32_t)decode_sign(S, uval);
- return getDeltaValue(this, uval, (bool)c.isSubrange);
-
- case cmk_BHS1D1full:
- assert(S == 1 && D == 1 && c.isFullRange);
- uval = coding::parse(rp, B, H);
- uval = (uint32_t)DECODE_SIGN_S1(uval);
- return getDeltaValue(this, uval, false);
-
- case cmk_BHS1D1sub:
- assert(S == 1 && D == 1 && c.isSubrange);
- uval = coding::parse(rp, B, H);
- uval = (uint32_t)DECODE_SIGN_S1(uval);
- return getDeltaValue(this, uval, true);
-
- case cmk_DELTA5:
- assert(c.spec == DELTA5_spec);
- assert(B == B5 && H == H64 && S == 1 && D == 1 && c.isFullRange);
- uval = coding::parse_lgH(rp, B5, H64, 6);
- sum += DECODE_SIGN_S1(uval);
- return sum;
-
- case cmk_BCI5:
- assert(c.spec == BCI5_spec);
- assert(B == B5 && H == H4 && S == 0 && D == 0);
- return coding::parse_lgH(rp, B5, H4, 2);
-
- case cmk_BRANCH5:
- assert(c.spec == BRANCH5_spec);
- assert(B == B5 && H == H4 && S == 2 && D == 0);
- uval = coding::parse_lgH(rp, B5, H4, 2);
- return decode_sign(S, uval);
-
- case cmk_pop:
- uval = coding::parse(rp, B, H);
- if (S != 0)
- {
- uval = (uint32_t)decode_sign(S, uval);
- }
- if (D != 0)
- {
- assert(c.isSubrange | c.isFullRange);
- if (c.isSubrange)
- sum = c.sumInUnsignedRange(sum, (int)uval);
- else
- sum += (int)uval;
- uval = (uint32_t)sum;
- }
- return getPopValue(this, uval);
-
- case cmk_pop_BHS0:
- assert(S == 0 && D == 0);
- uval = coding::parse(rp, B, H);
- return getPopValue(this, uval);
-
- case cmk_pop_BYTE1:
- assert(c.spec == BYTE1_spec);
- assert(B == 1 && H == 256 && S == 0 && D == 0);
- return getPopValue(this, *rp++ & 0xFF);
-
- default:
- break;
- }
- assert(false);
- return 0;
+ if (rp >= rplimit)
+ {
+ // Advance to next coding segment.
+ if (rp > rplimit || cm == nullptr || cm->next == nullptr)
+ {
+ // Must perform this check and throw an exception on bad input.
+ unpack_abort(ERB);
+ return 0;
+ }
+ cm->next->reset(this);
+ return getInt();
+ }
+
+ CODING_PRIVATE(c.spec);
+ uint32_t uval;
+ enum
+ {
+ B5 = 5,
+ B3 = 3,
+ H128 = 128,
+ H64 = 64,
+ H4 = 4
+ };
+ switch (cmk)
+ {
+ case cmk_BHS:
+ assert(D == 0);
+ uval = coding::parse(rp, B, H);
+ if (S == 0)
+ return (int)uval;
+ return decode_sign(S, uval);
+
+ case cmk_BHS0:
+ assert(S == 0 && D == 0);
+ uval = coding::parse(rp, B, H);
+ return (int)uval;
+
+ case cmk_BHS1:
+ assert(S == 1 && D == 0);
+ uval = coding::parse(rp, B, H);
+ return DECODE_SIGN_S1(uval);
+
+ case cmk_BYTE1:
+ assert(c.spec == BYTE1_spec);
+ assert(B == 1 && H == 256 && S == 0 && D == 0);
+ return *rp++ & 0xFF;
+
+ case cmk_CHAR3:
+ assert(c.spec == CHAR3_spec);
+ assert(B == B3 && H == H128 && S == 0 && D == 0);
+ return coding::parse_lgH(rp, B3, H128, 7);
+
+ case cmk_UNSIGNED5:
+ assert(c.spec == UNSIGNED5_spec);
+ assert(B == B5 && H == H64 && S == 0 && D == 0);
+ return coding::parse_lgH(rp, B5, H64, 6);
+
+ case cmk_BHSD1:
+ assert(D == 1);
+ uval = coding::parse(rp, B, H);
+ if (S != 0)
+ uval = (uint32_t)decode_sign(S, uval);
+ return getDeltaValue(this, uval, (bool)c.isSubrange);
+
+ case cmk_BHS1D1full:
+ assert(S == 1 && D == 1 && c.isFullRange);
+ uval = coding::parse(rp, B, H);
+ uval = (uint32_t)DECODE_SIGN_S1(uval);
+ return getDeltaValue(this, uval, false);
+
+ case cmk_BHS1D1sub:
+ assert(S == 1 && D == 1 && c.isSubrange);
+ uval = coding::parse(rp, B, H);
+ uval = (uint32_t)DECODE_SIGN_S1(uval);
+ return getDeltaValue(this, uval, true);
+
+ case cmk_DELTA5:
+ assert(c.spec == DELTA5_spec);
+ assert(B == B5 && H == H64 && S == 1 && D == 1 && c.isFullRange);
+ uval = coding::parse_lgH(rp, B5, H64, 6);
+ sum += DECODE_SIGN_S1(uval);
+ return sum;
+
+ case cmk_BCI5:
+ assert(c.spec == BCI5_spec);
+ assert(B == B5 && H == H4 && S == 0 && D == 0);
+ return coding::parse_lgH(rp, B5, H4, 2);
+
+ case cmk_BRANCH5:
+ assert(c.spec == BRANCH5_spec);
+ assert(B == B5 && H == H4 && S == 2 && D == 0);
+ uval = coding::parse_lgH(rp, B5, H4, 2);
+ return decode_sign(S, uval);
+
+ case cmk_pop:
+ uval = coding::parse(rp, B, H);
+ if (S != 0)
+ {
+ uval = (uint32_t)decode_sign(S, uval);
+ }
+ if (D != 0)
+ {
+ assert(c.isSubrange | c.isFullRange);
+ if (c.isSubrange)
+ sum = c.sumInUnsignedRange(sum, (int)uval);
+ else
+ sum += (int)uval;
+ uval = (uint32_t)sum;
+ }
+ return getPopValue(this, uval);
+
+ case cmk_pop_BHS0:
+ assert(S == 0 && D == 0);
+ uval = coding::parse(rp, B, H);
+ return getPopValue(this, uval);
+
+ case cmk_pop_BYTE1:
+ assert(c.spec == BYTE1_spec);
+ assert(B == 1 && H == 256 && S == 0 && D == 0);
+ return getPopValue(this, *rp++ & 0xFF);
+
+ default:
+ break;
+ }
+ assert(false);
+ return 0;
}
static int moreCentral(int x, int y)
{ // used to find end of Pop.{F}
- // Suggested implementation from the Pack200 specification:
- uint32_t kx = (x >> 31) ^ (x << 1);
- uint32_t ky = (y >> 31) ^ (y << 1);
- return (kx < ky ? x : y);
+ // Suggested implementation from the Pack200 specification:
+ uint32_t kx = (x >> 31) ^ (x << 1);
+ uint32_t ky = (y >> 31) ^ (y << 1);
+ return (kx < ky ? x : y);
}
// static maybe_inline
// int moreCentral2(int x, int y, int min) {
@@ -641,7 +641,7 @@ static const byte *no_meta[] = {nullptr};
#define NO_META (*(byte **)no_meta)
enum
{
- POP_FAVORED_N = -2
+ POP_FAVORED_N = -2
};
// mode bits
@@ -650,395 +650,395 @@ enum
// This function knows all about meta-coding.
void coding_method::init(byte *&band_rp, byte *band_limit, byte *&meta_rp, int mode,
- coding *defc, int N, intlist *valueSink)
+ coding *defc, int N, intlist *valueSink)
{
- assert(N != 0);
-
- assert(u != nullptr); // must be pre-initialized
- // if (u == nullptr) u = unpacker::current(); // expensive
-
- int op = (meta_rp == nullptr) ? _meta_default : (*meta_rp++ & 0xFF);
- coding *foundc = nullptr;
- coding *to_free = nullptr;
-
- if (op == _meta_default)
- {
- foundc = defc;
- // and fall through
- }
- else if (op >= _meta_canon_min && op <= _meta_canon_max)
- {
- foundc = coding::findByIndex(op);
- // and fall through
- }
- else if (op == _meta_arb)
- {
- int args = (*meta_rp++ & 0xFF);
- // args = (D:[0..1] + 2*S[0..2] + 8*(B:[1..5]-1))
- int D = ((args >> 0) & 1);
- int S = ((args >> 1) & 3);
- int B = ((args >> 3) & -1) + 1;
- // & (H[1..256]-1)
- int H = (*meta_rp++ & 0xFF) + 1;
- foundc = coding::findBySpec(B, H, S, D);
- to_free = foundc; // findBySpec may dynamically allocate
- if (foundc == nullptr)
- {
- unpack_abort("illegal arbitrary coding");
- return;
- }
- // and fall through
- }
- else if (op >= _meta_run && op < _meta_pop)
- {
- int args = (op - _meta_run);
- // args: KX:[0..3] + 4*(KBFlag:[0..1]) + 8*(ABDef:[0..2])
- int KX = ((args >> 0) & 3);
- int KBFlag = ((args >> 2) & 1);
- int ABDef = ((args >> 3) & -1);
- assert(ABDef <= 2);
- // & KB: one of [0..255] if KBFlag=1
- int KB = (!KBFlag ? 3 : (*meta_rp++ & 0xFF));
- int K = (KB + 1) << (KX * 4);
- int N2 = (N >= 0) ? N - K : N;
- if (N == 0 || (N2 <= 0 && N2 != N))
- {
- unpack_abort("illegal run encoding");
- }
- if ((mode & DISABLE_RUN) != 0)
- {
- unpack_abort("illegal nested run encoding");
- }
-
- // & Enc{ ACode } if ADef=0 (ABDef != 1)
- // No direct nesting of 'run' in ACode, but in BCode it's OK.
- int disRun = mode | DISABLE_RUN;
- if (ABDef == 1)
- {
- this->init(band_rp, band_limit, NO_META, disRun, defc, K, valueSink);
- }
- else
- {
- this->init(band_rp, band_limit, meta_rp, disRun, defc, K, valueSink);
- }
-
- // & Enc{ BCode } if BDef=0 (ABDef != 2)
- coding_method *tail = U_NEW(coding_method, 1);
- if (!tail)
- return;
- tail->u = u;
-
- // The 'run' codings may be nested indirectly via 'pop' codings.
- // This means that this->next may already be filled in, if
- // ACode was of type 'pop' with a 'run' token coding.
- // No problem: Just chain the upcoming BCode onto the end.
- for (coding_method *self = this;; self = self->next)
- {
- if (self->next == nullptr)
- {
- self->next = tail;
- break;
- }
- }
-
- if (ABDef == 2)
- {
- tail->init(band_rp, band_limit, NO_META, mode, defc, N2, valueSink);
- }
- else
- {
- tail->init(band_rp, band_limit, meta_rp, mode, defc, N2, valueSink);
- }
- // Note: The preceding calls to init should be tail-recursive.
-
- return; // done; no falling through
- }
- else if (op >= _meta_pop && op < _meta_limit)
- {
- int args = (op - _meta_pop);
- // args: (FDef:[0..1]) + 2*UDef:[0..1] + 4*(TDefL:[0..11])
- int FDef = ((args >> 0) & 1);
- int UDef = ((args >> 1) & 1);
- int TDefL = ((args >> 2) & -1);
- assert(TDefL <= 11);
- int TDef = (TDefL > 0);
- int TL = (TDefL <= 6) ? (2 << TDefL) : (256 - (4 << (11 - TDefL)));
- int TH = (256 - TL);
- if (N <= 0)
- {
- unpack_abort("illegal pop encoding");
- }
- if ((mode & DISABLE_POP) != 0)
- {
- unpack_abort("illegal nested pop encoding");
- }
-
- // No indirect nesting of 'pop', but 'run' is OK.
- int disPop = DISABLE_POP;
-
- // & Enc{ FCode } if FDef=0
- int FN = POP_FAVORED_N;
- assert(valueSink == nullptr);
- intlist fValueSink;
- fValueSink.init();
- coding_method fval;
- BYTES_OF(fval).clear();
- fval.u = u;
- if (FDef != 0)
- {
- fval.init(band_rp, band_limit, NO_META, disPop, defc, FN, &fValueSink);
- }
- else
- {
- fval.init(band_rp, band_limit, meta_rp, disPop, defc, FN, &fValueSink);
- }
- bytes fvbuf;
- fValues = (u->saveTo(fvbuf, fValueSink.b), (int *)fvbuf.ptr);
- fVlength = fValueSink.length(); // i.e., the parameter K
- fValueSink.free();
-
- // Skip the first {F} run in all subsequent passes.
- // The next call to this->init(...) will set vs0.rp to point after the {F}.
-
- // & Enc{ TCode } if TDef=0 (TDefL==0)
- if (TDef != 0)
- {
- coding *tcode = coding::findBySpec(1, 256); // BYTE1
- // find the most narrowly sufficient code:
- for (int B = 2; B <= B_MAX; B++)
- {
- if (fVlength <= tcode->umax)
- break; // found it
- tcode->free();
- tcode = coding::findBySpec(B, TH);
- if (!tcode)
- return;
- }
- if (!(fVlength <= tcode->umax))
- {
- unpack_abort("pop.L value too small");
- }
- this->init(band_rp, band_limit, NO_META, disPop, tcode, N, nullptr);
- tcode->free();
- }
- else
- {
- this->init(band_rp, band_limit, meta_rp, disPop, defc, N, nullptr);
- }
-
- // Count the number of zero tokens right now.
- // Also verify that they are in bounds.
- int UN = 0; // one {U} for each zero in {T}
- value_stream vs = vs0;
- for (int i = 0; i < N; i++)
- {
- uint32_t val = vs.getInt();
- if (val == 0)
- UN += 1;
- if (!(val <= (uint32_t)fVlength))
- {
- unpack_abort("pop token out of range");
- }
- }
- vs.done();
-
- // & Enc{ UCode } if UDef=0
- if (UN != 0)
- {
- uValues = U_NEW(coding_method, 1);
- if (uValues == nullptr)
- return;
- uValues->u = u;
- if (UDef != 0)
- {
- uValues->init(band_rp, band_limit, NO_META, disPop, defc, UN, nullptr);
- }
- else
- {
- uValues->init(band_rp, band_limit, meta_rp, disPop, defc, UN, nullptr);
- }
- }
- else
- {
- if (UDef == 0)
- {
- int uop = (*meta_rp++ & 0xFF);
- if (uop > _meta_canon_max)
- // %%% Spec. requires the more strict (uop != _meta_default).
- unpack_abort("bad meta-coding for empty pop/U");
- }
- }
-
- // Bug fix for 6259542
- // Last of all, adjust vs0.cmk to the 'pop' flavor
- for (coding_method *self = this; self != nullptr; self = self->next)
- {
- coding_method_kind cmk2 = cmk_pop;
- switch (self->vs0.cmk)
- {
- case cmk_BHS0:
- cmk2 = cmk_pop_BHS0;
- break;
- case cmk_BYTE1:
- cmk2 = cmk_pop_BYTE1;
- break;
- default:
- break;
- }
- self->vs0.cmk = cmk2;
- if (self != this)
- {
- assert(self->fValues == nullptr); // no double init
- self->fValues = this->fValues;
- self->fVlength = this->fVlength;
- assert(self->uValues == nullptr); // must stay nullptr
- }
- }
-
- return; // done; no falling through
- }
- else
- {
- unpack_abort("bad meta-coding");
- }
-
- // Common code here skips a series of values with one coding.
- assert(foundc != nullptr);
-
- assert(vs0.cmk == cmk_ERROR); // no garbage, please
- assert(vs0.rp == nullptr); // no garbage, please
- assert(vs0.rplimit == nullptr); // no garbage, please
- assert(vs0.sum == 0); // no garbage, please
-
- vs0.init(band_rp, band_limit, foundc);
-
- // Done with foundc. Free if necessary.
- if (to_free != nullptr)
- {
- to_free->free();
- to_free = nullptr;
- }
- foundc = nullptr;
-
- coding &c = vs0.c;
- CODING_PRIVATE(c.spec);
- // assert sane N
- assert((uint32_t)N < INT_MAX_VALUE || N == POP_FAVORED_N);
-
- // Look at the values, or at least skip over them quickly.
- if (valueSink == nullptr)
- {
- // Skip and ignore values in the first pass.
- c.parseMultiple(band_rp, N, band_limit, B, H);
- }
- else if (N >= 0)
- {
- // Pop coding, {F} sequence, initial run of values...
- assert((mode & DISABLE_POP) != 0);
- value_stream vs = vs0;
- for (int n = 0; n < N; n++)
- {
- int val = vs.getInt();
- valueSink->add(val);
- }
- band_rp = vs.rp;
- }
- else
- {
- // Pop coding, {F} sequence, final run of values...
- assert((mode & DISABLE_POP) != 0);
- assert(N == POP_FAVORED_N);
- int min = INT_MIN_VALUE; // farthest from the center
- // min2 is based on the buggy specification of centrality in version 150.7
- // no known implementations transmit this value, but just in case...
- // int min2 = INT_MIN_VALUE;
- int last = 0;
- // if there were initial runs, find the potential sentinels in them:
- for (int i = 0; i < valueSink->length(); i++)
- {
- last = valueSink->get(i);
- min = moreCentral(min, last);
- // min2 = moreCentral2(min2, last, min);
- }
- value_stream vs = vs0;
- for (;;)
- {
- int val = vs.getInt();
- if (valueSink->length() > 0 && (val == last || val == min)) //|| val == min2
- break;
- valueSink->add(val);
- last = val;
- min = moreCentral(min, last);
- // min2 = moreCentral2(min2, last, min);
- }
- band_rp = vs.rp;
- }
-
- // Get an accurate upper limit now.
- vs0.rplimit = band_rp;
- vs0.cm = this;
-
- return; // success
+ assert(N != 0);
+
+ assert(u != nullptr); // must be pre-initialized
+ // if (u == nullptr) u = unpacker::current(); // expensive
+
+ int op = (meta_rp == nullptr) ? _meta_default : (*meta_rp++ & 0xFF);
+ coding *foundc = nullptr;
+ coding *to_free = nullptr;
+
+ if (op == _meta_default)
+ {
+ foundc = defc;
+ // and fall through
+ }
+ else if (op >= _meta_canon_min && op <= _meta_canon_max)
+ {
+ foundc = coding::findByIndex(op);
+ // and fall through
+ }
+ else if (op == _meta_arb)
+ {
+ int args = (*meta_rp++ & 0xFF);
+ // args = (D:[0..1] + 2*S[0..2] + 8*(B:[1..5]-1))
+ int D = ((args >> 0) & 1);
+ int S = ((args >> 1) & 3);
+ int B = ((args >> 3) & -1) + 1;
+ // & (H[1..256]-1)
+ int H = (*meta_rp++ & 0xFF) + 1;
+ foundc = coding::findBySpec(B, H, S, D);
+ to_free = foundc; // findBySpec may dynamically allocate
+ if (foundc == nullptr)
+ {
+ unpack_abort("illegal arbitrary coding");
+ return;
+ }
+ // and fall through
+ }
+ else if (op >= _meta_run && op < _meta_pop)
+ {
+ int args = (op - _meta_run);
+ // args: KX:[0..3] + 4*(KBFlag:[0..1]) + 8*(ABDef:[0..2])
+ int KX = ((args >> 0) & 3);
+ int KBFlag = ((args >> 2) & 1);
+ int ABDef = ((args >> 3) & -1);
+ assert(ABDef <= 2);
+ // & KB: one of [0..255] if KBFlag=1
+ int KB = (!KBFlag ? 3 : (*meta_rp++ & 0xFF));
+ int K = (KB + 1) << (KX * 4);
+ int N2 = (N >= 0) ? N - K : N;
+ if (N == 0 || (N2 <= 0 && N2 != N))
+ {
+ unpack_abort("illegal run encoding");
+ }
+ if ((mode & DISABLE_RUN) != 0)
+ {
+ unpack_abort("illegal nested run encoding");
+ }
+
+ // & Enc{ ACode } if ADef=0 (ABDef != 1)
+ // No direct nesting of 'run' in ACode, but in BCode it's OK.
+ int disRun = mode | DISABLE_RUN;
+ if (ABDef == 1)
+ {
+ this->init(band_rp, band_limit, NO_META, disRun, defc, K, valueSink);
+ }
+ else
+ {
+ this->init(band_rp, band_limit, meta_rp, disRun, defc, K, valueSink);
+ }
+
+ // & Enc{ BCode } if BDef=0 (ABDef != 2)
+ coding_method *tail = U_NEW(coding_method, 1);
+ if (!tail)
+ return;
+ tail->u = u;
+
+ // The 'run' codings may be nested indirectly via 'pop' codings.
+ // This means that this->next may already be filled in, if
+ // ACode was of type 'pop' with a 'run' token coding.
+ // No problem: Just chain the upcoming BCode onto the end.
+ for (coding_method *self = this;; self = self->next)
+ {
+ if (self->next == nullptr)
+ {
+ self->next = tail;
+ break;
+ }
+ }
+
+ if (ABDef == 2)
+ {
+ tail->init(band_rp, band_limit, NO_META, mode, defc, N2, valueSink);
+ }
+ else
+ {
+ tail->init(band_rp, band_limit, meta_rp, mode, defc, N2, valueSink);
+ }
+ // Note: The preceding calls to init should be tail-recursive.
+
+ return; // done; no falling through
+ }
+ else if (op >= _meta_pop && op < _meta_limit)
+ {
+ int args = (op - _meta_pop);
+ // args: (FDef:[0..1]) + 2*UDef:[0..1] + 4*(TDefL:[0..11])
+ int FDef = ((args >> 0) & 1);
+ int UDef = ((args >> 1) & 1);
+ int TDefL = ((args >> 2) & -1);
+ assert(TDefL <= 11);
+ int TDef = (TDefL > 0);
+ int TL = (TDefL <= 6) ? (2 << TDefL) : (256 - (4 << (11 - TDefL)));
+ int TH = (256 - TL);
+ if (N <= 0)
+ {
+ unpack_abort("illegal pop encoding");
+ }
+ if ((mode & DISABLE_POP) != 0)
+ {
+ unpack_abort("illegal nested pop encoding");
+ }
+
+ // No indirect nesting of 'pop', but 'run' is OK.
+ int disPop = DISABLE_POP;
+
+ // & Enc{ FCode } if FDef=0
+ int FN = POP_FAVORED_N;
+ assert(valueSink == nullptr);
+ intlist fValueSink;
+ fValueSink.init();
+ coding_method fval;
+ BYTES_OF(fval).clear();
+ fval.u = u;
+ if (FDef != 0)
+ {
+ fval.init(band_rp, band_limit, NO_META, disPop, defc, FN, &fValueSink);
+ }
+ else
+ {
+ fval.init(band_rp, band_limit, meta_rp, disPop, defc, FN, &fValueSink);
+ }
+ bytes fvbuf;
+ fValues = (u->saveTo(fvbuf, fValueSink.b), (int *)fvbuf.ptr);
+ fVlength = fValueSink.length(); // i.e., the parameter K
+ fValueSink.free();
+
+ // Skip the first {F} run in all subsequent passes.
+ // The next call to this->init(...) will set vs0.rp to point after the {F}.
+
+ // & Enc{ TCode } if TDef=0 (TDefL==0)
+ if (TDef != 0)
+ {
+ coding *tcode = coding::findBySpec(1, 256); // BYTE1
+ // find the most narrowly sufficient code:
+ for (int B = 2; B <= B_MAX; B++)
+ {
+ if (fVlength <= tcode->umax)
+ break; // found it
+ tcode->free();
+ tcode = coding::findBySpec(B, TH);
+ if (!tcode)
+ return;
+ }
+ if (!(fVlength <= tcode->umax))
+ {
+ unpack_abort("pop.L value too small");
+ }
+ this->init(band_rp, band_limit, NO_META, disPop, tcode, N, nullptr);
+ tcode->free();
+ }
+ else
+ {
+ this->init(band_rp, band_limit, meta_rp, disPop, defc, N, nullptr);
+ }
+
+ // Count the number of zero tokens right now.
+ // Also verify that they are in bounds.
+ int UN = 0; // one {U} for each zero in {T}
+ value_stream vs = vs0;
+ for (int i = 0; i < N; i++)
+ {
+ uint32_t val = vs.getInt();
+ if (val == 0)
+ UN += 1;
+ if (!(val <= (uint32_t)fVlength))
+ {
+ unpack_abort("pop token out of range");
+ }
+ }
+ vs.done();
+
+ // & Enc{ UCode } if UDef=0
+ if (UN != 0)
+ {
+ uValues = U_NEW(coding_method, 1);
+ if (uValues == nullptr)
+ return;
+ uValues->u = u;
+ if (UDef != 0)
+ {
+ uValues->init(band_rp, band_limit, NO_META, disPop, defc, UN, nullptr);
+ }
+ else
+ {
+ uValues->init(band_rp, band_limit, meta_rp, disPop, defc, UN, nullptr);
+ }
+ }
+ else
+ {
+ if (UDef == 0)
+ {
+ int uop = (*meta_rp++ & 0xFF);
+ if (uop > _meta_canon_max)
+ // %%% Spec. requires the more strict (uop != _meta_default).
+ unpack_abort("bad meta-coding for empty pop/U");
+ }
+ }
+
+ // Bug fix for 6259542
+ // Last of all, adjust vs0.cmk to the 'pop' flavor
+ for (coding_method *self = this; self != nullptr; self = self->next)
+ {
+ coding_method_kind cmk2 = cmk_pop;
+ switch (self->vs0.cmk)
+ {
+ case cmk_BHS0:
+ cmk2 = cmk_pop_BHS0;
+ break;
+ case cmk_BYTE1:
+ cmk2 = cmk_pop_BYTE1;
+ break;
+ default:
+ break;
+ }
+ self->vs0.cmk = cmk2;
+ if (self != this)
+ {
+ assert(self->fValues == nullptr); // no double init
+ self->fValues = this->fValues;
+ self->fVlength = this->fVlength;
+ assert(self->uValues == nullptr); // must stay nullptr
+ }
+ }
+
+ return; // done; no falling through
+ }
+ else
+ {
+ unpack_abort("bad meta-coding");
+ }
+
+ // Common code here skips a series of values with one coding.
+ assert(foundc != nullptr);
+
+ assert(vs0.cmk == cmk_ERROR); // no garbage, please
+ assert(vs0.rp == nullptr); // no garbage, please
+ assert(vs0.rplimit == nullptr); // no garbage, please
+ assert(vs0.sum == 0); // no garbage, please
+
+ vs0.init(band_rp, band_limit, foundc);
+
+ // Done with foundc. Free if necessary.
+ if (to_free != nullptr)
+ {
+ to_free->free();
+ to_free = nullptr;
+ }
+ foundc = nullptr;
+
+ coding &c = vs0.c;
+ CODING_PRIVATE(c.spec);
+ // assert sane N
+ assert((uint32_t)N < INT_MAX_VALUE || N == POP_FAVORED_N);
+
+ // Look at the values, or at least skip over them quickly.
+ if (valueSink == nullptr)
+ {
+ // Skip and ignore values in the first pass.
+ c.parseMultiple(band_rp, N, band_limit, B, H);
+ }
+ else if (N >= 0)
+ {
+ // Pop coding, {F} sequence, initial run of values...
+ assert((mode & DISABLE_POP) != 0);
+ value_stream vs = vs0;
+ for (int n = 0; n < N; n++)
+ {
+ int val = vs.getInt();
+ valueSink->add(val);
+ }
+ band_rp = vs.rp;
+ }
+ else
+ {
+ // Pop coding, {F} sequence, final run of values...
+ assert((mode & DISABLE_POP) != 0);
+ assert(N == POP_FAVORED_N);
+ int min = INT_MIN_VALUE; // farthest from the center
+ // min2 is based on the buggy specification of centrality in version 150.7
+ // no known implementations transmit this value, but just in case...
+ // int min2 = INT_MIN_VALUE;
+ int last = 0;
+ // if there were initial runs, find the potential sentinels in them:
+ for (int i = 0; i < valueSink->length(); i++)
+ {
+ last = valueSink->get(i);
+ min = moreCentral(min, last);
+ // min2 = moreCentral2(min2, last, min);
+ }
+ value_stream vs = vs0;
+ for (;;)
+ {
+ int val = vs.getInt();
+ if (valueSink->length() > 0 && (val == last || val == min)) //|| val == min2
+ break;
+ valueSink->add(val);
+ last = val;
+ min = moreCentral(min, last);
+ // min2 = moreCentral2(min2, last, min);
+ }
+ band_rp = vs.rp;
+ }
+
+ // Get an accurate upper limit now.
+ vs0.rplimit = band_rp;
+ vs0.cm = this;
+
+ return; // success
}
coding basic_codings[] = {
- // This one is not a usable irregular coding, but is used by cp_Utf8_chars.
- CODING_INIT(3, 128, 0, 0),
-
- // Fixed-length codings:
- CODING_INIT(1, 256, 0, 0), CODING_INIT(1, 256, 1, 0), CODING_INIT(1, 256, 0, 1),
- CODING_INIT(1, 256, 1, 1), CODING_INIT(2, 256, 0, 0), CODING_INIT(2, 256, 1, 0),
- CODING_INIT(2, 256, 0, 1), CODING_INIT(2, 256, 1, 1), CODING_INIT(3, 256, 0, 0),
- CODING_INIT(3, 256, 1, 0), CODING_INIT(3, 256, 0, 1), CODING_INIT(3, 256, 1, 1),
- CODING_INIT(4, 256, 0, 0), CODING_INIT(4, 256, 1, 0), CODING_INIT(4, 256, 0, 1),
- CODING_INIT(4, 256, 1, 1),
-
- // Full-range variable-length codings:
- CODING_INIT(5, 4, 0, 0), CODING_INIT(5, 4, 1, 0), CODING_INIT(5, 4, 2, 0),
- CODING_INIT(5, 16, 0, 0), CODING_INIT(5, 16, 1, 0), CODING_INIT(5, 16, 2, 0),
- CODING_INIT(5, 32, 0, 0), CODING_INIT(5, 32, 1, 0), CODING_INIT(5, 32, 2, 0),
- CODING_INIT(5, 64, 0, 0), CODING_INIT(5, 64, 1, 0), CODING_INIT(5, 64, 2, 0),
- CODING_INIT(5, 128, 0, 0), CODING_INIT(5, 128, 1, 0), CODING_INIT(5, 128, 2, 0),
- CODING_INIT(5, 4, 0, 1), CODING_INIT(5, 4, 1, 1), CODING_INIT(5, 4, 2, 1),
- CODING_INIT(5, 16, 0, 1), CODING_INIT(5, 16, 1, 1), CODING_INIT(5, 16, 2, 1),
- CODING_INIT(5, 32, 0, 1), CODING_INIT(5, 32, 1, 1), CODING_INIT(5, 32, 2, 1),
- CODING_INIT(5, 64, 0, 1), CODING_INIT(5, 64, 1, 1), CODING_INIT(5, 64, 2, 1),
- CODING_INIT(5, 128, 0, 1), CODING_INIT(5, 128, 1, 1), CODING_INIT(5, 128, 2, 1),
-
- // Variable length subrange codings:
- CODING_INIT(2, 192, 0, 0), CODING_INIT(2, 224, 0, 0), CODING_INIT(2, 240, 0, 0),
- CODING_INIT(2, 248, 0, 0), CODING_INIT(2, 252, 0, 0), CODING_INIT(2, 8, 0, 1),
- CODING_INIT(2, 8, 1, 1), CODING_INIT(2, 16, 0, 1), CODING_INIT(2, 16, 1, 1),
- CODING_INIT(2, 32, 0, 1), CODING_INIT(2, 32, 1, 1), CODING_INIT(2, 64, 0, 1),
- CODING_INIT(2, 64, 1, 1), CODING_INIT(2, 128, 0, 1), CODING_INIT(2, 128, 1, 1),
- CODING_INIT(2, 192, 0, 1), CODING_INIT(2, 192, 1, 1), CODING_INIT(2, 224, 0, 1),
- CODING_INIT(2, 224, 1, 1), CODING_INIT(2, 240, 0, 1), CODING_INIT(2, 240, 1, 1),
- CODING_INIT(2, 248, 0, 1), CODING_INIT(2, 248, 1, 1), CODING_INIT(3, 192, 0, 0),
- CODING_INIT(3, 224, 0, 0), CODING_INIT(3, 240, 0, 0), CODING_INIT(3, 248, 0, 0),
- CODING_INIT(3, 252, 0, 0), CODING_INIT(3, 8, 0, 1), CODING_INIT(3, 8, 1, 1),
- CODING_INIT(3, 16, 0, 1), CODING_INIT(3, 16, 1, 1), CODING_INIT(3, 32, 0, 1),
- CODING_INIT(3, 32, 1, 1), CODING_INIT(3, 64, 0, 1), CODING_INIT(3, 64, 1, 1),
- CODING_INIT(3, 128, 0, 1), CODING_INIT(3, 128, 1, 1), CODING_INIT(3, 192, 0, 1),
- CODING_INIT(3, 192, 1, 1), CODING_INIT(3, 224, 0, 1), CODING_INIT(3, 224, 1, 1),
- CODING_INIT(3, 240, 0, 1), CODING_INIT(3, 240, 1, 1), CODING_INIT(3, 248, 0, 1),
- CODING_INIT(3, 248, 1, 1), CODING_INIT(4, 192, 0, 0), CODING_INIT(4, 224, 0, 0),
- CODING_INIT(4, 240, 0, 0), CODING_INIT(4, 248, 0, 0), CODING_INIT(4, 252, 0, 0),
- CODING_INIT(4, 8, 0, 1), CODING_INIT(4, 8, 1, 1), CODING_INIT(4, 16, 0, 1),
- CODING_INIT(4, 16, 1, 1), CODING_INIT(4, 32, 0, 1), CODING_INIT(4, 32, 1, 1),
- CODING_INIT(4, 64, 0, 1), CODING_INIT(4, 64, 1, 1), CODING_INIT(4, 128, 0, 1),
- CODING_INIT(4, 128, 1, 1), CODING_INIT(4, 192, 0, 1), CODING_INIT(4, 192, 1, 1),
- CODING_INIT(4, 224, 0, 1), CODING_INIT(4, 224, 1, 1), CODING_INIT(4, 240, 0, 1),
- CODING_INIT(4, 240, 1, 1), CODING_INIT(4, 248, 0, 1), CODING_INIT(4, 248, 1, 1),
- CODING_INIT(0, 0, 0, 0)};
+ // This one is not a usable irregular coding, but is used by cp_Utf8_chars.
+ CODING_INIT(3, 128, 0, 0),
+
+ // Fixed-length codings:
+ CODING_INIT(1, 256, 0, 0), CODING_INIT(1, 256, 1, 0), CODING_INIT(1, 256, 0, 1),
+ CODING_INIT(1, 256, 1, 1), CODING_INIT(2, 256, 0, 0), CODING_INIT(2, 256, 1, 0),
+ CODING_INIT(2, 256, 0, 1), CODING_INIT(2, 256, 1, 1), CODING_INIT(3, 256, 0, 0),
+ CODING_INIT(3, 256, 1, 0), CODING_INIT(3, 256, 0, 1), CODING_INIT(3, 256, 1, 1),
+ CODING_INIT(4, 256, 0, 0), CODING_INIT(4, 256, 1, 0), CODING_INIT(4, 256, 0, 1),
+ CODING_INIT(4, 256, 1, 1),
+
+ // Full-range variable-length codings:
+ CODING_INIT(5, 4, 0, 0), CODING_INIT(5, 4, 1, 0), CODING_INIT(5, 4, 2, 0),
+ CODING_INIT(5, 16, 0, 0), CODING_INIT(5, 16, 1, 0), CODING_INIT(5, 16, 2, 0),
+ CODING_INIT(5, 32, 0, 0), CODING_INIT(5, 32, 1, 0), CODING_INIT(5, 32, 2, 0),
+ CODING_INIT(5, 64, 0, 0), CODING_INIT(5, 64, 1, 0), CODING_INIT(5, 64, 2, 0),
+ CODING_INIT(5, 128, 0, 0), CODING_INIT(5, 128, 1, 0), CODING_INIT(5, 128, 2, 0),
+ CODING_INIT(5, 4, 0, 1), CODING_INIT(5, 4, 1, 1), CODING_INIT(5, 4, 2, 1),
+ CODING_INIT(5, 16, 0, 1), CODING_INIT(5, 16, 1, 1), CODING_INIT(5, 16, 2, 1),
+ CODING_INIT(5, 32, 0, 1), CODING_INIT(5, 32, 1, 1), CODING_INIT(5, 32, 2, 1),
+ CODING_INIT(5, 64, 0, 1), CODING_INIT(5, 64, 1, 1), CODING_INIT(5, 64, 2, 1),
+ CODING_INIT(5, 128, 0, 1), CODING_INIT(5, 128, 1, 1), CODING_INIT(5, 128, 2, 1),
+
+ // Variable length subrange codings:
+ CODING_INIT(2, 192, 0, 0), CODING_INIT(2, 224, 0, 0), CODING_INIT(2, 240, 0, 0),
+ CODING_INIT(2, 248, 0, 0), CODING_INIT(2, 252, 0, 0), CODING_INIT(2, 8, 0, 1),
+ CODING_INIT(2, 8, 1, 1), CODING_INIT(2, 16, 0, 1), CODING_INIT(2, 16, 1, 1),
+ CODING_INIT(2, 32, 0, 1), CODING_INIT(2, 32, 1, 1), CODING_INIT(2, 64, 0, 1),
+ CODING_INIT(2, 64, 1, 1), CODING_INIT(2, 128, 0, 1), CODING_INIT(2, 128, 1, 1),
+ CODING_INIT(2, 192, 0, 1), CODING_INIT(2, 192, 1, 1), CODING_INIT(2, 224, 0, 1),
+ CODING_INIT(2, 224, 1, 1), CODING_INIT(2, 240, 0, 1), CODING_INIT(2, 240, 1, 1),
+ CODING_INIT(2, 248, 0, 1), CODING_INIT(2, 248, 1, 1), CODING_INIT(3, 192, 0, 0),
+ CODING_INIT(3, 224, 0, 0), CODING_INIT(3, 240, 0, 0), CODING_INIT(3, 248, 0, 0),
+ CODING_INIT(3, 252, 0, 0), CODING_INIT(3, 8, 0, 1), CODING_INIT(3, 8, 1, 1),
+ CODING_INIT(3, 16, 0, 1), CODING_INIT(3, 16, 1, 1), CODING_INIT(3, 32, 0, 1),
+ CODING_INIT(3, 32, 1, 1), CODING_INIT(3, 64, 0, 1), CODING_INIT(3, 64, 1, 1),
+ CODING_INIT(3, 128, 0, 1), CODING_INIT(3, 128, 1, 1), CODING_INIT(3, 192, 0, 1),
+ CODING_INIT(3, 192, 1, 1), CODING_INIT(3, 224, 0, 1), CODING_INIT(3, 224, 1, 1),
+ CODING_INIT(3, 240, 0, 1), CODING_INIT(3, 240, 1, 1), CODING_INIT(3, 248, 0, 1),
+ CODING_INIT(3, 248, 1, 1), CODING_INIT(4, 192, 0, 0), CODING_INIT(4, 224, 0, 0),
+ CODING_INIT(4, 240, 0, 0), CODING_INIT(4, 248, 0, 0), CODING_INIT(4, 252, 0, 0),
+ CODING_INIT(4, 8, 0, 1), CODING_INIT(4, 8, 1, 1), CODING_INIT(4, 16, 0, 1),
+ CODING_INIT(4, 16, 1, 1), CODING_INIT(4, 32, 0, 1), CODING_INIT(4, 32, 1, 1),
+ CODING_INIT(4, 64, 0, 1), CODING_INIT(4, 64, 1, 1), CODING_INIT(4, 128, 0, 1),
+ CODING_INIT(4, 128, 1, 1), CODING_INIT(4, 192, 0, 1), CODING_INIT(4, 192, 1, 1),
+ CODING_INIT(4, 224, 0, 1), CODING_INIT(4, 224, 1, 1), CODING_INIT(4, 240, 0, 1),
+ CODING_INIT(4, 240, 1, 1), CODING_INIT(4, 248, 0, 1), CODING_INIT(4, 248, 1, 1),
+ CODING_INIT(0, 0, 0, 0)};
#define BASIC_INDEX_LIMIT (int)(sizeof(basic_codings) / sizeof(basic_codings[0]) - 1)
coding *coding::findByIndex(int idx)
{
- int index_limit = BASIC_INDEX_LIMIT;
- assert(_meta_canon_min == 1 && _meta_canon_max + 1 == index_limit);
+ int index_limit = BASIC_INDEX_LIMIT;
+ assert(_meta_canon_min == 1 && _meta_canon_max + 1 == index_limit);
- if (idx >= _meta_canon_min && idx <= _meta_canon_max)
- return basic_codings[idx].init();
- else
- return nullptr;
+ if (idx >= _meta_canon_min && idx <= _meta_canon_max)
+ return basic_codings[idx].init();
+ else
+ return nullptr;
}
diff --git a/libraries/pack200/src/coding.h b/libraries/pack200/src/coding.h
index f9bd6ca2..bfdd252e 100644
--- a/libraries/pack200/src/coding.h
+++ b/libraries/pack200/src/coding.h
@@ -35,9 +35,9 @@ struct unpacker;
#define CODING_D(x) ((x) >> 0 & 0xF)
#define CODING_INIT(B, H, S, D) \
- { \
- CODING_SPEC(B, H, S, D), 0, 0, 0, 0, 0, 0, 0, 0 \
- }
+ { \
+ CODING_SPEC(B, H, S, D), 0, 0, 0, 0, 0, 0, 0, 0 \
+ }
// For debugging purposes, some compilers do not like this and will complain.
// #define long do_not_use_C_long_types_use_jlong_or_int
@@ -45,126 +45,126 @@ struct unpacker;
struct coding
{
- int spec; // B,H,S,D
-
- // Handy values derived from the spec:
- int B()
- {
- return CODING_B(spec);
- }
- int H()
- {
- return CODING_H(spec);
- }
- int S()
- {
- return CODING_S(spec);
- }
- int D()
- {
- return CODING_D(spec);
- }
- int L()
- {
- return 256 - CODING_H(spec);
- }
- int min, max;
- int umin, umax;
- char isSigned, isSubrange, isFullRange, isMalloc;
-
- coding *init(); // returns self or nullptr if error
- coding *initFrom(int spec_)
- {
- assert(this->spec == 0);
- this->spec = spec_;
- return init();
- }
-
- static coding *findBySpec(int spec);
- static coding *findBySpec(int B, int H, int S = 0, int D = 0);
- static coding *findByIndex(int irregularCodingIndex);
-
- static uint32_t parse(byte *&rp, int B, int H);
- static uint32_t parse_lgH(byte *&rp, int B, int H, int lgH);
- static void parseMultiple(byte *&rp, int N, byte *limit, int B, int H);
-
- uint32_t parse(byte *&rp)
- {
- return parse(rp, CODING_B(spec), CODING_H(spec));
- }
- void parseMultiple(byte *&rp, int N, byte *limit)
- {
- parseMultiple(rp, N, limit, CODING_B(spec), CODING_H(spec));
- }
-
- bool canRepresent(int x)
- {
- return (x >= min && x <= max);
- }
- bool canRepresentUnsigned(int x)
- {
- return (x >= umin && x <= umax);
- }
-
- int sumInUnsignedRange(int x, int y);
-
- int readFrom(byte *&rpVar, int *dbase);
- void readArrayFrom(byte *&rpVar, int *dbase, int length, int *values);
- void skipArrayFrom(byte *&rpVar, int length)
- {
- readArrayFrom(rpVar, (int *)NULL, length, (int *)NULL);
- }
-
- void free(); // free self if isMalloc
+ int spec; // B,H,S,D
+
+ // Handy values derived from the spec:
+ int B()
+ {
+ return CODING_B(spec);
+ }
+ int H()
+ {
+ return CODING_H(spec);
+ }
+ int S()
+ {
+ return CODING_S(spec);
+ }
+ int D()
+ {
+ return CODING_D(spec);
+ }
+ int L()
+ {
+ return 256 - CODING_H(spec);
+ }
+ int min, max;
+ int umin, umax;
+ char isSigned, isSubrange, isFullRange, isMalloc;
+
+ coding *init(); // returns self or nullptr if error
+ coding *initFrom(int spec_)
+ {
+ assert(this->spec == 0);
+ this->spec = spec_;
+ return init();
+ }
+
+ static coding *findBySpec(int spec);
+ static coding *findBySpec(int B, int H, int S = 0, int D = 0);
+ static coding *findByIndex(int irregularCodingIndex);
+
+ static uint32_t parse(byte *&rp, int B, int H);
+ static uint32_t parse_lgH(byte *&rp, int B, int H, int lgH);
+ static void parseMultiple(byte *&rp, int N, byte *limit, int B, int H);
+
+ uint32_t parse(byte *&rp)
+ {
+ return parse(rp, CODING_B(spec), CODING_H(spec));
+ }
+ void parseMultiple(byte *&rp, int N, byte *limit)
+ {
+ parseMultiple(rp, N, limit, CODING_B(spec), CODING_H(spec));
+ }
+
+ bool canRepresent(int x)
+ {
+ return (x >= min && x <= max);
+ }
+ bool canRepresentUnsigned(int x)
+ {
+ return (x >= umin && x <= umax);
+ }
+
+ int sumInUnsignedRange(int x, int y);
+
+ int readFrom(byte *&rpVar, int *dbase);
+ void readArrayFrom(byte *&rpVar, int *dbase, int length, int *values);
+ void skipArrayFrom(byte *&rpVar, int length)
+ {
+ readArrayFrom(rpVar, (int *)NULL, length, (int *)NULL);
+ }
+
+ void free(); // free self if isMalloc
};
enum coding_method_kind
{
- cmk_ERROR,
- cmk_BHS,
- cmk_BHS0,
- cmk_BHS1,
- cmk_BHSD1,
- cmk_BHS1D1full, // isFullRange
- cmk_BHS1D1sub, // isSubRange
-
- // special cases hand-optimized (~50% of all decoded values)
- cmk_BYTE1, //(1,256) 6%
- cmk_CHAR3, //(3,128) 7%
- cmk_UNSIGNED5, //(5,64) 13%
- cmk_DELTA5, //(5,64,1,1) 5%
- cmk_BCI5, //(5,4) 18%
- cmk_BRANCH5, //(5,4,2) 4%
- // cmk_UNSIGNED5H16, //(5,16) 5%
- // cmk_UNSIGNED2H4, //(2,4) 6%
- // cmk_DELTA4H8, //(4,8,1,1) 10%
- // cmk_DELTA3H16, //(3,16,1,1) 9%
- cmk_BHS_LIMIT,
- cmk_pop,
- cmk_pop_BHS0,
- cmk_pop_BYTE1,
- cmk_pop_LIMIT,
- cmk_LIMIT
+ cmk_ERROR,
+ cmk_BHS,
+ cmk_BHS0,
+ cmk_BHS1,
+ cmk_BHSD1,
+ cmk_BHS1D1full, // isFullRange
+ cmk_BHS1D1sub, // isSubRange
+
+ // special cases hand-optimized (~50% of all decoded values)
+ cmk_BYTE1, //(1,256) 6%
+ cmk_CHAR3, //(3,128) 7%
+ cmk_UNSIGNED5, //(5,64) 13%
+ cmk_DELTA5, //(5,64,1,1) 5%
+ cmk_BCI5, //(5,4) 18%
+ cmk_BRANCH5, //(5,4,2) 4%
+ // cmk_UNSIGNED5H16, //(5,16) 5%
+ // cmk_UNSIGNED2H4, //(2,4) 6%
+ // cmk_DELTA4H8, //(4,8,1,1) 10%
+ // cmk_DELTA3H16, //(3,16,1,1) 9%
+ cmk_BHS_LIMIT,
+ cmk_pop,
+ cmk_pop_BHS0,
+ cmk_pop_BYTE1,
+ cmk_pop_LIMIT,
+ cmk_LIMIT
};
enum
{
- BYTE1_spec = CODING_SPEC(1, 256, 0, 0),
- CHAR3_spec = CODING_SPEC(3, 128, 0, 0),
- UNSIGNED4_spec = CODING_SPEC(4, 256, 0, 0),
- UNSIGNED5_spec = CODING_SPEC(5, 64, 0, 0),
- SIGNED5_spec = CODING_SPEC(5, 64, 1, 0),
- DELTA5_spec = CODING_SPEC(5, 64, 1, 1),
- UDELTA5_spec = CODING_SPEC(5, 64, 0, 1),
- MDELTA5_spec = CODING_SPEC(5, 64, 2, 1),
- BCI5_spec = CODING_SPEC(5, 4, 0, 0),
- BRANCH5_spec = CODING_SPEC(5, 4, 2, 0)
+ BYTE1_spec = CODING_SPEC(1, 256, 0, 0),
+ CHAR3_spec = CODING_SPEC(3, 128, 0, 0),
+ UNSIGNED4_spec = CODING_SPEC(4, 256, 0, 0),
+ UNSIGNED5_spec = CODING_SPEC(5, 64, 0, 0),
+ SIGNED5_spec = CODING_SPEC(5, 64, 1, 0),
+ DELTA5_spec = CODING_SPEC(5, 64, 1, 1),
+ UDELTA5_spec = CODING_SPEC(5, 64, 0, 1),
+ MDELTA5_spec = CODING_SPEC(5, 64, 2, 1),
+ BCI5_spec = CODING_SPEC(5, 4, 0, 0),
+ BRANCH5_spec = CODING_SPEC(5, 4, 2, 0)
};
enum
{
- B_MAX = 5,
- C_SLOP = B_MAX * 10
+ B_MAX = 5,
+ C_SLOP = B_MAX * 10
};
struct coding_method;
@@ -172,76 +172,76 @@ struct coding_method;
// iterator under the control of a meta-coding
struct value_stream
{
- // current coding of values or values
- coding c; // B,H,S,D,etc.
- coding_method_kind cmk; // type of decoding needed
- byte *rp; // read pointer
- byte *rplimit; // final value of read pointer
- int sum; // partial sum of all values so far (D=1 only)
- coding_method *cm; // coding method that defines this stream
-
- void init(byte *band_rp, byte *band_limit, coding *defc);
- void init(byte *band_rp, byte *band_limit, int spec)
- {
- init(band_rp, band_limit, coding::findBySpec(spec));
- }
-
- void setCoding(coding *c);
- void setCoding(int spec)
- {
- setCoding(coding::findBySpec(spec));
- }
-
- // Parse and decode a single value.
- int getInt();
-
- // Parse and decode a single byte, with no error checks.
- int getByte()
- {
- assert(cmk == cmk_BYTE1);
- assert(rp < rplimit);
- return *rp++ & 0xFF;
- }
-
- // Used only for asserts.
- bool hasValue();
-
- void done()
- {
- assert(!hasValue());
- }
-
- // Sometimes a value stream has an auxiliary (but there are never two).
- value_stream *helper()
- {
- assert(hasHelper());
- return this + 1;
- }
- bool hasHelper();
+ // current coding of values or values
+ coding c; // B,H,S,D,etc.
+ coding_method_kind cmk; // type of decoding needed
+ byte *rp; // read pointer
+ byte *rplimit; // final value of read pointer
+ int sum; // partial sum of all values so far (D=1 only)
+ coding_method *cm; // coding method that defines this stream
+
+ void init(byte *band_rp, byte *band_limit, coding *defc);
+ void init(byte *band_rp, byte *band_limit, int spec)
+ {
+ init(band_rp, band_limit, coding::findBySpec(spec));
+ }
+
+ void setCoding(coding *c);
+ void setCoding(int spec)
+ {
+ setCoding(coding::findBySpec(spec));
+ }
+
+ // Parse and decode a single value.
+ int getInt();
+
+ // Parse and decode a single byte, with no error checks.
+ int getByte()
+ {
+ assert(cmk == cmk_BYTE1);
+ assert(rp < rplimit);
+ return *rp++ & 0xFF;
+ }
+
+ // Used only for asserts.
+ bool hasValue();
+
+ void done()
+ {
+ assert(!hasValue());
+ }
+
+ // Sometimes a value stream has an auxiliary (but there are never two).
+ value_stream *helper()
+ {
+ assert(hasHelper());
+ return this + 1;
+ }
+ bool hasHelper();
};
struct coding_method
{
- value_stream vs0; // initial state snapshot (vs.meta==this)
+ value_stream vs0; // initial state snapshot (vs.meta==this)
- coding_method *next; // what to do when we run out of bytes
+ coding_method *next; // what to do when we run out of bytes
- // these fields are used for pop codes only:
- int *fValues; // favored value array
- int fVlength; // maximum favored value token
- coding_method *uValues; // unfavored value stream
+ // these fields are used for pop codes only:
+ int *fValues; // favored value array
+ int fVlength; // maximum favored value token
+ coding_method *uValues; // unfavored value stream
- // pointer to outer unpacker, for error checks etc.
- unpacker *u;
+ // pointer to outer unpacker, for error checks etc.
+ unpacker *u;
- // Initialize a value stream.
- void reset(value_stream *state);
+ // Initialize a value stream.
+ void reset(value_stream *state);
- // Parse a band header, size a band, and initialize for further action.
- // band_rp advances (but not past band_limit), and meta_rp advances.
- // The mode gives context, such as "inside a pop".
- // The defc and N are the incoming parameters to a meta-coding.
- // The value sink is used to collect output values, when desired.
- void init(byte *&band_rp, byte *band_limit, byte *&meta_rp, int mode, coding *defc, int N,
- intlist *valueSink);
+ // Parse a band header, size a band, and initialize for further action.
+ // band_rp advances (but not past band_limit), and meta_rp advances.
+ // The mode gives context, such as "inside a pop".
+ // The defc and N are the incoming parameters to a meta-coding.
+ // The value sink is used to collect output values, when desired.
+ void init(byte *&band_rp, byte *band_limit, byte *&meta_rp, int mode, coding *defc, int N,
+ intlist *valueSink);
};
diff --git a/libraries/pack200/src/constants.h b/libraries/pack200/src/constants.h
index 2cc14b7d..f1baf42a 100644
--- a/libraries/pack200/src/constants.h
+++ b/libraries/pack200/src/constants.h
@@ -55,388 +55,388 @@
enum
{
- CONSTANT_None,
- CONSTANT_Utf8,
- CONSTANT_unused2, /* unused, was Unicode */
- CONSTANT_Integer,
- CONSTANT_Float,
- CONSTANT_Long,
- CONSTANT_Double,
- CONSTANT_Class,
- CONSTANT_String,
- CONSTANT_Fieldref,
- CONSTANT_Methodref,
- CONSTANT_InterfaceMethodref,
- CONSTANT_NameandType,
- CONSTANT_Signature = 13,
- CONSTANT_All = 14,
- CONSTANT_Limit = 15,
- CONSTANT_NONE = 0,
- CONSTANT_Literal = 20, // pseudo-tag for debugging
- CONSTANT_Member = 21, // pseudo-tag for debugging
- SUBINDEX_BIT = 64, // combined with CONSTANT_xxx for ixTag
- ACC_STATIC = 0x0008,
- ACC_IC_LONG_FORM = (1 << 16), // for ic_flags
- CLASS_ATTR_SourceFile = 17,
- CLASS_ATTR_EnclosingMethod = 18,
- CLASS_ATTR_InnerClasses = 23,
- CLASS_ATTR_ClassFile_version = 24,
- FIELD_ATTR_ConstantValue = 17,
- METHOD_ATTR_Code = 17,
- METHOD_ATTR_Exceptions = 18,
- METHOD_ATTR_RuntimeVisibleParameterAnnotations = 23,
- METHOD_ATTR_RuntimeInvisibleParameterAnnotations = 24,
- METHOD_ATTR_AnnotationDefault = 25,
- CODE_ATTR_StackMapTable = 0,
- CODE_ATTR_LineNumberTable = 1,
- CODE_ATTR_LocalVariableTable = 2,
- CODE_ATTR_LocalVariableTypeTable = 3,
- // X_ATTR_Synthetic = 12, // ACC_SYNTHETIC; not predefined
- X_ATTR_Signature = 19,
- X_ATTR_Deprecated = 20,
- X_ATTR_RuntimeVisibleAnnotations = 21,
- X_ATTR_RuntimeInvisibleAnnotations = 22,
- X_ATTR_OVERFLOW = 16,
- X_ATTR_LIMIT_NO_FLAGS_HI = 32,
- X_ATTR_LIMIT_FLAGS_HI = 63,
+ CONSTANT_None,
+ CONSTANT_Utf8,
+ CONSTANT_unused2, /* unused, was Unicode */
+ CONSTANT_Integer,
+ CONSTANT_Float,
+ CONSTANT_Long,
+ CONSTANT_Double,
+ CONSTANT_Class,
+ CONSTANT_String,
+ CONSTANT_Fieldref,
+ CONSTANT_Methodref,
+ CONSTANT_InterfaceMethodref,
+ CONSTANT_NameandType,
+ CONSTANT_Signature = 13,
+ CONSTANT_All = 14,
+ CONSTANT_Limit = 15,
+ CONSTANT_NONE = 0,
+ CONSTANT_Literal = 20, // pseudo-tag for debugging
+ CONSTANT_Member = 21, // pseudo-tag for debugging
+ SUBINDEX_BIT = 64, // combined with CONSTANT_xxx for ixTag
+ ACC_STATIC = 0x0008,
+ ACC_IC_LONG_FORM = (1 << 16), // for ic_flags
+ CLASS_ATTR_SourceFile = 17,
+ CLASS_ATTR_EnclosingMethod = 18,
+ CLASS_ATTR_InnerClasses = 23,
+ CLASS_ATTR_ClassFile_version = 24,
+ FIELD_ATTR_ConstantValue = 17,
+ METHOD_ATTR_Code = 17,
+ METHOD_ATTR_Exceptions = 18,
+ METHOD_ATTR_RuntimeVisibleParameterAnnotations = 23,
+ METHOD_ATTR_RuntimeInvisibleParameterAnnotations = 24,
+ METHOD_ATTR_AnnotationDefault = 25,
+ CODE_ATTR_StackMapTable = 0,
+ CODE_ATTR_LineNumberTable = 1,
+ CODE_ATTR_LocalVariableTable = 2,
+ CODE_ATTR_LocalVariableTypeTable = 3,
+ // X_ATTR_Synthetic = 12, // ACC_SYNTHETIC; not predefined
+ X_ATTR_Signature = 19,
+ X_ATTR_Deprecated = 20,
+ X_ATTR_RuntimeVisibleAnnotations = 21,
+ X_ATTR_RuntimeInvisibleAnnotations = 22,
+ X_ATTR_OVERFLOW = 16,
+ X_ATTR_LIMIT_NO_FLAGS_HI = 32,
+ X_ATTR_LIMIT_FLAGS_HI = 63,
#define O_ATTR_DO(F) \
- F(X_ATTR_OVERFLOW, 01) \
- /*(end)*/
+ F(X_ATTR_OVERFLOW, 01) \
+ /*(end)*/
#define X_ATTR_DO(F) \
- O_ATTR_DO(F) F(X_ATTR_Signature, Signature) F(X_ATTR_Deprecated, Deprecated) \
- F(X_ATTR_RuntimeVisibleAnnotations, RuntimeVisibleAnnotations) \
- F(X_ATTR_RuntimeInvisibleAnnotations, RuntimeInvisibleAnnotations) \
- /*F(X_ATTR_Synthetic,Synthetic)*/ \
- /*(end)*/
+ O_ATTR_DO(F) F(X_ATTR_Signature, Signature) F(X_ATTR_Deprecated, Deprecated) \
+ F(X_ATTR_RuntimeVisibleAnnotations, RuntimeVisibleAnnotations) \
+ F(X_ATTR_RuntimeInvisibleAnnotations, RuntimeInvisibleAnnotations) \
+ /*F(X_ATTR_Synthetic,Synthetic)*/ \
+ /*(end)*/
#define CLASS_ATTR_DO(F) \
- F(CLASS_ATTR_SourceFile, SourceFile) F(CLASS_ATTR_InnerClasses, InnerClasses) \
- F(CLASS_ATTR_EnclosingMethod, EnclosingMethod) F(CLASS_ATTR_ClassFile_version, 02) \
- /*(end)*/
+ F(CLASS_ATTR_SourceFile, SourceFile) F(CLASS_ATTR_InnerClasses, InnerClasses) \
+ F(CLASS_ATTR_EnclosingMethod, EnclosingMethod) F(CLASS_ATTR_ClassFile_version, 02) \
+ /*(end)*/
#define FIELD_ATTR_DO(F) \
- F(FIELD_ATTR_ConstantValue, ConstantValue) \
- /*(end)*/
+ F(FIELD_ATTR_ConstantValue, ConstantValue) \
+ /*(end)*/
#define METHOD_ATTR_DO(F) \
- F(METHOD_ATTR_Code, Code) F(METHOD_ATTR_Exceptions, Exceptions) \
- F(METHOD_ATTR_RuntimeVisibleParameterAnnotations, RuntimeVisibleParameterAnnotations) \
- F(METHOD_ATTR_RuntimeInvisibleParameterAnnotations, \
- RuntimeInvisibleParameterAnnotations) \
- F(METHOD_ATTR_AnnotationDefault, AnnotationDefault) \
- /*(end)*/
+ F(METHOD_ATTR_Code, Code) F(METHOD_ATTR_Exceptions, Exceptions) \
+ F(METHOD_ATTR_RuntimeVisibleParameterAnnotations, RuntimeVisibleParameterAnnotations) \
+ F(METHOD_ATTR_RuntimeInvisibleParameterAnnotations, \
+ RuntimeInvisibleParameterAnnotations) \
+ F(METHOD_ATTR_AnnotationDefault, AnnotationDefault) \
+ /*(end)*/
#define CODE_ATTR_DO(F) \
- F(CODE_ATTR_StackMapTable, StackMapTable) F(CODE_ATTR_LineNumberTable, LineNumberTable) \
- F(CODE_ATTR_LocalVariableTable, LocalVariableTable) \
- F(CODE_ATTR_LocalVariableTypeTable, LocalVariableTypeTable) \
- /*(end)*/
+ F(CODE_ATTR_StackMapTable, StackMapTable) F(CODE_ATTR_LineNumberTable, LineNumberTable) \
+ F(CODE_ATTR_LocalVariableTable, LocalVariableTable) \
+ F(CODE_ATTR_LocalVariableTypeTable, LocalVariableTypeTable) \
+ /*(end)*/
#define ALL_ATTR_DO(F) \
- X_ATTR_DO(F) CLASS_ATTR_DO(F) FIELD_ATTR_DO(F) METHOD_ATTR_DO(F) CODE_ATTR_DO(F) \
- /*(end)*/
+ X_ATTR_DO(F) CLASS_ATTR_DO(F) FIELD_ATTR_DO(F) METHOD_ATTR_DO(F) CODE_ATTR_DO(F) \
+ /*(end)*/
- // attribute "context types"
- ATTR_CONTEXT_CLASS = 0,
- ATTR_CONTEXT_FIELD = 1,
- ATTR_CONTEXT_METHOD = 2,
- ATTR_CONTEXT_CODE = 3,
- ATTR_CONTEXT_LIMIT = 4,
+ // attribute "context types"
+ ATTR_CONTEXT_CLASS = 0,
+ ATTR_CONTEXT_FIELD = 1,
+ ATTR_CONTEXT_METHOD = 2,
+ ATTR_CONTEXT_CODE = 3,
+ ATTR_CONTEXT_LIMIT = 4,
- // constants for parsed layouts (stored in band::le_kind)
- EK_NONE = 0, // not a layout element
- EK_INT = 'I', // B H I SH etc., also FH etc.
- EK_BCI = 'P', // PH etc.
- EK_BCID = 'Q', // POH etc.
- EK_BCO = 'O', // OH etc.
- EK_REPL = 'N', // NH[...] etc.
- EK_REF = 'R', // RUH, RUNH, KQH, etc.
- EK_UN = 'T', // TB(...)[...] etc.
- EK_CASE = 'K', // (...)[...] etc.
- EK_CALL = '(', // (0), (1), etc.
- EK_CBLE = '[', // [...][...] etc.
- NO_BAND_INDEX = -1,
+ // constants for parsed layouts (stored in band::le_kind)
+ EK_NONE = 0, // not a layout element
+ EK_INT = 'I', // B H I SH etc., also FH etc.
+ EK_BCI = 'P', // PH etc.
+ EK_BCID = 'Q', // POH etc.
+ EK_BCO = 'O', // OH etc.
+ EK_REPL = 'N', // NH[...] etc.
+ EK_REF = 'R', // RUH, RUNH, KQH, etc.
+ EK_UN = 'T', // TB(...)[...] etc.
+ EK_CASE = 'K', // (...)[...] etc.
+ EK_CALL = '(', // (0), (1), etc.
+ EK_CBLE = '[', // [...][...] etc.
+ NO_BAND_INDEX = -1,
- // File option bits, from LSB in ascending bit position.
- FO_DEFLATE_HINT = 1 << 0,
- FO_IS_CLASS_STUB = 1 << 1,
+ // File option bits, from LSB in ascending bit position.
+ FO_DEFLATE_HINT = 1 << 0,
+ FO_IS_CLASS_STUB = 1 << 1,
- // Archive option bits, from LSB in ascending bit position:
- AO_HAVE_SPECIAL_FORMATS = 1 << 0,
- AO_HAVE_CP_NUMBERS = 1 << 1,
- AO_HAVE_ALL_CODE_FLAGS = 1 << 2,
- AO_3_UNUSED_MBZ = 1 << 3,
- AO_HAVE_FILE_HEADERS = 1 << 4,
- AO_DEFLATE_HINT = 1 << 5,
- AO_HAVE_FILE_MODTIME = 1 << 6,
- AO_HAVE_FILE_OPTIONS = 1 << 7,
- AO_HAVE_FILE_SIZE_HI = 1 << 8,
- AO_HAVE_CLASS_FLAGS_HI = 1 << 9,
- AO_HAVE_FIELD_FLAGS_HI = 1 << 10,
- AO_HAVE_METHOD_FLAGS_HI = 1 << 11,
- AO_HAVE_CODE_FLAGS_HI = 1 << 12,
+ // Archive option bits, from LSB in ascending bit position:
+ AO_HAVE_SPECIAL_FORMATS = 1 << 0,
+ AO_HAVE_CP_NUMBERS = 1 << 1,
+ AO_HAVE_ALL_CODE_FLAGS = 1 << 2,
+ AO_3_UNUSED_MBZ = 1 << 3,
+ AO_HAVE_FILE_HEADERS = 1 << 4,
+ AO_DEFLATE_HINT = 1 << 5,
+ AO_HAVE_FILE_MODTIME = 1 << 6,
+ AO_HAVE_FILE_OPTIONS = 1 << 7,
+ AO_HAVE_FILE_SIZE_HI = 1 << 8,
+ AO_HAVE_CLASS_FLAGS_HI = 1 << 9,
+ AO_HAVE_FIELD_FLAGS_HI = 1 << 10,
+ AO_HAVE_METHOD_FLAGS_HI = 1 << 11,
+ AO_HAVE_CODE_FLAGS_HI = 1 << 12,
#define ARCHIVE_BIT_DO(F) \
- F(AO_HAVE_SPECIAL_FORMATS) F(AO_HAVE_CP_NUMBERS) F(AO_HAVE_ALL_CODE_FLAGS) \
- /*F(AO_3_UNUSED_MBZ)*/ \
- F(AO_HAVE_FILE_HEADERS) F(AO_DEFLATE_HINT) F(AO_HAVE_FILE_MODTIME) \
- F(AO_HAVE_FILE_OPTIONS) F(AO_HAVE_FILE_SIZE_HI) F(AO_HAVE_CLASS_FLAGS_HI) \
- F(AO_HAVE_FIELD_FLAGS_HI) F(AO_HAVE_METHOD_FLAGS_HI) F(AO_HAVE_CODE_FLAGS_HI) \
- /*(end)*/
+ F(AO_HAVE_SPECIAL_FORMATS) F(AO_HAVE_CP_NUMBERS) F(AO_HAVE_ALL_CODE_FLAGS) \
+ /*F(AO_3_UNUSED_MBZ)*/ \
+ F(AO_HAVE_FILE_HEADERS) F(AO_DEFLATE_HINT) F(AO_HAVE_FILE_MODTIME) \
+ F(AO_HAVE_FILE_OPTIONS) F(AO_HAVE_FILE_SIZE_HI) F(AO_HAVE_CLASS_FLAGS_HI) \
+ F(AO_HAVE_FIELD_FLAGS_HI) F(AO_HAVE_METHOD_FLAGS_HI) F(AO_HAVE_CODE_FLAGS_HI) \
+ /*(end)*/
- // Constants for decoding attribute definition header bytes.
- ADH_CONTEXT_MASK = 0x3, // (hdr & ADH_CONTEXT_MASK)
- ADH_BIT_SHIFT = 0x2, // (hdr >> ADH_BIT_SHIFT)
- ADH_BIT_IS_LSB = 1, // (hdr >> ADH_BIT_SHIFT) - ADH_BIT_IS_LSB
+ // Constants for decoding attribute definition header bytes.
+ ADH_CONTEXT_MASK = 0x3, // (hdr & ADH_CONTEXT_MASK)
+ ADH_BIT_SHIFT = 0x2, // (hdr >> ADH_BIT_SHIFT)
+ ADH_BIT_IS_LSB = 1, // (hdr >> ADH_BIT_SHIFT) - ADH_BIT_IS_LSB
#define ADH_BYTE(context, index) ((((index) + ADH_BIT_IS_LSB) << ADH_BIT_SHIFT) + (context))
#define ADH_BYTE_CONTEXT(adhb) ((adhb) & ADH_CONTEXT_MASK)
#define ADH_BYTE_INDEX(adhb) (((adhb) >> ADH_BIT_SHIFT) - ADH_BIT_IS_LSB)
- NO_MODTIME = 0, // nullptr modtime value
+ NO_MODTIME = 0, // nullptr modtime value
- // meta-coding
- _meta_default = 0,
- _meta_canon_min = 1,
- _meta_canon_max = 115,
- _meta_arb = 116,
- _meta_run = 117,
- _meta_pop = 141,
- _meta_limit = 189,
- _meta_error = 255,
- _xxx_1_end
+ // meta-coding
+ _meta_default = 0,
+ _meta_canon_min = 1,
+ _meta_canon_max = 115,
+ _meta_arb = 116,
+ _meta_run = 117,
+ _meta_pop = 141,
+ _meta_limit = 189,
+ _meta_error = 255,
+ _xxx_1_end
};
// Bytecodes.
enum
{
- bc_nop = 0, // 0x00
- bc_aconst_null = 1, // 0x01
- bc_iconst_m1 = 2, // 0x02
- bc_iconst_0 = 3, // 0x03
- bc_iconst_1 = 4, // 0x04
- bc_iconst_2 = 5, // 0x05
- bc_iconst_3 = 6, // 0x06
- bc_iconst_4 = 7, // 0x07
- bc_iconst_5 = 8, // 0x08
- bc_lconst_0 = 9, // 0x09
- bc_lconst_1 = 10, // 0x0a
- bc_fconst_0 = 11, // 0x0b
- bc_fconst_1 = 12, // 0x0c
- bc_fconst_2 = 13, // 0x0d
- bc_dconst_0 = 14, // 0x0e
- bc_dconst_1 = 15, // 0x0f
- bc_bipush = 16, // 0x10
- bc_sipush = 17, // 0x11
- bc_ldc = 18, // 0x12
- bc_ldc_w = 19, // 0x13
- bc_ldc2_w = 20, // 0x14
- bc_iload = 21, // 0x15
- bc_lload = 22, // 0x16
- bc_fload = 23, // 0x17
- bc_dload = 24, // 0x18
- bc_aload = 25, // 0x19
- bc_iload_0 = 26, // 0x1a
- bc_iload_1 = 27, // 0x1b
- bc_iload_2 = 28, // 0x1c
- bc_iload_3 = 29, // 0x1d
- bc_lload_0 = 30, // 0x1e
- bc_lload_1 = 31, // 0x1f
- bc_lload_2 = 32, // 0x20
- bc_lload_3 = 33, // 0x21
- bc_fload_0 = 34, // 0x22
- bc_fload_1 = 35, // 0x23
- bc_fload_2 = 36, // 0x24
- bc_fload_3 = 37, // 0x25
- bc_dload_0 = 38, // 0x26
- bc_dload_1 = 39, // 0x27
- bc_dload_2 = 40, // 0x28
- bc_dload_3 = 41, // 0x29
- bc_aload_0 = 42, // 0x2a
- bc_aload_1 = 43, // 0x2b
- bc_aload_2 = 44, // 0x2c
- bc_aload_3 = 45, // 0x2d
- bc_iaload = 46, // 0x2e
- bc_laload = 47, // 0x2f
- bc_faload = 48, // 0x30
- bc_daload = 49, // 0x31
- bc_aaload = 50, // 0x32
- bc_baload = 51, // 0x33
- bc_caload = 52, // 0x34
- bc_saload = 53, // 0x35
- bc_istore = 54, // 0x36
- bc_lstore = 55, // 0x37
- bc_fstore = 56, // 0x38
- bc_dstore = 57, // 0x39
- bc_astore = 58, // 0x3a
- bc_istore_0 = 59, // 0x3b
- bc_istore_1 = 60, // 0x3c
- bc_istore_2 = 61, // 0x3d
- bc_istore_3 = 62, // 0x3e
- bc_lstore_0 = 63, // 0x3f
- bc_lstore_1 = 64, // 0x40
- bc_lstore_2 = 65, // 0x41
- bc_lstore_3 = 66, // 0x42
- bc_fstore_0 = 67, // 0x43
- bc_fstore_1 = 68, // 0x44
- bc_fstore_2 = 69, // 0x45
- bc_fstore_3 = 70, // 0x46
- bc_dstore_0 = 71, // 0x47
- bc_dstore_1 = 72, // 0x48
- bc_dstore_2 = 73, // 0x49
- bc_dstore_3 = 74, // 0x4a
- bc_astore_0 = 75, // 0x4b
- bc_astore_1 = 76, // 0x4c
- bc_astore_2 = 77, // 0x4d
- bc_astore_3 = 78, // 0x4e
- bc_iastore = 79, // 0x4f
- bc_lastore = 80, // 0x50
- bc_fastore = 81, // 0x51
- bc_dastore = 82, // 0x52
- bc_aastore = 83, // 0x53
- bc_bastore = 84, // 0x54
- bc_castore = 85, // 0x55
- bc_sastore = 86, // 0x56
- bc_pop = 87, // 0x57
- bc_pop2 = 88, // 0x58
- bc_dup = 89, // 0x59
- bc_dup_x1 = 90, // 0x5a
- bc_dup_x2 = 91, // 0x5b
- bc_dup2 = 92, // 0x5c
- bc_dup2_x1 = 93, // 0x5d
- bc_dup2_x2 = 94, // 0x5e
- bc_swap = 95, // 0x5f
- bc_iadd = 96, // 0x60
- bc_ladd = 97, // 0x61
- bc_fadd = 98, // 0x62
- bc_dadd = 99, // 0x63
- bc_isub = 100, // 0x64
- bc_lsub = 101, // 0x65
- bc_fsub = 102, // 0x66
- bc_dsub = 103, // 0x67
- bc_imul = 104, // 0x68
- bc_lmul = 105, // 0x69
- bc_fmul = 106, // 0x6a
- bc_dmul = 107, // 0x6b
- bc_idiv = 108, // 0x6c
- bc_ldiv = 109, // 0x6d
- bc_fdiv = 110, // 0x6e
- bc_ddiv = 111, // 0x6f
- bc_irem = 112, // 0x70
- bc_lrem = 113, // 0x71
- bc_frem = 114, // 0x72
- bc_drem = 115, // 0x73
- bc_ineg = 116, // 0x74
- bc_lneg = 117, // 0x75
- bc_fneg = 118, // 0x76
- bc_dneg = 119, // 0x77
- bc_ishl = 120, // 0x78
- bc_lshl = 121, // 0x79
- bc_ishr = 122, // 0x7a
- bc_lshr = 123, // 0x7b
- bc_iushr = 124, // 0x7c
- bc_lushr = 125, // 0x7d
- bc_iand = 126, // 0x7e
- bc_land = 127, // 0x7f
- bc_ior = 128, // 0x80
- bc_lor = 129, // 0x81
- bc_ixor = 130, // 0x82
- bc_lxor = 131, // 0x83
- bc_iinc = 132, // 0x84
- bc_i2l = 133, // 0x85
- bc_i2f = 134, // 0x86
- bc_i2d = 135, // 0x87
- bc_l2i = 136, // 0x88
- bc_l2f = 137, // 0x89
- bc_l2d = 138, // 0x8a
- bc_f2i = 139, // 0x8b
- bc_f2l = 140, // 0x8c
- bc_f2d = 141, // 0x8d
- bc_d2i = 142, // 0x8e
- bc_d2l = 143, // 0x8f
- bc_d2f = 144, // 0x90
- bc_i2b = 145, // 0x91
- bc_i2c = 146, // 0x92
- bc_i2s = 147, // 0x93
- bc_lcmp = 148, // 0x94
- bc_fcmpl = 149, // 0x95
- bc_fcmpg = 150, // 0x96
- bc_dcmpl = 151, // 0x97
- bc_dcmpg = 152, // 0x98
- bc_ifeq = 153, // 0x99
- bc_ifne = 154, // 0x9a
- bc_iflt = 155, // 0x9b
- bc_ifge = 156, // 0x9c
- bc_ifgt = 157, // 0x9d
- bc_ifle = 158, // 0x9e
- bc_if_icmpeq = 159, // 0x9f
- bc_if_icmpne = 160, // 0xa0
- bc_if_icmplt = 161, // 0xa1
- bc_if_icmpge = 162, // 0xa2
- bc_if_icmpgt = 163, // 0xa3
- bc_if_icmple = 164, // 0xa4
- bc_if_acmpeq = 165, // 0xa5
- bc_if_acmpne = 166, // 0xa6
- bc_goto = 167, // 0xa7
- bc_jsr = 168, // 0xa8
- bc_ret = 169, // 0xa9
- bc_tableswitch = 170, // 0xaa
- bc_lookupswitch = 171, // 0xab
- bc_ireturn = 172, // 0xac
- bc_lreturn = 173, // 0xad
- bc_freturn = 174, // 0xae
- bc_dreturn = 175, // 0xaf
- bc_areturn = 176, // 0xb0
- bc_return = 177, // 0xb1
- bc_getstatic = 178, // 0xb2
- bc_putstatic = 179, // 0xb3
- bc_getfield = 180, // 0xb4
- bc_putfield = 181, // 0xb5
- bc_invokevirtual = 182, // 0xb6
- bc_invokespecial = 183, // 0xb7
- bc_invokestatic = 184, // 0xb8
- bc_invokeinterface = 185, // 0xb9
- bc_xxxunusedxxx = 186, // 0xba
- bc_new = 187, // 0xbb
- bc_newarray = 188, // 0xbc
- bc_anewarray = 189, // 0xbd
- bc_arraylength = 190, // 0xbe
- bc_athrow = 191, // 0xbf
- bc_checkcast = 192, // 0xc0
- bc_instanceof = 193, // 0xc1
- bc_monitorenter = 194, // 0xc2
- bc_monitorexit = 195, // 0xc3
- bc_wide = 196, // 0xc4
- bc_multianewarray = 197, // 0xc5
- bc_ifnull = 198, // 0xc6
- bc_ifnonnull = 199, // 0xc7
- bc_goto_w = 200, // 0xc8
- bc_jsr_w = 201, // 0xc9
- bc_bytecode_limit = 202 // 0xca
+ bc_nop = 0, // 0x00
+ bc_aconst_null = 1, // 0x01
+ bc_iconst_m1 = 2, // 0x02
+ bc_iconst_0 = 3, // 0x03
+ bc_iconst_1 = 4, // 0x04
+ bc_iconst_2 = 5, // 0x05
+ bc_iconst_3 = 6, // 0x06
+ bc_iconst_4 = 7, // 0x07
+ bc_iconst_5 = 8, // 0x08
+ bc_lconst_0 = 9, // 0x09
+ bc_lconst_1 = 10, // 0x0a
+ bc_fconst_0 = 11, // 0x0b
+ bc_fconst_1 = 12, // 0x0c
+ bc_fconst_2 = 13, // 0x0d
+ bc_dconst_0 = 14, // 0x0e
+ bc_dconst_1 = 15, // 0x0f
+ bc_bipush = 16, // 0x10
+ bc_sipush = 17, // 0x11
+ bc_ldc = 18, // 0x12
+ bc_ldc_w = 19, // 0x13
+ bc_ldc2_w = 20, // 0x14
+ bc_iload = 21, // 0x15
+ bc_lload = 22, // 0x16
+ bc_fload = 23, // 0x17
+ bc_dload = 24, // 0x18
+ bc_aload = 25, // 0x19
+ bc_iload_0 = 26, // 0x1a
+ bc_iload_1 = 27, // 0x1b
+ bc_iload_2 = 28, // 0x1c
+ bc_iload_3 = 29, // 0x1d
+ bc_lload_0 = 30, // 0x1e
+ bc_lload_1 = 31, // 0x1f
+ bc_lload_2 = 32, // 0x20
+ bc_lload_3 = 33, // 0x21
+ bc_fload_0 = 34, // 0x22
+ bc_fload_1 = 35, // 0x23
+ bc_fload_2 = 36, // 0x24
+ bc_fload_3 = 37, // 0x25
+ bc_dload_0 = 38, // 0x26
+ bc_dload_1 = 39, // 0x27
+ bc_dload_2 = 40, // 0x28
+ bc_dload_3 = 41, // 0x29
+ bc_aload_0 = 42, // 0x2a
+ bc_aload_1 = 43, // 0x2b
+ bc_aload_2 = 44, // 0x2c
+ bc_aload_3 = 45, // 0x2d
+ bc_iaload = 46, // 0x2e
+ bc_laload = 47, // 0x2f
+ bc_faload = 48, // 0x30
+ bc_daload = 49, // 0x31
+ bc_aaload = 50, // 0x32
+ bc_baload = 51, // 0x33
+ bc_caload = 52, // 0x34
+ bc_saload = 53, // 0x35
+ bc_istore = 54, // 0x36
+ bc_lstore = 55, // 0x37
+ bc_fstore = 56, // 0x38
+ bc_dstore = 57, // 0x39
+ bc_astore = 58, // 0x3a
+ bc_istore_0 = 59, // 0x3b
+ bc_istore_1 = 60, // 0x3c
+ bc_istore_2 = 61, // 0x3d
+ bc_istore_3 = 62, // 0x3e
+ bc_lstore_0 = 63, // 0x3f
+ bc_lstore_1 = 64, // 0x40
+ bc_lstore_2 = 65, // 0x41
+ bc_lstore_3 = 66, // 0x42
+ bc_fstore_0 = 67, // 0x43
+ bc_fstore_1 = 68, // 0x44
+ bc_fstore_2 = 69, // 0x45
+ bc_fstore_3 = 70, // 0x46
+ bc_dstore_0 = 71, // 0x47
+ bc_dstore_1 = 72, // 0x48
+ bc_dstore_2 = 73, // 0x49
+ bc_dstore_3 = 74, // 0x4a
+ bc_astore_0 = 75, // 0x4b
+ bc_astore_1 = 76, // 0x4c
+ bc_astore_2 = 77, // 0x4d
+ bc_astore_3 = 78, // 0x4e
+ bc_iastore = 79, // 0x4f
+ bc_lastore = 80, // 0x50
+ bc_fastore = 81, // 0x51
+ bc_dastore = 82, // 0x52
+ bc_aastore = 83, // 0x53
+ bc_bastore = 84, // 0x54
+ bc_castore = 85, // 0x55
+ bc_sastore = 86, // 0x56
+ bc_pop = 87, // 0x57
+ bc_pop2 = 88, // 0x58
+ bc_dup = 89, // 0x59
+ bc_dup_x1 = 90, // 0x5a
+ bc_dup_x2 = 91, // 0x5b
+ bc_dup2 = 92, // 0x5c
+ bc_dup2_x1 = 93, // 0x5d
+ bc_dup2_x2 = 94, // 0x5e
+ bc_swap = 95, // 0x5f
+ bc_iadd = 96, // 0x60
+ bc_ladd = 97, // 0x61
+ bc_fadd = 98, // 0x62
+ bc_dadd = 99, // 0x63
+ bc_isub = 100, // 0x64
+ bc_lsub = 101, // 0x65
+ bc_fsub = 102, // 0x66
+ bc_dsub = 103, // 0x67
+ bc_imul = 104, // 0x68
+ bc_lmul = 105, // 0x69
+ bc_fmul = 106, // 0x6a
+ bc_dmul = 107, // 0x6b
+ bc_idiv = 108, // 0x6c
+ bc_ldiv = 109, // 0x6d
+ bc_fdiv = 110, // 0x6e
+ bc_ddiv = 111, // 0x6f
+ bc_irem = 112, // 0x70
+ bc_lrem = 113, // 0x71
+ bc_frem = 114, // 0x72
+ bc_drem = 115, // 0x73
+ bc_ineg = 116, // 0x74
+ bc_lneg = 117, // 0x75
+ bc_fneg = 118, // 0x76
+ bc_dneg = 119, // 0x77
+ bc_ishl = 120, // 0x78
+ bc_lshl = 121, // 0x79
+ bc_ishr = 122, // 0x7a
+ bc_lshr = 123, // 0x7b
+ bc_iushr = 124, // 0x7c
+ bc_lushr = 125, // 0x7d
+ bc_iand = 126, // 0x7e
+ bc_land = 127, // 0x7f
+ bc_ior = 128, // 0x80
+ bc_lor = 129, // 0x81
+ bc_ixor = 130, // 0x82
+ bc_lxor = 131, // 0x83
+ bc_iinc = 132, // 0x84
+ bc_i2l = 133, // 0x85
+ bc_i2f = 134, // 0x86
+ bc_i2d = 135, // 0x87
+ bc_l2i = 136, // 0x88
+ bc_l2f = 137, // 0x89
+ bc_l2d = 138, // 0x8a
+ bc_f2i = 139, // 0x8b
+ bc_f2l = 140, // 0x8c
+ bc_f2d = 141, // 0x8d
+ bc_d2i = 142, // 0x8e
+ bc_d2l = 143, // 0x8f
+ bc_d2f = 144, // 0x90
+ bc_i2b = 145, // 0x91
+ bc_i2c = 146, // 0x92
+ bc_i2s = 147, // 0x93
+ bc_lcmp = 148, // 0x94
+ bc_fcmpl = 149, // 0x95
+ bc_fcmpg = 150, // 0x96
+ bc_dcmpl = 151, // 0x97
+ bc_dcmpg = 152, // 0x98
+ bc_ifeq = 153, // 0x99
+ bc_ifne = 154, // 0x9a
+ bc_iflt = 155, // 0x9b
+ bc_ifge = 156, // 0x9c
+ bc_ifgt = 157, // 0x9d
+ bc_ifle = 158, // 0x9e
+ bc_if_icmpeq = 159, // 0x9f
+ bc_if_icmpne = 160, // 0xa0
+ bc_if_icmplt = 161, // 0xa1
+ bc_if_icmpge = 162, // 0xa2
+ bc_if_icmpgt = 163, // 0xa3
+ bc_if_icmple = 164, // 0xa4
+ bc_if_acmpeq = 165, // 0xa5
+ bc_if_acmpne = 166, // 0xa6
+ bc_goto = 167, // 0xa7
+ bc_jsr = 168, // 0xa8
+ bc_ret = 169, // 0xa9
+ bc_tableswitch = 170, // 0xaa
+ bc_lookupswitch = 171, // 0xab
+ bc_ireturn = 172, // 0xac
+ bc_lreturn = 173, // 0xad
+ bc_freturn = 174, // 0xae
+ bc_dreturn = 175, // 0xaf
+ bc_areturn = 176, // 0xb0
+ bc_return = 177, // 0xb1
+ bc_getstatic = 178, // 0xb2
+ bc_putstatic = 179, // 0xb3
+ bc_getfield = 180, // 0xb4
+ bc_putfield = 181, // 0xb5
+ bc_invokevirtual = 182, // 0xb6
+ bc_invokespecial = 183, // 0xb7
+ bc_invokestatic = 184, // 0xb8
+ bc_invokeinterface = 185, // 0xb9
+ bc_xxxunusedxxx = 186, // 0xba
+ bc_new = 187, // 0xbb
+ bc_newarray = 188, // 0xbc
+ bc_anewarray = 189, // 0xbd
+ bc_arraylength = 190, // 0xbe
+ bc_athrow = 191, // 0xbf
+ bc_checkcast = 192, // 0xc0
+ bc_instanceof = 193, // 0xc1
+ bc_monitorenter = 194, // 0xc2
+ bc_monitorexit = 195, // 0xc3
+ bc_wide = 196, // 0xc4
+ bc_multianewarray = 197, // 0xc5
+ bc_ifnull = 198, // 0xc6
+ bc_ifnonnull = 199, // 0xc7
+ bc_goto_w = 200, // 0xc8
+ bc_jsr_w = 201, // 0xc9
+ bc_bytecode_limit = 202 // 0xca
};
enum
{
- bc_end_marker = 255,
- bc_byte_escape = 254,
- bc_ref_escape = 253,
- _first_linker_op = bc_getstatic,
- _last_linker_op = bc_invokestatic,
- _num_linker_ops = (_last_linker_op - _first_linker_op) + 1,
- _self_linker_op = bc_bytecode_limit,
- _self_linker_aload_flag = 1 * _num_linker_ops,
- _self_linker_super_flag = 2 * _num_linker_ops,
- _self_linker_limit = _self_linker_op + 4 * _num_linker_ops,
- _invokeinit_op = _self_linker_limit,
- _invokeinit_self_option = 0,
- _invokeinit_super_option = 1,
- _invokeinit_new_option = 2,
- _invokeinit_limit = _invokeinit_op + 3,
- _xldc_op = _invokeinit_limit,
- bc_aldc = bc_ldc,
- bc_cldc = _xldc_op + 0,
- bc_ildc = _xldc_op + 1,
- bc_fldc = _xldc_op + 2,
- bc_aldc_w = bc_ldc_w,
- bc_cldc_w = _xldc_op + 3,
- bc_ildc_w = _xldc_op + 4,
- bc_fldc_w = _xldc_op + 5,
- bc_lldc2_w = bc_ldc2_w,
- bc_dldc2_w = _xldc_op + 6,
- _xldc_limit = _xldc_op + 7,
- _xxx_3_end
+ bc_end_marker = 255,
+ bc_byte_escape = 254,
+ bc_ref_escape = 253,
+ _first_linker_op = bc_getstatic,
+ _last_linker_op = bc_invokestatic,
+ _num_linker_ops = (_last_linker_op - _first_linker_op) + 1,
+ _self_linker_op = bc_bytecode_limit,
+ _self_linker_aload_flag = 1 * _num_linker_ops,
+ _self_linker_super_flag = 2 * _num_linker_ops,
+ _self_linker_limit = _self_linker_op + 4 * _num_linker_ops,
+ _invokeinit_op = _self_linker_limit,
+ _invokeinit_self_option = 0,
+ _invokeinit_super_option = 1,
+ _invokeinit_new_option = 2,
+ _invokeinit_limit = _invokeinit_op + 3,
+ _xldc_op = _invokeinit_limit,
+ bc_aldc = bc_ldc,
+ bc_cldc = _xldc_op + 0,
+ bc_ildc = _xldc_op + 1,
+ bc_fldc = _xldc_op + 2,
+ bc_aldc_w = bc_ldc_w,
+ bc_cldc_w = _xldc_op + 3,
+ bc_ildc_w = _xldc_op + 4,
+ bc_fldc_w = _xldc_op + 5,
+ bc_lldc2_w = bc_ldc2_w,
+ bc_dldc2_w = _xldc_op + 6,
+ _xldc_limit = _xldc_op + 7,
+ _xxx_3_end
};
diff --git a/libraries/pack200/src/unpack.cpp b/libraries/pack200/src/unpack.cpp
index 55d253b2..9c4c633c 100644
--- a/libraries/pack200/src/unpack.cpp
+++ b/libraries/pack200/src/unpack.cpp
@@ -34,13 +34,7 @@
* _LP64 can be explicitly set (used on Linux).
* Solaris compilers will define __sparcv9 or __x86_64 on 64bit compilations.
*/
-#if defined(_LP64) || defined(__sparcv9) || defined(__x86_64)
-#define LONG_LONG_FORMAT "%ld"
-#define LONG_LONG_HEX_FORMAT "%lx"
-#else
-#define LONG_LONG_FORMAT "%lld"
-#define LONG_LONG_HEX_FORMAT "%016llx"
-#endif
+#include <cinttypes>
#include <sys/types.h>
@@ -67,248 +61,248 @@
// tags, in canonical order:
static const byte TAGS_IN_ORDER[] = {
- CONSTANT_Utf8, CONSTANT_Integer, CONSTANT_Float, CONSTANT_Long,
- CONSTANT_Double, CONSTANT_String, CONSTANT_Class, CONSTANT_Signature,
- CONSTANT_NameandType, CONSTANT_Fieldref, CONSTANT_Methodref, CONSTANT_InterfaceMethodref};
+ CONSTANT_Utf8, CONSTANT_Integer, CONSTANT_Float, CONSTANT_Long,
+ CONSTANT_Double, CONSTANT_String, CONSTANT_Class, CONSTANT_Signature,
+ CONSTANT_NameandType, CONSTANT_Fieldref, CONSTANT_Methodref, CONSTANT_InterfaceMethodref};
#define N_TAGS_IN_ORDER (sizeof TAGS_IN_ORDER)
// REQUESTED must be -2 for u2 and REQUESTED_LDC must be -1 for u1
enum
{
- NOT_REQUESTED = 0,
- REQUESTED = -2,
- REQUESTED_LDC = -1
+ NOT_REQUESTED = 0,
+ REQUESTED = -2,
+ REQUESTED_LDC = -1
};
#define NO_INORD ((uint32_t) - 1)
struct entry
{
- byte tag;
- unsigned short nrefs; // pack w/ tag
-
- int outputIndex;
- uint32_t inord; // &cp.entries[cp.tag_base[this->tag]+this->inord] == this
-
- entry **refs;
-
- // put last to pack best
- union
- {
- bytes b;
- int i;
- int64_t l;
- } value;
-
- void requestOutputIndex(constant_pool &cp, int req = REQUESTED);
- int getOutputIndex()
- {
- assert(outputIndex > NOT_REQUESTED);
- return outputIndex;
- }
-
- entry *ref(int refnum)
- {
- assert((uint32_t)refnum < nrefs);
- return refs[refnum];
- }
-
- const char *utf8String()
- {
- assert(tagMatches(CONSTANT_Utf8));
- assert(value.b.len == strlen((const char *)value.b.ptr));
- return (const char *)value.b.ptr;
- }
-
- entry *className()
- {
- assert(tagMatches(CONSTANT_Class));
- return ref(0);
- }
-
- entry *memberClass()
- {
- assert(tagMatches(CONSTANT_Member));
- return ref(0);
- }
-
- entry *memberDescr()
- {
- assert(tagMatches(CONSTANT_Member));
- return ref(1);
- }
-
- entry *descrName()
- {
- assert(tagMatches(CONSTANT_NameandType));
- return ref(0);
- }
-
- entry *descrType()
- {
- assert(tagMatches(CONSTANT_NameandType));
- return ref(1);
- }
-
- int typeSize();
-
- bytes &asUtf8();
- int asInteger()
- {
- assert(tag == CONSTANT_Integer);
- return value.i;
- }
-
- bool isUtf8(bytes &b)
- {
- return tagMatches(CONSTANT_Utf8) && value.b.equals(b);
- }
-
- bool isDoubleWord()
- {
- return tag == CONSTANT_Double || tag == CONSTANT_Long;
- }
-
- bool tagMatches(byte tag2)
- {
- return (tag2 == tag) || (tag2 == CONSTANT_Utf8 && tag == CONSTANT_Signature) ||
- (tag2 == CONSTANT_Literal && tag >= CONSTANT_Integer && tag <= CONSTANT_String &&
- tag != CONSTANT_Class) ||
- (tag2 == CONSTANT_Member && tag >= CONSTANT_Fieldref &&
- tag <= CONSTANT_InterfaceMethodref);
- }
+ byte tag;
+ unsigned short nrefs; // pack w/ tag
+
+ int outputIndex;
+ uint32_t inord; // &cp.entries[cp.tag_base[this->tag]+this->inord] == this
+
+ entry **refs;
+
+ // put last to pack best
+ union
+ {
+ bytes b;
+ int i;
+ int64_t l;
+ } value;
+
+ void requestOutputIndex(constant_pool &cp, int req = REQUESTED);
+ int getOutputIndex()
+ {
+ assert(outputIndex > NOT_REQUESTED);
+ return outputIndex;
+ }
+
+ entry *ref(int refnum)
+ {
+ assert((uint32_t)refnum < nrefs);
+ return refs[refnum];
+ }
+
+ const char *utf8String()
+ {
+ assert(tagMatches(CONSTANT_Utf8));
+ assert(value.b.len == strlen((const char *)value.b.ptr));
+ return (const char *)value.b.ptr;
+ }
+
+ entry *className()
+ {
+ assert(tagMatches(CONSTANT_Class));
+ return ref(0);
+ }
+
+ entry *memberClass()
+ {
+ assert(tagMatches(CONSTANT_Member));
+ return ref(0);
+ }
+
+ entry *memberDescr()
+ {
+ assert(tagMatches(CONSTANT_Member));
+ return ref(1);
+ }
+
+ entry *descrName()
+ {
+ assert(tagMatches(CONSTANT_NameandType));
+ return ref(0);
+ }
+
+ entry *descrType()
+ {
+ assert(tagMatches(CONSTANT_NameandType));
+ return ref(1);
+ }
+
+ int typeSize();
+
+ bytes &asUtf8();
+ int asInteger()
+ {
+ assert(tag == CONSTANT_Integer);
+ return value.i;
+ }
+
+ bool isUtf8(bytes &b)
+ {
+ return tagMatches(CONSTANT_Utf8) && value.b.equals(b);
+ }
+
+ bool isDoubleWord()
+ {
+ return tag == CONSTANT_Double || tag == CONSTANT_Long;
+ }
+
+ bool tagMatches(byte tag2)
+ {
+ return (tag2 == tag) || (tag2 == CONSTANT_Utf8 && tag == CONSTANT_Signature) ||
+ (tag2 == CONSTANT_Literal && tag >= CONSTANT_Integer && tag <= CONSTANT_String &&
+ tag != CONSTANT_Class) ||
+ (tag2 == CONSTANT_Member && tag >= CONSTANT_Fieldref &&
+ tag <= CONSTANT_InterfaceMethodref);
+ }
};
entry *cpindex::get(uint32_t i)
{
- if (i >= len)
- return nullptr;
- else if (base1 != nullptr)
- // primary index
- return &base1[i];
- else
- // secondary index
- return base2[i];
+ if (i >= len)
+ return nullptr;
+ else if (base1 != nullptr)
+ // primary index
+ return &base1[i];
+ else
+ // secondary index
+ return base2[i];
}
inline bytes &entry::asUtf8()
{
- assert(tagMatches(CONSTANT_Utf8));
- return value.b;
+ assert(tagMatches(CONSTANT_Utf8));
+ return value.b;
}
int entry::typeSize()
{
- assert(tagMatches(CONSTANT_Utf8));
- const char *sigp = (char *)value.b.ptr;
- switch (*sigp)
- {
- case '(':
- sigp++;
- break; // skip opening '('
- case 'D':
- case 'J':
- return 2; // double field
- default:
- return 1; // field
- }
- int siglen = 0;
- for (;;)
- {
- int ch = *sigp++;
- switch (ch)
- {
- case 'D':
- case 'J':
- siglen += 1;
- break;
- case '[':
- // Skip rest of array info.
- while (ch == '[')
- {
- ch = *sigp++;
- }
- if (ch != 'L')
- break;
- // else fall through
- case 'L':
- sigp = strchr(sigp, ';');
- if (sigp == nullptr)
- {
- unpack_abort("bad data");
- return 0;
- }
- sigp += 1;
- break;
- case ')': // closing ')'
- return siglen;
- }
- siglen += 1;
- }
+ assert(tagMatches(CONSTANT_Utf8));
+ const char *sigp = (char *)value.b.ptr;
+ switch (*sigp)
+ {
+ case '(':
+ sigp++;
+ break; // skip opening '('
+ case 'D':
+ case 'J':
+ return 2; // double field
+ default:
+ return 1; // field
+ }
+ int siglen = 0;
+ for (;;)
+ {
+ int ch = *sigp++;
+ switch (ch)
+ {
+ case 'D':
+ case 'J':
+ siglen += 1;
+ break;
+ case '[':
+ // Skip rest of array info.
+ while (ch == '[')
+ {
+ ch = *sigp++;
+ }
+ if (ch != 'L')
+ break;
+ // else fall through
+ case 'L':
+ sigp = strchr(sigp, ';');
+ if (sigp == nullptr)
+ {
+ unpack_abort("bad data");
+ return 0;
+ }
+ sigp += 1;
+ break;
+ case ')': // closing ')'
+ return siglen;
+ }
+ siglen += 1;
+ }
}
inline cpindex *constant_pool::getFieldIndex(entry *classRef)
{
- assert(classRef->tagMatches(CONSTANT_Class));
- assert((uint32_t)classRef->inord < (uint32_t)tag_count[CONSTANT_Class]);
- return &member_indexes[classRef->inord * 2 + 0];
+ assert(classRef->tagMatches(CONSTANT_Class));
+ assert((uint32_t)classRef->inord < (uint32_t)tag_count[CONSTANT_Class]);
+ return &member_indexes[classRef->inord * 2 + 0];
}
inline cpindex *constant_pool::getMethodIndex(entry *classRef)
{
- assert(classRef->tagMatches(CONSTANT_Class));
- assert((uint32_t)classRef->inord < (uint32_t)tag_count[CONSTANT_Class]);
- return &member_indexes[classRef->inord * 2 + 1];
+ assert(classRef->tagMatches(CONSTANT_Class));
+ assert((uint32_t)classRef->inord < (uint32_t)tag_count[CONSTANT_Class]);
+ return &member_indexes[classRef->inord * 2 + 1];
}
struct inner_class
{
- entry *inner;
- entry *outer;
- entry *name;
- int flags;
- inner_class *next_sibling;
- bool requested;
+ entry *inner;
+ entry *outer;
+ entry *name;
+ int flags;
+ inner_class *next_sibling;
+ bool requested;
};
// Here is where everything gets deallocated:
void unpacker::free()
{
- int i;
- if (jarout != nullptr)
- jarout->reset();
- if (gzin != nullptr)
- {
- gzin->free();
- gzin = nullptr;
- }
- if (free_input)
- input.free();
- /*
- * free everybody ever allocated with U_NEW or (recently) with T_NEW
- */
- assert(smallbuf.base() == nullptr || mallocs.contains(smallbuf.base()));
- assert(tsmallbuf.base() == nullptr || tmallocs.contains(tsmallbuf.base()));
- mallocs.freeAll();
- tmallocs.freeAll();
- smallbuf.init();
- tsmallbuf.init();
- bcimap.free();
- class_fixup_type.free();
- class_fixup_offset.free();
- class_fixup_ref.free();
- code_fixup_type.free();
- code_fixup_offset.free();
- code_fixup_source.free();
- requested_ics.free();
- cur_classfile_head.free();
- cur_classfile_tail.free();
- for (i = 0; i < ATTR_CONTEXT_LIMIT; i++)
- attr_defs[i].free();
-
- // free CP state
- cp.outputEntries.free();
- for (i = 0; i < CONSTANT_Limit; i++)
- cp.tag_extras[i].free();
+ int i;
+ if (jarout != nullptr)
+ jarout->reset();
+ if (gzin != nullptr)
+ {
+ gzin->free();
+ gzin = nullptr;
+ }
+ if (free_input)
+ input.free();
+ /*
+ * free everybody ever allocated with U_NEW or (recently) with T_NEW
+ */
+ assert(smallbuf.base() == nullptr || mallocs.contains(smallbuf.base()));
+ assert(tsmallbuf.base() == nullptr || tmallocs.contains(tsmallbuf.base()));
+ mallocs.freeAll();
+ tmallocs.freeAll();
+ smallbuf.init();
+ tsmallbuf.init();
+ bcimap.free();
+ class_fixup_type.free();
+ class_fixup_offset.free();
+ class_fixup_ref.free();
+ code_fixup_type.free();
+ code_fixup_offset.free();
+ code_fixup_source.free();
+ requested_ics.free();
+ cur_classfile_head.free();
+ cur_classfile_tail.free();
+ for (i = 0; i < ATTR_CONTEXT_LIMIT; i++)
+ attr_defs[i].free();
+
+ // free CP state
+ cp.outputEntries.free();
+ for (i = 0; i < CONSTANT_Limit; i++)
+ cp.tag_extras[i].free();
}
// input handling
@@ -318,1933 +312,1933 @@ void unpacker::free()
// unless rplimit hits input.limit().
bool unpacker::ensure_input(int64_t more)
{
- uint64_t want = more - input_remaining();
- if ((int64_t)want <= 0)
- return true; // it's already in the buffer
- if (rplimit == input.limit())
- return true; // not expecting any more
-
- if (read_input_fn == nullptr)
- {
- // assume it is already all there
- bytes_read += input.limit() - rplimit;
- rplimit = input.limit();
- return true;
- }
-
- uint64_t remaining = (input.limit() - rplimit); // how much left to read?
- byte *rpgoal = (want >= remaining) ? input.limit() : rplimit + (size_t)want;
- enum
- {
- CHUNK_SIZE = (1 << 14)
- };
- uint64_t fetch = want;
- if (fetch < CHUNK_SIZE)
- fetch = CHUNK_SIZE;
- if (fetch > remaining * 3 / 4)
- fetch = remaining;
- // Try to fetch at least "more" bytes.
- while ((int64_t)fetch > 0)
- {
- int64_t nr = (*read_input_fn)(this, rplimit, fetch, remaining);
- if (nr <= 0)
- {
- return (rplimit >= rpgoal);
- }
- remaining -= nr;
- rplimit += nr;
- fetch -= nr;
- bytes_read += nr;
- assert(remaining == (uint64_t)(input.limit() - rplimit));
- }
- return true;
+ uint64_t want = more - input_remaining();
+ if ((int64_t)want <= 0)
+ return true; // it's already in the buffer
+ if (rplimit == input.limit())
+ return true; // not expecting any more
+
+ if (read_input_fn == nullptr)
+ {
+ // assume it is already all there
+ bytes_read += input.limit() - rplimit;
+ rplimit = input.limit();
+ return true;
+ }
+
+ uint64_t remaining = (input.limit() - rplimit); // how much left to read?
+ byte *rpgoal = (want >= remaining) ? input.limit() : rplimit + (size_t)want;
+ enum
+ {
+ CHUNK_SIZE = (1 << 14)
+ };
+ uint64_t fetch = want;
+ if (fetch < CHUNK_SIZE)
+ fetch = CHUNK_SIZE;
+ if (fetch > remaining * 3 / 4)
+ fetch = remaining;
+ // Try to fetch at least "more" bytes.
+ while ((int64_t)fetch > 0)
+ {
+ int64_t nr = (*read_input_fn)(this, rplimit, fetch, remaining);
+ if (nr <= 0)
+ {
+ return (rplimit >= rpgoal);
+ }
+ remaining -= nr;
+ rplimit += nr;
+ fetch -= nr;
+ bytes_read += nr;
+ assert(remaining == (uint64_t)(input.limit() - rplimit));
+ }
+ return true;
}
// output handling
fillbytes *unpacker::close_output(fillbytes *which)
{
- assert(wp != nullptr);
- if (which == nullptr)
- {
- if (wpbase == cur_classfile_head.base())
- {
- which = &cur_classfile_head;
- }
- else
- {
- which = &cur_classfile_tail;
- }
- }
- assert(wpbase == which->base());
- assert(wplimit == which->end());
- which->setLimit(wp);
- wp = nullptr;
- wplimit = nullptr;
- // wpbase = nullptr;
- return which;
+ assert(wp != nullptr);
+ if (which == nullptr)
+ {
+ if (wpbase == cur_classfile_head.base())
+ {
+ which = &cur_classfile_head;
+ }
+ else
+ {
+ which = &cur_classfile_tail;
+ }
+ }
+ assert(wpbase == which->base());
+ assert(wplimit == which->end());
+ which->setLimit(wp);
+ wp = nullptr;
+ wplimit = nullptr;
+ // wpbase = nullptr;
+ return which;
}
// maybe_inline
void unpacker::ensure_put_space(size_t size)
{
- if (wp + size <= wplimit)
- return;
- // Determine which segment needs expanding.
- fillbytes *which = close_output();
- byte *wp0 = which->grow(size);
- wpbase = which->base();
- wplimit = which->end();
- wp = wp0;
+ if (wp + size <= wplimit)
+ return;
+ // Determine which segment needs expanding.
+ fillbytes *which = close_output();
+ byte *wp0 = which->grow(size);
+ wpbase = which->base();
+ wplimit = which->end();
+ wp = wp0;
}
byte *unpacker::put_space(size_t size)
{
- byte *wp0 = wp;
- byte *wp1 = wp0 + size;
- if (wp1 > wplimit)
- {
- ensure_put_space(size);
- wp0 = wp;
- wp1 = wp0 + size;
- }
- wp = wp1;
- return wp0;
+ byte *wp0 = wp;
+ byte *wp1 = wp0 + size;
+ if (wp1 > wplimit)
+ {
+ ensure_put_space(size);
+ wp0 = wp;
+ wp1 = wp0 + size;
+ }
+ wp = wp1;
+ return wp0;
}
void unpacker::putu2_at(byte *wp, int n)
{
- if (n != (unsigned short)n)
- {
- unpack_abort(ERROR_OVERFLOW);
- return;
- }
- wp[0] = (n) >> 8;
- wp[1] = (n) >> 0;
+ if (n != (unsigned short)n)
+ {
+ unpack_abort(ERROR_OVERFLOW);
+ return;
+ }
+ wp[0] = (n) >> 8;
+ wp[1] = (n) >> 0;
}
void unpacker::putu4_at(byte *wp, int n)
{
- wp[0] = (n) >> 24;
- wp[1] = (n) >> 16;
- wp[2] = (n) >> 8;
- wp[3] = (n) >> 0;
+ wp[0] = (n) >> 24;
+ wp[1] = (n) >> 16;
+ wp[2] = (n) >> 8;
+ wp[3] = (n) >> 0;
}
void unpacker::putu8_at(byte *wp, int64_t n)
{
- putu4_at(wp + 0, (int)((uint64_t)n >> 32));
- putu4_at(wp + 4, (int)((uint64_t)n >> 0));
+ putu4_at(wp + 0, (int)((uint64_t)n >> 32));
+ putu4_at(wp + 4, (int)((uint64_t)n >> 0));
}
void unpacker::putu2(int n)
{
- putu2_at(put_space(2), n);
+ putu2_at(put_space(2), n);
}
void unpacker::putu4(int n)
{
- putu4_at(put_space(4), n);
+ putu4_at(put_space(4), n);
}
void unpacker::putu8(int64_t n)
{
- putu8_at(put_space(8), n);
+ putu8_at(put_space(8), n);
}
int unpacker::putref_index(entry *e, int size)
{
- if (e == nullptr)
- return 0;
- else if (e->outputIndex > NOT_REQUESTED)
- return e->outputIndex;
- else if (e->tag == CONSTANT_Signature)
- return putref_index(e->ref(0), size);
- else
- {
- e->requestOutputIndex(cp, -size);
- // Later on we'll fix the bits.
- class_fixup_type.addByte(size);
- class_fixup_offset.add((int)wpoffset());
- class_fixup_ref.add(e);
- return 0;
- }
+ if (e == nullptr)
+ return 0;
+ else if (e->outputIndex > NOT_REQUESTED)
+ return e->outputIndex;
+ else if (e->tag == CONSTANT_Signature)
+ return putref_index(e->ref(0), size);
+ else
+ {
+ e->requestOutputIndex(cp, -size);
+ // Later on we'll fix the bits.
+ class_fixup_type.addByte(size);
+ class_fixup_offset.add((int)wpoffset());
+ class_fixup_ref.add(e);
+ return 0;
+ }
}
void unpacker::putref(entry *e)
{
- int oidx = putref_index(e, 2);
- putu2_at(put_space(2), oidx);
+ int oidx = putref_index(e, 2);
+ putu2_at(put_space(2), oidx);
}
void unpacker::putu1ref(entry *e)
{
- int oidx = putref_index(e, 1);
- putu1_at(put_space(1), oidx);
+ int oidx = putref_index(e, 1);
+ putu1_at(put_space(1), oidx);
}
// Allocation of small and large blocks.
enum
{
- CHUNK = (1 << 14),
- SMALL = (1 << 9)
+ CHUNK = (1 << 14),
+ SMALL = (1 << 9)
};
// Call malloc. Try to combine small blocks and free much later.
void *unpacker::alloc_heap(size_t size, bool smallOK, bool temp)
{
- if (!smallOK || size > SMALL)
- {
- void *res = must_malloc((int)size);
- (temp ? &tmallocs : &mallocs)->add(res);
- return res;
- }
- fillbytes &xsmallbuf = *(temp ? &tsmallbuf : &smallbuf);
- if (!xsmallbuf.canAppend(size + 1))
- {
- xsmallbuf.init(CHUNK);
- (temp ? &tmallocs : &mallocs)->add(xsmallbuf.base());
- }
- int growBy = (int)size;
- growBy += -growBy & 7; // round up mod 8
- return xsmallbuf.grow(growBy);
+ if (!smallOK || size > SMALL)
+ {
+ void *res = must_malloc((int)size);
+ (temp ? &tmallocs : &mallocs)->add(res);
+ return res;
+ }
+ fillbytes &xsmallbuf = *(temp ? &tsmallbuf : &smallbuf);
+ if (!xsmallbuf.canAppend(size + 1))
+ {
+ xsmallbuf.init(CHUNK);
+ (temp ? &tmallocs : &mallocs)->add(xsmallbuf.base());
+ }
+ int growBy = (int)size;
+ growBy += -growBy & 7; // round up mod 8
+ return xsmallbuf.grow(growBy);
}
void unpacker::saveTo(bytes &b, byte *ptr, size_t len)
{
- b.ptr = U_NEW(byte, add_size(len, 1));
- b.len = len;
- b.copyFrom(ptr, len);
+ b.ptr = U_NEW(byte, add_size(len, 1));
+ b.len = len;
+ b.copyFrom(ptr, len);
}
// Read up through band_headers.
// Do the archive_size dance to set the size of the input mega-buffer.
void unpacker::read_file_header()
{
- // Read file header to determine file type and total size.
- enum
- {
- MAGIC_BYTES = 4,
- AH_LENGTH_0 = 3, // minver, majver, options are outside of archive_size
- AH_LENGTH_0_MAX = AH_LENGTH_0 + 1, // options might have 2 bytes
- AH_LENGTH = 26, // maximum archive header length (w/ all fields)
- // Length contributions from optional header fields:
- AH_FILE_HEADER_LEN = 5, // sizehi/lo/next/modtime/files
- AH_ARCHIVE_SIZE_LEN = 2, // sizehi/lo only; part of AH_FILE_HEADER_LEN
- AH_CP_NUMBER_LEN = 4, // int/float/long/double
- AH_SPECIAL_FORMAT_LEN = 2, // layouts/band-headers
- AH_LENGTH_MIN =
- AH_LENGTH - (AH_FILE_HEADER_LEN + AH_SPECIAL_FORMAT_LEN + AH_CP_NUMBER_LEN),
- ARCHIVE_SIZE_MIN = AH_LENGTH_MIN - (AH_LENGTH_0 + AH_ARCHIVE_SIZE_LEN),
- FIRST_READ = MAGIC_BYTES + AH_LENGTH_MIN
- };
-
- assert(AH_LENGTH_MIN == 15); // # of UNSIGNED5 fields required after archive_magic
- assert(ARCHIVE_SIZE_MIN == 10); // # of UNSIGNED5 fields required after archive_size
- // An absolute minimum nullptr archive is magic[4], {minver,majver,options}[3],
- // archive_size[0], cp_counts[8], class_counts[4], for a total of 19 bytes.
- // (Note that archive_size is optional; it may be 0..10 bytes in length.)
- // The first read must capture everything up through the options field.
- // This happens to work even if {minver,majver,options} is a pathological
- // 15 bytes long. Legal pack files limit those three fields to 1+1+2 bytes.
- assert(FIRST_READ >= MAGIC_BYTES + AH_LENGTH_0 * B_MAX);
-
- // Up through archive_size, the largest possible archive header is
- // magic[4], {minver,majver,options}[4], archive_size[10].
- // (Note only the low 12 bits of options are allowed to be non-zero.)
- // In order to parse archive_size, we need at least this many bytes
- // in the first read. Of course, if archive_size_hi is more than
- // a byte, we probably will fail to allocate the buffer, since it
- // will be many gigabytes long. This is a practical, not an
- // architectural limit to Pack200 archive sizes.
- assert(FIRST_READ >= MAGIC_BYTES + AH_LENGTH_0_MAX + 2 * B_MAX);
-
- bool foreign_buf = (read_input_fn == nullptr);
- byte initbuf[(int)FIRST_READ + (int)C_SLOP + 200]; // 200 is for JAR I/O
- if (foreign_buf)
- {
- // inbytes is all there is
- input.set(inbytes);
- rp = input.base();
- rplimit = input.limit();
- }
- else
- {
- // inbytes, if not empty, contains some read-ahead we must use first
- // ensure_input will take care of copying it into initbuf,
- // then querying read_input_fn for any additional data needed.
- // However, the caller must assume that we use up all of inbytes.
- // There is no way to tell the caller that we used only part of them.
- // Therefore, the caller must use only a bare minimum of read-ahead.
- if (inbytes.len > FIRST_READ)
- {
- unpack_abort("too much read-ahead");
- }
- input.set(initbuf, sizeof(initbuf));
- input.b.clear();
- input.b.copyFrom(inbytes);
- rplimit = rp = input.base();
- rplimit += inbytes.len;
- bytes_read += inbytes.len;
- }
- // Read only 19 bytes, which is certain to contain #archive_options fields,
- // but is certain not to overflow past the archive_header.
- input.b.len = FIRST_READ;
- if (!ensure_input(FIRST_READ))
- unpack_abort("EOF reading archive magic number");
-
- if (rp[0] == 'P' && rp[1] == 'K')
- {
- // In the Unix-style program, we simply simulate a copy command.
- // Copy until EOF; assume the JAR file is the last segment.
- fprintf(stderr, "Copy-mode.\n");
- for (;;)
- {
- jarout->write_data(rp, (int)input_remaining());
- if (foreign_buf)
- break; // one-time use of a passed in buffer
- if (input.size() < CHUNK)
- {
- // Get some breathing room.
- input.set(U_NEW(byte, (size_t)CHUNK + C_SLOP), (size_t)CHUNK);
- }
- rp = rplimit = input.base();
- if (!ensure_input(1))
- break;
- }
- jarout->closeJarFile(false);
- return;
- }
-
- // Read the magic number.
- magic = 0;
- for (int i1 = 0; i1 < (int)sizeof(magic); i1++)
- {
- magic <<= 8;
- magic += (*rp++ & 0xFF);
- }
-
- // Read the first 3 values from the header.
- value_stream hdr;
- int hdrVals = 0;
- int hdrValsSkipped = 0; // debug only
- hdr.init(rp, rplimit, UNSIGNED5_spec);
- minver = hdr.getInt();
- majver = hdr.getInt();
- hdrVals += 2;
-
- if (magic != (int)JAVA_PACKAGE_MAGIC ||
- (majver != JAVA5_PACKAGE_MAJOR_VERSION && majver != JAVA6_PACKAGE_MAJOR_VERSION) ||
- (minver != JAVA5_PACKAGE_MINOR_VERSION && minver != JAVA6_PACKAGE_MINOR_VERSION))
- {
- char message[200];
- sprintf(message, "@" ERROR_FORMAT ": magic/ver = "
- "%08X/%d.%d should be %08X/%d.%d OR %08X/%d.%d\n",
- magic, majver, minver, JAVA_PACKAGE_MAGIC, JAVA5_PACKAGE_MAJOR_VERSION,
- JAVA5_PACKAGE_MINOR_VERSION, JAVA_PACKAGE_MAGIC, JAVA6_PACKAGE_MAJOR_VERSION,
- JAVA6_PACKAGE_MINOR_VERSION);
- unpack_abort(message);
- }
-
- archive_options = hdr.getInt();
- hdrVals += 1;
- assert(hdrVals == AH_LENGTH_0); // first three fields only
+ // Read file header to determine file type and total size.
+ enum
+ {
+ MAGIC_BYTES = 4,
+ AH_LENGTH_0 = 3, // minver, majver, options are outside of archive_size
+ AH_LENGTH_0_MAX = AH_LENGTH_0 + 1, // options might have 2 bytes
+ AH_LENGTH = 26, // maximum archive header length (w/ all fields)
+ // Length contributions from optional header fields:
+ AH_FILE_HEADER_LEN = 5, // sizehi/lo/next/modtime/files
+ AH_ARCHIVE_SIZE_LEN = 2, // sizehi/lo only; part of AH_FILE_HEADER_LEN
+ AH_CP_NUMBER_LEN = 4, // int/float/long/double
+ AH_SPECIAL_FORMAT_LEN = 2, // layouts/band-headers
+ AH_LENGTH_MIN =
+ AH_LENGTH - (AH_FILE_HEADER_LEN + AH_SPECIAL_FORMAT_LEN + AH_CP_NUMBER_LEN),
+ ARCHIVE_SIZE_MIN = AH_LENGTH_MIN - (AH_LENGTH_0 + AH_ARCHIVE_SIZE_LEN),
+ FIRST_READ = MAGIC_BYTES + AH_LENGTH_MIN
+ };
+
+ assert(AH_LENGTH_MIN == 15); // # of UNSIGNED5 fields required after archive_magic
+ assert(ARCHIVE_SIZE_MIN == 10); // # of UNSIGNED5 fields required after archive_size
+ // An absolute minimum nullptr archive is magic[4], {minver,majver,options}[3],
+ // archive_size[0], cp_counts[8], class_counts[4], for a total of 19 bytes.
+ // (Note that archive_size is optional; it may be 0..10 bytes in length.)
+ // The first read must capture everything up through the options field.
+ // This happens to work even if {minver,majver,options} is a pathological
+ // 15 bytes long. Legal pack files limit those three fields to 1+1+2 bytes.
+ assert(FIRST_READ >= MAGIC_BYTES + AH_LENGTH_0 * B_MAX);
+
+ // Up through archive_size, the largest possible archive header is
+ // magic[4], {minver,majver,options}[4], archive_size[10].
+ // (Note only the low 12 bits of options are allowed to be non-zero.)
+ // In order to parse archive_size, we need at least this many bytes
+ // in the first read. Of course, if archive_size_hi is more than
+ // a byte, we probably will fail to allocate the buffer, since it
+ // will be many gigabytes long. This is a practical, not an
+ // architectural limit to Pack200 archive sizes.
+ assert(FIRST_READ >= MAGIC_BYTES + AH_LENGTH_0_MAX + 2 * B_MAX);
+
+ bool foreign_buf = (read_input_fn == nullptr);
+ byte initbuf[(int)FIRST_READ + (int)C_SLOP + 200]; // 200 is for JAR I/O
+ if (foreign_buf)
+ {
+ // inbytes is all there is
+ input.set(inbytes);
+ rp = input.base();
+ rplimit = input.limit();
+ }
+ else
+ {
+ // inbytes, if not empty, contains some read-ahead we must use first
+ // ensure_input will take care of copying it into initbuf,
+ // then querying read_input_fn for any additional data needed.
+ // However, the caller must assume that we use up all of inbytes.
+ // There is no way to tell the caller that we used only part of them.
+ // Therefore, the caller must use only a bare minimum of read-ahead.
+ if (inbytes.len > FIRST_READ)
+ {
+ unpack_abort("too much read-ahead");
+ }
+ input.set(initbuf, sizeof(initbuf));
+ input.b.clear();
+ input.b.copyFrom(inbytes);
+ rplimit = rp = input.base();
+ rplimit += inbytes.len;
+ bytes_read += inbytes.len;
+ }
+ // Read only 19 bytes, which is certain to contain #archive_options fields,
+ // but is certain not to overflow past the archive_header.
+ input.b.len = FIRST_READ;
+ if (!ensure_input(FIRST_READ))
+ unpack_abort("EOF reading archive magic number");
+
+ if (rp[0] == 'P' && rp[1] == 'K')
+ {
+ // In the Unix-style program, we simply simulate a copy command.
+ // Copy until EOF; assume the JAR file is the last segment.
+ fprintf(stderr, "Copy-mode.\n");
+ for (;;)
+ {
+ jarout->write_data(rp, (int)input_remaining());
+ if (foreign_buf)
+ break; // one-time use of a passed in buffer
+ if (input.size() < CHUNK)
+ {
+ // Get some breathing room.
+ input.set(U_NEW(byte, (size_t)CHUNK + C_SLOP), (size_t)CHUNK);
+ }
+ rp = rplimit = input.base();
+ if (!ensure_input(1))
+ break;
+ }
+ jarout->closeJarFile(false);
+ return;
+ }
+
+ // Read the magic number.
+ magic = 0;
+ for (int i1 = 0; i1 < (int)sizeof(magic); i1++)
+ {
+ magic <<= 8;
+ magic += (*rp++ & 0xFF);
+ }
+
+ // Read the first 3 values from the header.
+ value_stream hdr;
+ int hdrVals = 0;
+ int hdrValsSkipped = 0; // debug only
+ hdr.init(rp, rplimit, UNSIGNED5_spec);
+ minver = hdr.getInt();
+ majver = hdr.getInt();
+ hdrVals += 2;
+
+ if (magic != (int)JAVA_PACKAGE_MAGIC ||
+ (majver != JAVA5_PACKAGE_MAJOR_VERSION && majver != JAVA6_PACKAGE_MAJOR_VERSION) ||
+ (minver != JAVA5_PACKAGE_MINOR_VERSION && minver != JAVA6_PACKAGE_MINOR_VERSION))
+ {
+ char message[200];
+ sprintf(message, "@" ERROR_FORMAT ": magic/ver = "
+ "%08X/%d.%d should be %08X/%d.%d OR %08X/%d.%d\n",
+ magic, majver, minver, JAVA_PACKAGE_MAGIC, JAVA5_PACKAGE_MAJOR_VERSION,
+ JAVA5_PACKAGE_MINOR_VERSION, JAVA_PACKAGE_MAGIC, JAVA6_PACKAGE_MAJOR_VERSION,
+ JAVA6_PACKAGE_MINOR_VERSION);
+ unpack_abort(message);
+ }
+
+ archive_options = hdr.getInt();
+ hdrVals += 1;
+ assert(hdrVals == AH_LENGTH_0); // first three fields only
#define ORBIT(bit) | (bit)
- int OPTION_LIMIT = (0 ARCHIVE_BIT_DO(ORBIT));
+ int OPTION_LIMIT = (0 ARCHIVE_BIT_DO(ORBIT));
#undef ORBIT
- if ((archive_options & ~OPTION_LIMIT) != 0)
- {
- fprintf(stderr, "Warning: Illegal archive options 0x%x\n", archive_options);
- unpack_abort("illegal archive options");
- return;
- }
-
- if ((archive_options & AO_HAVE_FILE_HEADERS) != 0)
- {
- uint32_t hi = hdr.getInt();
- uint32_t lo = hdr.getInt();
- uint64_t x = band::makeLong(hi, lo);
- archive_size = (size_t)x;
- if (archive_size != x)
- {
- // Silly size specified; force overflow.
- archive_size = PSIZE_MAX + 1;
- }
- hdrVals += 2;
- }
- else
- {
- hdrValsSkipped += 2;
- }
-
- // Now we can size the whole archive.
- // Read everything else into a mega-buffer.
- rp = hdr.rp;
- int header_size_0 = (int)(rp - input.base()); // used-up header (4byte + 3int)
- int header_size_1 = (int)(rplimit - rp); // buffered unused initial fragment
- int header_size = header_size_0 + header_size_1;
- unsized_bytes_read = header_size_0;
- if (foreign_buf)
- {
- if (archive_size > (size_t)header_size_1)
- {
- unpack_abort("EOF reading fixed input buffer");
- return;
- }
- }
- else if (archive_size != 0)
- {
- if (archive_size < ARCHIVE_SIZE_MIN)
- {
- unpack_abort("impossible archive size"); // bad input data
- return;
- }
- if (archive_size < (size_t)header_size_1)
- {
- unpack_abort("too much read-ahead"); // somehow we pre-fetched too much?
- return;
- }
- input.set(U_NEW(byte, add_size(header_size_0, archive_size, C_SLOP)),
- (size_t)header_size_0 + archive_size);
- assert(input.limit()[0] == 0);
- // Move all the bytes we read initially into the real buffer.
- input.b.copyFrom(initbuf, header_size);
- rp = input.b.ptr + header_size_0;
- rplimit = input.b.ptr + header_size;
- }
- else
- {
- // It's more complicated and painful.
- // A zero archive_size means that we must read until EOF.
- input.init(CHUNK * 2);
- input.b.len = input.allocated;
- rp = rplimit = input.base();
- // Set up input buffer as if we already read the header:
- input.b.copyFrom(initbuf, header_size);
- rplimit += header_size;
- while (ensure_input(input.limit() - rp))
- {
- size_t dataSoFar = input_remaining();
- size_t nextSize = add_size(dataSoFar, CHUNK);
- input.ensureSize(nextSize);
- input.b.len = input.allocated;
- rp = rplimit = input.base();
- rplimit += dataSoFar;
- }
- size_t dataSize = (rplimit - input.base());
- input.b.len = dataSize;
- input.grow(C_SLOP);
- free_input = true; // free it later
- input.b.len = dataSize;
- assert(input.limit()[0] == 0);
- rp = rplimit = input.base();
- rplimit += dataSize;
- rp += header_size_0; // already scanned these bytes...
- }
- live_input = true; // mark as "do not reuse"
-
- // read the rest of the header fields
- ensure_input((AH_LENGTH - AH_LENGTH_0) * B_MAX);
- hdr.rp = rp;
- hdr.rplimit = rplimit;
-
- if ((archive_options & AO_HAVE_FILE_HEADERS) != 0)
- {
- archive_next_count = hdr.getInt();
- if (archive_next_count < 0)
- unpack_abort("bad archive_next_count");
- archive_modtime = hdr.getInt();
- file_count = hdr.getInt();
- if (file_count < 0)
- unpack_abort("bad file_count");
- hdrVals += 3;
- }
- else
- {
- hdrValsSkipped += 3;
- }
-
- if ((archive_options & AO_HAVE_SPECIAL_FORMATS) != 0)
- {
- band_headers_size = hdr.getInt();
- if (band_headers_size < 0)
- unpack_abort("bad band_headers_size");
- attr_definition_count = hdr.getInt();
- if (attr_definition_count < 0)
- unpack_abort("bad attr_definition_count");
- hdrVals += 2;
- }
- else
- {
- hdrValsSkipped += 2;
- }
-
- int cp_counts[N_TAGS_IN_ORDER];
- for (int k = 0; k < (int)N_TAGS_IN_ORDER; k++)
- {
- if (!(archive_options & AO_HAVE_CP_NUMBERS))
- {
- switch (TAGS_IN_ORDER[k])
- {
- case CONSTANT_Integer:
- case CONSTANT_Float:
- case CONSTANT_Long:
- case CONSTANT_Double:
- cp_counts[k] = 0;
- hdrValsSkipped += 1;
- continue;
- }
- }
- cp_counts[k] = hdr.getInt();
- if (cp_counts[k] < 0)
- unpack_abort("bad cp_counts");
- hdrVals += 1;
- }
-
- ic_count = hdr.getInt();
- if (ic_count < 0)
- unpack_abort("bad ic_count");
-
- default_class_minver = hdr.getInt();
- default_class_majver = hdr.getInt();
-
- class_count = hdr.getInt();
- if (class_count < 0)
- unpack_abort("bad class_count");
-
- hdrVals += 4;
-
- // done with archive_header
- hdrVals += hdrValsSkipped;
- assert(hdrVals == AH_LENGTH);
-
- rp = hdr.rp;
- if (rp > rplimit)
- unpack_abort("EOF reading archive header");
-
- // Now size the CP.
- cp.init(this, cp_counts);
-
- default_file_modtime = archive_modtime;
- if (default_file_modtime == 0 && !(archive_options & AO_HAVE_FILE_MODTIME))
- default_file_modtime = DEFAULT_ARCHIVE_MODTIME; // taken from driver
- if ((archive_options & AO_DEFLATE_HINT) != 0)
- default_file_options |= FO_DEFLATE_HINT;
-
- // meta-bytes, if any, immediately follow archive header
- // band_headers.readData(band_headers_size);
- ensure_input(band_headers_size);
- if (input_remaining() < (size_t)band_headers_size)
- {
- unpack_abort("EOF reading band headers");
- return;
- }
- bytes band_headers;
- // The "1+" allows an initial byte to be pushed on the front.
- band_headers.set(1 + U_NEW(byte, 1 + band_headers_size + C_SLOP), band_headers_size);
-
- // Start scanning band headers here:
- band_headers.copyFrom(rp, band_headers.len);
- rp += band_headers.len;
- assert(rp <= rplimit);
- meta_rp = band_headers.ptr;
- // Put evil meta-codes at the end of the band headers,
- // so we are sure to throw an error if we run off the end.
- bytes::of(band_headers.limit(), C_SLOP).clear(_meta_error);
+ if ((archive_options & ~OPTION_LIMIT) != 0)
+ {
+ fprintf(stderr, "Warning: Illegal archive options 0x%x\n", archive_options);
+ unpack_abort("illegal archive options");
+ return;
+ }
+
+ if ((archive_options & AO_HAVE_FILE_HEADERS) != 0)
+ {
+ uint32_t hi = hdr.getInt();
+ uint32_t lo = hdr.getInt();
+ uint64_t x = band::makeLong(hi, lo);
+ archive_size = (size_t)x;
+ if (archive_size != x)
+ {
+ // Silly size specified; force overflow.
+ archive_size = PSIZE_MAX + 1;
+ }
+ hdrVals += 2;
+ }
+ else
+ {
+ hdrValsSkipped += 2;
+ }
+
+ // Now we can size the whole archive.
+ // Read everything else into a mega-buffer.
+ rp = hdr.rp;
+ int header_size_0 = (int)(rp - input.base()); // used-up header (4byte + 3int)
+ int header_size_1 = (int)(rplimit - rp); // buffered unused initial fragment
+ int header_size = header_size_0 + header_size_1;
+ unsized_bytes_read = header_size_0;
+ if (foreign_buf)
+ {
+ if (archive_size > (size_t)header_size_1)
+ {
+ unpack_abort("EOF reading fixed input buffer");
+ return;
+ }
+ }
+ else if (archive_size != 0)
+ {
+ if (archive_size < ARCHIVE_SIZE_MIN)
+ {
+ unpack_abort("impossible archive size"); // bad input data
+ return;
+ }
+ if (archive_size < (size_t)header_size_1)
+ {
+ unpack_abort("too much read-ahead"); // somehow we pre-fetched too much?
+ return;
+ }
+ input.set(U_NEW(byte, add_size(header_size_0, archive_size, C_SLOP)),
+ (size_t)header_size_0 + archive_size);
+ assert(input.limit()[0] == 0);
+ // Move all the bytes we read initially into the real buffer.
+ input.b.copyFrom(initbuf, header_size);
+ rp = input.b.ptr + header_size_0;
+ rplimit = input.b.ptr + header_size;
+ }
+ else
+ {
+ // It's more complicated and painful.
+ // A zero archive_size means that we must read until EOF.
+ input.init(CHUNK * 2);
+ input.b.len = input.allocated;
+ rp = rplimit = input.base();
+ // Set up input buffer as if we already read the header:
+ input.b.copyFrom(initbuf, header_size);
+ rplimit += header_size;
+ while (ensure_input(input.limit() - rp))
+ {
+ size_t dataSoFar = input_remaining();
+ size_t nextSize = add_size(dataSoFar, CHUNK);
+ input.ensureSize(nextSize);
+ input.b.len = input.allocated;
+ rp = rplimit = input.base();
+ rplimit += dataSoFar;
+ }
+ size_t dataSize = (rplimit - input.base());
+ input.b.len = dataSize;
+ input.grow(C_SLOP);
+ free_input = true; // free it later
+ input.b.len = dataSize;
+ assert(input.limit()[0] == 0);
+ rp = rplimit = input.base();
+ rplimit += dataSize;
+ rp += header_size_0; // already scanned these bytes...
+ }
+ live_input = true; // mark as "do not reuse"
+
+ // read the rest of the header fields
+ ensure_input((AH_LENGTH - AH_LENGTH_0) * B_MAX);
+ hdr.rp = rp;
+ hdr.rplimit = rplimit;
+
+ if ((archive_options & AO_HAVE_FILE_HEADERS) != 0)
+ {
+ archive_next_count = hdr.getInt();
+ if (archive_next_count < 0)
+ unpack_abort("bad archive_next_count");
+ archive_modtime = hdr.getInt();
+ file_count = hdr.getInt();
+ if (file_count < 0)
+ unpack_abort("bad file_count");
+ hdrVals += 3;
+ }
+ else
+ {
+ hdrValsSkipped += 3;
+ }
+
+ if ((archive_options & AO_HAVE_SPECIAL_FORMATS) != 0)
+ {
+ band_headers_size = hdr.getInt();
+ if (band_headers_size < 0)
+ unpack_abort("bad band_headers_size");
+ attr_definition_count = hdr.getInt();
+ if (attr_definition_count < 0)
+ unpack_abort("bad attr_definition_count");
+ hdrVals += 2;
+ }
+ else
+ {
+ hdrValsSkipped += 2;
+ }
+
+ int cp_counts[N_TAGS_IN_ORDER];
+ for (int k = 0; k < (int)N_TAGS_IN_ORDER; k++)
+ {
+ if (!(archive_options & AO_HAVE_CP_NUMBERS))
+ {
+ switch (TAGS_IN_ORDER[k])
+ {
+ case CONSTANT_Integer:
+ case CONSTANT_Float:
+ case CONSTANT_Long:
+ case CONSTANT_Double:
+ cp_counts[k] = 0;
+ hdrValsSkipped += 1;
+ continue;
+ }
+ }
+ cp_counts[k] = hdr.getInt();
+ if (cp_counts[k] < 0)
+ unpack_abort("bad cp_counts");
+ hdrVals += 1;
+ }
+
+ ic_count = hdr.getInt();
+ if (ic_count < 0)
+ unpack_abort("bad ic_count");
+
+ default_class_minver = hdr.getInt();
+ default_class_majver = hdr.getInt();
+
+ class_count = hdr.getInt();
+ if (class_count < 0)
+ unpack_abort("bad class_count");
+
+ hdrVals += 4;
+
+ // done with archive_header
+ hdrVals += hdrValsSkipped;
+ assert(hdrVals == AH_LENGTH);
+
+ rp = hdr.rp;
+ if (rp > rplimit)
+ unpack_abort("EOF reading archive header");
+
+ // Now size the CP.
+ cp.init(this, cp_counts);
+
+ default_file_modtime = archive_modtime;
+ if (default_file_modtime == 0 && !(archive_options & AO_HAVE_FILE_MODTIME))
+ default_file_modtime = DEFAULT_ARCHIVE_MODTIME; // taken from driver
+ if ((archive_options & AO_DEFLATE_HINT) != 0)
+ default_file_options |= FO_DEFLATE_HINT;
+
+ // meta-bytes, if any, immediately follow archive header
+ // band_headers.readData(band_headers_size);
+ ensure_input(band_headers_size);
+ if (input_remaining() < (size_t)band_headers_size)
+ {
+ unpack_abort("EOF reading band headers");
+ return;
+ }
+ bytes band_headers;
+ // The "1+" allows an initial byte to be pushed on the front.
+ band_headers.set(1 + U_NEW(byte, 1 + band_headers_size + C_SLOP), band_headers_size);
+
+ // Start scanning band headers here:
+ band_headers.copyFrom(rp, band_headers.len);
+ rp += band_headers.len;
+ assert(rp <= rplimit);
+ meta_rp = band_headers.ptr;
+ // Put evil meta-codes at the end of the band headers,
+ // so we are sure to throw an error if we run off the end.
+ bytes::of(band_headers.limit(), C_SLOP).clear(_meta_error);
}
void unpacker::finish()
{
- if (verbose >= 1)
- {
- fprintf(stderr, "A total of " LONG_LONG_FORMAT " bytes were read in %d segment(s).\n",
- (bytes_read_before_reset + bytes_read), segments_read_before_reset + 1);
- fprintf(stderr, "A total of " LONG_LONG_FORMAT " file content bytes were written.\n",
- (bytes_written_before_reset + bytes_written));
- fprintf(stderr,
- "A total of %d files (of which %d are classes) were written to output.\n",
- files_written_before_reset + files_written,
- classes_written_before_reset + classes_written);
- }
- if (jarout != nullptr)
- jarout->closeJarFile(true);
+ if (verbose >= 1)
+ {
+ fprintf(stderr, "A total of %" PRIu64 " bytes were read in %d segment(s).\n",
+ (bytes_read_before_reset + bytes_read), segments_read_before_reset + 1);
+ fprintf(stderr, "A total of %" PRIu64 " file content bytes were written.\n",
+ (bytes_written_before_reset + bytes_written));
+ fprintf(stderr,
+ "A total of %d files (of which %d are classes) were written to output.\n",
+ files_written_before_reset + files_written,
+ classes_written_before_reset + classes_written);
+ }
+ if (jarout != nullptr)
+ jarout->closeJarFile(true);
}
// Cf. PackageReader.readConstantPoolCounts
void constant_pool::init(unpacker *u_, int counts[NUM_COUNTS])
{
- this->u = u_;
-
- // Fill-pointer for CP.
- int next_entry = 0;
-
- // Size the constant pool:
- for (int k = 0; k < (int)N_TAGS_IN_ORDER; k++)
- {
- byte tag = TAGS_IN_ORDER[k];
- int len = counts[k];
- tag_count[tag] = len;
- tag_base[tag] = next_entry;
- next_entry += len;
- // Detect and defend against constant pool size overflow.
- // (Pack200 forbids the sum of CP counts to exceed 2^29-1.)
- enum
- {
- CP_SIZE_LIMIT = (1 << 29),
- IMPLICIT_ENTRY_COUNT = 1 // empty Utf8 string
- };
- if (len >= (1 << 29) || len < 0 || next_entry >= CP_SIZE_LIMIT + IMPLICIT_ENTRY_COUNT)
- {
- unpack_abort("archive too large: constant pool limit exceeded");
- }
- }
-
- // Close off the end of the CP:
- nentries = next_entry;
-
- // place a limit on future CP growth:
- int generous = 0;
- generous = add_size(generous, u->ic_count); // implicit name
- generous = add_size(generous, u->ic_count); // outer
- generous = add_size(generous, u->ic_count); // outer.utf8
- generous = add_size(generous, 40); // WKUs, misc
- generous = add_size(generous, u->class_count); // implicit SourceFile strings
- maxentries = add_size(nentries, generous);
-
- // Note that this CP does not include "empty" entries
- // for longs and doubles. Those are introduced when
- // the entries are renumbered for classfile output.
-
- entries = U_NEW(entry, maxentries);
-
- first_extra_entry = &entries[nentries];
-
- // Initialize the standard indexes.
- tag_count[CONSTANT_All] = nentries;
- tag_base[CONSTANT_All] = 0;
- for (int tag = 0; tag < CONSTANT_Limit; tag++)
- {
- entry *cpMap = &entries[tag_base[tag]];
- tag_index[tag].init(tag_count[tag], cpMap, tag);
- }
-
- // Initialize hashTab to a generous power-of-two size.
- uint32_t pow2 = 1;
- uint32_t target = maxentries + maxentries / 2; // 60% full
- while (pow2 < target)
- pow2 <<= 1;
- hashTab = U_NEW(entry *, hashTabLength = pow2);
+ this->u = u_;
+
+ // Fill-pointer for CP.
+ int next_entry = 0;
+
+ // Size the constant pool:
+ for (int k = 0; k < (int)N_TAGS_IN_ORDER; k++)
+ {
+ byte tag = TAGS_IN_ORDER[k];
+ int len = counts[k];
+ tag_count[tag] = len;
+ tag_base[tag] = next_entry;
+ next_entry += len;
+ // Detect and defend against constant pool size overflow.
+ // (Pack200 forbids the sum of CP counts to exceed 2^29-1.)
+ enum
+ {
+ CP_SIZE_LIMIT = (1 << 29),
+ IMPLICIT_ENTRY_COUNT = 1 // empty Utf8 string
+ };
+ if (len >= (1 << 29) || len < 0 || next_entry >= CP_SIZE_LIMIT + IMPLICIT_ENTRY_COUNT)
+ {
+ unpack_abort("archive too large: constant pool limit exceeded");
+ }
+ }
+
+ // Close off the end of the CP:
+ nentries = next_entry;
+
+ // place a limit on future CP growth:
+ int generous = 0;
+ generous = add_size(generous, u->ic_count); // implicit name
+ generous = add_size(generous, u->ic_count); // outer
+ generous = add_size(generous, u->ic_count); // outer.utf8
+ generous = add_size(generous, 40); // WKUs, misc
+ generous = add_size(generous, u->class_count); // implicit SourceFile strings
+ maxentries = add_size(nentries, generous);
+
+ // Note that this CP does not include "empty" entries
+ // for longs and doubles. Those are introduced when
+ // the entries are renumbered for classfile output.
+
+ entries = U_NEW(entry, maxentries);
+
+ first_extra_entry = &entries[nentries];
+
+ // Initialize the standard indexes.
+ tag_count[CONSTANT_All] = nentries;
+ tag_base[CONSTANT_All] = 0;
+ for (int tag = 0; tag < CONSTANT_Limit; tag++)
+ {
+ entry *cpMap = &entries[tag_base[tag]];
+ tag_index[tag].init(tag_count[tag], cpMap, tag);
+ }
+
+ // Initialize hashTab to a generous power-of-two size.
+ uint32_t pow2 = 1;
+ uint32_t target = maxentries + maxentries / 2; // 60% full
+ while (pow2 < target)
+ pow2 <<= 1;
+ hashTab = U_NEW(entry *, hashTabLength = pow2);
}
static byte *store_Utf8_char(byte *cp, unsigned short ch)
{
- if (ch >= 0x001 && ch <= 0x007F)
- {
- *cp++ = (byte)ch;
- }
- else if (ch <= 0x07FF)
- {
- *cp++ = (byte)(0xC0 | ((ch >> 6) & 0x1F));
- *cp++ = (byte)(0x80 | ((ch >> 0) & 0x3F));
- }
- else
- {
- *cp++ = (byte)(0xE0 | ((ch >> 12) & 0x0F));
- *cp++ = (byte)(0x80 | ((ch >> 6) & 0x3F));
- *cp++ = (byte)(0x80 | ((ch >> 0) & 0x3F));
- }
- return cp;
+ if (ch >= 0x001 && ch <= 0x007F)
+ {
+ *cp++ = (byte)ch;
+ }
+ else if (ch <= 0x07FF)
+ {
+ *cp++ = (byte)(0xC0 | ((ch >> 6) & 0x1F));
+ *cp++ = (byte)(0x80 | ((ch >> 0) & 0x3F));
+ }
+ else
+ {
+ *cp++ = (byte)(0xE0 | ((ch >> 12) & 0x0F));
+ *cp++ = (byte)(0x80 | ((ch >> 6) & 0x3F));
+ *cp++ = (byte)(0x80 | ((ch >> 0) & 0x3F));
+ }
+ return cp;
}
static byte *skip_Utf8_chars(byte *cp, int len)
{
- for (;; cp++)
- {
- int ch = *cp & 0xFF;
- if ((ch & 0xC0) != 0x80)
- {
- if (len-- == 0)
- return cp;
- if (ch < 0x80 && len == 0)
- return cp + 1;
- }
- }
+ for (;; cp++)
+ {
+ int ch = *cp & 0xFF;
+ if ((ch & 0xC0) != 0x80)
+ {
+ if (len-- == 0)
+ return cp;
+ if (ch < 0x80 && len == 0)
+ return cp + 1;
+ }
+ }
}
static int compare_Utf8_chars(bytes &b1, bytes &b2)
{
- int l1 = (int)b1.len;
- int l2 = (int)b2.len;
- int l0 = (l1 < l2) ? l1 : l2;
- byte *p1 = b1.ptr;
- byte *p2 = b2.ptr;
- int c0 = 0;
- for (int i = 0; i < l0; i++)
- {
- int c1 = p1[i] & 0xFF;
- int c2 = p2[i] & 0xFF;
- if (c1 != c2)
- {
- // Before returning the obvious answer,
- // check to see if c1 or c2 is part of a 0x0000,
- // which encodes as {0xC0,0x80}. The 0x0000 is the
- // lowest-sorting Java char value, and yet it encodes
- // as if it were the first char after 0x7F, which causes
- // strings containing nulls to sort too high. All other
- // comparisons are consistent between Utf8 and Java chars.
- if (c1 == 0xC0 && (p1[i + 1] & 0xFF) == 0x80)
- c1 = 0;
- if (c2 == 0xC0 && (p2[i + 1] & 0xFF) == 0x80)
- c2 = 0;
- if (c0 == 0xC0)
- {
- assert(((c1 | c2) & 0xC0) == 0x80); // c1 & c2 are extension chars
- if (c1 == 0x80)
- c1 = 0; // will sort below c2
- if (c2 == 0x80)
- c2 = 0; // will sort below c1
- }
- return c1 - c2;
- }
- c0 = c1; // save away previous char
- }
- // common prefix is identical; return length difference if any
- return l1 - l2;
+ int l1 = (int)b1.len;
+ int l2 = (int)b2.len;
+ int l0 = (l1 < l2) ? l1 : l2;
+ byte *p1 = b1.ptr;
+ byte *p2 = b2.ptr;
+ int c0 = 0;
+ for (int i = 0; i < l0; i++)
+ {
+ int c1 = p1[i] & 0xFF;
+ int c2 = p2[i] & 0xFF;
+ if (c1 != c2)
+ {
+ // Before returning the obvious answer,
+ // check to see if c1 or c2 is part of a 0x0000,
+ // which encodes as {0xC0,0x80}. The 0x0000 is the
+ // lowest-sorting Java char value, and yet it encodes
+ // as if it were the first char after 0x7F, which causes
+ // strings containing nulls to sort too high. All other
+ // comparisons are consistent between Utf8 and Java chars.
+ if (c1 == 0xC0 && (p1[i + 1] & 0xFF) == 0x80)
+ c1 = 0;
+ if (c2 == 0xC0 && (p2[i + 1] & 0xFF) == 0x80)
+ c2 = 0;
+ if (c0 == 0xC0)
+ {
+ assert(((c1 | c2) & 0xC0) == 0x80); // c1 & c2 are extension chars
+ if (c1 == 0x80)
+ c1 = 0; // will sort below c2
+ if (c2 == 0x80)
+ c2 = 0; // will sort below c1
+ }
+ return c1 - c2;
+ }
+ c0 = c1; // save away previous char
+ }
+ // common prefix is identical; return length difference if any
+ return l1 - l2;
}
// Cf. PackageReader.readUtf8Bands
void unpacker::read_Utf8_values(entry *cpMap, int len)
{
- // Implicit first Utf8 string is the empty string.
- enum
- {
- // certain bands begin with implicit zeroes
- PREFIX_SKIP_2 = 2,
- SUFFIX_SKIP_1 = 1
- };
-
- int i;
-
- // First band: Read lengths of shared prefixes.
- if (len > PREFIX_SKIP_2)
- cp_Utf8_prefix.readData(len - PREFIX_SKIP_2);
-
- // Second band: Read lengths of unshared suffixes:
- if (len > SUFFIX_SKIP_1)
- cp_Utf8_suffix.readData(len - SUFFIX_SKIP_1);
-
- bytes *allsuffixes = T_NEW(bytes, len);
-
- int nbigsuf = 0;
- fillbytes charbuf; // buffer to allocate small strings
- charbuf.init();
-
- // Third band: Read the char values in the unshared suffixes:
- cp_Utf8_chars.readData(cp_Utf8_suffix.getIntTotal());
- for (i = 0; i < len; i++)
- {
- int suffix = (i < SUFFIX_SKIP_1) ? 0 : cp_Utf8_suffix.getInt();
- if (suffix < 0)
- {
- unpack_abort("bad utf8 suffix");
- }
- if (suffix == 0 && i >= SUFFIX_SKIP_1)
- {
- // chars are packed in cp_Utf8_big_chars
- nbigsuf += 1;
- continue;
- }
- bytes &chars = allsuffixes[i];
- uint32_t size3 = suffix * 3; // max Utf8 length
- bool isMalloc = (suffix > SMALL);
- if (isMalloc)
- {
- chars.malloc(size3);
- }
- else
- {
- if (!charbuf.canAppend(size3 + 1))
- {
- assert(charbuf.allocated == 0 || tmallocs.contains(charbuf.base()));
- charbuf.init(CHUNK); // Reset to new buffer.
- tmallocs.add(charbuf.base());
- }
- chars.set(charbuf.grow(size3 + 1), size3);
- }
-
- byte *chp = chars.ptr;
- for (int j = 0; j < suffix; j++)
- {
- unsigned short ch = cp_Utf8_chars.getInt();
- chp = store_Utf8_char(chp, ch);
- }
- // shrink to fit:
- if (isMalloc)
- {
- chars.realloc(chp - chars.ptr);
- tmallocs.add(chars.ptr); // free it later
- }
- else
- {
- int shrink = (int)(chars.limit() - chp);
- chars.len -= shrink;
- charbuf.b.len -= shrink; // ungrow to reclaim buffer space
- // Note that we did not reclaim the final '\0'.
- assert(chars.limit() == charbuf.limit() - 1);
- assert(strlen((char *)chars.ptr) == chars.len);
- }
- }
- // cp_Utf8_chars.done();
-
- // Fourth band: Go back and size the specially packed strings.
- int maxlen = 0;
- cp_Utf8_big_suffix.readData(nbigsuf);
- cp_Utf8_suffix.rewind();
- for (i = 0; i < len; i++)
- {
- int suffix = (i < SUFFIX_SKIP_1) ? 0 : cp_Utf8_suffix.getInt();
- int prefix = (i < PREFIX_SKIP_2) ? 0 : cp_Utf8_prefix.getInt();
- if (prefix < 0 || prefix + suffix < 0)
- {
- unpack_abort("bad utf8 prefix");
- }
- bytes &chars = allsuffixes[i];
- if (suffix == 0 && i >= SUFFIX_SKIP_1)
- {
- suffix = cp_Utf8_big_suffix.getInt();
- assert(chars.ptr == nullptr);
- chars.len = suffix; // just a momentary hack
- }
- else
- {
- assert(chars.ptr != nullptr);
- }
- if (maxlen < prefix + suffix)
- {
- maxlen = prefix + suffix;
- }
- }
- // cp_Utf8_suffix.done(); // will use allsuffixes[i].len (ptr!=nullptr)
- // cp_Utf8_big_suffix.done(); // will use allsuffixes[i].len
-
- // Fifth band(s): Get the specially packed characters.
- cp_Utf8_big_suffix.rewind();
- for (i = 0; i < len; i++)
- {
- bytes &chars = allsuffixes[i];
- if (chars.ptr != nullptr)
- continue; // already input
- int suffix = (int)chars.len; // pick up the hack
- uint32_t size3 = suffix * 3;
- if (suffix == 0)
- continue; // done with empty string
- chars.malloc(size3);
- byte *chp = chars.ptr;
- band saved_band = cp_Utf8_big_chars;
- cp_Utf8_big_chars.readData(suffix);
- for (int j = 0; j < suffix; j++)
- {
- unsigned short ch = cp_Utf8_big_chars.getInt();
- chp = store_Utf8_char(chp, ch);
- }
- chars.realloc(chp - chars.ptr);
- tmallocs.add(chars.ptr); // free it later
- // cp_Utf8_big_chars.done();
- cp_Utf8_big_chars = saved_band; // reset the band for the next string
- }
- cp_Utf8_big_chars.readData(0); // zero chars
- // cp_Utf8_big_chars.done();
-
- // Finally, sew together all the prefixes and suffixes.
- bytes bigbuf;
- bigbuf.malloc(maxlen * 3 + 1); // max Utf8 length, plus slop for nullptr
- int prevlen = 0; // previous string length (in chars)
- tmallocs.add(bigbuf.ptr); // free after this block
- cp_Utf8_prefix.rewind();
- for (i = 0; i < len; i++)
- {
- bytes &chars = allsuffixes[i];
- int prefix = (i < PREFIX_SKIP_2) ? 0 : cp_Utf8_prefix.getInt();
- int suffix = (int)chars.len;
- byte *fillp;
- // by induction, the buffer is already filled with the prefix
- // make sure the prefix value is not corrupted, though:
- if (prefix > prevlen)
- {
- unpack_abort("utf8 prefix overflow");
- return;
- }
- fillp = skip_Utf8_chars(bigbuf.ptr, prefix);
- // copy the suffix into the same buffer:
- fillp = chars.writeTo(fillp);
- assert(bigbuf.inBounds(fillp));
- *fillp = 0; // bigbuf must contain a well-formed Utf8 string
- int length = (int)(fillp - bigbuf.ptr);
- bytes &value = cpMap[i].value.b;
- value.set(U_NEW(byte, add_size(length, 1)), length);
- value.copyFrom(bigbuf.ptr, length);
- // Index all Utf8 strings
- entry *&htref = cp.hashTabRef(CONSTANT_Utf8, value);
- if (htref == nullptr)
- {
- // Note that if two identical strings are transmitted,
- // the first is taken to be the canonical one.
- htref = &cpMap[i];
- }
- prevlen = prefix + suffix;
- }
- // cp_Utf8_prefix.done();
-
- // Free intermediate buffers.
- free_temps();
+ // Implicit first Utf8 string is the empty string.
+ enum
+ {
+ // certain bands begin with implicit zeroes
+ PREFIX_SKIP_2 = 2,
+ SUFFIX_SKIP_1 = 1
+ };
+
+ int i;
+
+ // First band: Read lengths of shared prefixes.
+ if (len > PREFIX_SKIP_2)
+ cp_Utf8_prefix.readData(len - PREFIX_SKIP_2);
+
+ // Second band: Read lengths of unshared suffixes:
+ if (len > SUFFIX_SKIP_1)
+ cp_Utf8_suffix.readData(len - SUFFIX_SKIP_1);
+
+ bytes *allsuffixes = T_NEW(bytes, len);
+
+ int nbigsuf = 0;
+ fillbytes charbuf; // buffer to allocate small strings
+ charbuf.init();
+
+ // Third band: Read the char values in the unshared suffixes:
+ cp_Utf8_chars.readData(cp_Utf8_suffix.getIntTotal());
+ for (i = 0; i < len; i++)
+ {
+ int suffix = (i < SUFFIX_SKIP_1) ? 0 : cp_Utf8_suffix.getInt();
+ if (suffix < 0)
+ {
+ unpack_abort("bad utf8 suffix");
+ }
+ if (suffix == 0 && i >= SUFFIX_SKIP_1)
+ {
+ // chars are packed in cp_Utf8_big_chars
+ nbigsuf += 1;
+ continue;
+ }
+ bytes &chars = allsuffixes[i];
+ uint32_t size3 = suffix * 3; // max Utf8 length
+ bool isMalloc = (suffix > SMALL);
+ if (isMalloc)
+ {
+ chars.malloc(size3);
+ }
+ else
+ {
+ if (!charbuf.canAppend(size3 + 1))
+ {
+ assert(charbuf.allocated == 0 || tmallocs.contains(charbuf.base()));
+ charbuf.init(CHUNK); // Reset to new buffer.
+ tmallocs.add(charbuf.base());
+ }
+ chars.set(charbuf.grow(size3 + 1), size3);
+ }
+
+ byte *chp = chars.ptr;
+ for (int j = 0; j < suffix; j++)
+ {
+ unsigned short ch = cp_Utf8_chars.getInt();
+ chp = store_Utf8_char(chp, ch);
+ }
+ // shrink to fit:
+ if (isMalloc)
+ {
+ chars.realloc(chp - chars.ptr);
+ tmallocs.add(chars.ptr); // free it later
+ }
+ else
+ {
+ int shrink = (int)(chars.limit() - chp);
+ chars.len -= shrink;
+ charbuf.b.len -= shrink; // ungrow to reclaim buffer space
+ // Note that we did not reclaim the final '\0'.
+ assert(chars.limit() == charbuf.limit() - 1);
+ assert(strlen((char *)chars.ptr) == chars.len);
+ }
+ }
+ // cp_Utf8_chars.done();
+
+ // Fourth band: Go back and size the specially packed strings.
+ int maxlen = 0;
+ cp_Utf8_big_suffix.readData(nbigsuf);
+ cp_Utf8_suffix.rewind();
+ for (i = 0; i < len; i++)
+ {
+ int suffix = (i < SUFFIX_SKIP_1) ? 0 : cp_Utf8_suffix.getInt();
+ int prefix = (i < PREFIX_SKIP_2) ? 0 : cp_Utf8_prefix.getInt();
+ if (prefix < 0 || prefix + suffix < 0)
+ {
+ unpack_abort("bad utf8 prefix");
+ }
+ bytes &chars = allsuffixes[i];
+ if (suffix == 0 && i >= SUFFIX_SKIP_1)
+ {
+ suffix = cp_Utf8_big_suffix.getInt();
+ assert(chars.ptr == nullptr);
+ chars.len = suffix; // just a momentary hack
+ }
+ else
+ {
+ assert(chars.ptr != nullptr);
+ }
+ if (maxlen < prefix + suffix)
+ {
+ maxlen = prefix + suffix;
+ }
+ }
+ // cp_Utf8_suffix.done(); // will use allsuffixes[i].len (ptr!=nullptr)
+ // cp_Utf8_big_suffix.done(); // will use allsuffixes[i].len
+
+ // Fifth band(s): Get the specially packed characters.
+ cp_Utf8_big_suffix.rewind();
+ for (i = 0; i < len; i++)
+ {
+ bytes &chars = allsuffixes[i];
+ if (chars.ptr != nullptr)
+ continue; // already input
+ int suffix = (int)chars.len; // pick up the hack
+ uint32_t size3 = suffix * 3;
+ if (suffix == 0)
+ continue; // done with empty string
+ chars.malloc(size3);
+ byte *chp = chars.ptr;
+ band saved_band = cp_Utf8_big_chars;
+ cp_Utf8_big_chars.readData(suffix);
+ for (int j = 0; j < suffix; j++)
+ {
+ unsigned short ch = cp_Utf8_big_chars.getInt();
+ chp = store_Utf8_char(chp, ch);
+ }
+ chars.realloc(chp - chars.ptr);
+ tmallocs.add(chars.ptr); // free it later
+ // cp_Utf8_big_chars.done();
+ cp_Utf8_big_chars = saved_band; // reset the band for the next string
+ }
+ cp_Utf8_big_chars.readData(0); // zero chars
+ // cp_Utf8_big_chars.done();
+
+ // Finally, sew together all the prefixes and suffixes.
+ bytes bigbuf;
+ bigbuf.malloc(maxlen * 3 + 1); // max Utf8 length, plus slop for nullptr
+ int prevlen = 0; // previous string length (in chars)
+ tmallocs.add(bigbuf.ptr); // free after this block
+ cp_Utf8_prefix.rewind();
+ for (i = 0; i < len; i++)
+ {
+ bytes &chars = allsuffixes[i];
+ int prefix = (i < PREFIX_SKIP_2) ? 0 : cp_Utf8_prefix.getInt();
+ int suffix = (int)chars.len;
+ byte *fillp;
+ // by induction, the buffer is already filled with the prefix
+ // make sure the prefix value is not corrupted, though:
+ if (prefix > prevlen)
+ {
+ unpack_abort("utf8 prefix overflow");
+ return;
+ }
+ fillp = skip_Utf8_chars(bigbuf.ptr, prefix);
+ // copy the suffix into the same buffer:
+ fillp = chars.writeTo(fillp);
+ assert(bigbuf.inBounds(fillp));
+ *fillp = 0; // bigbuf must contain a well-formed Utf8 string
+ int length = (int)(fillp - bigbuf.ptr);
+ bytes &value = cpMap[i].value.b;
+ value.set(U_NEW(byte, add_size(length, 1)), length);
+ value.copyFrom(bigbuf.ptr, length);
+ // Index all Utf8 strings
+ entry *&htref = cp.hashTabRef(CONSTANT_Utf8, value);
+ if (htref == nullptr)
+ {
+ // Note that if two identical strings are transmitted,
+ // the first is taken to be the canonical one.
+ htref = &cpMap[i];
+ }
+ prevlen = prefix + suffix;
+ }
+ // cp_Utf8_prefix.done();
+
+ // Free intermediate buffers.
+ free_temps();
}
void unpacker::read_single_words(band &cp_band, entry *cpMap, int len)
{
- cp_band.readData(len);
- for (int i = 0; i < len; i++)
- {
- cpMap[i].value.i = cp_band.getInt(); // coding handles signs OK
- }
+ cp_band.readData(len);
+ for (int i = 0; i < len; i++)
+ {
+ cpMap[i].value.i = cp_band.getInt(); // coding handles signs OK
+ }
}
void unpacker::read_double_words(band &cp_bands, entry *cpMap, int len)
{
- band &cp_band_hi = cp_bands;
- band &cp_band_lo = cp_bands.nextBand();
- cp_band_hi.readData(len);
- cp_band_lo.readData(len);
- for (int i = 0; i < len; i++)
- {
- cpMap[i].value.l = cp_band_hi.getLong(cp_band_lo, true);
- }
- // cp_band_hi.done();
- // cp_band_lo.done();
+ band &cp_band_hi = cp_bands;
+ band &cp_band_lo = cp_bands.nextBand();
+ cp_band_hi.readData(len);
+ cp_band_lo.readData(len);
+ for (int i = 0; i < len; i++)
+ {
+ cpMap[i].value.l = cp_band_hi.getLong(cp_band_lo, true);
+ }
+ // cp_band_hi.done();
+ // cp_band_lo.done();
}
void unpacker::read_single_refs(band &cp_band, byte refTag, entry *cpMap, int len)
{
- assert(refTag == CONSTANT_Utf8);
- cp_band.setIndexByTag(refTag);
- cp_band.readData(len);
- int indexTag = (cp_band.bn == e_cp_Class) ? CONSTANT_Class : 0;
- for (int i = 0; i < len; i++)
- {
- entry &e = cpMap[i];
- e.refs = U_NEW(entry *, e.nrefs = 1);
- entry *utf = cp_band.getRef();
- e.refs[0] = utf;
- e.value.b = utf->value.b; // copy value of Utf8 string to self
- if (indexTag != 0)
- {
- // Maintain cross-reference:
- entry *&htref = cp.hashTabRef(indexTag, e.value.b);
- if (htref == nullptr)
- {
- // Note that if two identical classes are transmitted,
- // the first is taken to be the canonical one.
- htref = &e;
- }
- }
- }
- // cp_band.done();
+ assert(refTag == CONSTANT_Utf8);
+ cp_band.setIndexByTag(refTag);
+ cp_band.readData(len);
+ int indexTag = (cp_band.bn == e_cp_Class) ? CONSTANT_Class : 0;
+ for (int i = 0; i < len; i++)
+ {
+ entry &e = cpMap[i];
+ e.refs = U_NEW(entry *, e.nrefs = 1);
+ entry *utf = cp_band.getRef();
+ e.refs[0] = utf;
+ e.value.b = utf->value.b; // copy value of Utf8 string to self
+ if (indexTag != 0)
+ {
+ // Maintain cross-reference:
+ entry *&htref = cp.hashTabRef(indexTag, e.value.b);
+ if (htref == nullptr)
+ {
+ // Note that if two identical classes are transmitted,
+ // the first is taken to be the canonical one.
+ htref = &e;
+ }
+ }
+ }
+ // cp_band.done();
}
void unpacker::read_double_refs(band &cp_band, byte ref1Tag, byte ref2Tag, entry *cpMap,
- int len)
+ int len)
{
- band &cp_band1 = cp_band;
- band &cp_band2 = cp_band.nextBand();
- cp_band1.setIndexByTag(ref1Tag);
- cp_band2.setIndexByTag(ref2Tag);
- cp_band1.readData(len);
- cp_band2.readData(len);
- for (int i = 0; i < len; i++)
- {
- entry &e = cpMap[i];
- e.refs = U_NEW(entry *, e.nrefs = 2);
- e.refs[0] = cp_band1.getRef();
- e.refs[1] = cp_band2.getRef();
- }
- // cp_band1.done();
- // cp_band2.done();
+ band &cp_band1 = cp_band;
+ band &cp_band2 = cp_band.nextBand();
+ cp_band1.setIndexByTag(ref1Tag);
+ cp_band2.setIndexByTag(ref2Tag);
+ cp_band1.readData(len);
+ cp_band2.readData(len);
+ for (int i = 0; i < len; i++)
+ {
+ entry &e = cpMap[i];
+ e.refs = U_NEW(entry *, e.nrefs = 2);
+ e.refs[0] = cp_band1.getRef();
+ e.refs[1] = cp_band2.getRef();
+ }
+ // cp_band1.done();
+ // cp_band2.done();
}
// Cf. PackageReader.readSignatureBands
void unpacker::read_signature_values(entry *cpMap, int len)
{
- cp_Signature_form.setIndexByTag(CONSTANT_Utf8);
- cp_Signature_form.readData(len);
- int ncTotal = 0;
- int i;
- for (i = 0; i < len; i++)
- {
- entry &e = cpMap[i];
- entry &form = *cp_Signature_form.getRef();
- int nc = 0;
-
- for (const char *ncp = form.utf8String(); *ncp; ncp++)
- {
- if (*ncp == 'L')
- nc++;
- }
-
- ncTotal += nc;
- e.refs = U_NEW(entry *, cpMap[i].nrefs = 1 + nc);
- e.refs[0] = &form;
- }
- // cp_Signature_form.done();
- cp_Signature_classes.setIndexByTag(CONSTANT_Class);
- cp_Signature_classes.readData(ncTotal);
- for (i = 0; i < len; i++)
- {
- entry &e = cpMap[i];
- for (int j = 1; j < e.nrefs; j++)
- {
- e.refs[j] = cp_Signature_classes.getRef();
- }
- }
- // cp_Signature_classes.done();
+ cp_Signature_form.setIndexByTag(CONSTANT_Utf8);
+ cp_Signature_form.readData(len);
+ int ncTotal = 0;
+ int i;
+ for (i = 0; i < len; i++)
+ {
+ entry &e = cpMap[i];
+ entry &form = *cp_Signature_form.getRef();
+ int nc = 0;
+
+ for (const char *ncp = form.utf8String(); *ncp; ncp++)
+ {
+ if (*ncp == 'L')
+ nc++;
+ }
+
+ ncTotal += nc;
+ e.refs = U_NEW(entry *, cpMap[i].nrefs = 1 + nc);
+ e.refs[0] = &form;
+ }
+ // cp_Signature_form.done();
+ cp_Signature_classes.setIndexByTag(CONSTANT_Class);
+ cp_Signature_classes.readData(ncTotal);
+ for (i = 0; i < len; i++)
+ {
+ entry &e = cpMap[i];
+ for (int j = 1; j < e.nrefs; j++)
+ {
+ e.refs[j] = cp_Signature_classes.getRef();
+ }
+ }
+ // cp_Signature_classes.done();
}
// Cf. PackageReader.readConstantPool
void unpacker::read_cp()
{
- int i;
-
- for (int k = 0; k < (int)N_TAGS_IN_ORDER; k++)
- {
- byte tag = TAGS_IN_ORDER[k];
- int len = cp.tag_count[tag];
- int base = cp.tag_base[tag];
-
- entry *cpMap = &cp.entries[base];
- for (i = 0; i < len; i++)
- {
- cpMap[i].tag = tag;
- cpMap[i].inord = i;
- }
-
- switch (tag)
- {
- case CONSTANT_Utf8:
- read_Utf8_values(cpMap, len);
- break;
- case CONSTANT_Integer:
- read_single_words(cp_Int, cpMap, len);
- break;
- case CONSTANT_Float:
- read_single_words(cp_Float, cpMap, len);
- break;
- case CONSTANT_Long:
- read_double_words(cp_Long_hi /*& cp_Long_lo*/, cpMap, len);
- break;
- case CONSTANT_Double:
- read_double_words(cp_Double_hi /*& cp_Double_lo*/, cpMap, len);
- break;
- case CONSTANT_String:
- read_single_refs(cp_String, CONSTANT_Utf8, cpMap, len);
- break;
- case CONSTANT_Class:
- read_single_refs(cp_Class, CONSTANT_Utf8, cpMap, len);
- break;
- case CONSTANT_Signature:
- read_signature_values(cpMap, len);
- break;
- case CONSTANT_NameandType:
- read_double_refs(cp_Descr_name /*& cp_Descr_type*/, CONSTANT_Utf8,
- CONSTANT_Signature, cpMap, len);
- break;
- case CONSTANT_Fieldref:
- read_double_refs(cp_Field_class /*& cp_Field_desc*/, CONSTANT_Class,
- CONSTANT_NameandType, cpMap, len);
- break;
- case CONSTANT_Methodref:
- read_double_refs(cp_Method_class /*& cp_Method_desc*/, CONSTANT_Class,
- CONSTANT_NameandType, cpMap, len);
- break;
- case CONSTANT_InterfaceMethodref:
- read_double_refs(cp_Imethod_class /*& cp_Imethod_desc*/, CONSTANT_Class,
- CONSTANT_NameandType, cpMap, len);
- break;
- default:
- assert(false);
- break;
- }
- }
-
- cp.expandSignatures();
- cp.initMemberIndexes();
+ int i;
+
+ for (int k = 0; k < (int)N_TAGS_IN_ORDER; k++)
+ {
+ byte tag = TAGS_IN_ORDER[k];
+ int len = cp.tag_count[tag];
+ int base = cp.tag_base[tag];
+
+ entry *cpMap = &cp.entries[base];
+ for (i = 0; i < len; i++)
+ {
+ cpMap[i].tag = tag;
+ cpMap[i].inord = i;
+ }
+
+ switch (tag)
+ {
+ case CONSTANT_Utf8:
+ read_Utf8_values(cpMap, len);
+ break;
+ case CONSTANT_Integer:
+ read_single_words(cp_Int, cpMap, len);
+ break;
+ case CONSTANT_Float:
+ read_single_words(cp_Float, cpMap, len);
+ break;
+ case CONSTANT_Long:
+ read_double_words(cp_Long_hi /*& cp_Long_lo*/, cpMap, len);
+ break;
+ case CONSTANT_Double:
+ read_double_words(cp_Double_hi /*& cp_Double_lo*/, cpMap, len);
+ break;
+ case CONSTANT_String:
+ read_single_refs(cp_String, CONSTANT_Utf8, cpMap, len);
+ break;
+ case CONSTANT_Class:
+ read_single_refs(cp_Class, CONSTANT_Utf8, cpMap, len);
+ break;
+ case CONSTANT_Signature:
+ read_signature_values(cpMap, len);
+ break;
+ case CONSTANT_NameandType:
+ read_double_refs(cp_Descr_name /*& cp_Descr_type*/, CONSTANT_Utf8,
+ CONSTANT_Signature, cpMap, len);
+ break;
+ case CONSTANT_Fieldref:
+ read_double_refs(cp_Field_class /*& cp_Field_desc*/, CONSTANT_Class,
+ CONSTANT_NameandType, cpMap, len);
+ break;
+ case CONSTANT_Methodref:
+ read_double_refs(cp_Method_class /*& cp_Method_desc*/, CONSTANT_Class,
+ CONSTANT_NameandType, cpMap, len);
+ break;
+ case CONSTANT_InterfaceMethodref:
+ read_double_refs(cp_Imethod_class /*& cp_Imethod_desc*/, CONSTANT_Class,
+ CONSTANT_NameandType, cpMap, len);
+ break;
+ default:
+ assert(false);
+ break;
+ }
+ }
+
+ cp.expandSignatures();
+ cp.initMemberIndexes();
#define SNAME(n, s) #s "\0"
- const char *symNames = (ALL_ATTR_DO(SNAME) "<init>");
+ const char *symNames = (ALL_ATTR_DO(SNAME) "<init>");
#undef SNAME
- for (int sn = 0; sn < constant_pool::s_LIMIT; sn++)
- {
- assert(symNames[0] >= '0' && symNames[0] <= 'Z'); // sanity
- bytes name;
- name.set(symNames);
- if (name.len > 0 && name.ptr[0] != '0')
- {
- cp.sym[sn] = cp.ensureUtf8(name);
- }
- symNames += name.len + 1; // skip trailing nullptr to next name
- }
-
- band::initIndexes(this);
+ for (int sn = 0; sn < constant_pool::s_LIMIT; sn++)
+ {
+ assert(symNames[0] >= '0' && symNames[0] <= 'Z'); // sanity
+ bytes name;
+ name.set(symNames);
+ if (name.len > 0 && name.ptr[0] != '0')
+ {
+ cp.sym[sn] = cp.ensureUtf8(name);
+ }
+ symNames += name.len + 1; // skip trailing nullptr to next name
+ }
+
+ band::initIndexes(this);
}
static band *no_bands[] = {nullptr}; // shared empty body
inline band &unpacker::attr_definitions::fixed_band(int e_class_xxx)
{
- return u->all_bands[xxx_flags_hi_bn + (e_class_xxx - e_class_flags_hi)];
+ return u->all_bands[xxx_flags_hi_bn + (e_class_xxx - e_class_flags_hi)];
}
inline band &unpacker::attr_definitions::xxx_flags_hi()
{
- return fixed_band(e_class_flags_hi);
+ return fixed_band(e_class_flags_hi);
}
inline band &unpacker::attr_definitions::xxx_flags_lo()
{
- return fixed_band(e_class_flags_lo);
+ return fixed_band(e_class_flags_lo);
}
inline band &unpacker::attr_definitions::xxx_attr_count()
{
- return fixed_band(e_class_attr_count);
+ return fixed_band(e_class_attr_count);
}
inline band &unpacker::attr_definitions::xxx_attr_indexes()
{
- return fixed_band(e_class_attr_indexes);
+ return fixed_band(e_class_attr_indexes);
}
inline band &unpacker::attr_definitions::xxx_attr_calls()
{
- return fixed_band(e_class_attr_calls);
+ return fixed_band(e_class_attr_calls);
}
inline unpacker::layout_definition *
unpacker::attr_definitions::defineLayout(int idx, entry *nameEntry, const char *layout)
{
- const char *name = nameEntry->value.b.strval();
- layout_definition *lo = defineLayout(idx, name, layout);
- lo->nameEntry = nameEntry;
- return lo;
+ const char *name = nameEntry->value.b.strval();
+ layout_definition *lo = defineLayout(idx, name, layout);
+ lo->nameEntry = nameEntry;
+ return lo;
}
unpacker::layout_definition *unpacker::attr_definitions::defineLayout(int idx, const char *name,
- const char *layout)
+ const char *layout)
{
- assert(flag_limit != 0); // must be set up already
- if (idx >= 0)
- {
- // Fixed attr.
- if (idx >= (int)flag_limit)
- unpack_abort("attribute index too large");
- if (isRedefined(idx))
- unpack_abort("redefined attribute index");
- redef |= ((uint64_t)1 << idx);
- }
- else
- {
- idx = flag_limit + overflow_count.length();
- overflow_count.add(0); // make a new counter
- }
- layout_definition *lo = U_NEW(layout_definition, 1);
- lo->idx = idx;
- lo->name = name;
- lo->layout = layout;
- for (int adds = (idx + 1) - layouts.length(); adds > 0; adds--)
- {
- layouts.add(nullptr);
- }
- layouts.get(idx) = lo;
- return lo;
+ assert(flag_limit != 0); // must be set up already
+ if (idx >= 0)
+ {
+ // Fixed attr.
+ if (idx >= (int)flag_limit)
+ unpack_abort("attribute index too large");
+ if (isRedefined(idx))
+ unpack_abort("redefined attribute index");
+ redef |= ((uint64_t)1 << idx);
+ }
+ else
+ {
+ idx = flag_limit + overflow_count.length();
+ overflow_count.add(0); // make a new counter
+ }
+ layout_definition *lo = U_NEW(layout_definition, 1);
+ lo->idx = idx;
+ lo->name = name;
+ lo->layout = layout;
+ for (int adds = (idx + 1) - layouts.length(); adds > 0; adds--)
+ {
+ layouts.add(nullptr);
+ }
+ layouts.get(idx) = lo;
+ return lo;
}
band **unpacker::attr_definitions::buildBands(unpacker::layout_definition *lo)
{
- int i;
- if (lo->elems != nullptr)
- return lo->bands();
- if (lo->layout[0] == '\0')
- {
- lo->elems = no_bands;
- }
- else
- {
- // Create bands for this attribute by parsing the layout.
- bool hasCallables = lo->hasCallables();
- bands_made = 0x10000; // base number for bands made
- const char *lp = lo->layout;
- lp = parseLayout(lp, lo->elems, -1);
- if (lp[0] != '\0' || band_stack.length() > 0)
- {
- unpack_abort("garbage at end of layout");
- }
- band_stack.popTo(0);
-
- // Fix up callables to point at their callees.
- band **bands = lo->elems;
- assert(bands == lo->bands());
- int num_callables = 0;
- if (hasCallables)
- {
- while (bands[num_callables] != nullptr)
- {
- if (bands[num_callables]->le_kind != EK_CBLE)
- {
- unpack_abort("garbage mixed with callables");
- break;
- }
- num_callables += 1;
- }
- }
- for (i = 0; i < calls_to_link.length(); i++)
- {
- band &call = *(band *)calls_to_link.get(i);
- assert(call.le_kind == EK_CALL);
- // Determine the callee.
- int call_num = call.le_len;
- if (call_num < 0 || call_num >= num_callables)
- {
- unpack_abort("bad call in layout");
- break;
- }
- band &cble = *bands[call_num];
- // Link the call to it.
- call.le_body[0] = &cble;
- // Distinguish backward calls and callables:
- assert(cble.le_kind == EK_CBLE);
- // FIXME: hit this one
- // assert(cble.le_len == call_num);
- cble.le_back |= call.le_back;
- }
- calls_to_link.popTo(0);
- }
- return lo->elems;
+ int i;
+ if (lo->elems != nullptr)
+ return lo->bands();
+ if (lo->layout[0] == '\0')
+ {
+ lo->elems = no_bands;
+ }
+ else
+ {
+ // Create bands for this attribute by parsing the layout.
+ bool hasCallables = lo->hasCallables();
+ bands_made = 0x10000; // base number for bands made
+ const char *lp = lo->layout;
+ lp = parseLayout(lp, lo->elems, -1);
+ if (lp[0] != '\0' || band_stack.length() > 0)
+ {
+ unpack_abort("garbage at end of layout");
+ }
+ band_stack.popTo(0);
+
+ // Fix up callables to point at their callees.
+ band **bands = lo->elems;
+ assert(bands == lo->bands());
+ int num_callables = 0;
+ if (hasCallables)
+ {
+ while (bands[num_callables] != nullptr)
+ {
+ if (bands[num_callables]->le_kind != EK_CBLE)
+ {
+ unpack_abort("garbage mixed with callables");
+ break;
+ }
+ num_callables += 1;
+ }
+ }
+ for (i = 0; i < calls_to_link.length(); i++)
+ {
+ band &call = *(band *)calls_to_link.get(i);
+ assert(call.le_kind == EK_CALL);
+ // Determine the callee.
+ int call_num = call.le_len;
+ if (call_num < 0 || call_num >= num_callables)
+ {
+ unpack_abort("bad call in layout");
+ break;
+ }
+ band &cble = *bands[call_num];
+ // Link the call to it.
+ call.le_body[0] = &cble;
+ // Distinguish backward calls and callables:
+ assert(cble.le_kind == EK_CBLE);
+ // FIXME: hit this one
+ // assert(cble.le_len == call_num);
+ cble.le_back |= call.le_back;
+ }
+ calls_to_link.popTo(0);
+ }
+ return lo->elems;
}
/* attribute layout language parser
attribute_layout:
- ( layout_element )* | ( callable )+
+ ( layout_element )* | ( callable )+
layout_element:
- ( integral | replication | union | call | reference )
+ ( integral | replication | union | call | reference )
callable:
- '[' body ']'
+ '[' body ']'
body:
- ( layout_element )+
+ ( layout_element )+
integral:
- ( unsigned_int | signed_int | bc_index | bc_offset | flag )
+ ( unsigned_int | signed_int | bc_index | bc_offset | flag )
unsigned_int:
- uint_type
+ uint_type
signed_int:
- 'S' uint_type
+ 'S' uint_type
any_int:
- ( unsigned_int | signed_int )
+ ( unsigned_int | signed_int )
bc_index:
- ( 'P' uint_type | 'PO' uint_type )
+ ( 'P' uint_type | 'PO' uint_type )
bc_offset:
- 'O' any_int
+ 'O' any_int
flag:
- 'F' uint_type
+ 'F' uint_type
uint_type:
- ( 'B' | 'H' | 'I' | 'V' )
+ ( 'B' | 'H' | 'I' | 'V' )
replication:
- 'N' uint_type '[' body ']'
+ 'N' uint_type '[' body ']'
union:
- 'T' any_int (union_case)* '(' ')' '[' (body)? ']'
+ 'T' any_int (union_case)* '(' ')' '[' (body)? ']'
union_case:
- '(' union_case_tag (',' union_case_tag)* ')' '[' (body)? ']'
+ '(' union_case_tag (',' union_case_tag)* ')' '[' (body)? ']'
union_case_tag:
- ( numeral | numeral '-' numeral )
+ ( numeral | numeral '-' numeral )
call:
- '(' numeral ')'
+ '(' numeral ')'
reference:
- reference_type ( 'N' )? uint_type
+ reference_type ( 'N' )? uint_type
reference_type:
- ( constant_ref | schema_ref | utf8_ref | untyped_ref )
+ ( constant_ref | schema_ref | utf8_ref | untyped_ref )
constant_ref:
- ( 'KI' | 'KJ' | 'KF' | 'KD' | 'KS' | 'KQ' )
+ ( 'KI' | 'KJ' | 'KF' | 'KD' | 'KS' | 'KQ' )
schema_ref:
- ( 'RC' | 'RS' | 'RD' | 'RF' | 'RM' | 'RI' )
+ ( 'RC' | 'RS' | 'RD' | 'RF' | 'RM' | 'RI' )
utf8_ref:
- 'RU'
+ 'RU'
untyped_ref:
- 'RQ'
+ 'RQ'
numeral:
- '(' ('-')? (digit)+ ')'
+ '(' ('-')? (digit)+ ')'
digit:
- ( '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' )
+ ( '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' )
*/
const char *unpacker::attr_definitions::parseIntLayout(const char *lp, band *&res, byte le_kind,
- bool can_be_signed)
+ bool can_be_signed)
{
- band *b = U_NEW(band, 1);
- char le = *lp++;
- int spec = UNSIGNED5_spec;
- if (le == 'S' && can_be_signed)
- {
- // Note: This is the last use of sign. There is no 'EF_SIGN'.
- spec = SIGNED5_spec;
- le = *lp++;
- }
- else if (le == 'B')
- {
- spec = BYTE1_spec; // unsigned byte
- }
- b->init(u, bands_made++, spec);
- b->le_kind = le_kind;
- int le_len = 0;
- switch (le)
- {
- case 'B':
- le_len = 1;
- break;
- case 'H':
- le_len = 2;
- break;
- case 'I':
- le_len = 4;
- break;
- case 'V':
- le_len = 0;
- break;
- default:
- unpack_abort("bad layout element");
- }
- b->le_len = le_len;
- band_stack.add(b);
- res = b;
- return lp;
+ band *b = U_NEW(band, 1);
+ char le = *lp++;
+ int spec = UNSIGNED5_spec;
+ if (le == 'S' && can_be_signed)
+ {
+ // Note: This is the last use of sign. There is no 'EF_SIGN'.
+ spec = SIGNED5_spec;
+ le = *lp++;
+ }
+ else if (le == 'B')
+ {
+ spec = BYTE1_spec; // unsigned byte
+ }
+ b->init(u, bands_made++, spec);
+ b->le_kind = le_kind;
+ int le_len = 0;
+ switch (le)
+ {
+ case 'B':
+ le_len = 1;
+ break;
+ case 'H':
+ le_len = 2;
+ break;
+ case 'I':
+ le_len = 4;
+ break;
+ case 'V':
+ le_len = 0;
+ break;
+ default:
+ unpack_abort("bad layout element");
+ }
+ b->le_len = le_len;
+ band_stack.add(b);
+ res = b;
+ return lp;
}
const char *unpacker::attr_definitions::parseNumeral(const char *lp, int &res)
{
- bool sgn = false;
- if (*lp == '0')
- {
- res = 0;
- return lp + 1;
- } // special case '0'
- if (*lp == '-')
- {
- sgn = true;
- lp++;
- }
- const char *dp = lp;
- int con = 0;
- while (*dp >= '0' && *dp <= '9')
- {
- int con0 = con;
- con *= 10;
- con += (*dp++) - '0';
- if (con <= con0)
- {
- con = -1;
- break;
- } // numeral overflow
- }
- if (lp == dp)
- {
- unpack_abort("missing numeral in layout");
- }
- lp = dp;
- if (con < 0 && !(sgn && con == -con))
- {
- // (Portability note: Misses the error if int is not 32 bits.)
- unpack_abort("numeral overflow");
- }
- if (sgn)
- con = -con;
- res = con;
- return lp;
+ bool sgn = false;
+ if (*lp == '0')
+ {
+ res = 0;
+ return lp + 1;
+ } // special case '0'
+ if (*lp == '-')
+ {
+ sgn = true;
+ lp++;
+ }
+ const char *dp = lp;
+ int con = 0;
+ while (*dp >= '0' && *dp <= '9')
+ {
+ int con0 = con;
+ con *= 10;
+ con += (*dp++) - '0';
+ if (con <= con0)
+ {
+ con = -1;
+ break;
+ } // numeral overflow
+ }
+ if (lp == dp)
+ {
+ unpack_abort("missing numeral in layout");
+ }
+ lp = dp;
+ if (con < 0 && !(sgn && con == -con))
+ {
+ // (Portability note: Misses the error if int is not 32 bits.)
+ unpack_abort("numeral overflow");
+ }
+ if (sgn)
+ con = -con;
+ res = con;
+ return lp;
}
band **unpacker::attr_definitions::popBody(int bs_base)
{
- // Return everything that was pushed, as a nullptr-terminated pointer array.
- int bs_limit = band_stack.length();
- if (bs_base == bs_limit)
- {
- return no_bands;
- }
- else
- {
- int nb = bs_limit - bs_base;
- band **res = U_NEW(band *, add_size(nb, 1));
- for (int i = 0; i < nb; i++)
- {
- band *b = (band *)band_stack.get(bs_base + i);
- res[i] = b;
- }
- band_stack.popTo(bs_base);
- return res;
- }
+ // Return everything that was pushed, as a nullptr-terminated pointer array.
+ int bs_limit = band_stack.length();
+ if (bs_base == bs_limit)
+ {
+ return no_bands;
+ }
+ else
+ {
+ int nb = bs_limit - bs_base;
+ band **res = U_NEW(band *, add_size(nb, 1));
+ for (int i = 0; i < nb; i++)
+ {
+ band *b = (band *)band_stack.get(bs_base + i);
+ res[i] = b;
+ }
+ band_stack.popTo(bs_base);
+ return res;
+ }
}
const char *unpacker::attr_definitions::parseLayout(const char *lp, band **&res, int curCble)
{
- int bs_base = band_stack.length();
- bool top_level = (bs_base == 0);
- band *b;
- enum
- {
- can_be_signed = true
- }; // optional arg to parseIntLayout
-
- for (bool done = false; !done;)
- {
- switch (*lp++)
- {
- case 'B':
- case 'H':
- case 'I':
- case 'V': // unsigned_int
- case 'S': // signed_int
- --lp; // reparse
- case 'F':
- lp = parseIntLayout(lp, b, EK_INT);
- break;
- case 'P':
- {
- int le_bci = EK_BCI;
- if (*lp == 'O')
- {
- ++lp;
- le_bci = EK_BCID;
- }
- assert(*lp != 'S'); // no PSH, etc.
- lp = parseIntLayout(lp, b, EK_INT);
- b->le_bci = le_bci;
- if (le_bci == EK_BCI)
- b->defc = coding::findBySpec(BCI5_spec);
- else
- b->defc = coding::findBySpec(BRANCH5_spec);
- }
- break;
- case 'O':
- lp = parseIntLayout(lp, b, EK_INT, can_be_signed);
- b->le_bci = EK_BCO;
- b->defc = coding::findBySpec(BRANCH5_spec);
- break;
- case 'N': // replication: 'N' uint32_t '[' elem ... ']'
- lp = parseIntLayout(lp, b, EK_REPL);
- assert(*lp == '[');
- ++lp;
- lp = parseLayout(lp, b->le_body, curCble);
- break;
- case 'T': // union: 'T' any_int union_case* '(' ')' '[' body ']'
- lp = parseIntLayout(lp, b, EK_UN, can_be_signed);
- {
- int union_base = band_stack.length();
- for (;;)
- { // for each case
- band &k_case = *U_NEW(band, 1);
- band_stack.add(&k_case);
- k_case.le_kind = EK_CASE;
- k_case.bn = bands_made++;
- if (*lp++ != '(')
- {
- unpack_abort("bad union case");
- return "";
- }
- if (*lp++ != ')')
- {
- --lp; // reparse
- // Read some case values. (Use band_stack for temp. storage.)
- int case_base = band_stack.length();
- for (;;)
- {
- int caseval = 0;
- lp = parseNumeral(lp, caseval);
- band_stack.add((void *)(size_t)caseval);
- if (*lp == '-')
- {
- // new in version 160, allow (1-5) for (1,2,3,4,5)
- if (u->majver < JAVA6_PACKAGE_MAJOR_VERSION)
- {
- unpack_abort(
- "bad range in union case label (old archive format)");
- return "";
- }
- int caselimit = caseval;
- lp++;
- lp = parseNumeral(lp, caselimit);
- if (caseval >= caselimit ||
- (uint32_t)(caselimit - caseval) > 0x10000)
- {
- // Note: 0x10000 is arbitrary implementation restriction.
- // We can remove it later if it's important to.
- unpack_abort("bad range in union case label");
- }
- for (;;)
- {
- ++caseval;
- band_stack.add((void *)(size_t)caseval);
- if (caseval == caselimit)
- break;
- }
- }
- if (*lp != ',')
- break;
- lp++;
- }
- if (*lp++ != ')')
- {
- unpack_abort("bad case label");
- }
- // save away the case labels
- int ntags = band_stack.length() - case_base;
- int *tags = U_NEW(int, add_size(ntags, 1));
- k_case.le_casetags = tags;
- *tags++ = ntags;
- for (int i = 0; i < ntags; i++)
- {
- *tags++ = ptrlowbits(band_stack.get(case_base + i));
- }
- band_stack.popTo(case_base);
- }
- // Got le_casetags. Now grab the body.
- assert(*lp == '[');
- ++lp;
- lp = parseLayout(lp, k_case.le_body, curCble);
- if (k_case.le_casetags == nullptr)
- break; // done
- }
- b->le_body = popBody(union_base);
- }
- break;
- case '(': // call: '(' -?NN* ')'
- {
- band &call = *U_NEW(band, 1);
- band_stack.add(&call);
- call.le_kind = EK_CALL;
- call.bn = bands_made++;
- call.le_body = U_NEW(band *, 2); // fill in later
- int call_num = 0;
- lp = parseNumeral(lp, call_num);
- call.le_back = (call_num <= 0);
- call_num += curCble; // numeral is self-relative offset
- call.le_len = call_num; // use le_len as scratch
- calls_to_link.add(&call);
- if (*lp++ != ')')
- {
- unpack_abort("bad call label");
- }
- }
- break;
- case 'K': // reference_type: constant_ref
- case 'R': // reference_type: schema_ref
- {
- int ixTag = CONSTANT_None;
- if (lp[-1] == 'K')
- {
- switch (*lp++)
- {
- case 'I':
- ixTag = CONSTANT_Integer;
- break;
- case 'J':
- ixTag = CONSTANT_Long;
- break;
- case 'F':
- ixTag = CONSTANT_Float;
- break;
- case 'D':
- ixTag = CONSTANT_Double;
- break;
- case 'S':
- ixTag = CONSTANT_String;
- break;
- case 'Q':
- ixTag = CONSTANT_Literal;
- break;
- }
- }
- else
- {
- switch (*lp++)
- {
- case 'C':
- ixTag = CONSTANT_Class;
- break;
- case 'S':
- ixTag = CONSTANT_Signature;
- break;
- case 'D':
- ixTag = CONSTANT_NameandType;
- break;
- case 'F':
- ixTag = CONSTANT_Fieldref;
- break;
- case 'M':
- ixTag = CONSTANT_Methodref;
- break;
- case 'I':
- ixTag = CONSTANT_InterfaceMethodref;
- break;
- case 'U':
- ixTag = CONSTANT_Utf8;
- break; // utf8_ref
- case 'Q':
- ixTag = CONSTANT_All;
- break; // untyped_ref
- }
- }
- if (ixTag == CONSTANT_None)
- {
- unpack_abort("bad reference layout");
- break;
- }
- bool nullOK = false;
- if (*lp == 'N')
- {
- nullOK = true;
- lp++;
- }
- lp = parseIntLayout(lp, b, EK_REF);
- b->defc = coding::findBySpec(UNSIGNED5_spec);
- b->initRef(ixTag, nullOK);
- }
- break;
- case '[':
- {
- // [callable1][callable2]...
- if (!top_level)
- {
- unpack_abort("bad nested callable");
- break;
- }
- curCble += 1;
- band &cble = *U_NEW(band, 1);
- band_stack.add(&cble);
- cble.le_kind = EK_CBLE;
- cble.bn = bands_made++;
- lp = parseLayout(lp, cble.le_body, curCble);
- }
- break;
- case ']':
- // Hit a closing brace. This ends whatever body we were in.
- done = true;
- break;
- case '\0':
- // Hit a nullptr. Also ends the (top-level) body.
- --lp; // back up, so caller can see the nullptr also
- done = true;
- break;
- default:
- unpack_abort("bad layout");
- }
- }
-
- // Return the accumulated bands:
- res = popBody(bs_base);
- return lp;
+ int bs_base = band_stack.length();
+ bool top_level = (bs_base == 0);
+ band *b;
+ enum
+ {
+ can_be_signed = true
+ }; // optional arg to parseIntLayout
+
+ for (bool done = false; !done;)
+ {
+ switch (*lp++)
+ {
+ case 'B':
+ case 'H':
+ case 'I':
+ case 'V': // unsigned_int
+ case 'S': // signed_int
+ --lp; // reparse
+ case 'F':
+ lp = parseIntLayout(lp, b, EK_INT);
+ break;
+ case 'P':
+ {
+ int le_bci = EK_BCI;
+ if (*lp == 'O')
+ {
+ ++lp;
+ le_bci = EK_BCID;
+ }
+ assert(*lp != 'S'); // no PSH, etc.
+ lp = parseIntLayout(lp, b, EK_INT);
+ b->le_bci = le_bci;
+ if (le_bci == EK_BCI)
+ b->defc = coding::findBySpec(BCI5_spec);
+ else
+ b->defc = coding::findBySpec(BRANCH5_spec);
+ }
+ break;
+ case 'O':
+ lp = parseIntLayout(lp, b, EK_INT, can_be_signed);
+ b->le_bci = EK_BCO;
+ b->defc = coding::findBySpec(BRANCH5_spec);
+ break;
+ case 'N': // replication: 'N' uint32_t '[' elem ... ']'
+ lp = parseIntLayout(lp, b, EK_REPL);
+ assert(*lp == '[');
+ ++lp;
+ lp = parseLayout(lp, b->le_body, curCble);
+ break;
+ case 'T': // union: 'T' any_int union_case* '(' ')' '[' body ']'
+ lp = parseIntLayout(lp, b, EK_UN, can_be_signed);
+ {
+ int union_base = band_stack.length();
+ for (;;)
+ { // for each case
+ band &k_case = *U_NEW(band, 1);
+ band_stack.add(&k_case);
+ k_case.le_kind = EK_CASE;
+ k_case.bn = bands_made++;
+ if (*lp++ != '(')
+ {
+ unpack_abort("bad union case");
+ return "";
+ }
+ if (*lp++ != ')')
+ {
+ --lp; // reparse
+ // Read some case values. (Use band_stack for temp. storage.)
+ int case_base = band_stack.length();
+ for (;;)
+ {
+ int caseval = 0;
+ lp = parseNumeral(lp, caseval);
+ band_stack.add((void *)(size_t)caseval);
+ if (*lp == '-')
+ {
+ // new in version 160, allow (1-5) for (1,2,3,4,5)
+ if (u->majver < JAVA6_PACKAGE_MAJOR_VERSION)
+ {
+ unpack_abort(
+ "bad range in union case label (old archive format)");
+ return "";
+ }
+ int caselimit = caseval;
+ lp++;
+ lp = parseNumeral(lp, caselimit);
+ if (caseval >= caselimit ||
+ (uint32_t)(caselimit - caseval) > 0x10000)
+ {
+ // Note: 0x10000 is arbitrary implementation restriction.
+ // We can remove it later if it's important to.
+ unpack_abort("bad range in union case label");
+ }
+ for (;;)
+ {
+ ++caseval;
+ band_stack.add((void *)(size_t)caseval);
+ if (caseval == caselimit)
+ break;
+ }
+ }
+ if (*lp != ',')
+ break;
+ lp++;
+ }
+ if (*lp++ != ')')
+ {
+ unpack_abort("bad case label");
+ }
+ // save away the case labels
+ int ntags = band_stack.length() - case_base;
+ int *tags = U_NEW(int, add_size(ntags, 1));
+ k_case.le_casetags = tags;
+ *tags++ = ntags;
+ for (int i = 0; i < ntags; i++)
+ {
+ *tags++ = ptrlowbits(band_stack.get(case_base + i));
+ }
+ band_stack.popTo(case_base);
+ }
+ // Got le_casetags. Now grab the body.
+ assert(*lp == '[');
+ ++lp;
+ lp = parseLayout(lp, k_case.le_body, curCble);
+ if (k_case.le_casetags == nullptr)
+ break; // done
+ }
+ b->le_body = popBody(union_base);
+ }
+ break;
+ case '(': // call: '(' -?NN* ')'
+ {
+ band &call = *U_NEW(band, 1);
+ band_stack.add(&call);
+ call.le_kind = EK_CALL;
+ call.bn = bands_made++;
+ call.le_body = U_NEW(band *, 2); // fill in later
+ int call_num = 0;
+ lp = parseNumeral(lp, call_num);
+ call.le_back = (call_num <= 0);
+ call_num += curCble; // numeral is self-relative offset
+ call.le_len = call_num; // use le_len as scratch
+ calls_to_link.add(&call);
+ if (*lp++ != ')')
+ {
+ unpack_abort("bad call label");
+ }
+ }
+ break;
+ case 'K': // reference_type: constant_ref
+ case 'R': // reference_type: schema_ref
+ {
+ int ixTag = CONSTANT_None;
+ if (lp[-1] == 'K')
+ {
+ switch (*lp++)
+ {
+ case 'I':
+ ixTag = CONSTANT_Integer;
+ break;
+ case 'J':
+ ixTag = CONSTANT_Long;
+ break;
+ case 'F':
+ ixTag = CONSTANT_Float;
+ break;
+ case 'D':
+ ixTag = CONSTANT_Double;
+ break;
+ case 'S':
+ ixTag = CONSTANT_String;
+ break;
+ case 'Q':
+ ixTag = CONSTANT_Literal;
+ break;
+ }
+ }
+ else
+ {
+ switch (*lp++)
+ {
+ case 'C':
+ ixTag = CONSTANT_Class;
+ break;
+ case 'S':
+ ixTag = CONSTANT_Signature;
+ break;
+ case 'D':
+ ixTag = CONSTANT_NameandType;
+ break;
+ case 'F':
+ ixTag = CONSTANT_Fieldref;
+ break;
+ case 'M':
+ ixTag = CONSTANT_Methodref;
+ break;
+ case 'I':
+ ixTag = CONSTANT_InterfaceMethodref;
+ break;
+ case 'U':
+ ixTag = CONSTANT_Utf8;
+ break; // utf8_ref
+ case 'Q':
+ ixTag = CONSTANT_All;
+ break; // untyped_ref
+ }
+ }
+ if (ixTag == CONSTANT_None)
+ {
+ unpack_abort("bad reference layout");
+ break;
+ }
+ bool nullOK = false;
+ if (*lp == 'N')
+ {
+ nullOK = true;
+ lp++;
+ }
+ lp = parseIntLayout(lp, b, EK_REF);
+ b->defc = coding::findBySpec(UNSIGNED5_spec);
+ b->initRef(ixTag, nullOK);
+ }
+ break;
+ case '[':
+ {
+ // [callable1][callable2]...
+ if (!top_level)
+ {
+ unpack_abort("bad nested callable");
+ break;
+ }
+ curCble += 1;
+ band &cble = *U_NEW(band, 1);
+ band_stack.add(&cble);
+ cble.le_kind = EK_CBLE;
+ cble.bn = bands_made++;
+ lp = parseLayout(lp, cble.le_body, curCble);
+ }
+ break;
+ case ']':
+ // Hit a closing brace. This ends whatever body we were in.
+ done = true;
+ break;
+ case '\0':
+ // Hit a nullptr. Also ends the (top-level) body.
+ --lp; // back up, so caller can see the nullptr also
+ done = true;
+ break;
+ default:
+ unpack_abort("bad layout");
+ }
+ }
+
+ // Return the accumulated bands:
+ res = popBody(bs_base);
+ return lp;
}
void unpacker::read_attr_defs()
{
- int i;
-
- // Tell each AD which attrc it is and where its fixed flags are:
- attr_defs[ATTR_CONTEXT_CLASS].attrc = ATTR_CONTEXT_CLASS;
- attr_defs[ATTR_CONTEXT_CLASS].xxx_flags_hi_bn = e_class_flags_hi;
- attr_defs[ATTR_CONTEXT_FIELD].attrc = ATTR_CONTEXT_FIELD;
- attr_defs[ATTR_CONTEXT_FIELD].xxx_flags_hi_bn = e_field_flags_hi;
- attr_defs[ATTR_CONTEXT_METHOD].attrc = ATTR_CONTEXT_METHOD;
- attr_defs[ATTR_CONTEXT_METHOD].xxx_flags_hi_bn = e_method_flags_hi;
- attr_defs[ATTR_CONTEXT_CODE].attrc = ATTR_CONTEXT_CODE;
- attr_defs[ATTR_CONTEXT_CODE].xxx_flags_hi_bn = e_code_flags_hi;
-
- // Decide whether bands for the optional high flag words are present.
- attr_defs[ATTR_CONTEXT_CLASS]
- .setHaveLongFlags((archive_options & AO_HAVE_CLASS_FLAGS_HI) != 0);
- attr_defs[ATTR_CONTEXT_FIELD]
- .setHaveLongFlags((archive_options & AO_HAVE_FIELD_FLAGS_HI) != 0);
- attr_defs[ATTR_CONTEXT_METHOD]
- .setHaveLongFlags((archive_options & AO_HAVE_METHOD_FLAGS_HI) != 0);
- attr_defs[ATTR_CONTEXT_CODE]
- .setHaveLongFlags((archive_options & AO_HAVE_CODE_FLAGS_HI) != 0);
-
- // Set up built-in attrs.
- // (The simple ones are hard-coded. The metadata layouts are not.)
- const char *md_layout = (
+ int i;
+
+ // Tell each AD which attrc it is and where its fixed flags are:
+ attr_defs[ATTR_CONTEXT_CLASS].attrc = ATTR_CONTEXT_CLASS;
+ attr_defs[ATTR_CONTEXT_CLASS].xxx_flags_hi_bn = e_class_flags_hi;
+ attr_defs[ATTR_CONTEXT_FIELD].attrc = ATTR_CONTEXT_FIELD;
+ attr_defs[ATTR_CONTEXT_FIELD].xxx_flags_hi_bn = e_field_flags_hi;
+ attr_defs[ATTR_CONTEXT_METHOD].attrc = ATTR_CONTEXT_METHOD;
+ attr_defs[ATTR_CONTEXT_METHOD].xxx_flags_hi_bn = e_method_flags_hi;
+ attr_defs[ATTR_CONTEXT_CODE].attrc = ATTR_CONTEXT_CODE;
+ attr_defs[ATTR_CONTEXT_CODE].xxx_flags_hi_bn = e_code_flags_hi;
+
+ // Decide whether bands for the optional high flag words are present.
+ attr_defs[ATTR_CONTEXT_CLASS]
+ .setHaveLongFlags((archive_options & AO_HAVE_CLASS_FLAGS_HI) != 0);
+ attr_defs[ATTR_CONTEXT_FIELD]
+ .setHaveLongFlags((archive_options & AO_HAVE_FIELD_FLAGS_HI) != 0);
+ attr_defs[ATTR_CONTEXT_METHOD]
+ .setHaveLongFlags((archive_options & AO_HAVE_METHOD_FLAGS_HI) != 0);
+ attr_defs[ATTR_CONTEXT_CODE]
+ .setHaveLongFlags((archive_options & AO_HAVE_CODE_FLAGS_HI) != 0);
+
+ // Set up built-in attrs.
+ // (The simple ones are hard-coded. The metadata layouts are not.)
+ const char *md_layout = (
// parameter annotations:
#define MDL0 "[NB[(1)]]"
- MDL0
+ MDL0
// annotations:
#define MDL1 \
- "[NH[(1)]]" \
- "[RSHNH[RUH(1)]]"
- MDL1
- // member_value:
- "[TB"
- "(66,67,73,83,90)[KIH]"
- "(68)[KDH]"
- "(70)[KFH]"
- "(74)[KJH]"
- "(99)[RSH]"
- "(101)[RSHRUH]"
- "(115)[RUH]"
- "(91)[NH[(0)]]"
- "(64)["
- // nested annotation:
- "RSH"
- "NH[RUH(0)]"
- "]"
- "()[]"
- "]");
-
- const char *md_layout_P = md_layout;
- const char *md_layout_A = md_layout + strlen(MDL0);
- const char *md_layout_V = md_layout + strlen(MDL0 MDL1);
- assert(0 == strncmp(&md_layout_A[-3], ")]][", 4));
- assert(0 == strncmp(&md_layout_V[-3], ")]][", 4));
-
- for (i = 0; i < ATTR_CONTEXT_LIMIT; i++)
- {
- attr_definitions &ad = attr_defs[i];
- ad.defineLayout(X_ATTR_RuntimeVisibleAnnotations, "RuntimeVisibleAnnotations",
- md_layout_A);
- ad.defineLayout(X_ATTR_RuntimeInvisibleAnnotations, "RuntimeInvisibleAnnotations",
- md_layout_A);
- if (i != ATTR_CONTEXT_METHOD)
- continue;
- ad.defineLayout(METHOD_ATTR_RuntimeVisibleParameterAnnotations,
- "RuntimeVisibleParameterAnnotations", md_layout_P);
- ad.defineLayout(METHOD_ATTR_RuntimeInvisibleParameterAnnotations,
- "RuntimeInvisibleParameterAnnotations", md_layout_P);
- ad.defineLayout(METHOD_ATTR_AnnotationDefault, "AnnotationDefault", md_layout_V);
- }
-
- attr_definition_headers.readData(attr_definition_count);
- attr_definition_name.readData(attr_definition_count);
- attr_definition_layout.readData(attr_definition_count);
+ "[NH[(1)]]" \
+ "[RSHNH[RUH(1)]]"
+ MDL1
+ // member_value:
+ "[TB"
+ "(66,67,73,83,90)[KIH]"
+ "(68)[KDH]"
+ "(70)[KFH]"
+ "(74)[KJH]"
+ "(99)[RSH]"
+ "(101)[RSHRUH]"
+ "(115)[RUH]"
+ "(91)[NH[(0)]]"
+ "(64)["
+ // nested annotation:
+ "RSH"
+ "NH[RUH(0)]"
+ "]"
+ "()[]"
+ "]");
+
+ const char *md_layout_P = md_layout;
+ const char *md_layout_A = md_layout + strlen(MDL0);
+ const char *md_layout_V = md_layout + strlen(MDL0 MDL1);
+ assert(0 == strncmp(&md_layout_A[-3], ")]][", 4));
+ assert(0 == strncmp(&md_layout_V[-3], ")]][", 4));
+
+ for (i = 0; i < ATTR_CONTEXT_LIMIT; i++)
+ {
+ attr_definitions &ad = attr_defs[i];
+ ad.defineLayout(X_ATTR_RuntimeVisibleAnnotations, "RuntimeVisibleAnnotations",
+ md_layout_A);
+ ad.defineLayout(X_ATTR_RuntimeInvisibleAnnotations, "RuntimeInvisibleAnnotations",
+ md_layout_A);
+ if (i != ATTR_CONTEXT_METHOD)
+ continue;
+ ad.defineLayout(METHOD_ATTR_RuntimeVisibleParameterAnnotations,
+ "RuntimeVisibleParameterAnnotations", md_layout_P);
+ ad.defineLayout(METHOD_ATTR_RuntimeInvisibleParameterAnnotations,
+ "RuntimeInvisibleParameterAnnotations", md_layout_P);
+ ad.defineLayout(METHOD_ATTR_AnnotationDefault, "AnnotationDefault", md_layout_V);
+ }
+
+ attr_definition_headers.readData(attr_definition_count);
+ attr_definition_name.readData(attr_definition_count);
+ attr_definition_layout.readData(attr_definition_count);
// Initialize correct predef bits, to distinguish predefs from new defs.
#define ORBIT(n, s) | ((uint64_t)1 << n)
- attr_defs[ATTR_CONTEXT_CLASS].predef = (0 X_ATTR_DO(ORBIT) CLASS_ATTR_DO(ORBIT));
- attr_defs[ATTR_CONTEXT_FIELD].predef = (0 X_ATTR_DO(ORBIT) FIELD_ATTR_DO(ORBIT));
- attr_defs[ATTR_CONTEXT_METHOD].predef = (0 X_ATTR_DO(ORBIT) METHOD_ATTR_DO(ORBIT));
- attr_defs[ATTR_CONTEXT_CODE].predef = (0 O_ATTR_DO(ORBIT) CODE_ATTR_DO(ORBIT));
+ attr_defs[ATTR_CONTEXT_CLASS].predef = (0 X_ATTR_DO(ORBIT) CLASS_ATTR_DO(ORBIT));
+ attr_defs[ATTR_CONTEXT_FIELD].predef = (0 X_ATTR_DO(ORBIT) FIELD_ATTR_DO(ORBIT));
+ attr_defs[ATTR_CONTEXT_METHOD].predef = (0 X_ATTR_DO(ORBIT) METHOD_ATTR_DO(ORBIT));
+ attr_defs[ATTR_CONTEXT_CODE].predef = (0 O_ATTR_DO(ORBIT) CODE_ATTR_DO(ORBIT));
#undef ORBIT
- // Clear out the redef bits, folding them back into predef.
- for (i = 0; i < ATTR_CONTEXT_LIMIT; i++)
- {
- attr_defs[i].predef |= attr_defs[i].redef;
- attr_defs[i].redef = 0;
- }
-
- // Now read the transmitted locally defined attrs.
- // This will set redef bits again.
- for (i = 0; i < attr_definition_count; i++)
- {
- int header = attr_definition_headers.getByte();
- int attrc = ADH_BYTE_CONTEXT(header);
- int idx = ADH_BYTE_INDEX(header);
- entry *name = attr_definition_name.getRef();
- entry *layout = attr_definition_layout.getRef();
- attr_defs[attrc].defineLayout(idx, name, layout->value.b.strval());
- }
+ // Clear out the redef bits, folding them back into predef.
+ for (i = 0; i < ATTR_CONTEXT_LIMIT; i++)
+ {
+ attr_defs[i].predef |= attr_defs[i].redef;
+ attr_defs[i].redef = 0;
+ }
+
+ // Now read the transmitted locally defined attrs.
+ // This will set redef bits again.
+ for (i = 0; i < attr_definition_count; i++)
+ {
+ int header = attr_definition_headers.getByte();
+ int attrc = ADH_BYTE_CONTEXT(header);
+ int idx = ADH_BYTE_INDEX(header);
+ entry *name = attr_definition_name.getRef();
+ entry *layout = attr_definition_layout.getRef();
+ attr_defs[attrc].defineLayout(idx, name, layout->value.b.strval());
+ }
}
#define NO_ENTRY_YET ((entry *)-1)
static bool isDigitString(bytes &x, int beg, int end)
{
- if (beg == end)
- return false; // nullptr string
- byte *xptr = x.ptr;
- for (int i = beg; i < end; i++)
- {
- char ch = xptr[i];
- if (!(ch >= '0' && ch <= '9'))
- return false;
- }
- return true;
+ if (beg == end)
+ return false; // nullptr string
+ byte *xptr = x.ptr;
+ for (int i = beg; i < end; i++)
+ {
+ char ch = xptr[i];
+ if (!(ch >= '0' && ch <= '9'))
+ return false;
+ }
+ return true;
}
enum
{ // constants for parsing class names
- SLASH_MIN = '.',
- SLASH_MAX = '/',
- DOLLAR_MIN = 0,
- DOLLAR_MAX = '-'};
+ SLASH_MIN = '.',
+ SLASH_MAX = '/',
+ DOLLAR_MIN = 0,
+ DOLLAR_MAX = '-'};
static int lastIndexOf(int chmin, int chmax, bytes &x, int pos)
{
- byte *ptr = x.ptr;
- for (byte *cp = ptr + pos; --cp >= ptr;)
- {
- assert(x.inBounds(cp));
- if (*cp >= chmin && *cp <= chmax)
- return (int)(cp - ptr);
- }
- return -1;
+ byte *ptr = x.ptr;
+ for (byte *cp = ptr + pos; --cp >= ptr;)
+ {
+ assert(x.inBounds(cp));
+ if (*cp >= chmin && *cp <= chmax)
+ return (int)(cp - ptr);
+ }
+ return -1;
}
inner_class *constant_pool::getIC(entry *inner)
{
- if (inner == nullptr)
- return nullptr;
- assert(inner->tag == CONSTANT_Class);
- if (inner->inord == NO_INORD)
- return nullptr;
- inner_class *ic = ic_index[inner->inord];
- assert(ic == nullptr || ic->inner == inner);
- return ic;
+ if (inner == nullptr)
+ return nullptr;
+ assert(inner->tag == CONSTANT_Class);
+ if (inner->inord == NO_INORD)
+ return nullptr;
+ inner_class *ic = ic_index[inner->inord];
+ assert(ic == nullptr || ic->inner == inner);
+ return ic;
}
inner_class *constant_pool::getFirstChildIC(entry *outer)
{
- if (outer == nullptr)
- return nullptr;
- assert(outer->tag == CONSTANT_Class);
- if (outer->inord == NO_INORD)
- return nullptr;
- inner_class *ic = ic_child_index[outer->inord];
- assert(ic == nullptr || ic->outer == outer);
- return ic;
+ if (outer == nullptr)
+ return nullptr;
+ assert(outer->tag == CONSTANT_Class);
+ if (outer->inord == NO_INORD)
+ return nullptr;
+ inner_class *ic = ic_child_index[outer->inord];
+ assert(ic == nullptr || ic->outer == outer);
+ return ic;
}
inner_class *constant_pool::getNextChildIC(inner_class *child)
{
- inner_class *ic = child->next_sibling;
- assert(ic == nullptr || ic->outer == child->outer);
- return ic;
+ inner_class *ic = child->next_sibling;
+ assert(ic == nullptr || ic->outer == child->outer);
+ return ic;
}
void unpacker::read_ics()
{
- int i;
- int index_size = cp.tag_count[CONSTANT_Class];
- inner_class **ic_index = U_NEW(inner_class *, index_size);
- inner_class **ic_child_index = U_NEW(inner_class *, index_size);
- cp.ic_index = ic_index;
- cp.ic_child_index = ic_child_index;
- ics = U_NEW(inner_class, ic_count);
- ic_this_class.readData(ic_count);
- ic_flags.readData(ic_count);
- // Scan flags to get count of long-form bands.
- int long_forms = 0;
- for (i = 0; i < ic_count; i++)
- {
- int flags = ic_flags.getInt(); // may be long form!
- if ((flags & ACC_IC_LONG_FORM) != 0)
- {
- long_forms += 1;
- ics[i].name = NO_ENTRY_YET;
- }
- flags &= ~ACC_IC_LONG_FORM;
- entry *inner = ic_this_class.getRef();
- uint32_t inord = inner->inord;
- assert(inord < (uint32_t)cp.tag_count[CONSTANT_Class]);
- if (ic_index[inord] != nullptr)
- {
- unpack_abort("identical inner class");
- break;
- }
- ic_index[inord] = &ics[i];
- ics[i].inner = inner;
- ics[i].flags = flags;
- assert(cp.getIC(inner) == &ics[i]);
- }
- // ic_this_class.done();
- // ic_flags.done();
- ic_outer_class.readData(long_forms);
- ic_name.readData(long_forms);
- for (i = 0; i < ic_count; i++)
- {
- if (ics[i].name == NO_ENTRY_YET)
- {
- // Long form.
- ics[i].outer = ic_outer_class.getRefN();
- ics[i].name = ic_name.getRefN();
- }
- else
- {
- // Fill in outer and name based on inner.
- bytes &n = ics[i].inner->value.b;
- bytes pkgOuter;
- bytes number;
- bytes name;
- // Parse n into pkgOuter and name (and number).
- int dollar1, dollar2; // pointers to $ in the pattern
- // parse n = (<pkg>/)*<outer>($<number>)?($<name>)?
- int nlen = (int)n.len;
- int pkglen = lastIndexOf(SLASH_MIN, SLASH_MAX, n, nlen) + 1;
- dollar2 = lastIndexOf(DOLLAR_MIN, DOLLAR_MAX, n, nlen);
- if (dollar2 < 0)
- {
- unpack_abort();
- }
- assert(dollar2 >= pkglen);
- if (isDigitString(n, dollar2 + 1, nlen))
- {
- // n = (<pkg>/)*<outer>$<number>
- number = n.slice(dollar2 + 1, nlen);
- name.set(nullptr, 0);
- dollar1 = dollar2;
- }
- else if (pkglen < (dollar1 = lastIndexOf(DOLLAR_MIN, DOLLAR_MAX, n, dollar2 - 1)) &&
- isDigitString(n, dollar1 + 1, dollar2))
- {
- // n = (<pkg>/)*<outer>$<number>$<name>
- number = n.slice(dollar1 + 1, dollar2);
- name = n.slice(dollar2 + 1, nlen);
- }
- else
- {
- // n = (<pkg>/)*<outer>$<name>
- dollar1 = dollar2;
- number.set(nullptr, 0);
- name = n.slice(dollar2 + 1, nlen);
- }
- if (number.ptr == nullptr)
- pkgOuter = n.slice(0, dollar1);
- else
- pkgOuter.set(nullptr, 0);
-
- if (pkgOuter.ptr != nullptr)
- ics[i].outer = cp.ensureClass(pkgOuter);
-
- if (name.ptr != nullptr)
- ics[i].name = cp.ensureUtf8(name);
- }
-
- // update child/sibling list
- if (ics[i].outer != nullptr)
- {
- uint32_t outord = ics[i].outer->inord;
- if (outord != NO_INORD)
- {
- assert(outord < (uint32_t)cp.tag_count[CONSTANT_Class]);
- ics[i].next_sibling = ic_child_index[outord];
- ic_child_index[outord] = &ics[i];
- }
- }
- }
- // ic_outer_class.done();
- // ic_name.done();
+ int i;
+ int index_size = cp.tag_count[CONSTANT_Class];
+ inner_class **ic_index = U_NEW(inner_class *, index_size);
+ inner_class **ic_child_index = U_NEW(inner_class *, index_size);
+ cp.ic_index = ic_index;
+ cp.ic_child_index = ic_child_index;
+ ics = U_NEW(inner_class, ic_count);
+ ic_this_class.readData(ic_count);
+ ic_flags.readData(ic_count);
+ // Scan flags to get count of long-form bands.
+ int long_forms = 0;
+ for (i = 0; i < ic_count; i++)
+ {
+ int flags = ic_flags.getInt(); // may be long form!
+ if ((flags & ACC_IC_LONG_FORM) != 0)
+ {
+ long_forms += 1;
+ ics[i].name = NO_ENTRY_YET;
+ }
+ flags &= ~ACC_IC_LONG_FORM;
+ entry *inner = ic_this_class.getRef();
+ uint32_t inord = inner->inord;
+ assert(inord < (uint32_t)cp.tag_count[CONSTANT_Class]);
+ if (ic_index[inord] != nullptr)
+ {
+ unpack_abort("identical inner class");
+ break;
+ }
+ ic_index[inord] = &ics[i];
+ ics[i].inner = inner;
+ ics[i].flags = flags;
+ assert(cp.getIC(inner) == &ics[i]);
+ }
+ // ic_this_class.done();
+ // ic_flags.done();
+ ic_outer_class.readData(long_forms);
+ ic_name.readData(long_forms);
+ for (i = 0; i < ic_count; i++)
+ {
+ if (ics[i].name == NO_ENTRY_YET)
+ {
+ // Long form.
+ ics[i].outer = ic_outer_class.getRefN();
+ ics[i].name = ic_name.getRefN();
+ }
+ else
+ {
+ // Fill in outer and name based on inner.
+ bytes &n = ics[i].inner->value.b;
+ bytes pkgOuter;
+ bytes number;
+ bytes name;
+ // Parse n into pkgOuter and name (and number).
+ int dollar1, dollar2; // pointers to $ in the pattern
+ // parse n = (<pkg>/)*<outer>($<number>)?($<name>)?
+ int nlen = (int)n.len;
+ int pkglen = lastIndexOf(SLASH_MIN, SLASH_MAX, n, nlen) + 1;
+ dollar2 = lastIndexOf(DOLLAR_MIN, DOLLAR_MAX, n, nlen);
+ if (dollar2 < 0)
+ {
+ unpack_abort();
+ }
+ assert(dollar2 >= pkglen);
+ if (isDigitString(n, dollar2 + 1, nlen))
+ {
+ // n = (<pkg>/)*<outer>$<number>
+ number = n.slice(dollar2 + 1, nlen);
+ name.set(nullptr, 0);
+ dollar1 = dollar2;
+ }
+ else if (pkglen < (dollar1 = lastIndexOf(DOLLAR_MIN, DOLLAR_MAX, n, dollar2 - 1)) &&
+ isDigitString(n, dollar1 + 1, dollar2))
+ {
+ // n = (<pkg>/)*<outer>$<number>$<name>
+ number = n.slice(dollar1 + 1, dollar2);
+ name = n.slice(dollar2 + 1, nlen);
+ }
+ else
+ {
+ // n = (<pkg>/)*<outer>$<name>
+ dollar1 = dollar2;
+ number.set(nullptr, 0);
+ name = n.slice(dollar2 + 1, nlen);
+ }
+ if (number.ptr == nullptr)
+ pkgOuter = n.slice(0, dollar1);
+ else
+ pkgOuter.set(nullptr, 0);
+
+ if (pkgOuter.ptr != nullptr)
+ ics[i].outer = cp.ensureClass(pkgOuter);
+
+ if (name.ptr != nullptr)
+ ics[i].name = cp.ensureUtf8(name);
+ }
+
+ // update child/sibling list
+ if (ics[i].outer != nullptr)
+ {
+ uint32_t outord = ics[i].outer->inord;
+ if (outord != NO_INORD)
+ {
+ assert(outord < (uint32_t)cp.tag_count[CONSTANT_Class]);
+ ics[i].next_sibling = ic_child_index[outord];
+ ic_child_index[outord] = &ics[i];
+ }
+ }
+ }
+ // ic_outer_class.done();
+ // ic_name.done();
}
void unpacker::read_classes()
{
- class_this.readData(class_count);
- class_super.readData(class_count);
- class_interface_count.readData(class_count);
- class_interface.readData(class_interface_count.getIntTotal());
+ class_this.readData(class_count);
+ class_super.readData(class_count);
+ class_interface_count.readData(class_count);
+ class_interface.readData(class_interface_count.getIntTotal());
#if 0
int i;
@@ -2256,1218 +2250,1220 @@ void unpacker::read_classes()
class_super.rewind();
#endif
- // Members.
- class_field_count.readData(class_count);
- class_method_count.readData(class_count);
+ // Members.
+ class_field_count.readData(class_count);
+ class_method_count.readData(class_count);
- int field_count = class_field_count.getIntTotal();
- int method_count = class_method_count.getIntTotal();
+ int field_count = class_field_count.getIntTotal();
+ int method_count = class_method_count.getIntTotal();
- field_descr.readData(field_count);
- read_attrs(ATTR_CONTEXT_FIELD, field_count);
- method_descr.readData(method_count);
- read_attrs(ATTR_CONTEXT_METHOD, method_count);
- read_attrs(ATTR_CONTEXT_CLASS, class_count);
- read_code_headers();
+ field_descr.readData(field_count);
+ read_attrs(ATTR_CONTEXT_FIELD, field_count);
+ method_descr.readData(method_count);
+ read_attrs(ATTR_CONTEXT_METHOD, method_count);
+ read_attrs(ATTR_CONTEXT_CLASS, class_count);
+ read_code_headers();
}
int unpacker::attr_definitions::predefCount(uint32_t idx)
{
- return isPredefined(idx) ? flag_count[idx] : 0;
+ return isPredefined(idx) ? flag_count[idx] : 0;
}
void unpacker::read_attrs(int attrc, int obj_count)
{
- attr_definitions &ad = attr_defs[attrc];
- assert(ad.attrc == attrc);
-
- int i, idx, count;
-
- bool haveLongFlags = ad.haveLongFlags();
-
- band &xxx_flags_hi = ad.xxx_flags_hi();
- if (haveLongFlags)
- xxx_flags_hi.readData(obj_count);
-
- band &xxx_flags_lo = ad.xxx_flags_lo();
- xxx_flags_lo.readData(obj_count);
-
- // pre-scan flags, counting occurrences of each index bit
- uint64_t indexMask = ad.flagIndexMask(); // which flag bits are index bits?
- for (i = 0; i < obj_count; i++)
- {
- uint64_t indexBits = xxx_flags_hi.getLong(xxx_flags_lo, haveLongFlags);
- if ((indexBits & ~indexMask) > (ushort) - 1)
- {
- unpack_abort("undefined attribute flag bit");
- return;
- }
- indexBits &= indexMask; // ignore classfile flag bits
- for (idx = 0; indexBits != 0; idx++, indexBits >>= 1)
- {
- ad.flag_count[idx] += (int)(indexBits & 1);
- }
- }
- // we'll scan these again later for output:
- xxx_flags_lo.rewind();
- xxx_flags_hi.rewind();
-
- band &xxx_attr_count = ad.xxx_attr_count();
- // There is one count element for each 1<<16 bit set in flags:
- xxx_attr_count.readData(ad.predefCount(X_ATTR_OVERFLOW));
-
- band &xxx_attr_indexes = ad.xxx_attr_indexes();
- int overflowIndexCount = xxx_attr_count.getIntTotal();
- xxx_attr_indexes.readData(overflowIndexCount);
- // pre-scan attr indexes, counting occurrences of each value
- for (i = 0; i < overflowIndexCount; i++)
- {
- idx = xxx_attr_indexes.getInt();
- if (!ad.isIndex(idx))
- {
- unpack_abort("attribute index out of bounds");
- return;
- }
- ad.getCount(idx) += 1;
- }
- xxx_attr_indexes.rewind(); // we'll scan it again later for output
-
- // We will need a backward call count for each used backward callable.
- int backwardCounts = 0;
- for (idx = 0; idx < ad.layouts.length(); idx++)
- {
- layout_definition *lo = ad.getLayout(idx);
- if (lo != nullptr && ad.getCount(idx) != 0)
- {
- // Build the bands lazily, only when they are used.
- band **bands = ad.buildBands(lo);
- if (lo->hasCallables())
- {
- for (i = 0; bands[i] != nullptr; i++)
- {
- if (bands[i]->le_back)
- {
- assert(bands[i]->le_kind == EK_CBLE);
- backwardCounts += 1;
- }
- }
- }
- }
- }
- ad.xxx_attr_calls().readData(backwardCounts);
-
- // Read built-in bands.
- // Mostly, these are hand-coded equivalents to readBandData().
- switch (attrc)
- {
- case ATTR_CONTEXT_CLASS:
-
- count = ad.predefCount(CLASS_ATTR_SourceFile);
- class_SourceFile_RUN.readData(count);
-
- count = ad.predefCount(CLASS_ATTR_EnclosingMethod);
- class_EnclosingMethod_RC.readData(count);
- class_EnclosingMethod_RDN.readData(count);
-
- count = ad.predefCount(X_ATTR_Signature);
- class_Signature_RS.readData(count);
-
- ad.readBandData(X_ATTR_RuntimeVisibleAnnotations);
- ad.readBandData(X_ATTR_RuntimeInvisibleAnnotations);
-
- count = ad.predefCount(CLASS_ATTR_InnerClasses);
- class_InnerClasses_N.readData(count);
-
- count = class_InnerClasses_N.getIntTotal();
- class_InnerClasses_RC.readData(count);
- class_InnerClasses_F.readData(count);
-
- // Drop remaining columns wherever flags are zero:
- count -= class_InnerClasses_F.getIntCount(0);
- class_InnerClasses_outer_RCN.readData(count);
- class_InnerClasses_name_RUN.readData(count);
-
- count = ad.predefCount(CLASS_ATTR_ClassFile_version);
- class_ClassFile_version_minor_H.readData(count);
- class_ClassFile_version_major_H.readData(count);
- break;
-
- case ATTR_CONTEXT_FIELD:
-
- count = ad.predefCount(FIELD_ATTR_ConstantValue);
- field_ConstantValue_KQ.readData(count);
-
- count = ad.predefCount(X_ATTR_Signature);
- field_Signature_RS.readData(count);
-
- ad.readBandData(X_ATTR_RuntimeVisibleAnnotations);
- ad.readBandData(X_ATTR_RuntimeInvisibleAnnotations);
- break;
-
- case ATTR_CONTEXT_METHOD:
-
- code_count = ad.predefCount(METHOD_ATTR_Code);
- // Code attrs are handled very specially below...
-
- count = ad.predefCount(METHOD_ATTR_Exceptions);
- method_Exceptions_N.readData(count);
- count = method_Exceptions_N.getIntTotal();
- method_Exceptions_RC.readData(count);
-
- count = ad.predefCount(X_ATTR_Signature);
- method_Signature_RS.readData(count);
-
- ad.readBandData(X_ATTR_RuntimeVisibleAnnotations);
- ad.readBandData(X_ATTR_RuntimeInvisibleAnnotations);
- ad.readBandData(METHOD_ATTR_RuntimeVisibleParameterAnnotations);
- ad.readBandData(METHOD_ATTR_RuntimeInvisibleParameterAnnotations);
- ad.readBandData(METHOD_ATTR_AnnotationDefault);
- break;
-
- case ATTR_CONTEXT_CODE:
- // (keep this code aligned with its brother in unpacker::write_attrs)
- count = ad.predefCount(CODE_ATTR_StackMapTable);
- // disable this feature in old archives!
- if (count != 0 && majver < JAVA6_PACKAGE_MAJOR_VERSION)
- {
- unpack_abort("undefined StackMapTable attribute (old archive format)");
- return;
- }
- code_StackMapTable_N.readData(count);
- count = code_StackMapTable_N.getIntTotal();
- code_StackMapTable_frame_T.readData(count);
- // the rest of it depends in a complicated way on frame tags
- {
- int fat_frame_count = 0;
- int offset_count = 0;
- int type_count = 0;
- for (int k = 0; k < count; k++)
- {
- int tag = code_StackMapTable_frame_T.getByte();
- if (tag <= 127)
- {
- // (64-127) [(2)]
- if (tag >= 64)
- type_count++;
- }
- else if (tag <= 251)
- {
- // (247) [(1)(2)]
- // (248-251) [(1)]
- if (tag >= 247)
- offset_count++;
- if (tag == 247)
- type_count++;
- }
- else if (tag <= 254)
- {
- // (252) [(1)(2)]
- // (253) [(1)(2)(2)]
- // (254) [(1)(2)(2)(2)]
- offset_count++;
- type_count += (tag - 251);
- }
- else
- {
- // (255) [(1)NH[(2)]NH[(2)]]
- fat_frame_count++;
- }
- }
-
- // done pre-scanning frame tags:
- code_StackMapTable_frame_T.rewind();
-
- // deal completely with fat frames:
- offset_count += fat_frame_count;
- code_StackMapTable_local_N.readData(fat_frame_count);
- type_count += code_StackMapTable_local_N.getIntTotal();
- code_StackMapTable_stack_N.readData(fat_frame_count);
- type_count += code_StackMapTable_stack_N.getIntTotal();
- // read the rest:
- code_StackMapTable_offset.readData(offset_count);
- code_StackMapTable_T.readData(type_count);
- // (7) [RCH]
- count = code_StackMapTable_T.getIntCount(7);
- code_StackMapTable_RC.readData(count);
- // (8) [PH]
- count = code_StackMapTable_T.getIntCount(8);
- code_StackMapTable_P.readData(count);
- }
-
- count = ad.predefCount(CODE_ATTR_LineNumberTable);
- code_LineNumberTable_N.readData(count);
- count = code_LineNumberTable_N.getIntTotal();
- code_LineNumberTable_bci_P.readData(count);
- code_LineNumberTable_line.readData(count);
-
- count = ad.predefCount(CODE_ATTR_LocalVariableTable);
- code_LocalVariableTable_N.readData(count);
- count = code_LocalVariableTable_N.getIntTotal();
- code_LocalVariableTable_bci_P.readData(count);
- code_LocalVariableTable_span_O.readData(count);
- code_LocalVariableTable_name_RU.readData(count);
- code_LocalVariableTable_type_RS.readData(count);
- code_LocalVariableTable_slot.readData(count);
-
- count = ad.predefCount(CODE_ATTR_LocalVariableTypeTable);
- code_LocalVariableTypeTable_N.readData(count);
- count = code_LocalVariableTypeTable_N.getIntTotal();
- code_LocalVariableTypeTable_bci_P.readData(count);
- code_LocalVariableTypeTable_span_O.readData(count);
- code_LocalVariableTypeTable_name_RU.readData(count);
- code_LocalVariableTypeTable_type_RS.readData(count);
- code_LocalVariableTypeTable_slot.readData(count);
- break;
- }
-
- // Read compressor-defined bands.
- for (idx = 0; idx < ad.layouts.length(); idx++)
- {
- if (ad.getLayout(idx) == nullptr)
- continue; // none at this fixed index <32
- if (idx < (int)ad.flag_limit && ad.isPredefined(idx))
- continue; // already handled
- if (ad.getCount(idx) == 0)
- continue; // no attributes of this type (then why transmit layouts?)
- ad.readBandData(idx);
- }
+ attr_definitions &ad = attr_defs[attrc];
+ assert(ad.attrc == attrc);
+
+ int i, idx, count;
+
+ bool haveLongFlags = ad.haveLongFlags();
+
+ band &xxx_flags_hi = ad.xxx_flags_hi();
+ if (haveLongFlags)
+ xxx_flags_hi.readData(obj_count);
+
+ band &xxx_flags_lo = ad.xxx_flags_lo();
+ xxx_flags_lo.readData(obj_count);
+
+ // pre-scan flags, counting occurrences of each index bit
+ uint64_t indexMask = ad.flagIndexMask(); // which flag bits are index bits?
+ for (i = 0; i < obj_count; i++)
+ {
+ uint64_t indexBits = xxx_flags_hi.getLong(xxx_flags_lo, haveLongFlags);
+ if ((indexBits & ~indexMask) > (ushort) - 1)
+ {
+ unpack_abort("undefined attribute flag bit");
+ return;
+ }
+ indexBits &= indexMask; // ignore classfile flag bits
+ for (idx = 0; indexBits != 0; idx++, indexBits >>= 1)
+ {
+ ad.flag_count[idx] += (int)(indexBits & 1);
+ }
+ }
+ // we'll scan these again later for output:
+ xxx_flags_lo.rewind();
+ xxx_flags_hi.rewind();
+
+ band &xxx_attr_count = ad.xxx_attr_count();
+ // There is one count element for each 1<<16 bit set in flags:
+ xxx_attr_count.readData(ad.predefCount(X_ATTR_OVERFLOW));
+
+ band &xxx_attr_indexes = ad.xxx_attr_indexes();
+ int overflowIndexCount = xxx_attr_count.getIntTotal();
+ xxx_attr_indexes.readData(overflowIndexCount);
+ // pre-scan attr indexes, counting occurrences of each value
+ for (i = 0; i < overflowIndexCount; i++)
+ {
+ idx = xxx_attr_indexes.getInt();
+ if (!ad.isIndex(idx))
+ {
+ unpack_abort("attribute index out of bounds");
+ return;
+ }
+ ad.getCount(idx) += 1;
+ }
+ xxx_attr_indexes.rewind(); // we'll scan it again later for output
+
+ // We will need a backward call count for each used backward callable.
+ int backwardCounts = 0;
+ for (idx = 0; idx < ad.layouts.length(); idx++)
+ {
+ layout_definition *lo = ad.getLayout(idx);
+ if (lo != nullptr && ad.getCount(idx) != 0)
+ {
+ // Build the bands lazily, only when they are used.
+ band **bands = ad.buildBands(lo);
+ if (lo->hasCallables())
+ {
+ for (i = 0; bands[i] != nullptr; i++)
+ {
+ if (bands[i]->le_back)
+ {
+ assert(bands[i]->le_kind == EK_CBLE);
+ backwardCounts += 1;
+ }
+ }
+ }
+ }
+ }
+ ad.xxx_attr_calls().readData(backwardCounts);
+
+ // Read built-in bands.
+ // Mostly, these are hand-coded equivalents to readBandData().
+ switch (attrc)
+ {
+ case ATTR_CONTEXT_CLASS:
+
+ count = ad.predefCount(CLASS_ATTR_SourceFile);
+ class_SourceFile_RUN.readData(count);
+
+ count = ad.predefCount(CLASS_ATTR_EnclosingMethod);
+ class_EnclosingMethod_RC.readData(count);
+ class_EnclosingMethod_RDN.readData(count);
+
+ count = ad.predefCount(X_ATTR_Signature);
+ class_Signature_RS.readData(count);
+
+ ad.readBandData(X_ATTR_RuntimeVisibleAnnotations);
+ ad.readBandData(X_ATTR_RuntimeInvisibleAnnotations);
+
+ count = ad.predefCount(CLASS_ATTR_InnerClasses);
+ class_InnerClasses_N.readData(count);
+
+ count = class_InnerClasses_N.getIntTotal();
+ class_InnerClasses_RC.readData(count);
+ class_InnerClasses_F.readData(count);
+
+ // Drop remaining columns wherever flags are zero:
+ count -= class_InnerClasses_F.getIntCount(0);
+ class_InnerClasses_outer_RCN.readData(count);
+ class_InnerClasses_name_RUN.readData(count);
+
+ count = ad.predefCount(CLASS_ATTR_ClassFile_version);
+ class_ClassFile_version_minor_H.readData(count);
+ class_ClassFile_version_major_H.readData(count);
+ break;
+
+ case ATTR_CONTEXT_FIELD:
+
+ count = ad.predefCount(FIELD_ATTR_ConstantValue);
+ field_ConstantValue_KQ.readData(count);
+
+ count = ad.predefCount(X_ATTR_Signature);
+ field_Signature_RS.readData(count);
+
+ ad.readBandData(X_ATTR_RuntimeVisibleAnnotations);
+ ad.readBandData(X_ATTR_RuntimeInvisibleAnnotations);
+ break;
+
+ case ATTR_CONTEXT_METHOD:
+
+ code_count = ad.predefCount(METHOD_ATTR_Code);
+ // Code attrs are handled very specially below...
+
+ count = ad.predefCount(METHOD_ATTR_Exceptions);
+ method_Exceptions_N.readData(count);
+ count = method_Exceptions_N.getIntTotal();
+ method_Exceptions_RC.readData(count);
+
+ count = ad.predefCount(X_ATTR_Signature);
+ method_Signature_RS.readData(count);
+
+ ad.readBandData(X_ATTR_RuntimeVisibleAnnotations);
+ ad.readBandData(X_ATTR_RuntimeInvisibleAnnotations);
+ ad.readBandData(METHOD_ATTR_RuntimeVisibleParameterAnnotations);
+ ad.readBandData(METHOD_ATTR_RuntimeInvisibleParameterAnnotations);
+ ad.readBandData(METHOD_ATTR_AnnotationDefault);
+ break;
+
+ case ATTR_CONTEXT_CODE:
+ // (keep this code aligned with its brother in unpacker::write_attrs)
+ count = ad.predefCount(CODE_ATTR_StackMapTable);
+ // disable this feature in old archives!
+ if (count != 0 && majver < JAVA6_PACKAGE_MAJOR_VERSION)
+ {
+ unpack_abort("undefined StackMapTable attribute (old archive format)");
+ return;
+ }
+ code_StackMapTable_N.readData(count);
+ count = code_StackMapTable_N.getIntTotal();
+ code_StackMapTable_frame_T.readData(count);
+ // the rest of it depends in a complicated way on frame tags
+ {
+ int fat_frame_count = 0;
+ int offset_count = 0;
+ int type_count = 0;
+ for (int k = 0; k < count; k++)
+ {
+ int tag = code_StackMapTable_frame_T.getByte();
+ if (tag <= 127)
+ {
+ // (64-127) [(2)]
+ if (tag >= 64)
+ type_count++;
+ }
+ else if (tag <= 251)
+ {
+ // (247) [(1)(2)]
+ // (248-251) [(1)]
+ if (tag >= 247)
+ offset_count++;
+ if (tag == 247)
+ type_count++;
+ }
+ else if (tag <= 254)
+ {
+ // (252) [(1)(2)]
+ // (253) [(1)(2)(2)]
+ // (254) [(1)(2)(2)(2)]
+ offset_count++;
+ type_count += (tag - 251);
+ }
+ else
+ {
+ // (255) [(1)NH[(2)]NH[(2)]]
+ fat_frame_count++;
+ }
+ }
+
+ // done pre-scanning frame tags:
+ code_StackMapTable_frame_T.rewind();
+
+ // deal completely with fat frames:
+ offset_count += fat_frame_count;
+ code_StackMapTable_local_N.readData(fat_frame_count);
+ type_count += code_StackMapTable_local_N.getIntTotal();
+ code_StackMapTable_stack_N.readData(fat_frame_count);
+ type_count += code_StackMapTable_stack_N.getIntTotal();
+ // read the rest:
+ code_StackMapTable_offset.readData(offset_count);
+ code_StackMapTable_T.readData(type_count);
+ // (7) [RCH]
+ count = code_StackMapTable_T.getIntCount(7);
+ code_StackMapTable_RC.readData(count);
+ // (8) [PH]
+ count = code_StackMapTable_T.getIntCount(8);
+ code_StackMapTable_P.readData(count);
+ }
+
+ count = ad.predefCount(CODE_ATTR_LineNumberTable);
+ code_LineNumberTable_N.readData(count);
+ count = code_LineNumberTable_N.getIntTotal();
+ code_LineNumberTable_bci_P.readData(count);
+ code_LineNumberTable_line.readData(count);
+
+ count = ad.predefCount(CODE_ATTR_LocalVariableTable);
+ code_LocalVariableTable_N.readData(count);
+ count = code_LocalVariableTable_N.getIntTotal();
+ code_LocalVariableTable_bci_P.readData(count);
+ code_LocalVariableTable_span_O.readData(count);
+ code_LocalVariableTable_name_RU.readData(count);
+ code_LocalVariableTable_type_RS.readData(count);
+ code_LocalVariableTable_slot.readData(count);
+
+ count = ad.predefCount(CODE_ATTR_LocalVariableTypeTable);
+ code_LocalVariableTypeTable_N.readData(count);
+ count = code_LocalVariableTypeTable_N.getIntTotal();
+ code_LocalVariableTypeTable_bci_P.readData(count);
+ code_LocalVariableTypeTable_span_O.readData(count);
+ code_LocalVariableTypeTable_name_RU.readData(count);
+ code_LocalVariableTypeTable_type_RS.readData(count);
+ code_LocalVariableTypeTable_slot.readData(count);
+ break;
+ }
+
+ // Read compressor-defined bands.
+ for (idx = 0; idx < ad.layouts.length(); idx++)
+ {
+ if (ad.getLayout(idx) == nullptr)
+ continue; // none at this fixed index <32
+ if (idx < (int)ad.flag_limit && ad.isPredefined(idx))
+ continue; // already handled
+ if (ad.getCount(idx) == 0)
+ continue; // no attributes of this type (then why transmit layouts?)
+ ad.readBandData(idx);
+ }
}
void unpacker::attr_definitions::readBandData(int idx)
{
- int j;
- uint32_t count = getCount(idx);
- if (count == 0)
- return;
- layout_definition *lo = getLayout(idx);
- bool hasCallables = lo->hasCallables();
- band **bands = lo->bands();
- if (!hasCallables)
- {
- // Read through the rest of the bands in a regular way.
- readBandData(bands, count);
- }
- else
- {
- // Deal with the callables.
- // First set up the forward entry count for each callable.
- // This is stored on band::length of the callable.
- bands[0]->expectMoreLength(count);
- for (j = 0; bands[j] != nullptr; j++)
- {
- band &j_cble = *bands[j];
- assert(j_cble.le_kind == EK_CBLE);
- if (j_cble.le_back)
- {
- // Add in the predicted effects of backward calls, too.
- int back_calls = xxx_attr_calls().getInt();
- j_cble.expectMoreLength(back_calls);
- // In a moment, more forward calls may increment j_cble.length.
- }
- }
- // Now consult whichever callables have non-zero entry counts.
- readBandData(bands, (uint32_t) - 1);
- }
+ int j;
+ uint32_t count = getCount(idx);
+ if (count == 0)
+ return;
+ layout_definition *lo = getLayout(idx);
+ bool hasCallables = lo->hasCallables();
+ band **bands = lo->bands();
+ if (!hasCallables)
+ {
+ // Read through the rest of the bands in a regular way.
+ readBandData(bands, count);
+ }
+ else
+ {
+ // Deal with the callables.
+ // First set up the forward entry count for each callable.
+ // This is stored on band::length of the callable.
+ bands[0]->expectMoreLength(count);
+ for (j = 0; bands[j] != nullptr; j++)
+ {
+ band &j_cble = *bands[j];
+ assert(j_cble.le_kind == EK_CBLE);
+ if (j_cble.le_back)
+ {
+ // Add in the predicted effects of backward calls, too.
+ int back_calls = xxx_attr_calls().getInt();
+ j_cble.expectMoreLength(back_calls);
+ // In a moment, more forward calls may increment j_cble.length.
+ }
+ }
+ // Now consult whichever callables have non-zero entry counts.
+ readBandData(bands, (uint32_t) - 1);
+ }
}
// Recursive helper to the previous function:
void unpacker::attr_definitions::readBandData(band **body, uint32_t count)
{
- int j, k;
- for (j = 0; body[j] != nullptr; j++)
- {
- band &b = *body[j];
- if (b.defc != nullptr)
- {
- // It has data, so read it.
- b.readData(count);
- }
- switch (b.le_kind)
- {
- case EK_REPL:
- {
- int reps = b.getIntTotal();
- readBandData(b.le_body, reps);
- }
- break;
- case EK_UN:
- {
- int remaining = count;
- for (k = 0; b.le_body[k] != nullptr; k++)
- {
- band &k_case = *b.le_body[k];
- int k_count = 0;
- if (k_case.le_casetags == nullptr)
- {
- k_count = remaining; // last (empty) case
- }
- else
- {
- int *tags = k_case.le_casetags;
- int ntags = *tags++; // 1st element is length (why not?)
- while (ntags-- > 0)
- {
- int tag = *tags++;
- k_count += b.getIntCount(tag);
- }
- }
- readBandData(k_case.le_body, k_count);
- remaining -= k_count;
- }
- assert(remaining == 0);
- }
- break;
- case EK_CALL:
- // Push the count forward, if it is not a backward call.
- if (!b.le_back)
- {
- band &cble = *b.le_body[0];
- assert(cble.le_kind == EK_CBLE);
- cble.expectMoreLength(count);
- }
- break;
- case EK_CBLE:
- assert((int)count == -1); // incoming count is meaningless
- k = b.length;
- assert(k >= 0);
- // This is intended and required for non production mode.
- assert((b.length = -1)); // make it unable to accept more calls now.
- readBandData(b.le_body, k);
- break;
- }
- }
+ int j, k;
+ for (j = 0; body[j] != nullptr; j++)
+ {
+ band &b = *body[j];
+ if (b.defc != nullptr)
+ {
+ // It has data, so read it.
+ b.readData(count);
+ }
+ switch (b.le_kind)
+ {
+ case EK_REPL:
+ {
+ int reps = b.getIntTotal();
+ readBandData(b.le_body, reps);
+ }
+ break;
+ case EK_UN:
+ {
+ int remaining = count;
+ for (k = 0; b.le_body[k] != nullptr; k++)
+ {
+ band &k_case = *b.le_body[k];
+ int k_count = 0;
+ if (k_case.le_casetags == nullptr)
+ {
+ k_count = remaining; // last (empty) case
+ }
+ else
+ {
+ int *tags = k_case.le_casetags;
+ int ntags = *tags++; // 1st element is length (why not?)
+ while (ntags-- > 0)
+ {
+ int tag = *tags++;
+ k_count += b.getIntCount(tag);
+ }
+ }
+ readBandData(k_case.le_body, k_count);
+ remaining -= k_count;
+ }
+ assert(remaining == 0);
+ }
+ break;
+ case EK_CALL:
+ // Push the count forward, if it is not a backward call.
+ if (!b.le_back)
+ {
+ band &cble = *b.le_body[0];
+ assert(cble.le_kind == EK_CBLE);
+ cble.expectMoreLength(count);
+ }
+ break;
+ case EK_CBLE:
+ assert((int)count == -1); // incoming count is meaningless
+ k = b.length;
+ assert(k >= 0);
+ // This is intended and required for non production mode.
+ assert((b.length = -1)); // make it unable to accept more calls now.
+ readBandData(b.le_body, k);
+ break;
+ }
+ }
}
static inline band **findMatchingCase(int matchTag, band **cases)
{
- for (int k = 0; cases[k] != nullptr; k++)
- {
- band &k_case = *cases[k];
- if (k_case.le_casetags != nullptr)
- {
- // If it has tags, it must match a tag.
- int *tags = k_case.le_casetags;
- int ntags = *tags++; // 1st element is length
- for (; ntags > 0; ntags--)
- {
- int tag = *tags++;
- if (tag == matchTag)
- break;
- }
- if (ntags == 0)
- continue; // does not match
- }
- return k_case.le_body;
- }
- return nullptr;
+ for (int k = 0; cases[k] != nullptr; k++)
+ {
+ band &k_case = *cases[k];
+ if (k_case.le_casetags != nullptr)
+ {
+ // If it has tags, it must match a tag.
+ int *tags = k_case.le_casetags;
+ int ntags = *tags++; // 1st element is length
+ for (; ntags > 0; ntags--)
+ {
+ int tag = *tags++;
+ if (tag == matchTag)
+ break;
+ }
+ if (ntags == 0)
+ continue; // does not match
+ }
+ return k_case.le_body;
+ }
+ return nullptr;
}
// write attribute band data:
void unpacker::putlayout(band **body)
{
- int i;
- int prevBII = -1;
- int prevBCI = -1;
- if (body == NULL)
- {
- unpack_abort("putlayout: unexpected NULL for body");
- return;
- }
- for (i = 0; body[i] != nullptr; i++)
- {
- band &b = *body[i];
- byte le_kind = b.le_kind;
-
- // Handle scalar part, if any.
- int x = 0;
- entry *e = nullptr;
- if (b.defc != nullptr)
- {
- // It has data, so unparse an element.
- if (b.ixTag != CONSTANT_None)
- {
- assert(le_kind == EK_REF);
- if (b.ixTag == CONSTANT_Literal)
- e = b.getRefUsing(cp.getKQIndex());
- else
- e = b.getRefN();
- switch (b.le_len)
- {
- case 0:
- break;
- case 1:
- putu1ref(e);
- break;
- case 2:
- putref(e);
- break;
- case 4:
- putu2(0);
- putref(e);
- break;
- default:
- assert(false);
- }
- }
- else
- {
- assert(le_kind == EK_INT || le_kind == EK_REPL || le_kind == EK_UN);
- x = b.getInt();
-
- assert(!b.le_bci || prevBCI == (int)to_bci(prevBII));
- switch (b.le_bci)
- {
- case EK_BCI: // PH: transmit R(bci), store bci
- x = to_bci(prevBII = x);
- prevBCI = x;
- break;
- case EK_BCID: // POH: transmit D(R(bci)), store bci
- x = to_bci(prevBII += x);
- prevBCI = x;
- break;
- case EK_BCO: // OH: transmit D(R(bci)), store D(bci)
- x = to_bci(prevBII += x) - prevBCI;
- prevBCI += x;
- break;
- }
- assert(!b.le_bci || prevBCI == (int)to_bci(prevBII));
-
- switch (b.le_len)
- {
- case 0:
- break;
- case 1:
- putu1(x);
- break;
- case 2:
- putu2(x);
- break;
- case 4:
- putu4(x);
- break;
- default:
- assert(false);
- }
- }
- }
-
- // Handle subparts, if any.
- switch (le_kind)
- {
- case EK_REPL:
- // x is the repeat count
- while (x-- > 0)
- {
- putlayout(b.le_body);
- }
- break;
- case EK_UN:
- // x is the tag
- putlayout(findMatchingCase(x, b.le_body));
- break;
- case EK_CALL:
- {
- band &cble = *b.le_body[0];
- assert(cble.le_kind == EK_CBLE);
- // FIXME: hit this one
- // assert(cble.le_len == b.le_len);
- putlayout(cble.le_body);
- }
- break;
-
- case EK_CBLE:
- case EK_CASE:
- assert(false); // should not reach here
- }
- }
+ int i;
+ int prevBII = -1;
+ int prevBCI = -1;
+ if (body == NULL)
+ {
+ unpack_abort("putlayout: unexpected NULL for body");
+ return;
+ }
+ for (i = 0; body[i] != nullptr; i++)
+ {
+ band &b = *body[i];
+ byte le_kind = b.le_kind;
+
+ // Handle scalar part, if any.
+ int x = 0;
+ entry *e = nullptr;
+ if (b.defc != nullptr)
+ {
+ // It has data, so unparse an element.
+ if (b.ixTag != CONSTANT_None)
+ {
+ assert(le_kind == EK_REF);
+ if (b.ixTag == CONSTANT_Literal)
+ e = b.getRefUsing(cp.getKQIndex());
+ else
+ e = b.getRefN();
+ switch (b.le_len)
+ {
+ case 0:
+ break;
+ case 1:
+ putu1ref(e);
+ break;
+ case 2:
+ putref(e);
+ break;
+ case 4:
+ putu2(0);
+ putref(e);
+ break;
+ default:
+ assert(false);
+ }
+ }
+ else
+ {
+ assert(le_kind == EK_INT || le_kind == EK_REPL || le_kind == EK_UN);
+ x = b.getInt();
+
+ assert(!b.le_bci || prevBCI == (int)to_bci(prevBII));
+ switch (b.le_bci)
+ {
+ case EK_BCI: // PH: transmit R(bci), store bci
+ x = to_bci(prevBII = x);
+ prevBCI = x;
+ break;
+ case EK_BCID: // POH: transmit D(R(bci)), store bci
+ x = to_bci(prevBII += x);
+ prevBCI = x;
+ break;
+ case EK_BCO: // OH: transmit D(R(bci)), store D(bci)
+ x = to_bci(prevBII += x) - prevBCI;
+ prevBCI += x;
+ break;
+ }
+ assert(!b.le_bci || prevBCI == (int)to_bci(prevBII));
+
+ switch (b.le_len)
+ {
+ case 0:
+ break;
+ case 1:
+ putu1(x);
+ break;
+ case 2:
+ putu2(x);
+ break;
+ case 4:
+ putu4(x);
+ break;
+ default:
+ assert(false);
+ }
+ }
+ }
+
+ // Handle subparts, if any.
+ switch (le_kind)
+ {
+ case EK_REPL:
+ // x is the repeat count
+ while (x-- > 0)
+ {
+ putlayout(b.le_body);
+ }
+ break;
+ case EK_UN:
+ // x is the tag
+ putlayout(findMatchingCase(x, b.le_body));
+ break;
+ case EK_CALL:
+ {
+ band &cble = *b.le_body[0];
+ assert(cble.le_kind == EK_CBLE);
+ // FIXME: hit this one
+ // assert(cble.le_len == b.le_len);
+ putlayout(cble.le_body);
+ }
+ break;
+
+ case EK_CBLE:
+ case EK_CASE:
+ assert(false); // should not reach here
+ }
+ }
}
void unpacker::read_files()
{
- file_name.readData(file_count);
- if ((archive_options & AO_HAVE_FILE_SIZE_HI) != 0)
- file_size_hi.readData(file_count);
- file_size_lo.readData(file_count);
- if ((archive_options & AO_HAVE_FILE_MODTIME) != 0)
- file_modtime.readData(file_count);
- int allFiles = file_count + class_count;
- if ((archive_options & AO_HAVE_FILE_OPTIONS) != 0)
- {
- file_options.readData(file_count);
- // FO_IS_CLASS_STUB might be set, causing overlap between classes and files
- for (int i = 0; i < file_count; i++)
- {
- if ((file_options.getInt() & FO_IS_CLASS_STUB) != 0)
- {
- allFiles -= 1; // this one counts as both class and file
- }
- }
- file_options.rewind();
- }
- assert((default_file_options & FO_IS_CLASS_STUB) == 0);
- files_remaining = allFiles;
+ file_name.readData(file_count);
+ if ((archive_options & AO_HAVE_FILE_SIZE_HI) != 0)
+ file_size_hi.readData(file_count);
+ file_size_lo.readData(file_count);
+ if ((archive_options & AO_HAVE_FILE_MODTIME) != 0)
+ file_modtime.readData(file_count);
+ int allFiles = file_count + class_count;
+ if ((archive_options & AO_HAVE_FILE_OPTIONS) != 0)
+ {
+ file_options.readData(file_count);
+ // FO_IS_CLASS_STUB might be set, causing overlap between classes and files
+ for (int i = 0; i < file_count; i++)
+ {
+ if ((file_options.getInt() & FO_IS_CLASS_STUB) != 0)
+ {
+ allFiles -= 1; // this one counts as both class and file
+ }
+ }
+ file_options.rewind();
+ }
+ assert((default_file_options & FO_IS_CLASS_STUB) == 0);
+ files_remaining = allFiles;
}
void unpacker::get_code_header(int &max_stack, int &max_na_locals, int &handler_count,
- int &cflags)
+ int &cflags)
{
- int sc = code_headers.getByte();
- if (sc == 0)
- {
- max_stack = max_na_locals = handler_count = cflags = -1;
- return;
- }
- // Short code header is the usual case:
- int nh;
- int mod;
- if (sc < 1 + 12 * 12)
- {
- sc -= 1;
- nh = 0;
- mod = 12;
- }
- else if (sc < 1 + 12 * 12 + 8 * 8)
- {
- sc -= 1 + 12 * 12;
- nh = 1;
- mod = 8;
- }
- else
- {
- assert(sc < 1 + 12 * 12 + 8 * 8 + 7 * 7);
- sc -= 1 + 12 * 12 + 8 * 8;
- nh = 2;
- mod = 7;
- }
- max_stack = sc % mod;
- max_na_locals = sc / mod; // caller must add static, siglen
- handler_count = nh;
- if ((archive_options & AO_HAVE_ALL_CODE_FLAGS) != 0)
- cflags = -1;
- else
- cflags = 0; // this one has no attributes
+ int sc = code_headers.getByte();
+ if (sc == 0)
+ {
+ max_stack = max_na_locals = handler_count = cflags = -1;
+ return;
+ }
+ // Short code header is the usual case:
+ int nh;
+ int mod;
+ if (sc < 1 + 12 * 12)
+ {
+ sc -= 1;
+ nh = 0;
+ mod = 12;
+ }
+ else if (sc < 1 + 12 * 12 + 8 * 8)
+ {
+ sc -= 1 + 12 * 12;
+ nh = 1;
+ mod = 8;
+ }
+ else
+ {
+ assert(sc < 1 + 12 * 12 + 8 * 8 + 7 * 7);
+ sc -= 1 + 12 * 12 + 8 * 8;
+ nh = 2;
+ mod = 7;
+ }
+ max_stack = sc % mod;
+ max_na_locals = sc / mod; // caller must add static, siglen
+ handler_count = nh;
+ if ((archive_options & AO_HAVE_ALL_CODE_FLAGS) != 0)
+ cflags = -1;
+ else
+ cflags = 0; // this one has no attributes
}
// Cf. PackageReader.readCodeHeaders
void unpacker::read_code_headers()
{
- code_headers.readData(code_count);
- int totalHandlerCount = 0;
- int totalFlagsCount = 0;
- for (int i = 0; i < code_count; i++)
- {
- int max_stack, max_locals, handler_count, cflags;
- get_code_header(max_stack, max_locals, handler_count, cflags);
- if (max_stack < 0)
- code_max_stack.expectMoreLength(1);
- if (max_locals < 0)
- code_max_na_locals.expectMoreLength(1);
- if (handler_count < 0)
- code_handler_count.expectMoreLength(1);
- else
- totalHandlerCount += handler_count;
- if (cflags < 0)
- totalFlagsCount += 1;
- }
- code_headers.rewind(); // replay later during writing
-
- code_max_stack.readData();
- code_max_na_locals.readData();
- code_handler_count.readData();
- totalHandlerCount += code_handler_count.getIntTotal();
-
- // Read handler specifications.
- // Cf. PackageReader.readCodeHandlers.
- code_handler_start_P.readData(totalHandlerCount);
- code_handler_end_PO.readData(totalHandlerCount);
- code_handler_catch_PO.readData(totalHandlerCount);
- code_handler_class_RCN.readData(totalHandlerCount);
-
- read_attrs(ATTR_CONTEXT_CODE, totalFlagsCount);
+ code_headers.readData(code_count);
+ int totalHandlerCount = 0;
+ int totalFlagsCount = 0;
+ for (int i = 0; i < code_count; i++)
+ {
+ int max_stack, max_locals, handler_count, cflags;
+ get_code_header(max_stack, max_locals, handler_count, cflags);
+ if (max_stack < 0)
+ code_max_stack.expectMoreLength(1);
+ if (max_locals < 0)
+ code_max_na_locals.expectMoreLength(1);
+ if (handler_count < 0)
+ code_handler_count.expectMoreLength(1);
+ else
+ totalHandlerCount += handler_count;
+ if (cflags < 0)
+ totalFlagsCount += 1;
+ }
+ code_headers.rewind(); // replay later during writing
+
+ code_max_stack.readData();
+ code_max_na_locals.readData();
+ code_handler_count.readData();
+ totalHandlerCount += code_handler_count.getIntTotal();
+
+ // Read handler specifications.
+ // Cf. PackageReader.readCodeHandlers.
+ code_handler_start_P.readData(totalHandlerCount);
+ code_handler_end_PO.readData(totalHandlerCount);
+ code_handler_catch_PO.readData(totalHandlerCount);
+ code_handler_class_RCN.readData(totalHandlerCount);
+
+ read_attrs(ATTR_CONTEXT_CODE, totalFlagsCount);
}
static inline bool is_in_range(uint32_t n, uint32_t min, uint32_t max)
{
- return n - min <= max - min; // unsigned arithmetic!
+ return n - min <= max - min; // unsigned arithmetic!
}
static inline bool is_field_op(int bc)
{
- return is_in_range(bc, bc_getstatic, bc_putfield);
+ return is_in_range(bc, bc_getstatic, bc_putfield);
}
static inline bool is_invoke_init_op(int bc)
{
- return is_in_range(bc, _invokeinit_op, _invokeinit_limit - 1);
+ return is_in_range(bc, _invokeinit_op, _invokeinit_limit - 1);
}
static inline bool is_self_linker_op(int bc)
{
- return is_in_range(bc, _self_linker_op, _self_linker_limit - 1);
+ return is_in_range(bc, _self_linker_op, _self_linker_limit - 1);
}
static bool is_branch_op(int bc)
{
- return is_in_range(bc, bc_ifeq, bc_jsr) || is_in_range(bc, bc_ifnull, bc_jsr_w);
+ return is_in_range(bc, bc_ifeq, bc_jsr) || is_in_range(bc, bc_ifnull, bc_jsr_w);
}
static bool is_local_slot_op(int bc)
{
- return is_in_range(bc, bc_iload, bc_aload) || is_in_range(bc, bc_istore, bc_astore) ||
- bc == bc_iinc || bc == bc_ret;
+ return is_in_range(bc, bc_iload, bc_aload) || is_in_range(bc, bc_istore, bc_astore) ||
+ bc == bc_iinc || bc == bc_ret;
}
band *unpacker::ref_band_for_op(int bc)
{
- switch (bc)
- {
- case bc_ildc:
- case bc_ildc_w:
- return &bc_intref;
- case bc_fldc:
- case bc_fldc_w:
- return &bc_floatref;
- case bc_lldc2_w:
- return &bc_longref;
- case bc_dldc2_w:
- return &bc_doubleref;
- case bc_aldc:
- case bc_aldc_w:
- return &bc_stringref;
- case bc_cldc:
- case bc_cldc_w:
- return &bc_classref;
-
- case bc_getstatic:
- case bc_putstatic:
- case bc_getfield:
- case bc_putfield:
- return &bc_fieldref;
-
- case bc_invokevirtual:
- case bc_invokespecial:
- case bc_invokestatic:
- return &bc_methodref;
- case bc_invokeinterface:
- return &bc_imethodref;
-
- case bc_new:
- case bc_anewarray:
- case bc_checkcast:
- case bc_instanceof:
- case bc_multianewarray:
- return &bc_classref;
- }
- return nullptr;
+ switch (bc)
+ {
+ case bc_ildc:
+ case bc_ildc_w:
+ return &bc_intref;
+ case bc_fldc:
+ case bc_fldc_w:
+ return &bc_floatref;
+ case bc_lldc2_w:
+ return &bc_longref;
+ case bc_dldc2_w:
+ return &bc_doubleref;
+ case bc_aldc:
+ case bc_aldc_w:
+ return &bc_stringref;
+ case bc_cldc:
+ case bc_cldc_w:
+ return &bc_classref;
+
+ case bc_getstatic:
+ case bc_putstatic:
+ case bc_getfield:
+ case bc_putfield:
+ return &bc_fieldref;
+
+ case bc_invokevirtual:
+ case bc_invokespecial:
+ case bc_invokestatic:
+ return &bc_methodref;
+ case bc_invokeinterface:
+ return &bc_imethodref;
+
+ case bc_new:
+ case bc_anewarray:
+ case bc_checkcast:
+ case bc_instanceof:
+ case bc_multianewarray:
+ return &bc_classref;
+ }
+ return nullptr;
}
band *unpacker::ref_band_for_self_op(int bc, bool &isAloadVar, int &origBCVar)
{
- if (!is_self_linker_op(bc))
- return nullptr;
- int idx = (bc - _self_linker_op);
- bool isSuper = (idx >= _self_linker_super_flag);
- if (isSuper)
- idx -= _self_linker_super_flag;
- bool isAload = (idx >= _self_linker_aload_flag);
- if (isAload)
- idx -= _self_linker_aload_flag;
- int origBC = _first_linker_op + idx;
- bool isField = is_field_op(origBC);
- isAloadVar = isAload;
- origBCVar = _first_linker_op + idx;
- if (!isSuper)
- return isField ? &bc_thisfield : &bc_thismethod;
- else
- return isField ? &bc_superfield : &bc_supermethod;
+ if (!is_self_linker_op(bc))
+ return nullptr;
+ int idx = (bc - _self_linker_op);
+ bool isSuper = (idx >= _self_linker_super_flag);
+ if (isSuper)
+ idx -= _self_linker_super_flag;
+ bool isAload = (idx >= _self_linker_aload_flag);
+ if (isAload)
+ idx -= _self_linker_aload_flag;
+ int origBC = _first_linker_op + idx;
+ bool isField = is_field_op(origBC);
+ isAloadVar = isAload;
+ origBCVar = _first_linker_op + idx;
+ if (!isSuper)
+ return isField ? &bc_thisfield : &bc_thismethod;
+ else
+ return isField ? &bc_superfield : &bc_supermethod;
}
// Cf. PackageReader.readByteCodes
inline // called exactly once => inline
- void
+ void
unpacker::read_bcs()
{
- // read from bc_codes and bc_case_count
- fillbytes all_switch_ops;
- all_switch_ops.init();
-
- // Read directly from rp/rplimit.
- // Do this later: bc_codes.readData(...)
- byte *rp0 = rp;
-
- band *bc_which;
- byte *opptr = rp;
- byte *oplimit = rplimit;
-
- bool isAload; // passed by ref and then ignored
- int junkBC; // passed by ref and then ignored
- for (int k = 0; k < code_count; k++)
- {
- // Scan one method:
- for (;;)
- {
- if (opptr + 2 > oplimit)
- {
- rp = opptr;
- ensure_input(2);
- oplimit = rplimit;
- rp = rp0; // back up
- }
- if (opptr == oplimit)
- {
- unpack_abort();
- }
- int bc = *opptr++ & 0xFF;
- bool isWide = false;
- if (bc == bc_wide)
- {
- if (opptr == oplimit)
- {
- unpack_abort();
- }
- bc = *opptr++ & 0xFF;
- isWide = true;
- }
- // Adjust expectations of various band sizes.
- switch (bc)
- {
- case bc_tableswitch:
- case bc_lookupswitch:
- all_switch_ops.addByte(bc);
- break;
- case bc_iinc:
- bc_local.expectMoreLength(1);
- bc_which = isWide ? &bc_short : &bc_byte;
- bc_which->expectMoreLength(1);
- break;
- case bc_sipush:
- bc_short.expectMoreLength(1);
- break;
- case bc_bipush:
- bc_byte.expectMoreLength(1);
- break;
- case bc_newarray:
- bc_byte.expectMoreLength(1);
- break;
- case bc_multianewarray:
- assert(ref_band_for_op(bc) == &bc_classref);
- bc_classref.expectMoreLength(1);
- bc_byte.expectMoreLength(1);
- break;
- case bc_ref_escape:
- bc_escrefsize.expectMoreLength(1);
- bc_escref.expectMoreLength(1);
- break;
- case bc_byte_escape:
- bc_escsize.expectMoreLength(1);
- // bc_escbyte will have to be counted too
- break;
- default:
- if (is_invoke_init_op(bc))
- {
- bc_initref.expectMoreLength(1);
- break;
- }
- bc_which = ref_band_for_self_op(bc, isAload, junkBC);
- if (bc_which != nullptr)
- {
- bc_which->expectMoreLength(1);
- break;
- }
- if (is_branch_op(bc))
- {
- bc_label.expectMoreLength(1);
- break;
- }
- bc_which = ref_band_for_op(bc);
- if (bc_which != nullptr)
- {
- bc_which->expectMoreLength(1);
- assert(bc != bc_multianewarray); // handled elsewhere
- break;
- }
- if (is_local_slot_op(bc))
- {
- bc_local.expectMoreLength(1);
- break;
- }
- break;
- case bc_end_marker:
- // Increment k and test against code_count.
- goto doneScanningMethod;
- }
- }
- doneScanningMethod:
- {
- }
- }
-
- // Go through the formality, so we can use it in a regular fashion later:
- assert(rp == rp0);
- bc_codes.readData((int)(opptr - rp));
-
- int i = 0;
-
- // To size instruction bands correctly, we need info on switches:
- bc_case_count.readData((int)all_switch_ops.size());
- for (i = 0; i < (int)all_switch_ops.size(); i++)
- {
- int caseCount = bc_case_count.getInt();
- int bc = all_switch_ops.getByte(i);
- bc_label.expectMoreLength(1 + caseCount); // default label + cases
- bc_case_value.expectMoreLength(bc == bc_tableswitch ? 1 : caseCount);
- }
- bc_case_count.rewind(); // uses again for output
-
- all_switch_ops.free();
-
- for (i = e_bc_case_value; i <= e_bc_escsize; i++)
- {
- all_bands[i].readData();
- }
-
- // The bc_escbyte band is counted by the immediately previous band.
- bc_escbyte.readData(bc_escsize.getIntTotal());
+ // read from bc_codes and bc_case_count
+ fillbytes all_switch_ops;
+ all_switch_ops.init();
+
+ // Read directly from rp/rplimit.
+ // Do this later: bc_codes.readData(...)
+ byte *rp0 = rp;
+
+ band *bc_which;
+ byte *opptr = rp;
+ byte *oplimit = rplimit;
+
+ bool isAload; // passed by ref and then ignored
+ int junkBC; // passed by ref and then ignored
+ for (int k = 0; k < code_count; k++)
+ {
+ // Scan one method:
+ for (;;)
+ {
+ if (opptr + 2 > oplimit)
+ {
+ rp = opptr;
+ ensure_input(2);
+ oplimit = rplimit;
+ rp = rp0; // back up
+ }
+ if (opptr == oplimit)
+ {
+ unpack_abort();
+ }
+ int bc = *opptr++ & 0xFF;
+ bool isWide = false;
+ if (bc == bc_wide)
+ {
+ if (opptr == oplimit)
+ {
+ unpack_abort();
+ }
+ bc = *opptr++ & 0xFF;
+ isWide = true;
+ }
+ // Adjust expectations of various band sizes.
+ switch (bc)
+ {
+ case bc_tableswitch:
+ case bc_lookupswitch:
+ all_switch_ops.addByte(bc);
+ break;
+ case bc_iinc:
+ bc_local.expectMoreLength(1);
+ bc_which = isWide ? &bc_short : &bc_byte;
+ bc_which->expectMoreLength(1);
+ break;
+ case bc_sipush:
+ bc_short.expectMoreLength(1);
+ break;
+ case bc_bipush:
+ bc_byte.expectMoreLength(1);
+ break;
+ case bc_newarray:
+ bc_byte.expectMoreLength(1);
+ break;
+ case bc_multianewarray:
+ assert(ref_band_for_op(bc) == &bc_classref);
+ bc_classref.expectMoreLength(1);
+ bc_byte.expectMoreLength(1);
+ break;
+ case bc_ref_escape:
+ bc_escrefsize.expectMoreLength(1);
+ bc_escref.expectMoreLength(1);
+ break;
+ case bc_byte_escape:
+ bc_escsize.expectMoreLength(1);
+ // bc_escbyte will have to be counted too
+ break;
+ default:
+ if (is_invoke_init_op(bc))
+ {
+ bc_initref.expectMoreLength(1);
+ break;
+ }
+ bc_which = ref_band_for_self_op(bc, isAload, junkBC);
+ if (bc_which != nullptr)
+ {
+ bc_which->expectMoreLength(1);
+ break;
+ }
+ if (is_branch_op(bc))
+ {
+ bc_label.expectMoreLength(1);
+ break;
+ }
+ bc_which = ref_band_for_op(bc);
+ if (bc_which != nullptr)
+ {
+ bc_which->expectMoreLength(1);
+ assert(bc != bc_multianewarray); // handled elsewhere
+ break;
+ }
+ if (is_local_slot_op(bc))
+ {
+ bc_local.expectMoreLength(1);
+ break;
+ }
+ break;
+ case bc_end_marker:
+ // Increment k and test against code_count.
+ goto doneScanningMethod;
+ }
+ }
+ doneScanningMethod:
+ {
+ }
+ }
+
+ // Go through the formality, so we can use it in a regular fashion later:
+ assert(rp == rp0);
+ bc_codes.readData((int)(opptr - rp));
+
+ int i = 0;
+
+ // To size instruction bands correctly, we need info on switches:
+ bc_case_count.readData((int)all_switch_ops.size());
+ for (i = 0; i < (int)all_switch_ops.size(); i++)
+ {
+ int caseCount = bc_case_count.getInt();
+ int bc = all_switch_ops.getByte(i);
+ bc_label.expectMoreLength(1 + caseCount); // default label + cases
+ bc_case_value.expectMoreLength(bc == bc_tableswitch ? 1 : caseCount);
+ }
+ bc_case_count.rewind(); // uses again for output
+
+ all_switch_ops.free();
+
+ for (i = e_bc_case_value; i <= e_bc_escsize; i++)
+ {
+ all_bands[i].readData();
+ }
+
+ // The bc_escbyte band is counted by the immediately previous band.
+ bc_escbyte.readData(bc_escsize.getIntTotal());
}
void unpacker::read_bands()
{
- read_file_header();
-
- if (cp.nentries == 0)
- {
- // read_file_header failed to read a CP, because it copied a JAR.
- return;
- }
-
- // Do this after the file header has been read:
- check_options();
-
- read_cp();
- read_attr_defs();
- read_ics();
- read_classes();
- read_bcs();
- read_files();
+ read_file_header();
+
+ if (cp.nentries == 0)
+ {
+ // read_file_header failed to read a CP, because it copied a JAR.
+ return;
+ }
+
+ // Do this after the file header has been read:
+ check_options();
+
+ read_cp();
+ read_attr_defs();
+ read_ics();
+ read_classes();
+ read_bcs();
+ read_files();
}
/// CP routines
entry *&constant_pool::hashTabRef(byte tag, bytes &b)
{
- uint32_t hash = tag + (int)b.len;
- for (int i = 0; i < (int)b.len; i++)
- {
- hash = hash * 31 + (0xFF & b.ptr[i]);
- }
- entry **ht = hashTab;
- int hlen = hashTabLength;
- assert((hlen & (hlen - 1)) == 0); // must be power of 2
- uint32_t hash1 = hash & (hlen - 1); // == hash % hlen
- uint32_t hash2 = 0; // lazily computed (requires mod op.)
- int probes = 0;
- while (ht[hash1] != nullptr)
- {
- entry &e = *ht[hash1];
- if (e.value.b.equals(b) && e.tag == tag)
- break;
- if (hash2 == 0)
- // Note: hash2 must be relatively prime to hlen, hence the "|1".
- hash2 = (((hash % 499) & (hlen - 1)) | 1);
- hash1 += hash2;
- if (hash1 >= (uint32_t)hlen)
- hash1 -= hlen;
- assert(hash1 < (uint32_t)hlen);
- assert(++probes < hlen);
- }
- return ht[hash1];
+ uint32_t hash = tag + (int)b.len;
+ for (int i = 0; i < (int)b.len; i++)
+ {
+ hash = hash * 31 + (0xFF & b.ptr[i]);
+ }
+ entry **ht = hashTab;
+ int hlen = hashTabLength;
+ assert((hlen & (hlen - 1)) == 0); // must be power of 2
+ uint32_t hash1 = hash & (hlen - 1); // == hash % hlen
+ uint32_t hash2 = 0; // lazily computed (requires mod op.)
+#ifndef NDEBUG
+ int probes = 0;
+#endif
+ while (ht[hash1] != nullptr)
+ {
+ entry &e = *ht[hash1];
+ if (e.value.b.equals(b) && e.tag == tag)
+ break;
+ if (hash2 == 0)
+ // Note: hash2 must be relatively prime to hlen, hence the "|1".
+ hash2 = (((hash % 499) & (hlen - 1)) | 1);
+ hash1 += hash2;
+ if (hash1 >= (uint32_t)hlen)
+ hash1 -= hlen;
+ assert(hash1 < (uint32_t)hlen);
+ assert(++probes < hlen);
+ }
+ return ht[hash1];
}
static void insert_extra(entry *e, ptrlist &extras)
{
- // This ordering helps implement the Pack200 requirement
- // of a predictable CP order in the class files produced.
- e->inord = NO_INORD; // mark as an "extra"
- extras.add(e);
- // Note: We will sort the list (by string-name) later.
+ // This ordering helps implement the Pack200 requirement
+ // of a predictable CP order in the class files produced.
+ e->inord = NO_INORD; // mark as an "extra"
+ extras.add(e);
+ // Note: We will sort the list (by string-name) later.
}
entry *constant_pool::ensureUtf8(bytes &b)
{
- entry *&ix = hashTabRef(CONSTANT_Utf8, b);
- if (ix != nullptr)
- return ix;
- // Make one.
- if (nentries == maxentries)
- {
- unpack_abort("cp utf8 overflow");
- return &entries[tag_base[CONSTANT_Utf8]]; // return something
- }
- entry &e = entries[nentries++];
- e.tag = CONSTANT_Utf8;
- u->saveTo(e.value.b, b);
- assert(&e >= first_extra_entry);
- insert_extra(&e, tag_extras[CONSTANT_Utf8]);
- return ix = &e;
+ entry *&ix = hashTabRef(CONSTANT_Utf8, b);
+ if (ix != nullptr)
+ return ix;
+ // Make one.
+ if (nentries == maxentries)
+ {
+ unpack_abort("cp utf8 overflow");
+ return &entries[tag_base[CONSTANT_Utf8]]; // return something
+ }
+ entry &e = entries[nentries++];
+ e.tag = CONSTANT_Utf8;
+ u->saveTo(e.value.b, b);
+ assert(&e >= first_extra_entry);
+ insert_extra(&e, tag_extras[CONSTANT_Utf8]);
+ return ix = &e;
}
entry *constant_pool::ensureClass(bytes &b)
{
- entry *&ix = hashTabRef(CONSTANT_Class, b);
- if (ix != nullptr)
- return ix;
- // Make one.
- if (nentries == maxentries)
- {
- unpack_abort("cp class overflow");
- return &entries[tag_base[CONSTANT_Class]]; // return something
- }
- entry &e = entries[nentries++];
- e.tag = CONSTANT_Class;
- e.nrefs = 1;
- e.refs = U_NEW(entry *, 1);
- ix = &e; // hold my spot in the index
- entry *utf = ensureUtf8(b);
- e.refs[0] = utf;
- e.value.b = utf->value.b;
- assert(&e >= first_extra_entry);
- insert_extra(&e, tag_extras[CONSTANT_Class]);
- return &e;
+ entry *&ix = hashTabRef(CONSTANT_Class, b);
+ if (ix != nullptr)
+ return ix;
+ // Make one.
+ if (nentries == maxentries)
+ {
+ unpack_abort("cp class overflow");
+ return &entries[tag_base[CONSTANT_Class]]; // return something
+ }
+ entry &e = entries[nentries++];
+ e.tag = CONSTANT_Class;
+ e.nrefs = 1;
+ e.refs = U_NEW(entry *, 1);
+ ix = &e; // hold my spot in the index
+ entry *utf = ensureUtf8(b);
+ e.refs[0] = utf;
+ e.value.b = utf->value.b;
+ assert(&e >= first_extra_entry);
+ insert_extra(&e, tag_extras[CONSTANT_Class]);
+ return &e;
}
void constant_pool::expandSignatures()
{
- int i;
- int nsigs = 0;
- int nreused = 0;
- int first_sig = tag_base[CONSTANT_Signature];
- int sig_limit = tag_count[CONSTANT_Signature] + first_sig;
- fillbytes buf;
- buf.init(1 << 10);
- for (i = first_sig; i < sig_limit; i++)
- {
- entry &e = entries[i];
- assert(e.tag == CONSTANT_Signature);
- int refnum = 0;
- bytes form = e.refs[refnum++]->asUtf8();
- buf.empty();
- for (int j = 0; j < (int)form.len; j++)
- {
- int c = form.ptr[j];
- buf.addByte(c);
- if (c == 'L')
- {
- entry *cls = e.refs[refnum++];
- buf.append(cls->className()->asUtf8());
- }
- }
- assert(refnum == e.nrefs);
- bytes &sig = buf.b;
-
- // try to find a pre-existing Utf8:
- entry *&e2 = hashTabRef(CONSTANT_Utf8, sig);
- if (e2 != nullptr)
- {
- assert(e2->isUtf8(sig));
- e.value.b = e2->value.b;
- e.refs[0] = e2;
- e.nrefs = 1;
- nreused++;
- }
- else
- {
- // there is no other replacement; reuse this CP entry as a Utf8
- u->saveTo(e.value.b, sig);
- e.tag = CONSTANT_Utf8;
- e.nrefs = 0;
- e2 = &e;
- }
- nsigs++;
- }
- buf.free();
-
- // go expunge all references to remaining signatures:
- for (i = 0; i < (int)nentries; i++)
- {
- entry &e = entries[i];
- for (int j = 0; j < e.nrefs; j++)
- {
- entry *&e2 = e.refs[j];
- if (e2 != nullptr && e2->tag == CONSTANT_Signature)
- e2 = e2->refs[0];
- }
- }
+ int i;
+ int nsigs = 0;
+ int nreused = 0;
+ int first_sig = tag_base[CONSTANT_Signature];
+ int sig_limit = tag_count[CONSTANT_Signature] + first_sig;
+ fillbytes buf;
+ buf.init(1 << 10);
+ for (i = first_sig; i < sig_limit; i++)
+ {
+ entry &e = entries[i];
+ assert(e.tag == CONSTANT_Signature);
+ int refnum = 0;
+ bytes form = e.refs[refnum++]->asUtf8();
+ buf.empty();
+ for (int j = 0; j < (int)form.len; j++)
+ {
+ int c = form.ptr[j];
+ buf.addByte(c);
+ if (c == 'L')
+ {
+ entry *cls = e.refs[refnum++];
+ buf.append(cls->className()->asUtf8());
+ }
+ }
+ assert(refnum == e.nrefs);
+ bytes &sig = buf.b;
+
+ // try to find a pre-existing Utf8:
+ entry *&e2 = hashTabRef(CONSTANT_Utf8, sig);
+ if (e2 != nullptr)
+ {
+ assert(e2->isUtf8(sig));
+ e.value.b = e2->value.b;
+ e.refs[0] = e2;
+ e.nrefs = 1;
+ nreused++;
+ }
+ else
+ {
+ // there is no other replacement; reuse this CP entry as a Utf8
+ u->saveTo(e.value.b, sig);
+ e.tag = CONSTANT_Utf8;
+ e.nrefs = 0;
+ e2 = &e;
+ }
+ nsigs++;
+ }
+ buf.free();
+
+ // go expunge all references to remaining signatures:
+ for (i = 0; i < (int)nentries; i++)
+ {
+ entry &e = entries[i];
+ for (int j = 0; j < e.nrefs; j++)
+ {
+ entry *&e2 = e.refs[j];
+ if (e2 != nullptr && e2->tag == CONSTANT_Signature)
+ e2 = e2->refs[0];
+ }
+ }
}
void constant_pool::initMemberIndexes()
{
- // This function does NOT refer to any class schema.
- // It is totally internal to the cpool.
- int i, j;
-
- // Get the pre-existing indexes:
- int nclasses = tag_count[CONSTANT_Class];
- // entry *classes = tag_base[CONSTANT_Class] + entries; // UNUSED
- int nfields = tag_count[CONSTANT_Fieldref];
- entry *fields = tag_base[CONSTANT_Fieldref] + entries;
- int nmethods = tag_count[CONSTANT_Methodref];
- entry *methods = tag_base[CONSTANT_Methodref] + entries;
-
- int *field_counts = T_NEW(int, nclasses);
- int *method_counts = T_NEW(int, nclasses);
- cpindex *all_indexes = U_NEW(cpindex, nclasses * 2);
- entry **field_ix = U_NEW(entry *, add_size(nfields, nclasses));
- entry **method_ix = U_NEW(entry *, add_size(nmethods, nclasses));
-
- for (j = 0; j < nfields; j++)
- {
- entry &f = fields[j];
- i = f.memberClass()->inord;
- assert(i < nclasses);
- field_counts[i]++;
- }
- for (j = 0; j < nmethods; j++)
- {
- entry &m = methods[j];
- i = m.memberClass()->inord;
- assert(i < nclasses);
- method_counts[i]++;
- }
-
- int fbase = 0, mbase = 0;
- for (i = 0; i < nclasses; i++)
- {
- int fc = field_counts[i];
- int mc = method_counts[i];
- all_indexes[i * 2 + 0].init(fc, field_ix + fbase, CONSTANT_Fieldref + SUBINDEX_BIT);
- all_indexes[i * 2 + 1].init(mc, method_ix + mbase, CONSTANT_Methodref + SUBINDEX_BIT);
- // reuse field_counts and member_counts as fill pointers:
- field_counts[i] = fbase;
- method_counts[i] = mbase;
- fbase += fc + 1;
- mbase += mc + 1;
- // (the +1 leaves a space between every subarray)
- }
- assert(fbase == nfields + nclasses);
- assert(mbase == nmethods + nclasses);
-
- for (j = 0; j < nfields; j++)
- {
- entry &f = fields[j];
- i = f.memberClass()->inord;
- field_ix[field_counts[i]++] = &f;
- }
- for (j = 0; j < nmethods; j++)
- {
- entry &m = methods[j];
- i = m.memberClass()->inord;
- method_ix[method_counts[i]++] = &m;
- }
-
- member_indexes = all_indexes;
-
- // Free intermediate buffers.
- u->free_temps();
+ // This function does NOT refer to any class schema.
+ // It is totally internal to the cpool.
+ int i, j;
+
+ // Get the pre-existing indexes:
+ int nclasses = tag_count[CONSTANT_Class];
+ // entry *classes = tag_base[CONSTANT_Class] + entries; // UNUSED
+ int nfields = tag_count[CONSTANT_Fieldref];
+ entry *fields = tag_base[CONSTANT_Fieldref] + entries;
+ int nmethods = tag_count[CONSTANT_Methodref];
+ entry *methods = tag_base[CONSTANT_Methodref] + entries;
+
+ int *field_counts = T_NEW(int, nclasses);
+ int *method_counts = T_NEW(int, nclasses);
+ cpindex *all_indexes = U_NEW(cpindex, nclasses * 2);
+ entry **field_ix = U_NEW(entry *, add_size(nfields, nclasses));
+ entry **method_ix = U_NEW(entry *, add_size(nmethods, nclasses));
+
+ for (j = 0; j < nfields; j++)
+ {
+ entry &f = fields[j];
+ i = f.memberClass()->inord;
+ assert(i < nclasses);
+ field_counts[i]++;
+ }
+ for (j = 0; j < nmethods; j++)
+ {
+ entry &m = methods[j];
+ i = m.memberClass()->inord;
+ assert(i < nclasses);
+ method_counts[i]++;
+ }
+
+ int fbase = 0, mbase = 0;
+ for (i = 0; i < nclasses; i++)
+ {
+ int fc = field_counts[i];
+ int mc = method_counts[i];
+ all_indexes[i * 2 + 0].init(fc, field_ix + fbase, CONSTANT_Fieldref + SUBINDEX_BIT);
+ all_indexes[i * 2 + 1].init(mc, method_ix + mbase, CONSTANT_Methodref + SUBINDEX_BIT);
+ // reuse field_counts and member_counts as fill pointers:
+ field_counts[i] = fbase;
+ method_counts[i] = mbase;
+ fbase += fc + 1;
+ mbase += mc + 1;
+ // (the +1 leaves a space between every subarray)
+ }
+ assert(fbase == nfields + nclasses);
+ assert(mbase == nmethods + nclasses);
+
+ for (j = 0; j < nfields; j++)
+ {
+ entry &f = fields[j];
+ i = f.memberClass()->inord;
+ field_ix[field_counts[i]++] = &f;
+ }
+ for (j = 0; j < nmethods; j++)
+ {
+ entry &m = methods[j];
+ i = m.memberClass()->inord;
+ method_ix[method_counts[i]++] = &m;
+ }
+
+ member_indexes = all_indexes;
+
+ // Free intermediate buffers.
+ u->free_temps();
}
void entry::requestOutputIndex(constant_pool &cp, int req)
{
- assert(outputIndex <= NOT_REQUESTED); // must not have assigned indexes yet
- if (tag == CONSTANT_Signature)
- {
- ref(0)->requestOutputIndex(cp, req);
- return;
- }
- assert(req == REQUESTED || req == REQUESTED_LDC);
- if (outputIndex != NOT_REQUESTED)
- {
- if (req == REQUESTED_LDC)
- outputIndex = req; // this kind has precedence
- return;
- }
- outputIndex = req;
- // assert(!cp.outputEntries.contains(this));
- assert(tag != CONSTANT_Signature);
- cp.outputEntries.add(this);
- for (int j = 0; j < nrefs; j++)
- {
- ref(j)->requestOutputIndex(cp);
- }
+ assert(outputIndex <= NOT_REQUESTED); // must not have assigned indexes yet
+ if (tag == CONSTANT_Signature)
+ {
+ ref(0)->requestOutputIndex(cp, req);
+ return;
+ }
+ assert(req == REQUESTED || req == REQUESTED_LDC);
+ if (outputIndex != NOT_REQUESTED)
+ {
+ if (req == REQUESTED_LDC)
+ outputIndex = req; // this kind has precedence
+ return;
+ }
+ outputIndex = req;
+ // assert(!cp.outputEntries.contains(this));
+ assert(tag != CONSTANT_Signature);
+ cp.outputEntries.add(this);
+ for (int j = 0; j < nrefs; j++)
+ {
+ ref(j)->requestOutputIndex(cp);
+ }
}
void constant_pool::resetOutputIndexes()
{
- int i;
- int noes = outputEntries.length();
- entry **oes = (entry **)outputEntries.base();
- for (i = 0; i < noes; i++)
- {
- entry &e = *oes[i];
- e.outputIndex = NOT_REQUESTED;
- }
- outputIndexLimit = 0;
- outputEntries.empty();
+ int i;
+ int noes = outputEntries.length();
+ entry **oes = (entry **)outputEntries.base();
+ for (i = 0; i < noes; i++)
+ {
+ entry &e = *oes[i];
+ e.outputIndex = NOT_REQUESTED;
+ }
+ outputIndexLimit = 0;
+ outputEntries.empty();
}
static const byte TAG_ORDER[CONSTANT_Limit] = {0, 1, 0, 2, 3, 4, 5, 7, 6, 10, 11, 12, 9, 8};
extern "C" int outputEntry_cmp(const void *e1p, const void *e2p)
{
- // Sort entries according to the Pack200 rules for deterministic
- // constant pool ordering.
- //
- // The four sort keys as follows, in order of decreasing importance:
- // 1. ldc first, then non-ldc guys
- // 2. normal cp_All entries by input order (i.e., address order)
- // 3. after that, extra entries by lexical order (as in tag_extras[*])
- entry &e1 = *(entry *)*(void **)e1p;
- entry &e2 = *(entry *)*(void **)e2p;
- int oi1 = e1.outputIndex;
- int oi2 = e2.outputIndex;
- assert(oi1 == REQUESTED || oi1 == REQUESTED_LDC);
- assert(oi2 == REQUESTED || oi2 == REQUESTED_LDC);
- if (oi1 != oi2)
- {
- if (oi1 == REQUESTED_LDC)
- return 0 - 1;
- if (oi2 == REQUESTED_LDC)
- return 1 - 0;
- // Else fall through; neither is an ldc request.
- }
- if (e1.inord != NO_INORD || e2.inord != NO_INORD)
- {
- // One or both is normal. Use input order.
- if (&e1 > &e2)
- return 1 - 0;
- if (&e1 < &e2)
- return 0 - 1;
- return 0; // equal pointers
- }
- // Both are extras. Sort by tag and then by value.
- if (e1.tag != e2.tag)
- {
- return TAG_ORDER[e1.tag] - TAG_ORDER[e2.tag];
- }
- // If the tags are the same, use string comparison.
- return compare_Utf8_chars(e1.value.b, e2.value.b);
+ // Sort entries according to the Pack200 rules for deterministic
+ // constant pool ordering.
+ //
+ // The four sort keys as follows, in order of decreasing importance:
+ // 1. ldc first, then non-ldc guys
+ // 2. normal cp_All entries by input order (i.e., address order)
+ // 3. after that, extra entries by lexical order (as in tag_extras[*])
+ entry &e1 = *(entry *)*(void **)e1p;
+ entry &e2 = *(entry *)*(void **)e2p;
+ int oi1 = e1.outputIndex;
+ int oi2 = e2.outputIndex;
+ assert(oi1 == REQUESTED || oi1 == REQUESTED_LDC);
+ assert(oi2 == REQUESTED || oi2 == REQUESTED_LDC);
+ if (oi1 != oi2)
+ {
+ if (oi1 == REQUESTED_LDC)
+ return 0 - 1;
+ if (oi2 == REQUESTED_LDC)
+ return 1 - 0;
+ // Else fall through; neither is an ldc request.
+ }
+ if (e1.inord != NO_INORD || e2.inord != NO_INORD)
+ {
+ // One or both is normal. Use input order.
+ if (&e1 > &e2)
+ return 1 - 0;
+ if (&e1 < &e2)
+ return 0 - 1;
+ return 0; // equal pointers
+ }
+ // Both are extras. Sort by tag and then by value.
+ if (e1.tag != e2.tag)
+ {
+ return TAG_ORDER[e1.tag] - TAG_ORDER[e2.tag];
+ }
+ // If the tags are the same, use string comparison.
+ return compare_Utf8_chars(e1.value.b, e2.value.b);
}
void constant_pool::computeOutputIndexes()
{
- int i;
-
- int noes = outputEntries.length();
- entry **oes = (entry **)outputEntries.base();
-
- // Sort the output constant pool into the order required by Pack200.
- PTRLIST_QSORT(outputEntries, outputEntry_cmp);
-
- // Allocate a new index for each entry that needs one.
- // We do this in two passes, one for LDC entries and one for the rest.
- int nextIndex = 1; // always skip index #0 in output cpool
- for (i = 0; i < noes; i++)
- {
- entry &e = *oes[i];
- assert(e.outputIndex == REQUESTED || e.outputIndex == REQUESTED_LDC);
- e.outputIndex = nextIndex++;
- if (e.isDoubleWord())
- nextIndex++; // do not use the next index
- }
- outputIndexLimit = nextIndex;
+ int i;
+
+ int noes = outputEntries.length();
+ entry **oes = (entry **)outputEntries.base();
+
+ // Sort the output constant pool into the order required by Pack200.
+ PTRLIST_QSORT(outputEntries, outputEntry_cmp);
+
+ // Allocate a new index for each entry that needs one.
+ // We do this in two passes, one for LDC entries and one for the rest.
+ int nextIndex = 1; // always skip index #0 in output cpool
+ for (i = 0; i < noes; i++)
+ {
+ entry &e = *oes[i];
+ assert(e.outputIndex == REQUESTED || e.outputIndex == REQUESTED_LDC);
+ e.outputIndex = nextIndex++;
+ if (e.isDoubleWord())
+ nextIndex++; // do not use the next index
+ }
+ outputIndexLimit = nextIndex;
}
// Unpacker Start
@@ -3477,64 +3473,63 @@ void constant_pool::computeOutputIndexes()
// Do not reset any unpack options.
void unpacker::reset()
{
- bytes_read_before_reset += bytes_read;
- bytes_written_before_reset += bytes_written;
- files_written_before_reset += files_written;
- classes_written_before_reset += classes_written;
- segments_read_before_reset += 1;
- if (verbose >= 2)
- {
- fprintf(stderr, "After segment %d, " LONG_LONG_FORMAT
- " bytes read and " LONG_LONG_FORMAT " bytes written.\n",
- segments_read_before_reset - 1, bytes_read_before_reset,
- bytes_written_before_reset);
- fprintf(stderr,
- "After segment %d, %d files (of which %d are classes) written to output.\n",
- segments_read_before_reset - 1, files_written_before_reset,
- classes_written_before_reset);
- if (archive_next_count != 0)
- {
- fprintf(stderr, "After segment %d, %d segment%s remaining (estimated).\n",
- segments_read_before_reset - 1, archive_next_count,
- archive_next_count == 1 ? "" : "s");
- }
- }
-
- unpacker save_u = (*this); // save bytewise image
- infileptr = nullptr; // make asserts happy
- jarout = nullptr; // do not close the output jar
- gzin = nullptr; // do not close the input gzip stream
- this->free();
- this->init(read_input_fn);
-
- // restore selected interface state:
- infileptr = save_u.infileptr;
- inbytes = save_u.inbytes;
- jarout = save_u.jarout;
- gzin = save_u.gzin;
- verbose = save_u.verbose;
- deflate_hint_or_zero = save_u.deflate_hint_or_zero;
- modification_time_or_zero = save_u.modification_time_or_zero;
- bytes_read_before_reset = save_u.bytes_read_before_reset;
- bytes_written_before_reset = save_u.bytes_written_before_reset;
- files_written_before_reset = save_u.files_written_before_reset;
- classes_written_before_reset = save_u.classes_written_before_reset;
- segments_read_before_reset = save_u.segments_read_before_reset;
- // Note: If we use strip_names, watch out: They get nuked here.
+ bytes_read_before_reset += bytes_read;
+ bytes_written_before_reset += bytes_written;
+ files_written_before_reset += files_written;
+ classes_written_before_reset += classes_written;
+ segments_read_before_reset += 1;
+ if (verbose >= 2)
+ {
+ fprintf(stderr, "After segment %d, %" PRIu64 " bytes read and %" PRIu64 " bytes written.\n",
+ segments_read_before_reset - 1, bytes_read_before_reset,
+ bytes_written_before_reset);
+ fprintf(stderr,
+ "After segment %d, %d files (of which %d are classes) written to output.\n",
+ segments_read_before_reset - 1, files_written_before_reset,
+ classes_written_before_reset);
+ if (archive_next_count != 0)
+ {
+ fprintf(stderr, "After segment %d, %d segment%s remaining (estimated).\n",
+ segments_read_before_reset - 1, archive_next_count,
+ archive_next_count == 1 ? "" : "s");
+ }
+ }
+
+ unpacker save_u = (*this); // save bytewise image
+ infileptr = nullptr; // make asserts happy
+ jarout = nullptr; // do not close the output jar
+ gzin = nullptr; // do not close the input gzip stream
+ this->free();
+ this->init(read_input_fn);
+
+ // restore selected interface state:
+ infileptr = save_u.infileptr;
+ inbytes = save_u.inbytes;
+ jarout = save_u.jarout;
+ gzin = save_u.gzin;
+ verbose = save_u.verbose;
+ deflate_hint_or_zero = save_u.deflate_hint_or_zero;
+ modification_time_or_zero = save_u.modification_time_or_zero;
+ bytes_read_before_reset = save_u.bytes_read_before_reset;
+ bytes_written_before_reset = save_u.bytes_written_before_reset;
+ files_written_before_reset = save_u.files_written_before_reset;
+ classes_written_before_reset = save_u.classes_written_before_reset;
+ segments_read_before_reset = save_u.segments_read_before_reset;
+ // Note: If we use strip_names, watch out: They get nuked here.
}
void unpacker::init(read_input_fn_t input_fn)
{
- int i;
- BYTES_OF(*this).clear();
- this->u = this; // self-reference for U_NEW macro
- read_input_fn = input_fn;
- all_bands = band::makeBands(this);
- // Make a default jar buffer; caller may safely overwrite it.
- jarout = U_NEW(jar, 1);
- jarout->init(this);
- for (i = 0; i < ATTR_CONTEXT_LIMIT; i++)
- attr_defs[i].u = u; // set up outer ptr
+ int i;
+ BYTES_OF(*this).clear();
+ this->u = this; // self-reference for U_NEW macro
+ read_input_fn = input_fn;
+ all_bands = band::makeBands(this);
+ // Make a default jar buffer; caller may safely overwrite it.
+ jarout = U_NEW(jar, 1);
+ jarout->init(this);
+ for (i = 0; i < ATTR_CONTEXT_LIMIT; i++)
+ attr_defs[i].u = u; // set up outer ptr
}
// Usage: unpack a byte buffer
@@ -3543,1251 +3538,1253 @@ void unpacker::init(read_input_fn_t input_fn)
// If nullptr, the callback is used to fill an internal buffer.
void unpacker::start(void *packptr, size_t len)
{
- if (packptr != nullptr && len != 0)
- {
- inbytes.set((byte *)packptr, len);
- }
- read_bands();
+ if (packptr != nullptr && len != 0)
+ {
+ inbytes.set((byte *)packptr, len);
+ }
+ read_bands();
}
void unpacker::check_options()
{
- if (deflate_hint_or_zero != 0)
- {
- bool force_deflate_hint = (deflate_hint_or_zero > 0);
- if (force_deflate_hint)
- default_file_options |= FO_DEFLATE_HINT;
- else
- default_file_options &= ~FO_DEFLATE_HINT;
- // Turn off per-file deflate hint by force.
- suppress_file_options |= FO_DEFLATE_HINT;
- }
- if (modification_time_or_zero != 0)
- {
- default_file_modtime = modification_time_or_zero;
- // Turn off per-file modtime by force.
- archive_options &= ~AO_HAVE_FILE_MODTIME;
- }
+ if (deflate_hint_or_zero != 0)
+ {
+ bool force_deflate_hint = (deflate_hint_or_zero > 0);
+ if (force_deflate_hint)
+ default_file_options |= FO_DEFLATE_HINT;
+ else
+ default_file_options &= ~FO_DEFLATE_HINT;
+ // Turn off per-file deflate hint by force.
+ suppress_file_options |= FO_DEFLATE_HINT;
+ }
+ if (modification_time_or_zero != 0)
+ {
+ default_file_modtime = modification_time_or_zero;
+ // Turn off per-file modtime by force.
+ archive_options &= ~AO_HAVE_FILE_MODTIME;
+ }
}
// classfile writing
void unpacker::reset_cur_classfile()
{
- // set defaults
- cur_class_minver = default_class_minver;
- cur_class_majver = default_class_majver;
-
- // reset constant pool state
- cp.resetOutputIndexes();
-
- // reset fixups
- class_fixup_type.empty();
- class_fixup_offset.empty();
- class_fixup_ref.empty();
- requested_ics.empty();
+ // set defaults
+ cur_class_minver = default_class_minver;
+ cur_class_majver = default_class_majver;
+
+ // reset constant pool state
+ cp.resetOutputIndexes();
+
+ // reset fixups
+ class_fixup_type.empty();
+ class_fixup_offset.empty();
+ class_fixup_ref.empty();
+ requested_ics.empty();
}
cpindex *constant_pool::getKQIndex()
{
- char ch = '?';
- if (u->cur_descr != nullptr)
- {
- entry *type = u->cur_descr->descrType();
- ch = type->value.b.ptr[0];
- }
- byte tag = CONSTANT_Integer;
- switch (ch)
- {
- case 'L':
- tag = CONSTANT_String;
- break;
- case 'I':
- tag = CONSTANT_Integer;
- break;
- case 'J':
- tag = CONSTANT_Long;
- break;
- case 'F':
- tag = CONSTANT_Float;
- break;
- case 'D':
- tag = CONSTANT_Double;
- break;
- case 'B':
- case 'S':
- case 'C':
- case 'Z':
- tag = CONSTANT_Integer;
- break;
- default:
- unpack_abort("bad KQ reference");
- break;
- }
- return getIndex(tag);
+ char ch = '?';
+ if (u->cur_descr != nullptr)
+ {
+ entry *type = u->cur_descr->descrType();
+ ch = type->value.b.ptr[0];
+ }
+ byte tag = CONSTANT_Integer;
+ switch (ch)
+ {
+ case 'L':
+ tag = CONSTANT_String;
+ break;
+ case 'I':
+ tag = CONSTANT_Integer;
+ break;
+ case 'J':
+ tag = CONSTANT_Long;
+ break;
+ case 'F':
+ tag = CONSTANT_Float;
+ break;
+ case 'D':
+ tag = CONSTANT_Double;
+ break;
+ case 'B':
+ case 'S':
+ case 'C':
+ case 'Z':
+ tag = CONSTANT_Integer;
+ break;
+ default:
+ unpack_abort("bad KQ reference");
+ break;
+ }
+ return getIndex(tag);
}
uint32_t unpacker::to_bci(uint32_t bii)
{
- uint32_t len = bcimap.length();
- uint32_t *map = (uint32_t *)bcimap.base();
- assert(len > 0); // must be initialized before using to_bci
- if (bii < len)
- return map[bii];
- // Else it's a fractional or out-of-range BCI.
- uint32_t key = bii - len;
- for (int i = len;; i--)
- {
- if (map[i - 1] - (i - 1) <= key)
- break;
- else
- --bii;
- }
- return bii;
+ uint32_t len = bcimap.length();
+ uint32_t *map = (uint32_t *)bcimap.base();
+ assert(len > 0); // must be initialized before using to_bci
+ if (bii < len)
+ return map[bii];
+ // Else it's a fractional or out-of-range BCI.
+ uint32_t key = bii - len;
+ for (int i = len;; i--)
+ {
+ if (map[i - 1] - (i - 1) <= key)
+ break;
+ else
+ --bii;
+ }
+ return bii;
}
void unpacker::put_stackmap_type()
{
- int tag = code_StackMapTable_T.getByte();
- putu1(tag);
- switch (tag)
- {
- case 7: // (7) [RCH]
- putref(code_StackMapTable_RC.getRef());
- break;
- case 8: // (8) [PH]
- putu2(to_bci(code_StackMapTable_P.getInt()));
- break;
- }
+ int tag = code_StackMapTable_T.getByte();
+ putu1(tag);
+ switch (tag)
+ {
+ case 7: // (7) [RCH]
+ putref(code_StackMapTable_RC.getRef());
+ break;
+ case 8: // (8) [PH]
+ putu2(to_bci(code_StackMapTable_P.getInt()));
+ break;
+ }
}
// Functions for writing code.
void unpacker::put_label(int curIP, int size)
{
- code_fixup_type.addByte(size);
- code_fixup_offset.add((int)put_empty(size));
- code_fixup_source.add(curIP);
+ code_fixup_type.addByte(size);
+ code_fixup_offset.add((int)put_empty(size));
+ code_fixup_source.add(curIP);
}
inline // called exactly once => inline
- void
+ void
unpacker::write_bc_ops()
{
- bcimap.empty();
- code_fixup_type.empty();
- code_fixup_offset.empty();
- code_fixup_source.empty();
-
- band *bc_which;
-
- byte *opptr = bc_codes.curRP();
- // No need for oplimit, since the codes are pre-counted.
-
- size_t codeBase = wpoffset();
-
- bool isAload; // copy-out result
- int origBC;
-
- entry *thisClass = cur_class;
- entry *superClass = cur_super;
- entry *newClass = nullptr; // class of last _new opcode
-
- // overwrite any prior index on these bands; it changes w/ current class:
- bc_thisfield.setIndex(cp.getFieldIndex(thisClass));
- bc_thismethod.setIndex(cp.getMethodIndex(thisClass));
- if (superClass != nullptr)
- {
- bc_superfield.setIndex(cp.getFieldIndex(superClass));
- bc_supermethod.setIndex(cp.getMethodIndex(superClass));
- }
-
- for (int curIP = 0;; curIP++)
- {
- int curPC = (int)(wpoffset() - codeBase);
- bcimap.add(curPC);
- ensure_put_space(10); // covers most instrs w/o further bounds check
- int bc = *opptr++ & 0xFF;
-
- putu1_fast(bc);
- // Note: See '--wp' below for pseudo-bytecodes like bc_end_marker.
-
- bool isWide = false;
- if (bc == bc_wide)
- {
- bc = *opptr++ & 0xFF;
- putu1_fast(bc);
- isWide = true;
- }
- switch (bc)
- {
- case bc_end_marker:
- --wp; // not really part of the code
- assert(opptr <= bc_codes.maxRP());
- bc_codes.curRP() = opptr; // advance over this in bc_codes
- goto doneScanningMethod;
- case bc_tableswitch: // apc: (df, lo, hi, (hi-lo+1)*(label))
- case bc_lookupswitch: // apc: (df, nc, nc*(case, label))
- {
- int caseCount = bc_case_count.getInt();
- while (((wpoffset() - codeBase) % 4) != 0)
- putu1_fast(0);
- ensure_put_space(30 + caseCount * 8);
- put_label(curIP, 4); // int df = bc_label.getInt();
- if (bc == bc_tableswitch)
- {
- int lo = bc_case_value.getInt();
- int hi = lo + caseCount - 1;
- putu4(lo);
- putu4(hi);
- for (int j = 0; j < caseCount; j++)
- {
- put_label(curIP, 4); // int lVal = bc_label.getInt();
- // int cVal = lo + j;
- }
- }
- else
- {
- putu4(caseCount);
- for (int j = 0; j < caseCount; j++)
- {
- int cVal = bc_case_value.getInt();
- putu4(cVal);
- put_label(curIP, 4); // int lVal = bc_label.getInt();
- }
- }
- assert((int)to_bci(curIP) == curPC);
- continue;
- }
- case bc_iinc:
- {
- int local = bc_local.getInt();
- int delta = (isWide ? bc_short : bc_byte).getInt();
- if (isWide)
- {
- putu2(local);
- putu2(delta);
- }
- else
- {
- putu1_fast(local);
- putu1_fast(delta);
- }
- continue;
- }
- case bc_sipush:
- {
- int val = bc_short.getInt();
- putu2(val);
- continue;
- }
- case bc_bipush:
- case bc_newarray:
- {
- int val = bc_byte.getByte();
- putu1_fast(val);
- continue;
- }
- case bc_ref_escape:
- {
- // Note that insnMap has one entry for this.
- --wp; // not really part of the code
- int size = bc_escrefsize.getInt();
- entry *ref = bc_escref.getRefN();
- switch (size)
- {
- case 1:
- putu1ref(ref);
- break;
- case 2:
- putref(ref);
- break;
- default:
- assert(false);
- }
- continue;
- }
- case bc_byte_escape:
- {
- // Note that insnMap has one entry for all these bytes.
- --wp; // not really part of the code
- int size = bc_escsize.getInt();
- ensure_put_space(size);
- for (int j = 0; j < size; j++)
- putu1_fast(bc_escbyte.getByte());
- continue;
- }
- default:
- if (is_invoke_init_op(bc))
- {
- origBC = bc_invokespecial;
- entry *classRef;
- switch (bc - _invokeinit_op)
- {
- case _invokeinit_self_option:
- classRef = thisClass;
- break;
- case _invokeinit_super_option:
- classRef = superClass;
- break;
- default:
- assert(bc == _invokeinit_op + _invokeinit_new_option);
- case _invokeinit_new_option:
- classRef = newClass;
- break;
- }
- wp[-1] = origBC; // overwrite with origBC
- int coding = bc_initref.getInt();
- // Find the nth overloading of <init> in classRef.
- entry *ref = nullptr;
- cpindex *ix = (classRef == nullptr) ? nullptr : cp.getMethodIndex(classRef);
- for (int j = 0, which_init = 0;; j++)
- {
- ref = (ix == nullptr) ? nullptr : ix->get(j);
- if (ref == nullptr)
- break; // oops, bad input
- assert(ref->tag == CONSTANT_Methodref);
- if (ref->memberDescr()->descrName() == cp.sym[constant_pool::s_lt_init_gt])
- {
- if (which_init++ == coding)
- break;
- }
- }
- putref(ref);
- continue;
- }
- bc_which = ref_band_for_self_op(bc, isAload, origBC);
- if (bc_which != nullptr)
- {
- if (!isAload)
- {
- wp[-1] = origBC; // overwrite with origBC
- }
- else
- {
- wp[-1] = bc_aload_0; // overwrite with _aload_0
- // Note: insnMap keeps the _aload_0 separate.
- bcimap.add(++curPC);
- ++curIP;
- putu1_fast(origBC);
- }
- entry *ref = bc_which->getRef();
- putref(ref);
- continue;
- }
- if (is_branch_op(bc))
- {
- // int lVal = bc_label.getInt();
- if (bc < bc_goto_w)
- {
- put_label(curIP, 2); // putu2(lVal & 0xFFFF);
- }
- else
- {
- assert(bc <= bc_jsr_w);
- put_label(curIP, 4); // putu4(lVal);
- }
- assert((int)to_bci(curIP) == curPC);
- continue;
- }
- bc_which = ref_band_for_op(bc);
- if (bc_which != nullptr)
- {
- entry *ref = bc_which->getRefCommon(bc_which->ix, bc_which->nullOK);
- if (ref == nullptr && bc_which == &bc_classref)
- {
- // Shorthand for class self-references.
- ref = thisClass;
- }
- origBC = bc;
- switch (bc)
- {
- case bc_ildc:
- case bc_cldc:
- case bc_fldc:
- case bc_aldc:
- origBC = bc_ldc;
- break;
- case bc_ildc_w:
- case bc_cldc_w:
- case bc_fldc_w:
- case bc_aldc_w:
- origBC = bc_ldc_w;
- break;
- case bc_lldc2_w:
- case bc_dldc2_w:
- origBC = bc_ldc2_w;
- break;
- case bc_new:
- newClass = ref;
- break;
- }
- wp[-1] = origBC; // overwrite with origBC
- if (origBC == bc_ldc)
- {
- putu1ref(ref);
- }
- else
- {
- putref(ref);
- }
- if (origBC == bc_multianewarray)
- {
- // Copy the trailing byte also.
- int val = bc_byte.getByte();
- putu1_fast(val);
- }
- else if (origBC == bc_invokeinterface)
- {
- int argSize = ref->memberDescr()->descrType()->typeSize();
- putu1_fast(1 + argSize);
- putu1_fast(0);
- }
- continue;
- }
- if (is_local_slot_op(bc))
- {
- int local = bc_local.getInt();
- if (isWide)
- {
- putu2(local);
- if (bc == bc_iinc)
- {
- int iVal = bc_short.getInt();
- putu2(iVal);
- }
- }
- else
- {
- putu1_fast(local);
- if (bc == bc_iinc)
- {
- int iVal = bc_byte.getByte();
- putu1_fast(iVal);
- }
- }
- continue;
- }
- // Random bytecode. Just copy it.
- assert(bc < bc_bytecode_limit);
- }
- }
+ bcimap.empty();
+ code_fixup_type.empty();
+ code_fixup_offset.empty();
+ code_fixup_source.empty();
+
+ band *bc_which;
+
+ byte *opptr = bc_codes.curRP();
+ // No need for oplimit, since the codes are pre-counted.
+
+ size_t codeBase = wpoffset();
+
+ bool isAload; // copy-out result
+ int origBC;
+
+ entry *thisClass = cur_class;
+ entry *superClass = cur_super;
+ entry *newClass = nullptr; // class of last _new opcode
+
+ // overwrite any prior index on these bands; it changes w/ current class:
+ bc_thisfield.setIndex(cp.getFieldIndex(thisClass));
+ bc_thismethod.setIndex(cp.getMethodIndex(thisClass));
+ if (superClass != nullptr)
+ {
+ bc_superfield.setIndex(cp.getFieldIndex(superClass));
+ bc_supermethod.setIndex(cp.getMethodIndex(superClass));
+ }
+
+ for (int curIP = 0;; curIP++)
+ {
+ int curPC = (int)(wpoffset() - codeBase);
+ bcimap.add(curPC);
+ ensure_put_space(10); // covers most instrs w/o further bounds check
+ int bc = *opptr++ & 0xFF;
+
+ putu1_fast(bc);
+ // Note: See '--wp' below for pseudo-bytecodes like bc_end_marker.
+
+ bool isWide = false;
+ if (bc == bc_wide)
+ {
+ bc = *opptr++ & 0xFF;
+ putu1_fast(bc);
+ isWide = true;
+ }
+ switch (bc)
+ {
+ case bc_end_marker:
+ --wp; // not really part of the code
+ assert(opptr <= bc_codes.maxRP());
+ bc_codes.curRP() = opptr; // advance over this in bc_codes
+ goto doneScanningMethod;
+ case bc_tableswitch: // apc: (df, lo, hi, (hi-lo+1)*(label))
+ case bc_lookupswitch: // apc: (df, nc, nc*(case, label))
+ {
+ int caseCount = bc_case_count.getInt();
+ while (((wpoffset() - codeBase) % 4) != 0)
+ putu1_fast(0);
+ ensure_put_space(30 + caseCount * 8);
+ put_label(curIP, 4); // int df = bc_label.getInt();
+ if (bc == bc_tableswitch)
+ {
+ int lo = bc_case_value.getInt();
+ int hi = lo + caseCount - 1;
+ putu4(lo);
+ putu4(hi);
+ for (int j = 0; j < caseCount; j++)
+ {
+ put_label(curIP, 4); // int lVal = bc_label.getInt();
+ // int cVal = lo + j;
+ }
+ }
+ else
+ {
+ putu4(caseCount);
+ for (int j = 0; j < caseCount; j++)
+ {
+ int cVal = bc_case_value.getInt();
+ putu4(cVal);
+ put_label(curIP, 4); // int lVal = bc_label.getInt();
+ }
+ }
+ assert((int)to_bci(curIP) == curPC);
+ continue;
+ }
+ case bc_iinc:
+ {
+ int local = bc_local.getInt();
+ int delta = (isWide ? bc_short : bc_byte).getInt();
+ if (isWide)
+ {
+ putu2(local);
+ putu2(delta);
+ }
+ else
+ {
+ putu1_fast(local);
+ putu1_fast(delta);
+ }
+ continue;
+ }
+ case bc_sipush:
+ {
+ int val = bc_short.getInt();
+ putu2(val);
+ continue;
+ }
+ case bc_bipush:
+ case bc_newarray:
+ {
+ int val = bc_byte.getByte();
+ putu1_fast(val);
+ continue;
+ }
+ case bc_ref_escape:
+ {
+ // Note that insnMap has one entry for this.
+ --wp; // not really part of the code
+ int size = bc_escrefsize.getInt();
+ entry *ref = bc_escref.getRefN();
+ switch (size)
+ {
+ case 1:
+ putu1ref(ref);
+ break;
+ case 2:
+ putref(ref);
+ break;
+ default:
+ assert(false);
+ }
+ continue;
+ }
+ case bc_byte_escape:
+ {
+ // Note that insnMap has one entry for all these bytes.
+ --wp; // not really part of the code
+ int size = bc_escsize.getInt();
+ ensure_put_space(size);
+ for (int j = 0; j < size; j++)
+ putu1_fast(bc_escbyte.getByte());
+ continue;
+ }
+ default:
+ if (is_invoke_init_op(bc))
+ {
+ origBC = bc_invokespecial;
+ entry *classRef;
+ switch (bc - _invokeinit_op)
+ {
+ case _invokeinit_self_option:
+ classRef = thisClass;
+ break;
+ case _invokeinit_super_option:
+ classRef = superClass;
+ break;
+ default:
+ assert(bc == _invokeinit_op + _invokeinit_new_option);
+ case _invokeinit_new_option:
+ classRef = newClass;
+ break;
+ }
+ wp[-1] = origBC; // overwrite with origBC
+ int coding = bc_initref.getInt();
+ // Find the nth overloading of <init> in classRef.
+ entry *ref = nullptr;
+ cpindex *ix = (classRef == nullptr) ? nullptr : cp.getMethodIndex(classRef);
+ for (int j = 0, which_init = 0;; j++)
+ {
+ ref = (ix == nullptr) ? nullptr : ix->get(j);
+ if (ref == nullptr)
+ break; // oops, bad input
+ assert(ref->tag == CONSTANT_Methodref);
+ if (ref->memberDescr()->descrName() == cp.sym[constant_pool::s_lt_init_gt])
+ {
+ if (which_init++ == coding)
+ break;
+ }
+ }
+ putref(ref);
+ continue;
+ }
+ bc_which = ref_band_for_self_op(bc, isAload, origBC);
+ if (bc_which != nullptr)
+ {
+ if (!isAload)
+ {
+ wp[-1] = origBC; // overwrite with origBC
+ }
+ else
+ {
+ wp[-1] = bc_aload_0; // overwrite with _aload_0
+ // Note: insnMap keeps the _aload_0 separate.
+ bcimap.add(++curPC);
+ ++curIP;
+ putu1_fast(origBC);
+ }
+ entry *ref = bc_which->getRef();
+ putref(ref);
+ continue;
+ }
+ if (is_branch_op(bc))
+ {
+ // int lVal = bc_label.getInt();
+ if (bc < bc_goto_w)
+ {
+ put_label(curIP, 2); // putu2(lVal & 0xFFFF);
+ }
+ else
+ {
+ assert(bc <= bc_jsr_w);
+ put_label(curIP, 4); // putu4(lVal);
+ }
+ assert((int)to_bci(curIP) == curPC);
+ continue;
+ }
+ bc_which = ref_band_for_op(bc);
+ if (bc_which != nullptr)
+ {
+ entry *ref = bc_which->getRefCommon(bc_which->ix, bc_which->nullOK);
+ if (ref == nullptr && bc_which == &bc_classref)
+ {
+ // Shorthand for class self-references.
+ ref = thisClass;
+ }
+ origBC = bc;
+ switch (bc)
+ {
+ case bc_ildc:
+ case bc_cldc:
+ case bc_fldc:
+ case bc_aldc:
+ origBC = bc_ldc;
+ break;
+ case bc_ildc_w:
+ case bc_cldc_w:
+ case bc_fldc_w:
+ case bc_aldc_w:
+ origBC = bc_ldc_w;
+ break;
+ case bc_lldc2_w:
+ case bc_dldc2_w:
+ origBC = bc_ldc2_w;
+ break;
+ case bc_new:
+ newClass = ref;
+ break;
+ }
+ wp[-1] = origBC; // overwrite with origBC
+ if (origBC == bc_ldc)
+ {
+ putu1ref(ref);
+ }
+ else
+ {
+ putref(ref);
+ }
+ if (origBC == bc_multianewarray)
+ {
+ // Copy the trailing byte also.
+ int val = bc_byte.getByte();
+ putu1_fast(val);
+ }
+ else if (origBC == bc_invokeinterface)
+ {
+ int argSize = ref->memberDescr()->descrType()->typeSize();
+ putu1_fast(1 + argSize);
+ putu1_fast(0);
+ }
+ continue;
+ }
+ if (is_local_slot_op(bc))
+ {
+ int local = bc_local.getInt();
+ if (isWide)
+ {
+ putu2(local);
+ if (bc == bc_iinc)
+ {
+ int iVal = bc_short.getInt();
+ putu2(iVal);
+ }
+ }
+ else
+ {
+ putu1_fast(local);
+ if (bc == bc_iinc)
+ {
+ int iVal = bc_byte.getByte();
+ putu1_fast(iVal);
+ }
+ }
+ continue;
+ }
+ // Random bytecode. Just copy it.
+ assert(bc < bc_bytecode_limit);
+ }
+ }
doneScanningMethod:
{
}
- // bcimap.add(curPC); // PC limit is already also in map, from bc_end_marker
-
- // Armed with a bcimap, we can now fix up all the labels.
- for (int i = 0; i < (int)code_fixup_type.size(); i++)
- {
- int type = code_fixup_type.getByte(i);
- byte *bp = wp_at(code_fixup_offset.get(i));
- int curIP = code_fixup_source.get(i);
- int destIP = curIP + bc_label.getInt();
- int span = to_bci(destIP) - to_bci(curIP);
- switch (type)
- {
- case 2:
- putu2_at(bp, (ushort)span);
- break;
- case 4:
- putu4_at(bp, span);
- break;
- default:
- assert(false);
- }
- }
+ // bcimap.add(curPC); // PC limit is already also in map, from bc_end_marker
+
+ // Armed with a bcimap, we can now fix up all the labels.
+ for (int i = 0; i < (int)code_fixup_type.size(); i++)
+ {
+ int type = code_fixup_type.getByte(i);
+ byte *bp = wp_at(code_fixup_offset.get(i));
+ int curIP = code_fixup_source.get(i);
+ int destIP = curIP + bc_label.getInt();
+ int span = to_bci(destIP) - to_bci(curIP);
+ switch (type)
+ {
+ case 2:
+ putu2_at(bp, (ushort)span);
+ break;
+ case 4:
+ putu4_at(bp, span);
+ break;
+ default:
+ assert(false);
+ }
+ }
}
inline // called exactly once => inline
- void
+ void
unpacker::write_code()
{
- int j;
-
- int max_stack, max_locals, handler_count, cflags;
- get_code_header(max_stack, max_locals, handler_count, cflags);
-
- if (max_stack < 0)
- max_stack = code_max_stack.getInt();
- if (max_locals < 0)
- max_locals = code_max_na_locals.getInt();
- if (handler_count < 0)
- handler_count = code_handler_count.getInt();
-
- int siglen = cur_descr->descrType()->typeSize();
- if ((cur_descr_flags & ACC_STATIC) == 0)
- siglen++;
- max_locals += siglen;
-
- putu2(max_stack);
- putu2(max_locals);
- size_t bcbase = put_empty(4);
-
- // Write the bytecodes themselves.
- write_bc_ops();
-
- byte *bcbasewp = wp_at(bcbase);
- putu4_at(bcbasewp, (int)(wp - (bcbasewp + 4))); // size of code attr
-
- putu2(handler_count);
- for (j = 0; j < handler_count; j++)
- {
- int bii = code_handler_start_P.getInt();
- putu2(to_bci(bii));
- bii += code_handler_end_PO.getInt();
- putu2(to_bci(bii));
- bii += code_handler_catch_PO.getInt();
- putu2(to_bci(bii));
- putref(code_handler_class_RCN.getRefN());
- }
-
- uint64_t indexBits = cflags;
- if (cflags < 0)
- {
- bool haveLongFlags = attr_defs[ATTR_CONTEXT_CODE].haveLongFlags();
- indexBits = code_flags_hi.getLong(code_flags_lo, haveLongFlags);
- }
- write_attrs(ATTR_CONTEXT_CODE, indexBits);
+ int j;
+
+ int max_stack, max_locals, handler_count, cflags;
+ get_code_header(max_stack, max_locals, handler_count, cflags);
+
+ if (max_stack < 0)
+ max_stack = code_max_stack.getInt();
+ if (max_locals < 0)
+ max_locals = code_max_na_locals.getInt();
+ if (handler_count < 0)
+ handler_count = code_handler_count.getInt();
+
+ int siglen = cur_descr->descrType()->typeSize();
+ if ((cur_descr_flags & ACC_STATIC) == 0)
+ siglen++;
+ max_locals += siglen;
+
+ putu2(max_stack);
+ putu2(max_locals);
+ size_t bcbase = put_empty(4);
+
+ // Write the bytecodes themselves.
+ write_bc_ops();
+
+ byte *bcbasewp = wp_at(bcbase);
+ putu4_at(bcbasewp, (int)(wp - (bcbasewp + 4))); // size of code attr
+
+ putu2(handler_count);
+ for (j = 0; j < handler_count; j++)
+ {
+ int bii = code_handler_start_P.getInt();
+ putu2(to_bci(bii));
+ bii += code_handler_end_PO.getInt();
+ putu2(to_bci(bii));
+ bii += code_handler_catch_PO.getInt();
+ putu2(to_bci(bii));
+ putref(code_handler_class_RCN.getRefN());
+ }
+
+ uint64_t indexBits = cflags;
+ if (cflags < 0)
+ {
+ bool haveLongFlags = attr_defs[ATTR_CONTEXT_CODE].haveLongFlags();
+ indexBits = code_flags_hi.getLong(code_flags_lo, haveLongFlags);
+ }
+ write_attrs(ATTR_CONTEXT_CODE, indexBits);
}
int unpacker::write_attrs(int attrc, uint64_t indexBits)
{
- if (indexBits == 0)
- {
- // Quick short-circuit.
- putu2(0);
- return 0;
- }
-
- attr_definitions &ad = attr_defs[attrc];
-
- int i, j, j2, idx, count;
-
- int oiCount = 0;
- if (ad.isPredefined(X_ATTR_OVERFLOW) && (indexBits & ((uint64_t)1 << X_ATTR_OVERFLOW)) != 0)
- {
- indexBits -= ((uint64_t)1 << X_ATTR_OVERFLOW);
- oiCount = ad.xxx_attr_count().getInt();
- }
-
- int bitIndexes[X_ATTR_LIMIT_FLAGS_HI];
- int biCount = 0;
-
- // Fill bitIndexes with index bits, in order.
- for (idx = 0; indexBits != 0; idx++, indexBits >>= 1)
- {
- if ((indexBits & 1) != 0)
- bitIndexes[biCount++] = idx;
- }
- assert(biCount <= (int)lengthof(bitIndexes));
-
- // Write a provisional attribute count, perhaps to be corrected later.
- int naOffset = (int)wpoffset();
- int na0 = biCount + oiCount;
- putu2(na0);
-
- int na = 0;
- for (i = 0; i < na0; i++)
- {
- if (i < biCount)
- idx = bitIndexes[i];
- else
- idx = ad.xxx_attr_indexes().getInt();
- assert(ad.isIndex(idx));
- entry *aname = nullptr;
- entry *ref; // scratch
- size_t abase = put_empty(2 + 4);
- if (idx < (int)ad.flag_limit && ad.isPredefined(idx))
- {
- // Switch on the attrc and idx simultaneously.
- switch (ADH_BYTE(attrc, idx))
- {
-
- case ADH_BYTE(ATTR_CONTEXT_CLASS, X_ATTR_OVERFLOW) :
- case ADH_BYTE(ATTR_CONTEXT_FIELD, X_ATTR_OVERFLOW) :
- case ADH_BYTE(ATTR_CONTEXT_METHOD, X_ATTR_OVERFLOW) :
- case ADH_BYTE(ATTR_CONTEXT_CODE, X_ATTR_OVERFLOW) :
- // no attribute at all, so back up on this one
- wp = wp_at(abase);
- continue;
-
- case ADH_BYTE(ATTR_CONTEXT_CLASS, CLASS_ATTR_ClassFile_version) :
- cur_class_minver = class_ClassFile_version_minor_H.getInt();
- cur_class_majver = class_ClassFile_version_major_H.getInt();
- // back up; not a real attribute
- wp = wp_at(abase);
- continue;
-
- case ADH_BYTE(ATTR_CONTEXT_CLASS, CLASS_ATTR_InnerClasses) :
- // note the existence of this attr, but save for later
- if (cur_class_has_local_ics)
- unpack_abort("too many InnerClasses attrs");
- cur_class_has_local_ics = true;
- wp = wp_at(abase);
- continue;
-
- case ADH_BYTE(ATTR_CONTEXT_CLASS, CLASS_ATTR_SourceFile) :
- aname = cp.sym[constant_pool::s_SourceFile];
- ref = class_SourceFile_RUN.getRefN();
- if (ref == nullptr)
- {
- bytes &n = cur_class->ref(0)->value.b;
- // parse n = (<pkg>/)*<outer>?($<id>)*
- int pkglen = lastIndexOf(SLASH_MIN, SLASH_MAX, n, (int)n.len) + 1;
- bytes prefix = n.slice(pkglen, n.len);
- for (;;)
- {
- // Work backwards, finding all '$', '#', etc.
- int dollar =
- lastIndexOf(DOLLAR_MIN, DOLLAR_MAX, prefix, (int)prefix.len);
- if (dollar < 0)
- break;
- prefix = prefix.slice(0, dollar);
- }
- const char *suffix = ".java";
- int len = (int)(prefix.len + strlen(suffix));
- bytes name;
- name.set(T_NEW(byte, add_size(len, 1)), len);
- name.strcat(prefix).strcat(suffix);
- ref = cp.ensureUtf8(name);
- }
- putref(ref);
- break;
-
- case ADH_BYTE(ATTR_CONTEXT_CLASS, CLASS_ATTR_EnclosingMethod) :
- aname = cp.sym[constant_pool::s_EnclosingMethod];
- putref(class_EnclosingMethod_RC.getRefN());
- putref(class_EnclosingMethod_RDN.getRefN());
- break;
-
- case ADH_BYTE(ATTR_CONTEXT_FIELD, FIELD_ATTR_ConstantValue) :
- aname = cp.sym[constant_pool::s_ConstantValue];
- putref(field_ConstantValue_KQ.getRefUsing(cp.getKQIndex()));
- break;
-
- case ADH_BYTE(ATTR_CONTEXT_METHOD, METHOD_ATTR_Code) :
- aname = cp.sym[constant_pool::s_Code];
- write_code();
- break;
-
- case ADH_BYTE(ATTR_CONTEXT_METHOD, METHOD_ATTR_Exceptions) :
- aname = cp.sym[constant_pool::s_Exceptions];
- putu2(count = method_Exceptions_N.getInt());
- for (j = 0; j < count; j++)
- {
- putref(method_Exceptions_RC.getRefN());
- }
- break;
-
- case ADH_BYTE(ATTR_CONTEXT_CODE, CODE_ATTR_StackMapTable) :
- aname = cp.sym[constant_pool::s_StackMapTable];
- // (keep this code aligned with its brother in unpacker::read_attrs)
- putu2(count = code_StackMapTable_N.getInt());
- for (j = 0; j < count; j++)
- {
- int tag = code_StackMapTable_frame_T.getByte();
- putu1(tag);
- if (tag <= 127)
- {
- // (64-127) [(2)]
- if (tag >= 64)
- put_stackmap_type();
- }
- else if (tag <= 251)
- {
- // (247) [(1)(2)]
- // (248-251) [(1)]
- if (tag >= 247)
- putu2(code_StackMapTable_offset.getInt());
- if (tag == 247)
- put_stackmap_type();
- }
- else if (tag <= 254)
- {
- // (252) [(1)(2)]
- // (253) [(1)(2)(2)]
- // (254) [(1)(2)(2)(2)]
- putu2(code_StackMapTable_offset.getInt());
- for (int k = (tag - 251); k > 0; k--)
- {
- put_stackmap_type();
- }
- }
- else
- {
- // (255) [(1)NH[(2)]NH[(2)]]
- putu2(code_StackMapTable_offset.getInt());
- putu2(j2 = code_StackMapTable_local_N.getInt());
- while (j2-- > 0)
- put_stackmap_type();
- putu2(j2 = code_StackMapTable_stack_N.getInt());
- while (j2-- > 0)
- put_stackmap_type();
- }
- }
- break;
-
- case ADH_BYTE(ATTR_CONTEXT_CODE, CODE_ATTR_LineNumberTable) :
- aname = cp.sym[constant_pool::s_LineNumberTable];
- putu2(count = code_LineNumberTable_N.getInt());
- for (j = 0; j < count; j++)
- {
- putu2(to_bci(code_LineNumberTable_bci_P.getInt()));
- putu2(code_LineNumberTable_line.getInt());
- }
- break;
-
- case ADH_BYTE(ATTR_CONTEXT_CODE, CODE_ATTR_LocalVariableTable) :
- aname = cp.sym[constant_pool::s_LocalVariableTable];
- putu2(count = code_LocalVariableTable_N.getInt());
- for (j = 0; j < count; j++)
- {
- int bii = code_LocalVariableTable_bci_P.getInt();
- int bci = to_bci(bii);
- putu2(bci);
- bii += code_LocalVariableTable_span_O.getInt();
- putu2(to_bci(bii) - bci);
- putref(code_LocalVariableTable_name_RU.getRefN());
- putref(code_LocalVariableTable_type_RS.getRefN());
- putu2(code_LocalVariableTable_slot.getInt());
- }
- break;
-
- case ADH_BYTE(ATTR_CONTEXT_CODE, CODE_ATTR_LocalVariableTypeTable) :
- aname = cp.sym[constant_pool::s_LocalVariableTypeTable];
- putu2(count = code_LocalVariableTypeTable_N.getInt());
- for (j = 0; j < count; j++)
- {
- int bii = code_LocalVariableTypeTable_bci_P.getInt();
- int bci = to_bci(bii);
- putu2(bci);
- bii += code_LocalVariableTypeTable_span_O.getInt();
- putu2(to_bci(bii) - bci);
- putref(code_LocalVariableTypeTable_name_RU.getRefN());
- putref(code_LocalVariableTypeTable_type_RS.getRefN());
- putu2(code_LocalVariableTypeTable_slot.getInt());
- }
- break;
-
- case ADH_BYTE(ATTR_CONTEXT_CLASS, X_ATTR_Signature) :
- aname = cp.sym[constant_pool::s_Signature];
- putref(class_Signature_RS.getRefN());
- break;
-
- case ADH_BYTE(ATTR_CONTEXT_FIELD, X_ATTR_Signature) :
- aname = cp.sym[constant_pool::s_Signature];
- putref(field_Signature_RS.getRefN());
- break;
-
- case ADH_BYTE(ATTR_CONTEXT_METHOD, X_ATTR_Signature) :
- aname = cp.sym[constant_pool::s_Signature];
- putref(method_Signature_RS.getRefN());
- break;
-
- case ADH_BYTE(ATTR_CONTEXT_CLASS, X_ATTR_Deprecated) :
- case ADH_BYTE(ATTR_CONTEXT_FIELD, X_ATTR_Deprecated) :
- case ADH_BYTE(ATTR_CONTEXT_METHOD, X_ATTR_Deprecated) :
- aname = cp.sym[constant_pool::s_Deprecated];
- // no data
- break;
- }
- }
-
- if (aname == nullptr)
- {
- // Unparse a compressor-defined attribute.
- layout_definition *lo = ad.getLayout(idx);
- if (lo == nullptr)
- {
- unpack_abort("bad layout index");
- break;
- }
- assert((int)lo->idx == idx);
- aname = lo->nameEntry;
- if (aname == nullptr)
- {
- bytes nameb;
- nameb.set(lo->name);
- aname = cp.ensureUtf8(nameb);
- // Cache the name entry for next time.
- lo->nameEntry = aname;
- }
- // Execute all the layout elements.
- band **bands = lo->bands();
- if (lo->hasCallables())
- {
- band &cble = *bands[0];
- assert(cble.le_kind == EK_CBLE);
- bands = cble.le_body;
- }
- putlayout(bands);
- }
-
- if (aname == nullptr)
- unpack_abort("bad attribute index");
-
- byte *wp1 = wp;
- wp = wp_at(abase);
-
- // DTRT if this attr is on the strip-list.
- // (Note that we emptied the data out of the band first.)
- if (ad.strip_names.contains(aname))
- {
- continue;
- }
-
- // patch the name and length
- putref(aname);
- putu4((int)(wp1 - (wp + 4))); // put the attr size
- wp = wp1;
- na++; // count the attrs actually written
- }
-
- if (na != na0)
- // Refresh changed count.
- putu2_at(wp_at(naOffset), na);
- return na;
+ if (indexBits == 0)
+ {
+ // Quick short-circuit.
+ putu2(0);
+ return 0;
+ }
+
+ attr_definitions &ad = attr_defs[attrc];
+
+ int i, j, j2, idx, count;
+
+ int oiCount = 0;
+ if (ad.isPredefined(X_ATTR_OVERFLOW) && (indexBits & ((uint64_t)1 << X_ATTR_OVERFLOW)) != 0)
+ {
+ indexBits -= ((uint64_t)1 << X_ATTR_OVERFLOW);
+ oiCount = ad.xxx_attr_count().getInt();
+ }
+
+ int bitIndexes[X_ATTR_LIMIT_FLAGS_HI];
+ int biCount = 0;
+
+ // Fill bitIndexes with index bits, in order.
+ for (idx = 0; indexBits != 0; idx++, indexBits >>= 1)
+ {
+ if ((indexBits & 1) != 0)
+ bitIndexes[biCount++] = idx;
+ }
+ assert(biCount <= (int)lengthof(bitIndexes));
+
+ // Write a provisional attribute count, perhaps to be corrected later.
+ int naOffset = (int)wpoffset();
+ int na0 = biCount + oiCount;
+ putu2(na0);
+
+ int na = 0;
+ for (i = 0; i < na0; i++)
+ {
+ if (i < biCount)
+ idx = bitIndexes[i];
+ else
+ idx = ad.xxx_attr_indexes().getInt();
+ assert(ad.isIndex(idx));
+ entry *aname = nullptr;
+ entry *ref; // scratch
+ size_t abase = put_empty(2 + 4);
+ if (idx < (int)ad.flag_limit && ad.isPredefined(idx))
+ {
+ // Switch on the attrc and idx simultaneously.
+ switch (ADH_BYTE(attrc, idx))
+ {
+
+ case ADH_BYTE(ATTR_CONTEXT_CLASS, X_ATTR_OVERFLOW) :
+ case ADH_BYTE(ATTR_CONTEXT_FIELD, X_ATTR_OVERFLOW) :
+ case ADH_BYTE(ATTR_CONTEXT_METHOD, X_ATTR_OVERFLOW) :
+ case ADH_BYTE(ATTR_CONTEXT_CODE, X_ATTR_OVERFLOW) :
+ // no attribute at all, so back up on this one
+ wp = wp_at(abase);
+ continue;
+
+ case ADH_BYTE(ATTR_CONTEXT_CLASS, CLASS_ATTR_ClassFile_version) :
+ cur_class_minver = class_ClassFile_version_minor_H.getInt();
+ cur_class_majver = class_ClassFile_version_major_H.getInt();
+ // back up; not a real attribute
+ wp = wp_at(abase);
+ continue;
+
+ case ADH_BYTE(ATTR_CONTEXT_CLASS, CLASS_ATTR_InnerClasses) :
+ // note the existence of this attr, but save for later
+ if (cur_class_has_local_ics)
+ unpack_abort("too many InnerClasses attrs");
+ cur_class_has_local_ics = true;
+ wp = wp_at(abase);
+ continue;
+
+ case ADH_BYTE(ATTR_CONTEXT_CLASS, CLASS_ATTR_SourceFile) :
+ aname = cp.sym[constant_pool::s_SourceFile];
+ ref = class_SourceFile_RUN.getRefN();
+ if (ref == nullptr)
+ {
+ bytes &n = cur_class->ref(0)->value.b;
+ // parse n = (<pkg>/)*<outer>?($<id>)*
+ int pkglen = lastIndexOf(SLASH_MIN, SLASH_MAX, n, (int)n.len) + 1;
+ bytes prefix = n.slice(pkglen, n.len);
+ for (;;)
+ {
+ // Work backwards, finding all '$', '#', etc.
+ int dollar =
+ lastIndexOf(DOLLAR_MIN, DOLLAR_MAX, prefix, (int)prefix.len);
+ if (dollar < 0)
+ break;
+ prefix = prefix.slice(0, dollar);
+ }
+ const char *suffix = ".java";
+ int len = (int)(prefix.len + strlen(suffix));
+ bytes name;
+ name.set(T_NEW(byte, add_size(len, 1)), len);
+ name.strcat(prefix).strcat(suffix);
+ ref = cp.ensureUtf8(name);
+ }
+ putref(ref);
+ break;
+
+ case ADH_BYTE(ATTR_CONTEXT_CLASS, CLASS_ATTR_EnclosingMethod) :
+ aname = cp.sym[constant_pool::s_EnclosingMethod];
+ putref(class_EnclosingMethod_RC.getRefN());
+ putref(class_EnclosingMethod_RDN.getRefN());
+ break;
+
+ case ADH_BYTE(ATTR_CONTEXT_FIELD, FIELD_ATTR_ConstantValue) :
+ aname = cp.sym[constant_pool::s_ConstantValue];
+ putref(field_ConstantValue_KQ.getRefUsing(cp.getKQIndex()));
+ break;
+
+ case ADH_BYTE(ATTR_CONTEXT_METHOD, METHOD_ATTR_Code) :
+ aname = cp.sym[constant_pool::s_Code];
+ write_code();
+ break;
+
+ case ADH_BYTE(ATTR_CONTEXT_METHOD, METHOD_ATTR_Exceptions) :
+ aname = cp.sym[constant_pool::s_Exceptions];
+ putu2(count = method_Exceptions_N.getInt());
+ for (j = 0; j < count; j++)
+ {
+ putref(method_Exceptions_RC.getRefN());
+ }
+ break;
+
+ case ADH_BYTE(ATTR_CONTEXT_CODE, CODE_ATTR_StackMapTable) :
+ aname = cp.sym[constant_pool::s_StackMapTable];
+ // (keep this code aligned with its brother in unpacker::read_attrs)
+ putu2(count = code_StackMapTable_N.getInt());
+ for (j = 0; j < count; j++)
+ {
+ int tag = code_StackMapTable_frame_T.getByte();
+ putu1(tag);
+ if (tag <= 127)
+ {
+ // (64-127) [(2)]
+ if (tag >= 64)
+ put_stackmap_type();
+ }
+ else if (tag <= 251)
+ {
+ // (247) [(1)(2)]
+ // (248-251) [(1)]
+ if (tag >= 247)
+ putu2(code_StackMapTable_offset.getInt());
+ if (tag == 247)
+ put_stackmap_type();
+ }
+ else if (tag <= 254)
+ {
+ // (252) [(1)(2)]
+ // (253) [(1)(2)(2)]
+ // (254) [(1)(2)(2)(2)]
+ putu2(code_StackMapTable_offset.getInt());
+ for (int k = (tag - 251); k > 0; k--)
+ {
+ put_stackmap_type();
+ }
+ }
+ else
+ {
+ // (255) [(1)NH[(2)]NH[(2)]]
+ putu2(code_StackMapTable_offset.getInt());
+ putu2(j2 = code_StackMapTable_local_N.getInt());
+ while (j2-- > 0)
+ put_stackmap_type();
+ putu2(j2 = code_StackMapTable_stack_N.getInt());
+ while (j2-- > 0)
+ put_stackmap_type();
+ }
+ }
+ break;
+
+ case ADH_BYTE(ATTR_CONTEXT_CODE, CODE_ATTR_LineNumberTable) :
+ aname = cp.sym[constant_pool::s_LineNumberTable];
+ putu2(count = code_LineNumberTable_N.getInt());
+ for (j = 0; j < count; j++)
+ {
+ putu2(to_bci(code_LineNumberTable_bci_P.getInt()));
+ putu2(code_LineNumberTable_line.getInt());
+ }
+ break;
+
+ case ADH_BYTE(ATTR_CONTEXT_CODE, CODE_ATTR_LocalVariableTable) :
+ aname = cp.sym[constant_pool::s_LocalVariableTable];
+ putu2(count = code_LocalVariableTable_N.getInt());
+ for (j = 0; j < count; j++)
+ {
+ int bii = code_LocalVariableTable_bci_P.getInt();
+ int bci = to_bci(bii);
+ putu2(bci);
+ bii += code_LocalVariableTable_span_O.getInt();
+ putu2(to_bci(bii) - bci);
+ putref(code_LocalVariableTable_name_RU.getRefN());
+ putref(code_LocalVariableTable_type_RS.getRefN());
+ putu2(code_LocalVariableTable_slot.getInt());
+ }
+ break;
+
+ case ADH_BYTE(ATTR_CONTEXT_CODE, CODE_ATTR_LocalVariableTypeTable) :
+ aname = cp.sym[constant_pool::s_LocalVariableTypeTable];
+ putu2(count = code_LocalVariableTypeTable_N.getInt());
+ for (j = 0; j < count; j++)
+ {
+ int bii = code_LocalVariableTypeTable_bci_P.getInt();
+ int bci = to_bci(bii);
+ putu2(bci);
+ bii += code_LocalVariableTypeTable_span_O.getInt();
+ putu2(to_bci(bii) - bci);
+ putref(code_LocalVariableTypeTable_name_RU.getRefN());
+ putref(code_LocalVariableTypeTable_type_RS.getRefN());
+ putu2(code_LocalVariableTypeTable_slot.getInt());
+ }
+ break;
+
+ case ADH_BYTE(ATTR_CONTEXT_CLASS, X_ATTR_Signature) :
+ aname = cp.sym[constant_pool::s_Signature];
+ putref(class_Signature_RS.getRefN());
+ break;
+
+ case ADH_BYTE(ATTR_CONTEXT_FIELD, X_ATTR_Signature) :
+ aname = cp.sym[constant_pool::s_Signature];
+ putref(field_Signature_RS.getRefN());
+ break;
+
+ case ADH_BYTE(ATTR_CONTEXT_METHOD, X_ATTR_Signature) :
+ aname = cp.sym[constant_pool::s_Signature];
+ putref(method_Signature_RS.getRefN());
+ break;
+
+ case ADH_BYTE(ATTR_CONTEXT_CLASS, X_ATTR_Deprecated) :
+ case ADH_BYTE(ATTR_CONTEXT_FIELD, X_ATTR_Deprecated) :
+ case ADH_BYTE(ATTR_CONTEXT_METHOD, X_ATTR_Deprecated) :
+ aname = cp.sym[constant_pool::s_Deprecated];
+ // no data
+ break;
+ }
+ }
+
+ if (aname == nullptr)
+ {
+ // Unparse a compressor-defined attribute.
+ layout_definition *lo = ad.getLayout(idx);
+ if (lo == nullptr)
+ {
+ unpack_abort("bad layout index");
+ break;
+ }
+ assert((int)lo->idx == idx);
+ aname = lo->nameEntry;
+ if (aname == nullptr)
+ {
+ bytes nameb;
+ nameb.set(lo->name);
+ aname = cp.ensureUtf8(nameb);
+ // Cache the name entry for next time.
+ lo->nameEntry = aname;
+ }
+ // Execute all the layout elements.
+ band **bands = lo->bands();
+ if (lo->hasCallables())
+ {
+ band &cble = *bands[0];
+ assert(cble.le_kind == EK_CBLE);
+ bands = cble.le_body;
+ }
+ putlayout(bands);
+ }
+
+ if (aname == nullptr)
+ unpack_abort("bad attribute index");
+
+ byte *wp1 = wp;
+ wp = wp_at(abase);
+
+ // DTRT if this attr is on the strip-list.
+ // (Note that we emptied the data out of the band first.)
+ if (ad.strip_names.contains(aname))
+ {
+ continue;
+ }
+
+ // patch the name and length
+ putref(aname);
+ putu4((int)(wp1 - (wp + 4))); // put the attr size
+ wp = wp1;
+ na++; // count the attrs actually written
+ }
+
+ if (na != na0)
+ // Refresh changed count.
+ putu2_at(wp_at(naOffset), na);
+ return na;
}
void unpacker::write_members(int num, int attrc)
{
- attr_definitions &ad = attr_defs[attrc];
- band &member_flags_hi = ad.xxx_flags_hi();
- band &member_flags_lo = ad.xxx_flags_lo();
- band &member_descr = (&member_flags_hi)[e_field_descr - e_field_flags_hi];
- bool haveLongFlags = ad.haveLongFlags();
-
- putu2(num);
- uint64_t indexMask = attr_defs[attrc].flagIndexMask();
- for (int i = 0; i < num; i++)
- {
- uint64_t mflags = member_flags_hi.getLong(member_flags_lo, haveLongFlags);
- entry *mdescr = member_descr.getRef();
- cur_descr = mdescr;
- putu2(cur_descr_flags = (ushort)(mflags & ~indexMask));
- putref(mdescr->descrName());
- putref(mdescr->descrType());
- write_attrs(attrc, (mflags & indexMask));
- }
- cur_descr = nullptr;
+ attr_definitions &ad = attr_defs[attrc];
+ band &member_flags_hi = ad.xxx_flags_hi();
+ band &member_flags_lo = ad.xxx_flags_lo();
+ band &member_descr = (&member_flags_hi)[e_field_descr - e_field_flags_hi];
+ bool haveLongFlags = ad.haveLongFlags();
+
+ putu2(num);
+ uint64_t indexMask = attr_defs[attrc].flagIndexMask();
+ for (int i = 0; i < num; i++)
+ {
+ uint64_t mflags = member_flags_hi.getLong(member_flags_lo, haveLongFlags);
+ entry *mdescr = member_descr.getRef();
+ cur_descr = mdescr;
+ putu2(cur_descr_flags = (ushort)(mflags & ~indexMask));
+ putref(mdescr->descrName());
+ putref(mdescr->descrType());
+ write_attrs(attrc, (mflags & indexMask));
+ }
+ cur_descr = nullptr;
}
extern "C" int raw_address_cmp(const void *p1p, const void *p2p)
{
- void *p1 = *(void **)p1p;
- void *p2 = *(void **)p2p;
- return (p1 > p2) ? 1 : (p1 < p2) ? -1 : 0;
+ void *p1 = *(void **)p1p;
+ void *p2 = *(void **)p2p;
+ return (p1 > p2) ? 1 : (p1 < p2) ? -1 : 0;
}
void unpacker::write_classfile_tail()
{
- cur_classfile_tail.empty();
- set_output(&cur_classfile_tail);
+ cur_classfile_tail.empty();
+ set_output(&cur_classfile_tail);
- int i, num;
+ int i, num;
- attr_definitions &ad = attr_defs[ATTR_CONTEXT_CLASS];
+ attr_definitions &ad = attr_defs[ATTR_CONTEXT_CLASS];
- bool haveLongFlags = ad.haveLongFlags();
- uint64_t kflags = class_flags_hi.getLong(class_flags_lo, haveLongFlags);
- uint64_t indexMask = ad.flagIndexMask();
+ bool haveLongFlags = ad.haveLongFlags();
+ uint64_t kflags = class_flags_hi.getLong(class_flags_lo, haveLongFlags);
+ uint64_t indexMask = ad.flagIndexMask();
- cur_class = class_this.getRef();
- cur_super = class_super.getRef();
+ cur_class = class_this.getRef();
+ cur_super = class_super.getRef();
- if (cur_super == cur_class)
- cur_super = nullptr;
- // special representation for java/lang/Object
+ if (cur_super == cur_class)
+ cur_super = nullptr;
+ // special representation for java/lang/Object
- putu2((ushort)(kflags & ~indexMask));
- putref(cur_class);
- putref(cur_super);
+ putu2((ushort)(kflags & ~indexMask));
+ putref(cur_class);
+ putref(cur_super);
- putu2(num = class_interface_count.getInt());
- for (i = 0; i < num; i++)
- {
- putref(class_interface.getRef());
- }
+ putu2(num = class_interface_count.getInt());
+ for (i = 0; i < num; i++)
+ {
+ putref(class_interface.getRef());
+ }
- write_members(class_field_count.getInt(), ATTR_CONTEXT_FIELD);
- write_members(class_method_count.getInt(), ATTR_CONTEXT_METHOD);
+ write_members(class_field_count.getInt(), ATTR_CONTEXT_FIELD);
+ write_members(class_method_count.getInt(), ATTR_CONTEXT_METHOD);
- cur_class_has_local_ics = false; // may be set true by write_attrs
+ cur_class_has_local_ics = false; // may be set true by write_attrs
- int naOffset = (int)wpoffset();
- int na = write_attrs(ATTR_CONTEXT_CLASS, (kflags & indexMask));
+ int naOffset = (int)wpoffset();
+ int na = write_attrs(ATTR_CONTEXT_CLASS, (kflags & indexMask));
// at the very last, choose which inner classes (if any) pertain to k:
#ifdef ASSERT
- for (i = 0; i < ic_count; i++)
- {
- assert(!ics[i].requested);
- }
+ for (i = 0; i < ic_count; i++)
+ {
+ assert(!ics[i].requested);
+ }
#endif
- // First, consult the global table and the local constant pool,
- // and decide on the globally implied inner classes.
- // (Note that we read the cpool's outputIndex fields, but we
- // do not yet write them, since the local IC attribute might
- // reverse a global decision to declare an IC.)
- assert(requested_ics.length() == 0); // must start out empty
- // Always include all members of the current class.
- for (inner_class *child = cp.getFirstChildIC(cur_class); child != nullptr;
- child = cp.getNextChildIC(child))
- {
- child->requested = true;
- requested_ics.add(child);
- }
- // And, for each inner class mentioned in the constant pool,
- // include it and all its outers.
- int noes = cp.outputEntries.length();
- entry **oes = (entry **)cp.outputEntries.base();
- for (i = 0; i < noes; i++)
- {
- entry &e = *oes[i];
- if (e.tag != CONSTANT_Class)
- continue; // wrong sort
- for (inner_class *ic = cp.getIC(&e); ic != nullptr; ic = cp.getIC(ic->outer))
- {
- if (ic->requested)
- break; // already processed
- ic->requested = true;
- requested_ics.add(ic);
- }
- }
- int local_ics = requested_ics.length();
- // Second, consult a local attribute (if any) and adjust the global set.
- inner_class *extra_ics = nullptr;
- int num_extra_ics = 0;
- if (cur_class_has_local_ics)
- {
- // adjust the set of ICs by symmetric set difference w/ the locals
- num_extra_ics = class_InnerClasses_N.getInt();
- if (num_extra_ics == 0)
- {
- // Explicit zero count has an irregular meaning: It deletes the attr.
- local_ics = 0; // (short-circuit all tests of requested bits)
- }
- else
- {
- extra_ics = T_NEW(inner_class, num_extra_ics);
- // Note: extra_ics will be freed up by next call to get_next_file().
- }
- }
- for (i = 0; i < num_extra_ics; i++)
- {
- inner_class &extra_ic = extra_ics[i];
- extra_ic.inner = class_InnerClasses_RC.getRef();
- // Find the corresponding equivalent global IC:
- inner_class *global_ic = cp.getIC(extra_ic.inner);
- int flags = class_InnerClasses_F.getInt();
- if (flags == 0)
- {
- // The extra IC is simply a copy of a global IC.
- if (global_ic == nullptr)
- {
- unpack_abort("bad reference to inner class");
- break;
- }
- extra_ic = (*global_ic); // fill in rest of fields
- }
- else
- {
- flags &= ~ACC_IC_LONG_FORM; // clear high bit if set to get clean zero
- extra_ic.flags = flags;
- extra_ic.outer = class_InnerClasses_outer_RCN.getRefN();
- extra_ic.name = class_InnerClasses_name_RUN.getRefN();
- // Detect if this is an exact copy of the global tuple.
- if (global_ic != nullptr)
- {
- if (global_ic->flags != extra_ic.flags || global_ic->outer != extra_ic.outer ||
- global_ic->name != extra_ic.name)
- {
- global_ic = nullptr; // not really the same, so break the link
- }
- }
- }
- if (global_ic != nullptr && global_ic->requested)
- {
- // This local repetition reverses the globally implied request.
- global_ic->requested = false;
- extra_ic.requested = false;
- local_ics -= 1;
- }
- else
- {
- // The global either does not exist, or is not yet requested.
- extra_ic.requested = true;
- local_ics += 1;
- }
- }
- // Finally, if there are any that survived, put them into an attribute.
- // (Note that a zero-count attribute is always deleted.)
- // The putref calls below will tell the constant pool to add any
- // necessary local CP references to support the InnerClasses attribute.
- // This step must be the last round of additions to the local CP.
- if (local_ics > 0)
- {
- // append the new attribute:
- putref(cp.sym[constant_pool::s_InnerClasses]);
- putu4(2 + 2 * 4 * local_ics);
- putu2(local_ics);
- PTRLIST_QSORT(requested_ics, raw_address_cmp);
- int num_global_ics = requested_ics.length();
- for (i = -num_global_ics; i < num_extra_ics; i++)
- {
- inner_class *ic;
- if (i < 0)
- ic = (inner_class *)requested_ics.get(num_global_ics + i);
- else
- ic = &extra_ics[i];
- if (ic->requested)
- {
- putref(ic->inner);
- putref(ic->outer);
- putref(ic->name);
- putu2(ic->flags);
- }
- }
- putu2_at(wp_at(naOffset), ++na); // increment class attr count
- }
-
- // Tidy up global 'requested' bits:
- for (i = requested_ics.length(); --i >= 0;)
- {
- inner_class *ic = (inner_class *)requested_ics.get(i);
- ic->requested = false;
- }
- requested_ics.empty();
-
- close_output();
-
- // rewrite CP references in the tail
- cp.computeOutputIndexes();
- int nextref = 0;
- for (i = 0; i < (int)class_fixup_type.size(); i++)
- {
- int type = class_fixup_type.getByte(i);
- byte *fixp = wp_at(class_fixup_offset.get(i));
- entry *e = (entry *)class_fixup_ref.get(nextref++);
- int idx = e->getOutputIndex();
- switch (type)
- {
- case 1:
- putu1_at(fixp, idx);
- break;
- case 2:
- putu2_at(fixp, idx);
- break;
- default:
- assert(false); // should not reach here
- }
- }
+ // First, consult the global table and the local constant pool,
+ // and decide on the globally implied inner classes.
+ // (Note that we read the cpool's outputIndex fields, but we
+ // do not yet write them, since the local IC attribute might
+ // reverse a global decision to declare an IC.)
+ assert(requested_ics.length() == 0); // must start out empty
+ // Always include all members of the current class.
+ for (inner_class *child = cp.getFirstChildIC(cur_class); child != nullptr;
+ child = cp.getNextChildIC(child))
+ {
+ child->requested = true;
+ requested_ics.add(child);
+ }
+ // And, for each inner class mentioned in the constant pool,
+ // include it and all its outers.
+ int noes = cp.outputEntries.length();
+ entry **oes = (entry **)cp.outputEntries.base();
+ for (i = 0; i < noes; i++)
+ {
+ entry &e = *oes[i];
+ if (e.tag != CONSTANT_Class)
+ continue; // wrong sort
+ for (inner_class *ic = cp.getIC(&e); ic != nullptr; ic = cp.getIC(ic->outer))
+ {
+ if (ic->requested)
+ break; // already processed
+ ic->requested = true;
+ requested_ics.add(ic);
+ }
+ }
+ int local_ics = requested_ics.length();
+ // Second, consult a local attribute (if any) and adjust the global set.
+ inner_class *extra_ics = nullptr;
+ int num_extra_ics = 0;
+ if (cur_class_has_local_ics)
+ {
+ // adjust the set of ICs by symmetric set difference w/ the locals
+ num_extra_ics = class_InnerClasses_N.getInt();
+ if (num_extra_ics == 0)
+ {
+ // Explicit zero count has an irregular meaning: It deletes the attr.
+ local_ics = 0; // (short-circuit all tests of requested bits)
+ }
+ else
+ {
+ extra_ics = T_NEW(inner_class, num_extra_ics);
+ // Note: extra_ics will be freed up by next call to get_next_file().
+ }
+ }
+ for (i = 0; i < num_extra_ics; i++)
+ {
+ inner_class &extra_ic = extra_ics[i];
+ extra_ic.inner = class_InnerClasses_RC.getRef();
+ // Find the corresponding equivalent global IC:
+ inner_class *global_ic = cp.getIC(extra_ic.inner);
+ int flags = class_InnerClasses_F.getInt();
+ if (flags == 0)
+ {
+ // The extra IC is simply a copy of a global IC.
+ if (global_ic == nullptr)
+ {
+ unpack_abort("bad reference to inner class");
+ break;
+ }
+ extra_ic = (*global_ic); // fill in rest of fields
+ }
+ else
+ {
+ flags &= ~ACC_IC_LONG_FORM; // clear high bit if set to get clean zero
+ extra_ic.flags = flags;
+ extra_ic.outer = class_InnerClasses_outer_RCN.getRefN();
+ extra_ic.name = class_InnerClasses_name_RUN.getRefN();
+ // Detect if this is an exact copy of the global tuple.
+ if (global_ic != nullptr)
+ {
+ if (global_ic->flags != extra_ic.flags || global_ic->outer != extra_ic.outer ||
+ global_ic->name != extra_ic.name)
+ {
+ global_ic = nullptr; // not really the same, so break the link
+ }
+ }
+ }
+ if (global_ic != nullptr && global_ic->requested)
+ {
+ // This local repetition reverses the globally implied request.
+ global_ic->requested = false;
+ extra_ic.requested = false;
+ local_ics -= 1;
+ }
+ else
+ {
+ // The global either does not exist, or is not yet requested.
+ extra_ic.requested = true;
+ local_ics += 1;
+ }
+ }
+ // Finally, if there are any that survived, put them into an attribute.
+ // (Note that a zero-count attribute is always deleted.)
+ // The putref calls below will tell the constant pool to add any
+ // necessary local CP references to support the InnerClasses attribute.
+ // This step must be the last round of additions to the local CP.
+ if (local_ics > 0)
+ {
+ // append the new attribute:
+ putref(cp.sym[constant_pool::s_InnerClasses]);
+ putu4(2 + 2 * 4 * local_ics);
+ putu2(local_ics);
+ PTRLIST_QSORT(requested_ics, raw_address_cmp);
+ int num_global_ics = requested_ics.length();
+ for (i = -num_global_ics; i < num_extra_ics; i++)
+ {
+ inner_class *ic;
+ if (i < 0)
+ ic = (inner_class *)requested_ics.get(num_global_ics + i);
+ else
+ ic = &extra_ics[i];
+ if (ic->requested)
+ {
+ putref(ic->inner);
+ putref(ic->outer);
+ putref(ic->name);
+ putu2(ic->flags);
+ }
+ }
+ putu2_at(wp_at(naOffset), ++na); // increment class attr count
+ }
+
+ // Tidy up global 'requested' bits:
+ for (i = requested_ics.length(); --i >= 0;)
+ {
+ inner_class *ic = (inner_class *)requested_ics.get(i);
+ ic->requested = false;
+ }
+ requested_ics.empty();
+
+ close_output();
+
+ // rewrite CP references in the tail
+ cp.computeOutputIndexes();
+ int nextref = 0;
+ for (i = 0; i < (int)class_fixup_type.size(); i++)
+ {
+ int type = class_fixup_type.getByte(i);
+ byte *fixp = wp_at(class_fixup_offset.get(i));
+ entry *e = (entry *)class_fixup_ref.get(nextref++);
+ int idx = e->getOutputIndex();
+ switch (type)
+ {
+ case 1:
+ putu1_at(fixp, idx);
+ break;
+ case 2:
+ putu2_at(fixp, idx);
+ break;
+ default:
+ assert(false); // should not reach here
+ }
+ }
}
void unpacker::write_classfile_head()
{
- cur_classfile_head.empty();
- set_output(&cur_classfile_head);
-
- putu4(JAVA_MAGIC);
- putu2(cur_class_minver);
- putu2(cur_class_majver);
- putu2(cp.outputIndexLimit);
-
- int checkIndex = 1;
- int noes = cp.outputEntries.length();
- entry **oes = (entry **)cp.outputEntries.base();
- for (int i = 0; i < noes; i++)
- {
- entry &e = *oes[i];
- assert(e.getOutputIndex() == checkIndex++);
- byte tag = e.tag;
- assert(tag != CONSTANT_Signature);
- putu1(tag);
- switch (tag)
- {
- case CONSTANT_Utf8:
- putu2((int)e.value.b.len);
- put_bytes(e.value.b);
- break;
- case CONSTANT_Integer:
- case CONSTANT_Float:
- putu4(e.value.i);
- break;
- case CONSTANT_Long:
- case CONSTANT_Double:
- putu8(e.value.l);
- assert(checkIndex++);
- break;
- case CONSTANT_Class:
- case CONSTANT_String:
- // just write the ref
- putu2(e.refs[0]->getOutputIndex());
- break;
- case CONSTANT_Fieldref:
- case CONSTANT_Methodref:
- case CONSTANT_InterfaceMethodref:
- case CONSTANT_NameandType:
- putu2(e.refs[0]->getOutputIndex());
- putu2(e.refs[1]->getOutputIndex());
- break;
- default:
- unpack_abort(ERROR_INTERNAL);
- }
- }
- close_output();
+ cur_classfile_head.empty();
+ set_output(&cur_classfile_head);
+
+ putu4(JAVA_MAGIC);
+ putu2(cur_class_minver);
+ putu2(cur_class_majver);
+ putu2(cp.outputIndexLimit);
+
+#ifndef NDEBUG
+ int checkIndex = 1;
+#endif
+ int noes = cp.outputEntries.length();
+ entry **oes = (entry **)cp.outputEntries.base();
+ for (int i = 0; i < noes; i++)
+ {
+ entry &e = *oes[i];
+ assert(e.getOutputIndex() == checkIndex++);
+ byte tag = e.tag;
+ assert(tag != CONSTANT_Signature);
+ putu1(tag);
+ switch (tag)
+ {
+ case CONSTANT_Utf8:
+ putu2((int)e.value.b.len);
+ put_bytes(e.value.b);
+ break;
+ case CONSTANT_Integer:
+ case CONSTANT_Float:
+ putu4(e.value.i);
+ break;
+ case CONSTANT_Long:
+ case CONSTANT_Double:
+ putu8(e.value.l);
+ assert(checkIndex++);
+ break;
+ case CONSTANT_Class:
+ case CONSTANT_String:
+ // just write the ref
+ putu2(e.refs[0]->getOutputIndex());
+ break;
+ case CONSTANT_Fieldref:
+ case CONSTANT_Methodref:
+ case CONSTANT_InterfaceMethodref:
+ case CONSTANT_NameandType:
+ putu2(e.refs[0]->getOutputIndex());
+ putu2(e.refs[1]->getOutputIndex());
+ break;
+ default:
+ unpack_abort(ERROR_INTERNAL);
+ }
+ }
+ close_output();
}
unpacker::file *unpacker::get_next_file()
{
- free_temps();
- if (files_remaining == 0)
- {
- // Leave a clue that we're exhausted.
- cur_file.name = nullptr;
- cur_file.size = 0;
- if (archive_size != 0)
- {
- uint64_t predicted_size = unsized_bytes_read + archive_size;
- if (predicted_size != bytes_read)
- unpack_abort("archive header had incorrect size");
- }
- return nullptr;
- }
- files_remaining -= 1;
- assert(files_written < file_count || classes_written < class_count);
- cur_file.name = "";
- cur_file.size = 0;
- cur_file.modtime = default_file_modtime;
- cur_file.options = default_file_options;
- cur_file.data[0].set(nullptr, 0);
- cur_file.data[1].set(nullptr, 0);
- if (files_written < file_count)
- {
- entry *e = file_name.getRef();
- cur_file.name = e->utf8String();
- bool haveLongSize = ((archive_options & AO_HAVE_FILE_SIZE_HI) != 0);
- cur_file.size = file_size_hi.getLong(file_size_lo, haveLongSize);
- if ((archive_options & AO_HAVE_FILE_MODTIME) != 0)
- cur_file.modtime += file_modtime.getInt(); // relative to archive modtime
- if ((archive_options & AO_HAVE_FILE_OPTIONS) != 0)
- cur_file.options |= file_options.getInt() & ~suppress_file_options;
- }
- else if (classes_written < class_count)
- {
- // there is a class for a missing file record
- cur_file.options |= FO_IS_CLASS_STUB;
- }
- if ((cur_file.options & FO_IS_CLASS_STUB) != 0)
- {
- assert(classes_written < class_count);
- classes_written += 1;
- if (cur_file.size != 0)
- {
- unpack_abort("class file size transmitted");
- }
- reset_cur_classfile();
-
- // write the meat of the classfile:
- write_classfile_tail();
- cur_file.data[1] = cur_classfile_tail.b;
-
- // write the CP of the classfile, second:
- write_classfile_head();
- cur_file.data[0] = cur_classfile_head.b;
-
- cur_file.size += cur_file.data[0].len;
- cur_file.size += cur_file.data[1].len;
- if (cur_file.name[0] == '\0')
- {
- bytes &prefix = cur_class->ref(0)->value.b;
- const char *suffix = ".class";
- int len = (int)(prefix.len + strlen(suffix));
- bytes name;
- name.set(T_NEW(byte, add_size(len, 1)), len);
- cur_file.name = name.strcat(prefix).strcat(suffix).strval();
- }
- }
- else
- {
- // If there is buffered file data, produce a pointer to it.
- if (cur_file.size != (size_t)cur_file.size)
- {
- // Silly size specified.
- unpack_abort("resource file too large");
- }
- size_t rpleft = input_remaining();
- if (rpleft > 0)
- {
- if (rpleft > cur_file.size)
- rpleft = (size_t)cur_file.size;
- cur_file.data[0].set(rp, rpleft);
- rp += rpleft;
- }
- if (rpleft < cur_file.size)
- {
- // Caller must read the rest.
- size_t fleft = (size_t)cur_file.size - rpleft;
- bytes_read += fleft; // Credit it to the overall archive size.
- }
- }
- bytes_written += cur_file.size;
- files_written += 1;
- return &cur_file;
+ free_temps();
+ if (files_remaining == 0)
+ {
+ // Leave a clue that we're exhausted.
+ cur_file.name = nullptr;
+ cur_file.size = 0;
+ if (archive_size != 0)
+ {
+ uint64_t predicted_size = unsized_bytes_read + archive_size;
+ if (predicted_size != bytes_read)
+ unpack_abort("archive header had incorrect size");
+ }
+ return nullptr;
+ }
+ files_remaining -= 1;
+ assert(files_written < file_count || classes_written < class_count);
+ cur_file.name = "";
+ cur_file.size = 0;
+ cur_file.modtime = default_file_modtime;
+ cur_file.options = default_file_options;
+ cur_file.data[0].set(nullptr, 0);
+ cur_file.data[1].set(nullptr, 0);
+ if (files_written < file_count)
+ {
+ entry *e = file_name.getRef();
+ cur_file.name = e->utf8String();
+ bool haveLongSize = ((archive_options & AO_HAVE_FILE_SIZE_HI) != 0);
+ cur_file.size = file_size_hi.getLong(file_size_lo, haveLongSize);
+ if ((archive_options & AO_HAVE_FILE_MODTIME) != 0)
+ cur_file.modtime += file_modtime.getInt(); // relative to archive modtime
+ if ((archive_options & AO_HAVE_FILE_OPTIONS) != 0)
+ cur_file.options |= file_options.getInt() & ~suppress_file_options;
+ }
+ else if (classes_written < class_count)
+ {
+ // there is a class for a missing file record
+ cur_file.options |= FO_IS_CLASS_STUB;
+ }
+ if ((cur_file.options & FO_IS_CLASS_STUB) != 0)
+ {
+ assert(classes_written < class_count);
+ classes_written += 1;
+ if (cur_file.size != 0)
+ {
+ unpack_abort("class file size transmitted");
+ }
+ reset_cur_classfile();
+
+ // write the meat of the classfile:
+ write_classfile_tail();
+ cur_file.data[1] = cur_classfile_tail.b;
+
+ // write the CP of the classfile, second:
+ write_classfile_head();
+ cur_file.data[0] = cur_classfile_head.b;
+
+ cur_file.size += cur_file.data[0].len;
+ cur_file.size += cur_file.data[1].len;
+ if (cur_file.name[0] == '\0')
+ {
+ bytes &prefix = cur_class->ref(0)->value.b;
+ const char *suffix = ".class";
+ int len = (int)(prefix.len + strlen(suffix));
+ bytes name;
+ name.set(T_NEW(byte, add_size(len, 1)), len);
+ cur_file.name = name.strcat(prefix).strcat(suffix).strval();
+ }
+ }
+ else
+ {
+ // If there is buffered file data, produce a pointer to it.
+ if (cur_file.size != (size_t)cur_file.size)
+ {
+ // Silly size specified.
+ unpack_abort("resource file too large");
+ }
+ size_t rpleft = input_remaining();
+ if (rpleft > 0)
+ {
+ if (rpleft > cur_file.size)
+ rpleft = (size_t)cur_file.size;
+ cur_file.data[0].set(rp, rpleft);
+ rp += rpleft;
+ }
+ if (rpleft < cur_file.size)
+ {
+ // Caller must read the rest.
+ size_t fleft = (size_t)cur_file.size - rpleft;
+ bytes_read += fleft; // Credit it to the overall archive size.
+ }
+ }
+ bytes_written += cur_file.size;
+ files_written += 1;
+ return &cur_file;
}
// Write a file to jarout.
void unpacker::write_file_to_jar(unpacker::file *f)
{
- size_t htsize = f->data[0].len + f->data[1].len;
- uint64_t fsize = f->size;
- if (htsize == fsize)
- {
- jarout->addJarEntry(f->name, f->deflate_hint(), f->modtime, f->data[0], f->data[1]);
- }
- else
- {
- assert(input_remaining() == 0);
- bytes part1, part2;
- part1.len = f->data[0].len;
- part1.set(T_NEW(byte, part1.len), part1.len);
- part1.copyFrom(f->data[0]);
- assert(f->data[1].len == 0);
- part2.set(nullptr, 0);
- size_t fleft = (size_t)fsize - part1.len;
- assert(bytes_read > fleft); // part2 already credited by get_next_file
- bytes_read -= fleft;
- if (fleft > 0)
- {
- // Must read some more.
- if (live_input)
- {
- // Stop using the input buffer. Make a new one:
- if (free_input)
- input.free();
- input.init(fleft > (1 << 12) ? fleft : (1 << 12));
- free_input = true;
- live_input = false;
- }
- else
- {
- // Make it large enough.
- assert(free_input); // must be reallocable
- input.ensureSize(fleft);
- }
- rplimit = rp = input.base();
- input.setLimit(rp + fleft);
- if (!ensure_input(fleft))
- unpack_abort("EOF reading resource file");
- part2.ptr = input_scan();
- part2.len = input_remaining();
- rplimit = rp = input.base();
- }
- jarout->addJarEntry(f->name, f->deflate_hint(), f->modtime, part1, part2);
- }
- if (verbose >= 3)
- {
- fprintf(stderr, "Wrote " LONG_LONG_FORMAT " bytes to: %s\n", fsize, f->name);
- }
+ size_t htsize = f->data[0].len + f->data[1].len;
+ uint64_t fsize = f->size;
+ if (htsize == fsize)
+ {
+ jarout->addJarEntry(f->name, f->deflate_hint(), f->modtime, f->data[0], f->data[1]);
+ }
+ else
+ {
+ assert(input_remaining() == 0);
+ bytes part1, part2;
+ part1.len = f->data[0].len;
+ part1.set(T_NEW(byte, part1.len), part1.len);
+ part1.copyFrom(f->data[0]);
+ assert(f->data[1].len == 0);
+ part2.set(nullptr, 0);
+ size_t fleft = (size_t)fsize - part1.len;
+ assert(bytes_read > fleft); // part2 already credited by get_next_file
+ bytes_read -= fleft;
+ if (fleft > 0)
+ {
+ // Must read some more.
+ if (live_input)
+ {
+ // Stop using the input buffer. Make a new one:
+ if (free_input)
+ input.free();
+ input.init(fleft > (1 << 12) ? fleft : (1 << 12));
+ free_input = true;
+ live_input = false;
+ }
+ else
+ {
+ // Make it large enough.
+ assert(free_input); // must be reallocable
+ input.ensureSize(fleft);
+ }
+ rplimit = rp = input.base();
+ input.setLimit(rp + fleft);
+ if (!ensure_input(fleft))
+ unpack_abort("EOF reading resource file");
+ part2.ptr = input_scan();
+ part2.len = input_remaining();
+ rplimit = rp = input.base();
+ }
+ jarout->addJarEntry(f->name, f->deflate_hint(), f->modtime, part1, part2);
+ }
+ if (verbose >= 3)
+ {
+ fprintf(stderr, "Wrote %" PRIu64 " bytes to: %s\n", fsize, f->name);
+ }
}
diff --git a/libraries/pack200/src/unpack.h b/libraries/pack200/src/unpack.h
index 0100700d..cc5dd60a 100644
--- a/libraries/pack200/src/unpack.h
+++ b/libraries/pack200/src/unpack.h
@@ -23,6 +23,8 @@
* questions.
*/
+#pragma once
+
// Global Structures
struct jar;
struct gunzip;
@@ -33,106 +35,108 @@ struct cpindex;
struct inner_class;
struct value_stream;
+typedef int64_t (*read_input_fn_t)(unpacker *self, void *buf, int64_t minlen, int64_t maxlen);
+
struct cpindex
{
- uint32_t len;
- entry *base1; // base of primary index
- entry **base2; // base of secondary index
- byte ixTag; // type of entries (!= CONSTANT_None), plus 64 if sub-index
- enum
- {
- SUB_TAG = 64
- };
-
- entry *get(uint32_t i);
-
- void init(int len_, entry *base1_, int ixTag_)
- {
- len = len_;
- base1 = base1_;
- base2 = nullptr;
- ixTag = ixTag_;
- }
- void init(int len_, entry **base2_, int ixTag_)
- {
- len = len_;
- base1 = nullptr;
- base2 = base2_;
- ixTag = ixTag_;
- }
+ uint32_t len;
+ entry *base1; // base of primary index
+ entry **base2; // base of secondary index
+ byte ixTag; // type of entries (!= CONSTANT_None), plus 64 if sub-index
+ enum
+ {
+ SUB_TAG = 64
+ };
+
+ entry *get(uint32_t i);
+
+ void init(int len_, entry *base1_, int ixTag_)
+ {
+ len = len_;
+ base1 = base1_;
+ base2 = nullptr;
+ ixTag = ixTag_;
+ }
+ void init(int len_, entry **base2_, int ixTag_)
+ {
+ len = len_;
+ base1 = nullptr;
+ base2 = base2_;
+ ixTag = ixTag_;
+ }
};
struct constant_pool
{
- uint32_t nentries;
- entry *entries;
- entry *first_extra_entry;
- uint32_t maxentries; // total allocated size of entries
-
- // Position and size of each homogeneous subrange:
- int tag_count[CONSTANT_Limit];
- int tag_base[CONSTANT_Limit];
- cpindex tag_index[CONSTANT_Limit];
- ptrlist tag_extras[CONSTANT_Limit];
-
- cpindex *member_indexes; // indexed by 2*CONSTANT_Class.inord
- cpindex *getFieldIndex(entry *classRef);
- cpindex *getMethodIndex(entry *classRef);
-
- inner_class **ic_index;
- inner_class **ic_child_index;
- inner_class *getIC(entry *inner);
- inner_class *getFirstChildIC(entry *outer);
- inner_class *getNextChildIC(inner_class *child);
-
- int outputIndexLimit; // index limit after renumbering
- ptrlist outputEntries; // list of entry* needing output idx assigned
-
- entry **hashTab;
- uint32_t hashTabLength;
- entry *&hashTabRef(byte tag, bytes &b);
- entry *ensureUtf8(bytes &b);
- entry *ensureClass(bytes &b);
-
- // Well-known Utf8 symbols.
- enum
- {
+ uint32_t nentries;
+ entry *entries;
+ entry *first_extra_entry;
+ uint32_t maxentries; // total allocated size of entries
+
+ // Position and size of each homogeneous subrange:
+ int tag_count[CONSTANT_Limit];
+ int tag_base[CONSTANT_Limit];
+ cpindex tag_index[CONSTANT_Limit];
+ ptrlist tag_extras[CONSTANT_Limit];
+
+ cpindex *member_indexes; // indexed by 2*CONSTANT_Class.inord
+ cpindex *getFieldIndex(entry *classRef);
+ cpindex *getMethodIndex(entry *classRef);
+
+ inner_class **ic_index;
+ inner_class **ic_child_index;
+ inner_class *getIC(entry *inner);
+ inner_class *getFirstChildIC(entry *outer);
+ inner_class *getNextChildIC(inner_class *child);
+
+ int outputIndexLimit; // index limit after renumbering
+ ptrlist outputEntries; // list of entry* needing output idx assigned
+
+ entry **hashTab;
+ uint32_t hashTabLength;
+ entry *&hashTabRef(byte tag, bytes &b);
+ entry *ensureUtf8(bytes &b);
+ entry *ensureClass(bytes &b);
+
+ // Well-known Utf8 symbols.
+ enum
+ {
#define SNAME(n, s) s_##s,
- ALL_ATTR_DO(SNAME)
+ ALL_ATTR_DO(SNAME)
#undef SNAME
- s_lt_init_gt, // <init>
- s_LIMIT
- };
- entry *sym[s_LIMIT];
-
- // read counts from hdr, allocate main arrays
- enum
- {
- NUM_COUNTS = 12
- };
- void init(unpacker *u, int counts[NUM_COUNTS]);
-
- // pointer to outer unpacker, for error checks etc.
- unpacker *u;
-
- int getCount(byte tag)
- {
- assert((uint32_t)tag < CONSTANT_Limit);
- return tag_count[tag];
- }
- cpindex *getIndex(byte tag)
- {
- assert((uint32_t)tag < CONSTANT_Limit);
- return &tag_index[tag];
- }
- cpindex *getKQIndex(); // uses cur_descr
-
- void expandSignatures();
- void initMemberIndexes();
-
- void computeOutputOrder();
- void computeOutputIndexes();
- void resetOutputIndexes();
+ s_lt_init_gt, // <init>
+ s_LIMIT
+ };
+ entry *sym[s_LIMIT];
+
+ // read counts from hdr, allocate main arrays
+ enum
+ {
+ NUM_COUNTS = 12
+ };
+ void init(unpacker *u, int counts[NUM_COUNTS]);
+
+ // pointer to outer unpacker, for error checks etc.
+ unpacker *u;
+
+ int getCount(byte tag)
+ {
+ assert((uint32_t)tag < CONSTANT_Limit);
+ return tag_count[tag];
+ }
+ cpindex *getIndex(byte tag)
+ {
+ assert((uint32_t)tag < CONSTANT_Limit);
+ return &tag_index[tag];
+ }
+ cpindex *getKQIndex(); // uses cur_descr
+
+ void expandSignatures();
+ void initMemberIndexes();
+
+ void computeOutputOrder();
+ void computeOutputIndexes();
+ void resetOutputIndexes();
};
/*
@@ -141,407 +145,405 @@ struct constant_pool
*/
struct unpacker
{
- // One element of the resulting JAR.
- struct file
- {
- const char *name;
- uint64_t size;
- int modtime;
- int options;
- bytes data[2];
- // Note: If Sum(data[*].len) < size,
- // remaining bytes must be read directly from the input stream.
- bool deflate_hint()
- {
- return ((options & FO_DEFLATE_HINT) != 0);
- }
- };
-
- // if running Unix-style, here are the inputs and outputs
- FILE *infileptr; // buffered
- bytes inbytes; // direct
- gunzip *gzin; // gunzip filter, if any
- jar *jarout; // output JAR file
-
- // pointer to self, for U_NEW macro
- unpacker *u;
-
- ptrlist mallocs; // list of guys to free when we are all done
- ptrlist tmallocs; // list of guys to free on next client request
- fillbytes smallbuf; // supplies small alloc requests
- fillbytes tsmallbuf; // supplies temporary small alloc requests
-
- // option management members
- int verbose; // verbose level, 0 means no output
- int deflate_hint_or_zero; // ==0 means not set, otherwise -1 or 1
- int modification_time_or_zero;
-
- // input stream
- fillbytes input; // the whole block (size is predicted, has slop too)
- bool live_input; // is the data in this block live?
- bool free_input; // must the input buffer be freed?
- byte *rp; // read pointer (< rplimit <= input.limit())
- byte *rplimit; // how much of the input block has been read?
- uint64_t bytes_read;
- int unsized_bytes_read;
-
- // callback to read at least one byte, up to available input
- typedef int64_t (*read_input_fn_t)(unpacker *self, void *buf, int64_t minlen,
- int64_t maxlen);
- read_input_fn_t read_input_fn;
-
- // archive header fields
- int magic, minver, majver;
- size_t archive_size;
- int archive_next_count, archive_options, archive_modtime;
- int band_headers_size;
- int file_count, attr_definition_count, ic_count, class_count;
- int default_class_minver, default_class_majver;
- int default_file_options, suppress_file_options; // not header fields
- int default_archive_modtime, default_file_modtime; // not header fields
- int code_count; // not a header field
- int files_remaining; // not a header field
-
- // engine state
- band *all_bands; // indexed by band_number
- byte *meta_rp; // read-pointer into (copy of) band_headers
- constant_pool cp; // all constant pool information
- inner_class *ics; // InnerClasses
-
- // output stream
- bytes output; // output block (either classfile head or tail)
- byte *wp; // write pointer (< wplimit == output.limit())
- byte *wpbase; // write pointer starting address (<= wp)
- byte *wplimit; // how much of the output block has been written?
-
- // output state
- file cur_file;
- entry *cur_class; // CONSTANT_Class entry
- entry *cur_super; // CONSTANT_Class entry or nullptr
- entry *cur_descr; // CONSTANT_NameandType entry
- int cur_descr_flags; // flags corresponding to cur_descr
- int cur_class_minver, cur_class_majver;
- bool cur_class_has_local_ics;
- fillbytes cur_classfile_head;
- fillbytes cur_classfile_tail;
- int files_written; // also tells which file we're working on
- int classes_written; // also tells which class we're working on
- uint64_t bytes_written;
- intlist bcimap;
- fillbytes class_fixup_type;
- intlist class_fixup_offset;
- ptrlist class_fixup_ref;
- fillbytes code_fixup_type; // which format of branch operand?
- intlist code_fixup_offset; // location of operand needing fixup
- intlist code_fixup_source; // encoded ID of branch insn
- ptrlist requested_ics; // which ics need output?
-
- // stats pertaining to multiple segments (updated on reset)
- uint64_t bytes_read_before_reset;
- uint64_t bytes_written_before_reset;
- int files_written_before_reset;
- int classes_written_before_reset;
- int segments_read_before_reset;
-
- // attribute state
- struct layout_definition
- {
- uint32_t idx; // index (0..31...) which identifies this layout
- const char *name; // name of layout
- entry *nameEntry;
- const char *layout; // string of layout (not yet parsed)
- band **elems; // array of top-level layout elems (or callables)
-
- bool hasCallables()
- {
- return layout[0] == '[';
- }
- band **bands()
- {
- assert(elems != nullptr);
- return elems;
- }
- };
- struct attr_definitions
- {
- unpacker *u; // pointer to self, for U_NEW macro
- int xxx_flags_hi_bn; // locator for flags, count, indexes, calls bands
- int attrc; // ATTR_CONTEXT_CLASS, etc.
- uint32_t flag_limit; // 32 or 63, depending on archive_options bit
- uint64_t predef; // mask of built-in definitions
- uint64_t redef; // mask of local flag definitions or redefinitions
- ptrlist layouts; // local (compressor-defined) defs, in index order
- int flag_count[X_ATTR_LIMIT_FLAGS_HI];
- intlist overflow_count;
- ptrlist strip_names; // what attribute names are being stripped?
- ptrlist band_stack; // Temp., used during layout parsing.
- ptrlist calls_to_link; // (ditto)
- int bands_made; // (ditto)
-
- void free()
- {
- layouts.free();
- overflow_count.free();
- strip_names.free();
- band_stack.free();
- calls_to_link.free();
- }
-
- // Locate the five fixed bands.
- band &xxx_flags_hi();
- band &xxx_flags_lo();
- band &xxx_attr_count();
- band &xxx_attr_indexes();
- band &xxx_attr_calls();
- band &fixed_band(int e_class_xxx);
-
- // Register a new layout, and make bands for it.
- layout_definition *defineLayout(int idx, const char *name, const char *layout);
- layout_definition *defineLayout(int idx, entry *nameEntry, const char *layout);
- band **buildBands(layout_definition *lo);
-
- // Parse a layout string or part of one, recursively if necessary.
- const char *parseLayout(const char *lp, band **&res, int curCble);
- const char *parseNumeral(const char *lp, int &res);
- const char *parseIntLayout(const char *lp, band *&res, byte le_kind,
- bool can_be_signed = false);
- band **popBody(int band_stack_base); // pops a body off band_stack
-
- // Read data into the bands of the idx-th layout.
- void readBandData(int idx); // parse layout, make bands, read data
- void readBandData(band **body, uint32_t count); // recursive helper
-
- layout_definition *getLayout(uint32_t idx)
- {
- if (idx >= (uint32_t)layouts.length())
- return nullptr;
- return (layout_definition *)layouts.get(idx);
- }
-
- void setHaveLongFlags(bool z)
- {
- assert(flag_limit == 0); // not set up yet
- flag_limit = (z ? X_ATTR_LIMIT_FLAGS_HI : X_ATTR_LIMIT_NO_FLAGS_HI);
- }
- bool haveLongFlags()
- {
- assert(flag_limit == X_ATTR_LIMIT_NO_FLAGS_HI ||
- flag_limit == X_ATTR_LIMIT_FLAGS_HI);
- return flag_limit == X_ATTR_LIMIT_FLAGS_HI;
- }
-
- // Return flag_count if idx is predef and not redef, else zero.
- int predefCount(uint32_t idx);
-
- bool isRedefined(uint32_t idx)
- {
- if (idx >= flag_limit)
- return false;
- return (bool)((redef >> idx) & 1);
- }
- bool isPredefined(uint32_t idx)
- {
- if (idx >= flag_limit)
- return false;
- return (bool)(((predef & ~redef) >> idx) & 1);
- }
- uint64_t flagIndexMask()
- {
- return (predef | redef);
- }
- bool isIndex(uint32_t idx)
- {
- assert(flag_limit != 0); // must be set up already
- if (idx < flag_limit)
- return (bool)(((predef | redef) >> idx) & 1);
- else
- return (idx - flag_limit < (uint32_t)overflow_count.length());
- }
- int &getCount(uint32_t idx)
- {
- assert(isIndex(idx));
- if (idx < flag_limit)
- return flag_count[idx];
- else
- return overflow_count.get(idx - flag_limit);
- }
- };
-
- attr_definitions attr_defs[ATTR_CONTEXT_LIMIT];
-
- // Initialization
- void init(read_input_fn_t input_fn = nullptr);
- // Resets to a known sane state
- void reset();
- // Deallocates all storage.
- void free();
- // Deallocates temporary storage (volatile after next client call).
- void free_temps()
- {
- tsmallbuf.init();
- tmallocs.freeAll();
- }
-
- // Option management methods
- bool set_option(const char *option, const char *value);
- const char *get_option(const char *option);
-
- // Fetching input.
- bool ensure_input(int64_t more);
- byte *input_scan()
- {
- return rp;
- }
- size_t input_remaining()
- {
- return rplimit - rp;
- }
- size_t input_consumed()
- {
- return rp - input.base();
- }
-
- // Entry points to the unpack engine
- static int run(int argc, char **argv); // Unix-style entry point.
- void check_options();
- void start(void *packptr = nullptr, size_t len = 0);
- void write_file_to_jar(file *f);
- void finish();
-
- // Public post unpack methods
- int get_files_remaining()
- {
- return files_remaining;
- }
- int get_segments_remaining()
- {
- return archive_next_count;
- }
- file *get_next_file(); // returns nullptr on last file
-
- // General purpose methods
- void *alloc(size_t size)
- {
- return alloc_heap(size, true);
- }
- void *temp_alloc(size_t size)
- {
- return alloc_heap(size, true, true);
- }
- void *alloc_heap(size_t size, bool smallOK = false, bool temp = false);
- void saveTo(bytes &b, const char *str)
- {
- saveTo(b, (byte *)str, strlen(str));
- }
- void saveTo(bytes &b, bytes &data)
- {
- saveTo(b, data.ptr, data.len);
- }
- void saveTo(bytes &b, byte *ptr, size_t len); //{ b.ptr = U_NEW...}
- const char *saveStr(const char *str)
- {
- bytes buf;
- saveTo(buf, str);
- return buf.strval();
- }
- const char *saveIntStr(int num)
- {
- char buf[30];
- sprintf(buf, "%d", num);
- return saveStr(buf);
- }
- static unpacker *current(); // find current instance
-
- // Output management
- void set_output(fillbytes *which)
- {
- assert(wp == nullptr);
- which->ensureSize(1 << 12); // covers the average classfile
- wpbase = which->base();
- wp = which->limit();
- wplimit = which->end();
- }
- fillbytes *close_output(fillbytes *which = nullptr); // inverse of set_output
-
- // These take an implicit parameter of wp/wplimit, and resize as necessary:
- byte *put_space(size_t len); // allocates space at wp, returns pointer
- size_t put_empty(size_t s)
- {
- byte *p = put_space(s);
- return p - wpbase;
- }
- void ensure_put_space(size_t len);
- void put_bytes(bytes &b)
- {
- b.writeTo(put_space(b.len));
- }
- void putu1(int n)
- {
- putu1_at(put_space(1), n);
- }
- void putu1_fast(int n)
- {
- putu1_at(wp++, n);
- }
- void putu2(int n); // { putu2_at(put_space(2), n); }
- void putu4(int n); // { putu4_at(put_space(4), n); }
- void putu8(int64_t n); // { putu8_at(put_space(8), n); }
- void putref(entry *e); // { putu2_at(put_space(2), putref_index(e, 2)); }
- void putu1ref(entry *e); // { putu1_at(put_space(1), putref_index(e, 1)); }
- int putref_index(entry *e, int size); // size in [1..2]
- void put_label(int curIP, int size); // size in {2,4}
- void putlayout(band **body);
- void put_stackmap_type();
-
- size_t wpoffset()
- {
- return (size_t)(wp - wpbase);
- } // (unvariant across overflow)
- byte *wp_at(size_t offset)
- {
- return wpbase + offset;
- }
- uint32_t to_bci(uint32_t bii);
- void get_code_header(int &max_stack, int &max_na_locals, int &handler_count, int &cflags);
- band *ref_band_for_self_op(int bc, bool &isAloadVar, int &origBCVar);
- band *ref_band_for_op(int bc);
-
- // Definitions of standard classfile int formats:
- static void putu1_at(byte *wp, int n)
- {
- assert(n == (n & 0xFF));
- wp[0] = n;
- }
- static void putu2_at(byte *wp, int n);
- static void putu4_at(byte *wp, int n);
- static void putu8_at(byte *wp, int64_t n);
-
- // Private stuff
- void reset_cur_classfile();
- void write_classfile_tail();
- void write_classfile_head();
- void write_code();
- void write_bc_ops();
- void write_members(int num, int attrc); // attrc=ATTR_CONTEXT_FIELD/METHOD
- int write_attrs(int attrc, uint64_t indexBits);
-
- // The readers
- void read_bands();
- void read_file_header();
- void read_cp();
- void read_cp_counts(value_stream &hdr);
- void read_attr_defs();
- void read_ics();
- void read_attrs(int attrc, int obj_count);
- void read_classes();
- void read_code_headers();
- void read_bcs();
- void read_bc_ops();
- void read_files();
- void read_Utf8_values(entry *cpMap, int len);
- void read_single_words(band &cp_band, entry *cpMap, int len);
- void read_double_words(band &cp_bands, entry *cpMap, int len);
- void read_single_refs(band &cp_band, byte refTag, entry *cpMap, int len);
- void read_double_refs(band &cp_band, byte ref1Tag, byte ref2Tag, entry *cpMap, int len);
- void read_signature_values(entry *cpMap, int len);
+ // One element of the resulting JAR.
+ struct file
+ {
+ const char *name;
+ uint64_t size;
+ int modtime;
+ int options;
+ bytes data[2];
+ // Note: If Sum(data[*].len) < size,
+ // remaining bytes must be read directly from the input stream.
+ bool deflate_hint()
+ {
+ return ((options & FO_DEFLATE_HINT) != 0);
+ }
+ };
+
+ // if running Unix-style, here are the inputs and outputs
+ FILE *infileptr; // buffered
+ bytes inbytes; // direct
+ gunzip *gzin; // gunzip filter, if any
+ jar *jarout; // output JAR file
+
+ // pointer to self, for U_NEW macro
+ unpacker *u;
+
+ ptrlist mallocs; // list of guys to free when we are all done
+ ptrlist tmallocs; // list of guys to free on next client request
+ fillbytes smallbuf; // supplies small alloc requests
+ fillbytes tsmallbuf; // supplies temporary small alloc requests
+
+ // option management members
+ int verbose; // verbose level, 0 means no output
+ int deflate_hint_or_zero; // ==0 means not set, otherwise -1 or 1
+ int modification_time_or_zero;
+
+ // input stream
+ fillbytes input; // the whole block (size is predicted, has slop too)
+ bool live_input; // is the data in this block live?
+ bool free_input; // must the input buffer be freed?
+ byte *rp; // read pointer (< rplimit <= input.limit())
+ byte *rplimit; // how much of the input block has been read?
+ uint64_t bytes_read;
+ int unsized_bytes_read;
+
+ // callback to read at least one byte, up to available input
+ read_input_fn_t read_input_fn;
+
+ // archive header fields
+ int magic, minver, majver;
+ size_t archive_size;
+ int archive_next_count, archive_options, archive_modtime;
+ int band_headers_size;
+ int file_count, attr_definition_count, ic_count, class_count;
+ int default_class_minver, default_class_majver;
+ int default_file_options, suppress_file_options; // not header fields
+ int default_archive_modtime, default_file_modtime; // not header fields
+ int code_count; // not a header field
+ int files_remaining; // not a header field
+
+ // engine state
+ band *all_bands; // indexed by band_number
+ byte *meta_rp; // read-pointer into (copy of) band_headers
+ constant_pool cp; // all constant pool information
+ inner_class *ics; // InnerClasses
+
+ // output stream
+ bytes output; // output block (either classfile head or tail)
+ byte *wp; // write pointer (< wplimit == output.limit())
+ byte *wpbase; // write pointer starting address (<= wp)
+ byte *wplimit; // how much of the output block has been written?
+
+ // output state
+ file cur_file;
+ entry *cur_class; // CONSTANT_Class entry
+ entry *cur_super; // CONSTANT_Class entry or nullptr
+ entry *cur_descr; // CONSTANT_NameandType entry
+ int cur_descr_flags; // flags corresponding to cur_descr
+ int cur_class_minver, cur_class_majver;
+ bool cur_class_has_local_ics;
+ fillbytes cur_classfile_head;
+ fillbytes cur_classfile_tail;
+ int files_written; // also tells which file we're working on
+ int classes_written; // also tells which class we're working on
+ uint64_t bytes_written;
+ intlist bcimap;
+ fillbytes class_fixup_type;
+ intlist class_fixup_offset;
+ ptrlist class_fixup_ref;
+ fillbytes code_fixup_type; // which format of branch operand?
+ intlist code_fixup_offset; // location of operand needing fixup
+ intlist code_fixup_source; // encoded ID of branch insn
+ ptrlist requested_ics; // which ics need output?
+
+ // stats pertaining to multiple segments (updated on reset)
+ uint64_t bytes_read_before_reset;
+ uint64_t bytes_written_before_reset;
+ int files_written_before_reset;
+ int classes_written_before_reset;
+ int segments_read_before_reset;
+
+ // attribute state
+ struct layout_definition
+ {
+ uint32_t idx; // index (0..31...) which identifies this layout
+ const char *name; // name of layout
+ entry *nameEntry;
+ const char *layout; // string of layout (not yet parsed)
+ band **elems; // array of top-level layout elems (or callables)
+
+ bool hasCallables()
+ {
+ return layout[0] == '[';
+ }
+ band **bands()
+ {
+ assert(elems != nullptr);
+ return elems;
+ }
+ };
+ struct attr_definitions
+ {
+ unpacker *u; // pointer to self, for U_NEW macro
+ int xxx_flags_hi_bn; // locator for flags, count, indexes, calls bands
+ int attrc; // ATTR_CONTEXT_CLASS, etc.
+ uint32_t flag_limit; // 32 or 63, depending on archive_options bit
+ uint64_t predef; // mask of built-in definitions
+ uint64_t redef; // mask of local flag definitions or redefinitions
+ ptrlist layouts; // local (compressor-defined) defs, in index order
+ int flag_count[X_ATTR_LIMIT_FLAGS_HI];
+ intlist overflow_count;
+ ptrlist strip_names; // what attribute names are being stripped?
+ ptrlist band_stack; // Temp., used during layout parsing.
+ ptrlist calls_to_link; // (ditto)
+ int bands_made; // (ditto)
+
+ void free()
+ {
+ layouts.free();
+ overflow_count.free();
+ strip_names.free();
+ band_stack.free();
+ calls_to_link.free();
+ }
+
+ // Locate the five fixed bands.
+ band &xxx_flags_hi();
+ band &xxx_flags_lo();
+ band &xxx_attr_count();
+ band &xxx_attr_indexes();
+ band &xxx_attr_calls();
+ band &fixed_band(int e_class_xxx);
+
+ // Register a new layout, and make bands for it.
+ layout_definition *defineLayout(int idx, const char *name, const char *layout);
+ layout_definition *defineLayout(int idx, entry *nameEntry, const char *layout);
+ band **buildBands(layout_definition *lo);
+
+ // Parse a layout string or part of one, recursively if necessary.
+ const char *parseLayout(const char *lp, band **&res, int curCble);
+ const char *parseNumeral(const char *lp, int &res);
+ const char *parseIntLayout(const char *lp, band *&res, byte le_kind,
+ bool can_be_signed = false);
+ band **popBody(int band_stack_base); // pops a body off band_stack
+
+ // Read data into the bands of the idx-th layout.
+ void readBandData(int idx); // parse layout, make bands, read data
+ void readBandData(band **body, uint32_t count); // recursive helper
+
+ layout_definition *getLayout(uint32_t idx)
+ {
+ if (idx >= (uint32_t)layouts.length())
+ return nullptr;
+ return (layout_definition *)layouts.get(idx);
+ }
+
+ void setHaveLongFlags(bool z)
+ {
+ assert(flag_limit == 0); // not set up yet
+ flag_limit = (z ? X_ATTR_LIMIT_FLAGS_HI : X_ATTR_LIMIT_NO_FLAGS_HI);
+ }
+ bool haveLongFlags()
+ {
+ assert(flag_limit == X_ATTR_LIMIT_NO_FLAGS_HI ||
+ flag_limit == X_ATTR_LIMIT_FLAGS_HI);
+ return flag_limit == X_ATTR_LIMIT_FLAGS_HI;
+ }
+
+ // Return flag_count if idx is predef and not redef, else zero.
+ int predefCount(uint32_t idx);
+
+ bool isRedefined(uint32_t idx)
+ {
+ if (idx >= flag_limit)
+ return false;
+ return (bool)((redef >> idx) & 1);
+ }
+ bool isPredefined(uint32_t idx)
+ {
+ if (idx >= flag_limit)
+ return false;
+ return (bool)(((predef & ~redef) >> idx) & 1);
+ }
+ uint64_t flagIndexMask()
+ {
+ return (predef | redef);
+ }
+ bool isIndex(uint32_t idx)
+ {
+ assert(flag_limit != 0); // must be set up already
+ if (idx < flag_limit)
+ return (bool)(((predef | redef) >> idx) & 1);
+ else
+ return (idx - flag_limit < (uint32_t)overflow_count.length());
+ }
+ int &getCount(uint32_t idx)
+ {
+ assert(isIndex(idx));
+ if (idx < flag_limit)
+ return flag_count[idx];
+ else
+ return overflow_count.get(idx - flag_limit);
+ }
+ };
+
+ attr_definitions attr_defs[ATTR_CONTEXT_LIMIT];
+
+ // Initialization
+ void init(read_input_fn_t input_fn = nullptr);
+ // Resets to a known sane state
+ void reset();
+ // Deallocates all storage.
+ void free();
+ // Deallocates temporary storage (volatile after next client call).
+ void free_temps()
+ {
+ tsmallbuf.init();
+ tmallocs.freeAll();
+ }
+
+ // Option management methods
+ bool set_option(const char *option, const char *value);
+ const char *get_option(const char *option);
+
+ // Fetching input.
+ bool ensure_input(int64_t more);
+ byte *input_scan()
+ {
+ return rp;
+ }
+ size_t input_remaining()
+ {
+ return rplimit - rp;
+ }
+ size_t input_consumed()
+ {
+ return rp - input.base();
+ }
+
+ // Entry points to the unpack engine
+ static int run(int argc, char **argv); // Unix-style entry point.
+ void check_options();
+ void start(void *packptr = nullptr, size_t len = 0);
+ void write_file_to_jar(file *f);
+ void finish();
+
+ // Public post unpack methods
+ int get_files_remaining()
+ {
+ return files_remaining;
+ }
+ int get_segments_remaining()
+ {
+ return archive_next_count;
+ }
+ file *get_next_file(); // returns nullptr on last file
+
+ // General purpose methods
+ void *alloc(size_t size)
+ {
+ return alloc_heap(size, true);
+ }
+ void *temp_alloc(size_t size)
+ {
+ return alloc_heap(size, true, true);
+ }
+ void *alloc_heap(size_t size, bool smallOK = false, bool temp = false);
+ void saveTo(bytes &b, const char *str)
+ {
+ saveTo(b, (byte *)str, strlen(str));
+ }
+ void saveTo(bytes &b, bytes &data)
+ {
+ saveTo(b, data.ptr, data.len);
+ }
+ void saveTo(bytes &b, byte *ptr, size_t len); //{ b.ptr = U_NEW...}
+ const char *saveStr(const char *str)
+ {
+ bytes buf;
+ saveTo(buf, str);
+ return buf.strval();
+ }
+ const char *saveIntStr(int num)
+ {
+ char buf[30];
+ sprintf(buf, "%d", num);
+ return saveStr(buf);
+ }
+ static unpacker *current(); // find current instance
+
+ // Output management
+ void set_output(fillbytes *which)
+ {
+ assert(wp == nullptr);
+ which->ensureSize(1 << 12); // covers the average classfile
+ wpbase = which->base();
+ wp = which->limit();
+ wplimit = which->end();
+ }
+ fillbytes *close_output(fillbytes *which = nullptr); // inverse of set_output
+
+ // These take an implicit parameter of wp/wplimit, and resize as necessary:
+ byte *put_space(size_t len); // allocates space at wp, returns pointer
+ size_t put_empty(size_t s)
+ {
+ byte *p = put_space(s);
+ return p - wpbase;
+ }
+ void ensure_put_space(size_t len);
+ void put_bytes(bytes &b)
+ {
+ b.writeTo(put_space(b.len));
+ }
+ void putu1(int n)
+ {
+ putu1_at(put_space(1), n);
+ }
+ void putu1_fast(int n)
+ {
+ putu1_at(wp++, n);
+ }
+ void putu2(int n); // { putu2_at(put_space(2), n); }
+ void putu4(int n); // { putu4_at(put_space(4), n); }
+ void putu8(int64_t n); // { putu8_at(put_space(8), n); }
+ void putref(entry *e); // { putu2_at(put_space(2), putref_index(e, 2)); }
+ void putu1ref(entry *e); // { putu1_at(put_space(1), putref_index(e, 1)); }
+ int putref_index(entry *e, int size); // size in [1..2]
+ void put_label(int curIP, int size); // size in {2,4}
+ void putlayout(band **body);
+ void put_stackmap_type();
+
+ size_t wpoffset()
+ {
+ return (size_t)(wp - wpbase);
+ } // (unvariant across overflow)
+ byte *wp_at(size_t offset)
+ {
+ return wpbase + offset;
+ }
+ uint32_t to_bci(uint32_t bii);
+ void get_code_header(int &max_stack, int &max_na_locals, int &handler_count, int &cflags);
+ band *ref_band_for_self_op(int bc, bool &isAloadVar, int &origBCVar);
+ band *ref_band_for_op(int bc);
+
+ // Definitions of standard classfile int formats:
+ static void putu1_at(byte *wp, int n)
+ {
+ assert(n == (n & 0xFF));
+ wp[0] = n;
+ }
+ static void putu2_at(byte *wp, int n);
+ static void putu4_at(byte *wp, int n);
+ static void putu8_at(byte *wp, int64_t n);
+
+ // Private stuff
+ void reset_cur_classfile();
+ void write_classfile_tail();
+ void write_classfile_head();
+ void write_code();
+ void write_bc_ops();
+ void write_members(int num, int attrc); // attrc=ATTR_CONTEXT_FIELD/METHOD
+ int write_attrs(int attrc, uint64_t indexBits);
+
+ // The readers
+ void read_bands();
+ void read_file_header();
+ void read_cp();
+ void read_cp_counts(value_stream &hdr);
+ void read_attr_defs();
+ void read_ics();
+ void read_attrs(int attrc, int obj_count);
+ void read_classes();
+ void read_code_headers();
+ void read_bcs();
+ void read_bc_ops();
+ void read_files();
+ void read_Utf8_values(entry *cpMap, int len);
+ void read_single_words(band &cp_band, entry *cpMap, int len);
+ void read_double_words(band &cp_bands, entry *cpMap, int len);
+ void read_single_refs(band &cp_band, byte refTag, entry *cpMap, int len);
+ void read_double_refs(band &cp_band, byte ref1Tag, byte ref2Tag, entry *cpMap, int len);
+ void read_signature_values(entry *cpMap, int len);
};
diff --git a/libraries/pack200/src/unpack200.cpp b/libraries/pack200/src/unpack200.cpp
index 22b7f3b0..e8826f28 100644
--- a/libraries/pack200/src/unpack200.cpp
+++ b/libraries/pack200/src/unpack200.cpp
@@ -45,118 +45,118 @@
// Callback for fetching data, Unix style.
static int64_t read_input_via_stdio(unpacker *u, void *buf, int64_t minlen, int64_t maxlen)
{
- assert(u->infileptr != nullptr);
- assert(minlen <= maxlen); // don't talk nonsense
- int64_t numread = 0;
- char *bufptr = (char *)buf;
- while (numread < minlen)
- {
- // read available input, up to buf.length or maxlen
- int readlen = (1 << 16);
- if (readlen > (maxlen - numread))
- readlen = (int)(maxlen - numread);
- int nr = 0;
+ assert(u->infileptr != nullptr);
+ assert(minlen <= maxlen); // don't talk nonsense
+ int64_t numread = 0;
+ char *bufptr = (char *)buf;
+ while (numread < minlen)
+ {
+ // read available input, up to buf.length or maxlen
+ int readlen = (1 << 16);
+ if (readlen > (maxlen - numread))
+ readlen = (int)(maxlen - numread);
+ int nr = 0;
- nr = (int)fread(bufptr, 1, readlen, u->infileptr);
- if (nr <= 0)
- {
- if (errno != EINTR)
- break;
- nr = 0;
- }
- numread += nr;
- bufptr += nr;
- assert(numread <= maxlen);
- }
- return numread;
+ nr = (int)fread(bufptr, 1, readlen, u->infileptr);
+ if (nr <= 0)
+ {
+ if (errno != EINTR)
+ break;
+ nr = 0;
+ }
+ numread += nr;
+ bufptr += nr;
+ assert(numread <= maxlen);
+ }
+ return numread;
}
enum
{
- EOF_MAGIC = 0,
- BAD_MAGIC = -1
+ EOF_MAGIC = 0,
+ BAD_MAGIC = -1
};
static int read_magic(unpacker *u, char peek[], int peeklen)
{
- assert(peeklen == 4); // magic numbers are always 4 bytes
- int64_t nr = (u->read_input_fn)(u, peek, peeklen, peeklen);
- if (nr != peeklen)
- {
- return (nr == 0) ? EOF_MAGIC : BAD_MAGIC;
- }
- int magic = 0;
- for (int i = 0; i < peeklen; i++)
- {
- magic <<= 8;
- magic += peek[i] & 0xFF;
- }
- return magic;
+ assert(peeklen == 4); // magic numbers are always 4 bytes
+ int64_t nr = (u->read_input_fn)(u, peek, peeklen, peeklen);
+ if (nr != peeklen)
+ {
+ return (nr == 0) ? EOF_MAGIC : BAD_MAGIC;
+ }
+ int magic = 0;
+ for (int i = 0; i < peeklen; i++)
+ {
+ magic <<= 8;
+ magic += peek[i] & 0xFF;
+ }
+ return magic;
}
void unpack_200(FILE *input, FILE *output)
{
- unpacker u;
- u.init(read_input_via_stdio);
+ unpacker u;
+ u.init(read_input_via_stdio);
- // initialize jar output
- // the output takes ownership of the file handle
- jar jarout;
- jarout.init(&u);
- jarout.jarfp = output;
+ // initialize jar output
+ // the output takes ownership of the file handle
+ jar jarout;
+ jarout.init(&u);
+ jarout.jarfp = output;
- // the input doesn't
- u.infileptr = input;
+ // the input doesn't
+ u.infileptr = input;
- // read the magic!
- char peek[4];
- int magic;
- magic = read_magic(&u, peek, (int)sizeof(peek));
+ // read the magic!
+ char peek[4];
+ int magic;
+ magic = read_magic(&u, peek, (int)sizeof(peek));
- // if it is a gzip encoded file, we need an extra gzip input filter
- if ((magic & GZIP_MAGIC_MASK) == GZIP_MAGIC)
- {
- gunzip *gzin = NEW(gunzip, 1);
- gzin->init(&u);
- // FIXME: why the side effects? WHY?
- u.gzin->start(magic);
- u.start();
- }
- else
- {
- // otherwise, feed the bytes to the unpacker directly
- u.start(peek, sizeof(peek));
- }
+ // if it is a gzip encoded file, we need an extra gzip input filter
+ if ((magic & GZIP_MAGIC_MASK) == GZIP_MAGIC)
+ {
+ gunzip *gzin = NEW(gunzip, 1);
+ gzin->init(&u);
+ // FIXME: why the side effects? WHY?
+ u.gzin->start(magic);
+ u.start();
+ }
+ else
+ {
+ // otherwise, feed the bytes to the unpacker directly
+ u.start(peek, sizeof(peek));
+ }
- // Note: The checks to u.aborting() are necessary to gracefully
- // terminate processing when the first segment throws an error.
- for (;;)
- {
- // Each trip through this loop unpacks one segment
- // and then resets the unpacker.
- for (unpacker::file *filep; (filep = u.get_next_file()) != nullptr;)
- {
- u.write_file_to_jar(filep);
- }
+ // Note: The checks to u.aborting() are necessary to gracefully
+ // terminate processing when the first segment throws an error.
+ for (;;)
+ {
+ // Each trip through this loop unpacks one segment
+ // and then resets the unpacker.
+ for (unpacker::file *filep; (filep = u.get_next_file()) != nullptr;)
+ {
+ u.write_file_to_jar(filep);
+ }
- // Peek ahead for more data.
- magic = read_magic(&u, peek, (int)sizeof(peek));
- if (magic != (int)JAVA_PACKAGE_MAGIC)
- {
- // we do not feel strongly about this kind of thing...
- /*
- if (magic != EOF_MAGIC)
- unpack_abort("garbage after end of pack archive");
- */
- break; // all done
- }
+ // Peek ahead for more data.
+ magic = read_magic(&u, peek, (int)sizeof(peek));
+ if (magic != (int)JAVA_PACKAGE_MAGIC)
+ {
+ // we do not feel strongly about this kind of thing...
+ /*
+ if (magic != EOF_MAGIC)
+ unpack_abort("garbage after end of pack archive");
+ */
+ break; // all done
+ }
- // Release all storage from parsing the old segment.
- u.reset();
- // Restart, beginning with the peek-ahead.
- u.start(peek, sizeof(peek));
- }
- u.finish();
- u.free(); // tidy up malloc blocks
- fclose(input);
+ // Release all storage from parsing the old segment.
+ u.reset();
+ // Restart, beginning with the peek-ahead.
+ u.start(peek, sizeof(peek));
+ }
+ u.finish();
+ u.free(); // tidy up malloc blocks
+ fclose(input);
}
diff --git a/libraries/pack200/src/utils.cpp b/libraries/pack200/src/utils.cpp
index 0b7d91ca..fd6dad60 100644
--- a/libraries/pack200/src/utils.cpp
+++ b/libraries/pack200/src/utils.cpp
@@ -50,22 +50,22 @@
void *must_malloc(size_t size)
{
- size_t msize = size;
- void *ptr = (msize > PSIZE_MAX) ? nullptr : malloc(msize);
- if (ptr != nullptr)
- {
- memset(ptr, 0, size);
- }
- else
- {
- throw std::runtime_error(ERROR_ENOMEM);
- }
- return ptr;
+ size_t msize = size;
+ void *ptr = (msize > PSIZE_MAX) ? nullptr : malloc(msize);
+ if (ptr != nullptr)
+ {
+ memset(ptr, 0, size);
+ }
+ else
+ {
+ throw std::runtime_error(ERROR_ENOMEM);
+ }
+ return ptr;
}
void unpack_abort(const char *msg)
{
- if (msg == nullptr)
- msg = "corrupt pack file or internal error";
- throw std::runtime_error(msg);
+ if (msg == nullptr)
+ msg = "corrupt pack file or internal error";
+ throw std::runtime_error(msg);
}
diff --git a/libraries/pack200/src/utils.h b/libraries/pack200/src/utils.h
index 5a3dc8f6..3bd2dae7 100644
--- a/libraries/pack200/src/utils.h
+++ b/libraries/pack200/src/utils.h
@@ -35,17 +35,17 @@ void *must_malloc(size_t size);
inline size_t scale_size(size_t size, size_t scale)
{
- return (size > PSIZE_MAX / scale) ? OVERFLOW : size * scale;
+ return (size > PSIZE_MAX / scale) ? OVERFLOW : size * scale;
}
inline size_t add_size(size_t size1, size_t size2)
{
- return ((size1 | size2 | (size1 + size2)) > PSIZE_MAX) ? OVERFLOW : size1 + size2;
+ return ((size1 | size2 | (size1 + size2)) > PSIZE_MAX) ? OVERFLOW : size1 + size2;
}
inline size_t add_size(size_t size1, size_t size2, int size3)
{
- return add_size(add_size(size1, size2), size3);
+ return add_size(add_size(size1, size2), size3);
}
struct unpacker;
diff --git a/libraries/pack200/src/zip.cpp b/libraries/pack200/src/zip.cpp
index 32e8bd50..e776510b 100644
--- a/libraries/pack200/src/zip.cpp
+++ b/libraries/pack200/src/zip.cpp
@@ -52,7 +52,7 @@
inline uint32_t jar::get_crc32(uint32_t c, uchar *ptr, uint32_t len)
{
- return crc32(c, ptr, len);
+ return crc32(c, ptr, len);
}
// FIXME: this is bullshit. Do real endianness detection.
@@ -68,175 +68,175 @@ inline uint32_t jar::get_crc32(uint32_t c, uchar *ptr, uint32_t len)
void jar::init(unpacker *u_)
{
- BYTES_OF(*this).clear();
- u = u_;
- u->jarout = this;
+ BYTES_OF(*this).clear();
+ u = u_;
+ u->jarout = this;
}
// Write data to the ZIP output stream.
void jar::write_data(void *buff, int len)
{
- while (len > 0)
- {
- int rc = (int)fwrite(buff, 1, len, jarfp);
- if (rc <= 0)
- {
- fprintf(stderr, "Error: write on output file failed err=%d\n", errno);
- exit(1); // Called only from the native standalone unpacker
- }
- output_file_offset += rc;
- buff = ((char *)buff) + rc;
- len -= rc;
- }
+ while (len > 0)
+ {
+ int rc = (int)fwrite(buff, 1, len, jarfp);
+ if (rc <= 0)
+ {
+ fprintf(stderr, "Error: write on output file failed err=%d\n", errno);
+ exit(1); // Called only from the native standalone unpacker
+ }
+ output_file_offset += rc;
+ buff = ((char *)buff) + rc;
+ len -= rc;
+ }
}
void jar::add_to_jar_directory(const char *fname, bool store, int modtime, int len, int clen,
- uint32_t crc)
+ uint32_t crc)
{
- uint32_t fname_length = (uint32_t)strlen(fname);
- ushort header[23];
- if (modtime == 0)
- modtime = default_modtime;
- uint32_t dostime = get_dostime(modtime);
-
- header[0] = (ushort)SWAP_BYTES(0x4B50);
- header[1] = (ushort)SWAP_BYTES(0x0201);
- header[2] = (ushort)SWAP_BYTES(0xA);
-
- // required version
- header[3] = (ushort)SWAP_BYTES(0xA);
-
- // flags 02 = maximum sub-compression flag
- header[4] = (store) ? 0x0 : SWAP_BYTES(0x2);
-
- // Compression method 8=deflate.
- header[5] = (store) ? 0x0 : SWAP_BYTES(0x08);
-
- // Last modified date and time.
- header[6] = (ushort)GET_INT_LO(dostime);
- header[7] = (ushort)GET_INT_HI(dostime);
-
- // CRC
- header[8] = (ushort)GET_INT_LO(crc);
- header[9] = (ushort)GET_INT_HI(crc);
-
- // Compressed length:
- header[10] = (ushort)GET_INT_LO(clen);
- header[11] = (ushort)GET_INT_HI(clen);
-
- // Uncompressed length.
- header[12] = (ushort)GET_INT_LO(len);
- header[13] = (ushort)GET_INT_HI(len);
-
- // Filename length
- header[14] = (ushort)SWAP_BYTES(fname_length);
- // So called "extra field" length.
- header[15] = 0;
- // So called "comment" length.
- header[16] = 0;
- // Disk number start
- header[17] = 0;
- // File flags => binary
- header[18] = 0;
- // More file flags
- header[19] = 0;
- header[20] = 0;
- // Offset within ZIP file.
- header[21] = (ushort)GET_INT_LO(output_file_offset);
- header[22] = (ushort)GET_INT_HI(output_file_offset);
-
- // Copy the whole thing into the central directory.
- central_directory.append(header, sizeof(header));
-
- // Copy the fname to the header.
- central_directory.append(fname, fname_length);
-
- central_directory_count++;
+ uint32_t fname_length = (uint32_t)strlen(fname);
+ ushort header[23];
+ if (modtime == 0)
+ modtime = default_modtime;
+ uint32_t dostime = get_dostime(modtime);
+
+ header[0] = (ushort)SWAP_BYTES(0x4B50);
+ header[1] = (ushort)SWAP_BYTES(0x0201);
+ header[2] = (ushort)SWAP_BYTES(0xA);
+
+ // required version
+ header[3] = (ushort)SWAP_BYTES(0xA);
+
+ // flags 02 = maximum sub-compression flag
+ header[4] = (store) ? 0x0 : SWAP_BYTES(0x2);
+
+ // Compression method 8=deflate.
+ header[5] = (store) ? 0x0 : SWAP_BYTES(0x08);
+
+ // Last modified date and time.
+ header[6] = (ushort)GET_INT_LO(dostime);
+ header[7] = (ushort)GET_INT_HI(dostime);
+
+ // CRC
+ header[8] = (ushort)GET_INT_LO(crc);
+ header[9] = (ushort)GET_INT_HI(crc);
+
+ // Compressed length:
+ header[10] = (ushort)GET_INT_LO(clen);
+ header[11] = (ushort)GET_INT_HI(clen);
+
+ // Uncompressed length.
+ header[12] = (ushort)GET_INT_LO(len);
+ header[13] = (ushort)GET_INT_HI(len);
+
+ // Filename length
+ header[14] = (ushort)SWAP_BYTES(fname_length);
+ // So called "extra field" length.
+ header[15] = 0;
+ // So called "comment" length.
+ header[16] = 0;
+ // Disk number start
+ header[17] = 0;
+ // File flags => binary
+ header[18] = 0;
+ // More file flags
+ header[19] = 0;
+ header[20] = 0;
+ // Offset within ZIP file.
+ header[21] = (ushort)GET_INT_LO(output_file_offset);
+ header[22] = (ushort)GET_INT_HI(output_file_offset);
+
+ // Copy the whole thing into the central directory.
+ central_directory.append(header, sizeof(header));
+
+ // Copy the fname to the header.
+ central_directory.append(fname, fname_length);
+
+ central_directory_count++;
}
void jar::write_jar_header(const char *fname, bool store, int modtime, int len, int clen,
- uint32_t crc)
+ uint32_t crc)
{
- uint32_t fname_length = (uint32_t)strlen(fname);
- ushort header[15];
- if (modtime == 0)
- modtime = default_modtime;
- uint32_t dostime = get_dostime(modtime);
+ uint32_t fname_length = (uint32_t)strlen(fname);
+ ushort header[15];
+ if (modtime == 0)
+ modtime = default_modtime;
+ uint32_t dostime = get_dostime(modtime);
- // ZIP LOC magic.
- header[0] = (ushort)SWAP_BYTES(0x4B50);
- header[1] = (ushort)SWAP_BYTES(0x0403);
+ // ZIP LOC magic.
+ header[0] = (ushort)SWAP_BYTES(0x4B50);
+ header[1] = (ushort)SWAP_BYTES(0x0403);
- // Version
- header[2] = (ushort)SWAP_BYTES(0xA);
+ // Version
+ header[2] = (ushort)SWAP_BYTES(0xA);
- // flags 02 = maximum sub-compression flag
- header[3] = (store) ? 0x0 : SWAP_BYTES(0x2);
+ // flags 02 = maximum sub-compression flag
+ header[3] = (store) ? 0x0 : SWAP_BYTES(0x2);
- // Compression method = deflate
- header[4] = (store) ? 0x0 : SWAP_BYTES(0x08);
+ // Compression method = deflate
+ header[4] = (store) ? 0x0 : SWAP_BYTES(0x08);
- // Last modified date and time.
- header[5] = (ushort)GET_INT_LO(dostime);
- header[6] = (ushort)GET_INT_HI(dostime);
+ // Last modified date and time.
+ header[5] = (ushort)GET_INT_LO(dostime);
+ header[6] = (ushort)GET_INT_HI(dostime);
- // CRC
- header[7] = (ushort)GET_INT_LO(crc);
- header[8] = (ushort)GET_INT_HI(crc);
+ // CRC
+ header[7] = (ushort)GET_INT_LO(crc);
+ header[8] = (ushort)GET_INT_HI(crc);
- // Compressed length:
- header[9] = (ushort)GET_INT_LO(clen);
- header[10] = (ushort)GET_INT_HI(clen);
+ // Compressed length:
+ header[9] = (ushort)GET_INT_LO(clen);
+ header[10] = (ushort)GET_INT_HI(clen);
- // Uncompressed length.
- header[11] = (ushort)GET_INT_LO(len);
- header[12] = (ushort)GET_INT_HI(len);
+ // Uncompressed length.
+ header[11] = (ushort)GET_INT_LO(len);
+ header[12] = (ushort)GET_INT_HI(len);
- // Filename length
- header[13] = (ushort)SWAP_BYTES(fname_length);
- // So called "extra field" length.
- header[14] = 0;
+ // Filename length
+ header[13] = (ushort)SWAP_BYTES(fname_length);
+ // So called "extra field" length.
+ header[14] = 0;
- // Write the LOC header to the output file.
- write_data(header, (int)sizeof(header));
+ // Write the LOC header to the output file.
+ write_data(header, (int)sizeof(header));
- // Copy the fname to the header.
- write_data((char *)fname, (int)fname_length);
+ // Copy the fname to the header.
+ write_data((char *)fname, (int)fname_length);
}
void jar::write_central_directory()
{
- bytes mc;
- mc.set("PACK200");
-
- ushort header[11];
-
- // Create the End of Central Directory structure.
- header[0] = (ushort)SWAP_BYTES(0x4B50);
- header[1] = (ushort)SWAP_BYTES(0x0605);
- // disk numbers
- header[2] = 0;
- header[3] = 0;
- // Number of entries in central directory.
- header[4] = (ushort)SWAP_BYTES(central_directory_count);
- header[5] = (ushort)SWAP_BYTES(central_directory_count);
- // Size of the central directory}
- header[6] = (ushort)GET_INT_LO((int)central_directory.size());
- header[7] = (ushort)GET_INT_HI((int)central_directory.size());
- // Offset of central directory within disk.
- header[8] = (ushort)GET_INT_LO(output_file_offset);
- header[9] = (ushort)GET_INT_HI(output_file_offset);
- // zipfile comment length;
- header[10] = (ushort)SWAP_BYTES((int)mc.len);
-
- // Write the central directory.
- write_data(central_directory.b);
-
- // Write the End of Central Directory structure.
- write_data(header, (int)sizeof(header));
-
- // Write the comment.
- write_data(mc);
+ bytes mc;
+ mc.set("PACK200");
+
+ ushort header[11];
+
+ // Create the End of Central Directory structure.
+ header[0] = (ushort)SWAP_BYTES(0x4B50);
+ header[1] = (ushort)SWAP_BYTES(0x0605);
+ // disk numbers
+ header[2] = 0;
+ header[3] = 0;
+ // Number of entries in central directory.
+ header[4] = (ushort)SWAP_BYTES(central_directory_count);
+ header[5] = (ushort)SWAP_BYTES(central_directory_count);
+ // Size of the central directory}
+ header[6] = (ushort)GET_INT_LO((int)central_directory.size());
+ header[7] = (ushort)GET_INT_HI((int)central_directory.size());
+ // Offset of central directory within disk.
+ header[8] = (ushort)GET_INT_LO(output_file_offset);
+ header[9] = (ushort)GET_INT_HI(output_file_offset);
+ // zipfile comment length;
+ header[10] = (ushort)SWAP_BYTES((int)mc.len);
+
+ // Write the central directory.
+ write_data(central_directory.b);
+
+ // Write the End of Central Directory structure.
+ write_data(header, (int)sizeof(header));
+
+ // Write the comment.
+ write_data(mc);
}
// Public API
@@ -244,74 +244,74 @@ void jar::write_central_directory()
// Open a Jar file and initialize.
void jar::openJarFile(const char *fname)
{
- if (!jarfp)
- {
- jarfp = fopen(fname, "wb");
- if (!jarfp)
- {
- fprintf(stderr, "Error: Could not open jar file: %s\n", fname);
- exit(3); // Called only from the native standalone unpacker
- }
- }
+ if (!jarfp)
+ {
+ jarfp = fopen(fname, "wb");
+ if (!jarfp)
+ {
+ fprintf(stderr, "Error: Could not open jar file: %s\n", fname);
+ exit(3); // Called only from the native standalone unpacker
+ }
+ }
}
// Add a ZIP entry and copy the file data
void jar::addJarEntry(const char *fname, bool deflate_hint, int modtime, bytes &head,
- bytes &tail)
+ bytes &tail)
{
- int len = (int)(head.len + tail.len);
- int clen = 0;
-
- uint32_t crc = get_crc32(0, Z_NULL, 0);
- if (head.len != 0)
- crc = get_crc32(crc, (uchar *)head.ptr, (uint32_t)head.len);
- if (tail.len != 0)
- crc = get_crc32(crc, (uchar *)tail.ptr, (uint32_t)tail.len);
-
- bool deflate = (deflate_hint && len > 0);
-
- if (deflate)
- {
- if (deflate_bytes(head, tail) == false)
- {
- deflate = false;
- }
- }
- clen = (int)((deflate) ? deflated.size() : len);
- add_to_jar_directory(fname, !deflate, modtime, len, clen, crc);
- write_jar_header(fname, !deflate, modtime, len, clen, crc);
-
- if (deflate)
- {
- write_data(deflated.b);
- }
- else
- {
- write_data(head);
- write_data(tail);
- }
+ int len = (int)(head.len + tail.len);
+ int clen = 0;
+
+ uint32_t crc = get_crc32(0, Z_NULL, 0);
+ if (head.len != 0)
+ crc = get_crc32(crc, (uchar *)head.ptr, (uint32_t)head.len);
+ if (tail.len != 0)
+ crc = get_crc32(crc, (uchar *)tail.ptr, (uint32_t)tail.len);
+
+ bool deflate = (deflate_hint && len > 0);
+
+ if (deflate)
+ {
+ if (deflate_bytes(head, tail) == false)
+ {
+ deflate = false;
+ }
+ }
+ clen = (int)((deflate) ? deflated.size() : len);
+ add_to_jar_directory(fname, !deflate, modtime, len, clen, crc);
+ write_jar_header(fname, !deflate, modtime, len, clen, crc);
+
+ if (deflate)
+ {
+ write_data(deflated.b);
+ }
+ else
+ {
+ write_data(head);
+ write_data(tail);
+ }
}
// Add a ZIP entry for a directory name no data
void jar::addDirectoryToJarFile(const char *dir_name)
{
- bool store = true;
- add_to_jar_directory((const char *)dir_name, store, default_modtime, 0, 0, 0);
- write_jar_header((const char *)dir_name, store, default_modtime, 0, 0, 0);
+ bool store = true;
+ add_to_jar_directory((const char *)dir_name, store, default_modtime, 0, 0, 0);
+ write_jar_header((const char *)dir_name, store, default_modtime, 0, 0, 0);
}
// Write out the central directory and close the jar file.
void jar::closeJarFile(bool central)
{
- if (jarfp)
- {
- fflush(jarfp);
- if (central)
- write_central_directory();
- fflush(jarfp);
- fclose(jarfp);
- }
- reset();
+ if (jarfp)
+ {
+ fflush(jarfp);
+ if (central)
+ write_central_directory();
+ fflush(jarfp);
+ fclose(jarfp);
+ }
+ reset();
}
/* Convert the date y/n/d and time h:m:s to a four byte DOS date and
@@ -320,9 +320,9 @@ void jar::closeJarFile(bool central)
*/
inline uint32_t jar::dostime(int y, int n, int d, int h, int m, int s)
{
- return y < 1980 ? dostime(1980, 1, 1, 0, 0, 0)
- : (((uint32_t)y - 1980) << 25) | ((uint32_t)n << 21) | ((uint32_t)d << 16) |
- ((uint32_t)h << 11) | ((uint32_t)m << 5) | ((uint32_t)s >> 1);
+ return y < 1980 ? dostime(1980, 1, 1, 0, 0, 0)
+ : (((uint32_t)y - 1980) << 25) | ((uint32_t)n << 21) | ((uint32_t)d << 16) |
+ ((uint32_t)h << 11) | ((uint32_t)m << 5) | ((uint32_t)s >> 1);
}
/*
#ifdef _REENTRANT // solaris
@@ -336,20 +336,20 @@ extern "C" struct tm *gmtime_r(const time_t *, struct tm *);
*/
uint32_t jar::get_dostime(int modtime)
{
- // see defines.h
- if (modtime != 0 && modtime == modtime_cache)
- return dostime_cache;
- if (modtime != 0 && default_modtime == 0)
- default_modtime = modtime; // catch a reasonable default
- time_t t = modtime;
- struct tm sbuf;
- (void)memset((void *)&sbuf, 0, sizeof(sbuf));
- struct tm *s = gmtime_r(&t, &sbuf);
- modtime_cache = modtime;
- dostime_cache =
- dostime(s->tm_year + 1900, s->tm_mon + 1, s->tm_mday, s->tm_hour, s->tm_min, s->tm_sec);
- // printf("modtime %d => %d\n", modtime_cache, dostime_cache);
- return dostime_cache;
+ // see defines.h
+ if (modtime != 0 && modtime == modtime_cache)
+ return dostime_cache;
+ if (modtime != 0 && default_modtime == 0)
+ default_modtime = modtime; // catch a reasonable default
+ time_t t = modtime;
+ struct tm sbuf;
+ (void)memset((void *)&sbuf, 0, sizeof(sbuf));
+ struct tm *s = gmtime_r(&t, &sbuf);
+ modtime_cache = modtime;
+ dostime_cache =
+ dostime(s->tm_year + 1900, s->tm_mon + 1, s->tm_mday, s->tm_hour, s->tm_min, s->tm_sec);
+ // printf("modtime %d => %d\n", modtime_cache, dostime_cache);
+ return dostime_cache;
}
/* Returns true on success, and will set the clen to the compressed
@@ -358,232 +358,232 @@ uint32_t jar::get_dostime(int modtime)
*/
bool jar::deflate_bytes(bytes &head, bytes &tail)
{
- int len = (int)(head.len + tail.len);
-
- z_stream zs;
- BYTES_OF(zs).clear();
-
- // NOTE: the window size should always be -MAX_WBITS normally -15.
- // unzip/zipup.c and java/Deflater.c
-
- int error =
- deflateInit2(&zs, Z_BEST_COMPRESSION, Z_DEFLATED, -MAX_WBITS, 8, Z_DEFAULT_STRATEGY);
- if (error != Z_OK)
- {
- /*
- switch (error)
- {
- case Z_MEM_ERROR:
- PRINTCR((2, "Error: deflate error : Out of memory \n"));
- break;
- case Z_STREAM_ERROR:
- PRINTCR((2, "Error: deflate error : Invalid compression level \n"));
- break;
- case Z_VERSION_ERROR:
- PRINTCR((2, "Error: deflate error : Invalid version\n"));
- break;
- default:
- PRINTCR((2, "Error: Internal deflate error error = %d\n", error));
- }
- */
- return false;
- }
-
- deflated.empty();
- zs.next_out = (uchar *)deflated.grow(len + (len / 2));
- zs.avail_out = (int)deflated.size();
-
- zs.next_in = (uchar *)head.ptr;
- zs.avail_in = (int)head.len;
-
- bytes *first = &head;
- bytes *last = &tail;
- if (last->len == 0)
- {
- first = nullptr;
- last = &head;
- }
- else if (first->len == 0)
- {
- first = nullptr;
- }
-
- if (first != nullptr && error == Z_OK)
- {
- zs.next_in = (uchar *)first->ptr;
- zs.avail_in = (int)first->len;
- error = deflate(&zs, Z_NO_FLUSH);
- }
- if (error == Z_OK)
- {
- zs.next_in = (uchar *)last->ptr;
- zs.avail_in = (int)last->len;
- error = deflate(&zs, Z_FINISH);
- }
- if (error == Z_STREAM_END)
- {
- if (len > (int)zs.total_out)
- {
- deflated.b.len = zs.total_out;
- deflateEnd(&zs);
- return true;
- }
- deflateEnd(&zs);
- return false;
- }
-
- deflateEnd(&zs);
- return false;
+ int len = (int)(head.len + tail.len);
+
+ z_stream zs;
+ BYTES_OF(zs).clear();
+
+ // NOTE: the window size should always be -MAX_WBITS normally -15.
+ // unzip/zipup.c and java/Deflater.c
+
+ int error =
+ deflateInit2(&zs, Z_BEST_COMPRESSION, Z_DEFLATED, -MAX_WBITS, 8, Z_DEFAULT_STRATEGY);
+ if (error != Z_OK)
+ {
+ /*
+ switch (error)
+ {
+ case Z_MEM_ERROR:
+ PRINTCR((2, "Error: deflate error : Out of memory \n"));
+ break;
+ case Z_STREAM_ERROR:
+ PRINTCR((2, "Error: deflate error : Invalid compression level \n"));
+ break;
+ case Z_VERSION_ERROR:
+ PRINTCR((2, "Error: deflate error : Invalid version\n"));
+ break;
+ default:
+ PRINTCR((2, "Error: Internal deflate error error = %d\n", error));
+ }
+ */
+ return false;
+ }
+
+ deflated.empty();
+ zs.next_out = (uchar *)deflated.grow(len + (len / 2));
+ zs.avail_out = (int)deflated.size();
+
+ zs.next_in = (uchar *)head.ptr;
+ zs.avail_in = (int)head.len;
+
+ bytes *first = &head;
+ bytes *last = &tail;
+ if (last->len == 0)
+ {
+ first = nullptr;
+ last = &head;
+ }
+ else if (first->len == 0)
+ {
+ first = nullptr;
+ }
+
+ if (first != nullptr && error == Z_OK)
+ {
+ zs.next_in = (uchar *)first->ptr;
+ zs.avail_in = (int)first->len;
+ error = deflate(&zs, Z_NO_FLUSH);
+ }
+ if (error == Z_OK)
+ {
+ zs.next_in = (uchar *)last->ptr;
+ zs.avail_in = (int)last->len;
+ error = deflate(&zs, Z_FINISH);
+ }
+ if (error == Z_STREAM_END)
+ {
+ if (len > (int)zs.total_out)
+ {
+ deflated.b.len = zs.total_out;
+ deflateEnd(&zs);
+ return true;
+ }
+ deflateEnd(&zs);
+ return false;
+ }
+
+ deflateEnd(&zs);
+ return false;
}
// Callback for fetching data from a GZIP input stream
static int64_t read_input_via_gzip(unpacker *u, void *buf, int64_t minlen, int64_t maxlen)
{
- assert(minlen <= maxlen); // don't talk nonsense
- int64_t numread = 0;
- char *bufptr = (char *)buf;
- char *inbuf = u->gzin->inbuf;
- size_t inbuflen = sizeof(u->gzin->inbuf);
- unpacker::read_input_fn_t read_gzin_fn = (unpacker::read_input_fn_t)u->gzin->read_input_fn;
- z_stream &zs = *(z_stream *)u->gzin->zstream;
- while (numread < minlen)
- {
- int readlen = (1 << 16); // pretty arbitrary
- if (readlen > (maxlen - numread))
- readlen = (int)(maxlen - numread);
- zs.next_out = (uchar *)bufptr;
- zs.avail_out = readlen;
- if (zs.avail_in == 0)
- {
- zs.avail_in = (int)read_gzin_fn(u, inbuf, 1, inbuflen);
- zs.next_in = (uchar *)inbuf;
- }
- int error = inflate(&zs, Z_NO_FLUSH);
- if (error != Z_OK && error != Z_STREAM_END)
- {
- unpack_abort("error inflating input");
- break;
- }
- int nr = readlen - zs.avail_out;
- numread += nr;
- bufptr += nr;
- assert(numread <= maxlen);
- if (error == Z_STREAM_END)
- {
- enum
- {
- TRAILER_LEN = 8
- };
- // skip 8-byte trailer
- if (zs.avail_in >= TRAILER_LEN)
- {
- zs.avail_in -= TRAILER_LEN;
- }
- else
- {
- // Bug: 5023768,we read past the TRAILER_LEN to see if there is
- // any extraneous data, as we dont support concatenated .gz
- // files just yet.
- int extra = (int)read_gzin_fn(u, inbuf, 1, inbuflen);
- zs.avail_in += extra - TRAILER_LEN;
- }
- // %%% should check final CRC and length here
- // %%% should check for concatenated *.gz files here
- if (zs.avail_in > 0)
- unpack_abort("garbage after end of deflated input stream");
- // pop this filter off:
- u->gzin->free();
- break;
- }
- }
-
- // fprintf(u->errstrm, "readInputFn(%d,%d) => %d (gunzip)\n",
- // (int)minlen, (int)maxlen, (int)numread);
- return numread;
+ assert(minlen <= maxlen); // don't talk nonsense
+ int64_t numread = 0;
+ char *bufptr = (char *)buf;
+ char *inbuf = u->gzin->inbuf;
+ size_t inbuflen = sizeof(u->gzin->inbuf);
+ read_input_fn_t read_gzin_fn = u->gzin->read_input_fn;
+ z_stream &zs = *(z_stream *)u->gzin->zstream;
+ while (numread < minlen)
+ {
+ int readlen = (1 << 16); // pretty arbitrary
+ if (readlen > (maxlen - numread))
+ readlen = (int)(maxlen - numread);
+ zs.next_out = (uchar *)bufptr;
+ zs.avail_out = readlen;
+ if (zs.avail_in == 0)
+ {
+ zs.avail_in = (int)read_gzin_fn(u, inbuf, 1, inbuflen);
+ zs.next_in = (uchar *)inbuf;
+ }
+ int error = inflate(&zs, Z_NO_FLUSH);
+ if (error != Z_OK && error != Z_STREAM_END)
+ {
+ unpack_abort("error inflating input");
+ break;
+ }
+ int nr = readlen - zs.avail_out;
+ numread += nr;
+ bufptr += nr;
+ assert(numread <= maxlen);
+ if (error == Z_STREAM_END)
+ {
+ enum
+ {
+ TRAILER_LEN = 8
+ };
+ // skip 8-byte trailer
+ if (zs.avail_in >= TRAILER_LEN)
+ {
+ zs.avail_in -= TRAILER_LEN;
+ }
+ else
+ {
+ // Bug: 5023768,we read past the TRAILER_LEN to see if there is
+ // any extraneous data, as we dont support concatenated .gz
+ // files just yet.
+ int extra = (int)read_gzin_fn(u, inbuf, 1, inbuflen);
+ zs.avail_in += extra - TRAILER_LEN;
+ }
+ // %%% should check final CRC and length here
+ // %%% should check for concatenated *.gz files here
+ if (zs.avail_in > 0)
+ unpack_abort("garbage after end of deflated input stream");
+ // pop this filter off:
+ u->gzin->free();
+ break;
+ }
+ }
+
+ // fprintf(u->errstrm, "readInputFn(%d,%d) => %d (gunzip)\n",
+ // (int)minlen, (int)maxlen, (int)numread);
+ return numread;
}
void gunzip::init(unpacker *u_)
{
- BYTES_OF(*this).clear();
- u = u_;
- assert(u->gzin == nullptr); // once only, please
- read_input_fn = (void *)u->read_input_fn;
- zstream = NEW(z_stream, 1);
- u->gzin = this;
- u->read_input_fn = read_input_via_gzip;
+ BYTES_OF(*this).clear();
+ u = u_;
+ assert(u->gzin == nullptr); // once only, please
+ read_input_fn = u->read_input_fn;
+ zstream = NEW(z_stream, 1);
+ u->gzin = this;
+ u->read_input_fn = read_input_via_gzip;
}
void gunzip::start(int magic)
{
- assert((magic & GZIP_MAGIC_MASK) == GZIP_MAGIC);
- int gz_flg = (magic & 0xFF); // keep "flg", discard other 3 bytes
- enum
- {
- FHCRC = (1 << 1),
- FEXTRA = (1 << 2),
- FNAME = (1 << 3),
- FCOMMENT = (1 << 4)
- };
- char gz_mtime[4];
- char gz_xfl[1];
- char gz_os[1];
- char gz_extra_len[2];
- char gz_hcrc[2];
- char gz_ignore;
- // do not save extra, name, comment
- read_fixed_field(gz_mtime, sizeof(gz_mtime));
- read_fixed_field(gz_xfl, sizeof(gz_xfl));
- read_fixed_field(gz_os, sizeof(gz_os));
- if (gz_flg & FEXTRA)
- {
- read_fixed_field(gz_extra_len, sizeof(gz_extra_len));
- int extra_len = gz_extra_len[0] & 0xFF;
- extra_len += (gz_extra_len[1] & 0xFF) << 8;
- for (; extra_len > 0; extra_len--)
- {
- read_fixed_field(&gz_ignore, 1);
- }
- }
- int null_terms = 0;
- if (gz_flg & FNAME)
- null_terms++;
- if (gz_flg & FCOMMENT)
- null_terms++;
- for (; null_terms; null_terms--)
- {
- for (;;)
- {
- gz_ignore = 0;
- read_fixed_field(&gz_ignore, 1);
- if (gz_ignore == 0)
- break;
- }
- }
- if (gz_flg & FHCRC)
- read_fixed_field(gz_hcrc, sizeof(gz_hcrc));
-
- // now the input stream is ready to read into the inflater
- int error = inflateInit2((z_stream *)zstream, -MAX_WBITS);
- if (error != Z_OK)
- {
- unpack_abort("cannot create input");
- }
+ assert((magic & GZIP_MAGIC_MASK) == GZIP_MAGIC);
+ int gz_flg = (magic & 0xFF); // keep "flg", discard other 3 bytes
+ enum
+ {
+ FHCRC = (1 << 1),
+ FEXTRA = (1 << 2),
+ FNAME = (1 << 3),
+ FCOMMENT = (1 << 4)
+ };
+ char gz_mtime[4];
+ char gz_xfl[1];
+ char gz_os[1];
+ char gz_extra_len[2];
+ char gz_hcrc[2];
+ char gz_ignore;
+ // do not save extra, name, comment
+ read_fixed_field(gz_mtime, sizeof(gz_mtime));
+ read_fixed_field(gz_xfl, sizeof(gz_xfl));
+ read_fixed_field(gz_os, sizeof(gz_os));
+ if (gz_flg & FEXTRA)
+ {
+ read_fixed_field(gz_extra_len, sizeof(gz_extra_len));
+ int extra_len = gz_extra_len[0] & 0xFF;
+ extra_len += (gz_extra_len[1] & 0xFF) << 8;
+ for (; extra_len > 0; extra_len--)
+ {
+ read_fixed_field(&gz_ignore, 1);
+ }
+ }
+ int null_terms = 0;
+ if (gz_flg & FNAME)
+ null_terms++;
+ if (gz_flg & FCOMMENT)
+ null_terms++;
+ for (; null_terms; null_terms--)
+ {
+ for (;;)
+ {
+ gz_ignore = 0;
+ read_fixed_field(&gz_ignore, 1);
+ if (gz_ignore == 0)
+ break;
+ }
+ }
+ if (gz_flg & FHCRC)
+ read_fixed_field(gz_hcrc, sizeof(gz_hcrc));
+
+ // now the input stream is ready to read into the inflater
+ int error = inflateInit2((z_stream *)zstream, -MAX_WBITS);
+ if (error != Z_OK)
+ {
+ unpack_abort("cannot create input");
+ }
}
void gunzip::free()
{
- assert(u->gzin == this);
- u->gzin = nullptr;
- u->read_input_fn = (unpacker::read_input_fn_t) this->read_input_fn;
- inflateEnd((z_stream *)zstream);
- ::free(zstream);
- zstream = nullptr;
- ::free(this);
+ assert(u->gzin == this);
+ u->gzin = nullptr;
+ u->read_input_fn = this->read_input_fn;
+ inflateEnd((z_stream *)zstream);
+ ::free(zstream);
+ zstream = nullptr;
+ ::free(this);
}
void gunzip::read_fixed_field(char *buf, size_t buflen)
{
- int64_t nr = ((unpacker::read_input_fn_t)read_input_fn)(u, buf, buflen, buflen);
- if ((size_t)nr != buflen)
- unpack_abort("short stream header");
+ int64_t nr = read_input_fn(u, buf, buflen, buflen);
+ if ((size_t)nr != buflen)
+ unpack_abort("short stream header");
}
diff --git a/libraries/pack200/src/zip.h b/libraries/pack200/src/zip.h
index 67ec24da..ff973a86 100644
--- a/libraries/pack200/src/zip.h
+++ b/libraries/pack200/src/zip.h
@@ -22,89 +22,91 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+#pragma once
+
#include <stdint.h>
typedef unsigned short ushort;
typedef unsigned int uint32_t;
typedef unsigned char uchar;
-struct unpacker;
+#include "unpack.h"
struct jar
{
- // JAR file writer
- FILE *jarfp;
- int default_modtime;
-
- // Used by unix2dostime:
- int modtime_cache;
- uint32_t dostime_cache;
-
- // Private members
- fillbytes central_directory;
- ushort central_directory_count;
- uint32_t output_file_offset;
- fillbytes deflated; // temporary buffer
-
- // pointer to outer unpacker, for error checks etc.
- unpacker *u;
-
- // Public Methods
- void openJarFile(const char *fname);
- void addJarEntry(const char *fname, bool deflate_hint, int modtime, bytes &head,
- bytes &tail);
- void addDirectoryToJarFile(const char *dir_name);
- void closeJarFile(bool central);
-
- void init(unpacker *u_);
-
- void free()
- {
- central_directory.free();
- deflated.free();
- }
-
- void reset()
- {
- free();
- init(u);
- }
-
- // Private Methods
- void write_data(void *ptr, int len);
- void write_data(bytes &b)
- {
- write_data(b.ptr, (int)b.len);
- }
- void add_to_jar_directory(const char *fname, bool store, int modtime, int len, int clen,
- uint32_t crc);
- void write_jar_header(const char *fname, bool store, int modtime, int len, int clen,
- unsigned int crc);
- void write_central_directory();
- uint32_t dostime(int y, int n, int d, int h, int m, int s);
- uint32_t get_dostime(int modtime);
-
- // The definitions of these depend on the NO_ZLIB option:
- bool deflate_bytes(bytes &head, bytes &tail);
- static uint32_t get_crc32(uint32_t c, unsigned char *ptr, uint32_t len);
+ // JAR file writer
+ FILE *jarfp;
+ int default_modtime;
+
+ // Used by unix2dostime:
+ int modtime_cache;
+ uint32_t dostime_cache;
+
+ // Private members
+ fillbytes central_directory;
+ ushort central_directory_count;
+ uint32_t output_file_offset;
+ fillbytes deflated; // temporary buffer
+
+ // pointer to outer unpacker, for error checks etc.
+ unpacker *u;
+
+ // Public Methods
+ void openJarFile(const char *fname);
+ void addJarEntry(const char *fname, bool deflate_hint, int modtime, bytes &head,
+ bytes &tail);
+ void addDirectoryToJarFile(const char *dir_name);
+ void closeJarFile(bool central);
+
+ void init(unpacker *u_);
+
+ void free()
+ {
+ central_directory.free();
+ deflated.free();
+ }
+
+ void reset()
+ {
+ free();
+ init(u);
+ }
+
+ // Private Methods
+ void write_data(void *ptr, int len);
+ void write_data(bytes &b)
+ {
+ write_data(b.ptr, (int)b.len);
+ }
+ void add_to_jar_directory(const char *fname, bool store, int modtime, int len, int clen,
+ uint32_t crc);
+ void write_jar_header(const char *fname, bool store, int modtime, int len, int clen,
+ unsigned int crc);
+ void write_central_directory();
+ uint32_t dostime(int y, int n, int d, int h, int m, int s);
+ uint32_t get_dostime(int modtime);
+
+ // The definitions of these depend on the NO_ZLIB option:
+ bool deflate_bytes(bytes &head, bytes &tail);
+ static uint32_t get_crc32(uint32_t c, unsigned char *ptr, uint32_t len);
};
struct gunzip
{
- // optional gzip input stream control block
+ // optional gzip input stream control block
- // pointer to outer unpacker, for error checks etc.
- unpacker *u;
+ // pointer to outer unpacker, for error checks etc.
+ unpacker *u;
- void *read_input_fn; // underlying \bchar\b stream
- void *zstream; // inflater state
- char inbuf[1 << 14]; // input buffer
+ read_input_fn_t read_input_fn; // underlying \bchar\b stream
+ void *zstream; // inflater state
+ char inbuf[1 << 14]; // input buffer
- void init(unpacker *u_); // pushes new value on u->read_input_fn
+ void init(unpacker *u_); // pushes new value on u->read_input_fn
- void free();
+ void free();
- void start(int magic);
+ void start(int magic);
- // private stuff
- void read_fixed_field(char *buf, size_t buflen);
+ // private stuff
+ void read_fixed_field(char *buf, size_t buflen);
};
diff --git a/libraries/quazip b/libraries/quazip
-Subproject 683e2ec8ada758d6e48d31ec606840802e6941b
+Subproject 3691d57d3af13f49b2be2b62accddefee3c26b9
diff --git a/libraries/rainbow/CMakeLists.txt b/libraries/rainbow/CMakeLists.txt
index bc561800..ad806faa 100644
--- a/libraries/rainbow/CMakeLists.txt
+++ b/libraries/rainbow/CMakeLists.txt
@@ -12,11 +12,11 @@ add_definitions(-DRAINBOW_LIBRARY)
add_library(MultiMC_rainbow SHARED ${RAINBOW_SOURCES})
target_include_directories(MultiMC_rainbow PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include")
-qt5_use_modules(MultiMC_rainbow Core Gui)
+target_link_libraries(MultiMC_rainbow Qt5::Core Qt5::Gui)
# Install it
install(
- TARGETS MultiMC_rainbow
- RUNTIME DESTINATION ${LIBRARY_DEST_DIR}
- LIBRARY DESTINATION ${LIBRARY_DEST_DIR}
+ TARGETS MultiMC_rainbow
+ RUNTIME DESTINATION ${LIBRARY_DEST_DIR}
+ LIBRARY DESTINATION ${LIBRARY_DEST_DIR}
)
diff --git a/libraries/rainbow/include/rainbow.h b/libraries/rainbow/include/rainbow.h
index b12052b1..67c46300 100644
--- a/libraries/rainbow/include/rainbow.h
+++ b/libraries/rainbow/include/rainbow.h
@@ -50,7 +50,7 @@ RAINBOW_EXPORT qreal luma(const QColor &);
* @since 5.0
*/
RAINBOW_EXPORT void getHcy(const QColor &, qreal *hue, qreal *chroma, qreal *luma,
- qreal *alpha = 0);
+ qreal *alpha = 0);
/**
* Calculate the contrast ratio between two colors, according to the
@@ -132,7 +132,7 @@ RAINBOW_EXPORT QColor tint(const QColor &base, const QColor &color, qreal amount
/**
* Blend two colors into a new color by linear combination.
* @code
- QColor lighter = Rainbow::mix(myColor, Qt::white)
+ QColor lighter = Rainbow::mix(myColor, Qt::white)
* @endcode
* @param c1 first color.
* @param c2 second color.
@@ -146,9 +146,9 @@ RAINBOW_EXPORT QColor mix(const QColor &c1, const QColor &c2, qreal bias = 0.5);
* Blend two colors into a new color by painting the second color over the
* first using the specified composition mode.
* @code
- QColor white(Qt::white);
- white.setAlphaF(0.5);
- QColor lighter = Rainbow::overlayColors(myColor, white);
+ QColor white(Qt::white);
+ white.setAlphaF(0.5);
+ QColor lighter = Rainbow::overlayColors(myColor, white);
@endcode
* @param base the base color (alpha channel is ignored).
* @param paint the color to be overlayed onto the base color.
@@ -156,5 +156,5 @@ RAINBOW_EXPORT QColor mix(const QColor &c1, const QColor &c2, qreal bias = 0.5);
*/
RAINBOW_EXPORT QColor
overlayColors(const QColor &base, const QColor &paint,
- QPainter::CompositionMode comp = QPainter::CompositionMode_SourceOver);
+ QPainter::CompositionMode comp = QPainter::CompositionMode_SourceOver);
}
diff --git a/libraries/rainbow/include/rainbow_config.h b/libraries/rainbow/include/rainbow_config.h
index 9290dc8a..6e467bc7 100644
--- a/libraries/rainbow/include/rainbow_config.h
+++ b/libraries/rainbow/include/rainbow_config.h
@@ -1,4 +1,4 @@
-/* Copyright 2013-2018 MultiMC Contributors
+/* Copyright 2013-2019 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,11 +16,11 @@
#include <QtCore/QtGlobal>
#ifdef RAINBOW_STATIC
- #define RAINBOW_EXPORT
+ #define RAINBOW_EXPORT
#else
- #ifdef RAINBOW_LIBRARY
- #define RAINBOW_EXPORT Q_DECL_EXPORT
- #else
- #define RAINBOW_EXPORT Q_DECL_IMPORT
- #endif
+ #ifdef RAINBOW_LIBRARY
+ #define RAINBOW_EXPORT Q_DECL_EXPORT
+ #else
+ #define RAINBOW_EXPORT Q_DECL_IMPORT
+ #endif
#endif \ No newline at end of file
diff --git a/libraries/rainbow/src/rainbow.cpp b/libraries/rainbow/src/rainbow.cpp
index 8502fcd0..9054d71d 100644
--- a/libraries/rainbow/src/rainbow.cpp
+++ b/libraries/rainbow/src/rainbow.cpp
@@ -33,8 +33,8 @@
static inline qreal wrap(qreal a, qreal d = 1.0)
{
- qreal r = fmod(a, d);
- return (r < 0.0 ? d + r : (r > 0.0 ? r : 0.0));
+ qreal r = fmod(a, d);
+ return (r < 0.0 ? d + r : (r > 0.0 ? r : 0.0));
}
// normalize: like qBound(a, 0.0, 1.0) but without needing the args and with
@@ -60,306 +60,306 @@ static const qreal yc[3] = {0.34375, 0.5, 0.15625};
class KHCY
{
public:
- explicit KHCY(const QColor &color)
- {
- qreal r = gamma(color.redF());
- qreal g = gamma(color.greenF());
- qreal b = gamma(color.blueF());
- a = color.alphaF();
-
- // luma component
- y = lumag(r, g, b);
-
- // hue component
- qreal p = qMax(qMax(r, g), b);
- qreal n = qMin(qMin(r, g), b);
- qreal d = 6.0 * (p - n);
- if (n == p)
- {
- h = 0.0;
- }
- else if (r == p)
- {
- h = ((g - b) / d);
- }
- else if (g == p)
- {
- h = ((b - r) / d) + (1.0 / 3.0);
- }
- else
- {
- h = ((r - g) / d) + (2.0 / 3.0);
- }
-
- // chroma component
- if (r == g && g == b)
- {
- c = 0.0;
- }
- else
- {
- c = qMax((y - n) / y, (p - y) / (1 - y));
- }
- }
- explicit KHCY(qreal h_, qreal c_, qreal y_, qreal a_ = 1.0)
- {
- h = h_;
- c = c_;
- y = y_;
- a = a_;
- }
-
- QColor qColor() const
- {
- // start with sane component values
- qreal _h = wrap(h);
- qreal _c = normalize(c);
- qreal _y = normalize(y);
-
- // calculate some needed variables
- qreal _hs = _h * 6.0, th, tm;
- if (_hs < 1.0)
- {
- th = _hs;
- tm = yc[0] + yc[1] * th;
- }
- else if (_hs < 2.0)
- {
- th = 2.0 - _hs;
- tm = yc[1] + yc[0] * th;
- }
- else if (_hs < 3.0)
- {
- th = _hs - 2.0;
- tm = yc[1] + yc[2] * th;
- }
- else if (_hs < 4.0)
- {
- th = 4.0 - _hs;
- tm = yc[2] + yc[1] * th;
- }
- else if (_hs < 5.0)
- {
- th = _hs - 4.0;
- tm = yc[2] + yc[0] * th;
- }
- else
- {
- th = 6.0 - _hs;
- tm = yc[0] + yc[2] * th;
- }
-
- // calculate RGB channels in sorted order
- qreal tn, to, tp;
- if (tm >= _y)
- {
- tp = _y + _y * _c * (1.0 - tm) / tm;
- to = _y + _y * _c * (th - tm) / tm;
- tn = _y - (_y * _c);
- }
- else
- {
- tp = _y + (1.0 - _y) * _c;
- to = _y + (1.0 - _y) * _c * (th - tm) / (1.0 - tm);
- tn = _y - (1.0 - _y) * _c * tm / (1.0 - tm);
- }
-
- // return RGB channels in appropriate order
- if (_hs < 1.0)
- {
- return QColor::fromRgbF(igamma(tp), igamma(to), igamma(tn), a);
- }
- else if (_hs < 2.0)
- {
- return QColor::fromRgbF(igamma(to), igamma(tp), igamma(tn), a);
- }
- else if (_hs < 3.0)
- {
- return QColor::fromRgbF(igamma(tn), igamma(tp), igamma(to), a);
- }
- else if (_hs < 4.0)
- {
- return QColor::fromRgbF(igamma(tn), igamma(to), igamma(tp), a);
- }
- else if (_hs < 5.0)
- {
- return QColor::fromRgbF(igamma(to), igamma(tn), igamma(tp), a);
- }
- else
- {
- return QColor::fromRgbF(igamma(tp), igamma(tn), igamma(to), a);
- }
- }
-
- qreal h, c, y, a;
- static qreal luma(const QColor &color)
- {
- return lumag(gamma(color.redF()), gamma(color.greenF()), gamma(color.blueF()));
- }
+ explicit KHCY(const QColor &color)
+ {
+ qreal r = gamma(color.redF());
+ qreal g = gamma(color.greenF());
+ qreal b = gamma(color.blueF());
+ a = color.alphaF();
+
+ // luma component
+ y = lumag(r, g, b);
+
+ // hue component
+ qreal p = qMax(qMax(r, g), b);
+ qreal n = qMin(qMin(r, g), b);
+ qreal d = 6.0 * (p - n);
+ if (n == p)
+ {
+ h = 0.0;
+ }
+ else if (r == p)
+ {
+ h = ((g - b) / d);
+ }
+ else if (g == p)
+ {
+ h = ((b - r) / d) + (1.0 / 3.0);
+ }
+ else
+ {
+ h = ((r - g) / d) + (2.0 / 3.0);
+ }
+
+ // chroma component
+ if (r == g && g == b)
+ {
+ c = 0.0;
+ }
+ else
+ {
+ c = qMax((y - n) / y, (p - y) / (1 - y));
+ }
+ }
+ explicit KHCY(qreal h_, qreal c_, qreal y_, qreal a_ = 1.0)
+ {
+ h = h_;
+ c = c_;
+ y = y_;
+ a = a_;
+ }
+
+ QColor qColor() const
+ {
+ // start with sane component values
+ qreal _h = wrap(h);
+ qreal _c = normalize(c);
+ qreal _y = normalize(y);
+
+ // calculate some needed variables
+ qreal _hs = _h * 6.0, th, tm;
+ if (_hs < 1.0)
+ {
+ th = _hs;
+ tm = yc[0] + yc[1] * th;
+ }
+ else if (_hs < 2.0)
+ {
+ th = 2.0 - _hs;
+ tm = yc[1] + yc[0] * th;
+ }
+ else if (_hs < 3.0)
+ {
+ th = _hs - 2.0;
+ tm = yc[1] + yc[2] * th;
+ }
+ else if (_hs < 4.0)
+ {
+ th = 4.0 - _hs;
+ tm = yc[2] + yc[1] * th;
+ }
+ else if (_hs < 5.0)
+ {
+ th = _hs - 4.0;
+ tm = yc[2] + yc[0] * th;
+ }
+ else
+ {
+ th = 6.0 - _hs;
+ tm = yc[0] + yc[2] * th;
+ }
+
+ // calculate RGB channels in sorted order
+ qreal tn, to, tp;
+ if (tm >= _y)
+ {
+ tp = _y + _y * _c * (1.0 - tm) / tm;
+ to = _y + _y * _c * (th - tm) / tm;
+ tn = _y - (_y * _c);
+ }
+ else
+ {
+ tp = _y + (1.0 - _y) * _c;
+ to = _y + (1.0 - _y) * _c * (th - tm) / (1.0 - tm);
+ tn = _y - (1.0 - _y) * _c * tm / (1.0 - tm);
+ }
+
+ // return RGB channels in appropriate order
+ if (_hs < 1.0)
+ {
+ return QColor::fromRgbF(igamma(tp), igamma(to), igamma(tn), a);
+ }
+ else if (_hs < 2.0)
+ {
+ return QColor::fromRgbF(igamma(to), igamma(tp), igamma(tn), a);
+ }
+ else if (_hs < 3.0)
+ {
+ return QColor::fromRgbF(igamma(tn), igamma(tp), igamma(to), a);
+ }
+ else if (_hs < 4.0)
+ {
+ return QColor::fromRgbF(igamma(tn), igamma(to), igamma(tp), a);
+ }
+ else if (_hs < 5.0)
+ {
+ return QColor::fromRgbF(igamma(to), igamma(tn), igamma(tp), a);
+ }
+ else
+ {
+ return QColor::fromRgbF(igamma(tp), igamma(tn), igamma(to), a);
+ }
+ }
+
+ qreal h, c, y, a;
+ static qreal luma(const QColor &color)
+ {
+ return lumag(gamma(color.redF()), gamma(color.greenF()), gamma(color.blueF()));
+ }
private:
- static qreal gamma(qreal n)
- {
- return pow(normalize(n), 2.2);
- }
- static qreal igamma(qreal n)
- {
- return pow(normalize(n), 1.0 / 2.2);
- }
- static qreal lumag(qreal r, qreal g, qreal b)
- {
- return r * yc[0] + g * yc[1] + b * yc[2];
- }
+ static qreal gamma(qreal n)
+ {
+ return pow(normalize(n), 2.2);
+ }
+ static qreal igamma(qreal n)
+ {
+ return pow(normalize(n), 1.0 / 2.2);
+ }
+ static qreal lumag(qreal r, qreal g, qreal b)
+ {
+ return r * yc[0] + g * yc[1] + b * yc[2];
+ }
};
static inline qreal mixQreal(qreal a, qreal b, qreal bias)
{
- return a + (b - a) * bias;
+ return a + (b - a) * bias;
}
//END internal helper functions
qreal Rainbow::luma(const QColor &color)
{
- return KHCY::luma(color);
+ return KHCY::luma(color);
}
void Rainbow::getHcy(const QColor &color, qreal *h, qreal *c, qreal *y, qreal *a)
{
- if (!c || !h || !y)
- {
- return;
- }
- KHCY khcy(color);
- *c = khcy.c;
- *h = khcy.h;
- *y = khcy.y;
- if (a)
- {
- *a = khcy.a;
- }
+ if (!c || !h || !y)
+ {
+ return;
+ }
+ KHCY khcy(color);
+ *c = khcy.c;
+ *h = khcy.h;
+ *y = khcy.y;
+ if (a)
+ {
+ *a = khcy.a;
+ }
}
static qreal contrastRatioForLuma(qreal y1, qreal y2)
{
- if (y1 > y2)
- {
- return (y1 + 0.05) / (y2 + 0.05);
- }
- else
- {
- return (y2 + 0.05) / (y1 + 0.05);
- }
+ if (y1 > y2)
+ {
+ return (y1 + 0.05) / (y2 + 0.05);
+ }
+ else
+ {
+ return (y2 + 0.05) / (y1 + 0.05);
+ }
}
qreal Rainbow::contrastRatio(const QColor &c1, const QColor &c2)
{
- return contrastRatioForLuma(luma(c1), luma(c2));
+ return contrastRatioForLuma(luma(c1), luma(c2));
}
QColor Rainbow::lighten(const QColor &color, qreal ky, qreal kc)
{
- KHCY c(color);
- c.y = 1.0 - normalize((1.0 - c.y) * (1.0 - ky));
- c.c = 1.0 - normalize((1.0 - c.c) * kc);
- return c.qColor();
+ KHCY c(color);
+ c.y = 1.0 - normalize((1.0 - c.y) * (1.0 - ky));
+ c.c = 1.0 - normalize((1.0 - c.c) * kc);
+ return c.qColor();
}
QColor Rainbow::darken(const QColor &color, qreal ky, qreal kc)
{
- KHCY c(color);
- c.y = normalize(c.y * (1.0 - ky));
- c.c = normalize(c.c * kc);
- return c.qColor();
+ KHCY c(color);
+ c.y = normalize(c.y * (1.0 - ky));
+ c.c = normalize(c.c * kc);
+ return c.qColor();
}
QColor Rainbow::shade(const QColor &color, qreal ky, qreal kc)
{
- KHCY c(color);
- c.y = normalize(c.y + ky);
- c.c = normalize(c.c + kc);
- return c.qColor();
+ KHCY c(color);
+ c.y = normalize(c.y + ky);
+ c.c = normalize(c.c + kc);
+ return c.qColor();
}
static QColor tintHelper(const QColor &base, qreal baseLuma, const QColor &color, qreal amount)
{
- KHCY result(Rainbow::mix(base, color, pow(amount, 0.3)));
- result.y = mixQreal(baseLuma, result.y, amount);
+ KHCY result(Rainbow::mix(base, color, pow(amount, 0.3)));
+ result.y = mixQreal(baseLuma, result.y, amount);
- return result.qColor();
+ return result.qColor();
}
QColor Rainbow::tint(const QColor &base, const QColor &color, qreal amount)
{
- if (amount <= 0.0)
- {
- return base;
- }
- if (amount >= 1.0)
- {
- return color;
- }
- if (qIsNaN(amount))
- {
- return base;
- }
-
- qreal baseLuma = luma(base); // cache value because luma call is expensive
- double ri = contrastRatioForLuma(baseLuma, luma(color));
- double rg = 1.0 + ((ri + 1.0) * amount * amount * amount);
- double u = 1.0, l = 0.0;
- QColor result;
- for (int i = 12; i; --i)
- {
- double a = 0.5 * (l + u);
- result = tintHelper(base, baseLuma, color, a);
- double ra = contrastRatioForLuma(baseLuma, luma(result));
- if (ra > rg)
- {
- u = a;
- }
- else
- {
- l = a;
- }
- }
- return result;
+ if (amount <= 0.0)
+ {
+ return base;
+ }
+ if (amount >= 1.0)
+ {
+ return color;
+ }
+ if (qIsNaN(amount))
+ {
+ return base;
+ }
+
+ qreal baseLuma = luma(base); // cache value because luma call is expensive
+ double ri = contrastRatioForLuma(baseLuma, luma(color));
+ double rg = 1.0 + ((ri + 1.0) * amount * amount * amount);
+ double u = 1.0, l = 0.0;
+ QColor result;
+ for (int i = 12; i; --i)
+ {
+ double a = 0.5 * (l + u);
+ result = tintHelper(base, baseLuma, color, a);
+ double ra = contrastRatioForLuma(baseLuma, luma(result));
+ if (ra > rg)
+ {
+ u = a;
+ }
+ else
+ {
+ l = a;
+ }
+ }
+ return result;
}
QColor Rainbow::mix(const QColor &c1, const QColor &c2, qreal bias)
{
- if (bias <= 0.0)
- {
- return c1;
- }
- if (bias >= 1.0)
- {
- return c2;
- }
- if (qIsNaN(bias))
- {
- return c1;
- }
-
- qreal r = mixQreal(c1.redF(), c2.redF(), bias);
- qreal g = mixQreal(c1.greenF(), c2.greenF(), bias);
- qreal b = mixQreal(c1.blueF(), c2.blueF(), bias);
- qreal a = mixQreal(c1.alphaF(), c2.alphaF(), bias);
-
- return QColor::fromRgbF(r, g, b, a);
+ if (bias <= 0.0)
+ {
+ return c1;
+ }
+ if (bias >= 1.0)
+ {
+ return c2;
+ }
+ if (qIsNaN(bias))
+ {
+ return c1;
+ }
+
+ qreal r = mixQreal(c1.redF(), c2.redF(), bias);
+ qreal g = mixQreal(c1.greenF(), c2.greenF(), bias);
+ qreal b = mixQreal(c1.blueF(), c2.blueF(), bias);
+ qreal a = mixQreal(c1.alphaF(), c2.alphaF(), bias);
+
+ return QColor::fromRgbF(r, g, b, a);
}
QColor Rainbow::overlayColors(const QColor &base, const QColor &paint,
- QPainter::CompositionMode comp)
+ QPainter::CompositionMode comp)
{
- // This isn't the fastest way, but should be "fast enough".
- // It's also the only safe way to use QPainter::CompositionMode
- QImage img(1, 1, QImage::Format_ARGB32_Premultiplied);
- QPainter p(&img);
- QColor start = base;
- start.setAlpha(255); // opaque
- p.fillRect(0, 0, 1, 1, start);
- p.setCompositionMode(comp);
- p.fillRect(0, 0, 1, 1, paint);
- p.end();
- return img.pixel(0, 0);
+ // This isn't the fastest way, but should be "fast enough".
+ // It's also the only safe way to use QPainter::CompositionMode
+ QImage img(1, 1, QImage::Format_ARGB32_Premultiplied);
+ QPainter p(&img);
+ QColor start = base;
+ start.setAlpha(255); // opaque
+ p.fillRect(0, 0, 1, 1, start);
+ p.setCompositionMode(comp);
+ p.fillRect(0, 0, 1, 1, paint);
+ p.end();
+ return img.pixel(0, 0);
}
diff --git a/libraries/systeminfo/CMakeLists.txt b/libraries/systeminfo/CMakeLists.txt
index 393b5318..548a589c 100644
--- a/libraries/systeminfo/CMakeLists.txt
+++ b/libraries/systeminfo/CMakeLists.txt
@@ -9,21 +9,21 @@ src/distroutils.cpp
)
if (WIN32)
- list(APPEND systeminfo_SOURCES src/sys_win32.cpp)
+ list(APPEND systeminfo_SOURCES src/sys_win32.cpp)
elseif (UNIX)
- if(APPLE)
- list(APPEND systeminfo_SOURCES src/sys_apple.cpp)
- else()
- list(APPEND systeminfo_SOURCES src/sys_unix.cpp)
- endif()
+ if(APPLE)
+ list(APPEND systeminfo_SOURCES src/sys_apple.cpp)
+ else()
+ list(APPEND systeminfo_SOURCES src/sys_unix.cpp)
+ endif()
endif()
add_library(systeminfo STATIC ${systeminfo_SOURCES})
-qt5_use_modules(systeminfo Core Gui Network)
+target_link_libraries(systeminfo Qt5::Core Qt5::Gui Qt5::Network)
target_include_directories(systeminfo PUBLIC include)
include (UnitTest)
add_unit_test(sys
- SOURCES src/sys_test.cpp
- LIBS systeminfo
+ SOURCES src/sys_test.cpp
+ LIBS systeminfo
)
diff --git a/libraries/systeminfo/include/distroutils.h b/libraries/systeminfo/include/distroutils.h
index 5ff8d591..2e85f433 100644
--- a/libraries/systeminfo/include/distroutils.h
+++ b/libraries/systeminfo/include/distroutils.h
@@ -4,10 +4,10 @@
namespace Sys {
struct LsbInfo
{
- QString distributor;
- QString version;
- QString description;
- QString codename;
+ QString distributor;
+ QString version;
+ QString description;
+ QString codename;
};
bool main_lsb_info(LsbInfo & out);
diff --git a/libraries/systeminfo/include/sys.h b/libraries/systeminfo/include/sys.h
index c573eb53..7980dfdf 100644
--- a/libraries/systeminfo/include/sys.h
+++ b/libraries/systeminfo/include/sys.h
@@ -6,37 +6,37 @@ namespace Sys
const uint64_t megabyte = 1024ull * 1024ull;
struct KernelInfo
{
- QString kernelName;
- QString kernelVersion;
+ QString kernelName;
+ QString kernelVersion;
};
KernelInfo getKernelInfo();
struct DistributionInfo
{
- DistributionInfo operator+(const DistributionInfo& rhs) const
- {
- DistributionInfo out;
- if(!distributionName.isEmpty())
- {
- out.distributionName = distributionName;
- }
- else
- {
- out.distributionName = rhs.distributionName;
- }
- if(!distributionVersion.isEmpty())
- {
- out.distributionVersion = distributionVersion;
- }
- else
- {
- out.distributionVersion = rhs.distributionVersion;
- }
- return out;
- }
- QString distributionName;
- QString distributionVersion;
+ DistributionInfo operator+(const DistributionInfo& rhs) const
+ {
+ DistributionInfo out;
+ if(!distributionName.isEmpty())
+ {
+ out.distributionName = distributionName;
+ }
+ else
+ {
+ out.distributionName = rhs.distributionName;
+ }
+ if(!distributionVersion.isEmpty())
+ {
+ out.distributionVersion = distributionVersion;
+ }
+ else
+ {
+ out.distributionVersion = rhs.distributionVersion;
+ }
+ return out;
+ }
+ QString distributionName;
+ QString distributionVersion;
};
DistributionInfo getDistributionInfo();
diff --git a/libraries/systeminfo/src/distroutils.cpp b/libraries/systeminfo/src/distroutils.cpp
index cdba05d0..fb9ae25d 100644
--- a/libraries/systeminfo/src/distroutils.cpp
+++ b/libraries/systeminfo/src/distroutils.cpp
@@ -41,243 +41,243 @@ SOFTWARE.
Sys::DistributionInfo Sys::read_os_release()
{
- Sys::DistributionInfo out;
- QStringList files = { "/etc/os-release", "/usr/lib/os-release" };
- QString name;
- QString version;
- for (auto &file: files)
- {
- if(!QFile::exists(file))
- {
- continue;
- }
- QSettings settings(file, QSettings::IniFormat);
- if(settings.contains("ID"))
- {
- name = settings.value("ID").toString().toLower();
- }
- else if (settings.contains("NAME"))
- {
- name = settings.value("NAME").toString().toLower();
- }
- else
- {
- continue;
- }
+ Sys::DistributionInfo out;
+ QStringList files = { "/etc/os-release", "/usr/lib/os-release" };
+ QString name;
+ QString version;
+ for (auto &file: files)
+ {
+ if(!QFile::exists(file))
+ {
+ continue;
+ }
+ QSettings settings(file, QSettings::IniFormat);
+ if(settings.contains("ID"))
+ {
+ name = settings.value("ID").toString().toLower();
+ }
+ else if (settings.contains("NAME"))
+ {
+ name = settings.value("NAME").toString().toLower();
+ }
+ else
+ {
+ continue;
+ }
- if(settings.contains("VERSION_ID"))
- {
- version = settings.value("VERSION_ID").toString().toLower();
- }
- else if(settings.contains("VERSION"))
- {
- version = settings.value("VERSION").toString().toLower();
- }
- break;
- }
- if(name.isEmpty())
- {
- return out;
- }
- out.distributionName = name;
- out.distributionVersion = version;
- return out;
+ if(settings.contains("VERSION_ID"))
+ {
+ version = settings.value("VERSION_ID").toString().toLower();
+ }
+ else if(settings.contains("VERSION"))
+ {
+ version = settings.value("VERSION").toString().toLower();
+ }
+ break;
+ }
+ if(name.isEmpty())
+ {
+ return out;
+ }
+ out.distributionName = name;
+ out.distributionVersion = version;
+ return out;
}
bool Sys::main_lsb_info(Sys::LsbInfo & out)
{
- int status=0;
- QProcess lsbProcess;
- lsbProcess.start("lsb_release -a");
- lsbProcess.waitForFinished();
- status = lsbProcess.exitStatus();
- QString output = lsbProcess.readAllStandardOutput();
- qDebug() << output;
- lsbProcess.close();
- if(status == 0)
- {
- auto lines = output.split('\n');
- for(auto line:lines)
- {
- int index = line.indexOf(':');
- auto key = line.left(index).trimmed();
- auto value = line.mid(index + 1).toLower().trimmed();
- if(key == "Distributor ID")
- out.distributor = value;
- else if(key == "Release")
- out.version = value;
- else if(key == "Description")
- out.description = value;
- else if(key == "Codename")
- out.codename = value;
- }
- return !out.distributor.isEmpty();
- }
- return false;
+ int status=0;
+ QProcess lsbProcess;
+ lsbProcess.start("lsb_release -a");
+ lsbProcess.waitForFinished();
+ status = lsbProcess.exitStatus();
+ QString output = lsbProcess.readAllStandardOutput();
+ qDebug() << output;
+ lsbProcess.close();
+ if(status == 0)
+ {
+ auto lines = output.split('\n');
+ for(auto line:lines)
+ {
+ int index = line.indexOf(':');
+ auto key = line.left(index).trimmed();
+ auto value = line.mid(index + 1).toLower().trimmed();
+ if(key == "Distributor ID")
+ out.distributor = value;
+ else if(key == "Release")
+ out.version = value;
+ else if(key == "Description")
+ out.description = value;
+ else if(key == "Codename")
+ out.codename = value;
+ }
+ return !out.distributor.isEmpty();
+ }
+ return false;
}
bool Sys::fallback_lsb_info(Sys::LsbInfo & out)
{
- // running lsb_release failed, try to read the file instead
- // /etc/lsb-release format, if the file even exists, is non-standard.
- // Only the `lsb_release` command is specified by LSB. Nonetheless, some
- // distributions install an /etc/lsb-release as part of the base
- // distribution, but `lsb_release` remains optional.
- QString file = "/etc/lsb-release";
- if (QFile::exists(file))
- {
- QSettings settings(file, QSettings::IniFormat);
- if(settings.contains("DISTRIB_ID"))
- {
- out.distributor = settings.value("DISTRIB_ID").toString().toLower();
- }
- if(settings.contains("DISTRIB_RELEASE"))
- {
- out.version = settings.value("DISTRIB_RELEASE").toString().toLower();
- }
- return !out.distributor.isEmpty();
- }
- return false;
+ // running lsb_release failed, try to read the file instead
+ // /etc/lsb-release format, if the file even exists, is non-standard.
+ // Only the `lsb_release` command is specified by LSB. Nonetheless, some
+ // distributions install an /etc/lsb-release as part of the base
+ // distribution, but `lsb_release` remains optional.
+ QString file = "/etc/lsb-release";
+ if (QFile::exists(file))
+ {
+ QSettings settings(file, QSettings::IniFormat);
+ if(settings.contains("DISTRIB_ID"))
+ {
+ out.distributor = settings.value("DISTRIB_ID").toString().toLower();
+ }
+ if(settings.contains("DISTRIB_RELEASE"))
+ {
+ out.version = settings.value("DISTRIB_RELEASE").toString().toLower();
+ }
+ return !out.distributor.isEmpty();
+ }
+ return false;
}
void Sys::lsb_postprocess(Sys::LsbInfo & lsb, Sys::DistributionInfo & out)
{
- QString dist = lsb.distributor;
- QString vers = lsb.version;
- if(dist.startsWith("redhatenterprise"))
- {
- dist = "rhel";
- }
- else if(dist == "archlinux")
- {
- dist = "arch";
- }
- else if (dist.startsWith("suse"))
- {
- if(lsb.description.startsWith("opensuse"))
- {
- dist = "opensuse";
- }
- else if (lsb.description.startsWith("suse linux enterprise"))
- {
- dist = "sles";
- }
- }
- else if (dist == "debian" and vers == "testing")
- {
- vers = lsb.codename;
- }
- else
- {
- // ubuntu, debian, gentoo, scientific, slackware, ... ?
- auto parts = dist.split(QRegExp("\\s+"), QString::SkipEmptyParts);
- if(parts.size())
- {
- dist = parts[0];
- }
- }
- if(!dist.isEmpty())
- {
- out.distributionName = dist;
- out.distributionVersion = vers;
- }
+ QString dist = lsb.distributor;
+ QString vers = lsb.version;
+ if(dist.startsWith("redhatenterprise"))
+ {
+ dist = "rhel";
+ }
+ else if(dist == "archlinux")
+ {
+ dist = "arch";
+ }
+ else if (dist.startsWith("suse"))
+ {
+ if(lsb.description.startsWith("opensuse"))
+ {
+ dist = "opensuse";
+ }
+ else if (lsb.description.startsWith("suse linux enterprise"))
+ {
+ dist = "sles";
+ }
+ }
+ else if (dist == "debian" and vers == "testing")
+ {
+ vers = lsb.codename;
+ }
+ else
+ {
+ // ubuntu, debian, gentoo, scientific, slackware, ... ?
+ auto parts = dist.split(QRegExp("\\s+"), QString::SkipEmptyParts);
+ if(parts.size())
+ {
+ dist = parts[0];
+ }
+ }
+ if(!dist.isEmpty())
+ {
+ out.distributionName = dist;
+ out.distributionVersion = vers;
+ }
}
Sys::DistributionInfo Sys::read_lsb_release()
{
- LsbInfo lsb;
- if(!main_lsb_info(lsb))
- {
- if(!fallback_lsb_info(lsb))
- {
- return Sys::DistributionInfo();
- }
- }
- Sys::DistributionInfo out;
- lsb_postprocess(lsb, out);
- return out;
+ LsbInfo lsb;
+ if(!main_lsb_info(lsb))
+ {
+ if(!fallback_lsb_info(lsb))
+ {
+ return Sys::DistributionInfo();
+ }
+ }
+ Sys::DistributionInfo out;
+ lsb_postprocess(lsb, out);
+ return out;
}
QString Sys::_extract_distribution(const QString & x)
{
- QString release = x.toLower();
- if (release.startsWith("red hat enterprise"))
- {
- return "rhel";
- }
- if (release.startsWith("suse linux enterprise"))
- {
- return "sles";
- }
- QStringList list = release.split(QRegExp("\\s+"), QString::SkipEmptyParts);
- if(list.size())
- {
- return list[0];
- }
- return QString();
+ QString release = x.toLower();
+ if (release.startsWith("red hat enterprise"))
+ {
+ return "rhel";
+ }
+ if (release.startsWith("suse linux enterprise"))
+ {
+ return "sles";
+ }
+ QStringList list = release.split(QRegExp("\\s+"), QString::SkipEmptyParts);
+ if(list.size())
+ {
+ return list[0];
+ }
+ return QString();
}
QString Sys::_extract_version(const QString & x)
{
- QRegExp versionish_string("\\d+(?:\\.\\d+)*$");
- QStringList list = x.split(QRegExp("\\s+"), QString::SkipEmptyParts);
- for(int i = list.size() - 1; i >= 0; --i)
- {
- QString chunk = list[i];
- if(versionish_string.exactMatch(chunk))
- {
- return chunk;
- }
- }
- return QString();
+ QRegExp versionish_string("\\d+(?:\\.\\d+)*$");
+ QStringList list = x.split(QRegExp("\\s+"), QString::SkipEmptyParts);
+ for(int i = list.size() - 1; i >= 0; --i)
+ {
+ QString chunk = list[i];
+ if(versionish_string.exactMatch(chunk))
+ {
+ return chunk;
+ }
+ }
+ return QString();
}
Sys::DistributionInfo Sys::read_legacy_release()
{
- struct checkEntry
- {
- QString file;
- std::function<QString(const QString &)> extract_distro;
- std::function<QString(const QString &)> extract_version;
- };
- QList<checkEntry> checks =
- {
- {"/etc/arch-release", [](const QString &){ return "arch";}, [](const QString &){ return "rolling";}},
- {"/etc/slackware-version", &Sys::_extract_distribution, &Sys::_extract_version},
- {QString(), &Sys::_extract_distribution, &Sys::_extract_version},
- {"/etc/debian_version", [](const QString &){ return "debian";}, [](const QString & x){ return x;}},
- };
- for(auto & check: checks)
- {
- QStringList files;
- if(check.file.isNull())
- {
- QDir etcDir("/etc");
- etcDir.setNameFilters({"*-release"});
- etcDir.setFilter(QDir::Files | QDir::NoDot | QDir::NoDotDot | QDir::Readable | QDir::Hidden);
- files = etcDir.entryList();
- }
- else
- {
- files.append(check.file);
- }
- for (auto file : files)
- {
- QFile relfile(file);
- if(!relfile.open(QIODevice::ReadOnly | QIODevice::Text))
- continue;
- QString contents = QString::fromUtf8(relfile.readLine()).trimmed();
- QString dist = check.extract_distro(contents);
- QString vers = check.extract_version(contents);
- if(!dist.isEmpty())
- {
- Sys::DistributionInfo out;
- out.distributionName = dist;
- out.distributionVersion = vers;
- return out;
- }
- }
- }
- return Sys::DistributionInfo();
+ struct checkEntry
+ {
+ QString file;
+ std::function<QString(const QString &)> extract_distro;
+ std::function<QString(const QString &)> extract_version;
+ };
+ QList<checkEntry> checks =
+ {
+ {"/etc/arch-release", [](const QString &){ return "arch";}, [](const QString &){ return "rolling";}},
+ {"/etc/slackware-version", &Sys::_extract_distribution, &Sys::_extract_version},
+ {QString(), &Sys::_extract_distribution, &Sys::_extract_version},
+ {"/etc/debian_version", [](const QString &){ return "debian";}, [](const QString & x){ return x;}},
+ };
+ for(auto & check: checks)
+ {
+ QStringList files;
+ if(check.file.isNull())
+ {
+ QDir etcDir("/etc");
+ etcDir.setNameFilters({"*-release"});
+ etcDir.setFilter(QDir::Files | QDir::NoDot | QDir::NoDotDot | QDir::Readable | QDir::Hidden);
+ files = etcDir.entryList();
+ }
+ else
+ {
+ files.append(check.file);
+ }
+ for (auto file : files)
+ {
+ QFile relfile(file);
+ if(!relfile.open(QIODevice::ReadOnly | QIODevice::Text))
+ continue;
+ QString contents = QString::fromUtf8(relfile.readLine()).trimmed();
+ QString dist = check.extract_distro(contents);
+ QString vers = check.extract_version(contents);
+ if(!dist.isEmpty())
+ {
+ Sys::DistributionInfo out;
+ out.distributionName = dist;
+ out.distributionVersion = vers;
+ return out;
+ }
+ }
+ }
+ return Sys::DistributionInfo();
}
diff --git a/libraries/systeminfo/src/sys_apple.cpp b/libraries/systeminfo/src/sys_apple.cpp
index 62e6037d..4bcffae4 100644
--- a/libraries/systeminfo/src/sys_apple.cpp
+++ b/libraries/systeminfo/src/sys_apple.cpp
@@ -4,44 +4,44 @@
Sys::KernelInfo Sys::getKernelInfo()
{
- Sys::KernelInfo out;
- struct utsname buf;
- uname(&buf);
- out.kernelName = buf.sysname;
- out.kernelVersion = buf.release;
- return out;
+ Sys::KernelInfo out;
+ struct utsname buf;
+ uname(&buf);
+ out.kernelName = buf.sysname;
+ out.kernelVersion = buf.release;
+ return out;
}
#include <sys/sysctl.h>
uint64_t Sys::getSystemRam()
{
- uint64_t memsize;
- size_t memsizesize = sizeof(memsize);
- if(!sysctlbyname("hw.memsize", &memsize, &memsizesize, NULL, 0))
- {
- return memsize;
- }
- else
- {
- return 0;
- }
+ uint64_t memsize;
+ size_t memsizesize = sizeof(memsize);
+ if(!sysctlbyname("hw.memsize", &memsize, &memsizesize, NULL, 0))
+ {
+ return memsize;
+ }
+ else
+ {
+ return 0;
+ }
}
bool Sys::isCPU64bit()
{
- // not even going to pretend I'm going to support anything else
- return true;
+ // not even going to pretend I'm going to support anything else
+ return true;
}
bool Sys::isSystem64bit()
{
- // yep. maybe when we have 128bit CPUs on consumer devices.
- return true;
+ // yep. maybe when we have 128bit CPUs on consumer devices.
+ return true;
}
Sys::DistributionInfo Sys::getDistributionInfo()
{
- DistributionInfo result;
- return result;
+ DistributionInfo result;
+ return result;
}
diff --git a/libraries/systeminfo/src/sys_test.cpp b/libraries/systeminfo/src/sys_test.cpp
index 5888e02b..315050d2 100644
--- a/libraries/systeminfo/src/sys_test.cpp
+++ b/libraries/systeminfo/src/sys_test.cpp
@@ -5,24 +5,24 @@
class SysTest : public QObject
{
- Q_OBJECT
+ Q_OBJECT
private
slots:
- void test_kernelNotNull()
- {
- auto kinfo = Sys::getKernelInfo();
- QVERIFY(!kinfo.kernelName.isEmpty());
- QVERIFY(kinfo.kernelVersion != "0.0");
- }
+ void test_kernelNotNull()
+ {
+ auto kinfo = Sys::getKernelInfo();
+ QVERIFY(!kinfo.kernelName.isEmpty());
+ QVERIFY(kinfo.kernelVersion != "0.0");
+ }
/*
- void test_systemDistroNotNull()
- {
- auto kinfo = Sys::getDistributionInfo();
- QVERIFY(!kinfo.distributionName.isEmpty());
- QVERIFY(!kinfo.distributionVersion.isEmpty());
- qDebug() << "Distro: " << kinfo.distributionName << "version" << kinfo.distributionVersion;
- }
+ void test_systemDistroNotNull()
+ {
+ auto kinfo = Sys::getDistributionInfo();
+ QVERIFY(!kinfo.distributionName.isEmpty());
+ QVERIFY(!kinfo.distributionVersion.isEmpty());
+ qDebug() << "Distro: " << kinfo.distributionName << "version" << kinfo.distributionVersion;
+ }
*/
};
diff --git a/libraries/systeminfo/src/sys_unix.cpp b/libraries/systeminfo/src/sys_unix.cpp
index 313908f3..ab3f302e 100644
--- a/libraries/systeminfo/src/sys_unix.cpp
+++ b/libraries/systeminfo/src/sys_unix.cpp
@@ -7,69 +7,69 @@
Sys::KernelInfo Sys::getKernelInfo()
{
- Sys::KernelInfo out;
- struct utsname buf;
- uname(&buf);
- out.kernelName = buf.sysname;
- out.kernelVersion = buf.release;
- return out;
+ Sys::KernelInfo out;
+ struct utsname buf;
+ uname(&buf);
+ out.kernelName = buf.sysname;
+ out.kernelVersion = buf.release;
+ return out;
}
uint64_t Sys::getSystemRam()
{
- std::string token;
- std::ifstream file("/proc/meminfo");
- while(file >> token)
- {
- if(token == "MemTotal:")
- {
- uint64_t mem;
- if(file >> mem)
- {
- return mem * 1024ull;
- }
- else
- {
- return 0;
- }
- }
- // ignore rest of the line
- file.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
- }
- return 0; // nothing found
+ std::string token;
+ std::ifstream file("/proc/meminfo");
+ while(file >> token)
+ {
+ if(token == "MemTotal:")
+ {
+ uint64_t mem;
+ if(file >> mem)
+ {
+ return mem * 1024ull;
+ }
+ else
+ {
+ return 0;
+ }
+ }
+ // ignore rest of the line
+ file.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
+ }
+ return 0; // nothing found
}
bool Sys::isCPU64bit()
{
- return isSystem64bit();
+ return isSystem64bit();
}
bool Sys::isSystem64bit()
{
- // kernel build arch on linux
- return QSysInfo::currentCpuArchitecture() == "x86_64";
+ // kernel build arch on linux
+ return QSysInfo::currentCpuArchitecture() == "x86_64";
}
Sys::DistributionInfo Sys::getDistributionInfo()
{
- DistributionInfo systemd_info = read_os_release();
- DistributionInfo lsb_info = read_lsb_release();
- DistributionInfo legacy_info = read_legacy_release();
- DistributionInfo result = systemd_info + lsb_info + legacy_info;
- if(result.distributionName.isNull())
- {
- result.distributionName = "unknown";
- }
- if(result.distributionVersion.isNull())
- {
- if(result.distributionName == "arch")
- {
- result.distributionVersion = "rolling";
- }
- else
- {
- result.distributionVersion = "unknown";
- }
- }
- return result;
+ DistributionInfo systemd_info = read_os_release();
+ DistributionInfo lsb_info = read_lsb_release();
+ DistributionInfo legacy_info = read_legacy_release();
+ DistributionInfo result = systemd_info + lsb_info + legacy_info;
+ if(result.distributionName.isNull())
+ {
+ result.distributionName = "unknown";
+ }
+ if(result.distributionVersion.isNull())
+ {
+ if(result.distributionName == "arch")
+ {
+ result.distributionVersion = "rolling";
+ }
+ else
+ {
+ result.distributionVersion = "unknown";
+ }
+ }
+ return result;
}
diff --git a/libraries/systeminfo/src/sys_win32.cpp b/libraries/systeminfo/src/sys_win32.cpp
index cc1d61c1..a750b3a7 100644
--- a/libraries/systeminfo/src/sys_win32.cpp
+++ b/libraries/systeminfo/src/sys_win32.cpp
@@ -4,49 +4,49 @@
Sys::KernelInfo Sys::getKernelInfo()
{
- Sys::KernelInfo out;
- out.kernelName = "Windows";
- OSVERSIONINFOW osvi;
- ZeroMemory(&osvi, sizeof(OSVERSIONINFOW));
- osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW);
- GetVersionExW(&osvi);
- out.kernelVersion = QString("%1.%2").arg(osvi.dwMajorVersion).arg(osvi.dwMinorVersion);
- return out;
+ Sys::KernelInfo out;
+ out.kernelName = "Windows";
+ OSVERSIONINFOW osvi;
+ ZeroMemory(&osvi, sizeof(OSVERSIONINFOW));
+ osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW);
+ GetVersionExW(&osvi);
+ out.kernelVersion = QString("%1.%2").arg(osvi.dwMajorVersion).arg(osvi.dwMinorVersion);
+ return out;
}
uint64_t Sys::getSystemRam()
{
- MEMORYSTATUSEX status;
- status.dwLength = sizeof(status);
- GlobalMemoryStatusEx( &status );
- // bytes
- return (uint64_t)status.ullTotalPhys;
+ MEMORYSTATUSEX status;
+ status.dwLength = sizeof(status);
+ GlobalMemoryStatusEx( &status );
+ // bytes
+ return (uint64_t)status.ullTotalPhys;
}
bool Sys::isSystem64bit()
{
#if defined(_WIN64)
- return true;
+ return true;
#elif defined(_WIN32)
- BOOL f64 = false;
- return IsWow64Process(GetCurrentProcess(), &f64) && f64;
+ BOOL f64 = false;
+ return IsWow64Process(GetCurrentProcess(), &f64) && f64;
#else
- // it's some other kind of system...
- return false;
+ // it's some other kind of system...
+ return false;
#endif
}
bool Sys::isCPU64bit()
{
- SYSTEM_INFO info;
- ZeroMemory(&info, sizeof(SYSTEM_INFO));
- GetNativeSystemInfo(&info);
- auto arch = info.wProcessorArchitecture;
- return arch == PROCESSOR_ARCHITECTURE_AMD64 || arch == PROCESSOR_ARCHITECTURE_IA64;
+ SYSTEM_INFO info;
+ ZeroMemory(&info, sizeof(SYSTEM_INFO));
+ GetNativeSystemInfo(&info);
+ auto arch = info.wProcessorArchitecture;
+ return arch == PROCESSOR_ARCHITECTURE_AMD64 || arch == PROCESSOR_ARCHITECTURE_IA64;
}
Sys::DistributionInfo Sys::getDistributionInfo()
{
- DistributionInfo result;
- return result;
+ DistributionInfo result;
+ return result;
}
diff --git a/libraries/xz-embedded/CMakeLists.txt b/libraries/xz-embedded/CMakeLists.txt
index 5f744671..86ac60c8 100644
--- a/libraries/xz-embedded/CMakeLists.txt
+++ b/libraries/xz-embedded/CMakeLists.txt
@@ -9,18 +9,18 @@ option(XZ_BUILD_MINIDEC "Build a tiny utility that decompresses xz streams" OFF)
# tweak this list and xz.h to fit your needs
set(XZ_SOURCES
- src/xz_crc32.c
- src/xz_crc64.c
- src/xz_dec_lzma2.c
- src/xz_dec_stream.c
-# src/xz_dec_bcj.c
+ src/xz_crc32.c
+ src/xz_crc64.c
+ src/xz_dec_lzma2.c
+ src/xz_dec_stream.c
+# src/xz_dec_bcj.c
)
add_library(xz-embedded STATIC ${XZ_SOURCES})
target_include_directories(xz-embedded PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include")
set_property(TARGET xz-embedded PROPERTY C_STANDARD 99)
if(${XZ_BUILD_MINIDEC})
- add_executable(xzminidec xzminidec.c)
- target_link_libraries(xzminidec xz-embedded)
- set_property(TARGET xzminidec PROPERTY C_STANDARD 99)
+ add_executable(xzminidec xzminidec.c)
+ target_link_libraries(xzminidec xz-embedded)
+ set_property(TARGET xzminidec PROPERTY C_STANDARD 99)
endif()
diff --git a/libraries/xz-embedded/include/xz.h b/libraries/xz-embedded/include/xz.h
index eef8ef69..3779124c 100644
--- a/libraries/xz-embedded/include/xz.h
+++ b/libraries/xz-embedded/include/xz.h
@@ -69,9 +69,9 @@ extern "C" {
*/
enum xz_mode
{
- XZ_SINGLE,
- XZ_PREALLOC,
- XZ_DYNALLOC
+ XZ_SINGLE,
+ XZ_PREALLOC,
+ XZ_DYNALLOC
};
/**
@@ -126,15 +126,15 @@ enum xz_mode
*/
enum xz_ret
{
- XZ_OK,
- XZ_STREAM_END,
- XZ_UNSUPPORTED_CHECK,
- XZ_MEM_ERROR,
- XZ_MEMLIMIT_ERROR,
- XZ_FORMAT_ERROR,
- XZ_OPTIONS_ERROR,
- XZ_DATA_ERROR,
- XZ_BUF_ERROR
+ XZ_OK,
+ XZ_STREAM_END,
+ XZ_UNSUPPORTED_CHECK,
+ XZ_MEM_ERROR,
+ XZ_MEMLIMIT_ERROR,
+ XZ_FORMAT_ERROR,
+ XZ_OPTIONS_ERROR,
+ XZ_DATA_ERROR,
+ XZ_BUF_ERROR
};
/**
@@ -155,13 +155,13 @@ enum xz_ret
*/
struct xz_buf
{
- const uint8_t *in;
- size_t in_pos;
- size_t in_size;
+ const uint8_t *in;
+ size_t in_pos;
+ size_t in_size;
- uint8_t *out;
- size_t out_pos;
- size_t out_size;
+ uint8_t *out;
+ size_t out_pos;
+ size_t out_size;
};
/**
diff --git a/libraries/xz-embedded/src/xz_config.h b/libraries/xz-embedded/src/xz_config.h
index 40805b75..effdb1bd 100644
--- a/libraries/xz-embedded/src/xz_config.h
+++ b/libraries/xz-embedded/src/xz_config.h
@@ -74,36 +74,36 @@ typedef unsigned char bool;
#ifndef get_unaligned_le32
static inline uint32_t get_unaligned_le32(const uint8_t *buf)
{
- return (uint32_t)buf[0] | ((uint32_t)buf[1] << 8) | ((uint32_t)buf[2] << 16) |
- ((uint32_t)buf[3] << 24);
+ return (uint32_t)buf[0] | ((uint32_t)buf[1] << 8) | ((uint32_t)buf[2] << 16) |
+ ((uint32_t)buf[3] << 24);
}
#endif
#ifndef get_unaligned_be32
static inline uint32_t get_unaligned_be32(const uint8_t *buf)
{
- return (uint32_t)(buf[0] << 24) | ((uint32_t)buf[1] << 16) | ((uint32_t)buf[2] << 8) |
- (uint32_t)buf[3];
+ return (uint32_t)(buf[0] << 24) | ((uint32_t)buf[1] << 16) | ((uint32_t)buf[2] << 8) |
+ (uint32_t)buf[3];
}
#endif
#ifndef put_unaligned_le32
static inline void put_unaligned_le32(uint32_t val, uint8_t *buf)
{
- buf[0] = (uint8_t)val;
- buf[1] = (uint8_t)(val >> 8);
- buf[2] = (uint8_t)(val >> 16);
- buf[3] = (uint8_t)(val >> 24);
+ buf[0] = (uint8_t)val;
+ buf[1] = (uint8_t)(val >> 8);
+ buf[2] = (uint8_t)(val >> 16);
+ buf[3] = (uint8_t)(val >> 24);
}
#endif
#ifndef put_unaligned_be32
static inline void put_unaligned_be32(uint32_t val, uint8_t *buf)
{
- buf[0] = (uint8_t)(val >> 24);
- buf[1] = (uint8_t)(val >> 16);
- buf[2] = (uint8_t)(val >> 8);
- buf[3] = (uint8_t)val;
+ buf[0] = (uint8_t)(val >> 24);
+ buf[1] = (uint8_t)(val >> 16);
+ buf[2] = (uint8_t)(val >> 8);
+ buf[3] = (uint8_t)val;
}
#endif
diff --git a/libraries/xz-embedded/src/xz_crc32.c b/libraries/xz-embedded/src/xz_crc32.c
index c412662b..65d9d5b8 100644
--- a/libraries/xz-embedded/src/xz_crc32.c
+++ b/libraries/xz-embedded/src/xz_crc32.c
@@ -29,33 +29,33 @@ STATIC_RW_DATA uint32_t xz_crc32_table[256];
XZ_EXTERN void xz_crc32_init(void)
{
- const uint32_t poly = 0xEDB88320;
+ const uint32_t poly = 0xEDB88320;
- uint32_t i;
- uint32_t j;
- uint32_t r;
+ uint32_t i;
+ uint32_t j;
+ uint32_t r;
- for (i = 0; i < 256; ++i)
- {
- r = i;
- for (j = 0; j < 8; ++j)
- r = (r >> 1) ^ (poly & ~((r & 1) - 1));
+ for (i = 0; i < 256; ++i)
+ {
+ r = i;
+ for (j = 0; j < 8; ++j)
+ r = (r >> 1) ^ (poly & ~((r & 1) - 1));
- xz_crc32_table[i] = r;
- }
+ xz_crc32_table[i] = r;
+ }
- return;
+ return;
}
XZ_EXTERN uint32_t xz_crc32(const uint8_t *buf, size_t size, uint32_t crc)
{
- crc = ~crc;
+ crc = ~crc;
- while (size != 0)
- {
- crc = xz_crc32_table[*buf++ ^ (crc & 0xFF)] ^ (crc >> 8);
- --size;
- }
+ while (size != 0)
+ {
+ crc = xz_crc32_table[*buf++ ^ (crc & 0xFF)] ^ (crc >> 8);
+ --size;
+ }
- return ~crc;
+ return ~crc;
}
diff --git a/libraries/xz-embedded/src/xz_crc64.c b/libraries/xz-embedded/src/xz_crc64.c
index 4794b9d3..0f711d8d 100644
--- a/libraries/xz-embedded/src/xz_crc64.c
+++ b/libraries/xz-embedded/src/xz_crc64.c
@@ -20,33 +20,33 @@ STATIC_RW_DATA uint64_t xz_crc64_table[256];
XZ_EXTERN void xz_crc64_init(void)
{
- const uint64_t poly = 0xC96C5795D7870F42;
+ const uint64_t poly = 0xC96C5795D7870F42;
- uint32_t i;
- uint32_t j;
- uint64_t r;
+ uint32_t i;
+ uint32_t j;
+ uint64_t r;
- for (i = 0; i < 256; ++i)
- {
- r = i;
- for (j = 0; j < 8; ++j)
- r = (r >> 1) ^ (poly & ~((r & 1) - 1));
+ for (i = 0; i < 256; ++i)
+ {
+ r = i;
+ for (j = 0; j < 8; ++j)
+ r = (r >> 1) ^ (poly & ~((r & 1) - 1));
- xz_crc64_table[i] = r;
- }
+ xz_crc64_table[i] = r;
+ }
- return;
+ return;
}
XZ_EXTERN uint64_t xz_crc64(const uint8_t *buf, size_t size, uint64_t crc)
{
- crc = ~crc;
+ crc = ~crc;
- while (size != 0)
- {
- crc = xz_crc64_table[*buf++ ^ (crc & 0xFF)] ^ (crc >> 8);
- --size;
- }
+ while (size != 0)
+ {
+ crc = xz_crc64_table[*buf++ ^ (crc & 0xFF)] ^ (crc >> 8);
+ --size;
+ }
- return ~crc;
+ return ~crc;
}
diff --git a/libraries/xz-embedded/src/xz_dec_bcj.c b/libraries/xz-embedded/src/xz_dec_bcj.c
index 9ffda3bd..a79fa76d 100644
--- a/libraries/xz-embedded/src/xz_dec_bcj.c
+++ b/libraries/xz-embedded/src/xz_dec_bcj.c
@@ -18,64 +18,64 @@
struct xz_dec_bcj
{
- /* Type of the BCJ filter being used */
- enum
- {
- BCJ_X86 = 4, /* x86 or x86-64 */
- BCJ_POWERPC = 5, /* Big endian only */
- BCJ_IA64 = 6, /* Big or little endian */
- BCJ_ARM = 7, /* Little endian only */
- BCJ_ARMTHUMB = 8, /* Little endian only */
- BCJ_SPARC = 9 /* Big or little endian */
- } type;
-
- /*
- * Return value of the next filter in the chain. We need to preserve
- * this information across calls, because we must not call the next
- * filter anymore once it has returned XZ_STREAM_END.
- */
- enum xz_ret ret;
-
- /* True if we are operating in single-call mode. */
- bool single_call;
-
- /*
- * Absolute position relative to the beginning of the uncompressed
- * data (in a single .xz Block). We care only about the lowest 32
- * bits so this doesn't need to be uint64_t even with big files.
- */
- uint32_t pos;
-
- /* x86 filter state */
- uint32_t x86_prev_mask;
-
- /* Temporary space to hold the variables from struct xz_buf */
- uint8_t *out;
- size_t out_pos;
- size_t out_size;
-
- struct
- {
- /* Amount of already filtered data in the beginning of buf */
- size_t filtered;
-
- /* Total amount of data currently stored in buf */
- size_t size;
-
- /*
- * Buffer to hold a mix of filtered and unfiltered data. This
- * needs to be big enough to hold Alignment + 2 * Look-ahead:
- *
- * Type Alignment Look-ahead
- * x86 1 4
- * PowerPC 4 0
- * IA-64 16 0
- * ARM 4 0
- * ARM-Thumb 2 2
- * SPARC 4 0
- */
- uint8_t buf[16];
- } temp;
+ /* Type of the BCJ filter being used */
+ enum
+ {
+ BCJ_X86 = 4, /* x86 or x86-64 */
+ BCJ_POWERPC = 5, /* Big endian only */
+ BCJ_IA64 = 6, /* Big or little endian */
+ BCJ_ARM = 7, /* Little endian only */
+ BCJ_ARMTHUMB = 8, /* Little endian only */
+ BCJ_SPARC = 9 /* Big or little endian */
+ } type;
+
+ /*
+ * Return value of the next filter in the chain. We need to preserve
+ * this information across calls, because we must not call the next
+ * filter anymore once it has returned XZ_STREAM_END.
+ */
+ enum xz_ret ret;
+
+ /* True if we are operating in single-call mode. */
+ bool single_call;
+
+ /*
+ * Absolute position relative to the beginning of the uncompressed
+ * data (in a single .xz Block). We care only about the lowest 32
+ * bits so this doesn't need to be uint64_t even with big files.
+ */
+ uint32_t pos;
+
+ /* x86 filter state */
+ uint32_t x86_prev_mask;
+
+ /* Temporary space to hold the variables from struct xz_buf */
+ uint8_t *out;
+ size_t out_pos;
+ size_t out_size;
+
+ struct
+ {
+ /* Amount of already filtered data in the beginning of buf */
+ size_t filtered;
+
+ /* Total amount of data currently stored in buf */
+ size_t size;
+
+ /*
+ * Buffer to hold a mix of filtered and unfiltered data. This
+ * needs to be big enough to hold Alignment + 2 * Look-ahead:
+ *
+ * Type Alignment Look-ahead
+ * x86 1 4
+ * PowerPC 4 0
+ * IA-64 16 0
+ * ARM 4 0
+ * ARM-Thumb 2 2
+ * SPARC 4 0
+ */
+ uint8_t buf[16];
+ } temp;
};
#ifdef XZ_DEC_X86
@@ -85,264 +85,264 @@ struct xz_dec_bcj
*/
static inline int bcj_x86_test_msbyte(uint8_t b)
{
- return b == 0x00 || b == 0xFF;
+ return b == 0x00 || b == 0xFF;
}
static size_t bcj_x86(struct xz_dec_bcj *s, uint8_t *buf, size_t size)
{
- static const bool mask_to_allowed_status[8] = {true, true, true, false,
- true, false, false, false};
-
- static const uint8_t mask_to_bit_num[8] = {0, 1, 2, 2, 3, 3, 3, 3};
-
- size_t i;
- size_t prev_pos = (size_t) - 1;
- uint32_t prev_mask = s->x86_prev_mask;
- uint32_t src;
- uint32_t dest;
- uint32_t j;
- uint8_t b;
-
- if (size <= 4)
- return 0;
-
- size -= 4;
- for (i = 0; i < size; ++i)
- {
- if ((buf[i] & 0xFE) != 0xE8)
- continue;
-
- prev_pos = i - prev_pos;
- if (prev_pos > 3)
- {
- prev_mask = 0;
- }
- else
- {
- prev_mask = (prev_mask << (prev_pos - 1)) & 7;
- if (prev_mask != 0)
- {
- b = buf[i + 4 - mask_to_bit_num[prev_mask]];
- if (!mask_to_allowed_status[prev_mask] || bcj_x86_test_msbyte(b))
- {
- prev_pos = i;
- prev_mask = (prev_mask << 1) | 1;
- continue;
- }
- }
- }
-
- prev_pos = i;
-
- if (bcj_x86_test_msbyte(buf[i + 4]))
- {
- src = get_unaligned_le32(buf + i + 1);
- while (true)
- {
- dest = src - (s->pos + (uint32_t)i + 5);
- if (prev_mask == 0)
- break;
-
- j = mask_to_bit_num[prev_mask] * 8;
- b = (uint8_t)(dest >> (24 - j));
- if (!bcj_x86_test_msbyte(b))
- break;
-
- src = dest ^ (((uint32_t)1 << (32 - j)) - 1);
- }
-
- dest &= 0x01FFFFFF;
- dest |= (uint32_t)0 - (dest & 0x01000000);
- put_unaligned_le32(dest, buf + i + 1);
- i += 4;
- }
- else
- {
- prev_mask = (prev_mask << 1) | 1;
- }
- }
-
- prev_pos = i - prev_pos;
- s->x86_prev_mask = prev_pos > 3 ? 0 : prev_mask << (prev_pos - 1);
- return i;
+ static const bool mask_to_allowed_status[8] = {true, true, true, false,
+ true, false, false, false};
+
+ static const uint8_t mask_to_bit_num[8] = {0, 1, 2, 2, 3, 3, 3, 3};
+
+ size_t i;
+ size_t prev_pos = (size_t) - 1;
+ uint32_t prev_mask = s->x86_prev_mask;
+ uint32_t src;
+ uint32_t dest;
+ uint32_t j;
+ uint8_t b;
+
+ if (size <= 4)
+ return 0;
+
+ size -= 4;
+ for (i = 0; i < size; ++i)
+ {
+ if ((buf[i] & 0xFE) != 0xE8)
+ continue;
+
+ prev_pos = i - prev_pos;
+ if (prev_pos > 3)
+ {
+ prev_mask = 0;
+ }
+ else
+ {
+ prev_mask = (prev_mask << (prev_pos - 1)) & 7;
+ if (prev_mask != 0)
+ {
+ b = buf[i + 4 - mask_to_bit_num[prev_mask]];
+ if (!mask_to_allowed_status[prev_mask] || bcj_x86_test_msbyte(b))
+ {
+ prev_pos = i;
+ prev_mask = (prev_mask << 1) | 1;
+ continue;
+ }
+ }
+ }
+
+ prev_pos = i;
+
+ if (bcj_x86_test_msbyte(buf[i + 4]))
+ {
+ src = get_unaligned_le32(buf + i + 1);
+ while (true)
+ {
+ dest = src - (s->pos + (uint32_t)i + 5);
+ if (prev_mask == 0)
+ break;
+
+ j = mask_to_bit_num[prev_mask] * 8;
+ b = (uint8_t)(dest >> (24 - j));
+ if (!bcj_x86_test_msbyte(b))
+ break;
+
+ src = dest ^ (((uint32_t)1 << (32 - j)) - 1);
+ }
+
+ dest &= 0x01FFFFFF;
+ dest |= (uint32_t)0 - (dest & 0x01000000);
+ put_unaligned_le32(dest, buf + i + 1);
+ i += 4;
+ }
+ else
+ {
+ prev_mask = (prev_mask << 1) | 1;
+ }
+ }
+
+ prev_pos = i - prev_pos;
+ s->x86_prev_mask = prev_pos > 3 ? 0 : prev_mask << (prev_pos - 1);
+ return i;
}
#endif
#ifdef XZ_DEC_POWERPC
static size_t bcj_powerpc(struct xz_dec_bcj *s, uint8_t *buf, size_t size)
{
- size_t i;
- uint32_t instr;
-
- for (i = 0; i + 4 <= size; i += 4)
- {
- instr = get_unaligned_be32(buf + i);
- if ((instr & 0xFC000003) == 0x48000001)
- {
- instr &= 0x03FFFFFC;
- instr -= s->pos + (uint32_t)i;
- instr &= 0x03FFFFFC;
- instr |= 0x48000001;
- put_unaligned_be32(instr, buf + i);
- }
- }
-
- return i;
+ size_t i;
+ uint32_t instr;
+
+ for (i = 0; i + 4 <= size; i += 4)
+ {
+ instr = get_unaligned_be32(buf + i);
+ if ((instr & 0xFC000003) == 0x48000001)
+ {
+ instr &= 0x03FFFFFC;
+ instr -= s->pos + (uint32_t)i;
+ instr &= 0x03FFFFFC;
+ instr |= 0x48000001;
+ put_unaligned_be32(instr, buf + i);
+ }
+ }
+
+ return i;
}
#endif
#ifdef XZ_DEC_IA64
static size_t bcj_ia64(struct xz_dec_bcj *s, uint8_t *buf, size_t size)
{
- static const uint8_t branch_table[32] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 4, 4, 6, 6, 0, 0, 7, 7, 4, 4, 0, 0, 4, 4, 0, 0};
-
- /*
- * The local variables take a little bit stack space, but it's less
- * than what LZMA2 decoder takes, so it doesn't make sense to reduce
- * stack usage here without doing that for the LZMA2 decoder too.
- */
-
- /* Loop counters */
- size_t i;
- size_t j;
-
- /* Instruction slot (0, 1, or 2) in the 128-bit instruction word */
- uint32_t slot;
-
- /* Bitwise offset of the instruction indicated by slot */
- uint32_t bit_pos;
-
- /* bit_pos split into byte and bit parts */
- uint32_t byte_pos;
- uint32_t bit_res;
-
- /* Address part of an instruction */
- uint32_t addr;
-
- /* Mask used to detect which instructions to convert */
- uint32_t mask;
-
- /* 41-bit instruction stored somewhere in the lowest 48 bits */
- uint64_t instr;
-
- /* Instruction normalized with bit_res for easier manipulation */
- uint64_t norm;
-
- for (i = 0; i + 16 <= size; i += 16)
- {
- mask = branch_table[buf[i] & 0x1F];
- for (slot = 0, bit_pos = 5; slot < 3; ++slot, bit_pos += 41)
- {
- if (((mask >> slot) & 1) == 0)
- continue;
-
- byte_pos = bit_pos >> 3;
- bit_res = bit_pos & 7;
- instr = 0;
- for (j = 0; j < 6; ++j)
- instr |= (uint64_t)(buf[i + j + byte_pos]) << (8 * j);
-
- norm = instr >> bit_res;
-
- if (((norm >> 37) & 0x0F) == 0x05 && ((norm >> 9) & 0x07) == 0)
- {
- addr = (norm >> 13) & 0x0FFFFF;
- addr |= ((uint32_t)(norm >> 36) & 1) << 20;
- addr <<= 4;
- addr -= s->pos + (uint32_t)i;
- addr >>= 4;
-
- norm &= ~((uint64_t)0x8FFFFF << 13);
- norm |= (uint64_t)(addr & 0x0FFFFF) << 13;
- norm |= (uint64_t)(addr & 0x100000) << (36 - 20);
-
- instr &= (1 << bit_res) - 1;
- instr |= norm << bit_res;
-
- for (j = 0; j < 6; j++)
- buf[i + j + byte_pos] = (uint8_t)(instr >> (8 * j));
- }
- }
- }
-
- return i;
+ static const uint8_t branch_table[32] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 4, 4, 6, 6, 0, 0, 7, 7, 4, 4, 0, 0, 4, 4, 0, 0};
+
+ /*
+ * The local variables take a little bit stack space, but it's less
+ * than what LZMA2 decoder takes, so it doesn't make sense to reduce
+ * stack usage here without doing that for the LZMA2 decoder too.
+ */
+
+ /* Loop counters */
+ size_t i;
+ size_t j;
+
+ /* Instruction slot (0, 1, or 2) in the 128-bit instruction word */
+ uint32_t slot;
+
+ /* Bitwise offset of the instruction indicated by slot */
+ uint32_t bit_pos;
+
+ /* bit_pos split into byte and bit parts */
+ uint32_t byte_pos;
+ uint32_t bit_res;
+
+ /* Address part of an instruction */
+ uint32_t addr;
+
+ /* Mask used to detect which instructions to convert */
+ uint32_t mask;
+
+ /* 41-bit instruction stored somewhere in the lowest 48 bits */
+ uint64_t instr;
+
+ /* Instruction normalized with bit_res for easier manipulation */
+ uint64_t norm;
+
+ for (i = 0; i + 16 <= size; i += 16)
+ {
+ mask = branch_table[buf[i] & 0x1F];
+ for (slot = 0, bit_pos = 5; slot < 3; ++slot, bit_pos += 41)
+ {
+ if (((mask >> slot) & 1) == 0)
+ continue;
+
+ byte_pos = bit_pos >> 3;
+ bit_res = bit_pos & 7;
+ instr = 0;
+ for (j = 0; j < 6; ++j)
+ instr |= (uint64_t)(buf[i + j + byte_pos]) << (8 * j);
+
+ norm = instr >> bit_res;
+
+ if (((norm >> 37) & 0x0F) == 0x05 && ((norm >> 9) & 0x07) == 0)
+ {
+ addr = (norm >> 13) & 0x0FFFFF;
+ addr |= ((uint32_t)(norm >> 36) & 1) << 20;
+ addr <<= 4;
+ addr -= s->pos + (uint32_t)i;
+ addr >>= 4;
+
+ norm &= ~((uint64_t)0x8FFFFF << 13);
+ norm |= (uint64_t)(addr & 0x0FFFFF) << 13;
+ norm |= (uint64_t)(addr & 0x100000) << (36 - 20);
+
+ instr &= (1 << bit_res) - 1;
+ instr |= norm << bit_res;
+
+ for (j = 0; j < 6; j++)
+ buf[i + j + byte_pos] = (uint8_t)(instr >> (8 * j));
+ }
+ }
+ }
+
+ return i;
}
#endif
#ifdef XZ_DEC_ARM
static size_t bcj_arm(struct xz_dec_bcj *s, uint8_t *buf, size_t size)
{
- size_t i;
- uint32_t addr;
-
- for (i = 0; i + 4 <= size; i += 4)
- {
- if (buf[i + 3] == 0xEB)
- {
- addr =
- (uint32_t)buf[i] | ((uint32_t)buf[i + 1] << 8) | ((uint32_t)buf[i + 2] << 16);
- addr <<= 2;
- addr -= s->pos + (uint32_t)i + 8;
- addr >>= 2;
- buf[i] = (uint8_t)addr;
- buf[i + 1] = (uint8_t)(addr >> 8);
- buf[i + 2] = (uint8_t)(addr >> 16);
- }
- }
-
- return i;
+ size_t i;
+ uint32_t addr;
+
+ for (i = 0; i + 4 <= size; i += 4)
+ {
+ if (buf[i + 3] == 0xEB)
+ {
+ addr =
+ (uint32_t)buf[i] | ((uint32_t)buf[i + 1] << 8) | ((uint32_t)buf[i + 2] << 16);
+ addr <<= 2;
+ addr -= s->pos + (uint32_t)i + 8;
+ addr >>= 2;
+ buf[i] = (uint8_t)addr;
+ buf[i + 1] = (uint8_t)(addr >> 8);
+ buf[i + 2] = (uint8_t)(addr >> 16);
+ }
+ }
+
+ return i;
}
#endif
#ifdef XZ_DEC_ARMTHUMB
static size_t bcj_armthumb(struct xz_dec_bcj *s, uint8_t *buf, size_t size)
{
- size_t i;
- uint32_t addr;
-
- for (i = 0; i + 4 <= size; i += 2)
- {
- if ((buf[i + 1] & 0xF8) == 0xF0 && (buf[i + 3] & 0xF8) == 0xF8)
- {
- addr = (((uint32_t)buf[i + 1] & 0x07) << 19) | ((uint32_t)buf[i] << 11) |
- (((uint32_t)buf[i + 3] & 0x07) << 8) | (uint32_t)buf[i + 2];
- addr <<= 1;
- addr -= s->pos + (uint32_t)i + 4;
- addr >>= 1;
- buf[i + 1] = (uint8_t)(0xF0 | ((addr >> 19) & 0x07));
- buf[i] = (uint8_t)(addr >> 11);
- buf[i + 3] = (uint8_t)(0xF8 | ((addr >> 8) & 0x07));
- buf[i + 2] = (uint8_t)addr;
- i += 2;
- }
- }
-
- return i;
+ size_t i;
+ uint32_t addr;
+
+ for (i = 0; i + 4 <= size; i += 2)
+ {
+ if ((buf[i + 1] & 0xF8) == 0xF0 && (buf[i + 3] & 0xF8) == 0xF8)
+ {
+ addr = (((uint32_t)buf[i + 1] & 0x07) << 19) | ((uint32_t)buf[i] << 11) |
+ (((uint32_t)buf[i + 3] & 0x07) << 8) | (uint32_t)buf[i + 2];
+ addr <<= 1;
+ addr -= s->pos + (uint32_t)i + 4;
+ addr >>= 1;
+ buf[i + 1] = (uint8_t)(0xF0 | ((addr >> 19) & 0x07));
+ buf[i] = (uint8_t)(addr >> 11);
+ buf[i + 3] = (uint8_t)(0xF8 | ((addr >> 8) & 0x07));
+ buf[i + 2] = (uint8_t)addr;
+ i += 2;
+ }
+ }
+
+ return i;
}
#endif
#ifdef XZ_DEC_SPARC
static size_t bcj_sparc(struct xz_dec_bcj *s, uint8_t *buf, size_t size)
{
- size_t i;
- uint32_t instr;
-
- for (i = 0; i + 4 <= size; i += 4)
- {
- instr = get_unaligned_be32(buf + i);
- if ((instr >> 22) == 0x100 || (instr >> 22) == 0x1FF)
- {
- instr <<= 2;
- instr -= s->pos + (uint32_t)i;
- instr >>= 2;
- instr =
- ((uint32_t)0x40000000 - (instr & 0x400000)) | 0x40000000 | (instr & 0x3FFFFF);
- put_unaligned_be32(instr, buf + i);
- }
- }
-
- return i;
+ size_t i;
+ uint32_t instr;
+
+ for (i = 0; i + 4 <= size; i += 4)
+ {
+ instr = get_unaligned_be32(buf + i);
+ if ((instr >> 22) == 0x100 || (instr >> 22) == 0x1FF)
+ {
+ instr <<= 2;
+ instr -= s->pos + (uint32_t)i;
+ instr >>= 2;
+ instr =
+ ((uint32_t)0x40000000 - (instr & 0x400000)) | 0x40000000 | (instr & 0x3FFFFF);
+ put_unaligned_be32(instr, buf + i);
+ }
+ }
+
+ return i;
}
#endif
@@ -356,51 +356,51 @@ static size_t bcj_sparc(struct xz_dec_bcj *s, uint8_t *buf, size_t size)
*/
static void bcj_apply(struct xz_dec_bcj *s, uint8_t *buf, size_t *pos, size_t size)
{
- size_t filtered;
+ size_t filtered;
- buf += *pos;
- size -= *pos;
+ buf += *pos;
+ size -= *pos;
- switch (s->type)
- {
+ switch (s->type)
+ {
#ifdef XZ_DEC_X86
- case BCJ_X86:
- filtered = bcj_x86(s, buf, size);
- break;
+ case BCJ_X86:
+ filtered = bcj_x86(s, buf, size);
+ break;
#endif
#ifdef XZ_DEC_POWERPC
- case BCJ_POWERPC:
- filtered = bcj_powerpc(s, buf, size);
- break;
+ case BCJ_POWERPC:
+ filtered = bcj_powerpc(s, buf, size);
+ break;
#endif
#ifdef XZ_DEC_IA64
- case BCJ_IA64:
- filtered = bcj_ia64(s, buf, size);
- break;
+ case BCJ_IA64:
+ filtered = bcj_ia64(s, buf, size);
+ break;
#endif
#ifdef XZ_DEC_ARM
- case BCJ_ARM:
- filtered = bcj_arm(s, buf, size);
- break;
+ case BCJ_ARM:
+ filtered = bcj_arm(s, buf, size);
+ break;
#endif
#ifdef XZ_DEC_ARMTHUMB
- case BCJ_ARMTHUMB:
- filtered = bcj_armthumb(s, buf, size);
- break;
+ case BCJ_ARMTHUMB:
+ filtered = bcj_armthumb(s, buf, size);
+ break;
#endif
#ifdef XZ_DEC_SPARC
- case BCJ_SPARC:
- filtered = bcj_sparc(s, buf, size);
- break;
+ case BCJ_SPARC:
+ filtered = bcj_sparc(s, buf, size);
+ break;
#endif
- default:
- /* Never reached but silence compiler warnings. */
- filtered = 0;
- break;
- }
-
- *pos += filtered;
- s->pos += filtered;
+ default:
+ /* Never reached but silence compiler warnings. */
+ filtered = 0;
+ break;
+ }
+
+ *pos += filtered;
+ s->pos += filtered;
}
/*
@@ -410,15 +410,15 @@ static void bcj_apply(struct xz_dec_bcj *s, uint8_t *buf, size_t *pos, size_t si
*/
static void bcj_flush(struct xz_dec_bcj *s, struct xz_buf *b)
{
- size_t copy_size;
+ size_t copy_size;
- copy_size = min_t(size_t, s->temp.filtered, b->out_size - b->out_pos);
- memcpy(b->out + b->out_pos, s->temp.buf, copy_size);
- b->out_pos += copy_size;
+ copy_size = min_t(size_t, s->temp.filtered, b->out_size - b->out_pos);
+ memcpy(b->out + b->out_pos, s->temp.buf, copy_size);
+ b->out_pos += copy_size;
- s->temp.filtered -= copy_size;
- s->temp.size -= copy_size;
- memmove(s->temp.buf, s->temp.buf + copy_size, s->temp.size);
+ s->temp.filtered -= copy_size;
+ s->temp.size -= copy_size;
+ memmove(s->temp.buf, s->temp.buf + copy_size, s->temp.size);
}
/*
@@ -427,162 +427,162 @@ static void bcj_flush(struct xz_dec_bcj *s, struct xz_buf *b)
* some buffering.
*/
XZ_EXTERN enum xz_ret xz_dec_bcj_run(struct xz_dec_bcj *s, struct xz_dec_lzma2 *lzma2,
- struct xz_buf *b)
+ struct xz_buf *b)
{
- size_t out_start;
-
- /*
- * Flush pending already filtered data to the output buffer. Return
- * immediatelly if we couldn't flush everything, or if the next
- * filter in the chain had already returned XZ_STREAM_END.
- */
- if (s->temp.filtered > 0)
- {
- bcj_flush(s, b);
- if (s->temp.filtered > 0)
- return XZ_OK;
-
- if (s->ret == XZ_STREAM_END)
- return XZ_STREAM_END;
- }
-
- /*
- * If we have more output space than what is currently pending in
- * temp, copy the unfiltered data from temp to the output buffer
- * and try to fill the output buffer by decoding more data from the
- * next filter in the chain. Apply the BCJ filter on the new data
- * in the output buffer. If everything cannot be filtered, copy it
- * to temp and rewind the output buffer position accordingly.
- *
- * This needs to be always run when temp.size == 0 to handle a special
- * case where the output buffer is full and the next filter has no
- * more output coming but hasn't returned XZ_STREAM_END yet.
- */
- if (s->temp.size < b->out_size - b->out_pos || s->temp.size == 0)
- {
- out_start = b->out_pos;
- memcpy(b->out + b->out_pos, s->temp.buf, s->temp.size);
- b->out_pos += s->temp.size;
-
- s->ret = xz_dec_lzma2_run(lzma2, b);
- if (s->ret != XZ_STREAM_END && (s->ret != XZ_OK || s->single_call))
- return s->ret;
-
- bcj_apply(s, b->out, &out_start, b->out_pos);
-
- /*
- * As an exception, if the next filter returned XZ_STREAM_END,
- * we can do that too, since the last few bytes that remain
- * unfiltered are meant to remain unfiltered.
- */
- if (s->ret == XZ_STREAM_END)
- return XZ_STREAM_END;
-
- s->temp.size = b->out_pos - out_start;
- b->out_pos -= s->temp.size;
- memcpy(s->temp.buf, b->out + b->out_pos, s->temp.size);
-
- /*
- * If there wasn't enough input to the next filter to fill
- * the output buffer with unfiltered data, there's no point
- * to try decoding more data to temp.
- */
- if (b->out_pos + s->temp.size < b->out_size)
- return XZ_OK;
- }
-
- /*
- * We have unfiltered data in temp. If the output buffer isn't full
- * yet, try to fill the temp buffer by decoding more data from the
- * next filter. Apply the BCJ filter on temp. Then we hopefully can
- * fill the actual output buffer by copying filtered data from temp.
- * A mix of filtered and unfiltered data may be left in temp; it will
- * be taken care on the next call to this function.
- */
- if (b->out_pos < b->out_size)
- {
- /* Make b->out{,_pos,_size} temporarily point to s->temp. */
- s->out = b->out;
- s->out_pos = b->out_pos;
- s->out_size = b->out_size;
- b->out = s->temp.buf;
- b->out_pos = s->temp.size;
- b->out_size = sizeof(s->temp.buf);
-
- s->ret = xz_dec_lzma2_run(lzma2, b);
-
- s->temp.size = b->out_pos;
- b->out = s->out;
- b->out_pos = s->out_pos;
- b->out_size = s->out_size;
-
- if (s->ret != XZ_OK && s->ret != XZ_STREAM_END)
- return s->ret;
-
- bcj_apply(s, s->temp.buf, &s->temp.filtered, s->temp.size);
-
- /*
- * If the next filter returned XZ_STREAM_END, we mark that
- * everything is filtered, since the last unfiltered bytes
- * of the stream are meant to be left as is.
- */
- if (s->ret == XZ_STREAM_END)
- s->temp.filtered = s->temp.size;
-
- bcj_flush(s, b);
- if (s->temp.filtered > 0)
- return XZ_OK;
- }
-
- return s->ret;
+ size_t out_start;
+
+ /*
+ * Flush pending already filtered data to the output buffer. Return
+ * immediatelly if we couldn't flush everything, or if the next
+ * filter in the chain had already returned XZ_STREAM_END.
+ */
+ if (s->temp.filtered > 0)
+ {
+ bcj_flush(s, b);
+ if (s->temp.filtered > 0)
+ return XZ_OK;
+
+ if (s->ret == XZ_STREAM_END)
+ return XZ_STREAM_END;
+ }
+
+ /*
+ * If we have more output space than what is currently pending in
+ * temp, copy the unfiltered data from temp to the output buffer
+ * and try to fill the output buffer by decoding more data from the
+ * next filter in the chain. Apply the BCJ filter on the new data
+ * in the output buffer. If everything cannot be filtered, copy it
+ * to temp and rewind the output buffer position accordingly.
+ *
+ * This needs to be always run when temp.size == 0 to handle a special
+ * case where the output buffer is full and the next filter has no
+ * more output coming but hasn't returned XZ_STREAM_END yet.
+ */
+ if (s->temp.size < b->out_size - b->out_pos || s->temp.size == 0)
+ {
+ out_start = b->out_pos;
+ memcpy(b->out + b->out_pos, s->temp.buf, s->temp.size);
+ b->out_pos += s->temp.size;
+
+ s->ret = xz_dec_lzma2_run(lzma2, b);
+ if (s->ret != XZ_STREAM_END && (s->ret != XZ_OK || s->single_call))
+ return s->ret;
+
+ bcj_apply(s, b->out, &out_start, b->out_pos);
+
+ /*
+ * As an exception, if the next filter returned XZ_STREAM_END,
+ * we can do that too, since the last few bytes that remain
+ * unfiltered are meant to remain unfiltered.
+ */
+ if (s->ret == XZ_STREAM_END)
+ return XZ_STREAM_END;
+
+ s->temp.size = b->out_pos - out_start;
+ b->out_pos -= s->temp.size;
+ memcpy(s->temp.buf, b->out + b->out_pos, s->temp.size);
+
+ /*
+ * If there wasn't enough input to the next filter to fill
+ * the output buffer with unfiltered data, there's no point
+ * to try decoding more data to temp.
+ */
+ if (b->out_pos + s->temp.size < b->out_size)
+ return XZ_OK;
+ }
+
+ /*
+ * We have unfiltered data in temp. If the output buffer isn't full
+ * yet, try to fill the temp buffer by decoding more data from the
+ * next filter. Apply the BCJ filter on temp. Then we hopefully can
+ * fill the actual output buffer by copying filtered data from temp.
+ * A mix of filtered and unfiltered data may be left in temp; it will
+ * be taken care on the next call to this function.
+ */
+ if (b->out_pos < b->out_size)
+ {
+ /* Make b->out{,_pos,_size} temporarily point to s->temp. */
+ s->out = b->out;
+ s->out_pos = b->out_pos;
+ s->out_size = b->out_size;
+ b->out = s->temp.buf;
+ b->out_pos = s->temp.size;
+ b->out_size = sizeof(s->temp.buf);
+
+ s->ret = xz_dec_lzma2_run(lzma2, b);
+
+ s->temp.size = b->out_pos;
+ b->out = s->out;
+ b->out_pos = s->out_pos;
+ b->out_size = s->out_size;
+
+ if (s->ret != XZ_OK && s->ret != XZ_STREAM_END)
+ return s->ret;
+
+ bcj_apply(s, s->temp.buf, &s->temp.filtered, s->temp.size);
+
+ /*
+ * If the next filter returned XZ_STREAM_END, we mark that
+ * everything is filtered, since the last unfiltered bytes
+ * of the stream are meant to be left as is.
+ */
+ if (s->ret == XZ_STREAM_END)
+ s->temp.filtered = s->temp.size;
+
+ bcj_flush(s, b);
+ if (s->temp.filtered > 0)
+ return XZ_OK;
+ }
+
+ return s->ret;
}
XZ_EXTERN struct xz_dec_bcj *xz_dec_bcj_create(bool single_call)
{
- struct xz_dec_bcj *s = kmalloc(sizeof(*s), GFP_KERNEL);
- if (s != NULL)
- s->single_call = single_call;
+ struct xz_dec_bcj *s = kmalloc(sizeof(*s), GFP_KERNEL);
+ if (s != NULL)
+ s->single_call = single_call;
- return s;
+ return s;
}
XZ_EXTERN enum xz_ret xz_dec_bcj_reset(struct xz_dec_bcj *s, uint8_t id)
{
- switch (id)
- {
+ switch (id)
+ {
#ifdef XZ_DEC_X86
- case BCJ_X86:
+ case BCJ_X86:
#endif
#ifdef XZ_DEC_POWERPC
- case BCJ_POWERPC:
+ case BCJ_POWERPC:
#endif
#ifdef XZ_DEC_IA64
- case BCJ_IA64:
+ case BCJ_IA64:
#endif
#ifdef XZ_DEC_ARM
- case BCJ_ARM:
+ case BCJ_ARM:
#endif
#ifdef XZ_DEC_ARMTHUMB
- case BCJ_ARMTHUMB:
+ case BCJ_ARMTHUMB:
#endif
#ifdef XZ_DEC_SPARC
- case BCJ_SPARC:
+ case BCJ_SPARC:
#endif
- break;
+ break;
- default:
- /* Unsupported Filter ID */
- return XZ_OPTIONS_ERROR;
- }
+ default:
+ /* Unsupported Filter ID */
+ return XZ_OPTIONS_ERROR;
+ }
- s->type = id;
- s->ret = XZ_OK;
- s->pos = 0;
- s->x86_prev_mask = 0;
- s->temp.filtered = 0;
- s->temp.size = 0;
+ s->type = id;
+ s->ret = XZ_OK;
+ s->pos = 0;
+ s->x86_prev_mask = 0;
+ s->temp.filtered = 0;
+ s->temp.size = 0;
- return XZ_OK;
+ return XZ_OK;
}
#endif
diff --git a/libraries/xz-embedded/src/xz_dec_lzma2.c b/libraries/xz-embedded/src/xz_dec_lzma2.c
index 3d7b9a2e..365ace2b 100644
--- a/libraries/xz-embedded/src/xz_dec_lzma2.c
+++ b/libraries/xz-embedded/src/xz_dec_lzma2.c
@@ -43,244 +43,244 @@
*/
struct dictionary
{
- /* Beginning of the history buffer */
- uint8_t *buf;
-
- /* Old position in buf (before decoding more data) */
- size_t start;
-
- /* Position in buf */
- size_t pos;
-
- /*
- * How full dictionary is. This is used to detect corrupt input that
- * would read beyond the beginning of the uncompressed stream.
- */
- size_t full;
-
- /* Write limit; we don't write to buf[limit] or later bytes. */
- size_t limit;
-
- /*
- * End of the dictionary buffer. In multi-call mode, this is
- * the same as the dictionary size. In single-call mode, this
- * indicates the size of the output buffer.
- */
- size_t end;
-
- /*
- * Size of the dictionary as specified in Block Header. This is used
- * together with "full" to detect corrupt input that would make us
- * read beyond the beginning of the uncompressed stream.
- */
- uint32_t size;
-
- /*
- * Maximum allowed dictionary size in multi-call mode.
- * This is ignored in single-call mode.
- */
- uint32_t size_max;
-
- /*
- * Amount of memory currently allocated for the dictionary.
- * This is used only with XZ_DYNALLOC. (With XZ_PREALLOC,
- * size_max is always the same as the allocated size.)
- */
- uint32_t allocated;
-
- /* Operation mode */
- enum xz_mode mode;
+ /* Beginning of the history buffer */
+ uint8_t *buf;
+
+ /* Old position in buf (before decoding more data) */
+ size_t start;
+
+ /* Position in buf */
+ size_t pos;
+
+ /*
+ * How full dictionary is. This is used to detect corrupt input that
+ * would read beyond the beginning of the uncompressed stream.
+ */
+ size_t full;
+
+ /* Write limit; we don't write to buf[limit] or later bytes. */
+ size_t limit;
+
+ /*
+ * End of the dictionary buffer. In multi-call mode, this is
+ * the same as the dictionary size. In single-call mode, this
+ * indicates the size of the output buffer.
+ */
+ size_t end;
+
+ /*
+ * Size of the dictionary as specified in Block Header. This is used
+ * together with "full" to detect corrupt input that would make us
+ * read beyond the beginning of the uncompressed stream.
+ */
+ uint32_t size;
+
+ /*
+ * Maximum allowed dictionary size in multi-call mode.
+ * This is ignored in single-call mode.
+ */
+ uint32_t size_max;
+
+ /*
+ * Amount of memory currently allocated for the dictionary.
+ * This is used only with XZ_DYNALLOC. (With XZ_PREALLOC,
+ * size_max is always the same as the allocated size.)
+ */
+ uint32_t allocated;
+
+ /* Operation mode */
+ enum xz_mode mode;
};
/* Range decoder */
struct rc_dec
{
- uint32_t range;
- uint32_t code;
-
- /*
- * Number of initializing bytes remaining to be read
- * by rc_read_init().
- */
- uint32_t init_bytes_left;
-
- /*
- * Buffer from which we read our input. It can be either
- * temp.buf or the caller-provided input buffer.
- */
- const uint8_t *in;
- size_t in_pos;
- size_t in_limit;
+ uint32_t range;
+ uint32_t code;
+
+ /*
+ * Number of initializing bytes remaining to be read
+ * by rc_read_init().
+ */
+ uint32_t init_bytes_left;
+
+ /*
+ * Buffer from which we read our input. It can be either
+ * temp.buf or the caller-provided input buffer.
+ */
+ const uint8_t *in;
+ size_t in_pos;
+ size_t in_limit;
};
/* Probabilities for a length decoder. */
struct lzma_len_dec
{
- /* Probability of match length being at least 10 */
- uint16_t choice;
+ /* Probability of match length being at least 10 */
+ uint16_t choice;
- /* Probability of match length being at least 18 */
- uint16_t choice2;
+ /* Probability of match length being at least 18 */
+ uint16_t choice2;
- /* Probabilities for match lengths 2-9 */
- uint16_t low[POS_STATES_MAX][LEN_LOW_SYMBOLS];
+ /* Probabilities for match lengths 2-9 */
+ uint16_t low[POS_STATES_MAX][LEN_LOW_SYMBOLS];
- /* Probabilities for match lengths 10-17 */
- uint16_t mid[POS_STATES_MAX][LEN_MID_SYMBOLS];
+ /* Probabilities for match lengths 10-17 */
+ uint16_t mid[POS_STATES_MAX][LEN_MID_SYMBOLS];
- /* Probabilities for match lengths 18-273 */
- uint16_t high[LEN_HIGH_SYMBOLS];
+ /* Probabilities for match lengths 18-273 */
+ uint16_t high[LEN_HIGH_SYMBOLS];
};
struct lzma_dec
{
- /* Distances of latest four matches */
- uint32_t rep0;
- uint32_t rep1;
- uint32_t rep2;
- uint32_t rep3;
-
- /* Types of the most recently seen LZMA symbols */
- enum lzma_state state;
-
- /*
- * Length of a match. This is updated so that dict_repeat can
- * be called again to finish repeating the whole match.
- */
- uint32_t len;
-
- /*
- * LZMA properties or related bit masks (number of literal
- * context bits, a mask dervied from the number of literal
- * position bits, and a mask dervied from the number
- * position bits)
- */
- uint32_t lc;
- uint32_t literal_pos_mask; /* (1 << lp) - 1 */
- uint32_t pos_mask; /* (1 << pb) - 1 */
-
- /* If 1, it's a match. Otherwise it's a single 8-bit literal. */
- uint16_t is_match[STATES][POS_STATES_MAX];
-
- /* If 1, it's a repeated match. The distance is one of rep0 .. rep3. */
- uint16_t is_rep[STATES];
-
- /*
- * If 0, distance of a repeated match is rep0.
- * Otherwise check is_rep1.
- */
- uint16_t is_rep0[STATES];
-
- /*
- * If 0, distance of a repeated match is rep1.
- * Otherwise check is_rep2.
- */
- uint16_t is_rep1[STATES];
-
- /* If 0, distance of a repeated match is rep2. Otherwise it is rep3. */
- uint16_t is_rep2[STATES];
-
- /*
- * If 1, the repeated match has length of one byte. Otherwise
- * the length is decoded from rep_len_decoder.
- */
- uint16_t is_rep0_long[STATES][POS_STATES_MAX];
-
- /*
- * Probability tree for the highest two bits of the match
- * distance. There is a separate probability tree for match
- * lengths of 2 (i.e. MATCH_LEN_MIN), 3, 4, and [5, 273].
- */
- uint16_t dist_slot[DIST_STATES][DIST_SLOTS];
-
- /*
- * Probility trees for additional bits for match distance
- * when the distance is in the range [4, 127].
- */
- uint16_t dist_special[FULL_DISTANCES - DIST_MODEL_END];
-
- /*
- * Probability tree for the lowest four bits of a match
- * distance that is equal to or greater than 128.
- */
- uint16_t dist_align[ALIGN_SIZE];
-
- /* Length of a normal match */
- struct lzma_len_dec match_len_dec;
-
- /* Length of a repeated match */
- struct lzma_len_dec rep_len_dec;
-
- /* Probabilities of literals */
- uint16_t literal[LITERAL_CODERS_MAX][LITERAL_CODER_SIZE];
+ /* Distances of latest four matches */
+ uint32_t rep0;
+ uint32_t rep1;
+ uint32_t rep2;
+ uint32_t rep3;
+
+ /* Types of the most recently seen LZMA symbols */
+ enum lzma_state state;
+
+ /*
+ * Length of a match. This is updated so that dict_repeat can
+ * be called again to finish repeating the whole match.
+ */
+ uint32_t len;
+
+ /*
+ * LZMA properties or related bit masks (number of literal
+ * context bits, a mask dervied from the number of literal
+ * position bits, and a mask dervied from the number
+ * position bits)
+ */
+ uint32_t lc;
+ uint32_t literal_pos_mask; /* (1 << lp) - 1 */
+ uint32_t pos_mask; /* (1 << pb) - 1 */
+
+ /* If 1, it's a match. Otherwise it's a single 8-bit literal. */
+ uint16_t is_match[STATES][POS_STATES_MAX];
+
+ /* If 1, it's a repeated match. The distance is one of rep0 .. rep3. */
+ uint16_t is_rep[STATES];
+
+ /*
+ * If 0, distance of a repeated match is rep0.
+ * Otherwise check is_rep1.
+ */
+ uint16_t is_rep0[STATES];
+
+ /*
+ * If 0, distance of a repeated match is rep1.
+ * Otherwise check is_rep2.
+ */
+ uint16_t is_rep1[STATES];
+
+ /* If 0, distance of a repeated match is rep2. Otherwise it is rep3. */
+ uint16_t is_rep2[STATES];
+
+ /*
+ * If 1, the repeated match has length of one byte. Otherwise
+ * the length is decoded from rep_len_decoder.
+ */
+ uint16_t is_rep0_long[STATES][POS_STATES_MAX];
+
+ /*
+ * Probability tree for the highest two bits of the match
+ * distance. There is a separate probability tree for match
+ * lengths of 2 (i.e. MATCH_LEN_MIN), 3, 4, and [5, 273].
+ */
+ uint16_t dist_slot[DIST_STATES][DIST_SLOTS];
+
+ /*
+ * Probility trees for additional bits for match distance
+ * when the distance is in the range [4, 127].
+ */
+ uint16_t dist_special[FULL_DISTANCES - DIST_MODEL_END];
+
+ /*
+ * Probability tree for the lowest four bits of a match
+ * distance that is equal to or greater than 128.
+ */
+ uint16_t dist_align[ALIGN_SIZE];
+
+ /* Length of a normal match */
+ struct lzma_len_dec match_len_dec;
+
+ /* Length of a repeated match */
+ struct lzma_len_dec rep_len_dec;
+
+ /* Probabilities of literals */
+ uint16_t literal[LITERAL_CODERS_MAX][LITERAL_CODER_SIZE];
};
struct lzma2_dec
{
- /* Position in xz_dec_lzma2_run(). */
- enum lzma2_seq
- {
- SEQ_CONTROL,
- SEQ_UNCOMPRESSED_1,
- SEQ_UNCOMPRESSED_2,
- SEQ_COMPRESSED_0,
- SEQ_COMPRESSED_1,
- SEQ_PROPERTIES,
- SEQ_LZMA_PREPARE,
- SEQ_LZMA_RUN,
- SEQ_COPY
- } sequence;
-
- /* Next position after decoding the compressed size of the chunk. */
- enum lzma2_seq next_sequence;
-
- /* Uncompressed size of LZMA chunk (2 MiB at maximum) */
- uint32_t uncompressed;
-
- /*
- * Compressed size of LZMA chunk or compressed/uncompressed
- * size of uncompressed chunk (64 KiB at maximum)
- */
- uint32_t compressed;
-
- /*
- * True if dictionary reset is needed. This is false before
- * the first chunk (LZMA or uncompressed).
- */
- bool need_dict_reset;
-
- /*
- * True if new LZMA properties are needed. This is false
- * before the first LZMA chunk.
- */
- bool need_props;
+ /* Position in xz_dec_lzma2_run(). */
+ enum lzma2_seq
+ {
+ SEQ_CONTROL,
+ SEQ_UNCOMPRESSED_1,
+ SEQ_UNCOMPRESSED_2,
+ SEQ_COMPRESSED_0,
+ SEQ_COMPRESSED_1,
+ SEQ_PROPERTIES,
+ SEQ_LZMA_PREPARE,
+ SEQ_LZMA_RUN,
+ SEQ_COPY
+ } sequence;
+
+ /* Next position after decoding the compressed size of the chunk. */
+ enum lzma2_seq next_sequence;
+
+ /* Uncompressed size of LZMA chunk (2 MiB at maximum) */
+ uint32_t uncompressed;
+
+ /*
+ * Compressed size of LZMA chunk or compressed/uncompressed
+ * size of uncompressed chunk (64 KiB at maximum)
+ */
+ uint32_t compressed;
+
+ /*
+ * True if dictionary reset is needed. This is false before
+ * the first chunk (LZMA or uncompressed).
+ */
+ bool need_dict_reset;
+
+ /*
+ * True if new LZMA properties are needed. This is false
+ * before the first LZMA chunk.
+ */
+ bool need_props;
};
struct xz_dec_lzma2
{
- /*
- * The order below is important on x86 to reduce code size and
- * it shouldn't hurt on other platforms. Everything up to and
- * including lzma.pos_mask are in the first 128 bytes on x86-32,
- * which allows using smaller instructions to access those
- * variables. On x86-64, fewer variables fit into the first 128
- * bytes, but this is still the best order without sacrificing
- * the readability by splitting the structures.
- */
- struct rc_dec rc;
- struct dictionary dict;
- struct lzma2_dec lzma2;
- struct lzma_dec lzma;
-
- /*
- * Temporary buffer which holds small number of input bytes between
- * decoder calls. See lzma2_lzma() for details.
- */
- struct
- {
- uint32_t size;
- uint8_t buf[3 * LZMA_IN_REQUIRED];
- } temp;
+ /*
+ * The order below is important on x86 to reduce code size and
+ * it shouldn't hurt on other platforms. Everything up to and
+ * including lzma.pos_mask are in the first 128 bytes on x86-32,
+ * which allows using smaller instructions to access those
+ * variables. On x86-64, fewer variables fit into the first 128
+ * bytes, but this is still the best order without sacrificing
+ * the readability by splitting the structures.
+ */
+ struct rc_dec rc;
+ struct dictionary dict;
+ struct lzma2_dec lzma2;
+ struct lzma_dec lzma;
+
+ /*
+ * Temporary buffer which holds small number of input bytes between
+ * decoder calls. See lzma2_lzma() for details.
+ */
+ struct
+ {
+ uint32_t size;
+ uint8_t buf[3 * LZMA_IN_REQUIRED];
+ } temp;
};
/**************
@@ -293,31 +293,31 @@ struct xz_dec_lzma2
*/
static void dict_reset(struct dictionary *dict, struct xz_buf *b)
{
- if (DEC_IS_SINGLE(dict->mode))
- {
- dict->buf = b->out + b->out_pos;
- dict->end = b->out_size - b->out_pos;
- }
-
- dict->start = 0;
- dict->pos = 0;
- dict->limit = 0;
- dict->full = 0;
+ if (DEC_IS_SINGLE(dict->mode))
+ {
+ dict->buf = b->out + b->out_pos;
+ dict->end = b->out_size - b->out_pos;
+ }
+
+ dict->start = 0;
+ dict->pos = 0;
+ dict->limit = 0;
+ dict->full = 0;
}
/* Set dictionary write limit */
static void dict_limit(struct dictionary *dict, size_t out_max)
{
- if (dict->end - dict->pos <= out_max)
- dict->limit = dict->end;
- else
- dict->limit = dict->pos + out_max;
+ if (dict->end - dict->pos <= out_max)
+ dict->limit = dict->end;
+ else
+ dict->limit = dict->pos + out_max;
}
/* Return true if at least one byte can be written into the dictionary. */
static inline bool dict_has_space(const struct dictionary *dict)
{
- return dict->pos < dict->limit;
+ return dict->pos < dict->limit;
}
/*
@@ -328,12 +328,12 @@ static inline bool dict_has_space(const struct dictionary *dict)
*/
static inline uint32_t dict_get(const struct dictionary *dict, uint32_t dist)
{
- size_t offset = dict->pos - dist - 1;
+ size_t offset = dict->pos - dist - 1;
- if (dist >= dict->pos)
- offset += dict->end;
+ if (dist >= dict->pos)
+ offset += dict->end;
- return dict->full > 0 ? dict->buf[offset] : 0;
+ return dict->full > 0 ? dict->buf[offset] : 0;
}
/*
@@ -341,10 +341,10 @@ static inline uint32_t dict_get(const struct dictionary *dict, uint32_t dist)
*/
static inline void dict_put(struct dictionary *dict, uint8_t byte)
{
- dict->buf[dict->pos++] = byte;
+ dict->buf[dict->pos++] = byte;
- if (dict->full < dict->pos)
- dict->full = dict->pos;
+ if (dict->full < dict->pos)
+ dict->full = dict->pos;
}
/*
@@ -354,66 +354,66 @@ static inline void dict_put(struct dictionary *dict, uint8_t byte)
*/
static bool dict_repeat(struct dictionary *dict, uint32_t *len, uint32_t dist)
{
- size_t back;
- uint32_t left;
+ size_t back;
+ uint32_t left;
- if (dist >= dict->full || dist >= dict->size)
- return false;
+ if (dist >= dict->full || dist >= dict->size)
+ return false;
- left = min_t(size_t, dict->limit - dict->pos, *len);
- *len -= left;
+ left = min_t(size_t, dict->limit - dict->pos, *len);
+ *len -= left;
- back = dict->pos - dist - 1;
- if (dist >= dict->pos)
- back += dict->end;
+ back = dict->pos - dist - 1;
+ if (dist >= dict->pos)
+ back += dict->end;
- do
- {
- dict->buf[dict->pos++] = dict->buf[back++];
- if (back == dict->end)
- back = 0;
- } while (--left > 0);
+ do
+ {
+ dict->buf[dict->pos++] = dict->buf[back++];
+ if (back == dict->end)
+ back = 0;
+ } while (--left > 0);
- if (dict->full < dict->pos)
- dict->full = dict->pos;
+ if (dict->full < dict->pos)
+ dict->full = dict->pos;
- return true;
+ return true;
}
/* Copy uncompressed data as is from input to dictionary and output buffers. */
static void dict_uncompressed(struct dictionary *dict, struct xz_buf *b, uint32_t *left)
{
- size_t copy_size;
+ size_t copy_size;
- while (*left > 0 && b->in_pos < b->in_size && b->out_pos < b->out_size)
- {
- copy_size = min(b->in_size - b->in_pos, b->out_size - b->out_pos);
- if (copy_size > dict->end - dict->pos)
- copy_size = dict->end - dict->pos;
- if (copy_size > *left)
- copy_size = *left;
+ while (*left > 0 && b->in_pos < b->in_size && b->out_pos < b->out_size)
+ {
+ copy_size = min(b->in_size - b->in_pos, b->out_size - b->out_pos);
+ if (copy_size > dict->end - dict->pos)
+ copy_size = dict->end - dict->pos;
+ if (copy_size > *left)
+ copy_size = *left;
- *left -= copy_size;
+ *left -= copy_size;
- memcpy(dict->buf + dict->pos, b->in + b->in_pos, copy_size);
- dict->pos += copy_size;
+ memcpy(dict->buf + dict->pos, b->in + b->in_pos, copy_size);
+ dict->pos += copy_size;
- if (dict->full < dict->pos)
- dict->full = dict->pos;
+ if (dict->full < dict->pos)
+ dict->full = dict->pos;
- if (DEC_IS_MULTI(dict->mode))
- {
- if (dict->pos == dict->end)
- dict->pos = 0;
+ if (DEC_IS_MULTI(dict->mode))
+ {
+ if (dict->pos == dict->end)
+ dict->pos = 0;
- memcpy(b->out + b->out_pos, b->in + b->in_pos, copy_size);
- }
+ memcpy(b->out + b->out_pos, b->in + b->in_pos, copy_size);
+ }
- dict->start = dict->pos;
+ dict->start = dict->pos;
- b->out_pos += copy_size;
- b->in_pos += copy_size;
- }
+ b->out_pos += copy_size;
+ b->in_pos += copy_size;
+ }
}
/*
@@ -423,19 +423,19 @@ static void dict_uncompressed(struct dictionary *dict, struct xz_buf *b, uint32_
*/
static uint32_t dict_flush(struct dictionary *dict, struct xz_buf *b)
{
- size_t copy_size = dict->pos - dict->start;
+ size_t copy_size = dict->pos - dict->start;
- if (DEC_IS_MULTI(dict->mode))
- {
- if (dict->pos == dict->end)
- dict->pos = 0;
+ if (DEC_IS_MULTI(dict->mode))
+ {
+ if (dict->pos == dict->end)
+ dict->pos = 0;
- memcpy(b->out + b->out_pos, dict->buf + dict->start, copy_size);
- }
+ memcpy(b->out + b->out_pos, dict->buf + dict->start, copy_size);
+ }
- dict->start = dict->pos;
- b->out_pos += copy_size;
- return copy_size;
+ dict->start = dict->pos;
+ b->out_pos += copy_size;
+ return copy_size;
}
/*****************
@@ -445,9 +445,9 @@ static uint32_t dict_flush(struct dictionary *dict, struct xz_buf *b)
/* Reset the range decoder. */
static void rc_reset(struct rc_dec *rc)
{
- rc->range = (uint32_t) - 1;
- rc->code = 0;
- rc->init_bytes_left = RC_INIT_BYTES;
+ rc->range = (uint32_t) - 1;
+ rc->code = 0;
+ rc->init_bytes_left = RC_INIT_BYTES;
}
/*
@@ -456,22 +456,22 @@ static void rc_reset(struct rc_dec *rc)
*/
static bool rc_read_init(struct rc_dec *rc, struct xz_buf *b)
{
- while (rc->init_bytes_left > 0)
- {
- if (b->in_pos == b->in_size)
- return false;
+ while (rc->init_bytes_left > 0)
+ {
+ if (b->in_pos == b->in_size)
+ return false;
- rc->code = (rc->code << 8) + b->in[b->in_pos++];
- --rc->init_bytes_left;
- }
+ rc->code = (rc->code << 8) + b->in[b->in_pos++];
+ --rc->init_bytes_left;
+ }
- return true;
+ return true;
}
/* Return true if there may not be enough input for the next decoding loop. */
static inline bool rc_limit_exceeded(const struct rc_dec *rc)
{
- return rc->in_pos > rc->in_limit;
+ return rc->in_pos > rc->in_limit;
}
/*
@@ -480,17 +480,17 @@ static inline bool rc_limit_exceeded(const struct rc_dec *rc)
*/
static inline bool rc_is_finished(const struct rc_dec *rc)
{
- return rc->code == 0;
+ return rc->code == 0;
}
/* Read the next input byte if needed. */
static __always_inline void rc_normalize(struct rc_dec *rc)
{
- if (rc->range < RC_TOP_VALUE)
- {
- rc->range <<= RC_SHIFT_BITS;
- rc->code = (rc->code << RC_SHIFT_BITS) + rc->in[rc->in_pos++];
- }
+ if (rc->range < RC_TOP_VALUE)
+ {
+ rc->range <<= RC_SHIFT_BITS;
+ rc->code = (rc->code << RC_SHIFT_BITS) + rc->in[rc->in_pos++];
+ }
}
/*
@@ -506,79 +506,79 @@ static __always_inline void rc_normalize(struct rc_dec *rc)
*/
static __always_inline int rc_bit(struct rc_dec *rc, uint16_t *prob)
{
- uint32_t bound;
- int bit;
-
- rc_normalize(rc);
- bound = (rc->range >> RC_BIT_MODEL_TOTAL_BITS) * *prob;
- if (rc->code < bound)
- {
- rc->range = bound;
- *prob += (RC_BIT_MODEL_TOTAL - *prob) >> RC_MOVE_BITS;
- bit = 0;
- }
- else
- {
- rc->range -= bound;
- rc->code -= bound;
- *prob -= *prob >> RC_MOVE_BITS;
- bit = 1;
- }
-
- return bit;
+ uint32_t bound;
+ int bit;
+
+ rc_normalize(rc);
+ bound = (rc->range >> RC_BIT_MODEL_TOTAL_BITS) * *prob;
+ if (rc->code < bound)
+ {
+ rc->range = bound;
+ *prob += (RC_BIT_MODEL_TOTAL - *prob) >> RC_MOVE_BITS;
+ bit = 0;
+ }
+ else
+ {
+ rc->range -= bound;
+ rc->code -= bound;
+ *prob -= *prob >> RC_MOVE_BITS;
+ bit = 1;
+ }
+
+ return bit;
}
/* Decode a bittree starting from the most significant bit. */
static __always_inline uint32_t rc_bittree(struct rc_dec *rc, uint16_t *probs, uint32_t limit)
{
- uint32_t symbol = 1;
+ uint32_t symbol = 1;
- do
- {
- if (rc_bit(rc, &probs[symbol]))
- symbol = (symbol << 1) + 1;
- else
- symbol <<= 1;
- } while (symbol < limit);
+ do
+ {
+ if (rc_bit(rc, &probs[symbol]))
+ symbol = (symbol << 1) + 1;
+ else
+ symbol <<= 1;
+ } while (symbol < limit);
- return symbol;
+ return symbol;
}
/* Decode a bittree starting from the least significant bit. */
static __always_inline void rc_bittree_reverse(struct rc_dec *rc, uint16_t *probs,
- uint32_t *dest, uint32_t limit)
+ uint32_t *dest, uint32_t limit)
{
- uint32_t symbol = 1;
- uint32_t i = 0;
-
- do
- {
- if (rc_bit(rc, &probs[symbol]))
- {
- symbol = (symbol << 1) + 1;
- *dest += 1 << i;
- }
- else
- {
- symbol <<= 1;
- }
- } while (++i < limit);
+ uint32_t symbol = 1;
+ uint32_t i = 0;
+
+ do
+ {
+ if (rc_bit(rc, &probs[symbol]))
+ {
+ symbol = (symbol << 1) + 1;
+ *dest += 1 << i;
+ }
+ else
+ {
+ symbol <<= 1;
+ }
+ } while (++i < limit);
}
/* Decode direct bits (fixed fifty-fifty probability) */
static inline void rc_direct(struct rc_dec *rc, uint32_t *dest, uint32_t limit)
{
- uint32_t mask;
-
- do
- {
- rc_normalize(rc);
- rc->range >>= 1;
- rc->code -= rc->range;
- mask = (uint32_t)0 - (rc->code >> 31);
- rc->code += rc->range & mask;
- *dest = (*dest << 1) + (mask + 1);
- } while (--limit > 0);
+ uint32_t mask;
+
+ do
+ {
+ rc_normalize(rc);
+ rc->range >>= 1;
+ rc->code -= rc->range;
+ mask = (uint32_t)0 - (rc->code >> 31);
+ rc->code += rc->range & mask;
+ *dest = (*dest << 1) + (mask + 1);
+ } while (--limit > 0);
}
/********
@@ -588,128 +588,128 @@ static inline void rc_direct(struct rc_dec *rc, uint32_t *dest, uint32_t limit)
/* Get pointer to literal coder probability array. */
static uint16_t *lzma_literal_probs(struct xz_dec_lzma2 *s)
{
- uint32_t prev_byte = dict_get(&s->dict, 0);
- uint32_t low = prev_byte >> (8 - s->lzma.lc);
- uint32_t high = (s->dict.pos & s->lzma.literal_pos_mask) << s->lzma.lc;
- return s->lzma.literal[low + high];
+ uint32_t prev_byte = dict_get(&s->dict, 0);
+ uint32_t low = prev_byte >> (8 - s->lzma.lc);
+ uint32_t high = (s->dict.pos & s->lzma.literal_pos_mask) << s->lzma.lc;
+ return s->lzma.literal[low + high];
}
/* Decode a literal (one 8-bit byte) */
static void lzma_literal(struct xz_dec_lzma2 *s)
{
- uint16_t *probs;
- uint32_t symbol;
- uint32_t match_byte;
- uint32_t match_bit;
- uint32_t offset;
- uint32_t i;
-
- probs = lzma_literal_probs(s);
-
- if (lzma_state_is_literal(s->lzma.state))
- {
- symbol = rc_bittree(&s->rc, probs, 0x100);
- }
- else
- {
- symbol = 1;
- match_byte = dict_get(&s->dict, s->lzma.rep0) << 1;
- offset = 0x100;
-
- do
- {
- match_bit = match_byte & offset;
- match_byte <<= 1;
- i = offset + match_bit + symbol;
-
- if (rc_bit(&s->rc, &probs[i]))
- {
- symbol = (symbol << 1) + 1;
- offset &= match_bit;
- }
- else
- {
- symbol <<= 1;
- offset &= ~match_bit;
- }
- } while (symbol < 0x100);
- }
-
- dict_put(&s->dict, (uint8_t)symbol);
- lzma_state_literal(&s->lzma.state);
+ uint16_t *probs;
+ uint32_t symbol;
+ uint32_t match_byte;
+ uint32_t match_bit;
+ uint32_t offset;
+ uint32_t i;
+
+ probs = lzma_literal_probs(s);
+
+ if (lzma_state_is_literal(s->lzma.state))
+ {
+ symbol = rc_bittree(&s->rc, probs, 0x100);
+ }
+ else
+ {
+ symbol = 1;
+ match_byte = dict_get(&s->dict, s->lzma.rep0) << 1;
+ offset = 0x100;
+
+ do
+ {
+ match_bit = match_byte & offset;
+ match_byte <<= 1;
+ i = offset + match_bit + symbol;
+
+ if (rc_bit(&s->rc, &probs[i]))
+ {
+ symbol = (symbol << 1) + 1;
+ offset &= match_bit;
+ }
+ else
+ {
+ symbol <<= 1;
+ offset &= ~match_bit;
+ }
+ } while (symbol < 0x100);
+ }
+
+ dict_put(&s->dict, (uint8_t)symbol);
+ lzma_state_literal(&s->lzma.state);
}
/* Decode the length of the match into s->lzma.len. */
static void lzma_len(struct xz_dec_lzma2 *s, struct lzma_len_dec *l, uint32_t pos_state)
{
- uint16_t *probs;
- uint32_t limit;
-
- if (!rc_bit(&s->rc, &l->choice))
- {
- probs = l->low[pos_state];
- limit = LEN_LOW_SYMBOLS;
- s->lzma.len = MATCH_LEN_MIN;
- }
- else
- {
- if (!rc_bit(&s->rc, &l->choice2))
- {
- probs = l->mid[pos_state];
- limit = LEN_MID_SYMBOLS;
- s->lzma.len = MATCH_LEN_MIN + LEN_LOW_SYMBOLS;
- }
- else
- {
- probs = l->high;
- limit = LEN_HIGH_SYMBOLS;
- s->lzma.len = MATCH_LEN_MIN + LEN_LOW_SYMBOLS + LEN_MID_SYMBOLS;
- }
- }
-
- s->lzma.len += rc_bittree(&s->rc, probs, limit) - limit;
+ uint16_t *probs;
+ uint32_t limit;
+
+ if (!rc_bit(&s->rc, &l->choice))
+ {
+ probs = l->low[pos_state];
+ limit = LEN_LOW_SYMBOLS;
+ s->lzma.len = MATCH_LEN_MIN;
+ }
+ else
+ {
+ if (!rc_bit(&s->rc, &l->choice2))
+ {
+ probs = l->mid[pos_state];
+ limit = LEN_MID_SYMBOLS;
+ s->lzma.len = MATCH_LEN_MIN + LEN_LOW_SYMBOLS;
+ }
+ else
+ {
+ probs = l->high;
+ limit = LEN_HIGH_SYMBOLS;
+ s->lzma.len = MATCH_LEN_MIN + LEN_LOW_SYMBOLS + LEN_MID_SYMBOLS;
+ }
+ }
+
+ s->lzma.len += rc_bittree(&s->rc, probs, limit) - limit;
}
/* Decode a match. The distance will be stored in s->lzma.rep0. */
static void lzma_match(struct xz_dec_lzma2 *s, uint32_t pos_state)
{
- uint16_t *probs;
- uint32_t dist_slot;
- uint32_t limit;
-
- lzma_state_match(&s->lzma.state);
-
- s->lzma.rep3 = s->lzma.rep2;
- s->lzma.rep2 = s->lzma.rep1;
- s->lzma.rep1 = s->lzma.rep0;
-
- lzma_len(s, &s->lzma.match_len_dec, pos_state);
-
- probs = s->lzma.dist_slot[lzma_get_dist_state(s->lzma.len)];
- dist_slot = rc_bittree(&s->rc, probs, DIST_SLOTS) - DIST_SLOTS;
-
- if (dist_slot < DIST_MODEL_START)
- {
- s->lzma.rep0 = dist_slot;
- }
- else
- {
- limit = (dist_slot >> 1) - 1;
- s->lzma.rep0 = 2 + (dist_slot & 1);
-
- if (dist_slot < DIST_MODEL_END)
- {
- s->lzma.rep0 <<= limit;
- probs = s->lzma.dist_special + s->lzma.rep0 - dist_slot - 1;
- rc_bittree_reverse(&s->rc, probs, &s->lzma.rep0, limit);
- }
- else
- {
- rc_direct(&s->rc, &s->lzma.rep0, limit - ALIGN_BITS);
- s->lzma.rep0 <<= ALIGN_BITS;
- rc_bittree_reverse(&s->rc, s->lzma.dist_align, &s->lzma.rep0, ALIGN_BITS);
- }
- }
+ uint16_t *probs;
+ uint32_t dist_slot;
+ uint32_t limit;
+
+ lzma_state_match(&s->lzma.state);
+
+ s->lzma.rep3 = s->lzma.rep2;
+ s->lzma.rep2 = s->lzma.rep1;
+ s->lzma.rep1 = s->lzma.rep0;
+
+ lzma_len(s, &s->lzma.match_len_dec, pos_state);
+
+ probs = s->lzma.dist_slot[lzma_get_dist_state(s->lzma.len)];
+ dist_slot = rc_bittree(&s->rc, probs, DIST_SLOTS) - DIST_SLOTS;
+
+ if (dist_slot < DIST_MODEL_START)
+ {
+ s->lzma.rep0 = dist_slot;
+ }
+ else
+ {
+ limit = (dist_slot >> 1) - 1;
+ s->lzma.rep0 = 2 + (dist_slot & 1);
+
+ if (dist_slot < DIST_MODEL_END)
+ {
+ s->lzma.rep0 <<= limit;
+ probs = s->lzma.dist_special + s->lzma.rep0 - dist_slot - 1;
+ rc_bittree_reverse(&s->rc, probs, &s->lzma.rep0, limit);
+ }
+ else
+ {
+ rc_direct(&s->rc, &s->lzma.rep0, limit - ALIGN_BITS);
+ s->lzma.rep0 <<= ALIGN_BITS;
+ rc_bittree_reverse(&s->rc, s->lzma.dist_align, &s->lzma.rep0, ALIGN_BITS);
+ }
+ }
}
/*
@@ -718,89 +718,89 @@ static void lzma_match(struct xz_dec_lzma2 *s, uint32_t pos_state)
*/
static void lzma_rep_match(struct xz_dec_lzma2 *s, uint32_t pos_state)
{
- uint32_t tmp;
-
- if (!rc_bit(&s->rc, &s->lzma.is_rep0[s->lzma.state]))
- {
- if (!rc_bit(&s->rc, &s->lzma.is_rep0_long[s->lzma.state][pos_state]))
- {
- lzma_state_short_rep(&s->lzma.state);
- s->lzma.len = 1;
- return;
- }
- }
- else
- {
- if (!rc_bit(&s->rc, &s->lzma.is_rep1[s->lzma.state]))
- {
- tmp = s->lzma.rep1;
- }
- else
- {
- if (!rc_bit(&s->rc, &s->lzma.is_rep2[s->lzma.state]))
- {
- tmp = s->lzma.rep2;
- }
- else
- {
- tmp = s->lzma.rep3;
- s->lzma.rep3 = s->lzma.rep2;
- }
-
- s->lzma.rep2 = s->lzma.rep1;
- }
-
- s->lzma.rep1 = s->lzma.rep0;
- s->lzma.rep0 = tmp;
- }
-
- lzma_state_long_rep(&s->lzma.state);
- lzma_len(s, &s->lzma.rep_len_dec, pos_state);
+ uint32_t tmp;
+
+ if (!rc_bit(&s->rc, &s->lzma.is_rep0[s->lzma.state]))
+ {
+ if (!rc_bit(&s->rc, &s->lzma.is_rep0_long[s->lzma.state][pos_state]))
+ {
+ lzma_state_short_rep(&s->lzma.state);
+ s->lzma.len = 1;
+ return;
+ }
+ }
+ else
+ {
+ if (!rc_bit(&s->rc, &s->lzma.is_rep1[s->lzma.state]))
+ {
+ tmp = s->lzma.rep1;
+ }
+ else
+ {
+ if (!rc_bit(&s->rc, &s->lzma.is_rep2[s->lzma.state]))
+ {
+ tmp = s->lzma.rep2;
+ }
+ else
+ {
+ tmp = s->lzma.rep3;
+ s->lzma.rep3 = s->lzma.rep2;
+ }
+
+ s->lzma.rep2 = s->lzma.rep1;
+ }
+
+ s->lzma.rep1 = s->lzma.rep0;
+ s->lzma.rep0 = tmp;
+ }
+
+ lzma_state_long_rep(&s->lzma.state);
+ lzma_len(s, &s->lzma.rep_len_dec, pos_state);
}
/* LZMA decoder core */
static bool lzma_main(struct xz_dec_lzma2 *s)
{
- uint32_t pos_state;
-
- /*
- * If the dictionary was reached during the previous call, try to
- * finish the possibly pending repeat in the dictionary.
- */
- if (dict_has_space(&s->dict) && s->lzma.len > 0)
- dict_repeat(&s->dict, &s->lzma.len, s->lzma.rep0);
-
- /*
- * Decode more LZMA symbols. One iteration may consume up to
- * LZMA_IN_REQUIRED - 1 bytes.
- */
- while (dict_has_space(&s->dict) && !rc_limit_exceeded(&s->rc))
- {
- pos_state = s->dict.pos & s->lzma.pos_mask;
-
- if (!rc_bit(&s->rc, &s->lzma.is_match[s->lzma.state][pos_state]))
- {
- lzma_literal(s);
- }
- else
- {
- if (rc_bit(&s->rc, &s->lzma.is_rep[s->lzma.state]))
- lzma_rep_match(s, pos_state);
- else
- lzma_match(s, pos_state);
-
- if (!dict_repeat(&s->dict, &s->lzma.len, s->lzma.rep0))
- return false;
- }
- }
-
- /*
- * Having the range decoder always normalized when we are outside
- * this function makes it easier to correctly handle end of the chunk.
- */
- rc_normalize(&s->rc);
-
- return true;
+ uint32_t pos_state;
+
+ /*
+ * If the dictionary was reached during the previous call, try to
+ * finish the possibly pending repeat in the dictionary.
+ */
+ if (dict_has_space(&s->dict) && s->lzma.len > 0)
+ dict_repeat(&s->dict, &s->lzma.len, s->lzma.rep0);
+
+ /*
+ * Decode more LZMA symbols. One iteration may consume up to
+ * LZMA_IN_REQUIRED - 1 bytes.
+ */
+ while (dict_has_space(&s->dict) && !rc_limit_exceeded(&s->rc))
+ {
+ pos_state = s->dict.pos & s->lzma.pos_mask;
+
+ if (!rc_bit(&s->rc, &s->lzma.is_match[s->lzma.state][pos_state]))
+ {
+ lzma_literal(s);
+ }
+ else
+ {
+ if (rc_bit(&s->rc, &s->lzma.is_rep[s->lzma.state]))
+ lzma_rep_match(s, pos_state);
+ else
+ lzma_match(s, pos_state);
+
+ if (!dict_repeat(&s->dict, &s->lzma.len, s->lzma.rep0))
+ return false;
+ }
+ }
+
+ /*
+ * Having the range decoder always normalized when we are outside
+ * this function makes it easier to correctly handle end of the chunk.
+ */
+ rc_normalize(&s->rc);
+
+ return true;
}
/*
@@ -809,29 +809,29 @@ static bool lzma_main(struct xz_dec_lzma2 *s)
*/
static void lzma_reset(struct xz_dec_lzma2 *s)
{
- uint16_t *probs;
- size_t i;
-
- s->lzma.state = STATE_LIT_LIT;
- s->lzma.rep0 = 0;
- s->lzma.rep1 = 0;
- s->lzma.rep2 = 0;
- s->lzma.rep3 = 0;
-
- /*
- * All probabilities are initialized to the same value. This hack
- * makes the code smaller by avoiding a separate loop for each
- * probability array.
- *
- * This could be optimized so that only that part of literal
- * probabilities that are actually required. In the common case
- * we would write 12 KiB less.
- */
- probs = s->lzma.is_match[0];
- for (i = 0; i < PROBS_TOTAL; ++i)
- probs[i] = RC_BIT_MODEL_TOTAL / 2;
-
- rc_reset(&s->rc);
+ uint16_t *probs;
+ size_t i;
+
+ s->lzma.state = STATE_LIT_LIT;
+ s->lzma.rep0 = 0;
+ s->lzma.rep1 = 0;
+ s->lzma.rep2 = 0;
+ s->lzma.rep3 = 0;
+
+ /*
+ * All probabilities are initialized to the same value. This hack
+ * makes the code smaller by avoiding a separate loop for each
+ * probability array.
+ *
+ * This could be optimized so that only that part of literal
+ * probabilities that are actually required. In the common case
+ * we would write 12 KiB less.
+ */
+ probs = s->lzma.is_match[0];
+ for (i = 0; i < PROBS_TOTAL; ++i)
+ probs[i] = RC_BIT_MODEL_TOTAL / 2;
+
+ rc_reset(&s->rc);
}
/*
@@ -841,35 +841,35 @@ static void lzma_reset(struct xz_dec_lzma2 *s)
*/
static bool lzma_props(struct xz_dec_lzma2 *s, uint8_t props)
{
- if (props > (4 * 5 + 4) * 9 + 8)
- return false;
+ if (props > (4 * 5 + 4) * 9 + 8)
+ return false;
- s->lzma.pos_mask = 0;
- while (props >= 9 * 5)
- {
- props -= 9 * 5;
- ++s->lzma.pos_mask;
- }
+ s->lzma.pos_mask = 0;
+ while (props >= 9 * 5)
+ {
+ props -= 9 * 5;
+ ++s->lzma.pos_mask;
+ }
- s->lzma.pos_mask = (1 << s->lzma.pos_mask) - 1;
+ s->lzma.pos_mask = (1 << s->lzma.pos_mask) - 1;
- s->lzma.literal_pos_mask = 0;
- while (props >= 9)
- {
- props -= 9;
- ++s->lzma.literal_pos_mask;
- }
+ s->lzma.literal_pos_mask = 0;
+ while (props >= 9)
+ {
+ props -= 9;
+ ++s->lzma.literal_pos_mask;
+ }
- s->lzma.lc = props;
+ s->lzma.lc = props;
- if (s->lzma.lc + s->lzma.literal_pos_mask > 4)
- return false;
+ if (s->lzma.lc + s->lzma.literal_pos_mask > 4)
+ return false;
- s->lzma.literal_pos_mask = (1 << s->lzma.literal_pos_mask) - 1;
+ s->lzma.literal_pos_mask = (1 << s->lzma.literal_pos_mask) - 1;
- lzma_reset(s);
+ lzma_reset(s);
- return true;
+ return true;
}
/*********
@@ -890,89 +890,89 @@ static bool lzma_props(struct xz_dec_lzma2 *s, uint8_t props)
*/
static bool lzma2_lzma(struct xz_dec_lzma2 *s, struct xz_buf *b)
{
- size_t in_avail;
- uint32_t tmp;
-
- in_avail = b->in_size - b->in_pos;
- if (s->temp.size > 0 || s->lzma2.compressed == 0)
- {
- tmp = 2 * LZMA_IN_REQUIRED - s->temp.size;
- if (tmp > s->lzma2.compressed - s->temp.size)
- tmp = s->lzma2.compressed - s->temp.size;
- if (tmp > in_avail)
- tmp = in_avail;
-
- memcpy(s->temp.buf + s->temp.size, b->in + b->in_pos, tmp);
-
- if (s->temp.size + tmp == s->lzma2.compressed)
- {
- memzero(s->temp.buf + s->temp.size + tmp, sizeof(s->temp.buf) - s->temp.size - tmp);
- s->rc.in_limit = s->temp.size + tmp;
- }
- else if (s->temp.size + tmp < LZMA_IN_REQUIRED)
- {
- s->temp.size += tmp;
- b->in_pos += tmp;
- return true;
- }
- else
- {
- s->rc.in_limit = s->temp.size + tmp - LZMA_IN_REQUIRED;
- }
-
- s->rc.in = s->temp.buf;
- s->rc.in_pos = 0;
-
- if (!lzma_main(s) || s->rc.in_pos > s->temp.size + tmp)
- return false;
-
- s->lzma2.compressed -= s->rc.in_pos;
-
- if (s->rc.in_pos < s->temp.size)
- {
- s->temp.size -= s->rc.in_pos;
- memmove(s->temp.buf, s->temp.buf + s->rc.in_pos, s->temp.size);
- return true;
- }
-
- b->in_pos += s->rc.in_pos - s->temp.size;
- s->temp.size = 0;
- }
-
- in_avail = b->in_size - b->in_pos;
- if (in_avail >= LZMA_IN_REQUIRED)
- {
- s->rc.in = b->in;
- s->rc.in_pos = b->in_pos;
-
- if (in_avail >= s->lzma2.compressed + LZMA_IN_REQUIRED)
- s->rc.in_limit = b->in_pos + s->lzma2.compressed;
- else
- s->rc.in_limit = b->in_size - LZMA_IN_REQUIRED;
-
- if (!lzma_main(s))
- return false;
-
- in_avail = s->rc.in_pos - b->in_pos;
- if (in_avail > s->lzma2.compressed)
- return false;
-
- s->lzma2.compressed -= in_avail;
- b->in_pos = s->rc.in_pos;
- }
-
- in_avail = b->in_size - b->in_pos;
- if (in_avail < LZMA_IN_REQUIRED)
- {
- if (in_avail > s->lzma2.compressed)
- in_avail = s->lzma2.compressed;
-
- memcpy(s->temp.buf, b->in + b->in_pos, in_avail);
- s->temp.size = in_avail;
- b->in_pos += in_avail;
- }
-
- return true;
+ size_t in_avail;
+ uint32_t tmp;
+
+ in_avail = b->in_size - b->in_pos;
+ if (s->temp.size > 0 || s->lzma2.compressed == 0)
+ {
+ tmp = 2 * LZMA_IN_REQUIRED - s->temp.size;
+ if (tmp > s->lzma2.compressed - s->temp.size)
+ tmp = s->lzma2.compressed - s->temp.size;
+ if (tmp > in_avail)
+ tmp = in_avail;
+
+ memcpy(s->temp.buf + s->temp.size, b->in + b->in_pos, tmp);
+
+ if (s->temp.size + tmp == s->lzma2.compressed)
+ {
+ memzero(s->temp.buf + s->temp.size + tmp, sizeof(s->temp.buf) - s->temp.size - tmp);
+ s->rc.in_limit = s->temp.size + tmp;
+ }
+ else if (s->temp.size + tmp < LZMA_IN_REQUIRED)
+ {
+ s->temp.size += tmp;
+ b->in_pos += tmp;
+ return true;
+ }
+ else
+ {
+ s->rc.in_limit = s->temp.size + tmp - LZMA_IN_REQUIRED;
+ }
+
+ s->rc.in = s->temp.buf;
+ s->rc.in_pos = 0;
+
+ if (!lzma_main(s) || s->rc.in_pos > s->temp.size + tmp)
+ return false;
+
+ s->lzma2.compressed -= s->rc.in_pos;
+
+ if (s->rc.in_pos < s->temp.size)
+ {
+ s->temp.size -= s->rc.in_pos;
+ memmove(s->temp.buf, s->temp.buf + s->rc.in_pos, s->temp.size);
+ return true;
+ }
+
+ b->in_pos += s->rc.in_pos - s->temp.size;
+ s->temp.size = 0;
+ }
+
+ in_avail = b->in_size - b->in_pos;
+ if (in_avail >= LZMA_IN_REQUIRED)
+ {
+ s->rc.in = b->in;
+ s->rc.in_pos = b->in_pos;
+
+ if (in_avail >= s->lzma2.compressed + LZMA_IN_REQUIRED)
+ s->rc.in_limit = b->in_pos + s->lzma2.compressed;
+ else
+ s->rc.in_limit = b->in_size - LZMA_IN_REQUIRED;
+
+ if (!lzma_main(s))
+ return false;
+
+ in_avail = s->rc.in_pos - b->in_pos;
+ if (in_avail > s->lzma2.compressed)
+ return false;
+
+ s->lzma2.compressed -= in_avail;
+ b->in_pos = s->rc.in_pos;
+ }
+
+ in_avail = b->in_size - b->in_pos;
+ if (in_avail < LZMA_IN_REQUIRED)
+ {
+ if (in_avail > s->lzma2.compressed)
+ in_avail = s->lzma2.compressed;
+
+ memcpy(s->temp.buf, b->in + b->in_pos, in_avail);
+ s->temp.size = in_avail;
+ b->in_pos += in_avail;
+ }
+
+ return true;
}
/*
@@ -981,251 +981,251 @@ static bool lzma2_lzma(struct xz_dec_lzma2 *s, struct xz_buf *b)
*/
XZ_EXTERN enum xz_ret xz_dec_lzma2_run(struct xz_dec_lzma2 *s, struct xz_buf *b)
{
- uint32_t tmp;
-
- while (b->in_pos < b->in_size || s->lzma2.sequence == SEQ_LZMA_RUN)
- {
- switch (s->lzma2.sequence)
- {
- case SEQ_CONTROL:
- /*
- * LZMA2 control byte
- *
- * Exact values:
- * 0x00 End marker
- * 0x01 Dictionary reset followed by
- * an uncompressed chunk
- * 0x02 Uncompressed chunk (no dictionary reset)
- *
- * Highest three bits (s->control & 0xE0):
- * 0xE0 Dictionary reset, new properties and state
- * reset, followed by LZMA compressed chunk
- * 0xC0 New properties and state reset, followed
- * by LZMA compressed chunk (no dictionary
- * reset)
- * 0xA0 State reset using old properties,
- * followed by LZMA compressed chunk (no
- * dictionary reset)
- * 0x80 LZMA chunk (no dictionary or state reset)
- *
- * For LZMA compressed chunks, the lowest five bits
- * (s->control & 1F) are the highest bits of the
- * uncompressed size (bits 16-20).
- *
- * A new LZMA2 stream must begin with a dictionary
- * reset. The first LZMA chunk must set new
- * properties and reset the LZMA state.
- *
- * Values that don't match anything described above
- * are invalid and we return XZ_DATA_ERROR.
- */
- tmp = b->in[b->in_pos++];
-
- if (tmp == 0x00)
- return XZ_STREAM_END;
-
- if (tmp >= 0xE0 || tmp == 0x01)
- {
- s->lzma2.need_props = true;
- s->lzma2.need_dict_reset = false;
- dict_reset(&s->dict, b);
- }
- else if (s->lzma2.need_dict_reset)
- {
- return XZ_DATA_ERROR;
- }
-
- if (tmp >= 0x80)
- {
- s->lzma2.uncompressed = (tmp & 0x1F) << 16;
- s->lzma2.sequence = SEQ_UNCOMPRESSED_1;
-
- if (tmp >= 0xC0)
- {
- /*
- * When there are new properties,
- * state reset is done at
- * SEQ_PROPERTIES.
- */
- s->lzma2.need_props = false;
- s->lzma2.next_sequence = SEQ_PROPERTIES;
- }
- else if (s->lzma2.need_props)
- {
- return XZ_DATA_ERROR;
- }
- else
- {
- s->lzma2.next_sequence = SEQ_LZMA_PREPARE;
- if (tmp >= 0xA0)
- lzma_reset(s);
- }
- }
- else
- {
- if (tmp > 0x02)
- return XZ_DATA_ERROR;
-
- s->lzma2.sequence = SEQ_COMPRESSED_0;
- s->lzma2.next_sequence = SEQ_COPY;
- }
-
- break;
-
- case SEQ_UNCOMPRESSED_1:
- s->lzma2.uncompressed += (uint32_t)b->in[b->in_pos++] << 8;
- s->lzma2.sequence = SEQ_UNCOMPRESSED_2;
- break;
-
- case SEQ_UNCOMPRESSED_2:
- s->lzma2.uncompressed += (uint32_t)b->in[b->in_pos++] + 1;
- s->lzma2.sequence = SEQ_COMPRESSED_0;
- break;
-
- case SEQ_COMPRESSED_0:
- s->lzma2.compressed = (uint32_t)b->in[b->in_pos++] << 8;
- s->lzma2.sequence = SEQ_COMPRESSED_1;
- break;
-
- case SEQ_COMPRESSED_1:
- s->lzma2.compressed += (uint32_t)b->in[b->in_pos++] + 1;
- s->lzma2.sequence = s->lzma2.next_sequence;
- break;
-
- case SEQ_PROPERTIES:
- if (!lzma_props(s, b->in[b->in_pos++]))
- return XZ_DATA_ERROR;
-
- s->lzma2.sequence = SEQ_LZMA_PREPARE;
-
- case SEQ_LZMA_PREPARE:
- if (s->lzma2.compressed < RC_INIT_BYTES)
- return XZ_DATA_ERROR;
-
- if (!rc_read_init(&s->rc, b))
- return XZ_OK;
-
- s->lzma2.compressed -= RC_INIT_BYTES;
- s->lzma2.sequence = SEQ_LZMA_RUN;
-
- case SEQ_LZMA_RUN:
- /*
- * Set dictionary limit to indicate how much we want
- * to be encoded at maximum. Decode new data into the
- * dictionary. Flush the new data from dictionary to
- * b->out. Check if we finished decoding this chunk.
- * In case the dictionary got full but we didn't fill
- * the output buffer yet, we may run this loop
- * multiple times without changing s->lzma2.sequence.
- */
- dict_limit(&s->dict,
- min_t(size_t, b->out_size - b->out_pos, s->lzma2.uncompressed));
- if (!lzma2_lzma(s, b))
- return XZ_DATA_ERROR;
-
- s->lzma2.uncompressed -= dict_flush(&s->dict, b);
-
- if (s->lzma2.uncompressed == 0)
- {
- if (s->lzma2.compressed > 0 || s->lzma.len > 0 || !rc_is_finished(&s->rc))
- return XZ_DATA_ERROR;
-
- rc_reset(&s->rc);
- s->lzma2.sequence = SEQ_CONTROL;
- }
- else if (b->out_pos == b->out_size ||
- (b->in_pos == b->in_size && s->temp.size < s->lzma2.compressed))
- {
- return XZ_OK;
- }
-
- break;
-
- case SEQ_COPY:
- dict_uncompressed(&s->dict, b, &s->lzma2.compressed);
- if (s->lzma2.compressed > 0)
- return XZ_OK;
-
- s->lzma2.sequence = SEQ_CONTROL;
- break;
- }
- }
-
- return XZ_OK;
+ uint32_t tmp;
+
+ while (b->in_pos < b->in_size || s->lzma2.sequence == SEQ_LZMA_RUN)
+ {
+ switch (s->lzma2.sequence)
+ {
+ case SEQ_CONTROL:
+ /*
+ * LZMA2 control byte
+ *
+ * Exact values:
+ * 0x00 End marker
+ * 0x01 Dictionary reset followed by
+ * an uncompressed chunk
+ * 0x02 Uncompressed chunk (no dictionary reset)
+ *
+ * Highest three bits (s->control & 0xE0):
+ * 0xE0 Dictionary reset, new properties and state
+ * reset, followed by LZMA compressed chunk
+ * 0xC0 New properties and state reset, followed
+ * by LZMA compressed chunk (no dictionary
+ * reset)
+ * 0xA0 State reset using old properties,
+ * followed by LZMA compressed chunk (no
+ * dictionary reset)
+ * 0x80 LZMA chunk (no dictionary or state reset)
+ *
+ * For LZMA compressed chunks, the lowest five bits
+ * (s->control & 1F) are the highest bits of the
+ * uncompressed size (bits 16-20).
+ *
+ * A new LZMA2 stream must begin with a dictionary
+ * reset. The first LZMA chunk must set new
+ * properties and reset the LZMA state.
+ *
+ * Values that don't match anything described above
+ * are invalid and we return XZ_DATA_ERROR.
+ */
+ tmp = b->in[b->in_pos++];
+
+ if (tmp == 0x00)
+ return XZ_STREAM_END;
+
+ if (tmp >= 0xE0 || tmp == 0x01)
+ {
+ s->lzma2.need_props = true;
+ s->lzma2.need_dict_reset = false;
+ dict_reset(&s->dict, b);
+ }
+ else if (s->lzma2.need_dict_reset)
+ {
+ return XZ_DATA_ERROR;
+ }
+
+ if (tmp >= 0x80)
+ {
+ s->lzma2.uncompressed = (tmp & 0x1F) << 16;
+ s->lzma2.sequence = SEQ_UNCOMPRESSED_1;
+
+ if (tmp >= 0xC0)
+ {
+ /*
+ * When there are new properties,
+ * state reset is done at
+ * SEQ_PROPERTIES.
+ */
+ s->lzma2.need_props = false;
+ s->lzma2.next_sequence = SEQ_PROPERTIES;
+ }
+ else if (s->lzma2.need_props)
+ {
+ return XZ_DATA_ERROR;
+ }
+ else
+ {
+ s->lzma2.next_sequence = SEQ_LZMA_PREPARE;
+ if (tmp >= 0xA0)
+ lzma_reset(s);
+ }
+ }
+ else
+ {
+ if (tmp > 0x02)
+ return XZ_DATA_ERROR;
+
+ s->lzma2.sequence = SEQ_COMPRESSED_0;
+ s->lzma2.next_sequence = SEQ_COPY;
+ }
+
+ break;
+
+ case SEQ_UNCOMPRESSED_1:
+ s->lzma2.uncompressed += (uint32_t)b->in[b->in_pos++] << 8;
+ s->lzma2.sequence = SEQ_UNCOMPRESSED_2;
+ break;
+
+ case SEQ_UNCOMPRESSED_2:
+ s->lzma2.uncompressed += (uint32_t)b->in[b->in_pos++] + 1;
+ s->lzma2.sequence = SEQ_COMPRESSED_0;
+ break;
+
+ case SEQ_COMPRESSED_0:
+ s->lzma2.compressed = (uint32_t)b->in[b->in_pos++] << 8;
+ s->lzma2.sequence = SEQ_COMPRESSED_1;
+ break;
+
+ case SEQ_COMPRESSED_1:
+ s->lzma2.compressed += (uint32_t)b->in[b->in_pos++] + 1;
+ s->lzma2.sequence = s->lzma2.next_sequence;
+ break;
+
+ case SEQ_PROPERTIES:
+ if (!lzma_props(s, b->in[b->in_pos++]))
+ return XZ_DATA_ERROR;
+
+ s->lzma2.sequence = SEQ_LZMA_PREPARE;
+
+ case SEQ_LZMA_PREPARE:
+ if (s->lzma2.compressed < RC_INIT_BYTES)
+ return XZ_DATA_ERROR;
+
+ if (!rc_read_init(&s->rc, b))
+ return XZ_OK;
+
+ s->lzma2.compressed -= RC_INIT_BYTES;
+ s->lzma2.sequence = SEQ_LZMA_RUN;
+
+ case SEQ_LZMA_RUN:
+ /*
+ * Set dictionary limit to indicate how much we want
+ * to be encoded at maximum. Decode new data into the
+ * dictionary. Flush the new data from dictionary to
+ * b->out. Check if we finished decoding this chunk.
+ * In case the dictionary got full but we didn't fill
+ * the output buffer yet, we may run this loop
+ * multiple times without changing s->lzma2.sequence.
+ */
+ dict_limit(&s->dict,
+ min_t(size_t, b->out_size - b->out_pos, s->lzma2.uncompressed));
+ if (!lzma2_lzma(s, b))
+ return XZ_DATA_ERROR;
+
+ s->lzma2.uncompressed -= dict_flush(&s->dict, b);
+
+ if (s->lzma2.uncompressed == 0)
+ {
+ if (s->lzma2.compressed > 0 || s->lzma.len > 0 || !rc_is_finished(&s->rc))
+ return XZ_DATA_ERROR;
+
+ rc_reset(&s->rc);
+ s->lzma2.sequence = SEQ_CONTROL;
+ }
+ else if (b->out_pos == b->out_size ||
+ (b->in_pos == b->in_size && s->temp.size < s->lzma2.compressed))
+ {
+ return XZ_OK;
+ }
+
+ break;
+
+ case SEQ_COPY:
+ dict_uncompressed(&s->dict, b, &s->lzma2.compressed);
+ if (s->lzma2.compressed > 0)
+ return XZ_OK;
+
+ s->lzma2.sequence = SEQ_CONTROL;
+ break;
+ }
+ }
+
+ return XZ_OK;
}
XZ_EXTERN struct xz_dec_lzma2 *xz_dec_lzma2_create(enum xz_mode mode, uint32_t dict_max)
{
- struct xz_dec_lzma2 *s = kmalloc(sizeof(*s), GFP_KERNEL);
- if (s == NULL)
- return NULL;
-
- s->dict.mode = mode;
- s->dict.size_max = dict_max;
-
- if (DEC_IS_PREALLOC(mode))
- {
- s->dict.buf = vmalloc(dict_max);
- if (s->dict.buf == NULL)
- {
- kfree(s);
- return NULL;
- }
- }
- else if (DEC_IS_DYNALLOC(mode))
- {
- s->dict.buf = NULL;
- s->dict.allocated = 0;
- }
-
- return s;
+ struct xz_dec_lzma2 *s = kmalloc(sizeof(*s), GFP_KERNEL);
+ if (s == NULL)
+ return NULL;
+
+ s->dict.mode = mode;
+ s->dict.size_max = dict_max;
+
+ if (DEC_IS_PREALLOC(mode))
+ {
+ s->dict.buf = vmalloc(dict_max);
+ if (s->dict.buf == NULL)
+ {
+ kfree(s);
+ return NULL;
+ }
+ }
+ else if (DEC_IS_DYNALLOC(mode))
+ {
+ s->dict.buf = NULL;
+ s->dict.allocated = 0;
+ }
+
+ return s;
}
XZ_EXTERN enum xz_ret xz_dec_lzma2_reset(struct xz_dec_lzma2 *s, uint8_t props)
{
- /* This limits dictionary size to 3 GiB to keep parsing simpler. */
- if (props > 39)
- return XZ_OPTIONS_ERROR;
-
- s->dict.size = 2 + (props & 1);
- s->dict.size <<= (props >> 1) + 11;
-
- if (DEC_IS_MULTI(s->dict.mode))
- {
- if (s->dict.size > s->dict.size_max)
- return XZ_MEMLIMIT_ERROR;
-
- s->dict.end = s->dict.size;
-
- if (DEC_IS_DYNALLOC(s->dict.mode))
- {
- if (s->dict.allocated < s->dict.size)
- {
- vfree(s->dict.buf);
- s->dict.buf = vmalloc(s->dict.size);
- if (s->dict.buf == NULL)
- {
- s->dict.allocated = 0;
- return XZ_MEM_ERROR;
- }
- }
- }
- }
-
- s->lzma.len = 0;
-
- s->lzma2.sequence = SEQ_CONTROL;
- s->lzma2.need_dict_reset = true;
-
- s->temp.size = 0;
-
- return XZ_OK;
+ /* This limits dictionary size to 3 GiB to keep parsing simpler. */
+ if (props > 39)
+ return XZ_OPTIONS_ERROR;
+
+ s->dict.size = 2 + (props & 1);
+ s->dict.size <<= (props >> 1) + 11;
+
+ if (DEC_IS_MULTI(s->dict.mode))
+ {
+ if (s->dict.size > s->dict.size_max)
+ return XZ_MEMLIMIT_ERROR;
+
+ s->dict.end = s->dict.size;
+
+ if (DEC_IS_DYNALLOC(s->dict.mode))
+ {
+ if (s->dict.allocated < s->dict.size)
+ {
+ vfree(s->dict.buf);
+ s->dict.buf = vmalloc(s->dict.size);
+ if (s->dict.buf == NULL)
+ {
+ s->dict.allocated = 0;
+ return XZ_MEM_ERROR;
+ }
+ }
+ }
+ }
+
+ s->lzma.len = 0;
+
+ s->lzma2.sequence = SEQ_CONTROL;
+ s->lzma2.need_dict_reset = true;
+
+ s->temp.size = 0;
+
+ return XZ_OK;
}
XZ_EXTERN void xz_dec_lzma2_end(struct xz_dec_lzma2 *s)
{
- if (DEC_IS_MULTI(s->dict.mode))
- vfree(s->dict.buf);
+ if (DEC_IS_MULTI(s->dict.mode))
+ vfree(s->dict.buf);
- kfree(s);
+ kfree(s);
}
diff --git a/libraries/xz-embedded/src/xz_dec_stream.c b/libraries/xz-embedded/src/xz_dec_stream.c
index 6e935ded..f8d7be05 100644
--- a/libraries/xz-embedded/src/xz_dec_stream.c
+++ b/libraries/xz-embedded/src/xz_dec_stream.c
@@ -19,146 +19,146 @@
/* Hash used to validate the Index field */
struct xz_dec_hash
{
- vli_type unpadded;
- vli_type uncompressed;
- uint32_t crc32;
+ vli_type unpadded;
+ vli_type uncompressed;
+ uint32_t crc32;
};
struct xz_dec
{
- /* Position in dec_main() */
- enum
- {
- SEQ_STREAM_HEADER,
- SEQ_BLOCK_START,
- SEQ_BLOCK_HEADER,
- SEQ_BLOCK_UNCOMPRESS,
- SEQ_BLOCK_PADDING,
- SEQ_BLOCK_CHECK,
- SEQ_INDEX,
- SEQ_INDEX_PADDING,
- SEQ_INDEX_CRC32,
- SEQ_STREAM_FOOTER
- } sequence;
-
- /* Position in variable-length integers and Check fields */
- uint32_t pos;
-
- /* Variable-length integer decoded by dec_vli() */
- vli_type vli;
-
- /* Saved in_pos and out_pos */
- size_t in_start;
- size_t out_start;
+ /* Position in dec_main() */
+ enum
+ {
+ SEQ_STREAM_HEADER,
+ SEQ_BLOCK_START,
+ SEQ_BLOCK_HEADER,
+ SEQ_BLOCK_UNCOMPRESS,
+ SEQ_BLOCK_PADDING,
+ SEQ_BLOCK_CHECK,
+ SEQ_INDEX,
+ SEQ_INDEX_PADDING,
+ SEQ_INDEX_CRC32,
+ SEQ_STREAM_FOOTER
+ } sequence;
+
+ /* Position in variable-length integers and Check fields */
+ uint32_t pos;
+
+ /* Variable-length integer decoded by dec_vli() */
+ vli_type vli;
+
+ /* Saved in_pos and out_pos */
+ size_t in_start;
+ size_t out_start;
#ifdef XZ_USE_CRC64
- /* CRC32 or CRC64 value in Block or CRC32 value in Index */
- uint64_t crc;
+ /* CRC32 or CRC64 value in Block or CRC32 value in Index */
+ uint64_t crc;
#else
- /* CRC32 value in Block or Index */
- uint32_t crc;
+ /* CRC32 value in Block or Index */
+ uint32_t crc;
#endif
- /* Type of the integrity check calculated from uncompressed data */
- enum xz_check check_type;
-
- /* Operation mode */
- enum xz_mode mode;
-
- /*
- * True if the next call to xz_dec_run() is allowed to return
- * XZ_BUF_ERROR.
- */
- bool allow_buf_error;
-
- /* Information stored in Block Header */
- struct
- {
- /*
- * Value stored in the Compressed Size field, or
- * VLI_UNKNOWN if Compressed Size is not present.
- */
- vli_type compressed;
-
- /*
- * Value stored in the Uncompressed Size field, or
- * VLI_UNKNOWN if Uncompressed Size is not present.
- */
- vli_type uncompressed;
-
- /* Size of the Block Header field */
- uint32_t size;
- } block_header;
-
- /* Information collected when decoding Blocks */
- struct
- {
- /* Observed compressed size of the current Block */
- vli_type compressed;
-
- /* Observed uncompressed size of the current Block */
- vli_type uncompressed;
-
- /* Number of Blocks decoded so far */
- vli_type count;
-
- /*
- * Hash calculated from the Block sizes. This is used to
- * validate the Index field.
- */
- struct xz_dec_hash hash;
- } block;
-
- /* Variables needed when verifying the Index field */
- struct
- {
- /* Position in dec_index() */
- enum
- {
- SEQ_INDEX_COUNT,
- SEQ_INDEX_UNPADDED,
- SEQ_INDEX_UNCOMPRESSED
- } sequence;
-
- /* Size of the Index in bytes */
- vli_type size;
-
- /* Number of Records (matches block.count in valid files) */
- vli_type count;
-
- /*
- * Hash calculated from the Records (matches block.hash in
- * valid files).
- */
- struct xz_dec_hash hash;
- } index;
-
- /*
- * Temporary buffer needed to hold Stream Header, Block Header,
- * and Stream Footer. The Block Header is the biggest (1 KiB)
- * so we reserve space according to that. buf[] has to be aligned
- * to a multiple of four bytes; the size_t variables before it
- * should guarantee this.
- */
- struct
- {
- size_t pos;
- size_t size;
- uint8_t buf[1024];
- } temp;
-
- struct xz_dec_lzma2 *lzma2;
+ /* Type of the integrity check calculated from uncompressed data */
+ enum xz_check check_type;
+
+ /* Operation mode */
+ enum xz_mode mode;
+
+ /*
+ * True if the next call to xz_dec_run() is allowed to return
+ * XZ_BUF_ERROR.
+ */
+ bool allow_buf_error;
+
+ /* Information stored in Block Header */
+ struct
+ {
+ /*
+ * Value stored in the Compressed Size field, or
+ * VLI_UNKNOWN if Compressed Size is not present.
+ */
+ vli_type compressed;
+
+ /*
+ * Value stored in the Uncompressed Size field, or
+ * VLI_UNKNOWN if Uncompressed Size is not present.
+ */
+ vli_type uncompressed;
+
+ /* Size of the Block Header field */
+ uint32_t size;
+ } block_header;
+
+ /* Information collected when decoding Blocks */
+ struct
+ {
+ /* Observed compressed size of the current Block */
+ vli_type compressed;
+
+ /* Observed uncompressed size of the current Block */
+ vli_type uncompressed;
+
+ /* Number of Blocks decoded so far */
+ vli_type count;
+
+ /*
+ * Hash calculated from the Block sizes. This is used to
+ * validate the Index field.
+ */
+ struct xz_dec_hash hash;
+ } block;
+
+ /* Variables needed when verifying the Index field */
+ struct
+ {
+ /* Position in dec_index() */
+ enum
+ {
+ SEQ_INDEX_COUNT,
+ SEQ_INDEX_UNPADDED,
+ SEQ_INDEX_UNCOMPRESSED
+ } sequence;
+
+ /* Size of the Index in bytes */
+ vli_type size;
+
+ /* Number of Records (matches block.count in valid files) */
+ vli_type count;
+
+ /*
+ * Hash calculated from the Records (matches block.hash in
+ * valid files).
+ */
+ struct xz_dec_hash hash;
+ } index;
+
+ /*
+ * Temporary buffer needed to hold Stream Header, Block Header,
+ * and Stream Footer. The Block Header is the biggest (1 KiB)
+ * so we reserve space according to that. buf[] has to be aligned
+ * to a multiple of four bytes; the size_t variables before it
+ * should guarantee this.
+ */
+ struct
+ {
+ size_t pos;
+ size_t size;
+ uint8_t buf[1024];
+ } temp;
+
+ struct xz_dec_lzma2 *lzma2;
#ifdef XZ_DEC_BCJ
- struct xz_dec_bcj *bcj;
- bool bcj_active;
+ struct xz_dec_bcj *bcj;
+ bool bcj_active;
#endif
};
#ifdef XZ_DEC_ANY_CHECK
/* Sizes of the Check field with different Check IDs */
static const uint8_t check_sizes[16] = {0, 4, 4, 4, 8, 8, 8, 16,
- 16, 16, 32, 32, 32, 64, 64, 64};
+ 16, 16, 32, 32, 32, 64, 64, 64};
#endif
/*
@@ -169,52 +169,52 @@ static const uint8_t check_sizes[16] = {0, 4, 4, 4, 8, 8, 8, 16,
*/
static bool fill_temp(struct xz_dec *s, struct xz_buf *b)
{
- size_t copy_size = min_t(size_t, b->in_size - b->in_pos, s->temp.size - s->temp.pos);
+ size_t copy_size = min_t(size_t, b->in_size - b->in_pos, s->temp.size - s->temp.pos);
- memcpy(s->temp.buf + s->temp.pos, b->in + b->in_pos, copy_size);
- b->in_pos += copy_size;
- s->temp.pos += copy_size;
+ memcpy(s->temp.buf + s->temp.pos, b->in + b->in_pos, copy_size);
+ b->in_pos += copy_size;
+ s->temp.pos += copy_size;
- if (s->temp.pos == s->temp.size)
- {
- s->temp.pos = 0;
- return true;
- }
+ if (s->temp.pos == s->temp.size)
+ {
+ s->temp.pos = 0;
+ return true;
+ }
- return false;
+ return false;
}
/* Decode a variable-length integer (little-endian base-128 encoding) */
static enum xz_ret dec_vli(struct xz_dec *s, const uint8_t *in, size_t *in_pos, size_t in_size)
{
- uint8_t byte;
+ uint8_t byte;
- if (s->pos == 0)
- s->vli = 0;
+ if (s->pos == 0)
+ s->vli = 0;
- while (*in_pos < in_size)
- {
- byte = in[*in_pos];
- ++*in_pos;
+ while (*in_pos < in_size)
+ {
+ byte = in[*in_pos];
+ ++*in_pos;
- s->vli |= (vli_type)(byte & 0x7F) << s->pos;
+ s->vli |= (vli_type)(byte & 0x7F) << s->pos;
- if ((byte & 0x80) == 0)
- {
- /* Don't allow non-minimal encodings. */
- if (byte == 0 && s->pos != 0)
- return XZ_DATA_ERROR;
+ if ((byte & 0x80) == 0)
+ {
+ /* Don't allow non-minimal encodings. */
+ if (byte == 0 && s->pos != 0)
+ return XZ_DATA_ERROR;
- s->pos = 0;
- return XZ_STREAM_END;
- }
+ s->pos = 0;
+ return XZ_STREAM_END;
+ }
- s->pos += 7;
- if (s->pos == 7 * VLI_BYTES_MAX)
- return XZ_DATA_ERROR;
- }
+ s->pos += 7;
+ if (s->pos == 7 * VLI_BYTES_MAX)
+ return XZ_DATA_ERROR;
+ }
- return XZ_OK;
+ return XZ_OK;
}
/*
@@ -231,73 +231,73 @@ static enum xz_ret dec_vli(struct xz_dec *s, const uint8_t *in, size_t *in_pos,
*/
static enum xz_ret dec_block(struct xz_dec *s, struct xz_buf *b)
{
- enum xz_ret ret;
+ enum xz_ret ret;
- s->in_start = b->in_pos;
- s->out_start = b->out_pos;
+ s->in_start = b->in_pos;
+ s->out_start = b->out_pos;
#ifdef XZ_DEC_BCJ
- if (s->bcj_active)
- ret = xz_dec_bcj_run(s->bcj, s->lzma2, b);
- else
+ if (s->bcj_active)
+ ret = xz_dec_bcj_run(s->bcj, s->lzma2, b);
+ else
#endif
- ret = xz_dec_lzma2_run(s->lzma2, b);
+ ret = xz_dec_lzma2_run(s->lzma2, b);
- s->block.compressed += b->in_pos - s->in_start;
- s->block.uncompressed += b->out_pos - s->out_start;
+ s->block.compressed += b->in_pos - s->in_start;
+ s->block.uncompressed += b->out_pos - s->out_start;
- /*
- * There is no need to separately check for VLI_UNKNOWN, since
- * the observed sizes are always smaller than VLI_UNKNOWN.
- */
- if (s->block.compressed > s->block_header.compressed ||
- s->block.uncompressed > s->block_header.uncompressed)
- return XZ_DATA_ERROR;
+ /*
+ * There is no need to separately check for VLI_UNKNOWN, since
+ * the observed sizes are always smaller than VLI_UNKNOWN.
+ */
+ if (s->block.compressed > s->block_header.compressed ||
+ s->block.uncompressed > s->block_header.uncompressed)
+ return XZ_DATA_ERROR;
- if (s->check_type == XZ_CHECK_CRC32)
- s->crc = xz_crc32(b->out + s->out_start, b->out_pos - s->out_start, s->crc);
+ if (s->check_type == XZ_CHECK_CRC32)
+ s->crc = xz_crc32(b->out + s->out_start, b->out_pos - s->out_start, s->crc);
#ifdef XZ_USE_CRC64
- else if (s->check_type == XZ_CHECK_CRC64)
- s->crc = xz_crc64(b->out + s->out_start, b->out_pos - s->out_start, s->crc);
+ else if (s->check_type == XZ_CHECK_CRC64)
+ s->crc = xz_crc64(b->out + s->out_start, b->out_pos - s->out_start, s->crc);
#endif
- if (ret == XZ_STREAM_END)
- {
- if (s->block_header.compressed != VLI_UNKNOWN &&
- s->block_header.compressed != s->block.compressed)
- return XZ_DATA_ERROR;
+ if (ret == XZ_STREAM_END)
+ {
+ if (s->block_header.compressed != VLI_UNKNOWN &&
+ s->block_header.compressed != s->block.compressed)
+ return XZ_DATA_ERROR;
- if (s->block_header.uncompressed != VLI_UNKNOWN &&
- s->block_header.uncompressed != s->block.uncompressed)
- return XZ_DATA_ERROR;
+ if (s->block_header.uncompressed != VLI_UNKNOWN &&
+ s->block_header.uncompressed != s->block.uncompressed)
+ return XZ_DATA_ERROR;
- s->block.hash.unpadded += s->block_header.size + s->block.compressed;
+ s->block.hash.unpadded += s->block_header.size + s->block.compressed;
#ifdef XZ_DEC_ANY_CHECK
- s->block.hash.unpadded += check_sizes[s->check_type];
+ s->block.hash.unpadded += check_sizes[s->check_type];
#else
- if (s->check_type == XZ_CHECK_CRC32)
- s->block.hash.unpadded += 4;
- else if (IS_CRC64(s->check_type))
- s->block.hash.unpadded += 8;
+ if (s->check_type == XZ_CHECK_CRC32)
+ s->block.hash.unpadded += 4;
+ else if (IS_CRC64(s->check_type))
+ s->block.hash.unpadded += 8;
#endif
- s->block.hash.uncompressed += s->block.uncompressed;
- s->block.hash.crc32 = xz_crc32((const uint8_t *)&s->block.hash, sizeof(s->block.hash),
- s->block.hash.crc32);
+ s->block.hash.uncompressed += s->block.uncompressed;
+ s->block.hash.crc32 = xz_crc32((const uint8_t *)&s->block.hash, sizeof(s->block.hash),
+ s->block.hash.crc32);
- ++s->block.count;
- }
+ ++s->block.count;
+ }
- return ret;
+ return ret;
}
/* Update the Index size and the CRC32 value. */
static void index_update(struct xz_dec *s, const struct xz_buf *b)
{
- size_t in_used = b->in_pos - s->in_start;
- s->index.size += in_used;
- s->crc = xz_crc32(b->in + s->in_start, in_used, s->crc);
+ size_t in_used = b->in_pos - s->in_start;
+ s->index.size += in_used;
+ s->crc = xz_crc32(b->in + s->in_start, in_used, s->crc);
}
/*
@@ -310,49 +310,49 @@ static void index_update(struct xz_dec *s, const struct xz_buf *b)
*/
static enum xz_ret dec_index(struct xz_dec *s, struct xz_buf *b)
{
- enum xz_ret ret;
-
- do
- {
- ret = dec_vli(s, b->in, &b->in_pos, b->in_size);
- if (ret != XZ_STREAM_END)
- {
- index_update(s, b);
- return ret;
- }
-
- switch (s->index.sequence)
- {
- case SEQ_INDEX_COUNT:
- s->index.count = s->vli;
-
- /*
- * Validate that the Number of Records field
- * indicates the same number of Records as
- * there were Blocks in the Stream.
- */
- if (s->index.count != s->block.count)
- return XZ_DATA_ERROR;
-
- s->index.sequence = SEQ_INDEX_UNPADDED;
- break;
-
- case SEQ_INDEX_UNPADDED:
- s->index.hash.unpadded += s->vli;
- s->index.sequence = SEQ_INDEX_UNCOMPRESSED;
- break;
-
- case SEQ_INDEX_UNCOMPRESSED:
- s->index.hash.uncompressed += s->vli;
- s->index.hash.crc32 = xz_crc32((const uint8_t *)&s->index.hash,
- sizeof(s->index.hash), s->index.hash.crc32);
- --s->index.count;
- s->index.sequence = SEQ_INDEX_UNPADDED;
- break;
- }
- } while (s->index.count > 0);
-
- return XZ_STREAM_END;
+ enum xz_ret ret;
+
+ do
+ {
+ ret = dec_vli(s, b->in, &b->in_pos, b->in_size);
+ if (ret != XZ_STREAM_END)
+ {
+ index_update(s, b);
+ return ret;
+ }
+
+ switch (s->index.sequence)
+ {
+ case SEQ_INDEX_COUNT:
+ s->index.count = s->vli;
+
+ /*
+ * Validate that the Number of Records field
+ * indicates the same number of Records as
+ * there were Blocks in the Stream.
+ */
+ if (s->index.count != s->block.count)
+ return XZ_DATA_ERROR;
+
+ s->index.sequence = SEQ_INDEX_UNPADDED;
+ break;
+
+ case SEQ_INDEX_UNPADDED:
+ s->index.hash.unpadded += s->vli;
+ s->index.sequence = SEQ_INDEX_UNCOMPRESSED;
+ break;
+
+ case SEQ_INDEX_UNCOMPRESSED:
+ s->index.hash.uncompressed += s->vli;
+ s->index.hash.crc32 = xz_crc32((const uint8_t *)&s->index.hash,
+ sizeof(s->index.hash), s->index.hash.crc32);
+ --s->index.count;
+ s->index.sequence = SEQ_INDEX_UNPADDED;
+ break;
+ }
+ } while (s->index.count > 0);
+
+ return XZ_STREAM_END;
}
/*
@@ -362,22 +362,22 @@ static enum xz_ret dec_index(struct xz_dec *s, struct xz_buf *b)
*/
static enum xz_ret crc_validate(struct xz_dec *s, struct xz_buf *b, uint32_t bits)
{
- do
- {
- if (b->in_pos == b->in_size)
- return XZ_OK;
+ do
+ {
+ if (b->in_pos == b->in_size)
+ return XZ_OK;
- if (((s->crc >> s->pos) & 0xFF) != b->in[b->in_pos++])
- return XZ_DATA_ERROR;
+ if (((s->crc >> s->pos) & 0xFF) != b->in[b->in_pos++])
+ return XZ_DATA_ERROR;
- s->pos += 8;
+ s->pos += 8;
- } while (s->pos < bits);
+ } while (s->pos < bits);
- s->crc = 0;
- s->pos = 0;
+ s->crc = 0;
+ s->pos = 0;
- return XZ_STREAM_END;
+ return XZ_STREAM_END;
}
#ifdef XZ_DEC_ANY_CHECK
@@ -387,358 +387,358 @@ static enum xz_ret crc_validate(struct xz_dec *s, struct xz_buf *b, uint32_t bit
*/
static bool check_skip(struct xz_dec *s, struct xz_buf *b)
{
- while (s->pos < check_sizes[s->check_type])
- {
- if (b->in_pos == b->in_size)
- return false;
+ while (s->pos < check_sizes[s->check_type])
+ {
+ if (b->in_pos == b->in_size)
+ return false;
- ++b->in_pos;
- ++s->pos;
- }
+ ++b->in_pos;
+ ++s->pos;
+ }
- s->pos = 0;
+ s->pos = 0;
- return true;
+ return true;
}
#endif
/* Decode the Stream Header field (the first 12 bytes of the .xz Stream). */
static enum xz_ret dec_stream_header(struct xz_dec *s)
{
- if (!memeq(s->temp.buf, HEADER_MAGIC, HEADER_MAGIC_SIZE))
- return XZ_FORMAT_ERROR;
+ if (!memeq(s->temp.buf, HEADER_MAGIC, HEADER_MAGIC_SIZE))
+ return XZ_FORMAT_ERROR;
- if (xz_crc32(s->temp.buf + HEADER_MAGIC_SIZE, 2, 0) !=
- get_le32(s->temp.buf + HEADER_MAGIC_SIZE + 2))
- return XZ_DATA_ERROR;
+ if (xz_crc32(s->temp.buf + HEADER_MAGIC_SIZE, 2, 0) !=
+ get_le32(s->temp.buf + HEADER_MAGIC_SIZE + 2))
+ return XZ_DATA_ERROR;
- if (s->temp.buf[HEADER_MAGIC_SIZE] != 0)
- return XZ_OPTIONS_ERROR;
+ if (s->temp.buf[HEADER_MAGIC_SIZE] != 0)
+ return XZ_OPTIONS_ERROR;
- /*
- * Of integrity checks, we support none (Check ID = 0),
- * CRC32 (Check ID = 1), and optionally CRC64 (Check ID = 4).
- * However, if XZ_DEC_ANY_CHECK is defined, we will accept other
- * check types too, but then the check won't be verified and
- * a warning (XZ_UNSUPPORTED_CHECK) will be given.
- */
- s->check_type = s->temp.buf[HEADER_MAGIC_SIZE + 1];
+ /*
+ * Of integrity checks, we support none (Check ID = 0),
+ * CRC32 (Check ID = 1), and optionally CRC64 (Check ID = 4).
+ * However, if XZ_DEC_ANY_CHECK is defined, we will accept other
+ * check types too, but then the check won't be verified and
+ * a warning (XZ_UNSUPPORTED_CHECK) will be given.
+ */
+ s->check_type = s->temp.buf[HEADER_MAGIC_SIZE + 1];
#ifdef XZ_DEC_ANY_CHECK
- if (s->check_type > XZ_CHECK_MAX)
- return XZ_OPTIONS_ERROR;
+ if (s->check_type > XZ_CHECK_MAX)
+ return XZ_OPTIONS_ERROR;
- if (s->check_type > XZ_CHECK_CRC32 && !IS_CRC64(s->check_type))
- return XZ_UNSUPPORTED_CHECK;
+ if (s->check_type > XZ_CHECK_CRC32 && !IS_CRC64(s->check_type))
+ return XZ_UNSUPPORTED_CHECK;
#else
- if (s->check_type > XZ_CHECK_CRC32 && !IS_CRC64(s->check_type))
- return XZ_OPTIONS_ERROR;
+ if (s->check_type > XZ_CHECK_CRC32 && !IS_CRC64(s->check_type))
+ return XZ_OPTIONS_ERROR;
#endif
- return XZ_OK;
+ return XZ_OK;
}
/* Decode the Stream Footer field (the last 12 bytes of the .xz Stream) */
static enum xz_ret dec_stream_footer(struct xz_dec *s)
{
- if (!memeq(s->temp.buf + 10, FOOTER_MAGIC, FOOTER_MAGIC_SIZE))
- return XZ_DATA_ERROR;
-
- if (xz_crc32(s->temp.buf + 4, 6, 0) != get_le32(s->temp.buf))
- return XZ_DATA_ERROR;
-
- /*
- * Validate Backward Size. Note that we never added the size of the
- * Index CRC32 field to s->index.size, thus we use s->index.size / 4
- * instead of s->index.size / 4 - 1.
- */
- if ((s->index.size >> 2) != get_le32(s->temp.buf + 4))
- return XZ_DATA_ERROR;
-
- if (s->temp.buf[8] != 0 || s->temp.buf[9] != s->check_type)
- return XZ_DATA_ERROR;
-
- /*
- * Use XZ_STREAM_END instead of XZ_OK to be more convenient
- * for the caller.
- */
- return XZ_STREAM_END;
+ if (!memeq(s->temp.buf + 10, FOOTER_MAGIC, FOOTER_MAGIC_SIZE))
+ return XZ_DATA_ERROR;
+
+ if (xz_crc32(s->temp.buf + 4, 6, 0) != get_le32(s->temp.buf))
+ return XZ_DATA_ERROR;
+
+ /*
+ * Validate Backward Size. Note that we never added the size of the
+ * Index CRC32 field to s->index.size, thus we use s->index.size / 4
+ * instead of s->index.size / 4 - 1.
+ */
+ if ((s->index.size >> 2) != get_le32(s->temp.buf + 4))
+ return XZ_DATA_ERROR;
+
+ if (s->temp.buf[8] != 0 || s->temp.buf[9] != s->check_type)
+ return XZ_DATA_ERROR;
+
+ /*
+ * Use XZ_STREAM_END instead of XZ_OK to be more convenient
+ * for the caller.
+ */
+ return XZ_STREAM_END;
}
/* Decode the Block Header and initialize the filter chain. */
static enum xz_ret dec_block_header(struct xz_dec *s)
{
- enum xz_ret ret;
+ enum xz_ret ret;
- /*
- * Validate the CRC32. We know that the temp buffer is at least
- * eight bytes so this is safe.
- */
- s->temp.size -= 4;
- if (xz_crc32(s->temp.buf, s->temp.size, 0) != get_le32(s->temp.buf + s->temp.size))
- return XZ_DATA_ERROR;
+ /*
+ * Validate the CRC32. We know that the temp buffer is at least
+ * eight bytes so this is safe.
+ */
+ s->temp.size -= 4;
+ if (xz_crc32(s->temp.buf, s->temp.size, 0) != get_le32(s->temp.buf + s->temp.size))
+ return XZ_DATA_ERROR;
- s->temp.pos = 2;
+ s->temp.pos = 2;
/*
* Catch unsupported Block Flags. We support only one or two filters
* in the chain, so we catch that with the same test.
*/
#ifdef XZ_DEC_BCJ
- if (s->temp.buf[1] & 0x3E)
+ if (s->temp.buf[1] & 0x3E)
#else
- if (s->temp.buf[1] & 0x3F)
+ if (s->temp.buf[1] & 0x3F)
#endif
- return XZ_OPTIONS_ERROR;
-
- /* Compressed Size */
- if (s->temp.buf[1] & 0x40)
- {
- if (dec_vli(s, s->temp.buf, &s->temp.pos, s->temp.size) != XZ_STREAM_END)
- return XZ_DATA_ERROR;
-
- s->block_header.compressed = s->vli;
- }
- else
- {
- s->block_header.compressed = VLI_UNKNOWN;
- }
-
- /* Uncompressed Size */
- if (s->temp.buf[1] & 0x80)
- {
- if (dec_vli(s, s->temp.buf, &s->temp.pos, s->temp.size) != XZ_STREAM_END)
- return XZ_DATA_ERROR;
-
- s->block_header.uncompressed = s->vli;
- }
- else
- {
- s->block_header.uncompressed = VLI_UNKNOWN;
- }
+ return XZ_OPTIONS_ERROR;
+
+ /* Compressed Size */
+ if (s->temp.buf[1] & 0x40)
+ {
+ if (dec_vli(s, s->temp.buf, &s->temp.pos, s->temp.size) != XZ_STREAM_END)
+ return XZ_DATA_ERROR;
+
+ s->block_header.compressed = s->vli;
+ }
+ else
+ {
+ s->block_header.compressed = VLI_UNKNOWN;
+ }
+
+ /* Uncompressed Size */
+ if (s->temp.buf[1] & 0x80)
+ {
+ if (dec_vli(s, s->temp.buf, &s->temp.pos, s->temp.size) != XZ_STREAM_END)
+ return XZ_DATA_ERROR;
+
+ s->block_header.uncompressed = s->vli;
+ }
+ else
+ {
+ s->block_header.uncompressed = VLI_UNKNOWN;
+ }
#ifdef XZ_DEC_BCJ
- /* If there are two filters, the first one must be a BCJ filter. */
- s->bcj_active = s->temp.buf[1] & 0x01;
- if (s->bcj_active)
- {
- if (s->temp.size - s->temp.pos < 2)
- return XZ_OPTIONS_ERROR;
-
- ret = xz_dec_bcj_reset(s->bcj, s->temp.buf[s->temp.pos++]);
- if (ret != XZ_OK)
- return ret;
-
- /*
- * We don't support custom start offset,
- * so Size of Properties must be zero.
- */
- if (s->temp.buf[s->temp.pos++] != 0x00)
- return XZ_OPTIONS_ERROR;
- }
+ /* If there are two filters, the first one must be a BCJ filter. */
+ s->bcj_active = s->temp.buf[1] & 0x01;
+ if (s->bcj_active)
+ {
+ if (s->temp.size - s->temp.pos < 2)
+ return XZ_OPTIONS_ERROR;
+
+ ret = xz_dec_bcj_reset(s->bcj, s->temp.buf[s->temp.pos++]);
+ if (ret != XZ_OK)
+ return ret;
+
+ /*
+ * We don't support custom start offset,
+ * so Size of Properties must be zero.
+ */
+ if (s->temp.buf[s->temp.pos++] != 0x00)
+ return XZ_OPTIONS_ERROR;
+ }
#endif
- /* Valid Filter Flags always take at least two bytes. */
- if (s->temp.size - s->temp.pos < 2)
- return XZ_DATA_ERROR;
+ /* Valid Filter Flags always take at least two bytes. */
+ if (s->temp.size - s->temp.pos < 2)
+ return XZ_DATA_ERROR;
- /* Filter ID = LZMA2 */
- if (s->temp.buf[s->temp.pos++] != 0x21)
- return XZ_OPTIONS_ERROR;
+ /* Filter ID = LZMA2 */
+ if (s->temp.buf[s->temp.pos++] != 0x21)
+ return XZ_OPTIONS_ERROR;
- /* Size of Properties = 1-byte Filter Properties */
- if (s->temp.buf[s->temp.pos++] != 0x01)
- return XZ_OPTIONS_ERROR;
+ /* Size of Properties = 1-byte Filter Properties */
+ if (s->temp.buf[s->temp.pos++] != 0x01)
+ return XZ_OPTIONS_ERROR;
- /* Filter Properties contains LZMA2 dictionary size. */
- if (s->temp.size - s->temp.pos < 1)
- return XZ_DATA_ERROR;
+ /* Filter Properties contains LZMA2 dictionary size. */
+ if (s->temp.size - s->temp.pos < 1)
+ return XZ_DATA_ERROR;
- ret = xz_dec_lzma2_reset(s->lzma2, s->temp.buf[s->temp.pos++]);
- if (ret != XZ_OK)
- return ret;
+ ret = xz_dec_lzma2_reset(s->lzma2, s->temp.buf[s->temp.pos++]);
+ if (ret != XZ_OK)
+ return ret;
- /* The rest must be Header Padding. */
- while (s->temp.pos < s->temp.size)
- if (s->temp.buf[s->temp.pos++] != 0x00)
- return XZ_OPTIONS_ERROR;
+ /* The rest must be Header Padding. */
+ while (s->temp.pos < s->temp.size)
+ if (s->temp.buf[s->temp.pos++] != 0x00)
+ return XZ_OPTIONS_ERROR;
- s->temp.pos = 0;
- s->block.compressed = 0;
- s->block.uncompressed = 0;
+ s->temp.pos = 0;
+ s->block.compressed = 0;
+ s->block.uncompressed = 0;
- return XZ_OK;
+ return XZ_OK;
}
static enum xz_ret dec_main(struct xz_dec *s, struct xz_buf *b)
{
- enum xz_ret ret;
-
- /*
- * Store the start position for the case when we are in the middle
- * of the Index field.
- */
- s->in_start = b->in_pos;
-
- while (true)
- {
- switch (s->sequence)
- {
- case SEQ_STREAM_HEADER:
- /*
- * Stream Header is copied to s->temp, and then
- * decoded from there. This way if the caller
- * gives us only little input at a time, we can
- * still keep the Stream Header decoding code
- * simple. Similar approach is used in many places
- * in this file.
- */
- if (!fill_temp(s, b))
- return XZ_OK;
-
- /*
- * If dec_stream_header() returns
- * XZ_UNSUPPORTED_CHECK, it is still possible
- * to continue decoding if working in multi-call
- * mode. Thus, update s->sequence before calling
- * dec_stream_header().
- */
- s->sequence = SEQ_BLOCK_START;
-
- ret = dec_stream_header(s);
- if (ret != XZ_OK)
- return ret;
-
- case SEQ_BLOCK_START:
- /* We need one byte of input to continue. */
- if (b->in_pos == b->in_size)
- return XZ_OK;
-
- /* See if this is the beginning of the Index field. */
- if (b->in[b->in_pos] == 0)
- {
- s->in_start = b->in_pos++;
- s->sequence = SEQ_INDEX;
- break;
- }
-
- /*
- * Calculate the size of the Block Header and
- * prepare to decode it.
- */
- s->block_header.size = ((uint32_t)b->in[b->in_pos] + 1) * 4;
-
- s->temp.size = s->block_header.size;
- s->temp.pos = 0;
- s->sequence = SEQ_BLOCK_HEADER;
-
- case SEQ_BLOCK_HEADER:
- if (!fill_temp(s, b))
- return XZ_OK;
-
- ret = dec_block_header(s);
- if (ret != XZ_OK)
- return ret;
-
- s->sequence = SEQ_BLOCK_UNCOMPRESS;
-
- case SEQ_BLOCK_UNCOMPRESS:
- ret = dec_block(s, b);
- if (ret != XZ_STREAM_END)
- return ret;
-
- s->sequence = SEQ_BLOCK_PADDING;
-
- case SEQ_BLOCK_PADDING:
- /*
- * Size of Compressed Data + Block Padding
- * must be a multiple of four. We don't need
- * s->block.compressed for anything else
- * anymore, so we use it here to test the size
- * of the Block Padding field.
- */
- while (s->block.compressed & 3)
- {
- if (b->in_pos == b->in_size)
- return XZ_OK;
-
- if (b->in[b->in_pos++] != 0)
- return XZ_DATA_ERROR;
-
- ++s->block.compressed;
- }
-
- s->sequence = SEQ_BLOCK_CHECK;
-
- case SEQ_BLOCK_CHECK:
- if (s->check_type == XZ_CHECK_CRC32)
- {
- ret = crc_validate(s, b, 32);
- if (ret != XZ_STREAM_END)
- return ret;
- }
- else if (IS_CRC64(s->check_type))
- {
- ret = crc_validate(s, b, 64);
- if (ret != XZ_STREAM_END)
- return ret;
- }
+ enum xz_ret ret;
+
+ /*
+ * Store the start position for the case when we are in the middle
+ * of the Index field.
+ */
+ s->in_start = b->in_pos;
+
+ while (true)
+ {
+ switch (s->sequence)
+ {
+ case SEQ_STREAM_HEADER:
+ /*
+ * Stream Header is copied to s->temp, and then
+ * decoded from there. This way if the caller
+ * gives us only little input at a time, we can
+ * still keep the Stream Header decoding code
+ * simple. Similar approach is used in many places
+ * in this file.
+ */
+ if (!fill_temp(s, b))
+ return XZ_OK;
+
+ /*
+ * If dec_stream_header() returns
+ * XZ_UNSUPPORTED_CHECK, it is still possible
+ * to continue decoding if working in multi-call
+ * mode. Thus, update s->sequence before calling
+ * dec_stream_header().
+ */
+ s->sequence = SEQ_BLOCK_START;
+
+ ret = dec_stream_header(s);
+ if (ret != XZ_OK)
+ return ret;
+
+ case SEQ_BLOCK_START:
+ /* We need one byte of input to continue. */
+ if (b->in_pos == b->in_size)
+ return XZ_OK;
+
+ /* See if this is the beginning of the Index field. */
+ if (b->in[b->in_pos] == 0)
+ {
+ s->in_start = b->in_pos++;
+ s->sequence = SEQ_INDEX;
+ break;
+ }
+
+ /*
+ * Calculate the size of the Block Header and
+ * prepare to decode it.
+ */
+ s->block_header.size = ((uint32_t)b->in[b->in_pos] + 1) * 4;
+
+ s->temp.size = s->block_header.size;
+ s->temp.pos = 0;
+ s->sequence = SEQ_BLOCK_HEADER;
+
+ case SEQ_BLOCK_HEADER:
+ if (!fill_temp(s, b))
+ return XZ_OK;
+
+ ret = dec_block_header(s);
+ if (ret != XZ_OK)
+ return ret;
+
+ s->sequence = SEQ_BLOCK_UNCOMPRESS;
+
+ case SEQ_BLOCK_UNCOMPRESS:
+ ret = dec_block(s, b);
+ if (ret != XZ_STREAM_END)
+ return ret;
+
+ s->sequence = SEQ_BLOCK_PADDING;
+
+ case SEQ_BLOCK_PADDING:
+ /*
+ * Size of Compressed Data + Block Padding
+ * must be a multiple of four. We don't need
+ * s->block.compressed for anything else
+ * anymore, so we use it here to test the size
+ * of the Block Padding field.
+ */
+ while (s->block.compressed & 3)
+ {
+ if (b->in_pos == b->in_size)
+ return XZ_OK;
+
+ if (b->in[b->in_pos++] != 0)
+ return XZ_DATA_ERROR;
+
+ ++s->block.compressed;
+ }
+
+ s->sequence = SEQ_BLOCK_CHECK;
+
+ case SEQ_BLOCK_CHECK:
+ if (s->check_type == XZ_CHECK_CRC32)
+ {
+ ret = crc_validate(s, b, 32);
+ if (ret != XZ_STREAM_END)
+ return ret;
+ }
+ else if (IS_CRC64(s->check_type))
+ {
+ ret = crc_validate(s, b, 64);
+ if (ret != XZ_STREAM_END)
+ return ret;
+ }
#ifdef XZ_DEC_ANY_CHECK
- else if (!check_skip(s, b))
- {
- return XZ_OK;
- }
+ else if (!check_skip(s, b))
+ {
+ return XZ_OK;
+ }
#endif
- s->sequence = SEQ_BLOCK_START;
- break;
+ s->sequence = SEQ_BLOCK_START;
+ break;
- case SEQ_INDEX:
- ret = dec_index(s, b);
- if (ret != XZ_STREAM_END)
- return ret;
+ case SEQ_INDEX:
+ ret = dec_index(s, b);
+ if (ret != XZ_STREAM_END)
+ return ret;
- s->sequence = SEQ_INDEX_PADDING;
+ s->sequence = SEQ_INDEX_PADDING;
- case SEQ_INDEX_PADDING:
- while ((s->index.size + (b->in_pos - s->in_start)) & 3)
- {
- if (b->in_pos == b->in_size)
- {
- index_update(s, b);
- return XZ_OK;
- }
+ case SEQ_INDEX_PADDING:
+ while ((s->index.size + (b->in_pos - s->in_start)) & 3)
+ {
+ if (b->in_pos == b->in_size)
+ {
+ index_update(s, b);
+ return XZ_OK;
+ }
- if (b->in[b->in_pos++] != 0)
- return XZ_DATA_ERROR;
- }
+ if (b->in[b->in_pos++] != 0)
+ return XZ_DATA_ERROR;
+ }
- /* Finish the CRC32 value and Index size. */
- index_update(s, b);
+ /* Finish the CRC32 value and Index size. */
+ index_update(s, b);
- /* Compare the hashes to validate the Index field. */
- if (!memeq(&s->block.hash, &s->index.hash, sizeof(s->block.hash)))
- return XZ_DATA_ERROR;
+ /* Compare the hashes to validate the Index field. */
+ if (!memeq(&s->block.hash, &s->index.hash, sizeof(s->block.hash)))
+ return XZ_DATA_ERROR;
- s->sequence = SEQ_INDEX_CRC32;
+ s->sequence = SEQ_INDEX_CRC32;
- case SEQ_INDEX_CRC32:
- ret = crc_validate(s, b, 32);
- if (ret != XZ_STREAM_END)
- return ret;
+ case SEQ_INDEX_CRC32:
+ ret = crc_validate(s, b, 32);
+ if (ret != XZ_STREAM_END)
+ return ret;
- s->temp.size = STREAM_HEADER_SIZE;
- s->sequence = SEQ_STREAM_FOOTER;
+ s->temp.size = STREAM_HEADER_SIZE;
+ s->sequence = SEQ_STREAM_FOOTER;
- case SEQ_STREAM_FOOTER:
- if (!fill_temp(s, b))
- return XZ_OK;
+ case SEQ_STREAM_FOOTER:
+ if (!fill_temp(s, b))
+ return XZ_OK;
- return dec_stream_footer(s);
- }
- }
+ return dec_stream_footer(s);
+ }
+ }
- /* Never reached */
+ /* Never reached */
}
/*
@@ -768,93 +768,93 @@ static enum xz_ret dec_main(struct xz_dec *s, struct xz_buf *b)
*/
XZ_EXTERN enum xz_ret xz_dec_run(struct xz_dec *s, struct xz_buf *b)
{
- size_t in_start;
- size_t out_start;
- enum xz_ret ret;
-
- if (DEC_IS_SINGLE(s->mode))
- xz_dec_reset(s);
-
- in_start = b->in_pos;
- out_start = b->out_pos;
- ret = dec_main(s, b);
-
- if (DEC_IS_SINGLE(s->mode))
- {
- if (ret == XZ_OK)
- ret = b->in_pos == b->in_size ? XZ_DATA_ERROR : XZ_BUF_ERROR;
-
- if (ret != XZ_STREAM_END)
- {
- b->in_pos = in_start;
- b->out_pos = out_start;
- }
- }
- else if (ret == XZ_OK && in_start == b->in_pos && out_start == b->out_pos)
- {
- if (s->allow_buf_error)
- ret = XZ_BUF_ERROR;
-
- s->allow_buf_error = true;
- }
- else
- {
- s->allow_buf_error = false;
- }
-
- return ret;
+ size_t in_start;
+ size_t out_start;
+ enum xz_ret ret;
+
+ if (DEC_IS_SINGLE(s->mode))
+ xz_dec_reset(s);
+
+ in_start = b->in_pos;
+ out_start = b->out_pos;
+ ret = dec_main(s, b);
+
+ if (DEC_IS_SINGLE(s->mode))
+ {
+ if (ret == XZ_OK)
+ ret = b->in_pos == b->in_size ? XZ_DATA_ERROR : XZ_BUF_ERROR;
+
+ if (ret != XZ_STREAM_END)
+ {
+ b->in_pos = in_start;
+ b->out_pos = out_start;
+ }
+ }
+ else if (ret == XZ_OK && in_start == b->in_pos && out_start == b->out_pos)
+ {
+ if (s->allow_buf_error)
+ ret = XZ_BUF_ERROR;
+
+ s->allow_buf_error = true;
+ }
+ else
+ {
+ s->allow_buf_error = false;
+ }
+
+ return ret;
}
XZ_EXTERN struct xz_dec *xz_dec_init(enum xz_mode mode, uint32_t dict_max)
{
- struct xz_dec *s = kmalloc(sizeof(*s), GFP_KERNEL);
- if (s == NULL)
- return NULL;
+ struct xz_dec *s = kmalloc(sizeof(*s), GFP_KERNEL);
+ if (s == NULL)
+ return NULL;
- s->mode = mode;
+ s->mode = mode;
#ifdef XZ_DEC_BCJ
- s->bcj = xz_dec_bcj_create(DEC_IS_SINGLE(mode));
- if (s->bcj == NULL)
- goto error_bcj;
+ s->bcj = xz_dec_bcj_create(DEC_IS_SINGLE(mode));
+ if (s->bcj == NULL)
+ goto error_bcj;
#endif
- s->lzma2 = xz_dec_lzma2_create(mode, dict_max);
- if (s->lzma2 == NULL)
- goto error_lzma2;
+ s->lzma2 = xz_dec_lzma2_create(mode, dict_max);
+ if (s->lzma2 == NULL)
+ goto error_lzma2;
- xz_dec_reset(s);
- return s;
+ xz_dec_reset(s);
+ return s;
error_lzma2:
#ifdef XZ_DEC_BCJ
- xz_dec_bcj_end(s->bcj);
+ xz_dec_bcj_end(s->bcj);
error_bcj:
#endif
- kfree(s);
- return NULL;
+ kfree(s);
+ return NULL;
}
XZ_EXTERN void xz_dec_reset(struct xz_dec *s)
{
- s->sequence = SEQ_STREAM_HEADER;
- s->allow_buf_error = false;
- s->pos = 0;
- s->crc = 0;
- memzero(&s->block, sizeof(s->block));
- memzero(&s->index, sizeof(s->index));
- s->temp.pos = 0;
- s->temp.size = STREAM_HEADER_SIZE;
+ s->sequence = SEQ_STREAM_HEADER;
+ s->allow_buf_error = false;
+ s->pos = 0;
+ s->crc = 0;
+ memzero(&s->block, sizeof(s->block));
+ memzero(&s->index, sizeof(s->index));
+ s->temp.pos = 0;
+ s->temp.size = STREAM_HEADER_SIZE;
}
XZ_EXTERN void xz_dec_end(struct xz_dec *s)
{
- if (s != NULL)
- {
- xz_dec_lzma2_end(s->lzma2);
+ if (s != NULL)
+ {
+ xz_dec_lzma2_end(s->lzma2);
#ifdef XZ_DEC_BCJ
- xz_dec_bcj_end(s->bcj);
+ xz_dec_bcj_end(s->bcj);
#endif
- kfree(s);
- }
+ kfree(s);
+ }
}
diff --git a/libraries/xz-embedded/src/xz_lzma2.h b/libraries/xz-embedded/src/xz_lzma2.h
index 3976033a..82a425f2 100644
--- a/libraries/xz-embedded/src/xz_lzma2.h
+++ b/libraries/xz-embedded/src/xz_lzma2.h
@@ -41,18 +41,18 @@
*/
enum lzma_state
{
- STATE_LIT_LIT,
- STATE_MATCH_LIT_LIT,
- STATE_REP_LIT_LIT,
- STATE_SHORTREP_LIT_LIT,
- STATE_MATCH_LIT,
- STATE_REP_LIT,
- STATE_SHORTREP_LIT,
- STATE_LIT_MATCH,
- STATE_LIT_LONGREP,
- STATE_LIT_SHORTREP,
- STATE_NONLIT_MATCH,
- STATE_NONLIT_REP
+ STATE_LIT_LIT,
+ STATE_MATCH_LIT_LIT,
+ STATE_REP_LIT_LIT,
+ STATE_SHORTREP_LIT_LIT,
+ STATE_MATCH_LIT,
+ STATE_REP_LIT,
+ STATE_SHORTREP_LIT,
+ STATE_LIT_MATCH,
+ STATE_LIT_LONGREP,
+ STATE_LIT_SHORTREP,
+ STATE_NONLIT_MATCH,
+ STATE_NONLIT_REP
};
/* Total number of states */
@@ -64,36 +64,36 @@ enum lzma_state
/* Indicate that the latest symbol was a literal. */
static inline void lzma_state_literal(enum lzma_state *state)
{
- if (*state <= STATE_SHORTREP_LIT_LIT)
- *state = STATE_LIT_LIT;
- else if (*state <= STATE_LIT_SHORTREP)
- *state -= 3;
- else
- *state -= 6;
+ if (*state <= STATE_SHORTREP_LIT_LIT)
+ *state = STATE_LIT_LIT;
+ else if (*state <= STATE_LIT_SHORTREP)
+ *state -= 3;
+ else
+ *state -= 6;
}
/* Indicate that the latest symbol was a match. */
static inline void lzma_state_match(enum lzma_state *state)
{
- *state = *state < LIT_STATES ? STATE_LIT_MATCH : STATE_NONLIT_MATCH;
+ *state = *state < LIT_STATES ? STATE_LIT_MATCH : STATE_NONLIT_MATCH;
}
/* Indicate that the latest state was a long repeated match. */
static inline void lzma_state_long_rep(enum lzma_state *state)
{
- *state = *state < LIT_STATES ? STATE_LIT_LONGREP : STATE_NONLIT_REP;
+ *state = *state < LIT_STATES ? STATE_LIT_LONGREP : STATE_NONLIT_REP;
}
/* Indicate that the latest symbol was a short match. */
static inline void lzma_state_short_rep(enum lzma_state *state)
{
- *state = *state < LIT_STATES ? STATE_LIT_SHORTREP : STATE_NONLIT_REP;
+ *state = *state < LIT_STATES ? STATE_LIT_SHORTREP : STATE_NONLIT_REP;
}
/* Test if the previous symbol was a literal. */
static inline bool lzma_state_is_literal(enum lzma_state state)
{
- return state < LIT_STATES;
+ return state < LIT_STATES;
}
/* Each literal coder is divided in three sections:
@@ -147,7 +147,7 @@ static inline bool lzma_state_is_literal(enum lzma_state state)
*/
static inline uint32_t lzma_get_dist_state(uint32_t len)
{
- return len < DIST_STATES + MATCH_LEN_MIN ? len - MATCH_LEN_MIN : DIST_STATES - 1;
+ return len < DIST_STATES + MATCH_LEN_MIN ? len - MATCH_LEN_MIN : DIST_STATES - 1;
}
/*
diff --git a/libraries/xz-embedded/src/xz_private.h b/libraries/xz-embedded/src/xz_private.h
index 55a3af1c..1b616430 100644
--- a/libraries/xz-embedded/src/xz_private.h
+++ b/libraries/xz-embedded/src/xz_private.h
@@ -94,8 +94,8 @@
*/
#ifndef XZ_DEC_BCJ
#if defined(XZ_DEC_X86) || defined(XZ_DEC_POWERPC) || defined(XZ_DEC_IA64) || \
- defined(XZ_DEC_ARM) || defined(XZ_DEC_ARM) || defined(XZ_DEC_ARMTHUMB) || \
- defined(XZ_DEC_SPARC)
+ defined(XZ_DEC_ARM) || defined(XZ_DEC_ARM) || defined(XZ_DEC_ARMTHUMB) || \
+ defined(XZ_DEC_SPARC)
#define XZ_DEC_BCJ
#endif
#endif
@@ -141,7 +141,7 @@ XZ_EXTERN enum xz_ret xz_dec_bcj_reset(struct xz_dec_bcj *s, uint8_t id);
* must be called directly.
*/
XZ_EXTERN enum xz_ret xz_dec_bcj_run(struct xz_dec_bcj *s, struct xz_dec_lzma2 *lzma2,
- struct xz_buf *b);
+ struct xz_buf *b);
/* Free the memory allocated for the BCJ filters. */
#define xz_dec_bcj_end(s) kfree(s)
diff --git a/libraries/xz-embedded/src/xz_stream.h b/libraries/xz-embedded/src/xz_stream.h
index c0e191e6..b3d2c9fd 100644
--- a/libraries/xz-embedded/src/xz_stream.h
+++ b/libraries/xz-embedded/src/xz_stream.h
@@ -50,10 +50,10 @@ typedef uint64_t vli_type;
/* Integrity Check types */
enum xz_check
{
- XZ_CHECK_NONE = 0,
- XZ_CHECK_CRC32 = 1,
- XZ_CHECK_CRC64 = 4,
- XZ_CHECK_SHA256 = 10
+ XZ_CHECK_NONE = 0,
+ XZ_CHECK_CRC32 = 1,
+ XZ_CHECK_CRC64 = 4,
+ XZ_CHECK_SHA256 = 10
};
/* Maximum possible Check ID */
diff --git a/libraries/xz-embedded/xzminidec.c b/libraries/xz-embedded/xzminidec.c
index bb62c3ac..44f60602 100644
--- a/libraries/xz-embedded/xzminidec.c
+++ b/libraries/xz-embedded/xzminidec.c
@@ -24,121 +24,121 @@ static uint8_t out[BUFSIZ];
int main(int argc, char **argv)
{
- struct xz_buf b;
- struct xz_dec *s;
- enum xz_ret ret;
- const char *msg;
-
- if (argc >= 2 && strcmp(argv[1], "--help") == 0)
- {
- fputs("Uncompress a .xz file from stdin to stdout.\n"
- "Arguments other than `--help' are ignored.\n",
- stdout);
- return 0;
- }
-
- xz_crc32_init();
+ struct xz_buf b;
+ struct xz_dec *s;
+ enum xz_ret ret;
+ const char *msg;
+
+ if (argc >= 2 && strcmp(argv[1], "--help") == 0)
+ {
+ fputs("Uncompress a .xz file from stdin to stdout.\n"
+ "Arguments other than `--help' are ignored.\n",
+ stdout);
+ return 0;
+ }
+
+ xz_crc32_init();
#ifdef XZ_USE_CRC64
- xz_crc64_init();
+ xz_crc64_init();
#endif
- /*
- * Support up to 64 MiB dictionary. The actually needed memory
- * is allocated once the headers have been parsed.
- */
- s = xz_dec_init(XZ_DYNALLOC, 1 << 26);
- if (s == NULL)
- {
- msg = "Memory allocation failed\n";
- goto error;
- }
-
- b.in = in;
- b.in_pos = 0;
- b.in_size = 0;
- b.out = out;
- b.out_pos = 0;
- b.out_size = BUFSIZ;
-
- while (true)
- {
- if (b.in_pos == b.in_size)
- {
- b.in_size = fread(in, 1, sizeof(in), stdin);
- b.in_pos = 0;
- }
-
- ret = xz_dec_run(s, &b);
-
- if (b.out_pos == sizeof(out))
- {
- if (fwrite(out, 1, b.out_pos, stdout) != b.out_pos)
- {
- msg = "Write error\n";
- goto error;
- }
-
- b.out_pos = 0;
- }
-
- if (ret == XZ_OK)
- continue;
+ /*
+ * Support up to 64 MiB dictionary. The actually needed memory
+ * is allocated once the headers have been parsed.
+ */
+ s = xz_dec_init(XZ_DYNALLOC, 1 << 26);
+ if (s == NULL)
+ {
+ msg = "Memory allocation failed\n";
+ goto error;
+ }
+
+ b.in = in;
+ b.in_pos = 0;
+ b.in_size = 0;
+ b.out = out;
+ b.out_pos = 0;
+ b.out_size = BUFSIZ;
+
+ while (true)
+ {
+ if (b.in_pos == b.in_size)
+ {
+ b.in_size = fread(in, 1, sizeof(in), stdin);
+ b.in_pos = 0;
+ }
+
+ ret = xz_dec_run(s, &b);
+
+ if (b.out_pos == sizeof(out))
+ {
+ if (fwrite(out, 1, b.out_pos, stdout) != b.out_pos)
+ {
+ msg = "Write error\n";
+ goto error;
+ }
+
+ b.out_pos = 0;
+ }
+
+ if (ret == XZ_OK)
+ continue;
#ifdef XZ_DEC_ANY_CHECK
- if (ret == XZ_UNSUPPORTED_CHECK)
- {
- fputs(argv[0], stderr);
- fputs(": ", stderr);
- fputs("Unsupported check; not verifying "
- "file integrity\n",
- stderr);
- continue;
- }
+ if (ret == XZ_UNSUPPORTED_CHECK)
+ {
+ fputs(argv[0], stderr);
+ fputs(": ", stderr);
+ fputs("Unsupported check; not verifying "
+ "file integrity\n",
+ stderr);
+ continue;
+ }
#endif
- if (fwrite(out, 1, b.out_pos, stdout) != b.out_pos || fclose(stdout))
- {
- msg = "Write error\n";
- goto error;
- }
-
- switch (ret)
- {
- case XZ_STREAM_END:
- xz_dec_end(s);
- return 0;
-
- case XZ_MEM_ERROR:
- msg = "Memory allocation failed\n";
- goto error;
-
- case XZ_MEMLIMIT_ERROR:
- msg = "Memory usage limit reached\n";
- goto error;
-
- case XZ_FORMAT_ERROR:
- msg = "Not a .xz file\n";
- goto error;
-
- case XZ_OPTIONS_ERROR:
- msg = "Unsupported options in the .xz headers\n";
- goto error;
-
- case XZ_DATA_ERROR:
- case XZ_BUF_ERROR:
- msg = "File is corrupt\n";
- goto error;
-
- default:
- msg = "Bug!\n";
- goto error;
- }
- }
+ if (fwrite(out, 1, b.out_pos, stdout) != b.out_pos || fclose(stdout))
+ {
+ msg = "Write error\n";
+ goto error;
+ }
+
+ switch (ret)
+ {
+ case XZ_STREAM_END:
+ xz_dec_end(s);
+ return 0;
+
+ case XZ_MEM_ERROR:
+ msg = "Memory allocation failed\n";
+ goto error;
+
+ case XZ_MEMLIMIT_ERROR:
+ msg = "Memory usage limit reached\n";
+ goto error;
+
+ case XZ_FORMAT_ERROR:
+ msg = "Not a .xz file\n";
+ goto error;
+
+ case XZ_OPTIONS_ERROR:
+ msg = "Unsupported options in the .xz headers\n";
+ goto error;
+
+ case XZ_DATA_ERROR:
+ case XZ_BUF_ERROR:
+ msg = "File is corrupt\n";
+ goto error;
+
+ default:
+ msg = "Bug!\n";
+ goto error;
+ }
+ }
error:
- xz_dec_end(s);
- fputs(argv[0], stderr);
- fputs(": ", stderr);
- fputs(msg, stderr);
- return 1;
+ xz_dec_end(s);
+ fputs(argv[0], stderr);
+ fputs(": ", stderr);
+ fputs(msg, stderr);
+ return 1;
}