提交 0933a343 authored 作者: Anthony Minessale's avatar Anthony Minessale

RTMP as easy as A.B.C. Avant-Garde Solutions Inc. -- Barracuda Networks Inc. --…

RTMP as easy as A.B.C. Avant-Garde Solutions Inc. -- Barracuda Networks Inc. -- ClueCon! http://www.cluecon.com
上级 21096275
......@@ -68,6 +68,7 @@ endpoints/mod_loopback
#endpoints/mod_skypopen
#endpoints/mod_h323
#endpoints/mod_khomp
#endpoints/mod_rtmp
#../../libs/openzap/mod_openzap
#../../libs/freetdm/mod_freetdm
#asr_tts/mod_unimrcp
......
......@@ -42,6 +42,7 @@
<!-- <load module="mod_unicall"/> -->
<!-- <load module="mod_skinny"/> -->
<!-- <load module="mod_khomp"/> -->
<!-- <load module="mod_rtmp"/> -->
<!-- Applications -->
<load module="mod_commands"/>
......
BASE=../../../..
LIBAMF_OBJS=libamf/src/amf0.o libamf/src/hash.o libamf/src/io.o libamf/src/ptrarray.o libamf/src/types.o
LOCAL_OBJS=rtmp_sig.o rtmp.o rtmp_tcp.o $(LIBAMF_OBJS)
LOCAL_CFLAGS=-Ilibamf/src
include $(BASE)/build/modmake.rules
cmake_minimum_required(VERSION 2.6)
project(libamf C)
# generic variables
set(PACKAGE "libamf")
set(PACKAGE_NAME ${PACKAGE})
set(PACKAGE_BUGREPORT "libamf@sf.net")
set(PACKAGE_VERSION "0.1.0")
set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}")
#platform tests
include(CheckFunctionExists)
include(CheckIncludeFile)
include(CheckTypeSize)
include(TestBigEndian)
check_include_file(sys/types.h HAVE_SYS_TYPES_H)
check_include_file(stdint.h HAVE_STDINT_H)
check_include_file(stddef.h HAVE_STDDEF_H)
check_include_file(inttypes.h HAVE_INTTYPES_H)
check_type_size("double" SIZEOF_DOUBLE)
check_type_size("float" SIZEOF_FLOAT)
check_type_size("long double" SIZEOF_LONG_DOUBLE)
if(WIN32)
set(int16_t 1)
set(int32_t 1)
set(int64_t 1)
set(int8_t 1)
set(uint16_t 1)
set(uint32_t 1)
set(uint64_t 1)
set(uint8_t 1)
endif(WIN32)
test_big_endian(IS_BIGENDIAN)
if(IS_BIGENDIAN)
set(WORDS_BIGENDIAN 1)
endif(IS_BIGENDIAN)
# configuration file
configure_file(amf-cmake.h.in ${CMAKE_BINARY_DIR}/amf.h)
include_directories(${CMAKE_BINARY_DIR})
install(
FILES ${CMAKE_BINARY_DIR}/amf.h
DESTINATION include/amf
)
# Visual C++ specific configuration
if(MSVC)
# use static library
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /MT")
# C runtime deprecation in Visual C++ 2005 and later
add_definitions(-D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE)
endif(MSVC)
add_subdirectory(src)
# tests
enable_testing()
add_subdirectory(tests)
#ifndef __AMF_H__
#define __AMF_H__
/* Name of package */
#define PACKAGE "@PACKAGE@"
/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT "@PACKAGE_BUGREPORT@"
/* Define to the full name of this package. */
#define PACKAGE_NAME "@PACKAGE_NAME@"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "@PACKAGE_STRING@"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "@PACKAGE_NAME@"
/* Define to the version of this package. */
#define PACKAGE_VERSION "@PACKAGE_VERSION@"
/* The size of `double', as computed by sizeof. */
#define SIZEOF_DOUBLE @SIZEOF_DOUBLE@
/* The size of `float', as computed by sizeof. */
#define SIZEOF_FLOAT @SIZEOF_FLOAT@
/* The size of `long double', as computed by sizeof. */
#define SIZEOF_LONG_DOUBLE @SIZEOF_LONG_DOUBLE@
/* Version number of package */
#define VERSION "@PACKAGE_VERSION@"
/* Define to 1 if you have the <sys/types.h> header file. */
#cmakedefine HAVE_SYS_TYPES_H
/* Define to 1 if you have the <stdint.h> header file. */
#cmakedefine HAVE_STDINT_H
/* Define to 1 if you have the <stddef.h> header file. */
#cmakedefine HAVE_STDDEF_H
/* Define to 1 if you have the <inttypes.h> header file. */
#cmakedefine HAVE_INTTYPES_H
/* Define to 1 if your processor stores words with the most significant byte
first (like Motorola and SPARC, unlike Intel and VAX). */
#cmakedefine WORDS_BIGENDIAN
/* Define to the type of an integer type of width exactly 16 bits if
such a type exists and the standard includes do not define it. */
#cmakedefine int16_t short int
/* Define to the type of an integer type of width exactly 32 bits if
such a type exists and the standard includes do not define it. */
#cmakedefine int32_t int
/* Define to the type of an integer type of width exactly 64 bits if
such a type exists and the standard includes do not define it. */
#cmakedefine int64_t long long int
/* Define to the type of an integer type of width exactly 8 bits if
such a type exists and the standard includes do not define it. */
#cmakedefine int8_t char
/* Define to the type of an unsigned integer type of width exactly 16 bits if
such a type exists and the standard includes do not define it. */
#cmakedefine uint16_t unsigned short int
/* Define to the type of an unsigned integer type of width exactly 32 bits if
such a type exists and the standard includes do not define it. */
#cmakedefine uint32_t unsigned int
/* Define to the type of an unsigned integer type of width exactly 64 bits if
such a type exists and the standard includes do not define it. */
#cmakedefine uint64_t unsigned long long int
/* Define to the type of an unsigned integer type of width exactly 8 bits if
such a type exists and the standard includes do not define it. */
#cmakedefine uint8_t unsigned char
#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#endif
#include <stdlib.h>
/* AMF number */
typedef
#if SIZEOF_FLOAT == 8
float
#elif SIZEOF_DOUBLE == 8
double
#elif SIZEOF_LONG_DOUBLE == 8
long double
#else
uint64_t
#endif
number64_t;
/* custom read/write function type */
typedef size_t (*read_proc_t)(void * out_buffer, size_t size, void * user_data);
typedef size_t (*write_proc_t)(const void * in_buffer, size_t size, void * user_data);
#endif /* __AMF_H__ */
set(libamf_src
amf0.c
amf0.h
hash.c
hash.h
io.c
io.h
ptrarray.c
ptrarray.h
types.c
types.h
${CMAKE_BINARY_DIR}/amf.h
)
add_library(amf ${libamf_src})
install(TARGETS amf
RUNTIME DESTINATION lib
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib
)
install(
FILES amf0.h amf3.h
DESTINATION include/amf
)
#ifndef __AMF_H__
#define __AMF_H__
#include <switch.h>
/* AMF number */
typedef double number64_t;
/* custom read/write function type */
typedef size_t (*read_proc_t)(void * out_buffer, size_t size, void * user_data);
typedef size_t (*write_proc_t)(const void * in_buffer, size_t size, void * user_data);
#endif /* __AMF_H__ */
差异被折叠。
差异被折叠。
#ifndef __AMF0_H__
#define __AMF0_H__
#include <stdio.h>
#include <time.h>
#include "amf.h"
/* AMF data types */
#define AMF0_TYPE_NUMBER 0x00
#define AMF0_TYPE_BOOLEAN 0x01
#define AMF0_TYPE_STRING 0x02
#define AMF0_TYPE_OBJECT 0x03
#define AMF0_TYPE_MOVIECLIP 0x04 /* reserved, not supported */
#define AMF0_TYPE_NULL 0x05
#define AMF0_TYPE_UNDEFINED 0x06
#define AMF0_TYPE_REFERENCE 0x07
#define AMF0_TYPE_ECMA_ARRAY 0x08
#define AMF0_TYPE_OBJECT_END 0x09
#define AMF0_TYPE_STRICT_ARRAY 0x0A
#define AMF0_TYPE_DATE 0x0B
#define AMF0_TYPE_LONG_STRING 0x0C
#define AMF0_TYPE_UNSUPPORTED 0x0D
#define AMF0_TYPE_RECORDSET 0x0E /* reserved, not supported */
#define AMF0_TYPE_XML_DOCUMENT 0x0F
#define AMF0_TYPE_TYPED_OBJECT 0x10
typedef struct __amf0_node * p_amf0_node;
/* string type */
typedef struct __amf0_string {
uint16_t size;
uint8_t * mbstr;
} amf0_string;
/* array type */
typedef struct __amf0_list {
uint32_t size;
p_amf0_node first_element;
p_amf0_node last_element;
} amf0_list;
/* date type */
typedef struct __amf0_date {
number64_t milliseconds;
int16_t timezone;
} amf0_date;
/* XML string type */
typedef struct __amf0_xmlstring {
uint32_t size;
uint8_t * mbstr;
} amf0_xmlstring;
/* class type */
typedef struct __amf0_class {
amf0_string name;
amf0_list elements;
} amf0_class;
/* structure encapsulating the various AMF objects */
typedef struct __amf0_data {
uint8_t type;
union {
number64_t number_data;
uint8_t boolean_data;
amf0_string string_data;
amf0_list list_data;
amf0_date date_data;
amf0_xmlstring xmlstring_data;
amf0_class class_data;
} u;
} amf0_data;
/* node used in lists, relies on amf0_data */
typedef struct __amf0_node {
amf0_data * data;
p_amf0_node prev;
p_amf0_node next;
} amf0_node;
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* read AMF data */
amf0_data * amf0_data_read(read_proc_t read_proc, void * user_data);
/* write AMF data */
size_t amf0_data_write(amf0_data * data, write_proc_t write_proc, void * user_data);
/* generic functions */
/* allocate an AMF data object */
amf0_data * amf0_data_new(uint8_t type);
/* load AMF data from buffer */
amf0_data * amf0_data_buffer_read(uint8_t * buffer, size_t maxbytes);
/* load AMF data from stream */
amf0_data * amf0_data_file_read(FILE * stream);
/* AMF data size */
size_t amf0_data_size(amf0_data * data);
/* write encoded AMF data into a buffer */
size_t amf0_data_buffer_write(amf0_data * data, uint8_t * buffer, size_t maxbytes);
/* write encoded AMF data into a stream */
size_t amf0_data_file_write(amf0_data * data, FILE * stream);
/* get the type of AMF data */
uint8_t amf0_data_get_type(amf0_data * data);
/* return a new copy of AMF data */
amf0_data * amf0_data_clone(amf0_data * data);
/* release the memory of AMF data */
void amf0_data_free(amf0_data * data);
/* dump AMF data into a stream as text */
void amf0_data_dump(FILE * stream, amf0_data * data, int indent_level);
/* number functions */
amf0_data * amf0_number_new(number64_t value);
number64_t amf0_number_get_value(amf0_data * data);
void amf0_number_set_value(amf0_data * data, number64_t value);
/* boolean functions */
amf0_data * amf0_boolean_new(uint8_t value);
uint8_t amf0_boolean_get_value(amf0_data * data);
void amf0_boolean_set_value(amf0_data * data, uint8_t value);
/* string functions */
amf0_data * amf0_string_new(uint8_t * str, uint16_t size);
amf0_data * amf0_str(const char * str);
uint16_t amf0_string_get_size(amf0_data * data);
uint8_t * amf0_string_get_uint8_ts(amf0_data * data);
/* object functions */
amf0_data * amf0_object_new(void);
uint32_t amf0_object_size(amf0_data * data);
amf0_data * amf0_object_add(amf0_data * data, const char * name, amf0_data * element);
amf0_data * amf0_object_get(amf0_data * data, const char * name);
amf0_data * amf0_object_set(amf0_data * data, const char * name, amf0_data * element);
amf0_data * amf0_object_delete(amf0_data * data, const char * name);
amf0_node * amf0_object_first(amf0_data * data);
amf0_node * amf0_object_last(amf0_data * data);
amf0_node * amf0_object_next(amf0_node * node);
amf0_node * amf0_object_prev(amf0_node * node);
amf0_data * amf0_object_get_name(amf0_node * node);
amf0_data * amf0_object_get_data(amf0_node * node);
/* null functions */
#define amf0_null_new() amf0_data_new(AMF0_TYPE_NULL)
/* undefined functions */
#define amf0_undefined_new() amf0_data_new(AMF0_TYPE_UNDEFINED)
/* associative array functions */
amf0_data * amf0_associative_array_new(void);
#define amf0_associative_array_size(d) amf0_object_size(d)
#define amf0_associative_array_add(d, n, e) amf0_object_add(d, n, e)
#define amf0_associative_array_get(d, n) amf0_object_get(d, n)
#define amf0_associative_array_set(d, n, e) amf0_object_set(d, n, e)
#define amf0_associative_array_delete(d, n) amf0_object_delete(d, n)
#define amf0_associative_array_first(d) amf0_object_first(d)
#define amf0_associative_array_last(d) amf0_object_last(d)
#define amf0_associative_array_next(n) amf0_object_next(n)
#define amf0_associative_array_prev(n) amf0_object_prev(n)
#define amf0_associative_array_get_name(n) amf0_object_get_name(n)
#define amf0_associative_array_get_data(n) amf0_object_get_data(n)
/* array functions */
amf0_data * amf0_array_new(void);
uint32_t amf0_array_size(amf0_data * data);
amf0_data * amf0_array_push(amf0_data * data, amf0_data * element);
amf0_data * amf0_array_pop(amf0_data * data);
amf0_node * amf0_array_first(amf0_data * data);
amf0_node * amf0_array_last(amf0_data * data);
amf0_node * amf0_array_next(amf0_node * node);
amf0_node * amf0_array_prev(amf0_node * node);
amf0_data * amf0_array_get(amf0_node * node);
amf0_data * amf0_array_get_at(amf0_data * data, uint32_t n);
amf0_data * amf0_array_delete(amf0_data * data, amf0_node * node);
amf0_data * amf0_array_insert_before(amf0_data * data, amf0_node * node, amf0_data * element);
amf0_data * amf0_array_insert_after(amf0_data * data, amf0_node * node, amf0_data * element);
/* date functions */
amf0_data * amf0_date_new(number64_t milliseconds, int16_t timezone);
number64_t amf0_date_get_milliseconds(amf0_data * data);
int16_t amf0_date_get_timezone(amf0_data * data);
time_t amf0_date_to_time_t(amf0_data * data);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __AMF0_H__ */
/* function common to all array types */
static void amf_list_init(amf_list * list) {
if (list != NULL) {
list->size = 0;
list->first_element = NULL;
list->last_element = NULL;
}
}
static amf_data * amf_list_push(amf_list * list, amf_data * data) {
amf_node * node = (amf_node*)malloc(sizeof(amf_node));
if (node != NULL) {
node->data = data;
node->next = NULL;
node->prev = NULL;
if (list->size == 0) {
list->first_element = node;
list->last_element = node;
}
else {
list->last_element->next = node;
node->prev = list->last_element;
list->last_element = node;
}
++(list->size);
return data;
}
return NULL;
}
static amf_data * amf_list_insert_before(amf_list * list, amf_node * node, amf_data * data) {
if (node != NULL) {
amf_node * new_node = (amf_node*)malloc(sizeof(amf_node));
if (new_node != NULL) {
new_node->next = node;
new_node->prev = node->prev;
if (node->prev != NULL) {
node->prev->next = new_node;
node->prev = new_node;
}
if (node == list->first_element) {
list->first_element = new_node;
}
++(list->size);
new_node->data = data;
return data;
}
}
return NULL;
}
static amf_data * amf_list_insert_after(amf_list * list, amf_node * node, amf_data * data) {
if (node != NULL) {
amf_node * new_node = (amf_node*)malloc(sizeof(amf_node));
if (new_node != NULL) {
new_node->next = node->next;
new_node->prev = node;
if (node->next != NULL) {
node->next->prev = new_node;
node->next = new_node;
}
if (node == list->last_element) {
list->last_element = new_node;
}
++(list->size);
new_node->data = data;
return data;
}
}
return NULL;
}
static amf_data * amf_list_delete(amf_list * list, amf_node * node) {
amf_data * data = NULL;
if (node != NULL) {
if (node->next != NULL) {
node->next->prev = node->prev;
}
if (node->prev != NULL) {
node->prev->next = node->next;
}
if (node == list->first_element) {
list->first_element = node->next;
}
if (node == list->last_element) {
list->last_element = node->prev;
}
data = node->data;
free(node);
--(list->size);
}
return data;
}
static amf_data * amf_list_get_at(amf_list * list, uint32 n) {
if (n < list->size) {
uint32 i;
amf_node * node = list->first_element;
for (i = 0; i < n; ++i) {
node = node->next;
}
return node->data;
}
return NULL;
}
static amf_data * amf_list_pop(amf_list * list) {
return amf_list_delete(list, list->last_element);
}
static amf_node * amf_list_first(amf_list * list) {
return list->first_element;
}
static amf_node * amf_list_last(amf_list * list) {
return list->last_element;
}
static void amf_list_clear(amf_list * list) {
amf_node * node = list->first_element;
while (node != NULL) {
amf_data_free(node->data);
amf_node * tmp = node;
node = node->next;
free(tmp);
}
list->size = 0;
}
typedef struct __amf_list {
uint32 size;
p_amf_node first_element;
p_amf_node last_element;
} amf_list;
\ No newline at end of file
#include <stdlib.h>
#include <string.h>
#include "hash.h"
#define assert(x)
/*static void *malloc_and_zero(int n){
void *p = malloc(n);
if( p ){
memset(p, 0, n);
}
return p;
}*/
/**
Create a hash table
*/
Hash * HashCreate(char copyKey) {
return HashCreateAlloc(copyKey, malloc, free);
}
Hash * HashCreateAlloc(char copyKey, void *(*xMalloc)(size_t), void (*xFree)(void *)) {
Hash * pHash = (Hash*)xMalloc(sizeof(Hash));
if (pHash != NULL) {
HashInit(pHash, copyKey, xMalloc, xFree);
return pHash;
}
else {
return 0;
}
}
/**
Erase the hash table
*/
void HashFree(Hash* pHash) {
pHash->xFree(pHash);
}
/*
insert a string key element
*/
void * HashInsertSz(Hash *pH, const char *pKey, void *data) {
return HashInsert(pH, pKey, (int) strlen(pKey)+1, data);
}
/*
find a string key element
*/
void * HashFindSz(const Hash* pH, const char *pKey) {
return HashFind(pH, pKey, (int) strlen(pKey)+1);
}
/* Turn bulk memory into a hash table object by initializing the
** fields of the Hash structure.
**
** "pNew" is a pointer to the hash table that is to be initialized.
** "copyKey" is true if the hash table should make its own private
** copy of keys and false if it should just use the supplied pointer.
*/
void HashInit(Hash* pNew, char copyKey, void *(*xMalloc)(size_t), void (*xFree)(void *)){
assert( pNew!=0 );
pNew->copyKey = copyKey;
pNew->first = 0;
pNew->count = 0;
pNew->htsize = 0;
pNew->ht = 0;
pNew->xMalloc = xMalloc;
pNew->xFree = xFree;
}
/* Remove all entries from a hash table. Reclaim all memory.
** Call this routine to delete a hash table or to reset a hash table
** to the empty state.
*/
void HashClear(Hash *pH){
HashElem *elem; /* For looping over all elements of the table */
assert( pH!=0 );
elem = pH->first;
pH->first = 0;
if( pH->ht ) pH->xFree(pH->ht);
pH->ht = 0;
pH->htsize = 0;
while( elem ){
HashElem *next_elem = elem->next;
if( pH->copyKey && elem->pKey ){
pH->xFree(elem->pKey);
}
pH->xFree(elem);
elem = next_elem;
}
pH->count = 0;
}
/*
** Hash and comparison functions
*/
static int binHash(const void *pKey, int nKey){
int h = 0;
const char *z = (const char *)pKey;
while( nKey-- > 0 ){
h = (h<<3) ^ h ^ *(z++);
}
return h & 0x7fffffff;
}
static int binCompare(const void *pKey1, int n1, const void *pKey2, int n2){
if( n1!=n2 ) return 1;
return memcmp(pKey1,pKey2,n1);
}
/* Link an element into the hash table
*/
static void insertElement(
Hash *pH, /* The complete hash table */
struct _ht *pEntry, /* The entry into which pNew is inserted */
HashElem *pNew /* The element to be inserted */
){
HashElem *pHead; /* First element already in pEntry */
pHead = pEntry->chain;
if( pHead ){
pNew->next = pHead;
pNew->prev = pHead->prev;
if( pHead->prev ){ pHead->prev->next = pNew; }
else { pH->first = pNew; }
pHead->prev = pNew;
}else{
pNew->next = pH->first;
if( pH->first ){ pH->first->prev = pNew; }
pNew->prev = 0;
pH->first = pNew;
}
pEntry->count++;
pEntry->chain = pNew;
}
/* Resize the hash table so that it cantains "new_size" buckets.
** "new_size" must be a power of 2. The hash table might fail
** to resize if malloc fails.
*/
static void rehash(Hash *pH, int new_size){
struct _ht *new_ht; /* The new hash table */
HashElem *elem, *next_elem; /* For looping over existing elements */
assert( (new_size & (new_size-1))==0 );
new_ht = (struct _ht *)pH->xMalloc( new_size*sizeof(struct _ht) );
if( new_ht==0 ) return;
if( pH->ht ) pH->xFree(pH->ht);
pH->ht = new_ht;
pH->htsize = new_size;
for(elem=pH->first, pH->first=0; elem; elem = next_elem){
int h = binHash(elem->pKey, elem->nKey) & (new_size-1);
next_elem = elem->next;
insertElement(pH, &new_ht[h], elem);
}
}
/* This function (for internal use only) locates an element in an
** hash table that matches the given key. The hash for this key has
** already been computed and is passed as the 4th parameter.
*/
static HashElem *findElementGivenHash(
const Hash *pH, /* The pH to be searched */
const void *pKey, /* The key we are searching for */
int nKey,
int h /* The hash for this key. */
){
HashElem *elem; /* Used to loop thru the element list */
int count; /* Number of elements left to test */
if( pH->ht ){
struct _ht *pEntry = &pH->ht[h];
elem = pEntry->chain;
count = pEntry->count;
while( count-- && elem ){
if( binCompare(elem->pKey,elem->nKey,pKey,nKey)==0 ){
return elem;
}
elem = elem->next;
}
}
return 0;
}
/* Remove a single entry from the hash table given a pointer to that
** element and a hash on the element's key.
*/
static void removeElementGivenHash(
Hash *pH, /* The pH containing "elem" */
HashElem* elem, /* The element to be removed from the pH */
int h /* Hash value for the element */
){
struct _ht *pEntry;
if( elem->prev ){
elem->prev->next = elem->next;
}else{
pH->first = elem->next;
}
if( elem->next ){
elem->next->prev = elem->prev;
}
pEntry = &pH->ht[h];
if( pEntry->chain==elem ){
pEntry->chain = elem->next;
}
pEntry->count--;
if( pEntry->count<=0 ){
pEntry->chain = 0;
}
if( pH->copyKey && elem->pKey ){
pH->xFree(elem->pKey);
}
pH->xFree( elem );
pH->count--;
if( pH->count<=0 ){
assert( pH->first==0 );
assert( pH->count==0 );
HashClear(pH);
}
}
/* Attempt to locate an element of the hash table pH with a key
** that matches pKey,nKey. Return the data for this element if it is
** found, or NULL if there is no match.
*/
void * HashFind(const Hash *pH, const void *pKey, int nKey){
int h; /* A hash on key */
HashElem *elem; /* The element that matches key */
if( pH==0 || pH->ht==0 ) return 0;
h = binHash(pKey,nKey);
assert( (pH->htsize & (pH->htsize-1))==0 );
elem = findElementGivenHash(pH,pKey,nKey, h & (pH->htsize-1));
return elem ? elem->data : 0;
}
/* Insert an element into the hash table pH. The key is pKey,nKey
** and the data is "data".
**
** If no element exists with a matching key, then a new
** element is created. A copy of the key is made if the copyKey
** flag is set. NULL is returned.
**
** If another element already exists with the same key, then the
** new data replaces the old data and the old data is returned.
** The key is not copied in this instance. If a malloc fails, then
** the new data is returned and the hash table is unchanged.
**
** If the "data" parameter to this function is NULL, then the
** element corresponding to "key" is removed from the hash table.
*/
void * HashInsert(
Hash *pH, /* The hash table to insert into */
const void *pKey, /* The key */
int nKey, /* Number of bytes in the key */
void *data /* The data */
){
int hraw; /* Raw hash value of the key */
int h; /* the hash of the key modulo hash table size */
HashElem *elem; /* Used to loop thru the element list */
HashElem *new_elem; /* New element added to the pH */
assert( pH!=0 );
hraw = binHash(pKey, nKey);
assert( (pH->htsize & (pH->htsize-1))==0 );
h = hraw & (pH->htsize-1);
elem = findElementGivenHash(pH,pKey,nKey,h);
if( elem ){
void *old_data = elem->data;
if( data==0 ){
removeElementGivenHash(pH,elem,h);
}else{
elem->data = data;
}
return old_data;
}
if( data==0 ) return 0;
new_elem = (HashElem*)pH->xMalloc( sizeof(HashElem) );
if( new_elem==0 ) return data;
if( pH->copyKey && pKey!=0 ){
new_elem->pKey = pH->xMalloc( nKey );
if( new_elem->pKey==0 ){
pH->xFree(new_elem);
return data;
}
memcpy((void*)new_elem->pKey, pKey, nKey);
}else{
new_elem->pKey = (void*)pKey;
}
new_elem->nKey = nKey;
pH->count++;
if( pH->htsize==0 ){
rehash(pH,8);
if( pH->htsize==0 ){
pH->count = 0;
pH->xFree(new_elem);
return data;
}
}
if( pH->count > pH->htsize ){
rehash(pH,pH->htsize*2);
}
assert( pH->htsize>0 );
assert( (pH->htsize & (pH->htsize-1))==0 );
h = hraw & (pH->htsize-1);
insertElement(pH, &pH->ht[h], new_elem);
new_elem->data = data;
return 0;
}
#ifndef _HASH_H_
#define _HASH_H_
/* Forward declarations of structures. */
typedef struct Hash Hash;
typedef struct HashElem HashElem;
/* A complete hash table is an instance of the following structure.
** The internals of this structure are intended to be opaque -- client
** code should not attempt to access or modify the fields of this structure
** directly. Change this structure only by using the routines below.
** However, many of the "procedures" and "functions" for modifying and
** accessing this structure are really macros, so we can't really make
** this structure opaque.
*/
struct Hash {
char copyKey; /* True if copy of key made on insert */
int count; /* Number of entries in this table */
HashElem *first; /* The first element of the array */
void *(*xMalloc)(size_t); /* malloc() function to use */
void (*xFree)(void *); /* free() function to use */
int htsize; /* Number of buckets in the hash table */
struct _ht { /* the hash table */
int count; /* Number of entries with this hash */
HashElem *chain; /* Pointer to first entry with this hash */
} *ht;
};
/* Each element in the hash table is an instance of the following
** structure. All elements are stored on a single doubly-linked list.
**
** Again, this structure is intended to be opaque, but it can't really
** be opaque because it is used by macros.
*/
struct HashElem {
HashElem *next, *prev; /* Next and previous elements in the table */
void *data; /* Data associated with this element */
void *pKey; int nKey; /* Key associated with this element */
};
/*
** Access routines. To delete, insert a NULL pointer.
*/
Hash * HashCreate(char copyKey);
Hash * HashCreateAlloc(char copyKey, void *(*xMalloc)(size_t), void (*xFree)(void *));
void HashFree(Hash*);
void HashInit(Hash*, char copyKey, void *(*xMalloc)(size_t), void (*xFree)(void *));
void * HashInsert(Hash*, const void *pKey, int nKey, void *pData);
void * HashFind(const Hash*, const void *pKey, int nKey);
void HashClear(Hash*);
void * HashInsertSz(Hash*, const char *pKey, void *pData);
void * HashFindSz(const Hash*, const char *pKey);
/*
Element deletion macro
*/
#define HashDelete(H, K, N) (HashInsert(H, K, N, 0))
/*
** Macros for looping over all elements of a hash table. The idiom is
** like this:
**
** Hash h;
** HashElem *p;
** ...
** for(p=HashFirst(&h); p; p=HashNext(p)){
** SomeStructure *pData = HashData(p);
** // do something with pData
** }
*/
#define HashFirst(H) ((H)->first)
#define HashNext(E) ((E)->next)
#define HashData(E) ((E)->data)
#define HashKey(E) ((E)->pKey)
#define HashKeysize(E) ((E)->nKey)
/*
** Number of entries in a hash table
*/
#define HashCount(H) ((H)->count)
/*
more macros
*/
typedef struct Hash* hash_table;
typedef struct HashElem* hash_elem;
#define hash_create() (HashCreate(1))
#define hash_insert(H, K, V) (HashInsertSz(H, K, V))
#define hash_find(H, K) (HashFindSz(H, K))
#define hash_delete(H, K) (HashInsertSz(H, K, 0))
#define hash_clear(H) (HashClear(H))
#define hash_free(H) (HashFree(H))
#define hash_first(H) ((H)->first)
#define hash_next(E) ((E)->next)
#define hash_data(E) ((E)->data)
#define hash_key(E) ((E)->pKey)
#define hash_keysize(E) ((E)->nKey)
#define hash_count(H) ((H)->count)
#endif /* _HASH_H_ */
#include <stdio.h>
#include <string.h>
#include "io.h"
/* callback function to mimic fread using a memory buffer */
size_t buffer_read(void * out_buffer, size_t size, void * user_data) {
buffer_context * ctxt = (buffer_context *)user_data;
if (ctxt->current_address >= ctxt->start_address &&
ctxt->current_address + size <= ctxt->start_address + ctxt->buffer_size) {
memcpy(out_buffer, ctxt->current_address, size);
ctxt->current_address += size;
return size;
}
else {
return 0;
}
}
/* callback function to mimic fwrite using a memory buffer */
size_t buffer_write(const void * in_buffer, size_t size, void * user_data) {
buffer_context * ctxt = (buffer_context *)user_data;
if (ctxt->current_address >= ctxt->start_address &&
ctxt->current_address + size <= ctxt->start_address + ctxt->buffer_size) {
memcpy(ctxt->current_address, in_buffer, size);
ctxt->current_address += size;
return size;
}
else {
return 0;
}
}
/* callback function to read data from a file stream */
size_t file_read(void * out_buffer, size_t size, void * user_data) {
return fread(out_buffer, sizeof(uint8_t), size, (FILE *)user_data);
}
/* callback function to write data to a file stream */
size_t file_write(const void * in_buffer, size_t size, void * user_data) {
return fwrite(in_buffer, sizeof(uint8_t), size, (FILE *)user_data);
}
#ifndef __IO_H__
#define __IO_H__
#include "amf.h"
/* structure used to mimic a stream with a memory buffer */
typedef struct __buffer_context {
uint8_t * start_address;
uint8_t * current_address;
size_t buffer_size;
} buffer_context;
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* callback function to mimic fread using a memory buffer */
size_t buffer_read(void * out_buffer, size_t size, void * user_data);
/* callback function to mimic fwrite using a memory buffer */
size_t buffer_write(const void * in_buffer, size_t size, void * user_data);
/* callback function to read data from a file stream */
size_t file_read(void * out_buffer, size_t size, void * user_data);
/* callback function to write data to a file stream */
size_t file_write(const void * in_buffer, size_t size, void * user_data);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __IO_H__ */
#include "ptrarray.h"
#include <string.h>
/**
Customize default capacity
*/
#ifndef PTRARRAY_DEFAULT_CAPACITY
# define PTRARRAY_DEFAULT_CAPACITY 5
#endif
/**
Enable array security checking
*/
/* #define PTRARRAY_SECURITY_CHECKS */
/**
Customize memory allocation routines
*/
#ifndef PTRARRAY_MALLOC
# define PTRARRAY_MALLOC malloc
#endif
#ifndef PTRARRAY_FREE
# define PTRARRAY_FREE free
#endif
#ifndef PTRARRAY_REALLOC
# define PTRARRAY_REALLOC realloc
#endif
/**
This function doubles the current capacity
of the given dynamic array.
*/
static int ptrarray_grow(ptrarray * array) {
void * new_mem;
size_t new_capacity;
#ifdef PTRARRAY_SECURITY_CHECKS
if (array == NULL)
return;
#endif
new_capacity = array->capacity * 2;
new_mem = PTRARRAY_REALLOC(array->data, new_capacity * sizeof(void*));
if (new_mem != NULL) {
array->data = new_mem;
array->capacity = new_capacity;
return 1;
}
else {
return 0;
}
}
void ptrarray_init(ptrarray * array, size_t initial_capacity, data_free_proc free_proc) {
if (free_proc == NULL) {
free_proc = PTRARRAY_FREE;
}
array->data_free = free_proc;
if (initial_capacity <= 0) {
initial_capacity = PTRARRAY_DEFAULT_CAPACITY;
}
array->capacity = initial_capacity;
array->data = PTRARRAY_MALLOC(initial_capacity * sizeof(void*));
array->size = 0;
}
/*size_t ptrarray_capacity(ptrarray * array) {
return array->capacity;
}*/
/*size_t ptrarray_size(ptrarray * array) {
return array->size;
}*/
/*int ptrarray_empty(ptrarray * array) {
return !((array)->size);
}*/
void ptrarray_reserve(ptrarray * array, size_t new_capacity) {
void * new_mem;
#ifdef PTRARRAY_SECURITY_CHECKS
if (array == NULL)
return;
#endif
if (new_capacity > array->capacity) {
new_mem = PTRARRAY_REALLOC(array->data, new_capacity * sizeof(void*));
if (new_mem != NULL) {
array->data = new_mem;
array->capacity = new_capacity;
}
}
else if (new_capacity < array->capacity) {
new_capacity = (new_capacity < array->size) ? array->size : new_capacity;
new_capacity = (new_capacity < PTRARRAY_DEFAULT_CAPACITY) ? PTRARRAY_DEFAULT_CAPACITY : new_capacity;
new_mem = PTRARRAY_REALLOC(array->data, new_capacity * sizeof(void*));
if (new_mem != NULL) {
array->data = new_mem;
array->capacity = new_capacity;
}
}
}
void ptrarray_compact(ptrarray * array) {
size_t new_capacity;
void * new_mem;
#ifdef PTRARRAY_SECURITY_CHECKS
if (array == NULL)
return;
#endif
new_capacity = (array->size < PTRARRAY_DEFAULT_CAPACITY) ? PTRARRAY_DEFAULT_CAPACITY : array->size;
new_mem = PTRARRAY_REALLOC(array->data, new_capacity * sizeof(void*));
if (new_mem != NULL) {
array->data = new_mem;
array->capacity = new_capacity;
}
}
void ptrarray_push(ptrarray * array, void * data) {
#ifdef PTRARRAY_SECURITY_CHECKS
if (array == NULL)
return;
#endif
if (array->size == array->capacity) {
if (!ptrarray_grow(array)) {
return;
}
}
array->data[array->size++] = data;
}
void * ptrarray_pop(ptrarray * array) {
#ifdef PTRARRAY_SECURITY_CHECKS
if (array == NULL)
return NULL;
#endif
if (ptrarray_empty(array)) {
return NULL;
}
return array->data[array->size--];
}
void ptrarray_insert(ptrarray * array, size_t position, void * data) {
void ** src_pos;
#ifdef PTRARRAY_SECURITY_CHECKS
if (array == NULL)
return;
#endif
if (array->size > position) {
if (array->size == array->capacity) {
if (!ptrarray_grow(array)) {
return;
}
}
src_pos = array->data + position;
memmove(src_pos + 1, src_pos, array->size - position);
*src_pos = data;
}
}
void ptrarray_prepend(ptrarray * array, void * data);
void * ptrarray_replace(ptrarray * array, size_t position, void * data);
void * ptrarray_remove(ptrarray * array, size_t position);
void ptrarray_clear(ptrarray * array);
void * ptrarray_first(ptrarray * array);
void * ptrarray_last(ptrarray * array);
void * ptrarray_get(size_t position);
void ptrarray_destroy(ptrarray * array) {
}
#ifndef __PTRARRAY_H__
#define __PTRARRAY_H__
#include <stdlib.h>
typedef void (*data_free_proc)(void *);
typedef struct __ptrarray {
size_t capacity;
size_t size;
void ** data;
data_free_proc data_free;
} ptrarray;
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
void ptrarray_init(ptrarray * array, size_t initial_capacity, data_free_proc free_proc);
/*size_t ptrarray_capacity(ptrarray * array);*/
#define ptrarray_capacity(a) ((a)->capacity)
/*size_t ptrarray_size(ptrarray * array);*/
#define ptrarray_size(a) ((a)->size)
/*int ptrarray_empty(ptrarray * array);*/
#define ptrarray_empty(a) (!((a)->size))
void ptrarray_reserve(ptrarray * array, size_t new_capacity);
void ptrarray_compact(ptrarray * array);
void ptrarray_push(ptrarray * array, void * data);
void * ptrarray_pop(ptrarray * array);
void ptrarray_insert(ptrarray * array, size_t position, void * data);
void ptrarray_prepend(ptrarray * array, void * data);
void * ptrarray_replace(ptrarray * array, size_t position, void * data);
void * ptrarray_remove(ptrarray * array, size_t position);
void ptrarray_clear(ptrarray * array);
void * ptrarray_first(ptrarray * array);
void * ptrarray_last(ptrarray * array);
void * ptrarray_get(size_t position);
void ptrarray_destroy(ptrarray * array);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __PTRARRAY_H__ */
/*
$Id: types.c 1 2009-11-13 00:04:24Z noirotm $
FLV Metadata updater
Copyright (C) 2007, 2008 Marc Noirot <marc.noirot AT gmail.com>
This file is part of FLVMeta.
FLVMeta is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
FLVMeta is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with FLVMeta; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "types.h"
#ifndef WORDS_BIGENDIAN
/* swap 64 bits doubles */
typedef union __convert_u {
uint64_t i;
number64_t f;
} convert_u;
number64_t swap_number64(number64_t n) {
convert_u c;
c.f = n;
c.i = (((c.i & 0x00000000000000FFULL) << 56) |
((c.i & 0x000000000000FF00ULL) << 40) |
((c.i & 0x0000000000FF0000ULL) << 24) |
((c.i & 0x00000000FF000000ULL) << 8) |
((c.i & 0x000000FF00000000ULL) >> 8) |
((c.i & 0x0000FF0000000000ULL) >> 24) |
((c.i & 0x00FF000000000000ULL) >> 40) |
((c.i & 0xFF00000000000000ULL) >> 56));
return c.f;
}
#endif /* !WORDS_BIGENDIAN */
/*
$Id: types.h 1 2009-11-13 00:04:24Z noirotm $
FLV Metadata updater
Copyright (C) 2007, 2008 Marc Noirot <marc.noirot AT gmail.com>
This file is part of FLVMeta.
FLVMeta is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
FLVMeta is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with FLVMeta; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __TYPES_H__
#define __TYPES_H__
#include "amf.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#ifdef WORDS_BIGENDIAN
# define swap_uint16(x) (x)
# define swap_int16(x) (x)
# define swap_uint32(x) (x)
# define swap_number64(x) (x)
#else /* WORDS_BIGENDIAN */
/* swap 16 bits integers */
# define swap_uint16(x) ((((x) & 0x00FFU) << 8) | (((x) & 0xFF00U) >> 8))
# define swap_sint16(x) ((((x) & 0x00FF) << 8) | (((x) & 0xFF00) >> 8))
/* swap 32 bits integers */
# define swap_uint32(x) ((((x) & 0x000000FFU) << 24) | \
(((x) & 0x0000FF00U) << 8) | \
(((x) & 0x00FF0000U) >> 8) | \
(((x) & 0xFF000000U) >> 24))
/* swap 64 bits doubles */
number64_t swap_number64(number64_t);
#endif /* WORDS_BIGENDIAN */
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __TYPES_H__ */
include_directories(${CMAKE_SOURCE_DIR}/src)
add_executable(amf0_demo amf0_demo.c)
add_dependencies(amf0_demo amf)
#include <stdio.h>
#include "amf0.h"
#include "io.h"
#include "types.h"
int main() {
amf0_data * test;
test = amf0_object_new();
amf0_object_add(test, "toto", amf0_str("une chaine de caracteres"));
amf0_object_add(test, "test_bool", amf0_boolean_new(1));
amf0_data_dump(stdout, test, 0);
amf0_data_free(test);
}
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论