Piero V.

C++ Logger

Ultimamente non stavo più andando avanti con progetti di programmazione, ma, riprendendo, ho sentito la necessità di fare un buon sistema di logging basato sugli stream di C++.

In passato avevo già affrontato l’argomento, ma questa è stata una sfida per vedere se riuscivo a fare tutto da capo e da solo. Ce l’ho fatta, così ho deciso di pubblicare qui i risultati.

Come requisiti ho tenuto in mente la versatilità e la sicurezza per l’uso con i thread.

La versatilità l’ho ottenuta mediante la divisione per modulo (per esempio networking, audio etc…) e livello (errore, informazione…). A coordinare tutto c’è il Log Manager, una classe che coordina i vari log. È un singleton (ottenuto tramite la mia classe allegata), e ritorna degli stream, uno per ogni coppia modulo-livello (che insieme fanno il LogId), assicurandosi che queste istanze siano uniche. Inoltre dispone di una funzione per mandare direttamente in output una stringa, dove in più si può specificare anche il file e la linea, magari usando le macro __FILE__ e __LINE__.

Ho pensato come vari output lo standard output e error, in più un file e un’eventuale consolle interna al programma, configurabili per ogni log, con una questa priorità: LogId > Modulo > Livello > Configurazione globale.

Come dipendenze ha gli smart pointer e i mutex/recursive mutex di Boost. Comunque se preferite e potete, C++11 ha integrato tutti questi componenti nella libreria standard, quindi potete usarli da là, ma sinceramente non ho provato a farlo.

Mancano, volendo, una funzione per impostare la configurazione “grezza” tramite gli enum e l’operatore OR e un controllo nei metodi overflow, xputn e sync della classe LogStreamBuf che ritornino subito se l’output è disabilitato, senza fare movimenti di memoria.

Ho fatto un paio di test anche con dei thread e non ho avuto problemi.

Non mi metto a scrivere tutte le funzioni perché mi pare siano già abbastanza spiegate nell’header 😉 .

Rilascio il materiale sotto il pubblico dominio.

Download: cpp_logger.tar.gz

PHP: non ci sono più abituato

In questi giorni nel poco tempo libero sto cercando di sistemare i problemi del comment center e di aggiungere qualche nuova funzionalità.

Nell’ultimo anno ho scritto sempre meno software in PHP e si è visto anche dagli aggiornamenti per i miei plugin di Flatpress. Mi sono invece dedicato molto al game programming in C++ più qualche lavoretto in C.

Ciò ha fatto molto bene alle mie facoltà da programmatore (o se non posso essere definito così almeno lasciatemi la libertà di chiamarmi almeno «scrittore di codice» 😌 ).

C e C++ sono linguaggi compilati e fino a poco più di un anno fa ero stato a contatto prettamente con linguaggi interpretati o linguaggi di scripting.

La cosa in cui avevo avuto più problemi era la gestione della memoria, infatti negli script è gestita automaticamente. C++ mi ha insegnato a pensare se veramente serve una variabile oppure no, mi ha insegnato la tipizzazione e l’uso della memoria dinamica. Adesso le apprezzo molto, nonostante i problemi iniziali.

Tuttavia non è stata questa la cosa più utile. Ciò che più si impara con un linguaggio come C++ è che non ci si può permettere di fare un codice disordinato. … [Leggi il resto]

OgreStream

Update 13 ottobre 2012: vedere a fine articolo.

Basandomi sul lavoro di Edd, ho scritto un bridge per leggere i file degli archivi di Ogre con gli stream di C++.

Ciò comporta che potete riempire archivi zip, archivi deflate o anche un vostro formato proprietario e passarli direttamente a librerie compatibili con gli stream, quindi, per esempio TinyXML.

La classe si chiama OgreStream, e come parametri vuole un Ogre::DataStreamPtr, che viene ritornato da una classe di archivi e poi ci sarebbero come parametri opzionali la grandezza del buffer da leggere ogni volta e i caratteri da spostare. Comunque non c’è bisogno di personalizzarli.

Ho implementato anche i meccanismi di seeking.

Prima del 13 ottobre 2012 la funzione readsome non andava, perché è legata all’implementazione dello stream e al metodo showmanyc, che ho implementato successivamente.

Troverete tutte le informazioni utili nel file.

Invertire chiavi e valori nelle map (C++)

Mi è capitato di dover invertire le chiavi con i valori delle mappe, così ho creato questo template:

#include <map>
#include <vector>

template <class oldkey, class oldvalue>
typename std::map< oldvalue, std::vector<oldkey> > reverse_map(typename std::map<oldkey, oldvalue> the_map)
{
	std::map< oldvalue, std::vector<oldkey> > ret;

	typename std::map<oldkey, oldvalue>::iterator it;
	for(it = the_map.begin(); it != the_map.end(); it++) {
		ret[it->second].push_back(it->first);
	}

	return ret;
}

Era il primo template che scrivevo. Comunque sembra che funzioni, ma se c’è qualcosa che non va scrivete nei commenti (però per favore non mangiatemi 😊 ).

Come al solito per queste cose, rilascio questo codice nel pubblico dominio.

Risoluzione: da stringa a interi e viceversa in C++

Ho fatto due funzioni utili in C++. Servono per trasformare la stringa della risoluzione in numeri e viceversa.

Da numberi a stringa è stato molto facile, ho usato uno stringstream. In questo caso era la modalità più semplice, veloce ed elegante.

Il contrario era un po’ più difficile.

Ho usato sempre uno stringstream. Per la larghezza è bastato fare il contrario di quello che avevo fatto prima, però dovevo trovare il separatore prima di trovare l’altezza. Perciò ho fatto un while che fino a quando lo stream era buono continuava a prendere i char e se trovava x o * si fermava. Dopodiché trovare l’altezza era semplicissimo.

Avrei voluto aggiungere anche × ai separatori, però non era possibile perché non stava in un char.

Se volete vedere il codice che parla da solo eccolo qui: risoluzione.cpp.

Ovviamente potete farne quello che volete. Non è richiesto alcun tipo di credito per righe che tutti potrebbero fare.