2012-06-13 16:16 UTC+0200 Viktor Szakats (harbour syenar.net)

* contrib/hbplist
  + contrib/hbamf
  + contrib/hbamf/amf.h
  + contrib/hbamf/amfdec.c
  + contrib/hbamf/amfenc.c
  + contrib/hbamf/amfstdio.c
  + contrib/hbamf/hbamf.hbc
  + contrib/hbamf/hbamf.hbp
  + contrib/hbamf/hbamf.hbx
  + contrib/hbamf/hbcls.c
  + contrib/hbamf/hbref.c
  + contrib/hbamf/issues.txt
  + contrib/hbamf/readme.txt
  + contrib/hbamf/tests
  + contrib/hbamf/tests/hbmk.hbm
  + contrib/hbamf/tests/tstendin.prg
    + added AMF3 encoder/decoder
      work of Aleksander Czajczynski and Ilina Stoilkovska
      (with minor additions of mine: build file
      cleanup, some C level formatting/comment cleanup, C++ 
      fixes)
    ; NOTE: this is only the pure AMF3 encoder/decoder,
            and doesn't include websocket layers
    ; TODO: adding license

  * utils/hbmk2/hbmk2.prg
    * minor in comments
This commit is contained in:
Viktor Szakats
2012-06-13 14:16:52 +00:00
parent 231d40b08d
commit 0bdc87ca0e
16 changed files with 3239 additions and 7 deletions

View File

@@ -16,6 +16,35 @@
The license applies to all entries newer than 2009-04-28.
*/
2012-06-13 16:16 UTC+0200 Viktor Szakats (harbour syenar.net)
* contrib/hbplist
+ contrib/hbamf
+ contrib/hbamf/amf.h
+ contrib/hbamf/amfdec.c
+ contrib/hbamf/amfenc.c
+ contrib/hbamf/amfstdio.c
+ contrib/hbamf/hbamf.hbc
+ contrib/hbamf/hbamf.hbp
+ contrib/hbamf/hbamf.hbx
+ contrib/hbamf/hbcls.c
+ contrib/hbamf/hbref.c
+ contrib/hbamf/issues.txt
+ contrib/hbamf/readme.txt
+ contrib/hbamf/tests
+ contrib/hbamf/tests/hbmk.hbm
+ contrib/hbamf/tests/tstendin.prg
+ added AMF3 encoder/decoder
work of Aleksander Czajczynski and Ilina Stoilkovska
(with minor additions of mine: build file
cleanup, some C level formatting/comment cleanup, C++
fixes)
; NOTE: this is only the pure AMF3 encoder/decoder,
and doesn't include websocket layers
; TODO: adding license
* utils/hbmk2/hbmk2.prg
* minor in comments
2012-06-13 15:44 UTC+0200 Viktor Szakats (harbour syenar.net)
* contrib/hbrun/hbrun.prg
* contrib/hbrun/plugins.prg

View File

