Jump to page: 1 2
Thread overview
Base32v65
Feb 07, 2013
Salih Dinçer
Feb 10, 2013
Salih Dinçer
Feb 10, 2013
Salih Dinçer
Feb 10, 2013
Salih Dinçer
Feb 11, 2013
Salih Dinçer
Feb 11, 2013
Salih Dinçer
February 07, 2013

Merhaba,

Bu konu sadece D dilini ilgilendirmiyor. Aslında tam olarak D Dili ile yapmak istediğim bir çözümü yine bu forumda bulmuş ve yayınlamış oluyorum. Elbette forum, D ile ilgili olduğuna göre yine aşağıdaki basit kodlar, aynı dilin mahsulü...:)

Kodlara geçmeden evvel bir özeleştiri yapmalıyım!

Sanırım, internete başladığımdan beri (1996'lı yıllar) hep karşıma çıkan Base32 konusunda hiç çalışmamış olmam ve böyle bir temel konuyu öğrenmeyişim, büyük bir eleştiri konusu olsa gerek. Öyle ya, e-postaların ekli dosyalarından tutun da internette hep karşımıza gelir bu Base32 kodlama. Gerçi ben bilinçli olarak standartlardan uzaklaşarak, Crockford'un abecesini ve kendi kodlamamı kullanmak istedim. Ama sonuçta işin tekniğini öğrendim ve belki hızlı bir algoritma geliştirmeyi amaçlamakla suçumu affetirmiş olurum inşaallah...

Bu tartışma şurada alevlenmişti: http://ddili.org/forum/thread/1094

import std.stdio;

struct Base32v65 {
 string abece;
 ulong[char] dizin;

 this(string alphabet) {
   this.abece = alphabet;
   foreach(i, a; abece) {
     dizin[a] = i;
   }
 }

 auto encode (ulong veri) @property{
   string dizge;

   do {
     dizge ~= abece[veri & 31];
   } while(veri>>=5);

   return dizge;
 }

 auto decode (string veri) @property {
   ulong sayı;

   foreach(i, v; veri) {
     sayı += dizin[v] * (32UL ^^ cast(ulong)i);
   }

   return sayı;
 }
}

void main() {
 /* Alphabetical Reference:
  * http://www.crockford.com/wrmg/base32.html
  */ string rfc4648  = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
 /*
  *http://tools.ietf.org/html/rfc4648
  */ string alphabet = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";

 auto rakamlar = 9876543210UL;

 auto base32 = Base32v65(rfc4648);
 string deneme = base32.encode(ulong.max);//rakamlar);
        deneme.writeln(": Base32v65 Encoded");

 ulong çözücü = base32.decode(deneme);
       çözücü.writeln(": Base32v65 Decoded");
/+ Toogle Switch On/Off
 long.max.writeln(": long.max"); //9223372036854775807: long.max
 writefln("%b", long.max);/* 63.bit--------------------------v
111111111111111111111111111111111111111111111111111111111111111
*/
 ulong.max.writeln(": ulong.max"); //18446744073709551615: ulong.max
 writefln("%b", ulong.max);/* 64.bit--------------------------v
1111111111111111111111111111111111111111111111111111111111111111
*/
/*v----Toggle Switch Close
 +/
//*/
}

Başarılar...

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

February 07, 2013

Bu kodlamanın bir dizi bayta uygulanması gerekiyor. Kodu doğru anlıyorsam, senin algoritma sonucu ters sırada veriyor, değil mi? Base32'nin RFC'si şu:

https://tools.ietf.org/html/rfc4648

Sonlara doğru, "Test Vectors"ün altında beklenen sonuçlar var.

Ali

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

February 10, 2013

Ali hocam dün, şu iletisinde, standartlara bağlı kalarak ve aralıkları kullanarak harika bir iş başarmış:
http://ddili.org/forum/post/8745

Açıkcası yapmak istediğimden fazlası yer alıyor. Hatta bunlar Phobos içinde bulunmadığından ilk fırsatta kodların kütüphaneye eklenmesini önereceğim. Tabi yazarı bunu kabül ederse...:)

Ben de base32 standartı ile basit v65 sürümünü karşılaştırmak için şu aşağıdaki test kodunu yazdım. Kabül ediyorum çok çok amatörce ve Ali hocamın kodlarına bile yaklaşamaz! Ama n'apayım, basit şeyler kafama daha iyi oturuyor...

