27 Ağustos 2017 Pazar

fseek

Giriş
Şu satırı dahil ederiz.
#include <cstdio>
SEEK_SET seçeneği
Dosyanın başından itibaren 16. byte'a gitmek için şöyle yaparız.
FILE *f = fopen ('...', "rb");
fseek (f,16,SEEK_SET);

lseek metodu
fseek çağrısının POSIX dünyasında karşılığı lseek. Şu satırları dahil ederiz.
#include <sys/types.h>
#include <unistd.h>
Şöyle yaparız.
int fd = ...;
lseek (fd, 0, SEEK_SET);
Eğer lseek yapmazsak
Elimizde şöyle bir kod olsun. Okuma işlemi 4 byte ilerletir. Yazma işlemi 4. byte'tan itibaren başlar.
int num = 0;
int fd = open("/dev/sda6", O_RDWR);

ssize_t ret = read(fd, &num, sizeof(int));
...
num = 199;
ret = write(fd, &num, sizeof(int));
...
close(fd);
Başa yazmak için lseek ile 0. konuma gitmek gerekir.Şöyle yaparız.
lseek(fd,0,SEEK_SET);
Posix konum değiştirmeden okuyup yazmak için API'ler sağlar. Şöyle yaparız. pread ve pwrite o anki konumu değiştirmeden belirtilen konumdan okuma yazma yapabilir.
#include <unistd.h>
ssize_t pread(int fd, void *buf, size_t count, off_t offset);
ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset);
Şöyle yaparız
ssize_t ret = pread(fd, &num, sizeof(int), 0);
ssize_t ret = pwrite(fd, &num, sizeof(int), 0);

25 Ağustos 2017 Cuma

std::underlying_type

Giriş
Şu satırı dahil ederiz.
#include <type_traits>
std::underlying_type ile bir enum primitive değerine çevirilebilir.

Diğer
std::underlying_type_t
Template kodlarda kullanılır. Şöyle yaparız.
enum class EventOrder
{
  Last = 1'000'000,
  Default = 0,
  Logger = -1024,
  First = -1'000'000
};

constexpr void sum(const EventOrder order, const std::underlying_type_t<EventOrder> d)
{
  ...
}

constexpr EventOrder e = EventOrder::Default;
sum(e, 2);

22 Ağustos 2017 Salı

Gömülü Proje - Finite State Machine

FSM
Bu sınıfları tasarlarken iki tane daha önce yaptığım projeden faydalandım.

İlk projede FSM sadece dışarıdan gelen mesajlarla tetikleniyordu. Her state gelen mesajı işlerken bir sonraki state'i bir enum olarak dönüyordu. FSM bir sonraki state current state değerinden farklı ise bir sonraki state'e geçebiliyordu.

Aşağıdaki örnekte biraz daha farklı bir durum var. State'ler içinde timer'lar çalıştırmak gerekiyordu. Bu yüzden State kendi kendine FSM'yi tetikleyerek başka State'e geç emri verebiliyor. Dolayısıyla
State <-->> FSM
şeklinde çift yönlü bir ilişki var

1. Context Sınıfı
FSM'nin çalışması için gerekli bilgileri saklar.

2. BaseState Sınıfı
Bu sınıf std::enable_shared_from_this sınıfından kalıtır. Böylece Bir state FSM'yi başka state'e geçmek için tetikleyince nesnemiz yaşamaya devam edebilir.

m_pFSMPtr Alanı
FSM ile olan çift yönlü ilişki. Bir State FSM'nin başka bir State'e geçmesini istiyorsa önce
auto pState = shared_from_this ();
ile kendinin silinmemesini sağlar.Daha sonra
m_FSMPtr->gotoXState ();
şeklinde bir metod çağrı yapar.

onEnter metodu
Her state ilk girişte yapacağı şeyleri onEnter () metodu içinde yapar. State'ten çıkarken yapılacak işler onExit() metodunda yapar diye düşünmüştük anca bu metoda ihtiyaç olmadı.

setContext metodu
State yaratılırken context nesnesi atanır.

