CodeUp

Feeling the byte

How to catch an invalid array index/offset as a native exception in PHP

leave a comment

Written by Moisés Maciá

July 5th, 2011 at 1:06 pm

Posted in Recipes

Tagged with , , , , ,

XSLT Recipes: String tokenizer

leave a comment

How to convert string values such as “10,20,30,40” into a XML node set dynamically.

The template

<xsl:template name="tokenize">
	<xsl:param name="string" />
	<xsl:param name="delim" />
 
	<xsl:choose>
		<xsl:when test="contains($string, $delim)">
			<token><xsl:value-of select="substring-before($string, $delim)" /></token>
			<xsl:call-template name="tokenize">
				<xsl:with-param name="string" select="substring-after($string, $delim)" />
				<xsl:with-param name="delim" select="$delim" />
			</xsl:call-template>
		</xsl:when>
 
		<xsl:otherwise>
			<token><xsl:value-of select="$string" /></token>
		</xsl:otherwise>
	</xsl:choose>
</xsl:template>

Usage

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
		xmlns:exsl="http://exslt.org/common" extension-element-prefixes="exsl">
	<xsl:output method="xml"/>
 
	<xsl:template match="/">
		<xsl:variable name="tokens">
			<xsl:call-template name="tokenize">
				<xsl:with-param name="string" select="'10,20,30,40,50'" />
				<xsl:with-param name="delim" select="','" />
			</xsl:call-template>
		</xsl:variable>
 
		<ul>
		<xsl:for-each select="exsl:node-set($tokens)/token">
			<li><xsl:value-of select="."/></li>
		</xsl:for-each>
		</ul>
	</xsl:template>
</xsl:stylesheet>

Result

<ul>
	<li>10</li>
	<li>20</li>
	<li>30</li>
	<li>40</li>
	<li>50</li>
</ul>

Written by Moisés Maciá

June 30th, 2010 at 10:30 am

Posted in Recipes

Tagged with , , , ,

XSLT Recipes: escape single quotes

leave a comment

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
	<xsl:output method="xml"/>
 
	<xsl:template name="escapeQuotes">
		<xsl:param name="txt"/>
 
		<xsl:variable name="backSlashQuote">&#92;&#39;</xsl:variable>
		<xsl:variable name="singleQuote">&#39;</xsl:variable>
 
		<xsl:choose>
			<xsl:when test="string-length($txt) = 0">
				<!-- ... -->
			</xsl:when>
 
			<xsl:when test="contains($txt, $singleQuote)">
				<xsl:value-of disable-output-escaping="yes" 
						select="concat(substring-before($txt, $singleQuote), $backSlashQuote)"/>
 
				<xsl:call-template name="escapeQuotes">
					<xsl:with-param name="txt" select="substring-after($txt, $singleQuote)"/>
				</xsl:call-template>
			</xsl:when>
 
			<xsl:otherwise>
				<xsl:value-of disable-output-escaping="yes" select="$txt"/>
			</xsl:otherwise>
		</xsl:choose>
	</xsl:template>
 
</xsl:stylesheet>

Written by Moisés Maciá

May 25th, 2010 at 4:26 pm

Posted in Recipes

Tagged with , ,

Smart pointers en C++: ¿Por qué debería usarlos? (parte 2 de 3)

one comment

Menos errores

  • Limpieza automática. Tal y como ilustra el código del anterior artículo de la serie, usar punteros inteligentes que liberan la memoria automáticamente puede ahorrar unas cuantas lineas de código. La importancia no radica en cuantas pulsaciones ahorramos, sino en reducir la probabilidad de error: no es necesario recordar la liberación del puntero, y por lo tanto no hay margen de error para que se pueda olvidar.
  • Inicialización automática. Otra cosa buena es que no es necesario inicializar un puntero auto_ptr a NULL, el constructor por defecto se encarga de ello. Una cosa menos que el programador necesita recordar.
  • Punteros olvidados. Un error muy común de la gestión de memoria es el de los punteros olvidados: un puntero que apunta a una zona de memoria que ya ha sido eliminada.

El siguiente código ilustra la situación:

1
2
3
4
5
6
MyClass* p(new MyClass);
MyClass* q = p;
delete p;
p->DoSomething(); // Vigila! p está ahora en el limbo!
p = NULL; // p ya apunta correctamente
q->DoSomething(); // Ojo! q continua en el limbo!

En la implementación de auto_ptr, esto se soluciona asignando NULL al puntero interno cuando se copia:

1
2
3
4
5
6
7
8
9
10
template <class T>
auto_ptr<T>& auto_ptr<T>::operator=(auto_ptr<T>& rhs)
{
	if (this != &rhs) {
		delete ptr;
		ptr = rhs.ptr;
		rhs.ptr = NULL;
	}
	return *this;
}

Otros tipos de punteros inteligentes pueden seguir distintas estrategias de copiado. Estas son algunas de las técnicas más habituales para manejar la situación q = p, donde p y q son punteros inteligentes:

  • Crear una nueva copia del objeto apuntado por p, y hacer que q apunte a esa copia.
  • Transferencia de propiedad: Hacemos que p y q apunten al mismo objeto, pero transferimos la responsabilidad de limpiar la memoria reservada (“propiedad”) desde p a q.
  • Contador de referencias: Se mantiene un contador de los punteros inteligentes que apuntan a un mismo objeto, y se elimina la memoria cuando este contador llega a cero. De manera que la sentencia q = p provoca que el contador apuntado por p se incremente en uno. Scott Meyers ofrece una implementación para el contador de referencias en su libro More Effective C++.
  • Enlazado de referencias: Similar a la técnica del contador de referencias, sólo que en lugar de mantener un contador, mantiene una lista circular doblemente enlazada de todos los punteros que apuntan al mismo objeto.
  • COW (Copy-on-write): Se usa un contador de referencias o la lista mientras que el objeto apuntado no se modifique. En el instante en que el objeto se va a modificar, se copia y se modifica la copia.

Todas estas técnicas ayudan a sanear el código de punteros olvidados. Cada una tiene sus beneficios y sus desventajas. En la siguiente parte de esta serie de artículos se discute acerca de la conveniencia del tipo de puntero inteligente para diferentes situaciones.

Manejo de excepciones y punteros

Veamos de nuevo el ejemplo:

1
2
3
4
5
void foo() {
	MyClass* p(new MyClass);
	p->DoSomething();
	delete p;
}

¿Qué ocurre si DoSomething() lanza una excepción? Todas las lineas después de la llamada al método no se ejecutarán y p nunca va a ser eliminado correctamente. Si tenemos suerte esto sólo provocará una fuga de memoria. Sin embargo, es posible que MyClass sea responsable de liberar otros recursos en su propio destructor (archivos, threads, transacciones, mutex, etc…) y el hecho de no llamarlo puede provocar problemas serios de concurrencia.

Si usamos un puntero inteligente, sin embargo, p va a ser liberado cuando salga de su ámbito, sin importar si sigue su linea habitual de ejecución o durante el desenrollado de la pila causado por la excepción.

¿Pero es posible escribir código con excepciones que se comporte de manera segura usando punteros tradicionales? Seguramente sí, pero no merece la pena el esfuerzo teniendo alternativas mucho más sencillas.

Este código ilustra el uso de punteros tradicionales junto a excepciones:

1
2
3
4
5
6
7
8
9
10
11
12
13
void foo() {
	MyClass* p;
 
	try {
		p = new MyClass;
		p->DoSomething();
		delete p;
	}
	catch (...) {
		delete p;
		throw;
	}
}

Considerablemente más engorroso de programar y mantener que la versión con smart pointers.

Recolección de basura