// Derleme:dmd base32v65.d sdb\algorithm.d
import std.stdio,
      sdb.algorithm;
enum dicts : string {
 RFC4648    = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567",  // http://tools.ietf.org/html/rfc4648
 RFC4648HEX = "0123456789ABCDEFGHIJKLMNOPQRSTUV",  // HEX'in devamı ile uyumlu
 Crockford  = "0123456789ABCDEFGHJKMNPQRSTVWXYZ",  // İnsan algılarıyla uyumlu
 ASCIIcomp  = "0ABCDEFGHIJKLMNOPQRSTUVWXYZ12345"   /* ASCII ile uyumlu giden abece!
 Örneğin 'a' => AC, 'A' => AB, '0' => PA, '9' => YA kodlarına denk geliyor... */
}

class TEST {
 string str;
 Base32v65 cmd;

 this(string dizge, dicts abece) {
   this.str = dizge;
   this.cmd = Base32v65(abece);
 }

 auto str2encode() @property {
   string rslt;

   foreach(ulong chr; this.str) {
     rslt ~= cmd.encode(chr);
   }
   return rslt;
 }

 auto str2decode(string code) @property {
   string rslt;

   for(size_t i; i < code.length-1; i+=2) {
     string chr;
     chr ~= code[i];
     chr ~= code[i+1];
     rslt ~= cast(char)cmd.decode(chr);
   }
   return rslt;
 }
}

void main() {
 auto veri = "foobar";
 auto test = new TEST(veri, dicts.RFC4648);

 auto kodu = test.str2encode();
      kodu.writeln; /* => GDPDPDCDBDSD (RFC4648) */

 assert(test.str2decode(kodu) == veri);

 auto dosya = File("base32v65.d", "r");
 auto okuma = new char[](40); // Dosyanın başında 40 byte okur!

 dosya.rawRead(okuma);
 okuma.writeln; // Derleme:dmd base32v65.d sdb\algorithm

 auto base32 = new TEST(cast(string)okuma, dicts.RFC4648);
      base32.str2encode.writeln; /* Çevrilen =>
PBPBABEDNDEDABCDBDTDFDTBSBWDWBVBOBEDABTDEDCD4CBDMDHDPDSDJDUDIDNDOBEDABNBSDFDMDFD
*/
}

Eğer kodu denemek isterseniz, sizde sdb/algorithm.d dosyası olmayacağı için sıkıntı yapacaktır. Bunun yerine Base32v65 yapısını, aynı dosya içine veya sdb dizinindeki algorithm.d dosyası içine şu başlık ile ekleyerek de yapabilirsiniz:
Alıntı:

>
> module sdb.algorithm;
> public import std.math;
> ```

>

**Dip Not:** Eklemeliyim! Sözlükler (abece ~ alphabet) arasındaki farklar bazen çok önemli olabiliyor. Kimi insan algısıyla çok uyumlu olabiliyorken, başına 0 eklenerek yapılan başka bir varyasyon ASCII ile paralellik arz ediyormuş. Bu bana ilginç gelen öğeler.

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

Yorumlar için teşekkürler hocam ama forumu takip eden diğer arkadaşlarımız da iki çift cümle yazsalar ne güzel olurdu. Dialog içerisinde yaptığımız bu paylaşımlar e-posta ile de yapabilirdik. Sanırım tek farkı iki kişinin karşılıklı iletişim kurması ve buna seyirci olası çoğunluk...

O çoğunluğa sesleniyorum, nasılsınız...:)

Hocamın yorumlarını birazdan değerlendireceğim ama önemli bir vurgu daha yapmak istiyorum:

Yazdıklarım özelleştirilmiş bir base32 uygulaması; o yüzden ismi Base32v65 ya. Yani RFC4648 ile uyumlu bir sonuç üretmeye çalışmıyorum. Belki biraz gayret edersem bu olabilir ama daha önce de yazdığım gibi Ali hocamın yaptıkları benim beklentilerimi fazlasıyla karşılıyor...

Amacım daha çok hız! Yoksa aynı kodları Base64'e uyarlayamayız çünkü 64 % 6 = 2. Yani 2 bitlik fark olduğu için basit yöntemlerden vazgeçip karmaşıklaştırmak gerekiyor. Ben ise bunu istemiyorum ki hali hazırda yapılmışı var.

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

February 10, 2013

Alıntı (acehreli):

>

Base32v65 ile ayrı ayrı kodlanmış olan ulong'ları str2encode'da yapıldığı gibi uç uca ekleyemediğimizi farkettim. str2decode asıl ulong'ların her birisinin kaçar karakter olarak kodlandığını bilemez.
Hocam haklısın, ben de şimdi fark ettim...

TEST sınıfını tekrar yazmam gerekiyor, adeta ayak üstü yapılmış basit bir şey oldu. Şöyle saçma bir şey olabilir mi Allah aşkına:

   foreach(ulong chr; this.str) {
     rslt ~= cmd.encode(chr);
   }

Tamam, encode() ULONG istiyor ve biz ona foreach() sırasında bu türü veriyoruz. Ancak gel gelelim dizgeden her seferinde bir bayt okunuyor. Bunun böyle olmaması gerekiyor. Toplamda 8 byte gelmesi lazımdı. Artık kafa nereye gittiyse...:)

Teşekkürler...

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

February 10, 2013

Alıntı (Salih Dinçer):

>

kodların kütüphaneye eklenmesini önereceğim. Tabi yazarı bunu kabül ederse...:)

Olur tabii ama std.base64 zaten var. Onunla da karşılaştırmak gerek. Belki de onu base32 ve base16'ya çevirmek daha uygun olur çünkü dediğim gibi, benim yazdığım dizileri bile InputRange olarak kullandığı için gereğinden fazla işlem yapıyor (gibi geliyor). Benimkine 'if (isRandomAccessRange!R)' koşuluna uyan daha hızlı gerçekleştirmeler eklenebilir.

Alıntı:

>
>     foreach(ulong chr; this.str) {
>       rslt ~= cmd.encode(chr);
>     }
> ```


O hatalı olmuyor mu? str'nin "a" olduğunu düşünelim (iki olarak 01100001). Şimdi o değerin soldaki 5 bitinin değerini bulmak istiyoruz. Oysa, yanılmıyorsam encode() şu:


auto encode (ulong veri) @property{
string dizge;

do {
dizge ~= abece[veri & 31];
} while(veri>>=5);

return dizge;
}



Gördüğün gibi, '& 31' yaptığında değerin soldaki değil, sağdaki 5 bitini çekiyor. RFC'ye uymuyor, değil mi?

Alıntı:
>
>

auto veri = "foobar";
auto test = new TEST(veri, dicts.RFC4648);

auto kodu = test.str2encode();
kodu.writeln; /* => GDPDPDCDBDSD (RFC4648) */

O yanlış olmuş işte. RFC'ye baktığımızda "foobar" için "MZXW6YTBOI======" üretilmesi gerektiğini görüyoruz, "GDPDPDCDBDSD" değil.

Alıntı:

>
>   assert(test.str2decode(kodu) == veri);
> ```


O encode() ve decode()'un birbirleriyle uyumlu işlediklerini kanıtlıyor ama doğru işledikleri hakkında bir şey söylemiyor.

Ali

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

Alıntı (Salih Dinçer):

>

Yazdıklarım özelleştirilmiş bir base32 uygulaması; o yüzden ismi Base32v65 ya. Yani RFC4648 ile uyumlu bir sonuç üretmeye çalışmıyorum.

Pardon, ben onu hiç farketmemişim. İsmi Base32 ile başlayınca ve kod içinde RFC4648 ve RFC4648HEX isimlerini görünce Base32 üzerine konuşuyoruz sanmışım.

Ali

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

February 10, 2013

Alıntı (Salih Dinçer):

>
> class TEST {
> // ...
>   auto str2encode() @property {
>     string rslt;
>
>     foreach(ulong chr; this.str) {
>       rslt ~= cmd.encode(chr);
>     }
>     return rslt;
>   }
> // ...
> }
> ```


Base32v65 ile ayrı ayrı kodlanmış olan ulong'ları str2encode'da yapıldığı gibi uç uca ekleyemediğimizi farkettim. str2decode asıl ulong'ların her birisinin kaçar karakter olarak kodlandığını bilemez.

