• Skip to content
  • Skip to link menu
KDE 4.4 API Reference
  • KDE API Reference
  • KDE Support
  • Sitemap
  • Contact Us
 

strigi/src/streams

base64inputstream.cpp

Go to the documentation of this file.
00001 /* This file is part of Strigi Desktop Search
00002  *
00003  * Copyright (C) 2006 Jos van den Oever <jos@vandenoever.info>
00004  *
00005  * This library is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU Library General Public
00007  * License as published by the Free Software Foundation; either
00008  * version 2 of the License, or (at your option) any later version.
00009  *
00010  * This library is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  * Library General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU Library General Public License
00016  * along with this library; see the file COPYING.LIB.  If not, write to
00017  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018  * Boston, MA 02110-1301, USA.
00019  */
00020 #include "base64inputstream.h"
00021 
00022 #include <cstring>
00023 
00024 using namespace std;
00025 using namespace Strigi;
00026 
00027 /* code is based on public domain code at
00028    http://www.tug.org/ftp/vm/base64-decode.c
00029 */
00030 
00031 class Base64InputStream::Private {
00032 public:
00033     Base64InputStream* const p;
00034     InputStream* input;
00035     const char* pos, * pend;
00036     int32_t bits;
00037     int32_t nleft;
00038     char bytestodo;
00039     char char_count;
00040 
00041     Private(Base64InputStream* p, InputStream* i);
00042     bool moreData();
00043     int32_t fillBuffer(char* start, int32_t space);
00044 };
00045 
00046 
00047 const unsigned char alphabet[]
00048     = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
00049 bool inalphabet[256];
00050 unsigned char decoder[133];
00051 bool initializedAlphabet = false;
00052 void initialize();
00053 string decode(const char* in, string::size_type length);
00054 
00055 
00056 void
00057 initialize() {
00058     if (!initializedAlphabet) {
00059         initializedAlphabet = true;
00060         // initialize the translation arrays
00061         for (int i=64; i<256; ++i) {
00062             inalphabet[i] = 0;
00063         }
00064         for (int i=0; i<64; ++i) {
00065             inalphabet[alphabet[i]] = true;
00066             decoder[alphabet[i]] = i;
00067         }
00068     }
00069 }
00070 
00071 Base64InputStream::Base64InputStream(InputStream* i) 
00072     :p(new Private(this, i)) 
00073 {
00074 }
00075 
00076 Base64InputStream::~Base64InputStream() {
00077     delete p;
00078 }
00079 Base64InputStream::Private::Private(Base64InputStream* bi, InputStream* i)
00080         :p(bi), input(i) {
00081     initialize();
00082     nleft = 0;
00083     char_count = 0;
00084     bits = 0;
00085     bytestodo = 0;
00086     pos = pend = 0;
00087 }
00088 bool
00089 Base64InputStream::Private::moreData() {
00090     if (pos == pend) {
00091         int32_t nread = input->read(pos, 1, 0);
00092         if (nread < -1) {
00093             p->m_status = Error;
00094             p->m_error = input->error();
00095             input = 0;
00096             return false;
00097         }
00098         if (nread <= 0) {
00099             input = 0;
00100             return false;
00101         }
00102         pend = pos + nread;
00103     }
00104     return true;
00105 }
00106 int32_t
00107 Base64InputStream::fillBuffer(char* start, int32_t space) {
00108     return p->fillBuffer(start, space);
00109 }
00110 int32_t
00111 Base64InputStream::Private::fillBuffer(char* start, int32_t space) {
00112     if (input == 0 && bytestodo == 0) return -1;
00113     // handle the  bytes that were left over from the last call
00114     if (bytestodo) {
00115         switch (bytestodo) {
00116         case 3:
00117             *start = bits >> 16;
00118             break;
00119         case 2:
00120             *start = (bits >> 8) & 0xff;
00121             break;
00122         case 1:
00123             *start = bits & 0xff;
00124             bits = 0;
00125             char_count = 0;
00126             break;
00127         }
00128         bytestodo--;
00129         return 1;
00130     }
00131     const char* end = start + space;
00132     char* p = start;
00133     int32_t nwritten = 0;
00134     while (moreData()) {
00135         unsigned char c = *pos++;
00136         // = signals the end of the encoded block
00137         if (c == '=') {
00138             if (char_count == 2) {
00139                 bytestodo = 1;
00140                 bits >>= 10;
00141             } else if (char_count == 3) {
00142                 bytestodo = 2;
00143                 bits >>= 8;
00144             }
00145             input = 0;
00146             break;
00147         }
00148         // we ignore characters that do not fit
00149         if (!inalphabet[c]) {
00150             continue;
00151         }
00152         bits += decoder[c];
00153         char_count++;
00154         if (char_count == 4) {
00155             if (p >= end) {
00156                 bytestodo = 3;
00157                 break;
00158             }
00159             *p++ = bits >> 16;
00160             if (p >= end) {
00161                 bytestodo = 2;
00162                 nwritten++;
00163                 break;
00164             }
00165             *p++ = (bits >> 8) & 0xff;
00166             if (p >= end) {
00167                 bytestodo = 1;
00168                 nwritten += 2;
00169                 break;
00170             }
00171             *p++ = bits & 0xff;
00172             bits = 0;
00173             char_count = 0;
00174             nwritten += 3;
00175         } else {
00176             bits <<= 6;
00177         }
00178     }
00179     if (nwritten == 0 && input == 0 && bytestodo == 0) {
00180 //        printf("EOF\n");
00181         nwritten = -1;
00182     }
00183     return nwritten;
00184 }
00185 string
00186 Base64InputStream::decode(const char* in, string::size_type length) {
00187     initialize();
00188     string d;
00189     if (length%4) return d;
00190     initialize();
00191     int32_t words = length/4;
00192     d.reserve(words*3);
00193     const unsigned char* c = (const unsigned char*)in;
00194     const unsigned char* e = c + length;
00195     if (in[length-1] == '=') {
00196         e -= 4;
00197     }
00198     char k, l, b[3];
00199     for (; c < e; c += 4) {
00200          if (inalphabet[c[0]]  && inalphabet[c[1]] && inalphabet[c[2]]
00201              && inalphabet[c[3]]) {
00202             k = decoder[c[1]];
00203             l = decoder[c[2]];
00204             b[0] = (decoder[c[0]] << 2) + (k >> 4);
00205             b[1] = (k             << 4) + (l >> 2);
00206             b[2] = (l             << 6) + (decoder[c[3]]);
00207             d.append(b, 3);
00208          } else {
00209              return string();
00210          }
00211     }
00212     if (in[length-2] == '=') {
00213         if (inalphabet[c[0]]  && inalphabet[c[1]]) {
00214             b[0] = (decoder[c[0]] << 2)+((decoder[c[1]] >> 4));
00215             d.append(b, 1);
00216         } else {
00217             return string();
00218         }
00219     } else if (in[length-1] == '=') {
00220         if (inalphabet[c[0]]  && inalphabet[c[1]] && inalphabet[c[2]]) {
00221             k = decoder[c[1]];
00222             b[0] = (decoder[c[0]] << 2) + (k >> 4);
00223             b[1] = (k             << 4) + (decoder[c[2]] >> 2);
00224             d.append(b, 2);
00225         } else {
00226             return string();
00227         }
00228     }
00229     return d;
00230 }

strigi/src/streams

Skip menu "strigi/src/streams"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members

KDE Support

Skip menu "KDE Support"
  • akonadi
  • Decibel
  • grantlee
  • kdewin
  • phonon
  •     Backend
  • polkit-qt
  • qca
  • qimageblitz
  • soprano
  • strigi
  •     searchclient
  •     streamanalyzer
  •     streams
Generated for KDE Support by doxygen 1.5.9-20090814
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal