February 07, 2013

Sonunda anlaştığımıza sevindim. ;) Sen bir ara 32'lik sayı sistemini düşünmüşsün. Bu ise bitleri beşer beşer ele alan ve 32 uzunluklu bir alfabedeki karşılıklarına dönüştüren bir kodlama.

64/5 = 12
64%5 = 4

Yani sonuncu harfe 4 bit kalıyor. Demek ki sonuna hayali bir 0 biti ekleyerek düşünülecek.

Ek gözlem: 8 bayt yerine 13 bayt kullandığımız için veri büyüyor.

Ama burada amaç ulong gibi temel türleri mi kodlamak yoksa belirsiz uzunluktaki veriyi mi kodlamak? Benim anladığım, bu işlevin 'ubyte[]' alması daha doğru olur ve yine 'ubyte[]' döndürür. (Doğal olarak, string demiyorum çünkü her ne kadar ASCII karakterlere karşılık gelse de aslında metin olarak düşünülmemeli. (Biraz daha düşününce belki de dönüş türü string olabilir gibi geliyor. Çünkü bu kodlamanın amaçlarından birisi insanların da kolayca okuyabilmeleri ve söyleyebilmeleri.))

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

February 09, 2013

Hocam ellerine sağlık...

Bir iki küçük düzeltmek gerekiyor sanırım, örneğin assert() satırlarının birinde ama henüz deneme fırsatı bulamadım. Bunun yerine önce kodu anlamaya çalışıyorum. Açıkcası başta çuvalladım çünkü bitÇek() işlevini anlayamadım...:)

Kısaca ne işe yarıyor?

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

February 09, 2013

Bu konu beni de çekti ve gittikçe içine girdim. :) Baştan çok zorlandım ama sonunda üç farklı aralık kullanan bir çözüm buldum.

RFC'de de anlatıldığı gibi, aslında Base32 RandomAccessRange aralıklarıyla çok daha hızlı işlenebilir. Ben yalnızca InputRange gerektiren ve asıl aralığın başındaki iki elemanı gerektikçe kendi ara belleğinde tutan bir aralık yazdım.

Kodda bir sürü denetim eksik; örneğin, bir sürü assert serpiştirilebilir.

Bu çözüm Base32'nin üç işlevini farklı aralıklarla gerçekleştiriyor:

BitParçaları: Veriyi belirtilen genişlikteki parçalar halinde sunuyor. Bu genişlik, Base32 için 5; Base64 için 6. (Base32 dışında denemedim.)

UzunluğuTamBölünen: Asıl aralık kısa bile olsa belirtilen doldurma elemanını kullanarak belirli bir uzunluğa tam olarak bölünen sayıda eleman üretiyor. Bu, Base32 kodlamasının 8'in katları olması gereğini karşılıyor.

Dönüştür: Eleman değerlerini indeks olarak kullanarak belirtilen alfabenin harflerine dönüştürüyor.

Base64'ü denemedim ama bence bu aralıklardan yola çıkıldığında o da çok kolay olacaktır.

Ali

import std.stdio;
import std.array;
import std.range;
import std.traits;
import std.conv;

/**
* Belirtilen türün kaç bitten oluştuğunu bildirir.
*/
size_t toplamBit(T)() @property
{
   return T.sizeof * 8;
}

unittest
{
   assert(toplamBit!char == 8);
   assert(toplamBit!long == 64);
}

/*
* Verinin belirtilen konumdaki bitinden sağa doğru 'adet' adet bitinin
* değerini döndürür.
*
* Veriyi bir bit topluluğu olarak gördüğü için 0 numaralı bit en soldakidir.
*/
T bitÇek(T)(T veri, size_t konum, size_t adet)
   if (!isStaticArray!T)
{
   veri <<= konum;
   veri >>>= toplamBit!T - adet;
   return veri;
}

unittest
{
   ubyte veri = 0b_1010_1100;
   assert(bitÇek(veri, 0, 0) == 0);
   assert(bitÇek(veri, 0, 1) == 1);
   assert(bitÇek(veri, 0, 2) == 2);
   assert(bitÇek(veri, 0, 3) == 5);
   assert(bitÇek(veri, 0, 4) == 10);
   assert(bitÇek(veri, 0, 5) == 21);
   assert(bitÇek(veri, 0, 6) == 43);
   assert(bitÇek(veri, 0, 7) == 86);
   assert(bitÇek(veri, 0, 8) == 172);

   veri = 0b10110101;
   assert(bitÇek(veri, 0, 3) == 5);
   assert(bitÇek(veri, 1, 3) == 3);
   assert(bitÇek(veri, 2, 3) == 6);
   assert(bitÇek(veri, 3, 3) == 5);
   assert(bitÇek(veri, 4, 3) == 2);
   assert(bitÇek(veri, 5, 3) == 5);
}

/*
* Yukarıdaki bitÇek gibi işler ama iki elemanlı sabit dizi kullanır. Çekilen
* bitler her iki eleman üzerinde duruyor olabilir.
*/
E bitÇek(T : E[2], E)(T veri, size_t konum, size_t adet)
   if (isStaticArray!T)
{
   if ((konum + adet) < toplamBit!E) {
       // Hepsi ilk baytın içinde
       return bitÇek(veri[0], konum, adet);

   } else if (konum >= toplamBit!E) {
       // Hepsi ikinci baytın içinde
       return bitÇek(veri[1], konum - toplamBit!E, adet);

   } else {
       // İki baytta da parçası var
       immutable ilkBaytBiti = toplamBit!E - konum;
       immutable ikinciBaytBiti = adet - ilkBaytBiti;

       auto sonuç = ((bitÇek(veri[0], konum, ilkBaytBiti) << ikinciBaytBiti) |
                     bitÇek(veri[1], 0, ikinciBaytBiti));

       // İşlemler int terfileri nedeniyle E'den başka bir türde gerçekleşmiş
       // olabilir. Eleman türüne dönüştürmemiz gerekiyor.
       return cast(E)sonuç;
   }
}

unittest
{
   ubyte[2] veri = [ 0b_1011_0101, 0b_1001_0011 ];

   assert(bitÇek(veri, 0, 2) == 2);
   assert(bitÇek(veri, 2, 3) == 6);
   assert(bitÇek(veri, 6, 5) == 12);
   assert(bitÇek(veri, 8, 4) == 9);
   assert(bitÇek(veri, 11, 5) == 19);
}