processMessage metodu
Bu metod bir template. Dışarıdan gelen mesajları kalıtan State nesnelerine geçmek için kullanlır. İçin şöyledir.
template <class T>
void processMessage (const T& msg)
{
  processInternal (msg)
}
Bu template metodu şöyle iç metodlara dağıtım yapar.
virtual processInternal (const A& msg)
{
}
virtual processInternal (const B& msg)
{
}

Bu metodlar boştur. Böylece sadece  mesaj ile ilgilenen State gerekli metodu override eder.

3. FSM Sınıfı
Bu sınfın gotoStateA (); gotoStateB () gibi metodları vardır. Bu metodlar çağrılınca
1. m_CurrentState enum değişkeni güncellenir.
2. Eski State nesnesinin onExit() metodu çağrılır.
3. Yeni State nesnesi yaratılır ve onEnter() metodu çağrılır. onEnter metodu en son çağrılan şey olmalı yoksa bir State hemen bir başka State'e geçişi tetiklerse ortalık karışabilir.

isXState metodu
FSM sınıfı dışarından hangi state içinde olduğunun sorgulanabilmesi için isXState() gibi metodlar sunar.

processMessage metodu
Şöyledir
template <class T>
void processMessage (const T& msg)
{
  m_pCurrentState->processMessage (msg)
}



memchr

Giriş
Belirtilen bellek alanı içindeki bir char arar.

Yanlış kullanım
int değerini arayamayız. Şu kod yanlış.
char* pStart = ...;
char *p1 = (char*)memchr(pStart,0xFF,10);

21 Ağustos 2017 Pazartesi

realloc metodu

Giriş
Şu satırı dahil ederiz.
#include <stdlib.h>
Bu metod standart C metodudur

Metodun imzası şöyle
void *realloc(void *ptr, size_t size);
Açıklaması şöyle
The realloc function deallocates the old object pointed to by ptr and returns a pointer to a new object that has the size specified by size.
realloc fonksiyonu daha önce malloc ya da calloc fonksiyonlarıyla tahsis edilmiş bellek bloğunu büyültmek ya da küçültmek amacıyla kullanılır.
Metodun genellikle yeni bir bellek alanı yaratması ve eski bilgilerin sığdığı kadarını da kopyalaması beklenir.

Kullanım
Şöyle yaparız. Yeni döndürülen pointer'ı saklar ve null olup olmadığını kontrol ederiz. Eğer null değilse eski pointer'a atarız. null ise hata vardır
tempPtr = realloc (oldPtr, newSize);

if (tempPtr)  //allocation successful, oldPtr is `free()`-d can be reused now
{
  oldPtr = tempPtr;
} // and continue using `oldPtr`
else
{
  // some error handling
  // can still make use of `oldPtr`
}
Yanlış kullanım şöyledir. realloc başarısız olursa null döner ve eski pointer'ı kaybederiz.
pointerVar = realloc (pointerVar , newsize);  // use the same pointer variable
realloc başarısız olursa
realloc çağrısı başarısız olursa da eski bellek alanı halen geçerlidir.
void *buffer = realloc(oldbuffer, sizeof(oldbuffer)*2);
if ( !buffer )
  // take some action.... the old buffer is still valid
else
  ...
realloc başarılı olursa
Eski bellek alanı artık yok olmuştur. Kullanmamak gerekir.
double *a = (double *) malloc(sizeof(double) * 20);...
double *b = (double *) realloc(a, 30);
a[20] = 11; //Error!a[21] = 12; //Error!

Belleği Küçültmek
Eğer metod belleği küçültmek için kullanılıyorsa aynı bellek alanını da döndürebilir. Şöyle  yaparız
// Intialize big array
int * a = (int *)malloc(10*sizeof(int));
assert(a);
// Fill it with squares
for (int i = 0; i < 10; ++i)
  a[i] = i*i;
// Expected to print 64
printf("%d\n", a[8]);
// Shrink the big array
int * b = (int *)realloc(a, 5*sizeof(int));
assert(b);
// Expected to cause SEGFAULT
printf("%d\n", b[8]);
realloc ilk parametrenin ne kadar büyüklükte yer tuttuğunu nereden biliyor?
realloc aynen free() metodunda olduğu gibi, heap veri yapılarına erişebildiği için malloc ile ayrılmış alanın kaç byte tuttuğunu da biliyor. Metodun imzası void * alsa bile sorun olmuyor.