Manu Exposito's pearls

Manu Exposito's pearls

Postby Antonio Linares » Sat Aug 10, 2019 6:06 am

Code: Select all  Expand view  RUN
HB_FUNC( PARAM2HASH )
{
    PHB_ITEM pHash = hb_hashNew( NULL );
    PHB_DYNS pFuncSym = hb_dynsymFindName( "HB_ATOKENS" );

    if( pFuncSym && hb_dynsymIsFunction( pFuncSym ) )
    {
        HB_SIZE nLen;
        PHB_ITEM aTokens = hb_stackReturnItem();

        hb_itemSetNil( aTokens );

        hb_vmPushDynSym( pFuncSym );
        hb_vmPushNil();
        hb_vmPush( hb_param( 1, HB_IT_STRING ) );
        hb_vmPushString( "&", 1 );
        hb_vmProc( 2 );

        if( ( nLen = hb_arrayLen( aTokens ) ) > 0 )
        {
            HB_SIZE i, nPos;
            const char *szText;
            PHB_ITEM pKey = hb_itemNew( NULL );
            PHB_ITEM pValue = hb_itemNew( NULL );

            hb_hashPreallocate( pHash, nLen );

            for( i = 0; i < nLen; i++ )
            {
                szText = hb_arrayGetCPtr( aTokens, i + 1 );
                nPos = hb_strAt( "=", 1, szText, strlen( szText ) );

                hb_hashAdd( pHash, hb_itemPutCL( pKey,  szText, nPos - 1 ), hb_itemPutC( pValue, szText + nPos ) );
            }

            hb_itemRelease( pKey );
            hb_itemRelease( pValue );
        }
    }

    hb_itemReturnRelease( pHash );
}
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 42122
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Re: Manu Exposito's pearls

Postby AntoninoP » Wed Aug 14, 2019 7:05 am

Why don't write it in harbour?
Why don't write it in C?
Why don't use strtok instead of use HB_ATokens?
It is a strange mix, that I don't like, it looks like he takes the harbour code and translate it in C++ automatically...

In harbour is:
Code: Select all  Expand view  RUN
proc main()
   LOCAL test := Param2Hash("param1=23&param2=Pippo")
   LOCAL i
   for i:=1 to len(test)
      ? i, hb_HKeyAt(test,i), "=", hb_HValueAt(test,i)
   next

func Param2Hash(cParam)
   LOCAL aTokens := HB_ATokens(cParam,"&")
   LOCAL i, nLen := len(aTokens)
   LOCAL szText, nPos, pHash := {=>}
   for i:=1 to nLen
      szText := aTokens[i]
      nPos = at("=",szText)
      pHash[left(szText,nPos-1)] := substr(szText,nPos+1)
   next
return pHash
AntoninoP
 
Posts: 375
Joined: Tue Feb 10, 2015 9:48 am
Location: Albenga, Italy

Re: Manu Exposito's pearls

Postby xmanuel » Wed Aug 14, 2019 8:18 pm

En primer lugar te doy las gracias por hacer tu crítica...
Aprendo más de ellas que de los halagos.
Paso a contestarte cada pregunta...
Why don't write it in harbour?
Me gusta explorar todos recursos que tiene Harbour y el sistema extendido es lo mejor que tiene. Podría haber optado por hacerlo en Harbour pero creo que hay ciertos procesos que pueden mejorar el rendimiento y este podría ser uno de ellos. Es cuestión de hacer algún test.
Why don't write it in C?
Bueno ambas preguntas son autoexcluyentes, obviamente está escrita en lenguaje C, pero usando los recursos que Harbour pone a nuestro alcance, como por ejemplo correr una función (HB_ATOKENS) escrita para usarla desde PRG ejecutarla usando la pila de Harbour, si te refieres a eso,