/*
* Belirtilen aralığı bir bit topluluğu olarak görür. O bitleri her birisi
* 'parçaGenişliği' genişliğindeki parçalar halinde sunar.
*/
struct BitParçaları(size_t parçaGenişliği, R)
   if (isInputRange!R &&
       __traits(isUnsigned, ElementType!R) &&
       parçaGenişliği <= toplamBit!(ElementType!R))
{
   alias E = ElementType!R;

   R aralık;                 // Asıl aralık

   Unqual!E[2] araBellek;    // Aralığın ilk iki elemanının kopyası

   size_t konum;             // Bir sonraki okumanın araBellek'in hangi
                             // konumundan olacağı

   int hazırBitler;          // araBellek'te kaç bitin hazır olduğu (Eksi
                             // değer aralığın boş olduğunu belirtir)

   Unqual!E front_;          // Bu aralığın ilk elemanı

   /*
    * Asıl aralığın bir sonraki elemanını ara belleğin belirtilen elemanına
    * okur
    */
   void elemanOku(size_t hangiBayt)
   {
       araBellek[hangiBayt] = aralık.front;
       aralık.popFront();
       hazırBitler += toplamBit!E;
   }

   /*
    * front()'un değerini hazırlar
    */
   void ilkElemanıHazırla()
   {
       front_ = bitÇek(araBellek, konum, parçaGenişliği);
       konum += parçaGenişliği;
       hazırBitler -= parçaGenişliği;
   }

   this(R aralık)
   {
       this.aralık = aralık;
       this.konum = 0;
       this.hazırBitler = 0;

       if (!this.aralık.empty) {
           elemanOku(0);

           if (!this.aralık.empty) {
               elemanOku(1);
           }

           ilkElemanıHazırla();

       } else {
           // Boş olduğumuzu özel bir değerle belirt
           this.hazırBitler = -1;
       }
   }

   bool empty() const @property
   {
       return hazırBitler < 0;
   }

   E front() const @property
   {
       return front_;
   }

   void popFront()
   {
       if (hazırBitler < parçaGenişliği) {
           // Hazırda yeterli bit yok

           if (konum >= toplamBit!E) {
               // Buraya geldiysek ikinci bayttan okumaktayız demektir. Yeni
               // elemana yer açmak için ikinci baytı ilk bayta kaydırıyoruz.
               araBellek[0] = araBellek[1];
               konum -= toplamBit!E;
           }

           if (!aralık.empty) {
               elemanOku(1);

           } else {
               // Asıl aralıkta eleman kalmamış. Son baytı boşaltalım.
               araBellek[1] = E.init;

               if (hazırBitler > 0) {
                   // En az bir bit daha sunmamız gerekiyor. Sondaki elemana
                   // erişilebilsin diye hazırdaki bitleri parça genişliğine
                   // eşitliyoruz.
                   hazırBitler = parçaGenişliği;
               }
           }
       }

       ilkElemanıHazırla();
   }
}

/*
* BitParçaları aralığının kolaylık işlevi. Dizgileri doğru işleyebilmek için
* bundan iki tane yazmamız gerekti. Yoksa örneğin string'ler dchar aralıkları
* olarak ilerleniyorlardı ve o zaman her bir karakter 32 bit olarak
* genişlemis oluyordu.
*/
BitParçaları!(parçaGenişliği, R)
bitParçaları(size_t parçaGenişliği, R)(R aralık)
   if (!(is (R : const(char)[])))    // "string değilse" anlamında. (wchar
                                     // ile de ilgilenmek gerek ama şimdilik
                                     // boşverdim.
{
   return BitParçaları!(parçaGenişliği, R)(aralık);
}

/*
* Aynı kolaylık işlevinin string yüklemesi. string'ler ubyte aralıkları
* olarak işlenecekler.
*/
BitParçaları!(parçaGenişliği, ubyte[])
bitParçaları(size_t parçaGenişliği)(string aralık)
{
   return bitParçaları!parçaGenişliği(cast(ubyte[])aralık);
}

unittest
{
   // Sonda iki tane de 0 biti varsayılır
   ubyte[] veri = [ 0b01110_101 ];
   assert(bitParçaları!5(veri).array == [ 0b01110, 0b10100 ]);
}

unittest
{
   // Bunu elle doldurdum. Her beşer bit artan değer taşıyor.
   ubyte[] veri = [ 0b00000_000,
                    0b01_00010_0,
                    0b0011_0010,
                    0b0_00101_00,
                    0b110_00111,
                    0b01000_010,
                    0b01_01010_0,
                    0b1011_0110,
                    0b0_01101_00 ]; // Sonda üç tane 0 biti varsayılır.

   assert(bitParçaları!5(veri).array
          == [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0 ]);
}

/*
* Bu aralık, asıl aralığın uzunluğu kısa bile olsa onu 'bölen'e tam bölünen
* bir uzunlukta gösterir. Örneğin 'bölen' 4 ise, aralıkta tek eleman bile
* olsa o tek eleman ve üç tane de doldurma elemanı olarak sunulur.
*/
struct UzunluğuTamBölünen(R)
{
   R aralık;
   size_t bölen;
   ElementType!R doldurmaElemanı;
   size_t toplamEleman;

