Feijoada

Sempre gostei de comer feijoadas, e de um tempo para cá passei a curtir fazer uma. Quando fui fazer a minha primeira, a minha avó me passou umas 6 receitas diferentes, sendo uma delas a Feijoada da Nina Horta. A Feijoada a seguir é uma variação da feijoada dela, para menos pessoas, incorporando algumas coisas das outras 5 receitas. O resultado ficou ótimo!

A receita rende para pelo menos 10 pessoas, dobrando as quantidades dá para servir umas 25. O processo é simples, porém leva bastante tempo, reserve uma manhã inteira (começando às 8h) para fazer!

Receita

  • 1 kg de feijão
  • 1/2kg de carne seca com pouca gordura
  • 1/2kg de lombo de porco salgado
  • 2 paios
  • 2 linguiças de porco
  • 2 linguiçinhas forte
  • 250g de costela de porco salgada
  • 50g de toucinho (bacon)
  • 1 rabo de porco
  • 1 dentes de alho socado
  • 2 colheres de sopa de cebola ralada
  • 1 folha de louro
  • 3 colheres de sopa de azeite de oliva
  • sal e pimenta a gosto

Cozinhe as carnes salgadas (porco), dando primeiramente uma ligeira fervura de 15min e jogue toda a água fora. A seguir, coloque bastante água e deixe cozinhar as carnes. Quando amolecerem, reserve a água numa vasilha, este é o pré-caldo da feijoada.

Cozinhe separadamente a carne-seca. Dê a primeira fervura e jogue fora a água. Depois cozinhe com nova água e reserve o caldo. Se faltar água na feijoada, utilize esta água. A carne seca tem que ficar bem mole.

Quando as carnes estiverem cozidas, cozinha-se o feijão na água de porco. Quando o feijão estiver cozido faça o tempeiro: alho, cebola, gordura do torresmo e uma folha de louro. Depois de frito o tempero, pegue uma escumadeira para tirar o feijão sem caldo. Frite-o e esmague um pouco. Volte para o caldo. Tudo cozido, junte as carnes salgadas e secas. Deixe-o em fogo baixo por uma hora pelo menos. Não ficar mexendo.

O paio e a linguiça devem ser cozidos separadamente e só juntados no momento em que forem colocadas as carnes. A água deve ser deixada de lado para ser colocada no caldeirão da feijoada se estiver muito grossa. Só utilize a água da carne seca de precisar.

Servir com couve à mineira e laranja em gomos, pode-se servir com uma farofa ou somente com farinha de mandioca.

Dicas

  • Feijão: não colocar de molho
  • Carnes salgadas: lavar muito bem, deixar de molho por pelo menos 4h. Cortar em pedaçoas nunca inferiores a 5cm.
  • Carne seca: lavar muito bem, deixar de molho por pelo menos 4h. Cortar em pedaçoas nunca inferiores a 5cm.
  • Paio e Linguiça: apenas lave, não precisa ficar de molho. Não cortar em pedaços muito pequenos.
  • Pé e rabo de porco: dividi-lo ao meio, deixar de molho por 4h.

Fotos

Assando as carnes

Cozinhando o feijão na água do porco

Ingredientes para temperar a feijoada

Tempero do feijão, ainda sem o feijão incorporado

Cozinhando as linguiças

Linguiças prontas, esperando para serem incorporadas ao feijão

Couve na manteiga

Quase pronto! Arroz, couve e o feijão!

Laranjas!

Prato pronto! Bom apetite!

Nutella (Cup)cake

Sábado chuvoso, nada para fazer, então nada melhor do que ir para a cozinha e fazer alguma delícia! Queríamos testar a receita de cupcake de Nutella deste blog, compramos todos os ingredientes, mas acabamos esquecendo das forminhas. Então mudamos um pouco a receita e fizemos um bolo de Nutella!

Bolo de Nutella


Bolo de Nutella

Segue abaixo a receita. Ah, na receita original eles usam self-rising flour, que não tínhamos, então adicionamos fermento à receita original.