Why don't use strtok instead of use HB_ATokens?
Para mi hubiera sido fácil usar strtok pero me encanta estudiar como está hecho Harbour y leo su código fuente con mucha atención, seguramente no habrás reparado en las diferentes entradas que hay en el changelog.txt ad virtiendo que está función de C no se debe usar ya que es incompatible con el sistema MT. Mira esto:
-----------------------
2006-12-15 16:55 UTC+0100 Przemyslaw Czerpak (druzus/at/priv.onet.pl)
* general PCODE cleanup and address most of TODO/FIXME notes in
source code:
! removed all strtok() functions
----------------------
2011-09-20 13:56 UTC+0200 Viktor Szakats (vszakats.net/harbour)
* contrib/hbqt/qtcore/hbqt_pointer.cpp
! fixed to avoid non-MT compatible strtok() C RTL call.
NOTE: Please continue to avoid strtok() usage in any further Harbour patches,
it is avoided for good reason.
----------------------
2011-08-27 13:49 UTC-0800 Pritpal Bedi (bedipritpal@hotmail.com)
* contrib/hbqt/hbmk2_qt.hbs
* contrib/hbqt/qtcore/hbqt.h
+ Implemented: C level class creation is now thread-safe.
With this only pending issue with hbQT remains to replace
usage of strtok() function with Harbour's implementation.
------------------------
Por eso no uso esa funcion de C :(

It is a strange mix, that I don't like, it looks like he takes the harbour code and translate it in C++ automatically...

Admito que no te guste... en mi tierra hay un dicho que dice que para gusto colores...
Pero el tema es que no te entiendo que quieres decir. La mezcla para nada es extraña, el código de Harbour está llena de esto. Yo no traduzco lo que hace Harbour en C, más bien me parece que tu has traducido lo que yo he hecho en C en PRG. Eso demuestra lo grande que es Harbour. Practicamente cualquier cosa que se pueda hacer en C se puede hacer en Harbour y en algunas incluso supera la velocidad de procesado, pero no es este el caso.

"Yo hago lo imposible, porque lo posible lo hace cualquiera", lo dijo alguien al que yo admiro, Pablo Picasso, por cierto paisano de A. Linares.
Y como soy un romántico informático también pongo en mi puño esta otra frase de Ernesto Guevara:
"Seamos realistas y hagamos lo imposible"

Termino reiterando mi agradecimiento a tu crítica.

Pongo aquí una nueva versión más optimizada de la función que me gusta más:
Code: Select all  Expand view  RUN

/***
 * Convierte un cadena como esta "esto=123&es=una&prueba=de&token=999" a u
 * Hash asi { esto => 123, es => una, prueba => de, token => 999 }
 */

HB_FUNC( PARAM2HASH )
{
    PHB_ITEM pHash = hb_hashNew( NULL );
    static PHB_DYNS s_pFuncATokens;

    if( !s_pFuncATokens )
    {
        s_pFuncATokens = hb_dynsymFind( "HB_ATOKENS" );
    }

    if( s_pFuncATokens )
    {
        HB_SIZE nLen;
        PHB_ITEM aTokens = hb_stackReturnItem();

        hb_itemSetNil( aTokens );

        hb_vmPushDynSym( s_pFuncATokens );
        hb_vmPushNil();
        hb_vmPush( hb_param( 1, HB_IT_STRING ) );
        hb_vmPushString( "&", 1 );
        hb_vmProc( 2 );

        if( ( nLen = hb_arrayLen( aTokens ) ) > 0 )
        {
            const char *szText;
            HB_SIZE i = 0, nPos, nStrLen;
            PHB_ITEM pKey = hb_itemNew( NULL );
            PHB_ITEM pValue = hb_itemNew( NULL );

            hb_hashPreallocate( pHash, nLen );

            while( i < nLen )
            {
                i++;
                szText = hb_arrayGetCPtr( aTokens, i );
                nStrLen = hb_arrayGetCLen( aTokens, i );
                nPos = hb_strAt( "=", 1, szText, nStrLen );

                hb_hashAdd( pHash, hb_itemPutCL( pKey, szText, nPos - 1 ),
                                   hb_itemPutCL( pValue, szText + nPos, nStrLen - nPos ) );
            }

            hb_itemRelease( pKey );
            hb_itemRelease( pValue );
        }
    }

    hb_itemReturnRelease( pHash );
}

 


Antonio traduce si puedes :-)
______________________________________________________________________________
Sevilla - Andalucía
xmanuel
 
Posts: 762
Joined: Sun Jun 15, 2008 7:47 pm
Location: Sevilla

Re: Manu Exposito's pearls

Postby Carlos Mora » Fri Aug 16, 2019 4:24 pm

Hey Manu,

antes de que te enfríes, una pregunta para que te piques :D ... He visto que en la versión nueva resuelves el símbolo hb_dynsymFind( "HB_ATOKENS" ) una vez. ¿No hay forma de usarlo invocándolo de forma estática, como hace el propio Harbour cuando genera pcode? No solo sería un enlace estático con la ventaja de velocidad que eso supone, sino también la referencia al símbolo generaría un "require" y obligaría al enlazador a incluir la función.

Abrazo!
Saludos
Carlos Mora
http://harbouradvisor.blogspot.com/
StackOverflow http://stackoverflow.com/users/549761/carlos-mora
“If you think education is expensive, try ignorance"
Carlos Mora
 