@@ -0,0 +1,67 @@
/*
* $Id$
*/
/*******
*
* amf.h
*
* Aleksander Czajczynski <hb/at/fki.pl> 2011-2012
*
* amf.h - AMF3 headers
*
* Based on a AmFast C library for Python by Dave Thompson
*
********/
#ifndef __HBAMF_H
#define __HBAMF_H
/* Things used by both the encoder and the decoder. */
/* Use to test for endianness at run time. */
/* #define is_bigendian() ((*(char*)&endian_test) == 0) */
/* ---- Harbour support */
#define OBJAMF_VER 0
#define OBJAMF_VAR_COUNT 5
#define OBJAMF_VAR_VER 1
#define OBJAMF_VAR_NAME 2
#define OBJAMF_VAR_HASH 3
/* ---- AMF3 */
/* Valid AMF3 integer range */
#define MIN_INT -268435457
#define MAX_INT 268435456
/* Reference bit */
#define REFERENCE_BIT 0x01
/* Empty string */
#define EMPTY_STRING_TYPE 0x01
/* Object Headers */
#define STATIC 0x03
#define DYNAMIC 0x0B
#define EXTERNALIZABLE 0x07
/* Type markers */
#define UNDEFINED_TYPE 0x00
#define NULL_TYPE 0x01
#define FALSE_TYPE 0x02
#define TRUE_TYPE 0x03
#define INT_TYPE 0x04
#define DOUBLE_TYPE 0x05
#define STRING_TYPE 0x06
#define XML_DOC_TYPE 0x07
#define DATE_TYPE 0x08
#define ARRAY_TYPE 0x09
#define OBJECT_TYPE 0x0A
#define XML_TYPE 0x0B
#define BYTE_ARRAY_TYPE 0x0C
#define AMF3_AMF0 0x11
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,100 @@
/*
* $Id$
*/
/*******
*
* amfstdio.c by Ilina Stoilkovska <anili100/at/gmail.com> 2011
* Aleksander Czajczynski <hb/at/fki.pl> 2012
*
* amfstdio.c - Reading AMFIO data from standard input pipe
*
*
********/
#include "hbapi.h"
#include "hbapiitm.h"
#include "hbapigt.h"
#include "hbapifs.h"
#define SINGLEBUF 32768
#define MAXLEN ( 16 * 1024 * 1024 )
static int s_nCount = 0;
static void countCheck( int n )
{
/* yes, this is flow-control */
s_nCount += n;
while( s_nCount >= SINGLEBUF )
{
hb_conOutStd( "\0\0\0\0", 4 );
s_nCount -= SINGLEBUF;
}
}
HB_FUNC( AMFSTDIO_READ )
{
char * pszStrIn = ( char * ) hb_xgrab( SINGLEBUF );
char * pszLenPrefix = ( char * ) hb_xgrab( 5 );
char * pszBuf; /* = ( char * ) hb_xgrab( SINGLEBUF ); */
char * pszTmp = pszLenPrefix;
HB_USHORT nBytes = 0;
int nTotal = 0;
int nLen = 0;
int nToRead;
HB_FHANDLE hStdIn = hb_fsGetOsHandle( HB_STDIN_HANDLE );
while( nTotal < 4 )
{
nToRead = ( s_nCount + 4 - nTotal > SINGLEBUF ? SINGLEBUF - s_nCount : 4 - nTotal );
nBytes = hb_fsRead( hStdIn, pszStrIn, ( HB_USHORT ) nToRead );
countCheck( nBytes );
memcpy( pszTmp, pszStrIn, nBytes );
nTotal += nBytes;
pszTmp = pszLenPrefix + nTotal;
}
pszLenPrefix[ 4 ] = '\0';
nLen = HB_GET_LE_UINT32( pszLenPrefix );
if( nLen >= MAXLEN )
{
hb_ret();
return;
}
nTotal = 0;
pszBuf = ( char * ) hb_xgrab( nLen + 1 );
pszTmp = pszBuf;
while( nTotal < nLen )
{
/*
* here it's being decided that nToRead is never over 32768 bytes long,
* so hb_fsRead() is fine, no hb_fsReadLarge() needed
*/
if( nLen - nTotal > SINGLEBUF )
nToRead = SINGLEBUF - s_nCount;
else
nToRead = ( s_nCount + nLen - nTotal > SINGLEBUF ? SINGLEBUF - s_nCount : nLen - nTotal );
nBytes = hb_fsRead( hStdIn, pszStrIn, ( HB_USHORT ) nToRead );
countCheck( nBytes );
memcpy( pszTmp, pszStrIn, nBytes );
nTotal += nBytes;
pszTmp = pszBuf + nTotal;
}
hb_xfree( pszStrIn );
hb_xfree( pszLenPrefix );
hb_retclen_buffer( pszBuf, nLen );
}

View File

@@ -0,0 +1,7 @@
#
# $Id$
#
incpaths=.
libs=${_HB_DYNPREF}${hb_name}${_HB_DYNSUFF}