   this(R aralık, size_t bölen, ElementType!R doldurmaElemanı)
   {
       this.aralık = aralık;
       this.bölen = bölen;
       this.doldurmaElemanı = doldurmaElemanı;
   }

   bool empty() const @property
   {
       // Boş kabul edilebilmesi için toplam uzunluğun 'bölen'e tam bölünmesi
       // gerekir.
       return aralık.empty && !(toplamEleman % bölen);
   }

   ElementType!R front() const @property
   {
       // Asıl aralık boşsa kendimiz 'doldurmaElemanı' üretmeliyiz.
       return aralık.empty ? doldurmaElemanı : aralık.front;
   }

   void popFront()
   {
       if (!aralık.empty) {
           aralık.popFront();
       }

       ++toplamEleman;
   }
}

/*
* UzunluğuTamBölünen aralığının kolaylık işlevi
*/
UzunluğuTamBölünen!R
uzunluğuTamBölünen(R, E)(R aralık, size_t bölen, E doldurmaElemanı)
       if (is (E : ElementType!R))
{
   return UzunluğuTamBölünen!R(aralık, bölen, doldurmaElemanı);
}

unittest
{
   assert(uzunluğuTamBölünen([ 1, 1, 1, 1, 1 ], 4, 42).array
          == [ 1, 1, 1, 1, 1, 42, 42, 42 ]);

   assert(uzunluğuTamBölünen([ 3 ], 8, 7).array
          == [ 3, 7, 7, 7, 7, 7, 7, 7 ]);
}

/*
* Asıl aralığın elemanlarını belirtilen alfabeye erişen indeks değerleri
* olarak kullanır.
*/
struct Dönüştür(R)
{
   R aralık;
   string alfabe;

   bool empty() const @property
   {
       return aralık.empty;
   }

   char front() const @property
   {
       return alfabe[aralık.front];
   }

   void popFront()
   {
       aralık.popFront();
   }
}

/*
* Dönüştür'ün kolaylık işlevi.
*/
Dönüştür!R
dönüştür(R)(R aralık, string alfabe)
{
   return Dönüştür!R(aralık, alfabe);
}

unittest
{
   assert(dönüştür([ 0, 1, 3, 3, 7 ], "abcdefghi").array == "abddh");
}

enum Base32Alfabesi : string
{
   Rfc4648 =    "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567=",
   Rfc4648Hex = "0123456789ABCDEFGHIJKLMNOPQRSTUV=",
   Crockford =  "0123456789ABCDEFGHJKMNPQRSTVWXYZ=",
}

enum ubyte doldurmaKarakteriİndeksi = Base32Alfabesi.Rfc4648.length - 1;

/*
* Belirtilen aralığı Base32'ye dönüştürür. Dönüş türü tembel bir aralıktır.
*/
auto base32(T)(T veri, Base32Alfabesi alfabe = Base32Alfabesi.Rfc4648)
{
   return (bitParçaları!5(veri)
           .uzunluğuTamBölünen(8, doldurmaKarakteriİndeksi)
           .dönüştür(alfabe));
}

unittest
{
   ubyte[] a = [ 0b00000_000,
                 0b01_00010_0,
                 0b0011_0010,
                 0b0_00101_00,
                 0b110_00111,
                 0b01000_010,
                 0b01_01010_0,
                 0b1011_0110,
                 0b0_01101_11,
                 0b111_11111 ];

   assert(base32(a).array == "ABCDEFGHIJKLMN77");
}

