Convertendo string multibyte UTF-8 para wchar_t e vice-versa com iconv

Posted in Outros on 25 \25\-03:00 abril \25\-03:00 2010 by enygmata

Nos ultimos dias eu estive trabalhando em uma forma de suportar caracteres utf-8 no bitsheet. Ontem eu resolvi usar a iconv para fazer este trabalho de conversão de wchar_t para UTF-8 e vice-versa. Resolvi postar aqui a solução que usei.

<Teoria chata>

O tipo wchar_t foi introduzido para que houvesse suporte a wide characters, mas a codificação de uma array de wchar_t (ou wide string) é dependente da locale do sistema (LC_TYPE/LC_ALL/LC_LANG) e do compilador. O padrão C não especifica um tamanho exato para o tipo wchar_t, largando esta tarefa aos compiladores, então o valor deste tipo geralmente varia entre 8 e 32 bits. No caso da implementação do wchar_t do gcc, o tamanho é 32 bits, portanto o mesmo comporta caracteres que consumam até 4bytes (como alguns caracteres Unicode).

UTF-8 (8-bit Unicode Transformation Format) é uma das primeiras codificações que implementam suporte a Unicode characters, ele foi criado por Ken Thompson (o cara que criou a linguagem B e que ja recebeu até premio turing junto com o Denis Ritchie) e Rob Pike (junto com Ken Thompson criou o sistema operacional Plan 9) num restaurante de New Jersey (pode acreditar!) em setembro de 1992. Os caras resolveram fazer isso porque odiaram o suporte a caracteres 16bit do UTF original e do ISO 10646. O formato foi feito para ser compatível com o padrão ASCII e utiliza um numero variado de bytes para representar os caracteres (caracteres ASCII usam 1 caracteres, e letras acentuadas geralmente utilizam 2 caracteres).

Nem todas as implementações do tipo wchar_t comportam todas as possibilidades da codificação UTF-8, o wchar_t do compilador c++ da microsoft é de 16bits e portanto não comporta os casos em que os caracteres utf-8 são maiores que 16bits (É UMA CILADA BINO!). Mas aí existem umas manhas pra resolver este problema.

</Teoria chata>

A biblioteca iconv é uma biblioteca comum em sistemas UNIX, ela faz a conversão entre diferentes codificações de caracteres inclusive de uma codificação como o utf-8 para a codificação interna do wchar_t. Chega de enrolação, la vai o code.

(a linguagem é C++)
// lembre se desses headers:
#include <cwchar>
#include <iconv.h>
#include <langinfo.h>

// UTF-8 multibyte string para wide char string
wchar_t * utf8mbstowcs (const char *str) {
    iconv_t cd;
    size_t inleft, outleft;
    wchar_t *wbuf;

    wbuf = new wchar_t[strlen(str)+1];
    memset(wbuf, 0, strlen(str)+1);

    cd = iconv_open("WCHAR_T", "UTF8");
    iconv(cd, NULL, NULL, NULL, NULL);

    inleft = strlen(str) + 1;
    outleft = strlen(str) * sizeof(wchar_t)+1;

    char *in = (char*)str;
    char *out = reinterpret_cast<char *>(wbuf);

    if (iconv(cd, &in, &inleft, &out, &outleft) < 0) {
        delete wbuf;
        wbuf = NULL;
    }

    iconv_close(cd);

    return wbuf;
}


// wide char string para UTF-8 multibyte string
char *wcstoutf8mbs (const wchar_t *wstr) {
    iconv_t cd;
    size_t inleft, outleft;
    char *buf;
    char str[wcstombs(NULL, wstr, 0)+1];

    inleft = wcstombs(NULL, wstr, 0)+1;
    outleft = (inleft -1)* sizeof(wchar_t)+1;

    memset(str, 0, inleft);
    // melhor converter, vai que a endianess fez alguma besteira ;)
    wcstombs(str, wstr, inleft);

    buf = new char[outleft];
    memset(buf, 0, outleft);

    cd = iconv_open("UTF8", nl_langinfo(CODESET));
    iconv(cd, NULL, NULL, NULL, NULL);

    char *in = reinterpret_cast<char *>((wchar_t*)str);
    char *out = (char*) buf;

    if (iconv(cd, &in, &inleft, &out, &outleft) < 0) {
        delete buf;
        buf = NULL;
    }

    iconv_close(cd);

    return buf;
}

Referencias:
http://www.cl.cam.ac.uk/~mgk25/ucs/utf-8-history.txt
http://opengroup.org/onlinepubs/007908799/xsh/wchar.h.html
http://icu-project.org/docs/papers/unicode_wchar_t.html