View File

@@ -0,0 +1,20 @@
#
# $Id$
#
-hblib
-inc
-o${hb_name}
-w3 -es2
-instfile=inc:hbamf.hbx
hbamf.hbx
amfenc.c
amfdec.c
amfstdio.c
hbref.c
hbcls.c

View File

@@ -0,0 +1,37 @@
/*
* $Id$
*/
/* -------------------------------------------------------------------- */
/* NOTE: You can add manual override which functions to include or */
/* exclude from automatically generated EXTERNAL/DYNAMIC list. */
/* Syntax: // HB_FUNC_INCLUDE <func> */
/* // HB_FUNC_EXCLUDE <func> */
/* -------------------------------------------------------------------- */
/* -------------------------------------------------------------------- */
/* WARNING: Automatically generated code below. DO NOT EDIT! */
/* Regenerate using hbmk2 '-hbx=' option. */
/* -------------------------------------------------------------------- */
#ifndef __HBEXTERN_CH__HBAMF__
#define __HBEXTERN_CH__HBAMF__
#if defined( __HBEXTREQ__ ) .OR. defined( __HBEXTERN__HBAMF__ANNOUNCE )
ANNOUNCE __HBEXTERN__HBAMF__
#endif
#if defined( __HBEXTREQ__ ) .OR. defined( __HBEXTERN__HBAMF__REQUEST )
#command DYNAMIC <fncs,...> => EXTERNAL <fncs>
#endif
DYNAMIC AMF3_DECODE
DYNAMIC AMF3_ENCODE
DYNAMIC AMF3_FROMWA
DYNAMIC AMFSTDIO_READ
#if defined( __HBEXTREQ__ ) .OR. defined( __HBEXTERN__HBAMF__REQUEST )
#uncommand DYNAMIC <fncs,...> => EXTERNAL <fncs>
#endif
#endif

View File

@@ -0,0 +1,80 @@
/*******
*
* hbref.c by Aleksander Czajczynski <hb/at/fki.pl> 2011
**
* hbref.c - Some class support functions for AMF3 (de)serialization
*
********/
#include "hbapi.h"
#include "hbapicls.h"
#include "hbapiitm.h"
#include "hbapistr.h"
#include "hbstack.h"
#include "hbvm.h"
#include "hboo.ch"
HB_BOOL is_cls_externalizable( HB_USHORT uiClass )
{
PHB_DYNS pSymbol = hb_dynsymGet( "__CLSMSGTYPE" );
HB_BOOL result = HB_FALSE;
/* as far as i know, there is no exported Harbour C level api for this */
if( uiClass && pSymbol )
{
PHB_ITEM pRetCopy = hb_itemNew( NULL );
hb_itemMove( pRetCopy, hb_stackReturnItem() );
hb_vmPushDynSym( pSymbol );
hb_vmPushNil();
hb_vmPushInteger( uiClass );
hb_vmPushString( "EXTERNALIZABLE", 14 );
hb_vmDo( 2 );
if( hb_itemGetNI( hb_stackReturnItem() ) == HB_OO_MSG_CLASSDATA )
result = HB_TRUE;
hb_itemMove( hb_stackReturnItem(), pRetCopy );
hb_itemRelease( pRetCopy );
}
return result;
}
PHB_ITEM cls_externalizable_instance( PHB_ITEM pClassFuncStr )
{
PHB_DYNS pSymbol = hb_dynsymGet( hb_itemGetCPtr( pClassFuncStr ) );
if( pSymbol )
{
PHB_ITEM pRetCopy = hb_itemNew( NULL );
PHB_ITEM pNewItem = hb_itemNew( NULL );
hb_itemMove( pRetCopy, hb_stackReturnItem() );
hb_vmPushDynSym( pSymbol );
hb_vmPushNil();
hb_vmDo( 0 );
hb_objSendMsg( hb_stackReturnItem(), "NEW", 0 );
hb_itemMove( pNewItem, hb_stackReturnItem() );
hb_itemMove( hb_stackReturnItem(), pRetCopy );
hb_itemRelease( pRetCopy );
if( pNewItem )
{
if( ! HB_IS_OBJECT( pNewItem ) )
{
hb_itemRelease( pNewItem );
pNewItem = NULL;
}
}
return pNewItem;
}
return NULL;
}

