28 Eylül 2017 Perşembe

Variable Length Array

Giriş
Variable Length Array (VLA) sadece C dilinde bulunur.

Örnek
Şöyle yaparız.
#include <stdio.h>
int main(int argc, char const *argv[])
{
  int n;
  scanf("%d",&n);
  int k[n];
  printf("%ld",sizeof(k));
  return 0;
}
C++
Bazı derleyiciler bu özelliği destekler. gcc ve clang gibi. MSVC desteklemez. Açıklaması şöyle
VLA's are not standard C++. Some compilers support them as an extension.
Şöyle yaparız.
class Test {
public:
  Test() {
    P = 5;
  }
  void somemethod() {
    int array[P];
    // do something with the array
  }
private:
  int P;
}

27 Eylül 2017 Çarşamba

Gömülü Proje - BitStream

Giriş
Bu sınıfı sağdan sola doğru okuma ve yazma işlemi yapar. Çok nadiren de olsa soldan sağa doğru kullanılan BitStream sınıfları da gördüm.

Bit Mask
Açıklaması şöyle
A bit mask is used to mask some bits of a bit field while exposing others.
initial value: 011011001
bit mask.....: 111110000
result value.: 011010000

MASK'lar şöyledir
const unsigned int MASKS      [] = {0,           //0
                                                        0x1,      //1
                                                        0x3,      //2
                                                        0x7,      //3
                                                        0xf,       //4
                                                        0x1f,     //5
                                                        0x3f,     //6
                                                        0x7f,     //7
                                                        0xff,      //8
                                                       }
