]> granicus.if.org Git - taglib/commitdiff
add base64 encoder/decoder to bytevector
authorSander Jansen <s.jansen@gmail.com>
Sat, 16 May 2015 19:06:49 +0000 (14:06 -0500)
committerSander Jansen <s.jansen@gmail.com>
Thu, 12 Nov 2015 14:48:00 +0000 (08:48 -0600)
taglib/toolkit/tbytevector.cpp
taglib/toolkit/tbytevector.h
tests/test_bytevector.cpp

index 6262bec6e9e06cd2091d61913ebb5f8c2cb1c0d5..eb559390e9b4ed34f540edc1116f15a87973f26f 100644 (file)
@@ -950,6 +950,98 @@ ByteVector ByteVector::toHex() const
   return encoded;
 }
 
+
+
+
+
+ByteVector & ByteVector::fromBase64()
+{
+  static const unsigned char base64[256]={
+    0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
+    0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
+    0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x3e,0x80,0x80,0x80,0x3f,
+    0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x80,0x80,0x80,0xff,0x80,0x80,
+    0x80,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
+    0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x80,0x80,0x80,0x80,0x80,
+    0x80,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,
+    0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,0x30,0x31,0x32,0x33,0x80,0x80,0x80,0x80,0x80,
+    0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
+    0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
+    0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
+    0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
+    0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
+    0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
+    0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
+    0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80
+  };
+
+  detach();
+  uint len = size();
+  const unsigned char * src = (unsigned char*) data();
+  unsigned char * dst = (unsigned char*) data();
+  while(4<=len) {
+    if(base64[src[0]]==0x80) break;
+    if(base64[src[1]]==0x80) break;
+    if(base64[src[2]]==0x80) break;
+    if(base64[src[3]]==0x80) break;
+    *dst++=((base64[src[0]]<<2)&0xfc)|((base64[src[1]]>>4)&0x03);
+    if(src[2]!='=') {
+      *dst++=((base64[src[1]]&0x0f)<<4)|((base64[src[2]]>>2)&0x0f);
+      if(src[3]!='=') {
+        *dst++=((base64[src[2]]&0x03)<<6)|(base64[src[3]]&0x3f);
+      }
+      else {
+        break;
+      }
+    }
+    else {
+      break;
+    }
+    src+=4;
+    len-=4;
+    }
+  resize(dst-(unsigned char*)data());
+  return *this;
+}
+
+
+
+
+ByteVector ByteVector::toBase64() const
+{
+  static const char alphabet[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+  if (size()) {
+    uint len=size();
+    ByteVector output(4 * ((len-1)/3+1)); // note roundup
+
+    const char * src = data();
+    char * dst = output.data();
+    while(3<=len) {
+      *dst++=alphabet[(src[0]>>2)&0x3f];
+      *dst++=alphabet[((src[0]&0x03)<<4)|((src[1]>>4)&0x0f)];
+      *dst++=alphabet[((src[1]&0x0f)<<2)|((src[2]>>6)&0x03)];
+      *dst++=alphabet[src[2]&0x3f];
+      src+=3;
+      len-=3;
+    }
+    if(len) {
+      *dst++=alphabet[(src[0]>>2)&0x3f];
+      if(len>1) {
+        *dst++=alphabet[((src[0]&0x03)<<4)|((src[1]>>4)&0x0f)];
+        *dst++=alphabet[((src[1]&0x0f)<<2)];
+      }
+      else {
+        *dst++=alphabet[(src[0]&0x03)<<4];
+        *dst++='=';
+      }
+    *dst++='=';
+    }
+    return output;
+  }
+  return ByteVector();
+}
+
+
 ////////////////////////////////////////////////////////////////////////////////
 // protected members
 ////////////////////////////////////////////////////////////////////////////////
index 793b414cecbed35d86f9d35559660f166d70256a..0f96c77f181c41b09bcfbb334ed2777650815953 100644 (file)
@@ -573,6 +573,19 @@ namespace TagLib {
      */
     ByteVector toHex() const;
 
+    /*!
+     * Returns a base64 encoded copy of the byte vector
+     */
+    ByteVector toBase64() const;
+
+    /*!
+     * Decodes the base64 encoded byte vector in-memory. Returns a reference
+     * to this vector. Calls detach before decoding.
+     */
+    ByteVector & fromBase64();
+
+
+
   protected:
     /*
      * If this ByteVector is being shared via implicit sharing, do a deep copy
index 1c2ca904d0ff5fc4ea35fa67e749f239e9a29d1e..19f5151845e88631487433c3f9837a6317b55143 100644 (file)
@@ -43,6 +43,7 @@ class TestByteVector : public CppUnit::TestFixture
   CPPUNIT_TEST(testReplace);
   CPPUNIT_TEST(testIterator);
   CPPUNIT_TEST(testResize);
+  CPPUNIT_TEST(testBase64);
   CPPUNIT_TEST_SUITE_END();
 
 public:
@@ -379,6 +380,45 @@ public:
     CPPUNIT_ASSERT_EQUAL(-1, c.find('C'));
   }
 
+  void testBase64()
+  {
+    ByteVector sempty;
+    ByteVector t0("a"); // test 1 byte
+    ByteVector t1("any carnal pleasure.");
+    ByteVector t2("any carnal pleasure");
+    ByteVector t3("any carnal pleasur");
+    ByteVector s0("a"); // test 1 byte
+    ByteVector s1("any carnal pleasure.");
+    ByteVector s2("any carnal pleasure");
+    ByteVector s3("any carnal pleasur");
+    ByteVector eempty;
+    ByteVector e0("YQ==");
+    ByteVector e1("YW55IGNhcm5hbCBwbGVhc3VyZS4=");
+    ByteVector e2("YW55IGNhcm5hbCBwbGVhc3VyZQ==");
+    ByteVector e3("YW55IGNhcm5hbCBwbGVhc3Vy");
+
+    // Encode
+    CPPUNIT_ASSERT_EQUAL(eempty, sempty.toBase64());
+    CPPUNIT_ASSERT_EQUAL(e0, s0.toBase64());
+    CPPUNIT_ASSERT_EQUAL(e1, s1.toBase64());
+    CPPUNIT_ASSERT_EQUAL(e2, s2.toBase64());
+    CPPUNIT_ASSERT_EQUAL(e3, s3.toBase64());
+
+    // Decode
+    CPPUNIT_ASSERT_EQUAL(sempty, eempty.toBase64());
+    CPPUNIT_ASSERT_EQUAL(s0, e0.fromBase64());
+    CPPUNIT_ASSERT_EQUAL(s1, e1.fromBase64());
+    CPPUNIT_ASSERT_EQUAL(s2, e2.fromBase64());
+    CPPUNIT_ASSERT_EQUAL(s3, e3.fromBase64());
+
+    CPPUNIT_ASSERT_EQUAL(t0, s0.toBase64().fromBase64());
+    CPPUNIT_ASSERT_EQUAL(t1, s1.toBase64().fromBase64());
+    CPPUNIT_ASSERT_EQUAL(t2, s2.toBase64().fromBase64());
+    CPPUNIT_ASSERT_EQUAL(t3, s3.toBase64().fromBase64());
+
+  }
+
+
 };
 
 CPPUNIT_TEST_SUITE_REGISTRATION(TestByteVector);