C++ no proporciona un recolector automático de basura como si lo hacen otros lenguajes de programación (Java, C#, etc.) así que los punteros inteligentes pueden usarse para este propósito. De entre las diferentes técnicas de recolección de basura, el esquema más simple es el contador de referencias o las referencias enlazadas vistas anteriormente, pero es posible implementar mecanismos mucho más sofisticados de recolección de basura con los punteros inteligentes.

Más información sobre la recolección de basura y sus diferentes implementaciones.

Eficiencia

Los punteros inteligentes pueden emplearse para un uso eficiente de la memoria disponible y acortar los ciclos de reserva y liberación de memoria.

Una técnica habitual para usar memoria de una forma más eficiente es la llamada copiar al escribir (copy-on-write, abreviado a veces como COW). Consiste en compartir el mismo objeto entre varios punteros COW, mientras el objeto compartido no se modifique y los accesos sean sólo de lectura. Cuando en algún punto del programa se intenta modificar el objeto (escritura), el puntero COW crea una nueva copia y la modifica en lugar de tocar el objeto original.

La clase estándar de C++ string se implementa habitualmente usando esta técnica (ver la cabecera <string>).

1
2
3
4
5
string s("Hello");
 
string t = s;   // t y s apuntan al mismo buffer de caracteres
t += " world!"; // se reserva un nuevo buffer para t antes de
                // añadir " world!", por lo tanto s permanece sin cambio.

Los esquemas de reserva de memoria optimizados tienen sentido cuando podemos establecer una serie de suposiciones sobre los objetos que van a ser instanciados o el entorno operativo en el que se ejecutará. Por ejemplo, podríamos suponer que todos los objetos reservados ocupan el mismo tamaño, o su vida va a transcurrir en un solo hilo de ejecución. Aunque es posible implementar esquemas de reserva optimizados usando la sobrecarga de los operadores new y delete específicos de clase, los punteros inteligentes nos proporcionan la libertad de elegir el esquema de reserva adecuado para cada tipo de objeto, en lugar de emplear el mismo mecanismo para todos los objetos de una clase. Por tanto es posible elegir diferentes aproximaciones de reserva de memoria optimizadas para diferentes entornos operativos y aplicaciones, sin modificar el código de la clase.

Contenedores STL

La librería estándar de C++ incluye una serie de contenedores y algoritmos conocidos como Standard Template Library (STL). La STL fue diseñada para ser genérica (puede utilizarse para contener cualquier tipo de objeto) y eficiente (no incurre en gastos adicionales comparado con otras alternativas). Para alcanzar estos dos objetivos de diseño, los contenedores STL almacenan sus objetos por valor. Esto significa que si tenemos un contenedor STL que almacena objetos de la clase Base, por definición no puede almacenar objetos de una clase derivada de Base.

1
2
3
4
5
6
7
8
9
class Base { /*...*/ };
class Derived : public Base { /*...*/ };
 
Base b;
Derived d;
vector<Base> v;
 
v.push_back(b); // OK
v.push_back(d); // error

¿Qué podemos hacer si necesitamos almacenar un lote de objetos de diferentes clases? La solución más simple es tener una colección de punteros a dichas clases:

1
2
3
4
5
6
7
8
9
vector<Base*> v;
 
v.push_back(new Base); // OK
v.push_back(new Derived); // OK
 
// hay que limpiar la memoria despues!
for (vector<Base*>::iterator i = v.begin(); i != v.end(); ++i) {
	delete *i;
}

El problema de esta solución es después de trabajar con el contenedor, necesitamos liberar manualmente todos los objetos almacenados en él. Este proceso es muy propenso a errores y volvemos a tener problemas con las excepciones tal y como se vio en el punto anterior.

Los punteros inteligentes proporcionan una posible solución a este problema, como podemos ver más abajo.

1
2
3
4
5
vector< boost::shared_ptr<Base> > v;
v.push_back(new Base); // OK
v.push_back(new Derived); // OK
 
// la limpieza es automatica ...

Como el puntero inteligente se limpia automáticamente, no es necesario eliminar manualmente los objetos apuntados.

Cuidado: Los contenedores STL pueden copiar y borrar sus elementos sin aviso previo (por ejemplo, cuando se redimensionan a si mismos). Por tanto, todas las copias de un elemento tienen que ser equivalentes, o es probable que una copia errónea sea la que sobreviva a este proceso de copia y borrado. Esto significa que algunos tipos de punteros inteligentes no son apropiados para utilizarse conjuntamente con los contenedores STL, concretamente el estándar auto_ptr y otros punteros de transferencia de propiedad.

Este punto se discute en detalle en el artículo C++ Guru of the Week #25.

Una solución a este problema es el empleo de “contenedores inteligentes” a medida o emplear soluciones como los shared_ptr de Boost. El uso específico de los smart pointers de Boost se verá más adelante.

Artículos de esta serie:

  1. Smart pointers en C++: ¿Qué son? (parte 1 de 3)
  2. Smart pointers en C++: ¿Por qué debería usarlos? (parte 2 de 3)
  3. Smart pointers en C++: ¿Qué tipo de smart pointer emplear? (parte 3 de 3) [próximamente]

Written by Moisés Maciá

April 27th, 2010 at 10:46 am

XSLT recipes: Sum all values of not null nodes

leave a comment

Input document:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<Books>
	<row>
		<col name="title">Dead in the Family: A Sookie Stackhouse Novel</col>
		<col name="price">9.99</col>
	</row>
 
	<row>
		<col name="title">The Girl Who Kicked the Hornet's Nest</col>
		<col name="price">null</col>
	</row>
 
	<row>
		<col name="title">The Big Short: Inside the Doomsday Machine</col>
		<col name="price">15.37</col>
	</row>
 
	<row>
		<col name="title">Savor the Moment</col>
		<col name="price">null</col>
	</row>
</Books>

XSL transform stylesheet:

1
2
3
4
5
6
7
8
9
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
	<xsl:output method="text"/>
 
	<xsl:template match="/">
		<xsl:text>Total: </xsl:text>
		<xsl:value-of select="sum(row/col[@name = 'price' and node()/self::text() != 'null'])"/>
	</xsl:template>
 
</xsl:stylesheet>

Outputs:

Total: 25.36

Written by Moisés Maciá

April 26th, 2010 at 1:46 pm

Posted in Recipes

Tagged with , , , , ,

Smart pointers en C++: ¿Qué son? (parte 1 de 3)

2 comments

Los punteros inteligentes (smart pointers) son objetos que se parecen y se comportan como los punteros tradicionales, pero son más inteligentes. ¿Qué significa esto? Para parecerse y comportarse como punteros, los punteros inteligentes necesitan tener el mismo interfaz que los punteros normales: necesitan soportar operaciones de derreferenciación (operador *) y de indirección (operador ->).

Un objeto que se parece y se comporta como otro se llama objeto proxy, o simplemente proxy. El patrón de diseño proxy y sus múltiples usos se describen en detalle en los libros Design Patterns: Elements of reusable object-oriented software y Pattern Oriented Software Architecture.

La inteligencia de los smart pointers reside en las capacidades extendidas que presentan frente a los punteros tradicionales. Probablemente los errores mas frecuentes en C++ (y C) son aquellos relacionados con el manejo de memoria y los punteros: fugas de memoria, fallos en la reserva de memoria, punteros que apuntan a zonas de memoria inválida y otras diversiones. Tener un puntero inteligente que se haga cargo de todas estas tareas de forma automática nos ahorra muchos dolores de cabeza.

El ejemplo más simple de puntero inteligente es auto_ptr, que viene incluido en la librería estándar de C++ (STL). Se puede encontrar en la cabecera <memory>. A continuación se muestra una parte de la implementación de auto_ptr, para ilustrar su funcionamiento:

1
2
3
4
5
6
7
8
9
10
template <class T> class auto_ptr
{
	T* ptr;
	public:
	explicit auto_ptr(T* p = 0) : ptr(p) {}
	~auto_ptr() {delete ptr;}
	T& operator*() {return *ptr;}
	T* operator->() {return ptr;}
	// ...
};

Como se puede observar, auto_ptr es una simple envoltura alrededor de un puntero tradicional que delega todas las operaciones relevantes a su puntero interno (derreferencia e indirección). Su inteligencia se encuentra en el destructor: el destructor se encarga de eliminar la memoria del puntero.

Para el usuario de auto_ptr, esto significa que en lugar de escribir:

1
2
3
4
5
void foo() {
	MyClass* p(new MyClass);
	p->DoSomething();
	delete p;
}

Simplemente puede escribir:

1
2
3
4
void foo() {
	auto_ptr<MyClass> p(new MyClass);
	p->DoSomething();
}

Y auto_ptr nos garantiza que la memoria se liberará automáticamente cuando el objeto p salga de su ámbito.

Artículos de esta serie:

  1. Smart pointers en C++: ¿Qué son? (parte 1 de 3)
  2. Smart pointers en C++: ¿Por qué debería usarlos? (parte 2 de 3)
  3. Smart pointers en C++: ¿Qué tipo de smart pointer emplear? (parte 3 de 3) [próximamente]

Written by Moisés Maciá

April 22nd, 2010 at 10:37 am

Posted in Uncategorized

Tagged with , , , ,

Get XPath of one element in XSLT

leave a comment

Here is the code to get all XPath trees of all elements of given XML document. You can easily change the code to get a single node’s XPath.

?Download xpath.xsl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
	<xsl:output method="text"/>
 
	<xsl:template match="*" mode="get-xpath">
		<xsl:apply-templates select="parent::*" mode="get-xpath"/>
 
		<xsl:text>/</xsl:text><xsl:value-of select="name()"/>
		<xsl:if test="../*[2]">
			<xsl:text>[</xsl:text>
			<xsl:value-of select="1+count(preceding-sibling::*[name(.)=name(current())])"/>
			<xsl:text>]</xsl:text>
		</xsl:if>
	</xsl:template>
 
	<xsl:template match="@*" mode="get-xpath">
		<xsl:apply-templates select="parent::*" mode="get-xpath"/>
 
		<xsl:text>/@</xsl:text>
 
		<xsl:choose>
			<xsl:when test="namespace-uri() = ''">
				<xsl:value-of select="name()"/>
				<!--<xsl:text> = <xsl:value-of select="."/></xsl:text>-->
			</xsl:when>
			<xsl:otherwise>
				<xsl:text>*[local-name()='</xsl:text>
				<xsl:value-of select="local-name()"/>
				<xsl:text>' and namespace-uri()='</xsl:text>
				<xsl:value-of select="namespace-uri()"/>
				<xsl:text>']</xsl:text>
				<!--<xsl:text> = <xsl:value-of select="."/></xsl:text>-->
			</xsl:otherwise>
		</xsl:choose>
	</xsl:template>
 
	<xsl:template match="/">
		<xsl:for-each select="//*|//*/@*">
			<xsl:apply-templates mode="get-xpath" select="."/><xsl:text>
</xsl:text>
		</xsl:for-each>
	</xsl:template>
 
</xsl:stylesheet>

If you try to transform this example XML document …

?Download example.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?xml version="1.0" encoding="UTF-8"?>
<books>
	<book isbn="0130353132">
		<title>Thinking in C++, Volume 2: Practical Programming</title>
		<author>Bruce Eckel</author>
		<pages>832</pages>
	</book>
	<book isbn="0385504225">
		<title>The Lost Symbol</title>
		<author>Dan Brown</author>
		<pages>528</pages>
	</book>
	<book isbn="0307454541">
		<title>The Girl with the Dragon Tattoo</title>
		<author>Stieg Larsson</author>
		<pages>608</pages>
	</book>
</books>

.. you’ll got all expanded tree of XPaths (as expected :) )

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/books
/books/book[1]
/books/book[1]/@isbn
/books/book[1]/title[1]
/books/book[1]/author[1]
/books/book[1]/pages[1]
/books/book[2]
/books/book[2]/@isbn
/books/book[2]/title[1]
/books/book[2]/author[1]
/books/book[2]/pages[1]
/books/book[3]
/books/book[3]/@isbn
/books/book[3]/title[1]
/books/book[3]/author[1]
/books/book[3]/pages[1]

Written by Moisés Maciá

January 7th, 2010 at 1:39 pm

Posted in Recipes

Tagged with , , ,

How to get Apple’s look like fonts on Linux

leave a comment

I want to share with you my fontconfig config file.

The default configuration in Kubuntu doesn’t use all the power of FreeType‘s font rendering engine, so you get ugly and sharped fonts.

My customized version uses all the bells and whistles (anti-alias, font hint, etc.) to improve the quality of fonts. Follow theese steps to test it on your system:

  1. Download the file.
  2. Rename it to .fonts.conf (notice the first period) and put it in your $HOME.
  3. Restart X

Written by Moisés Maciá

November 26th, 2009 at 11:17 pm

Google Wave invitations

one comment

Hi all.

I have 15 invitations for Google’s newest application: Google Wave. So if you want to try it and you don’t have an account yet you can drop me a comment and I’ll send you an invitation.

Written by Moisés Maciá

November 21st, 2009 at 7:11 pm

Posted in Uncategorized

Tagged with , ,