View File

@@ -0,0 +1,29 @@
/*******
*
* hbref.c by Aleksander Czajczynski <hb/at/fki.pl> 2011-2012
*
* hbref.c - Using Harbour C-pointers to various items as hashkeys
*
********/
#include "hbapiitm.h"
void _ref_realItemPtr( PHB_ITEM pKey, PHB_ITEM pItem )
{
if( HB_IS_STRING( pItem ) )
{
hb_itemPutPtr( pKey, ( void * ) hb_itemGetCPtr( pItem ) );
}
else if( HB_IS_ARRAY( pItem ) )
{
hb_itemPutPtr( pKey, hb_arrayId( pItem ) );
}
else if( HB_IS_HASH( pItem ) )
{
hb_itemPutPtr( pKey, hb_hashId( pItem ) );
}
else if( HB_IS_DATETIME( pItem ) )
{
hb_itemCopy( pKey, pItem );
}
}

View File

@@ -0,0 +1,34 @@
/*
* $Id$
*/
* amf3enc.c
* amf3dec.c
; AMF3_ENCODE(), AMF3_DECODE()
- there is no real serialization class-mapping included at the moment,
due to lack of time to make a concept of it complete.
Only anonymous (emulated on Harbour side using ObjAMF class)
and externalizable objects are supported.
- context->positon-- decrements should be removed from the .c code,
before we make the functions able to work on real streams without
buffering. There is no rewind in such situations.
; AMF3_FROMWA() - generates AMF3 array from current workarea,
but the function doesn't have an idea of SET DELETED switch!
It should have, because it tries to predict the number of records.
As a workaround <bFor> parameter could be used, because it switches
off the prediction. Another option could be creating temporary INDEX FOR,
it should have correct OrdKeyCount().
; AMF3_DECODE() - really doesn't need a hash for references, because
reference id in AMF increase sequentially. It could be okay and faster
to use some array with decent resize schema. Other than that benchmarks (in
ST mode) showed that decoding speed is a little bit faster in this
implementation than with Flash's bulit-in.
; .c function amf3_encode_string() does string hb_strRTrimLen()
on a utf8 values. so far i haven't found a string that was broken
by this, but i have a feeling that it is possible...
Note your issues too!

View File

@@ -0,0 +1,68 @@
/*
* $Id$
*/
--------------------------------------
Short description of Harbour functions
--------------------------------------
cAMF := AMF3_ENCODE( xVal, symConvOut, lBinaryStrings )
xVal - any supported datatype:
Character (String/MEMO), Numeric (Integer/Double), NIL, Logical, Date (encoded as DateTime),
DateTime, Array, Hash (String and Integer keys only),
Object (anonymous hash-like, externalizable, class-mapped)
AMF supports references, so this example a1 value will be serialized correctly.
a1 := { NIL }
a2 := { a1 }
a1[1] := a2
symConvOut - function symbol for outbound conversion
Acts recursively, so if xVal is array,
all of it's values will be passed to this
function.
lBinaryStrings - treat strings as binary, resulting AMF
datatype will be ByteArray. Normally
a string is encoded to UTF-8.
xVal := AMF3_DECODE( cAMF, symConvIn )
cAMF - AMF3 serialized binary string
symConvIn - function symbol for inbound conversion
cAMF := AMF3_FROMWA( [ <bWhile> ], [ <bFor> ], [ <aFields> ], [ <nCount> ], [ <lStrTrim> ], [ <nPackage> ], [ pContext ] )
Function to convert current workarea to AMF3 Array.
bWhile - COPY TO like WHILE codeblock
bFor - COPY TO like FOR codeblock
aFields - array of fieldnames (codeblocks are going to be supported here too)
nCount - NEXT like, process only specified count of records
lStrTrim - RTrim() strings, default is .T.
nPackage - determine the exact output AMF format
0 - Array of records contains Arrays of fields (default)
1 - Array of records contains Anonymous objects
2 - ArrayCollection object
Lower number means lesser packet size on the network.
pContext - when this function is used inside AMF3_ENCODE specified
outbound conversion function, you must pass pointer to
encoding context, otherwise AMF3 references will encoded
incorrectly. Example code of such case:
STATIC FUNCTION ConvOut( xVal, pOuterContext )
LOCAL lClose
IF ValType( xVal ) = "O"
IF xVal:className == "WORKAREAEXPORT"
lClose := xVal:lCloseWA
SELECT ( xVal:nWorkArea )
xVal := RawAMF():New( AMF3_FROMWA( xVal:bWhile, xVal:bFor, xVal:aFields, xVal:nCount, xVal:lStrTrim, 1, pOuterContext ) )
IF lClose
CLOSE
ENDIF
ENDIF
ENDIF
RETURN xVal