Desenvolvimento orientado a feriados

Posted in Outros on 25 \25\-03:00 abril \25\-03:00 2010 by enygmata

É engraçado perceber que nesse período de feriados do inicio e fim do ano, assim como nas férias do meio do ano, a minha produtividade aumenta uns 200% em relação ao período em que tenho aulas ou trabalho. Neste recesso de fim de ano programei bastante, iniciei um projeto, ajudei um pouco num projeto de um colega de IRC e aprendi bastante também.

O que acontece é que, na época em que trabalho ou estudo, programar ou fazer algo no computador que não seja diversão me faz sentir como se estivesse trabalhando. E olha que eu nem trabalho com programação!

Estes ultimos dias do meu recesso de fim de ano foram mais produtivos que qualquer outro momento no ano de 2009. Eu realmente senti vontade de programar e me divertia com isso, MUITO. Foi como na época em que eu fazia o EMI de informática: eu não precisava trabalhar então estudava e programava enquanto meus colegas passavam horas viciando naquele jogo-super-legal-da-época ou perdiam tempo dando refresh na página de recados do Orkut.

Agora só o que resta é esperar pelo próximo feriado prolongado (carnaval?) pra programar um pouco mais.

Instalando o php-gtk2 (svn trunk) no Linux

Posted in Outros on 25 \25\-03:00 abril \25\-03:00 2010 by enygmata

Com a mudança do repositório do php para svn e com o lançamento da extensão Cairo pra php, meu tutorial anterior sobre como instalar o php-gtk se tornou obsoleto, mas vou deixa-lo no blog caso alguém ainda precise dele. Aqui vai a receita nova!

Ingredientes

  • Uma porção grande de Linux
  • Uma xícara de PHP versão 5.2 ou superior (estou usando 5.3.0)
  • Uma colher de Gtk versão 2.8 ou superior (recomendo 2.12 no minimo)
  • Uma porção de GCC, Make, Autoconf e Automake
  • Uma pitada de Svn

Modo de preparo

Primeiro precisamos baixar o código fonte do php-gtk e da extensão cairo, então dirija-se ao diretório mais próximo e adicione o svn aos poucos (pode demorar dependendo da sua conexão):

$ svn co http://svn.php.net/repository/gtk/php-gtk/trunk php-gtk
$ svn co http://svn.php.net/repository/pecl/cairo/trunk cairo

Entre no diretório da extensão cairo e compile bem.

$ cd cairo
$ phpize
$ ./configure && make
$ sudo make install

O cairo está pronto, agora temos que preparar o php-gtk.

EDIT: A partir da revisão 289268 não é mais necessario adicionar manualmente a flag HAVE_CAIRO à CFLAGS.

$ cd ..
$ cd php-gtk
$ ./buildconf
$ ./configure
$ sudo make install

Yum! Isto parece delicioso, vamos provar? Vá ao diretório do php-gtk (se ainda não estiver) e execute o seguinte comando:

$ php -d extension=cairo.so -d extension=php_gtk2.so demos/stock-browser.php

Uma janela listando os items do GtkStock deve aparecer.

Free Image Hosting at www.ImageShack.us

Então é isso, espero que a receita tenha dado certo. Qualquer coisa é só colocar um comentário. Tchau! :)

OBS: Não testei mas é provável que o tutorial funcione em outros ambientes Unix-like.

isset e checagem por indices de arrays

Posted in Outros on 25 \25\-03:00 abril \25\-03:00 2010 by enygmata

Muita gente se depara com erros de lógica pelo mal uso da função isset(). O que ocorre é que geralmente queremos que uma ação seja feita caso a variável não esteja definida, porém se definirmos a variável como null a função isset irá retornar false como se a variável não tivesse sido definida.

O mesmo ocorre com a checagem por índices de arrays, caso o valor para o qual o índice aponta estiver definido como null a função isset irá retornar false. A solução para este problema é utilizar a função array_key_exists() caso o valor null numa determinada posição de array seja importante para sua aplicação. O código abaixo demonstra o comportamento das duas funções.

<?php
$a = array(
    'key' => null
);

if (!isset($a['key'])) {
    print "isset: o indice 'key' não existe em \$a!\n";
}

if (!array_key_exists('key', $a)) {
    print "array_key_exists: o indice 'key' não existe em \$a!\n";
}

Saída:

isset: o indice 'key' não existe em $a!

Integrando Doxygen ao GNU Build System

Posted in Linux, Outros, Programação, Tutorial with tags on 25 \25\-03:00 abril \25\-03:00 2010 by enygmata