unittest
{
   // Rfc4648 belgesindeki "test vectors" örnekleri
   assert(base32("").array == "");
   assert(base32("f").array == "MY======", base32("f").array);
   assert(base32("fo").array == "MZXQ====");
   assert(base32("foo").array == "MZXW6===");
   assert(base32("foob").array == "MZXW6YQ=");
   assert(base32("fooba").array == "MZXW6YTB");
   assert(base32("foobar").array == "MZXW6YTBOI======");

   assert(base32("", Base32Alfabesi.Rfc4648Hex).array == "");
   assert(base32("f", Base32Alfabesi.Rfc4648Hex).array == "CO======");
   assert(base32("fo", Base32Alfabesi.Rfc4648Hex).array == "CPNG====");
   assert(base32("foo", Base32Alfabesi.Rfc4648Hex).array == "CPNMU===");
   assert(base32("foob", Base32Alfabesi.Rfc4648Hex).array == "CPNMUOG=");
   assert(base32("fooba", Base32Alfabesi.Rfc4648Hex).array == "CPNMUOJ1");
   assert(base32("foobar", Base32Alfabesi.Rfc4648Hex).array
          == "CPNMUOJ1E8======");
}

void main()
{}

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

February 09, 2013

Teşekkürler Ali hocam,

Bu durumda kodlarını kütüphanemin baş köşesine koymam gerekiyor...:)

Tabi önce kodları anlamam ve denemem lazım. Bu Pazar sabahına henüz yeni uyandım. Biraz kendime geleyim, gün içerisinde bu konu hakkında yazışmak isterim.

Sevgiler, saygılar...

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

February 09, 2013

O assert hata ayıklarken o hale gelmişti. O satırda hata yok aslında. assert başarısız olursa üçüncü parametresini mesaj olarak yazdırır. Bir noktada o assert geçmiyordu ben de ne hesaplandığını görmek için üçüncü parametresini eklemiştim.

bitÇek, verilen değerin istediğimiz bitlerini değer olarak döndürüyor. Base32 veriyi beşer bit olarak ele alır ya... Ben de "şu değerin şu bitinden başlayarak 5 bitin değerini ver" demek istedim.

Sekiz bit üzerinde görelim. Ama bir fark var: 0 numaralı bit alışılmışın tersi olarak solda:
'
bit numarası: 0 1 2 3 4 5 6 7
---------------
değer: 0 0 1 1 0 1 0 1
'

O değerin 0'ıncı bitinden başlayan 3 bitin değerine bakalım: İkili olarak 001, yani 1.

Başka örnek, 2'nci bitinden başlayan 4 bitin değerine bakalım: ikili 1101, yani 13.

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

February 09, 2013

D'nin ve aralıkların üstünlüğünü tekrar yaşadım ve heyecanlandım! :) Yukarıdaki programı yalnızca Base32'yi desteklemek için ve gerçekten Base64'e hiç bakmadan yazmıştım. Base64'ün veriyi altışar bit ayırdığını biliyordum ama hiç denememiştim. Buna rağmen aynı aralıklar base64() işlevini de destekliyorlar.

Programa yalnızca aşağıdaki kodları ekledim ve Base64'ün işi de bitmişti:

enum Base64Alfabesi : string
{
   Rfc4648 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
             "abcdefghijklmnopqrstuvwxyz"
             "0123456789+/="
}

enum ubyte Base64DoldurmaKarakteriİndeksi = Base64Alfabesi.Rfc4648.length - 1;

auto base64(T)(T veri, Base64Alfabesi alfabe = Base64Alfabesi.Rfc4648)
{
   return (bitParçaları!6(veri)
           .uzunluğuTamBölünen(4, Base64DoldurmaKarakteriİndeksi)
           .dönüştür(alfabe));
}

Aslında tek hata yapmışım: uzunluğuTamBölünen()'e yine 8 vermişim; oysa Base64'te 4 olacakmış. Onu düzeltince iş bitti. :) Şu birim testleri geçiyor:

unittest
{
   // Rfc4648 belgesindeki "test vectors" örnekleri
   assert(base64("").array == "");
   assert(base64("f").array == "Zg==");
   assert(base64("fo").array == "Zm8=");
   assert(base64("foo").array == "Zm9v");
   assert(base64("foob").array == "Zm9vYg==");
   assert(base64("fooba").array == "Zm9vYmE=");
   assert(base64("foobar").array == "Zm9vYmFy");
}