Posts: 989
Joined: Thu Nov 24, 2005 3:01 pm
Location: Madrid, España

Re: Manu Exposito's pearls

Postby xmanuel » Mon Aug 19, 2019 10:30 am

SI SE PUEDE!!!
:D
Harbour te da mecanismos para hacerlo...
Miráte hbinit.h...

De cualquier modo con esta versión última solo busca en la tabla de símbolos una vez... :P pero tiene que estar definida previamente por haberla usado o con un request ya que de lo contrario el compilador por optimización ni siquiera la mete en la tabla...
______________________________________________________________________________
Sevilla - Andalucía
xmanuel
 
Posts: 762
Joined: Sun Jun 15, 2008 7:47 pm
Location: Sevilla

Re: Manu Exposito's pearls

Postby Antonio Linares » Mon Aug 19, 2019 2:56 pm

harbour -gc3 -n test.prg

test.prg
Code: Select all  Expand view  RUN
function Main()

   local aLines := hb_aTokens()

return nil


test.c
Code: Select all  Expand view  RUN
/*
 * Harbour 3.2.0dev (r1904111533)
 * LLVM/Clang C 10.0.1 (clang-1001.0.46.4) (64-bit)
 * Generated C source from "test.prg"
 */


#include "hbvmpub.h"
#include "hbpcode.h"
#include "hbinit.h"
#include "hbxvm.h"


HB_FUNC( MAIN );
HB_FUNC_EXTERN( HB_ATOKENS );


HB_INIT_SYMBOLS_BEGIN( hb_vm_SymbolInit_TEST )
{ "MAIN", {HB_FS_PUBLIC | HB_FS_FIRST | HB_FS_LOCAL}, {HB_FUNCNAME( MAIN )}, NULL },
{ "HB_ATOKENS", {HB_FS_PUBLIC}, {HB_FUNCNAME( HB_ATOKENS )}, NULL }
HB_INIT_SYMBOLS_EX_END( hb_vm_SymbolInit_TEST, "test.prg", 0x0, 0x0003 )

#if defined( HB_PRAGMA_STARTUP )
   #pragma startup hb_vm_SymbolInit_TEST
#elif defined( HB_DATASEG_STARTUP )
   #define HB_DATASEG_BODY    HB_DATASEG_FUNC( hb_vm_SymbolInit_TEST )
   #include "hbiniseg.h"
#endif

HB_FUNC( MAIN )
{
   do {
    hb_xvmFrame( 1, 0 );
    hb_xvmSetLine( 3 );
    hb_xvmPushFuncSymbol( symbols + 1 );
    if( hb_xvmFunction( 0 ) ) break;
    hb_xvmPopLocal( 1 );
    hb_xvmSetLine( 5 );
    hb_xvmRetNil();
    /* *** END PROC *** */
   } while( 0 );
}

 
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 42122
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Re: Manu Exposito's pearls

Postby xmanuel » Tue Aug 20, 2019 12:52 pm

Esto es parte de HDO:
Code: Select all  Expand view  RUN

HB_INIT_SYMBOLS_BEGIN( LIST__InitSymbols )
{ "THASHLIST", { HB_FS_PUBLIC | HB_FS_LOCAL }, { HB_FUNCNAME( THASHLIST ) }, NULL },
{ "TMEMLIST",  { HB_FS_PUBLIC | HB_FS_LOCAL }, { HB_FUNCNAME( TMEMLIST ) },  NULL }
HB_INIT_SYMBOLS_END( LIST__InitSymbols )

#if defined( HB_PRAGMA_STARTUP )
    #pragma startup LIST__InitSymbols
#elif defined( HB_DATASEG_STARTUP )
    #define HB_DATASEG_BODY HB_DATASEG_FUNC( LIST__InitSymbols )
    #include "hbiniseg.h"
#endif
 

Así declaro esos dos símbolos que son dos clases hechas en C y serán usadas en PRG con herencia incluso :-)
______________________________________________________________________________
Sevilla - Andalucía
xmanuel
 
Posts: 762
Joined: Sun Jun 15, 2008 7:47 pm
Location: Sevilla

Re: Manu Exposito's pearls

Postby Verhoven » Tue Aug 20, 2019 4:40 pm

Buenas tardes Manu,
He leido en tus mensajes que Harbour indica la sustitución de strtok de C por HB_ATokens de Harbour, pero sustituir la primera por la segunda no se puede hacer directamente ya que strtok admite como parámetro una cadena con una serie de delimitadores, es decir, más de un delimitador para los tokens, mientras que HB_ATokens solo admite un delimitador.

