Advance Wayland and KDE package bring-up
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -0,0 +1,240 @@
|
||||
/* -*- c++ -*-
|
||||
SPDX-FileCopyrightText: 2002 Marc Mutz <mutz@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
/**
|
||||
@file
|
||||
This file is part of the API for handling @ref MIME data and
|
||||
defines a @ref uuencode @ref Codec class.
|
||||
|
||||
@brief
|
||||
Defines the UUCodec class.
|
||||
|
||||
@authors Marc Mutz \<mutz@kde.org\>
|
||||
*/
|
||||
|
||||
#include "kcodecsuuencode.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include <cassert>
|
||||
|
||||
using namespace KCodecs;
|
||||
|
||||
namespace KCodecs
|
||||
{
|
||||
class UUDecoder : public Decoder
|
||||
{
|
||||
uint mStepNo;
|
||||
uchar mAnnouncedOctetCount; // (on current line)
|
||||
uchar mCurrentOctetCount; // (on current line)
|
||||
uchar mOutbits;
|
||||
bool mLastWasCRLF : 1;
|
||||
bool mSawBegin : 1; // whether we already saw ^begin...
|
||||
uint mIntoBeginLine : 3; // count #chars we compared against "begin" 0..5
|
||||
bool mSawEnd : 1; // whether we already saw ^end...
|
||||
uint mIntoEndLine : 2; // count #chars we compared against "end" 0..3
|
||||
|
||||
void searchForBegin(const char *&scursor, const char *const send);
|
||||
|
||||
protected:
|
||||
friend class UUCodec;
|
||||
UUDecoder(Codec::NewlineType newline = Codec::NewlineLF)
|
||||
: Decoder(newline)
|
||||
, mStepNo(0)
|
||||
, mAnnouncedOctetCount(0)
|
||||
, mCurrentOctetCount(0)
|
||||
, mOutbits(0)
|
||||
, mLastWasCRLF(true)
|
||||
, mSawBegin(false)
|
||||
, mIntoBeginLine(0)
|
||||
, mSawEnd(false)
|
||||
, mIntoEndLine(0)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
~UUDecoder() override
|
||||
{
|
||||
}
|
||||
|
||||
bool decode(const char *&scursor, const char *const send, char *&dcursor, const char *const dend) override;
|
||||
// ### really needs no finishing???
|
||||
bool finish(char *&dcursor, const char *const dend) override
|
||||
{
|
||||
Q_UNUSED(dcursor);
|
||||
Q_UNUSED(dend);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
Encoder *UUCodec::makeEncoder(NewlineType newline) const
|
||||
{
|
||||
Q_UNUSED(newline)
|
||||
return nullptr; // encoding not supported
|
||||
}
|
||||
|
||||
Decoder *UUCodec::makeDecoder(NewlineType newline) const
|
||||
{
|
||||
return new UUDecoder(newline);
|
||||
}
|
||||
|
||||
/********************************************************/
|
||||
/********************************************************/
|
||||
/********************************************************/
|
||||
|
||||
void UUDecoder::searchForBegin(const char *&scursor, const char *const send)
|
||||
{
|
||||
static const char begin[] = "begin\n";
|
||||
static const uint beginLength = 5; // sic!
|
||||
|
||||
assert(!mSawBegin || mIntoBeginLine > 0);
|
||||
|
||||
while (scursor != send) {
|
||||
uchar ch = *scursor++;
|
||||
if (ch == begin[mIntoBeginLine]) {
|
||||
if (mIntoBeginLine < beginLength) {
|
||||
// found another char
|
||||
++mIntoBeginLine;
|
||||
if (mIntoBeginLine == beginLength) {
|
||||
mSawBegin = true; // "begin" complete, now search the next \n...
|
||||
}
|
||||
} else { // mIntoBeginLine == beginLength
|
||||
// found '\n': begin line complete
|
||||
mLastWasCRLF = true;
|
||||
mIntoBeginLine = 0;
|
||||
return;
|
||||
}
|
||||
} else if (mSawBegin) {
|
||||
// OK, skip stuff until the next \n
|
||||
} else {
|
||||
// qWarning() << "UUDecoder: garbage before \"begin\", resetting parser";
|
||||
mIntoBeginLine = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// uuencoding just shifts all 6-bit octets by 32 (SP/' '), except NUL,
|
||||
// which gets mapped to 0x60
|
||||
static inline uchar uuDecode(uchar c)
|
||||
{
|
||||
return (c - ' ') // undo shift and
|
||||
& 0x3F; // map 0x40 (0x60-' ') to 0...
|
||||
}
|
||||
|
||||
bool UUDecoder::decode(const char *&scursor, const char *const send, char *&dcursor, const char *const dend)
|
||||
{
|
||||
// First, check whether we still need to find the "begin" line:
|
||||
if (!mSawBegin || mIntoBeginLine != 0) {
|
||||
searchForBegin(scursor, send);
|
||||
} else if (mSawEnd) {
|
||||
// or if we are past the end line:
|
||||
scursor = send; // do nothing anymore...
|
||||
return true;
|
||||
}
|
||||
|
||||
while (dcursor != dend && scursor != send) {
|
||||
uchar ch = *scursor++;
|
||||
uchar value;
|
||||
|
||||
// Check whether we need to look for the "end" line:
|
||||
if (mIntoEndLine > 0) {
|
||||
static const char end[] = "end";
|
||||
static const uint endLength = 3;
|
||||
|
||||
if (ch == end[mIntoEndLine]) {
|
||||
++mIntoEndLine;
|
||||
if (mIntoEndLine == endLength) {
|
||||
mSawEnd = true;
|
||||
scursor = send; // shortcut to the end
|
||||
return true;
|
||||
}
|
||||
continue;
|
||||
} else {
|
||||
// qWarning() << "UUDecoder: invalid line octet count looks like \"end\" (mIntoEndLine ="
|
||||
// << mIntoEndLine << ")!";
|
||||
mIntoEndLine = 0;
|
||||
// fall through...
|
||||
}
|
||||
}
|
||||
|
||||
// Normal parsing:
|
||||
|
||||
// The first char of a line is an encoding of the length of the
|
||||
// current line. We simply ignore it:
|
||||
if (mLastWasCRLF) {
|
||||
// reset char-per-line counter:
|
||||
mLastWasCRLF = false;
|
||||
mCurrentOctetCount = 0;
|
||||
|
||||
// try to decode the chars-on-this-line announcement:
|
||||
if (ch == 'e') { // maybe the beginning of the "end"? ;-)
|
||||
mIntoEndLine = 1;
|
||||
} else if (ch > 0x60) {
|
||||
// ### invalid line length char: what shall we do??
|
||||
} else if (ch > ' ') {
|
||||
mAnnouncedOctetCount = uuDecode(ch);
|
||||
} else if (ch == '\n') {
|
||||
mLastWasCRLF = true; // oops, empty line
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// try converting ch to a 6-bit value:
|
||||
if (ch > 0x60) {
|
||||
continue; // invalid char
|
||||
} else if (ch > ' ') {
|
||||
value = uuDecode(ch);
|
||||
} else if (ch == '\n') { // line end
|
||||
mLastWasCRLF = true;
|
||||
continue;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
// add the new bits to the output stream and flush full octets:
|
||||
switch (mStepNo) {
|
||||
case 0:
|
||||
mOutbits = value << 2;
|
||||
break;
|
||||
case 1:
|
||||
if (mCurrentOctetCount < mAnnouncedOctetCount) {
|
||||
*dcursor++ = (char)(mOutbits | value >> 4);
|
||||
}
|
||||
++mCurrentOctetCount;
|
||||
mOutbits = value << 4;
|
||||
break;
|
||||
case 2:
|
||||
if (mCurrentOctetCount < mAnnouncedOctetCount) {
|
||||
*dcursor++ = (char)(mOutbits | value >> 2);
|
||||
}
|
||||
++mCurrentOctetCount;
|
||||
mOutbits = value << 6;
|
||||
break;
|
||||
case 3:
|
||||
if (mCurrentOctetCount < mAnnouncedOctetCount) {
|
||||
*dcursor++ = (char)(mOutbits | value);
|
||||
}
|
||||
++mCurrentOctetCount;
|
||||
mOutbits = 0;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
mStepNo = (mStepNo + 1) % 4;
|
||||
|
||||
// check whether we ran over the announced octet count for this line:
|
||||
if (mCurrentOctetCount == mAnnouncedOctetCount + 1) {
|
||||
// qWarning()
|
||||
// << "UUDecoder: mismatch between announced ("
|
||||
// << mAnnouncedOctetCount << ") and actual line octet count!";
|
||||
}
|
||||
}
|
||||
|
||||
// return false when caller should call us again:
|
||||
return scursor == send;
|
||||
} // UUDecoder::decode()
|
||||
|
||||
} // namespace KCodecs
|
||||
Reference in New Issue
Block a user