Örneğin, aşağıdaki 'a' ile 'b', 'c' gibi aynı "BC" kodunu üretiyor:

void main()
{
string abece = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
auto base32 = Base32v65(abece);

ulong a = 0b00001;
ulong b = 0b00010;
ulong c = 0b0001000001; // tesadüf, b ile a'nın bitlerinin yan yana
// gelmesinde oluşuyor

auto sonuç1 = base32.encode(a) ~ base32.encode(b);
auto sonuç2 = base32.encode(c);

assert(sonuç1 == "BC");
assert(sonuç2 == "BC");
}


"BC"den yola çıkarak hangi asıl kodları üreteceğimizi bilemiyoruz.

Ali

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

Ali hocam sorunu halletim galiba, bir bakarsan sevinirim. Çekirdek kodda (Base32v65 yapısında) tek düzelttiğim bölüm aşağıda ve denemek için yaptığım TEST sınıfı ise hemen altında...

Alıntı ("Base32v65 yapısındaki bir üye işlev"):

>
>   auto encode (ulong veri) @property{
>     string dizge;
>
>     foreach(i; 0..13) {  // 64 / 5 bit = ~13
>         dizge ~= abece[veri & 31];
>         veri >>= 5;
>     }
>     /* HATALI ALGORİTMA: (belirsiz döngü sayısından dolayı)
>     do dizge ~= abece[veri & 31]; while (veri >>= 5);//*/
>
>     return dizge;
>   }
> ```

>


// Derleme:dmd base32v65.d sdb\algorithm.d
import std.stdio, std.format,
sdb.algorithm;

enum dicts : string {
RFC4648 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567", // http://tools.ietf.org/html/rfc4648
RFC4648HEX = "0123456789ABCDEFGHIJKLMNOPQRSTUV", // HEX'in devamı ile uyumlu
Crockford = "0123456789ABCDEFGHJKMNPQRSTVWXYZ", // İnsan algılarıyla uyumlu
ASCIIcomp = "0ABCDEFGHIJKLMNOPQRSTUVWXYZ12345" /* ASCII ile uyumlu giden abece!
Örneğin 'a' => AC, 'A' => AB, '0' => PA, '9' => YA kodlarına denk geliyor... */
}

enum codes : string {
RFC4648 = "U2QZLZNNJL6KG",
RFC4648HEX = "KQGPBPDD9BUA6",
Crockford = "MTGSBSDD9BYA6",
ASCIIcomp = "TZPYKYMMIK4JF"
}

union char8ulong {
char[8] str;
ulong num;
}

class TEST {
string str;
Base32v65 cmd;
char8ulong con;

this(string dizge, dicts abece) {
this.str = dizge;
this.cmd = Base32v65(abece);
this.con = char8ulong(0);
}

auto str2encode() @property {
string rslt;
size_t xsay;

foreach(chr; this.str) {
con.str[xsay++] = chr;
if(xsay > 7) {
rslt ~= cmd.encode(con.num);
con.num = 0;
xsay = 0;
}
}
// char[8] hücreleri dolmadan döngü biterse:
if(xsay > 0 && xsay < 7) {
rslt ~= cmd.encode(con.num);
}
return rslt;
}

auto str2decode(string code) @property {
string rslt;

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;
}
}
return rslt;
}
}

void main() {
// ÖRNEK 1: ÇİFT KONTROL
auto veri = "Türkiye"; // ü (2x) => 8 chr
auto test = new TEST(veri, dicts.ASCIIcomp);

auto kodu = test.str2encode();
kodu.writeln;
assert(kodu == codes.ASCIIcomp);
/* => TZPYKYMMIK4JF (ASCIIcomp) = Türkiye /
assert(test.str2decode(kodu) == veri); /
OK */

// ÖRNEK 2: GÖRSEL KONTROL
with(new TEST("bar", dicts.ASCIIcomp)) {
auto test2 = str2encode();
test2.writeln(" == ", str2decode(test2));
}/* => BKXDG00000000 (ASCIIcomp) = bar

  • Not: 0'lar null character
    */

// ÖRNEK 3: DOSYA KONTROL
string okuma = "Bu bir denemedir ve nokta dahil 51 bayt yer tutar.";/*

auto okuma = new char; // Dosyanın başından itibaren 40 byte okur!
auto dosya = File("base32v65.d", "r");
dosya.rawRead(okuma); // Derleme:dmd base32v65.d sdb\algorithm//*/

auto base32 = new TEST(cast(string)okuma, dicts.RFC4648);
auto kodlanan = base32.str2encode;
kodlanan.writeln;
base32.str2decode(kodlanan).writeln; /* Çevrilen =>
/
}/
HATALI OLAN: (40 byte)
PBPBABEDNDEDABCDBDTDFDTBSBWDWBVBOBEDABTDEDCD4CBDMDHDPDSDJDUDIDNDOBEDABNBSDFDMDFD
DOĞRU OLAN: (40 byte)
PZLACCVMSD3KGNLZUDSVNEDIEGB34KWZIGWTNKDOBZASZRMCDXCGM3Z6GZFNUD22G
*/


Ayrıca aşağıya kulandığım algoritma kütüphanesinden ilgili bölüme yer vermeliyim. Her ne kadar küçük bir bölüm düzeltildiyse de konuya yabancı birinin kolaylıkla erişebilmesi için iyi olacaktır. Böylece artık yeni bir standartımız oldu; ne dersiniz?

BASE32v65 veya TS6513 gibi anlamlı sihirli sabitler...:)

module sdb.algorithm;

public import std.math;

struct Base32v65 {
string abece;
ulong[char] dizin;

this(string alphabet) {
this.abece = alphabet;
foreach(i, a; abece) {
dizin[a] = i;
}
}

auto encode (ulong veri) @property{
string dizge;

foreach(i; 0..13) { // 64 / 5 bit = ~13
dizge ~= abece[veri & 31];
veri >>= 5;
}
/* HATALI ALGORİTMA: (belirsiz dögü sayısından dolayı)
do dizge ~= abece[veri & 31]; while (veri >>= 5);//*/

return dizge;
}

auto decode (string veri) @property {
ulong sayı;

foreach(i, v; veri) {
sayı += dizin[v] * (32UL ^^ cast(ulong)i);
}

return sayı;
}
}



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

Sanırım doğru çalışıyor çünkü TEST sınıfı kurulurken bir dizin (dictionary indexing) oluşturuyorum:

struct Base32v65 {
 string abece;
 ulong[char] dizin;

 this(string alphabet) {
   this.abece = alphabet;
   foreach(i, a; abece) {
     dizin[a] = i;
   }
 }
:  :  :

Başka kodlarda, kullandığım bu çağrışımsal dizi (associative array) veya eşleme tablosu her iki işlemi (encode/decode) yaparken de kullanıldığını gördüm. Doğal olarak iki farklı dizi ve birbirinin tersi olacak şekilde geliştirilmiş. Böyle bir kaynak israfı yerine pekala encode yaparken doğal dizin değerleri (index values) kullanılabileceğini düşündüm. Hem böyle kullanım çok pratik oluyor çünkü elimizde string gibi çok güzel bir tür var. Fakat iş kodu çözmeye (decode) gelince aşağıdakinden başka yol aklıma gelmedi:

 auto decode (string veri) @property {
   ulong sayı;

   foreach(i, v; veri) {
     sayı += dizin[v] * (32UL ^^ cast(ulong)i);
   }

   return sayı;
 }

Aslında üssü ifadesini kullanmak istemiyorum. Çünkü derleyici bu işareti gördüğü yerde std.math sınıfındaki algoritmalara yönlendiriyor. Bunların da ne kadar hızlı olduğu tartışılır o yüzden, aşağıda alıntıladığım kendi kütüphanemdeki matematik sınıfındaki işlevi kullanıyorum. Hız karşılaştırması yaptığım zaman bunu da değerlendirmekte fayda görüyorum. Öyle ya, decode işlemi (kodun sayısal karşılığının çağrılmasını saymazsak) aslında çarpımların toplamları şekilde meydan gelmekte.

module sdb.newmath;

/* üsT function:
* Tam ve işaretsiz sayılarda üssünü alan işlev...
*/
auto üsT(size_t taban, size_t kuvvet = 0) @property {
 size_t sonuç = taban;
 foreach(üssü; 1..kuvvet) sonuç *= taban;
 return kuvvet ? sonuç : 1;
}

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

« First   ‹ Prev
1 2