Depois de procurar muito e só achar coisas que não funcionavam, eu resolvi meter a mão na massa! Foi até divertido!

Como todos sabem, ou deveriam saber, o GNU Build System – autohell para os mais íntimos – é o sistema de compilação mais famoso no mundo UNIX, ele tem suporte padrão a algumas linguagens (como C, C++ e Fortran), compilação de documentação na forma de man pages e LaTeX, e até uma suite de testes – essa eu não sei nem pra onde vai.

Até aí tudo bem com o autohell, o problema é que eu não queria gerar man pages e muito menos documentos TeX: eu queria HTML pra ficar bonitinho que nem aquelas documentações de gente que sabe programar. Foi aí que encontrei o Doxygen, ele gera HTML e também tem suporte a uma pancada de formatos. O que eu queria mesmo era poder gerar a documentação usando o próprio autohell, e aí eu saí procurando e acabei achando algumas soluções como uma que está no arquivo de macros do autoconf. Só que a unica coisa que elas estavam fazendo era procurar o doxygen e outras ferramentas que ele precisa no sistema. O aminclude de algumas soluções que encontrei, estava muito mal escrito e o make relatava problemas o tempo todo.

Bom, vamos deixar de enrolação e por logo a mão na massa. Primeiro, no configure.ac, você tem que adicionar o código a seguir:


# Checa se o executavel doxygen existe no $PATH, se existir $DOXYGEN
# recebe doxygen
AC_CHECK_PROG([DOXYGEN], [doxygen], [doxygen], [])

# Agora a gente faz a checagem pra ver se o doxygen foi detectado
# mesmo ou não se ele tiver sido detectado, temos que adicionar alguns
# alvos para o make
AC_MSG_CHECKING([wheter to add documentation targets])
if test ! -z "$DOXYGEN"; then
AC_MSG_RESULT([yes])
else
AC_MSG_RESULT([no])
fi

# Se o doxygen foi detectado DOXY_DOC vai ser true.
AM_CONDITIONAL([DOXY_DOC],[test ! -z "$DOXYGEN"])
# A variavel DOXYGEN é só para o make encontrar o executavel do dito
# cujo.
AC_SUBST([DOXYGEN], [$DOXYGEN])


AC_CONFIG_FILES([Makefile doc/Doxyfile doc/Makefile outro_diretorio/Makefile])

No Makefile.am da raiz do seu projeto vc só precisa colocar o seguinte:


# No projeto em que estou trabalhando o diretorio da documentação é o
# diretorio doc, por isso DOC_DIR = doc quando o doxygen é
# detectado
DOC_DIR =
if DOXY_DOC
DOC_DIR = doc
endif
SUBDIRS = $(DOC_DIR) outro_diretorio

# Aqui a gente adiciona o alvo para o make
doc:
cd $(top_srcdir)/doc && $(MAKE) && cd ..

# E aqui a gente diz ao make que o alvo doc não pode ser tratado como
# arquivo.
.PHONY: doc

O diretorio da documentação também precisa de um Makefile.am, é esse o arquivo responsável por executar a compilação da documentação.


# Isso aqui faz o make compilar quando ele for executar o make all.
all: html-local


# Instruções para compilação da documentação
html-local:
if DOXY_DOC
rm -rf html/
$(DOXYGEN)
else
@echo Doxygen not detected, skipping documentation build.
endif