¿Cómo se puede entonces hacer la sustitución de strtok en las rutinas donde los hayamos incorporado?.

Desde hace años vengo utlizando strtok en alguna función en C para agilizar al máximo el tratamiento de archivos grandes donde los distintos tokens pueden estar separados por más de un delimitador y me gustaría poder dejar de utilizar strtok de C por los problemas anunciados de compatibilidad.
Verhoven
 
Posts: 522
Joined: Sun Oct 09, 2005 7:23 pm

Re: Manu Exposito's pearls

Postby xmanuel » Tue Aug 20, 2019 6:03 pm

Hola.
Realmente no son totalmente compatibles hay que hacer retoques :? .
Fíjate en la definición de la función de C:
Code: Select all  Expand view  RUN

char *strtok(char *str, const char *delim)
 


No sé de donde sacas que puede admitir varios separadores, o tal vez te refieres que el separador puede ser mas de un caracter, por ejempo: "=>"?
Lo que esta claro es que va devolviendo tokens (trozos de cadena) mientras no llegue a '\0' o sea fin de cadena pasada.
Aquí tienes un ejemplo: https://www.tutorialspoint.com/compile_c_online.php

En cambio la sintaxis de hb_ATokens es:
Code: Select all  Expand view  RUN

hb_ATokens( <cString>, [<cDelim>|<lEOL>], [<lSkipStrings>], ;
            [<lDoubleQuoteOnly>] ) → aTokens
 


O sea que es más versátil que la de C con la ventaja de que nos devuelve un item de tipo array con item de tipo caracteres que desde el sistema extendido de harbour es más fácil su manejo.
Seguro que la sustitución de la primera por la segunda te resultará más fácil y provechosa :-)
______________________________________________________________________________
Sevilla - Andalucía
xmanuel
 
Posts: 762
Joined: Sun Jun 15, 2008 7:47 pm
Location: Sevilla

Re: Manu Exposito's pearls

Postby Verhoven » Wed Aug 21, 2019 12:47 pm

Buenas tardes Antonio,
Ciertamente creo que no me expresé con suficiente rigor:

strtok admite como segundo parámetro una cadena de caracteres, de tal manera que cada caracter de esa cadena lo interpreta como un delimitador, devolviendo nuevos elementos hasta que llega al final de la cadena pasada como primer parámetro. Sin embargo la función de Harbour, aunque coloquemos la misma cadena conteniendo esos delimitadores, solo interpreta como delimitador de los distintos elementos (items) el primero de los caracteres de la misma, el resto no los tiene en cuenta.

Por ello para sustituir la función strtok por la función hb_ATokens de Harbour habría que construir bucles anidados que fueran pasando por cada elemento del array devuelto en el bucle anterior por el siguiente caracter de la cadena que contenga los delimitadores. Lo cual parece que va a complicar las cosas y va a añadir líneas de código al proceso que relentizarán algo el procesado de los archivos de datos a analizar.

El problema de incompatibilidad de strtok podríais explicar exactamente en qué consiste porque he visto el código fuente de hb_ATokens pero no me atrevo a retocarlo con seguridad para incluir la posibilidad de "varios delimitadores".
Verhoven
 
Posts: 522
Joined: Sun Oct 09, 2005 7:23 pm

Re: Manu Exposito's pearls

Postby xmanuel » Wed Aug 21, 2019 7:50 pm

Así es...
Ese comportamiento es diferente :-(
______________________________________________________________________________
Sevilla - Andalucía
xmanuel
 
Posts: 762
Joined: Sun Jun 15, 2008 7:47 pm
Location: Sevilla

Re: Manu Exposito's pearls

Postby AntoninoP » Thu Aug 22, 2019 6:34 am

we can move this thread to Spanish forum :(
AntoninoP
 
Posts: 375
Joined: Tue Feb 10, 2015 9:48 am
Location: Albenga, Italy

Re: Manu Exposito's pearls

Postby Lailton » Thu Aug 22, 2019 10:45 pm

Hi Manu,

Keep doing your excellent job and code.
I am a big fan your job, I like style how you make your codes

WHO write equal always? everybody here have your way to write code :)

Thanks for share the function good job. :D
Regards,
Lailton Fernando Mariano
User avatar
Lailton
 
Posts: 156
Joined: Fri Jul 20, 2012 1:49 am
Location: Brazil


Return to FiveWin for Harbour/xHarbour

Who is online

Users browsing this forum: Google [Bot] and 82 guests