Bu, bir kaç ay önce konuştuğumuz makalede anlatılanın çok güzel bir örneği:

http://ddili.org/forum/thread/989

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

February 09, 2013

Bu da Base16: :)

enum Base16Alfabesi : string
{
   Rfc4648 = "0123456789ABCDEF"
}

/*
* Belirtilen aralığı Base16'ya dönüştürür. Dönüş türü tembel bir aralıktır.
*/
auto base16(T)(T veri, Base16Alfabesi alfabe = Base16Alfabesi.Rfc4648)
{
   return (bitParçaları!4(veri)
           .dönüştür(alfabe));
}

unittest
{
   assert(base16("").array == "");
   assert(base16("f").array == "66");
   assert(base16("fo").array == "666F");
   assert(base16("foo").array == "666F6F");
   assert(base16("foob").array == "666F6F62");
   assert(base16("fooba").array == "666F6F6261");
   assert(base16("foobar").array == "666F6F626172");
}

Dikkat ederseniz bunda doldurma karakteri yok. RFC'de Base16'nın hep denk geldiği yazılı. (Zaten her bayta iki kod sığıyor ve hep tam geliyor). O yüzden bunda uzunluğuTamBölünen()'e gerek kalmadı.

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

February 09, 2013

bitÇek'lerin birim testlerini aşağıdaki gibi değiştirince daha kolay anlaşılacaklarını düşünüyorum. Hangi bitlerinin alındığı verinin bitlerinin altına rastlatılınca daha kolay görülüyor:

unittest
{
   ubyte veri =                 0b10101100;
   assert(bitÇek(veri, 0, 1) == 0b1_______);
   assert(bitÇek(veri, 0, 2) == 0b10______);
   assert(bitÇek(veri, 0, 3) == 0b101_____);
   assert(bitÇek(veri, 0, 4) == 0b1010____);
   assert(bitÇek(veri, 0, 5) == 0b10101___);
   assert(bitÇek(veri, 0, 6) == 0b101011__);
   assert(bitÇek(veri, 0, 7) == 0b1010110_);
   assert(bitÇek(veri, 0, 8) == 0b10101100);
   assert(bitÇek(veri, 0, 0) == 0);

   veri =                       0b10110101;
   assert(bitÇek(veri, 0, 3) == 0b101_____);
   assert(bitÇek(veri, 1, 3) == 0b_011____);
   assert(bitÇek(veri, 2, 3) == 0b__110___);
   assert(bitÇek(veri, 3, 3) == 0b___101__);
   assert(bitÇek(veri, 4, 3) == 0b____010_);
   assert(bitÇek(veri, 5, 3) == 0b_____101);
}

// ...

unittest
{
   ubyte[2] veri =            [ 0b10110101,
                                        0b10010011 ];
   assert(bitÇek(veri, 0, 2) == 0b10______________);
   assert(bitÇek(veri, 2, 3) == 0b__110___________);
   assert(bitÇek(veri, 6, 5) == 0b______01100_____);
   assert(bitÇek(veri, 8, 4) == 0b________1001____);
   assert(bitÇek(veri, 11, 5) ==0b___________10011);
   assert(bitÇek(veri, 0, 0) == 0);
}

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

February 12, 2013

Merhaba,

Elbette standartlar, büyüklerimiz (hatta onların da büyükleri) tarafından defalarca tecrübe edilmiş ve kullanılmasına salık verilmiş güvenli kaidelerden oluşuyor. Ancak Crockford'un yaptığı gibi, gelişen şartları dikkate alıp standartlara yenilikler getirmenin bir sakıncası olmasa gerek. Şimdi bir kaç not alıp test sonuçları ile bilgilerimizi katmerleyelim...:)

  • Phobos kütüphanesinde adıyla ayrılmış bir std\base64 modülü mevcuttur.
  • Kısmen ihtiyaç duyulmayacağı düşüncesiyle base32'ye yer verilmemiştir.
  • Bu konunun çıkış noktası olan standart, kolayca her dilde programlanabilir.
  • Abecesi veya algoritması arzuya göre kişiselleştirilebilir. Örneğin
    ** Crocford'un Abecesi
    ** Base32v65 Algoritması gibi...