# Arquivos a serem copiados
html_DATA = html/*

# Truque para o make não reclamar quando não achar os alvos com nomes
# dos arquivos gerados pelo Doxygen
$(html_DATA):

# Instruções para instalação da documentação
install-html-local:
@$(NORMAL_INSTALL)
test -z "$(htmldir)" || $(MKDIR_P) "$(DESTDIR)$(htmldir)"
@list='$(html_DATA)'; \
for p in $$list; do \
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
f=$(am__strip_dir) \
echo " $(INSTALL_DATA) '$$d$$p' '$(DESTDIR)$(htmldir)/$$f'"; \
$(INSTALL_DATA) "$$d$$p" "$(DESTDIR)$(htmldir)/$$f"; \
done

# Instruções para limpeza de arquivos.
clean-local:
-rm -rf html/

# Variáveis com os nomes de arquivos a ser excluidos
CLEANFILES = Doxyfile Makefile.in
MAINTAINERCLEANFILES = $(CLEANFILES)

Para finalizar, você precisa ter um arquivo Doxyfile.in no diretório da documentação. Ahn? Por que você precisa? Pelo simples fato de que é melhor usar paths absolutas para determinar o caminho do diretorio onde está o source e do de saida da documentação. Assim evitamos problemas caso desejemos dar um make all dentro do diretorio da documentação. No Doxyfile você precisa mudar o valor de algumas variaveis como no exemplo abaixo:


PROJECT_NAME = "@PACKAGE_NAME@"
PROJECT_NUMBER = "@PACKAGE_VERSION@"
OUTPUT_DIRECTORY = @abs_top_srcdir@/doc
STRIP_FROM_PATH = @abs_top_srcdir@

Uma vantagem de se fazer isso é não precisar ficar atualizando o nome do projeto ou a versão, toda vez que você resolver mudar.

Espero ter ajudado, qualquer coisa comenta aí que eu tento ajudar.

Mudança para outro host

Posted in Outros on 2 \02\-03:00 maio \02\-03:00 2009 by enygmata

Novo endereço: http://enygmata.c2zlabs.com

Conheça o Awesome

Posted in Outros with tags , , , on 16 \16\-03:00 abril \16\-03:00 2009 by enygmata

Oi pessoal, hoje eu vim aqui mostrar um pouco desse window manager que estou usando a algum tempo (2 dias haha =P). O Awesome é por padrão um tiling window manager, ou seja, ele organiza sua área de trabalho (estou falando de janelas e coisas do tipo, não aquele lugar onde você põe seus ícones super coloridos) em uma espécie de ladrilho para aumentar sua produtividade e otimizar o uso da tela. Antes de tudo, se você se sente incomodado em ver alguém que na maior parte do tempo utiliza programas que rodam em terminal ou se você é viciado em firulas estilo screenlets ou gdesklets, este window manager não é pra você a menos que você esteja realmente procurando se elevar intelectualmente. Brincadeira =P.

Antes do Awesome eu utilizei o ion3 por uma semana, o ion3 é muito bom por sinal, porém ele interfere nos atalhos dos programas em execução e um dos motivos é utilizar por padrão a tecla Alt em quase todos os seus keybindings. O que gostei no awesome é que ele não cria barras de títulos para cada janela ou frame que você possui na tela: está tudo na statusbar do Awesome, o que faz a economia de espaço ser maior ainda. Esta tal statusbar contém as tags, uma tasklist da tag atual, o relógio e um botão alternador de layout. As tags são simplesmente uma forma de organizar de forma lógica suas janelas, cada tag tem um layout separado. Os layouts são a forma na qual as janelas ativas vão ser organizadas, elas podem por exemplo flutuar ou formar ‘tiles’. O Awesome wm também suporta menus, para criar basta editar seu rc.lua, os menus são acessiveis através do icone do Awesome que fica na statusbar.

O Awesome é altamente customizável e da mesma forma que o ion3, o Awesome wm pode ser customizado utilizando scripts lua. Você pode criar widgets para incrementar sua statusbar ou scripts que automatizem algo.

Screenshot do Awesome wm

Screenshot do Awesome wm 3.0

Os atalhos do Awesome são geralmentes ligados à tecla Mod4 que geralmente representa a tecla Windows ou Apple do seu teclado. Exemplos:

  • Mod4 + Espaço: Mudar o layout da tag atual.
  • Mod4 + J ou Mod4 + K: Alternar entre janelas/frames da tag atual.
  • Mod4 + H ou Mod4 + L ou Mod4 + Botão direito: Redimensionar janela.
  • Mod4 + n: Onde n é um numero de 1 a 9, mudar para a n-ésima tag.
  • Mod4 + Setas Esquerda ou Seta Direita:  Mudar para a tag anterior ou próxima.
  • Mod4 + Botão esquerdo: Mover janela

Caso você queira mover uma janela de uma tag para outra você pode ir para a janela desejada e pressionar Mod4+Botão esquerdo na tag que você quer. Para que uma janela esteja presente em mais de uma tag, você pode fazer o mesmo porém clicando na tag desejada usando Mod4 + Botão direito. Estes e outros atalhos você encontra na manpage do awesome.

Certo, certo, então quer dizer que como eu você também gosta de por umas micro frescuras só pra deixar sua tela mais bonitinha? Fácil. O Awesome wm também suporta transparência: você pode utilizar o xcompmgr para ativar compositing na sua configuração do Awesome. Olha como ficou a minha:

Screenshot da minha configuração do Awesome

Screenshot da minha configuração do Awesome

Então.. é isso aí galera, espero que vocês tenham se interessado por este window manager e que pelo menos o teste hehe. =)

Até a proxima.

Referencias:

http://wiki.archlinux.org/index.php/Awesome3

http://awesome.naquadah.org/wiki/

Instalando o PHP-GTK2 mais recente no Linux

Posted in Programação, Tutorial on 21 \21\-03:00 fevereiro \21\-03:00 2009 by enygmata

Olá, hoje estou aqui para ensinar como instalar o PHP-GTK do CVS no Linux. Resolvi fazer este tutorial porque vejo que muita gente está tendo problemas com isso, e também por que eu quero te-lo anotado em algum lugar hehehe. Bem, mãos a obra!.

Antes de começarmos, certifique-se que você possui o php compilado e instalado na sua maquina (isso mesmo, você vai ter que pegar o source e compilar, presumo que você ja saiba fazer isso). Veja também se você possui as seguintes bibliotecas e seus cabeçalhos:

  • Gtk versão >= 2.14
  • LibCairo versão >= 1.8
  • Glib versão >= 2.14

Versões anteriores funcionam, porém estas são as necessárias para que você tenha suporte completo (ou quase) das funções Gtk.

Agora devemos baixar o source do php-gtk que está no repositorio do php, para isso vamos primeiro logar como ‘cvsread’, a senha é ‘phpfi’:

$ cvs -d :pserver:cvsread@cvs.php.net:/repository login

Agora podemos baixar o source do php e do php-gtk do repositório rodando este comando:

$ cvs -d :pserver:cvsread@cvs.php.net:/repository co php-gtk

O php-gtk do cvs requer a extensão php-cairo se você está compilando num sistema que possui gtk superior a 2.8, então vamos baixá-lo também!

$ svn co svn://whisky.macvicar.net/php-cairo

Agora compilamos o php-cairo com os seguintes comandos:


$ cd php-cairo
$ phpize
$ ./configure && make
$ sudo make install

OBS: caso ocorra um problema quado você rodar o ./configure, antes de rodá-lo execute o autoconf mais recente que você possuir em sua máquina (no ubuntu 8.10 é o programa autoconf2.50) e depois rode


$ ./configure && make
$ sudo make install.

Finalmente, a hora está chegando… vamos compilar o php-gtk!! Vá para o diretório do php-gtk e execute os seguintes comandos:


$ ./buildconf
$ CFLAGS="-DHAVE_CAIRO" ./configure
$ make
$ sudo make install

TADAA! Teu php-gtk deve estar funcionando uma hora dessas :) Huh? Quer testar??

Rode a seguinte linha de comando:

$ php -d extension=cairo.so -d extension=php_gtk2.so -r '$w=new GtkWindow();$l=new GtkLabel("Hello");$w->add($l);$w->show_all();$w->connect_simple("destroy", array("gtk", "main_quit"));$w->set_size_request(300,300); gtk::main();'

Po-por hoje é só pe-pessoal!

Renomear arquivos MP3 de acordo com as tags ID3 usando o php

Posted in Programação with tags , on 14 \14\-03:00 fevereiro \14\-03:00 2009 by enygmata

Ontem baixei o Songbird, é pesadinho mas gostei mesmo sabendo que eu vou acabar voltando para o MPD. Mas aí eu vi um problema  com as músicas: em alguns casos o Songbird não encontrava informações das músicas. Foi aí que decidi ficar até altas horas editando as tags das minhas músicas para que o Songbird podesse me apresenta-las de forma melhor.

Hoje de manhã, quando fui colocar alguns mp3’s que tinha baixado nas suas devidas pastas percebi a bagunça que havia, alguns arquivos estavam nomeados assim: 123.mp3 ou get_song_nightwish_3.Mp3 e haviam outras variações. Foi aí que decidi fazer um pequeno script php para renomear o nome dos arquivos da forma que quero: Artista – Titulo.mp3. Dei uma pesquisada e encontrei as funções que precisava para ler as tags ID3.

O script não sobrescreve o arquivo atual, ele cria uma pasta chamada mp3_output que contém os arquivos renomeados, os arquivos que não possuem tags ID3 não são renomeados, somente copiados para mp3_output. O script também não converte mp3s recursivamente.

Para usá-lo basta ir para  a pasta que contém os arquivos que você deseja renomear e chamar o script. Ah, e você tem que ter compilado o php com a extensão ID3.

Tchau! ;)

Download do script

Olá

Posted in Outros on 11 \11\-03:00 dezembro \11\-03:00 2008 by enygmata

Olá, esta é a minha tentativa Nº 4010 (lê-se “quarenteidez”)  de criar (e manter) um blog. Prentendo falar principalmente de coisas da área de informática.

Como eu sou meio “arfanalbeto” concerteza com certeza irão aparecer erros absurdos aqui, “cokecoisa” avisa aí.