Bolo de Nutella

  • 1 xícara de farinha
  • 1 1/4 colher de sopa de fermento
  • 1/4 colher de sopa de sal
  • 4 colheres de sopa de manteiga sem sal
  • 1 colher de chá de extrato de baunilha
  • 1/2 xícara de açucar
  • 350 gramas de Nutella
  • 4 ovos
  • 4 colheres de sopa de leite

Preaqueça o forno em 180ºC.

Misture a farinha, o fermento e o sal e reserve.

Com a batedeira, em outro recipiente, bata a manteiga até ficar cremosa. Adicione o extrato de baunilha e bata até incorporar. Adicione o açucar e bata bem. Bata a Nutella, cuidando para raspar as laterais do pote para a massa ficar homogênea. Adicione um ovo por vez e bata até ficar cremoso. Bata metade da mistura de farinha e em seguida adicione o leite. Adicione o restante da farinha e bata ligeiramente.

Coloque a massa em uma forma de uns 25cm de diâmetro, untada com manteiga e farinha. Asse por certa de 30 minutos. Logo que retirar do forno, coloque pedaços de chocolate meio-amargo por cima e espere derreter para logo em seguida espalhar sobre o bolo.

Bom apetite!

Ponteiros!

Outro dia no trabalho resolvemos brincar com ponteiros, não que o código que resultou da brincadeira seja algo bom, mas foi divertido. Basicamente tinhamos uma função que traduzia uma string interna passada para a string que utilizariamos em tela, software foi crescendo e mais traduções eram necessárias para a mesma string.

Então aos exemplos, do que tinhamos, da brincadeira que fizemos com os ponteiros e o que seria a melhor solução para o código. Antes algumas definições, a estrutura que contém as strings é a seguinte, basicamente um mapa 1 pra n:

enum {
	KERNEL = 1,
	WEB,
	CLI
};

struct test {
	int idx;
	char *kernel;
	char *web;
	char *cli;
};

struct test example[] = {
	{.idx = 0, .kernel = "eth0", .web = "Ethernet 0", .cli = "ethernet0" },
	{.idx = 1, .kernel = "eth1", .web = "Ethernet 1", .cli = "ethernet1" },
	{.idx = 2, .kernel = "eth2", .web = "Ethernet 2", .cli = "ethernet2" },
	{.idx = 3, .kernel = NULL, .web = NULL, .cli = NULL}
};

A versão original da função que procurava pela string correta era algo parecido com:

char *get_str_for_v1(const char *eth, enum str_type type)
{
	char *rtn = NULL;
	int i;
	
	switch (type) {
	case KERNEL:
		for (i = 0; i < sizeof (example); i++) {
			if (strcmp(eth, example&#91;i&#93;.kernel) == 0) {
				rtn = example&#91;i&#93;.kernel;
				break;
			}
		}
		break;
	case WEB:
		for (i = 0; i < sizeof (example); i++) {
			if (strcmp(eth, example&#91;i&#93;.kernel) == 0) {
				rtn = example&#91;i&#93;.web;
				break;
			}
		}
		break;
	case CLI:
		for (i = 0; i < sizeof (example); i++) {
			if (strcmp(eth, example&#91;i&#93;.kernel) == 0) {
				rtn = example&#91;i&#93;.cli;
				break;
			}
		}
		break;
	}
	
	return rtn;
}
&#91;/sourcecode&#93;

O que é obviamente muito feio! Com excesso de código repetido, péssimo de ler e dar manutenção. Vendo esse código propus o desafio de escrever a mesma função com um <code>for</code> só. Meu colega de trabalho resolveu usar ponteiros pra resolver isso, calculando o offset de cada um dos membros da estrutura e recuperando o ponteiro da string a partir do offset. Claro, isso parece muito simples de se fazer... mas na hora de escrever o código, demorou bem mais do que imaginavamos, mas foi bastante divertido entender como funcionam os casts em C.

O resultado foi o seguinte código, as macros eu adicionei para facilitar a leitura do código, mais sobre elas daqui um pouco...

#define member_offset(type, member) \
			((unsigned long)(&((type *)0)->member))
#define get_member_by_offset(ptr, type, offset) \
			((type *)((void *)(ptr) + offset))

char *get_str_for_pointer_fun(const char *eth, enum str_type type)
{
	int i;
	unsigned long offset;
	
	switch(type) {
	case KERNEL:
		offset = member_offset(struct test, kernel);
		break;
	case WEB:
		offset = member_offset(struct test, web);
		break;
	case CLI:
		offset = member_offset(struct test, cli);
		break;
	}
	
	for (i = 0; i < sizeof (example); i++) {
		if (strcmp(eth, example&#91;i&#93;.kernel) == 0) {
			return *get_member_by_offset(&example&#91;i&#93;, char *, offset);
		}
	}
	
	return NULL;
}
&#91;/sourcecode&#93;

Com certeza não é a melhor implementação possível, talvez seja a mais complexa de se entender, especialmente se não for utilizada uma macro para esconder a implementação. Mas é uma implementação divertida, ou pelo menos foi divertido tentar achar a combinação correta de ponteiros para gerá-la.

E finalmente o código que eu julgo o mais aceitável:
&#91;sourcecode lang="c"&#93;
char *get_str_for_v2(const char *eth, enum str_type type)
{
	int i;

	for (i = 0; i < sizeof (example); i++) {
		if (strcmp(eth, example&#91;i&#93;.kernel) == 0) {
			switch (type) {
			case KERNEL:
				return example&#91;i&#93;.kernel;
			case WEB:
				return example&#91;i&#93;.web;
			case CLI:
				return example&#91;i&#93;.cli;
			}
		}
	}
	
	return NULL;
}
&#91;/sourcecode&#93;

<h2>Macros</h2>
Bom, disse que ia explicar o funcionamento das duas macros utilizadas, então recapitulando elas:

#define member_offset(type, member) \
			((unsigned long)(&((type *)0)->member))

#define get_member_by_offset(ptr, type, offset) \
			((type *)((void *)(ptr) + offset))

A macro member_offset calcula o offset de um membro qualquer de um estrutura. Para fazer isso, ela dá um cast para um ponteiro do tipo da estrutura requerida ao valor 0. O que parece estranho a princípio, mas faz todo o sentido! Do ponteiro para zero até o membro requerido da estrutura existem os n bytes que representam o offset em memória do início da estrutura até o membro.

Munido do valor do offset, podemos então recuperar a estrutura que se encontra naquele offset utilizando a macro get_member_by_offset. Obviamente é necessário sabermos qual o tipo de dado que se encontra naquele offset! Então a partir do ponteiro (endereço) da estrura que queremos acessar podemos somar o offset do membro requerido. Mas só somar o offset não resolve, é necessário dar os casts apropriados.

Como queremos um que o endereço calculado (ponteiro original + offset) seja um ponteiro, é necessário indicar isto ao compilador, colocando um * no cast do cálculo. Além disso, é necessário indicar que tipo de ponteiro estamos recuperando naquele endereço, portanto o cast vira (type *). No exemplo, o cast é (char **) indicando corretamente que naquele endereço encontra-se uma string.

Esse mesmo método de recuperar um membro de uma estrutura é utilizado na implementação de listas no kernel do linux. A macro definida é um pouco diferente, uma vez que ela realiza estas duas operações de uma só vez, mas a explicação do seu funcionamento é a mesma! Segue a sua implementação:

#define list_entry(ptr, type, member) \
	((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))

Basicamente o que este código faz é recuperar o ponteiro para a estrutura a partir de um membro qualquer dela. No caso das listas, o membro utilizado para recuperar a estrutura original é o struct list_head. Com isso, é possível utilizar diversos struct list_head numa mesma estrutura, adicionando ou não a estrutura alocada a uma das listas.