Header
Şöyle yaparız.
class BitStream {
  uint32_t m_BitPosition;
  uint32_t m_BytePosition;
  uint8_t* m_pBuffer;
  uint32_t m_SizeInBytes;
}
Constructor
Şöyle yaparız.
BitStream(uint8_t* pBuffer,uint32_t sizeInBytes){
  m_BitPosition      = 0;
  m_ BytePosition = 0;
  m_pBuffer            = pBuffer;
  m_SizeInBytes     = sizeInBytes;
}
setPosition metodu
Şöyle yaparız.
void setPosition (uint32_t bitPosition){
  m_BytePosition = bitPosition /  8;
  m_BitPosition = bitPosition % 8;
}
read metodu
Şöyle yaparız. Bu metod içinde buffer overflow kontrolü yok ancak kolaylıkla yapılabilir.
//1 ile işaretli yerde mask zaten okunmuş bit sayısı kadar kaydırılır. Böylece doğru mask elde edilir. Buffer'dan istenilen bit sayısı okunduktan sonra elde edilen değer tekrar sağa kaydırılır.
//2 ile işaretli yerde okunan değer toplam okunan bit sayısı kadar kaydırılı ve sonuca dahil edilir.
uint32_t read (uint8_t numberOfBits){
  uint32_t result = 0;

  uint8_t bitsRead = 0;
    while (numberOfBits > 0) {
      uint8_t bitsToRead = numberOfBits;
      bool nextByte = false;
   
      if (numberOfBits + m_BitPosition) > 8) {
        bitsToRead = 8 - m_BitPosition;
        nextWord = true;
      }

      numberOfBits -= bitsToRead;
      //1
      uint8_t buf = ((MASKS [bitsToRead] << m_BitPosition) & m_pBuffer [m_BytePosition]) >> m_BitPosition;

      if (nextByte){
        m_BytePosition ++;
        m_BitPosition = 0;

      }
      else {
        m_BitPosition +=   bitsToRead;
      }
    //2
    result |= (buf << bitsRead);
    bitsRead += bitsToRead;
  } //while
  return result;
}
write metodu
Şöyle yaparız. Bu metod içinde buffer overflow kontrolü yok ancak kolaylıkla yapılabilir.
//1 ile işaretli yerde buffer'daki alan temizlenir
//2 ile işaretli yerde data yazılır
//3 ile işaretli yerde data'nın yazılan bitleri atılır.
void write (uint32_t data, uint8_t numberOfBits){

  while (numberOfBits > 0) {
    uint8_t bitsToWrite = numberOfBits;
    bool nextByte = false;
   
    if (numberOfBits + m_BitPosition) >= 8) {
      bitsToWrite = 8 - m_BitPosition;
      nextByte = true;
    }

    numberOfBits -= bitsToWrite;
    //1
    m_pBuffer [m_BytePosition] &= ~(data & (MASKS [bitsToWrite] << m_BitPosition);
    //2
    m_pBuffer [m_BytePosition] |= (data & (MASKS [bitsToWrite] << m_BitPosition);

    if (nextByte){
      m_BytePosition ++;
      m_BitPosition = 0;
    }
    else {
      m_BitPosition +=   bitsToWrite;
    }
    //3
    data = (data >> bitsToWrite);
  }

};





std::time_t

Giriş
Bu yapı ile Epoch'tan beri geçen saniye tutulur.

std::time_t yapısının ne olduğu belirsiz bırakılmış ancka integral bir type olarak tanımlıdır. Yani 32 veya 64 bit integer olarak. Benim gördüğüm tüm derleyicilerde long veya long türevi olarak gerçekleştirilmiş.

gün + saat +dakika + saniye'ye dönüşüm
time_t'yi long kabul edersek, şöyle yaparız.
static void printRemainingTime(time_t t) {
  const char *s = "%d days, %d hours, %d minutes, %d seconds remaining...\n";
  int days = t / 86400;
  t -= days * 86400;
  int hours = t / 3600;
  t -= hours * 3600;
  int minutes = t / 60;
  t -= minutes * 60;
  int seconds = t;
  fprintf(stdout, s, days, hours, minutes, seconds);   
}

struct tm

Giriş
broken time olarak ta bilinir. Alanların alabileceği değerler şöyle. Year alanı 1900'den başlar. Month alanı ise 0'dan başlar. Ocak 2016 için year alanına 116, month alanına ise 0 değeri verilir.
int tm_sec; // seconds after the minute — [0, 60]
int tm_min; // minutes after the hour — [0, 59]
int tm_hour; // hours since midnight — [0, 23]
int tm_mday; // day of the month — [1, 31]
int tm_mon; // months since January — [0, 11]
int tm_year; // years since 1900
int tm_wday; // days since Sunday — [0, 6]
int tm_yday; // days since January 1 — [0, 365]
int tm_isdst; // Daylight Saving Time flag

String'e çevirme
Şöyle yaparız.
struct tm * ptm = ..
char buf[64];
memset(buf, 0, sizeof(buf));
sprintf(veccNextTime, "%d-%02d-%02d %02d:%02d:%02d.000",
        ptm->tm_year + 1900, ptm->tm_mon + 1, ptm->tm_mday,
        ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
std::string str (buf);

26 Eylül 2017 Salı

Closure

Giriş
Closure, lambda ile kullanılıyor. Bu yazıdan lambda konusuna değinmiyorum. Sadece closure sözdizimi üzerinde duracağım.
Closure sözdizimi şöyle. Capture ve mutable alanları mecburi değil.
["CAPTURE"] PARAMETERS ["mutable"] [RETURN] { BODY }
C++11'de kullanılabilecek closure türleri şöyle
[]  Capture nothing (or, a scorched earth strategy?)
[&] Capture any referenced variable by reference
[=] Capture any referenced variable by making a copy
[=, &foo]   Capture any referenced variable by making a copy,
 but capture variable foo by reference
[bar]   Capture bar by making a copy; don't copy anything else
[this]  Capture the this pointer of the enclosing class
Odr-Used
Closure sadece odr-used değişkenleri capture etmek zorunda. const değişkenleri veya derleme zamanı değişkenleri capture etmeden de kullanabiliriz. Şöyle yaparız.
#include <iostream>

template<typename T> void foo(const int *, T f) {...}

int main()
{
  const int data=0;
  foo(&data,[](int baz){
    return data;
  });
}
1. Capture By Reference
Closure - Capture By Reference yazısına taşıdım.

2. Capture By Value
Closure - Capture By Value yazısına taşıdım.

Closure ve Move
Closure move işlemine tabi tutulabilir. Bu durumda içinde capture edilen değişkenler de move edilir. Şöyle yaparız.
std::string s{"Test"};
auto T = [s]() { std::cout << s.size() << ' '; };  // make a copy of s
T();
auto F = std::move(T);
T();
F();
Çıktı olarak 4 0 4 alırız.



25 Eylül 2017 Pazartesi

MultiByteToWideChar

Giriş
Windows bir çok API'de UTF-16 kullanıyor. Bu yüzden UTF-8'in UTF-16'ye çevrilmesi ve std::string içinde saklanması gerekiyor.

Örnek
Şöyle yaparız.
#include <windows.h>

std::string get_filename_token( const std::string& filename )
{
  // Convert the UTF-8 argument path to a Windows-friendly UTF-16 path
  wchar_t* widepath = new wchar_t[ filename.length() + 1 ];
  MultiByteToWideChar( CP_UTF8, 0, filename.c_str(), -1, widepath, filename.length() + 1);

  // Now get the 8.5 version of the name
  DWORD n = GetShortPathNameW( widepath, NULL, 0 );
  wchar_t* shortpath = new wchar_t[ n ];
  GetShortPathNameW( widepath, shortpath, n );

  // Convert the short version back to a C++-friendly char version
  n = WideCharToMultiByte( CP_UTF8, 0, shortpath, -1, NULL, 0, NULL, NULL );
  char* ansipath = new char[ n ];
  WideCharToMultiByte( CP_UTF8, 0, shortpath, -1, ansipath, n, NULL, NULL );

  std::string result( ansipath );

  delete [] ansipath;
  delete [] shortpath;
  delete [] widepath;

  return result;
}