View File

@@ -0,0 +1,7 @@
#
# $Id$
#
hbamf.hbc
-w3 -es2

View File

@@ -0,0 +1,45 @@
/*
* $Id$
*/
REQUEST HB_CODEPAGE_UTF8EX
#uncommand ? [<explist,...>] =>
#command ? [<explist,...>] => A( <explist> )
PROCEDURE MAIN()
hb_cdpSelect( "UTF8EX" )
? { }, "8352"
? "a", "F248"
? "¥", "96F0"
? 1, "AE79"
? 1000, "278B"
? 1000000, "A752"
? 268435455, "4907"
? 268435456, "E677"
? 268435456000, "4271"
? - 1, "FE11"
? 9007199254740990, "0009"
? AMF3_DECODE( AMF3_ENCODE( 9007199254740990 ) ), "0009"
? 9007199254740991, "8918"
? AMF3_DECODE( AMF3_ENCODE( 9007199254740991 ) ), "8918"
? 9007199254740991.00, "8918"
? 6969.69, "10AF"
? NIL, "F1E1"
? .T. , "E3C2"
? .F. , "6AD3"
? { 1, - 1 }, "0560"
? { "ONE" => 0xcafe, "TWO" => 0xbabe }, "CE93"
RETURN
PROCEDURE A( a, cChkOK )
LOCAL x := AMF3_ENCODE( a )
LOCAL cChk := hb_StrToHex( I2Bin( hb_CRC( x ) ) )
QOut( PadL( hb_ValToExp( a ), 18 ), hb_StrToHex( x, " " ), "CHECKSUM", cChk, IIF( !Empty( cChkOK ) .AND. !( cChk == cChkOK ), "!TEST FAILED!, should be " + cChkOK, " " ) )
RETURN

View File

@@ -4,6 +4,7 @@
gtalleg/gtalleg.hbp
gtwvg/gtwvg.hbp
hbamf/hbamf.hbp
hbblat/hbblat.hbp
hbblink/hbblink.hbp
hbbz2/hbbz2.hbp # uses: bz2 (locally hosted)

View File

@@ -518,13 +518,8 @@ REQUEST hbmk_KEYW
#define PathMakeAbsolute( cPathR, cPathA ) hb_PathJoin( cPathA, cPathR )
/* NOTE: use hbextern library instead of #include "hbextern.ch"
* in dynamic builds it will greatly reduce the size because
* all function symbols will be registered by harbour shared
* library (.dll, .so, .sl, .dyn, ...) not by this code
*/
REQUEST __HB_EXTERN__ /* for runner and interactive shell */
/* Request for runner and interactive shell */
REQUEST __HB_EXTERN__
/* Request some functions for plugins */
REQUEST HBCLASS