Test için şuradaki (http://hubblesite.org/gallery/album/galaxy/pr2003028a/warn/), yaklaşık 221 MB.'lık TIFF dosyası (M104 - Sombrero Gökadası) seçilmiştir. Kendisini çok sevdiğim için ve Hubble'ın çektiği çok güzel bir kare fotoğraf bulunduğundan bunu seçtim. Teşekekkürler NASA...

Platform olarak 8 GB.'lık 64 bit Linux kullanılmış ve giriş seviyesinde basit bir işlemci (Intel® Core™ i3 CPU 540 @ 3.07GHz × 4) ile yetinilmiştir. Derleyici ise DMD'nin v2.059-64 bit sürümü kullanılmış, time komutu ile toplam işlem süresi ölçülmüştür. TEST1 (base32) ve TEST2(base32v65) gerçekleştirilirken main() kodu ise şu şekilde tertiplenmiştir:

void main() {
 auto inFile = File("/home/atelyeweb/Resimlerim/hs-2003-28-a-full_tif.tif", "r");
 auto buffer = new char[](inFile.size);
      inFile.rawRead(buffer);

 auto outFile = File("hs-2003-28-a-full_tif.b32", "w");
      //outFile.write(base32(cast(string)buffer).array);/* TEST1
      with(new TEST(cast(string)buffer, dicts.RFC4648)) {
         outFile.write(str2encode());
      }//* TEST2 */
}

Bir kaç tekrarlı alınan sonuçlar ise şöyle:

' TEST1 TEST1
real 0m33.168s real 0m24.697s
real 0m31.817s real 0m23.616s
real 0m31.851s real 0m23.725s

354.048.280 / 359.580.286 bytes (Decompress)
198.770.551 / 203.081.872 bytes (ZIP file)'

Özetle; base32.RFC4648 standardında doldurma karakter (=) bulunmasına rağmen (aslında diğerinde de doğal bir null karakteri mevcut), dosya boyutu binde 15 daha kısa olmuştur. Ancak süre ortalamalarına (32 / 24 sn.) baktığımızda 8 sn. daha yavaş işlem yaptığı gözlemlenmiştir.

Başarılar...

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

February 12, 2013

Ben de onu soracaktım hocam...:)

Parça parça okumamız gerektiğini bildiğimden, bunu nasıl ve en hızlı şekilde yapabileceğimizi öğrenmek istiyordum. Chunk'u daha önce kullanmadım ve ezberimde sadece her şeyi hafızaya alıp orada işlemek vardı. Zaten sistem kaynakları konusunda sıkıntı çıkmıyor ve belki bir kaç GB. dosyayı aynı şekilde işleyebilirdim.

Şimdi bu sorunu madem aştık başka bir sorundan bahsedeyim. Sanırım bunu benim çözmem gerekecek çünkü binary dosyalarda decrypt yaptığımda kısmen dosyanın bozulduğunu tespit ettim. Buna da null character'leri dikkate almama ile ilgili bölümün neden olduğunu düşünüyorum:

   for(size_t i; i < code.length; i += 13) {
     con.num = cmd.decode(code[i..i + 13]);
     foreach(chr; con.str) {
       // Eğer null character ise dikkate alma!
       if(chr) rslt ~= chr; // <------------------------------ bu satır!
     }
   }

Dolayısıyla henüz algoritma 0,5 bile değil. Tamam, decrypt kısmen hazır ama birbirleri ile uyum için bazı şeyleri değiştirmem şart görünüyor. Çünkü dosya %3-5 oranında bozuluyor...:(

Başarılar...

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]