File indexing completed on 2024-05-05 04:45:04

0001 /*
0002  * Copyright (C) 2003-2005  Justin Karneges <justin@affinix.com>
0003  *
0004  * This library is free software; you can redistribute it and/or
0005  * modify it under the terms of the GNU Lesser General Public
0006  * License as published by the Free Software Foundation; either
0007  * version 2.1 of the License, or (at your option) any later version.
0008  *
0009  * This library is distributed in the hope that it will be useful,
0010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0012  * Lesser General Public License for more details.
0013  *
0014  * You should have received a copy of the GNU Lesser General Public
0015  * License along with this library; if not, write to the Free Software
0016  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
0017  *
0018  */
0019 
0020 #include "lineconverter.h"
0021 
0022 namespace gpgQCAPlugin {
0023 
0024 void LineConverter::setup(LineConverter::Mode m)
0025 {
0026     state    = Normal;
0027     mode     = m;
0028     prebytes = 0;
0029     list.clear();
0030 }
0031 
0032 QByteArray LineConverter::update(const QByteArray &buf)
0033 {
0034     if (mode == Read) {
0035         // Convert buf to UNIX line ending style
0036         // If buf ends with '\r' set state to Partival
0037 
0038         QByteArray out;
0039 
0040         if (state == Normal) {
0041             out = buf;
0042         } else {
0043             out.resize(buf.size() + 1);
0044             out[0] = '\r';
0045             memcpy(out.data() + 1, buf.data(), buf.size());
0046         }
0047 
0048         int n = 0;
0049         while (true) {
0050             n = out.indexOf('\r', n);
0051             // not found
0052             if (n == -1) {
0053                 break;
0054             }
0055             // found, not last character
0056             if (n < (buf.size() - 1)) {
0057                 // found windows line ending "\r\n"
0058                 if (out[n + 1] == '\n') {
0059                     // clip out the '\r'
0060                     memmove(out.data() + n, out.data() + n + 1, out.size() - n - 1);
0061                     out.resize(out.size() - 1);
0062                 }
0063             }
0064             // found, last character
0065             else {
0066                 state = Partial;
0067                 break;
0068             }
0069             ++n;
0070         }
0071 
0072         return out;
0073     } else {
0074         // On Windows use DOS line ending style.
0075         // On UNIX don't do any convertation. Return buf as is.
0076 #ifdef Q_OS_WIN
0077         QByteArray out;
0078         int        prev = 0;
0079         int        at   = 0;
0080 
0081         while (1) {
0082             int n = buf.indexOf('\n', at);
0083             if (n == -1)
0084                 break;
0085 
0086             int       chunksize = n - at;
0087             const int oldsize   = out.size();
0088             out.resize(oldsize + chunksize + 2);
0089             memcpy(out.data() + oldsize, buf.data() + at, chunksize);
0090             memcpy(out.data() + oldsize + chunksize, "\r\n", 2);
0091 
0092             list.append(prebytes + n + 1 - prev);
0093             prebytes = 0;
0094             prev     = n;
0095 
0096             at = n + 1;
0097         }
0098         if (at < buf.size()) {
0099             const int chunksize = buf.size() - at;
0100             const int oldsize   = out.size();
0101             out.resize(oldsize + chunksize);
0102             memcpy(out.data() + oldsize, buf.data() + at, chunksize);
0103         }
0104 
0105         prebytes += buf.size() - prev;
0106         return out;
0107 #else
0108         return buf;
0109 #endif
0110     }
0111 }
0112 
0113 QByteArray LineConverter::final()
0114 {
0115     if (mode == Read) {
0116         QByteArray out;
0117         if (state == Partial) {
0118             out.resize(1);
0119             out[0] = '\n';
0120         }
0121         return out;
0122     } else {
0123         return QByteArray();
0124     }
0125 }
0126 
0127 QByteArray LineConverter::process(const QByteArray &buf)
0128 {
0129     return update(buf) + final();
0130 }
0131 
0132 int LineConverter::writtenToActual(int bytes)
0133 {
0134 #ifdef Q_OS_WIN
0135     int n       = 0;
0136     int counter = bytes;
0137     while (counter > 0) {
0138         if (!list.isEmpty() && bytes >= list.first()) {
0139             ++n;
0140             counter -= list.takeFirst();
0141         } else {
0142             if (list.isEmpty())
0143                 prebytes -= counter;
0144             else
0145                 list.first() -= counter;
0146 
0147             if (prebytes < 0) {
0148                 bytes += prebytes;
0149                 prebytes = 0;
0150             }
0151 
0152             break;
0153         }
0154     }
0155     return bytes - n;
0156 #else
0157     return bytes;
0158 #endif
0159 }
0160 
0161 } // end namespace gpgQCAPlugin