Abr 10
Articulos programación Aunque el formato de datos XML alardea de características como: extensibilidad, legibilidad, jerarquización, estandarización y capacidad de adaptación a multitud de formatos. A la hora de analizarlo y extraer información de él es, computacionalmente, un formato que presenta algunas dificultades con respecto a otros. Si bien es verdad que existen librerías/APIs dedicadas a superar este pequeño handicap. A continuación veremos ejemplos de dos tipos de librerías para analizar un documente XML desde java. Uno de ellos es el DOM (Document Object Model) y otro es el SAX (Simple API from XML).

Las diferencias principales entre DOM y SAX es que DOM genera un arból de objetos con sus dependencias en memoria. Esto permite acceder a cualquier elemento en cualquier posición una y otra vez, atrás y adelante sin problemas. El problema es que consume mucha memoria y no sería una opción recomendable para XMLs muy grandes. SAX por otro lado no almacena información en memoria y lee el fichero secuencialmente hasta encontrar el elemento y la información que necesitas en un proceso en donde se registran métodos callback cada vez que se detecta determinados patrones en el documento (apertura de etiquetas XML por ejemplo). SAX podría manejar con mayor facilidad grandes ficheros XML pero sin la libertad del DOM.

Veamos como podemos analizar este fragmento de XML


<?xml version="1.0" encoding="UTF-8"?>
<personas>
 <persona sexo="masculino">
  <nombre>Pepe</nombre>
  <apellidos>Gracia Perez</apellidos>
 </persona>
 <persona sexo="femenino">
  <nombre>María</nombre>
  <apellidos>Suarez Martinez</apellidos>
 </persona>
</personas>



Continua leyendo "Analizar XML con Java"

Publicado por Abraham Covelo

Abr 5
Articulos programación A continuación unas pequeñas recetas de java para pasar de cadena a entero o de entero a cadena.

Para convertir un String (cadena) a int (entero) hay que emplear el método estático de la clase Integer, parseInt

Ejemplo:


String enteroString = "5";
int entero = Integer.parseInt(enteroString);


Para convertir int(entero) a String sólo debemos hacer una llamada al método estático de la clase Integer, toString

Ejemplo:


int entero = 1;
String enteroString = Integer.toString(entero);



Análogamente para pasar de cadena a double tenemos el método Double.parseDouble

Ejemplo:


double aDouble = Double.parseDouble(aString);


o al revés (double a string) llamamos al método Double.toString

Ejemplo:


double d = 8342342;
System.out.println(Double.toString(d));


Tanto la clase Integer con la clase Double se encuentran en el package java.lang. Atención int y double son tipos primitivos del lenguaje java. Integer y Double son clases que representan estos tipos primitivos y le añaden más funcionalidades. Como por ejemplo las que acabamos de ver.

Publicado por Abraham Covelo

May 31
Articulos programación Hoy le daré algo de publicidad al elemento canvas de la especificación HTML versión 5. Esta especificación aún está en estado de borrador pero ha incluido este elemento que ya estaba presente en navegadores como Safari y navegadores basados en Gecko 1.8 como Firefox 1.5 y posteriores. También Opera desde la versión 9 y Chrome soportan canvas. Internet Explorer no lo soporta, aunque algunas personas han querido arreglar esto. A lo largo de este artículo incluyo varios canvas y podréis comprobar si vuestro navegador los soporta simplemente viendo si aparece la imagen del canvas en vuestro navegador.

Canvas es un elemento que permite representar gráficos empleando javascript. Veamos paso por paso como podemos utilizar canvas. Primero creamos el elemento canvas en nuestro html. Este es un ejemplo


<canvas id="micanvas" width="200" height="150">Lo siento, tu navegador no soporta <strong>canvas</strong></canvas>


Sencillo ¿no?. Aquí hemos creado un canvas de 200 pixeles de ancho por 150 de alto y le hemos asignado un identificador para poder referirnos a él posteriormente. Siguiendo la especificación de w3c el valor por defecto del ancho del canvas es 300 pixeles y el del alto es 150 pixeles. Estos valores pueden ser modificados a posteriori empleando hojas de estilo CSS. Si tu navegador no soporta canvas se mostrará el contenido entre las etiquetas canvas permitiendo así mostrar contenido alternativo. Este es el efecto de este código canvas en tu navegador:



Lo siento, tu navegador no soporta canvas

Veamos ahora como a través de javascript podemos pintar algo sobre canvas. Este es el código inicial al que hemos añadido un cuadrado rojo:

var micanvas = document.getElementById('micanvas');
if (micanvas.getContext)
{
var context = micanvas.getContext('2d');
context.fillStyle = "rgb(255,0,0)";
context.fillRect(20,20,100,120);
}
else
{
//canvas no soportado
}

Veamos el resultado

Lo siento, tu navegador no soporta canvas



Atención, si se modifica el ancho o el alto del objeto canvas la imagen se borra volviendo al estado inicial. Esto se puede lograr como habíamos comentado antes a través de hojas de estilo o en javascript mediante:

micanvas.setAttribute('width',250)

ó

micanvas.width = 250;

También

micanvas.width = micanvas.with

ó

micanvas.height = micanvas.height

Borra el canvas actual pero mantiene su tamaño.

El único contexto válido actualmente es el 2d que tiene una API 2D especifica. Es posible que en el futuro surjan otros contextos, por ejemplo 3d que empleen la API de OPENGL para representar contenido tridimensional con aceleración por hardware (estaremos atentos a esto)

Algunos de los métodos empleados por la API 2d y que podéis utilizar son:

save()
restore()
scale(x, y)
rotate(angle)
translate(x, y)
transform(m11, m12, m21, m22, dx, dy)
setTransform(m11, m12, m21, m22, dx, dy)
globalAlpha [ = value ]
globalCompositeOperation [ = value ]
strokeStyle [ = value ]
fillStyle [ = value ]
clearRect(x, y, w, h)
fillRect(x, y, w, h)
strokeRect(x, y, w, h)
arc(x, y, radius, startAngle, endAngle, anticlockwise)


La lista de métodos es muy extensa aunque no todos están soportados por todos los navegadores.

Por cierto el origen de coordenadas para este contexto esta el borde superior izquierdo.

Bueno para que no os quedéis con las ganas de ver lo que se puede hacer con este elemento os paso unos ejemplos:

canvex, racing, benjoffe


Publicado por Abraham Covelo

May 27
Articulos programación Puedes encontrar la primera parte del artículo aquí: Extendiendo PHP (I)

En esta segunda parte incluiremos el código necesario para que nuestra función haga su trabajo. Invertir una cadena o devolverla tal y como le ha llegado.

Una implementación en C para invertir una cadena podría ser esta (el código se presenta así con el proposito de ser claro, no óptimo)


#include
#include

char* reverseString(const char* str)
{
char* buffer;
int i=0;
buffer = (char*)malloc(strlen(str)*sizeof(char));
while(str[i]) buffer[strlen(str)-i++-1] = str[i];
return buffer;
}

int main(int argc,char** argv)
{
char* rstr;
rstr = (char*)reverseString("Hola mundo");
printf("%s\n",rstr);
free(rstr);
return(0);
}


Pues bien, habíamos dejado nuestra extensión en el directorio ext/dummy/ en donde podemos encontrar varios ficheros

config.m4 - reglas de configuración para \*nix
config.w32 - reglas de configuración para Güindow$
CREDITS - para meter el nombre de la extensión y tu nombre
EXPERIMENTAL - indica que la extensión es experimental
dummy.c - el código fuente de tu extensión
dummy.php - código de pruebas para tu extensión
Makefile.in - plantilla para el makefile
php_dummy.h - Cabecera para tu extensión
test/ - Directorio con las pruebas de regresión

Pasemos a editar dummy.c. Aunque esté lleno de código y marcaciones que pueden resultar extraños sólo debemos fijarnos en la estructura zend_module_entry llamada dummy_module_entry. Debemos sustituir PHP_RINIT(dummy) y PHP_RSHUTDOWN(dummy) por NULL pues no son necesarias para nuestra extensión. Se trata de código para inicializar o finalizar peticiones a la extensión. El código de la estructura se debe parecer a:


zend_module_entry dummy_module_entry = {
#if ZEND_MODULE_API_NO >= 20010901
STANDARD_MODULE_HEADER,
#endif
"dummy",
dummy_functions,
PHP_MINIT(dummy),
PHP_MSHUTDOWN(dummy),
NULL, /* Replace with NULL if there's nothing to do at request start */
NULL, /* Replace with NULL if there's nothing to do at request end */
PHP_MINFO(dummy),
#if ZEND_MODULE_API_NO >= 20010901
"0.1", /* Replace with version number for your extension */
#endif
STANDARD_MODULE_PROPERTIES
};


A continuación aparece comentado código para emplear valores propios de la extensión en las entradas de php.ini. Lo dejaremos como está, comentado, pues no las necesitaremos. Más abajo aparecen las implementaciones de MINIT(), MSHUTDOWN(), RINIT(), RSHUTDOWN() y MINFO(). Para MINIT() y MSHUTDOWN() sólo añadimos el código return SUCCESS; pues no queremos que hagan nada más. RINIT() y RSHUTDOWN() pueden ser borradas pero recuerda borrarlas también en el archivo de cabecera php_dummy.h

La función MINFO() se llama en la llamada a phpinfo() y en ella puedes añadir cualquier información que consideres relevante para la extensión.

Finalmente tenemos la función principal PHP_FUNCTION(dummy) donde agregaremos nuestro código adaptado:


/* {{{ proto string dummy(string msg, bool inv)
Devuelve la misma cadena enviada en orden normal o invertido */
PHP_FUNCTION(dummy)
{
char *msg = NULL;
int argc = ZEND_NUM_ARGS();
int msg_len;
zend_bool inv;
char *buffer = NULL;
int i=0;

if (zend_parse_parameters(argc TSRMLS_CC, "sb", &msg, &msg_len, &inv) == FAILURE)
return;

if(!inv) RETURN_STRINGL(msg, msg_len, 1);
buffer = (char*)malloc(strlen(msg)*sizeof(char));
while(msg[i]) buffer[strlen(msg)-i++-1] = msg[i];
RETURN_STRINGL(buffer, strlen(buffer), 1);
// php_error(E_WARNING, "dummy: not yet implemented");
}
/* }}} */


Antes de construir nuestra extensión debemos editar config.m4 para indicar como el usuario especificará que el módulo debe ser compilado en PHP. Estas líneas, comentadas por defecto, hacen justamente esto:



PHP_ARG_ENABLE(dummy, whether to enable dummy support,
[ --enable-dummy Enable dummy support])



Ahora existen 2 opciones a la hora de construir la extensión puedes hacerlo completamente independiente (standalone) y tu extensión será un módulo compartido cuya compilación será más rápida pero que necesitará ser habilitad desde php.ini para su carga o compilarla directamente en PHP que lleva más tiempo.

Para el modo independiente (standalone) debes ejecutar en el directorio de tu extensión el script phpsize que generará unos ficheros para configurar y construir tu extensión independientemente de PHP.

Luego sólo debes ejecutar:

$ ./configure
$ make
# make install

La extensión generada debería llamarse dummy.so y deberías copiarla al directorio donde php busca sus extensiones externas. Ahora debes precargar tu extensión desde php.ini mediante


extension=dummy.so


O desde el código de php directamente como:


dl('dummy.so');


Para la compilación dentro de PHP debes ejecutar en la raiz del código de PHP5

$ ./buildconf

Esto añadirá la opción --enable-dummy al script ./configure. Para probarlo ejecuta

$ ./configure --help

Ahora puedes construir PHP con:

$ ./configure --enable-dummy --enable-mysql=/usr/ ...

También puedes usar --enable-dummy=shared para forzar la compilación como librería compartida

¡Ya puedes probar tu extensión en tus scripts php!

<?php
var_dump(dummy('hola mundo',true));
?>

Una última consideración sobre memoria

La asignación de memoria dinámica es la causa principal de las perdidas de memoria (memory leaks). PHP dispone de funciones propias para la gestión de memoria dinámica. Estas funciones son:

emalloc()
efree()
estrdup()
estrndup()
ecalloc()
erealloc()

Que funcionan exactamente igual que sus contrapartidas en C. Estas funciones son seguras para evitar perdidas de memoria. Así que nuestra extensión tiene que sustituir la llama a malloc por emalloc. También debe ejecutar un efree por cada zona de memoria asignada con emalloc.

Publicado por Abraham Covelo

(Página 2 de 5, en total 18 entradas)