Init projects
This commit is contained in:
commit
c0026875f8
|
@ -0,0 +1,53 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <openssl/evp.h>
|
||||||
|
#include <openssl/sha.h>
|
||||||
|
|
||||||
|
#include "log.h"
|
||||||
|
#include "crypto.h"
|
||||||
|
|
||||||
|
const char* rand_string(char* pRandKey, int ilen)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
static const char keyTbl[] = "0123456789abcdefghigklmnopqrstuvwxyzABCDEFGHIGKLMNOPQRSTUVWXYZ";
|
||||||
|
int maxSed = strlen(keyTbl);
|
||||||
|
|
||||||
|
if(pRandKey == NULL || ilen <= 0)
|
||||||
|
{
|
||||||
|
LOG_EX(LOG_Debug, "Input params error(%d)\n", ilen);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
srand(time(NULL));
|
||||||
|
|
||||||
|
for(i = 0; i < ilen; i++)
|
||||||
|
{
|
||||||
|
pRandKey[i] = keyTbl[rand() % maxSed];
|
||||||
|
}
|
||||||
|
|
||||||
|
return (const char*)pRandKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* hash_sha1(unsigned char* pData, int iSize, char* pHashCode)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
unsigned char sha1[SHA1_DIGEST_LENGTH];
|
||||||
|
EVP_MD_CTX evpCtx;
|
||||||
|
|
||||||
|
memset(sha1, 0, SHA1_DIGEST_LENGTH);
|
||||||
|
|
||||||
|
len = iSize;
|
||||||
|
|
||||||
|
EVP_MD_CTX_init(&evpCtx);
|
||||||
|
EVP_DigestInit_ex(&evpCtx, EVP_sha1(), NULL);
|
||||||
|
EVP_DigestUpdate(&evpCtx, pData, len);
|
||||||
|
EVP_DigestFinal_ex(&evpCtx, sha1, &len);
|
||||||
|
EVP_MD_CTX_cleanup(&evpCtx);
|
||||||
|
|
||||||
|
print_hex_dump_bytes("SHA1", DUMP_PREFIX_OFFSET, sha1, SHA1_DIGEST_LENGTH);
|
||||||
|
|
||||||
|
return (const char*)IHW_bin2hex(pHashCode, sha1, len);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,554 @@
|
||||||
|
/*
|
||||||
|
* A generic kernel FIFO implementation
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009/2010 Stefani Seibold <stefani@seibold.net>
|
||||||
|
*
|
||||||
|
* This program 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.
|
||||||
|
*
|
||||||
|
* This program 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 this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#if 0
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/export.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <linux/err.h>
|
||||||
|
#include <linux/log2.h>
|
||||||
|
#include <linux/uaccess.h>
|
||||||
|
#include <linux/kfifo.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "fifo.h"
|
||||||
|
|
||||||
|
#define is_power_of_2(x) ((x) != 0 && (((x) & ((x) - 1)) == 0))
|
||||||
|
#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
|
||||||
|
#define min(x,y) ({ \
|
||||||
|
typeof(x) _x = (x); \
|
||||||
|
typeof(y) _y = (y); \
|
||||||
|
(void) (&_x == &_y); \
|
||||||
|
_x < _y ? _x : _y; })
|
||||||
|
|
||||||
|
#define max(x,y) ({ \
|
||||||
|
typeof(x) _x = (x); \
|
||||||
|
typeof(y) _y = (y); \
|
||||||
|
(void) (&_x == &_y); \
|
||||||
|
_x > _y ? _x : _y; })
|
||||||
|
|
||||||
|
//#define EINVAL (1)
|
||||||
|
//#define ENOMEM (2)
|
||||||
|
|
||||||
|
static inline int fls(int x);
|
||||||
|
|
||||||
|
#if defined(PLATFORM_R16) || defined(PLATFORM_R311)
|
||||||
|
static inline int constant_fls(int x)
|
||||||
|
{
|
||||||
|
int r = 32;
|
||||||
|
|
||||||
|
if (!x)
|
||||||
|
return 0;
|
||||||
|
if (!(x & 0xffff0000u)) {
|
||||||
|
x <<= 16;
|
||||||
|
r -= 16;
|
||||||
|
}
|
||||||
|
if (!(x & 0xff000000u)) {
|
||||||
|
x <<= 8;
|
||||||
|
r -= 8;
|
||||||
|
}
|
||||||
|
if (!(x & 0xf0000000u)) {
|
||||||
|
x <<= 4;
|
||||||
|
r -= 4;
|
||||||
|
}
|
||||||
|
if (!(x & 0xc0000000u)) {
|
||||||
|
x <<= 2;
|
||||||
|
r -= 2;
|
||||||
|
}
|
||||||
|
if (!(x & 0x80000000u)) {
|
||||||
|
x <<= 1;
|
||||||
|
r -= 1;
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fls64(unsigned long long x)
|
||||||
|
{
|
||||||
|
unsigned int h = x >> 32;
|
||||||
|
if (h)
|
||||||
|
return fls(h) + 32;
|
||||||
|
return fls(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int fls(int x)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (__builtin_constant_p(x))
|
||||||
|
return constant_fls(x);
|
||||||
|
|
||||||
|
asm("clz\t%0, %1" : "=r" (ret) : "r" (x));
|
||||||
|
ret = 32 - ret;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef PLATFORM_CPU
|
||||||
|
#define __fls(x) (fls(x) - 1)
|
||||||
|
static __always_inline int fls64(unsigned long x)
|
||||||
|
{
|
||||||
|
if (x == 0)
|
||||||
|
return 0;
|
||||||
|
return __fls(x) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int fls(int x)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
|
||||||
|
long tmp = -1;
|
||||||
|
asm("bsrl %1,%0"
|
||||||
|
: "=r" (r)
|
||||||
|
: "rm" (x), "0" (tmp));
|
||||||
|
#if 0
|
||||||
|
#ifdef CONFIG_X86_64
|
||||||
|
/*
|
||||||
|
* AMD64 says BSRL won't clobber the dest reg if x==0; Intel64 says the
|
||||||
|
* dest reg is undefined if x==0, but their CPU architect says its
|
||||||
|
* value is written to set it to the same as before, except that the
|
||||||
|
* top 32 bits will be cleared.
|
||||||
|
*
|
||||||
|
* We cannot do this on 32 bits because at the very least some
|
||||||
|
* 486 CPUs did not behave this way.
|
||||||
|
*/
|
||||||
|
long tmp = -1;
|
||||||
|
asm("bsrl %1,%0"
|
||||||
|
: "=r" (r)
|
||||||
|
: "rm" (x), "0" (tmp));
|
||||||
|
#elif defined(CONFIG_X86_CMOV)
|
||||||
|
asm("bsrl %1,%0\n\t"
|
||||||
|
"cmovzl %2,%0"
|
||||||
|
: "=&r" (r) : "rm" (x), "rm" (-1));
|
||||||
|
#else
|
||||||
|
asm("bsrl %1,%0\n\t"
|
||||||
|
"jnz 1f\n\t"
|
||||||
|
"movl $-1,%0\n"
|
||||||
|
"1:" : "=r" (r) : "rm" (x));
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
return r + 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/*
|
||||||
|
* internal helper to calculate the unused elements in a fifo
|
||||||
|
*/
|
||||||
|
static inline unsigned int kfifo_unused(struct __kfifo *fifo)
|
||||||
|
{
|
||||||
|
return (fifo->mask + 1) - (fifo->in - fifo->out);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline unsigned fls_long(unsigned long l)
|
||||||
|
{
|
||||||
|
if (sizeof(l) == 4)
|
||||||
|
return fls(l);
|
||||||
|
return fls64(l);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long roundup_pow_of_two(unsigned long n)
|
||||||
|
{
|
||||||
|
return 1UL << (fls_long(n));
|
||||||
|
}
|
||||||
|
|
||||||
|
int __kfifo_alloc(struct __kfifo *fifo, unsigned int size, unsigned int esize)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* round down to the next power of 2, since our 'let the indices
|
||||||
|
* wrap' technique works only in this case.
|
||||||
|
*/
|
||||||
|
if (!is_power_of_2(size))
|
||||||
|
size = roundup_pow_of_two(size);
|
||||||
|
|
||||||
|
fprintf(stdout, "+++++++++++kfifo malloc size = %u\n", size);
|
||||||
|
|
||||||
|
fifo->in = 0;
|
||||||
|
fifo->out = 0;
|
||||||
|
fifo->esize = esize;
|
||||||
|
|
||||||
|
if (size < 2) {
|
||||||
|
fifo->data = NULL;
|
||||||
|
fifo->mask = 0;
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
fifo->data = malloc(size * esize);
|
||||||
|
|
||||||
|
if (!fifo->data) {
|
||||||
|
fifo->mask = 0;
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
fifo->mask = size - 1;
|
||||||
|
uv_mutex_init(&fifo->lock);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void __kfifo_free(struct __kfifo *fifo)
|
||||||
|
{
|
||||||
|
free(fifo->data);
|
||||||
|
fifo->in = 0;
|
||||||
|
fifo->out = 0;
|
||||||
|
fifo->esize = 0;
|
||||||
|
fifo->data = NULL;
|
||||||
|
fifo->mask = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int __kfifo_init(struct __kfifo *fifo, void *buffer,
|
||||||
|
unsigned int size, unsigned int esize)
|
||||||
|
{
|
||||||
|
size /= esize;
|
||||||
|
|
||||||
|
if (!is_power_of_2(size))
|
||||||
|
size = roundup_pow_of_two(size);
|
||||||
|
|
||||||
|
fifo->in = 0;
|
||||||
|
fifo->out = 0;
|
||||||
|
fifo->esize = esize;
|
||||||
|
fifo->data = buffer;
|
||||||
|
|
||||||
|
if (size < 2) {
|
||||||
|
fifo->mask = 0;
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
fifo->mask = size - 1;
|
||||||
|
uv_mutex_init(&fifo->lock);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void kfifo_copy_in(struct __kfifo *fifo, const void *src,
|
||||||
|
unsigned int len, unsigned int off)
|
||||||
|
{
|
||||||
|
unsigned int size = fifo->mask + 1;
|
||||||
|
unsigned int esize = fifo->esize;
|
||||||
|
unsigned int l;
|
||||||
|
|
||||||
|
off &= fifo->mask;
|
||||||
|
if (esize != 1) {
|
||||||
|
off *= esize;
|
||||||
|
size *= esize;
|
||||||
|
len *= esize;
|
||||||
|
}
|
||||||
|
l = min(len, size - off);
|
||||||
|
|
||||||
|
memcpy(fifo->data + off, src, l);
|
||||||
|
memcpy(fifo->data, src + l, len - l);
|
||||||
|
/*
|
||||||
|
* make sure that the data in the fifo is up to date before
|
||||||
|
* incrementing the fifo->in index counter
|
||||||
|
*/
|
||||||
|
// smp_wmb();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int __kfifo_in(struct __kfifo *fifo,
|
||||||
|
const void *buf, unsigned int len)
|
||||||
|
{
|
||||||
|
unsigned int l;
|
||||||
|
|
||||||
|
l = kfifo_unused(fifo);
|
||||||
|
if (len > l)
|
||||||
|
len = l;
|
||||||
|
|
||||||
|
kfifo_copy_in(fifo, buf, len, fifo->in);
|
||||||
|
fifo->in += len;
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void kfifo_copy_out(struct __kfifo *fifo, void *dst,
|
||||||
|
unsigned int len, unsigned int off)
|
||||||
|
{
|
||||||
|
unsigned int size = fifo->mask + 1;
|
||||||
|
unsigned int esize = fifo->esize;
|
||||||
|
unsigned int l;
|
||||||
|
|
||||||
|
off &= fifo->mask;
|
||||||
|
if (esize != 1) {
|
||||||
|
off *= esize;
|
||||||
|
size *= esize;
|
||||||
|
len *= esize;
|
||||||
|
}
|
||||||
|
l = min(len, size - off);
|
||||||
|
|
||||||
|
if (dst) {
|
||||||
|
memcpy(dst, fifo->data + off, l);
|
||||||
|
memcpy(dst + l, fifo->data, len - l);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* make sure that the data is copied before
|
||||||
|
* incrementing the fifo->out index counter
|
||||||
|
*/
|
||||||
|
// smp_wmb();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int __kfifo_out_peek(struct __kfifo *fifo,
|
||||||
|
void *buf, unsigned int len)
|
||||||
|
{
|
||||||
|
unsigned int l;
|
||||||
|
|
||||||
|
l = fifo->in - fifo->out;
|
||||||
|
if (len > l)
|
||||||
|
len = l;
|
||||||
|
|
||||||
|
kfifo_copy_out(fifo, buf, len, fifo->out);
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int __kfifo_out(struct __kfifo *fifo,
|
||||||
|
void *buf, unsigned int len)
|
||||||
|
{
|
||||||
|
len = __kfifo_out_peek(fifo, buf, len);
|
||||||
|
fifo->out += len;
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
static unsigned long kfifo_copy_from_user(struct __kfifo *fifo,
|
||||||
|
const void *from, unsigned int len, unsigned int off,
|
||||||
|
unsigned int *copied)
|
||||||
|
{
|
||||||
|
unsigned int size = fifo->mask + 1;
|
||||||
|
unsigned int esize = fifo->esize;
|
||||||
|
unsigned int l;
|
||||||
|
unsigned long ret;
|
||||||
|
|
||||||
|
off &= fifo->mask;
|
||||||
|
if (esize != 1) {
|
||||||
|
off *= esize;
|
||||||
|
size *= esize;
|
||||||
|
len *= esize;
|
||||||
|
}
|
||||||
|
l = min(len, size - off);
|
||||||
|
|
||||||
|
ret = memcpy(fifo->data + off, from, l);
|
||||||
|
if (unlikely(ret))
|
||||||
|
ret = DIV_ROUND_UP(ret + len - l, esize);
|
||||||
|
else {
|
||||||
|
ret = memcpy(fifo->data, from + l, len - l);
|
||||||
|
if (unlikely(ret))
|
||||||
|
ret = DIV_ROUND_UP(ret, esize);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* make sure that the data in the fifo is up to date before
|
||||||
|
* incrementing the fifo->in index counter
|
||||||
|
*/
|
||||||
|
// smp_wmb();
|
||||||
|
*copied = len - ret;
|
||||||
|
/* return the number of elements which are not copied */
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int __kfifo_from_user(struct __kfifo *fifo, const void __user *from,
|
||||||
|
unsigned long len, unsigned int *copied)
|
||||||
|
{
|
||||||
|
unsigned int l;
|
||||||
|
unsigned long ret;
|
||||||
|
unsigned int esize = fifo->esize;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (esize != 1)
|
||||||
|
len /= esize;
|
||||||
|
|
||||||
|
l = kfifo_unused(fifo);
|
||||||
|
if (len > l)
|
||||||
|
len = l;
|
||||||
|
|
||||||
|
ret = kfifo_copy_from_user(fifo, from, len, fifo->in, copied);
|
||||||
|
if (unlikely(ret)) {
|
||||||
|
len -= ret;
|
||||||
|
err = -EFAULT;
|
||||||
|
} else
|
||||||
|
err = 0;
|
||||||
|
fifo->in += len;
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned long kfifo_copy_to_user(struct __kfifo *fifo, void __user *to,
|
||||||
|
unsigned int len, unsigned int off, unsigned int *copied)
|
||||||
|
{
|
||||||
|
unsigned int l;
|
||||||
|
unsigned long ret;
|
||||||
|
unsigned int size = fifo->mask + 1;
|
||||||
|
unsigned int esize = fifo->esize;
|
||||||
|
|
||||||
|
off &= fifo->mask;
|
||||||
|
if (esize != 1) {
|
||||||
|
off *= esize;
|
||||||
|
size *= esize;
|
||||||
|
len *= esize;
|
||||||
|
}
|
||||||
|
l = min(len, size - off);
|
||||||
|
|
||||||
|
ret = memcpy(to, fifo->data + off, l);
|
||||||
|
if (unlikely(ret))
|
||||||
|
ret = DIV_ROUND_UP(ret + len - l, esize);
|
||||||
|
else {
|
||||||
|
ret = memcpy(to + l, fifo->data, len - l);
|
||||||
|
if (unlikely(ret))
|
||||||
|
ret = DIV_ROUND_UP(ret, esize);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* make sure that the data is copied before
|
||||||
|
* incrementing the fifo->out index counter
|
||||||
|
*/
|
||||||
|
//smp_wmb();
|
||||||
|
*copied = len - ret;
|
||||||
|
/* return the number of elements which are not copied */
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int __kfifo_to_user(struct __kfifo *fifo, void __user *to,
|
||||||
|
unsigned long len, unsigned int *copied)
|
||||||
|
{
|
||||||
|
unsigned int l;
|
||||||
|
unsigned long ret;
|
||||||
|
unsigned int esize = fifo->esize;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (esize != 1)
|
||||||
|
len /= esize;
|
||||||
|
|
||||||
|
l = fifo->in - fifo->out;
|
||||||
|
if (len > l)
|
||||||
|
len = l;
|
||||||
|
ret = kfifo_copy_to_user(fifo, to, len, fifo->out, copied);
|
||||||
|
if (unlikely(ret)) {
|
||||||
|
len -= ret;
|
||||||
|
err = -EFAULT;
|
||||||
|
} else
|
||||||
|
err = 0;
|
||||||
|
fifo->out += len;
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
unsigned int __kfifo_max_r(unsigned int len, unsigned int recsize)
|
||||||
|
{
|
||||||
|
unsigned int max = (1 << (recsize << 3)) - 1;
|
||||||
|
|
||||||
|
if (len > max)
|
||||||
|
return max;
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define __KFIFO_PEEK(data, out, mask) \
|
||||||
|
((data)[(out) & (mask)])
|
||||||
|
/*
|
||||||
|
* __kfifo_peek_n internal helper function for determinate the length of
|
||||||
|
* the next record in the fifo
|
||||||
|
*/
|
||||||
|
static unsigned int __kfifo_peek_n(struct __kfifo *fifo, unsigned int recsize)
|
||||||
|
{
|
||||||
|
unsigned int l;
|
||||||
|
unsigned int mask = fifo->mask;
|
||||||
|
unsigned char *data = fifo->data;
|
||||||
|
|
||||||
|
l = __KFIFO_PEEK(data, fifo->out, mask);
|
||||||
|
|
||||||
|
if (--recsize)
|
||||||
|
l |= __KFIFO_PEEK(data, fifo->out + 1, mask) << 8;
|
||||||
|
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define __KFIFO_POKE(data, in, mask, val) \
|
||||||
|
( \
|
||||||
|
(data)[(in) & (mask)] = (unsigned char)(val) \
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* __kfifo_poke_n internal helper function for storeing the length of
|
||||||
|
* the record into the fifo
|
||||||
|
*/
|
||||||
|
static void __kfifo_poke_n(struct __kfifo *fifo, unsigned int n, unsigned int recsize)
|
||||||
|
{
|
||||||
|
unsigned int mask = fifo->mask;
|
||||||
|
unsigned char *data = fifo->data;
|
||||||
|
|
||||||
|
__KFIFO_POKE(data, fifo->in, mask, n);
|
||||||
|
|
||||||
|
if (recsize > 1)
|
||||||
|
__KFIFO_POKE(data, fifo->in + 1, mask, n >> 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int __kfifo_len_r(struct __kfifo *fifo, unsigned int recsize)
|
||||||
|
{
|
||||||
|
return __kfifo_peek_n(fifo, recsize);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int __kfifo_in_r(struct __kfifo *fifo, const void *buf,
|
||||||
|
unsigned int len, unsigned int recsize)
|
||||||
|
{
|
||||||
|
if (len + recsize > kfifo_unused(fifo))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
__kfifo_poke_n(fifo, len, recsize);
|
||||||
|
|
||||||
|
kfifo_copy_in(fifo, buf, len, fifo->in + recsize);
|
||||||
|
fifo->in += len + recsize;
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned int kfifo_out_copy_r(struct __kfifo *fifo,
|
||||||
|
void *buf, unsigned int len, unsigned int recsize, unsigned int *n)
|
||||||
|
{
|
||||||
|
*n = __kfifo_peek_n(fifo, recsize);
|
||||||
|
|
||||||
|
if (len > *n)
|
||||||
|
len = *n;
|
||||||
|
|
||||||
|
kfifo_copy_out(fifo, buf, len, fifo->out + recsize);
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int __kfifo_out_peek_r(struct __kfifo *fifo, void *buf,
|
||||||
|
unsigned int len, unsigned int recsize)
|
||||||
|
{
|
||||||
|
unsigned int n;
|
||||||
|
|
||||||
|
if (fifo->in == fifo->out)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return kfifo_out_copy_r(fifo, buf, len, recsize, &n);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int __kfifo_out_r(struct __kfifo *fifo, void *buf,
|
||||||
|
unsigned int len, unsigned int recsize)
|
||||||
|
{
|
||||||
|
unsigned int n;
|
||||||
|
|
||||||
|
if (fifo->in == fifo->out)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
len = kfifo_out_copy_r(fifo, buf, len, recsize, &n);
|
||||||
|
fifo->out += n + recsize;
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
void __kfifo_skip_r(struct __kfifo *fifo, unsigned int recsize)
|
||||||
|
{
|
||||||
|
unsigned int n;
|
||||||
|
|
||||||
|
n = __kfifo_peek_n(fifo, recsize);
|
||||||
|
fifo->out += n + recsize;
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "hal_mtk.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
|
#define CFG_SAVE_PATH ("/var/mqttcfg/mqtt_cfg.cfg")
|
||||||
|
|
||||||
|
const char* hal_get_device_id(void)
|
||||||
|
{
|
||||||
|
return "547e1a1d7a7e5ced38ee8a3989fb8f97";
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* hal_get_device_secret(void)
|
||||||
|
{
|
||||||
|
return "266726e07bf3210192e0868d9f7315f7";
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* hal_get_device_name(void)
|
||||||
|
{
|
||||||
|
return "e0d7930776e745508ef930e1b0efaf65";
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* hal_get_device_iot_id(void)
|
||||||
|
{
|
||||||
|
return "f65250e202664a229446b6bd2d6bccc4";
|
||||||
|
}
|
|
@ -0,0 +1,112 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <curl/curl.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
#include "uthash/utstring.h"
|
||||||
|
#include "hal_mtk.h"
|
||||||
|
#include "crypto.h"
|
||||||
|
#include "http.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
|
#define HTTPS_RANDOM_LEN (14)
|
||||||
|
|
||||||
|
static size_t __writeDataCb(void *pData, size_t size, size_t nmemb, void *pParams)
|
||||||
|
{
|
||||||
|
int iMemSize = size * nmemb;
|
||||||
|
|
||||||
|
if(iMemSize > 0)
|
||||||
|
{
|
||||||
|
LOG_EX(LOG_Debug, "Receive: %s\n", (char*)pData);
|
||||||
|
}
|
||||||
|
|
||||||
|
return iMemSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* calc_register_checksum(char* pSecKey, char* pRandKey, int timeStamp, char* pCheckSum)
|
||||||
|
{
|
||||||
|
UT_string* pMsg;
|
||||||
|
|
||||||
|
utstring_new(pMsg);
|
||||||
|
utstring_printf(pMsg, "%s%s%d", pSecKey, pRandKey, timeStamp);
|
||||||
|
|
||||||
|
return hash_sha1((unsigned char*)utstring_body(pMsg), utstring_len(pMsg), pCheckSum);
|
||||||
|
}
|
||||||
|
|
||||||
|
int device_register(void)
|
||||||
|
{
|
||||||
|
CURLcode ret;
|
||||||
|
CURL* pCurl = NULL;
|
||||||
|
struct curl_slist* pList = NULL;
|
||||||
|
const char* pPostMsg = "";
|
||||||
|
UT_string* pProduct, *pNonce, *pCurTime, *pChecksum;
|
||||||
|
char randKey[HTTPS_RANDOM_LEN + 1];
|
||||||
|
char checkSum[64];
|
||||||
|
time_t timsStamp = time(NULL);
|
||||||
|
|
||||||
|
pCurl = curl_easy_init();
|
||||||
|
|
||||||
|
if(pCurl == NULL)
|
||||||
|
{
|
||||||
|
LOG_EX(LOG_Error, "Create CURL handle error\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(checkSum, 0, 64);
|
||||||
|
memset(randKey, 0, HTTPS_RANDOM_LEN + 1);
|
||||||
|
rand_string(randKey, HTTPS_RANDOM_LEN);
|
||||||
|
|
||||||
|
utstring_new(pProduct);
|
||||||
|
utstring_new(pNonce);
|
||||||
|
utstring_new(pCurTime);
|
||||||
|
utstring_new(pChecksum);
|
||||||
|
|
||||||
|
calc_register_checksum(NETEASE_PRODUCT_SEC, randKey, timsStamp, checkSum);
|
||||||
|
|
||||||
|
utstring_printf(pProduct, "ProductKey: %s", NETEASE_PRODUCT_KEY);
|
||||||
|
utstring_printf(pNonce, "Nonce: %s", randKey);
|
||||||
|
utstring_printf(pCurTime, "CurTime: %d", timsStamp);
|
||||||
|
utstring_printf(pChecksum, "CheckSum: %s", checkSum);
|
||||||
|
|
||||||
|
pList = curl_slist_append(pList, utstring_body(pProduct));
|
||||||
|
pList = curl_slist_append(pList, utstring_body(pNonce));
|
||||||
|
pList = curl_slist_append(pList, utstring_body(pCurTime));
|
||||||
|
pList = curl_slist_append(pList, utstring_body(pChecksum));
|
||||||
|
pList = curl_slist_append(pList, "Content-Type:application/json;charset=UTF-8");
|
||||||
|
|
||||||
|
curl_easy_setopt(pCurl, CURLOPT_URL, NETEASE_API_SERVER);
|
||||||
|
curl_easy_setopt(pCurl, CURLOPT_WRITEFUNCTION, __writeDataCb);
|
||||||
|
curl_easy_setopt(pCurl, CURLOPT_NOPROGRESS, 1L);
|
||||||
|
curl_easy_setopt(pCurl, CURLOPT_USERAGENT, "libcurl-agent/1.0");
|
||||||
|
curl_easy_setopt(pCurl, CURLOPT_HTTPHEADER, pList);
|
||||||
|
curl_easy_setopt(pCurl, CURLOPT_POSTFIELDS, NULL);
|
||||||
|
curl_easy_setopt(pCurl, CURLOPT_POSTFIELDSIZE, (long)0);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
curl_easy_setopt(pCurl, CURLOPT_CAINFO, "/etc/ssl/certs/ca-certificates.crt");
|
||||||
|
curl_easy_setopt(pCurl, CURLOPT_SSL_VERIFYPEER, 1L);
|
||||||
|
#else
|
||||||
|
curl_easy_setopt(pCurl, CURLOPT_SSL_VERIFYPEER, 0L);
|
||||||
|
#endif
|
||||||
|
ret = curl_easy_perform(pCurl);
|
||||||
|
|
||||||
|
curl_slist_free_all(pList);
|
||||||
|
utstring_free(pProduct);
|
||||||
|
utstring_free(pNonce);
|
||||||
|
utstring_free(pCurTime);
|
||||||
|
utstring_free(pChecksum);
|
||||||
|
|
||||||
|
if(ret != CURLE_OK)
|
||||||
|
{
|
||||||
|
LOG_EX(LOG_Error, "Run Http POST error: %s\n", curl_easy_strerror(ret));
|
||||||
|
curl_easy_cleanup(pCurl);
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
curl_easy_cleanup(pCurl);
|
||||||
|
LOG_EX(LOG_Debug, "HTTP Post Finished\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,294 @@
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "cjson/s2j.h"
|
||||||
|
#include "protocol.h"
|
||||||
|
#include "log.h"
|
||||||
|
//#include "jsprase.h"
|
||||||
|
|
||||||
|
static char* __jsonSafeDecodeStr(cJSON* pJson, const char* pTags)
|
||||||
|
{
|
||||||
|
cJSON* pItem = cJSON_GetObjectItem(pJson, pTags);
|
||||||
|
|
||||||
|
if(pItem)
|
||||||
|
{
|
||||||
|
return strdup(pItem->valuestring);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return strdup("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* __pro2Json(void* pData)
|
||||||
|
{
|
||||||
|
PCLOUND_API pPro = (PCLOUND_API)pData;
|
||||||
|
const char* pJsonS;
|
||||||
|
|
||||||
|
s2j_create_json_obj(jObject);
|
||||||
|
|
||||||
|
s2j_json_set_basic_element(jObject, pPro, int, cmdId);
|
||||||
|
//s2j_json_set_basic_element(jObject, pPro, int, ver);
|
||||||
|
s2j_json_set_basic_element(jObject, pPro, int, cryptoType);
|
||||||
|
s2j_json_set_basic_element(jObject, pPro, int, timeStamp);
|
||||||
|
|
||||||
|
if(pPro->msgContent)
|
||||||
|
{
|
||||||
|
s2j_json_set_basic_element(jObject, pPro, string, msgContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
pJsonS = cJSON_Print(jObject);
|
||||||
|
|
||||||
|
cJSON_Delete(jObject);
|
||||||
|
|
||||||
|
return pJsonS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void* __json2pro(const char* pJsonS)
|
||||||
|
{
|
||||||
|
cJSON* pItem = NULL;
|
||||||
|
PCLOUND_API pApi = NULL;
|
||||||
|
cJSON *pRoot = cJSON_Parse(pJsonS);
|
||||||
|
|
||||||
|
if(pRoot == NULL)
|
||||||
|
{
|
||||||
|
LOG_EX(LOG_Error, "Json Format Error: [%s]\n", pJsonS);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pApi = (PCLOUND_API)malloc(sizeof(CLOUND_API));
|
||||||
|
|
||||||
|
if(pApi == NULL)
|
||||||
|
{
|
||||||
|
LOG_EX(LOG_Error, "Malloc CLOUND_API Error\n");
|
||||||
|
cJSON_Delete(pRoot);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pApi->cmdId = cJSON_GetObjectItem(pRoot, "cmdId")->valueint;
|
||||||
|
//pApi->cmdId = cJSON_GetObjectItem(pRoot, "ver")->valueint;
|
||||||
|
pApi->cryptoType = cJSON_GetObjectItem(pRoot, "cryptoType")->valueint;
|
||||||
|
pApi->timeStamp = cJSON_GetObjectItem(pRoot, "timeStamp")->valueint;
|
||||||
|
|
||||||
|
pItem = cJSON_GetObjectItem(pRoot, "msgContent");
|
||||||
|
|
||||||
|
if(pItem)
|
||||||
|
{
|
||||||
|
char* pMsgContent = cJSON_GetObjectItem(pRoot, "msgContent")->valuestring;
|
||||||
|
pApi->msgContent = (char *)malloc(strlen(pMsgContent) + 1);
|
||||||
|
|
||||||
|
if(pApi->msgContent == NULL)
|
||||||
|
{
|
||||||
|
LOG_EX(LOG_Error, "Malloc MsgContent(%u) Memory Error\n", strlen(pMsgContent) + 1);
|
||||||
|
cJSON_Delete(pRoot);
|
||||||
|
free(pApi);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(pApi->msgContent, 0, strlen(pMsgContent) + 1);
|
||||||
|
strcpy(pApi->msgContent, pMsgContent);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pApi->msgContent = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
cJSON_Delete(pRoot);
|
||||||
|
return pApi;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* __bypass2Json(void* pData)
|
||||||
|
{
|
||||||
|
PBYPASS_INFO pInfo = (PBYPASS_INFO)pData;
|
||||||
|
const char* pJsonS;
|
||||||
|
|
||||||
|
s2j_create_json_obj(jObject);
|
||||||
|
|
||||||
|
if(pInfo->mcuCmd)
|
||||||
|
{
|
||||||
|
s2j_json_set_basic_element(jObject, pInfo, string, mcuCmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
pJsonS = cJSON_Print(jObject);
|
||||||
|
|
||||||
|
cJSON_Delete(jObject);
|
||||||
|
|
||||||
|
return pJsonS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void* __json2bypass(const char* pJsonS)
|
||||||
|
{
|
||||||
|
PBYPASS_INFO pInfo = NULL;
|
||||||
|
cJSON *pRoot = cJSON_Parse(pJsonS);
|
||||||
|
|
||||||
|
if(pRoot == NULL)
|
||||||
|
{
|
||||||
|
LOG_EX(LOG_Error, "Json Format Error: [%s]\n", pJsonS);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pInfo = (PBYPASS_INFO)malloc(sizeof(BYPASS_INFO));
|
||||||
|
|
||||||
|
if(pInfo == NULL)
|
||||||
|
{
|
||||||
|
LOG_EX(LOG_Error, "Malloc BYPASS_INFO Error\n");
|
||||||
|
cJSON_Delete(pRoot);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pInfo->mcuCmd = __jsonSafeDecodeStr(pRoot, "mcuCmd");
|
||||||
|
|
||||||
|
cJSON_Delete(pRoot);
|
||||||
|
return pInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* __shadow2Json(void* pData)
|
||||||
|
{
|
||||||
|
PSHADOW_UPDATE pInfo = (PSHADOW_UPDATE)pData;
|
||||||
|
cJSON *pRoot, *pStatus, *pReports;
|
||||||
|
|
||||||
|
const char* pJsonS;
|
||||||
|
|
||||||
|
pRoot = cJSON_CreateObject();
|
||||||
|
|
||||||
|
cJSON_AddNumberToObject(pRoot, "version", pInfo->version);
|
||||||
|
cJSON_AddItemToObject(pRoot, "method", cJSON_CreateString(pInfo->method));
|
||||||
|
|
||||||
|
pStatus = cJSON_CreateObject();
|
||||||
|
pReports = cJSON_CreateObject();
|
||||||
|
|
||||||
|
cJSON_AddItemToObject(pRoot, "state", pStatus);
|
||||||
|
cJSON_AddItemToObject(pStatus, "reported", pReports);
|
||||||
|
cJSON_AddItemToObject(pReports, "mcuCmd", cJSON_CreateString(pInfo->state.reported.mcuCmd));
|
||||||
|
|
||||||
|
pJsonS = cJSON_Print(pRoot);
|
||||||
|
|
||||||
|
cJSON_Delete(pRoot);
|
||||||
|
|
||||||
|
return pJsonS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void* json2RegDev(const char* pJsonS)
|
||||||
|
{
|
||||||
|
PREGIST_DEVICE pInfo = NULL;
|
||||||
|
cJSON *pItem = NULL;
|
||||||
|
cJSON *pRoot = cJSON_Parse(pJsonS);
|
||||||
|
|
||||||
|
if(pRoot == NULL)
|
||||||
|
{
|
||||||
|
LOG_EX(LOG_Error, "Json Format Error: [%s]\n", pJsonS);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pInfo = (PREGIST_DEVICE)malloc(sizeof(REGIST_DEVICE));
|
||||||
|
|
||||||
|
if(pInfo == NULL)
|
||||||
|
{
|
||||||
|
LOG_EX(LOG_Error, "Malloc REGIST_DEVICE Error\n");
|
||||||
|
cJSON_Delete(pRoot);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(pInfo, 0, sizeof(REGIST_DEVICE));
|
||||||
|
|
||||||
|
pInfo->code = cJSON_GetObjectItem(pRoot, "code")->valueint;;
|
||||||
|
pInfo->msg = __jsonSafeDecodeStr(pRoot, "msg");
|
||||||
|
pInfo->requestId = __jsonSafeDecodeStr(pRoot, "requestId");
|
||||||
|
|
||||||
|
pItem = cJSON_GetObjectItem(pRoot, "data");
|
||||||
|
|
||||||
|
if(pItem)
|
||||||
|
{
|
||||||
|
pInfo->data.IotId = __jsonSafeDecodeStr(pItem, "IotId");
|
||||||
|
pInfo->data.DeviceName = __jsonSafeDecodeStr(pItem, "DeviceName");
|
||||||
|
pInfo->data.ProductKey = __jsonSafeDecodeStr(pItem, "ProductKey");
|
||||||
|
pInfo->data.DeviceSecret = __jsonSafeDecodeStr(pItem, "DeviceSecret");
|
||||||
|
}
|
||||||
|
|
||||||
|
cJSON_Delete(pRoot);
|
||||||
|
return pInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSON_ENGINE g_jSonEngine[] =
|
||||||
|
{
|
||||||
|
{JE_PROMAIN, __pro2Json, __json2pro, NULL},
|
||||||
|
{JE_BYPASS, __bypass2Json, __json2bypass, NULL},
|
||||||
|
{JE_SHADOWUP, __shadow2Json, NULL, NULL},
|
||||||
|
{JE_REGDEVICE, NULL, json2RegDev, NULL},
|
||||||
|
};
|
||||||
|
|
||||||
|
void* Json2Struct(const char* pJsonStr, JSON_ENGINE_TYPE type, int cryptoType, int* pErr)
|
||||||
|
{
|
||||||
|
if(pJsonStr == NULL || pErr == NULL)
|
||||||
|
{
|
||||||
|
if(pErr)
|
||||||
|
{
|
||||||
|
*pErr = -ERR_INPUT_PARAMS;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(type < 0 || type >= JE_MAX)
|
||||||
|
{
|
||||||
|
*pErr = -ERR_INPUT_PARAMS;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
*pErr = 0;
|
||||||
|
|
||||||
|
//LOG_EX(LOG_Debug, "Json:\n%s\n", pJsonStr);
|
||||||
|
|
||||||
|
if(g_jSonEngine[type].jsonDecodeCb)
|
||||||
|
{
|
||||||
|
void *pStruct = g_jSonEngine[type].jsonDecodeCb(pJsonStr);
|
||||||
|
|
||||||
|
if(CRYPTO_NONE != cryptoType && g_jSonEngine[type].cryptoCb)
|
||||||
|
{
|
||||||
|
g_jSonEngine[type].cryptoCb(pStruct, cryptoType, CRYPTO_ENCODE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (pStruct);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* Struct2Json(void* pStruct, JSON_ENGINE_TYPE type, int cryptoType, int* pErr)
|
||||||
|
{
|
||||||
|
if(pStruct == NULL || pErr == NULL)
|
||||||
|
{
|
||||||
|
if(pErr)
|
||||||
|
{
|
||||||
|
*pErr = -ERR_INPUT_PARAMS;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(type < 0 || type >= JE_MAX)
|
||||||
|
{
|
||||||
|
*pErr = -ERR_INPUT_PARAMS;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
*pErr = 0;
|
||||||
|
|
||||||
|
if(CRYPTO_NONE != cryptoType && g_jSonEngine[type].cryptoCb)
|
||||||
|
{
|
||||||
|
g_jSonEngine[type].cryptoCb(pStruct, cryptoType, CRYPTO_DECODE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(g_jSonEngine[type].jsonEncodeCb)
|
||||||
|
{
|
||||||
|
const char *pJsongStr = g_jSonEngine[type].jsonEncodeCb(pStruct);
|
||||||
|
|
||||||
|
LOG_EX(LOG_Debug, "Json: \n%s\n", pJsongStr);
|
||||||
|
return (pJsongStr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the struct2json Library.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2015, Armink, <armink.ztl@gmail.com>
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
* a copy of this software and associated documentation files (the
|
||||||
|
* 'Software'), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* Function: Initialize interface for this library.
|
||||||
|
* Created on: 2015-10-14
|
||||||
|
*/
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <cjson/s2j.h>
|
||||||
|
|
||||||
|
S2jHook s2jHook = {
|
||||||
|
.malloc_fn = malloc,
|
||||||
|
.free_fn = free,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct2json library initialize
|
||||||
|
* @note It will initialize cJSON library hooks.
|
||||||
|
*/
|
||||||
|
void s2j_init(S2jHook *hook) {
|
||||||
|
/* initialize cJSON library */
|
||||||
|
cJSON_InitHooks((cJSON_Hooks *)hook);
|
||||||
|
/* initialize hooks */
|
||||||
|
if (hook) {
|
||||||
|
s2jHook.malloc_fn = (hook->malloc_fn) ? hook->malloc_fn : malloc;
|
||||||
|
s2jHook.free_fn = (hook->free_fn) ? hook->free_fn : free;
|
||||||
|
} else {
|
||||||
|
s2jHook.malloc_fn = malloc;
|
||||||
|
s2jHook.free_fn = free;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,168 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <mosquitto.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
#include "uthash/utstring.h"
|
||||||
|
|
||||||
|
#include "mqtt.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include "hal_mtk.h"
|
||||||
|
|
||||||
|
static struct mosquitto *g_pMosq = NULL;
|
||||||
|
static pthread_t g_mqttThread;
|
||||||
|
static int g_isMqttConnected = FALSE;
|
||||||
|
|
||||||
|
static void __mqtt_connected_cb(struct mosquitto* pMosq, void* obj, int rc)
|
||||||
|
{
|
||||||
|
g_isMqttConnected = TRUE;
|
||||||
|
LOG_EX(LOG_Debug, "Connect to MQTT Server: %d\n", rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __mqtt_publish_cb(struct mosquitto* pMosq, void* obj, int mid)
|
||||||
|
{
|
||||||
|
LOG_EX(LOG_Debug, "Publish MQTT Message: %d\n", mid);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __mqtt_log_cb(struct mosquitto* pMosq, void* obj, int level, const char* pMsg)
|
||||||
|
{
|
||||||
|
LOG_EX(LOG_Debug, "MQTT Log Message[%d]: %s\n", level, pMsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __mqtt_disconnect_cb(struct mosquitto* pMosq, void* obj, int rc)
|
||||||
|
{
|
||||||
|
g_isMqttConnected = FALSE;
|
||||||
|
LOG_EX(LOG_Debug, "Disonnect to MQTT Server: %d\n", rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __mqtt_subscribe_cb(struct mosquitto* pMosq, void* obj, int mid, int qos_count, const int* granted_qos)
|
||||||
|
{
|
||||||
|
LOG_EX(LOG_Debug, "MQTT Subscribe: mid = %d, qos = %d\n", mid, qos_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __mqtt_unsubscribe_cb(struct mosquitto* pMosq, void* obj, int mid)
|
||||||
|
{
|
||||||
|
LOG_EX(LOG_Debug, "MQTT Subscribe: mid = %d\n", mid);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __mqtt_message_cb(struct mosquitto* pMosq, void* obj, const struct mosquitto_message* pMsg)
|
||||||
|
{
|
||||||
|
LOG_EX(LOG_Debug, "Receive MQTT Message:\nMid: %d\nMessage Size: %d\nMessage: %s\n",
|
||||||
|
pMsg->mid, pMsg->payloadlen, (char*)pMsg->payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __mqtt_connect_init(void)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
int major, minor, rev;
|
||||||
|
struct mosquitto *pMosq = NULL;
|
||||||
|
UT_string* pString = NULL;
|
||||||
|
|
||||||
|
g_isMqttConnected = FALSE;
|
||||||
|
|
||||||
|
rc = mosquitto_lib_version(&major, &minor, &rev);
|
||||||
|
|
||||||
|
LOG_EX(LOG_Debug, "rc:%d, major:%d, minor:%d, rev:%d\n", rc, major, minor, rev);
|
||||||
|
|
||||||
|
pMosq = mosquitto_new(hal_get_device_id(), TRUE, NULL);
|
||||||
|
|
||||||
|
if(!pMosq)
|
||||||
|
{
|
||||||
|
LOG_EX(LOG_Error, "Create MQTT Object Error\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = mosquitto_tls_opts_set(pMosq, TRUE, "tlsv1.2", NULL);
|
||||||
|
|
||||||
|
if(rc)
|
||||||
|
{
|
||||||
|
LOG_EX(LOG_Error, "Set TLS Options Failed: %d\n", rc);
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = mosquitto_tls_set(pMosq, MQTT_CA_FILE_PATH, NULL, NULL, NULL, NULL);
|
||||||
|
|
||||||
|
if(rc)
|
||||||
|
{
|
||||||
|
LOG_EX(LOG_Error, "Set TLS Failed: %d\n", rc);
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = mosquitto_tls_insecure_set(pMosq, TRUE);
|
||||||
|
|
||||||
|
if(rc)
|
||||||
|
{
|
||||||
|
LOG_EX(LOG_Error, "Set Insecure Failed: %d\n", rc);
|
||||||
|
return -4;
|
||||||
|
}
|
||||||
|
|
||||||
|
mosquitto_connect_callback_set(pMosq, __mqtt_connected_cb);
|
||||||
|
mosquitto_publish_callback_set(pMosq, __mqtt_publish_cb);
|
||||||
|
mosquitto_log_callback_set(pMosq, __mqtt_log_cb);
|
||||||
|
mosquitto_disconnect_callback_set(pMosq, __mqtt_disconnect_cb);
|
||||||
|
mosquitto_subscribe_callback_set(pMosq, __mqtt_subscribe_cb);
|
||||||
|
mosquitto_unsubscribe_callback_set(pMosq, __mqtt_unsubscribe_cb);
|
||||||
|
mosquitto_message_callback_set(pMosq, __mqtt_message_cb);
|
||||||
|
|
||||||
|
utstring_new(pString);
|
||||||
|
|
||||||
|
utstring_printf(pString, "%s&%s", hal_get_device_name(), NETEASE_PRODUCT_KEY);
|
||||||
|
rc = mosquitto_username_pw_set(pMosq, utstring_body(pString), hal_get_device_secret());
|
||||||
|
|
||||||
|
if(rc)
|
||||||
|
{
|
||||||
|
utstring_free(pString);
|
||||||
|
LOG_EX(LOG_Error, "Set Username And Password error: %d\n", rc);
|
||||||
|
return -5;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = mosquitto_connect(pMosq, NETEASE_MQTT_SERVER, NETEASE_MQTT_PORT, 10);
|
||||||
|
|
||||||
|
if(rc)
|
||||||
|
{
|
||||||
|
utstring_free(pString);
|
||||||
|
LOG_EX(LOG_Error, "Can not connect to MQTT Server: %d\n", rc);
|
||||||
|
return -6;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_EX(LOG_Debug, "MQTT Connect OK\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
utstring_renew(pString);
|
||||||
|
|
||||||
|
utstring_printf(pString, "/%s/%s/get", NETEASE_PRODUCT_KEY, hal_get_device_name());
|
||||||
|
mosquitto_subscribe(pMosq, NULL, utstring_body(pString), 1);
|
||||||
|
|
||||||
|
g_pMosq = pMosq;
|
||||||
|
g_isMqttConnected = TRUE;
|
||||||
|
utstring_free(pString);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void* __mqtt_serverce_cb(void *p)
|
||||||
|
{
|
||||||
|
while(TRUE)
|
||||||
|
{
|
||||||
|
__mqtt_connect_init();
|
||||||
|
|
||||||
|
while(g_isMqttConnected)
|
||||||
|
{
|
||||||
|
mosquitto_loop(g_pMosq, 1000, 1);
|
||||||
|
usleep(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
mosquitto_disconnect(g_pMosq);
|
||||||
|
mosquitto_destroy(g_pMosq);
|
||||||
|
|
||||||
|
sleep(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mqtt_proxy_setup(void)
|
||||||
|
{
|
||||||
|
pthread_create(&g_mqttThread, NULL, __mqtt_serverce_cb, NULL);
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
SHELL := /bin/sh
|
||||||
|
|
||||||
|
DIS_BUILD_WARRING ?= FALSE
|
||||||
|
EN_MAKE_MSG ?= TRUE
|
||||||
|
|
||||||
|
ifeq ($(EN_MAKE_MSG), TRUE)
|
||||||
|
MAKE_FLAGS :=
|
||||||
|
else
|
||||||
|
MAKE_FLAGS := -s
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifneq ($(OPT), clean)
|
||||||
|
ifneq ($(OPT), install)
|
||||||
|
MAKE_FLAGS += -j$(shell cat /proc/cpuinfo | grep processor | wc -l)
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(DIR), )
|
||||||
|
DEMO_INS_PATH := ./release
|
||||||
|
else
|
||||||
|
DEMO_INS_PATH := $(DIR)
|
||||||
|
endif
|
||||||
|
|
||||||
|
.PHONY : mqtt_proxy
|
||||||
|
|
||||||
|
all: mqtt_proxy
|
||||||
|
|
||||||
|
|
||||||
|
mqtt_proxy:
|
||||||
|
ifeq ($(OPT), clean)
|
||||||
|
@make $(MAKE_FLAGS) -C build -f Makefile.app.cross cleanall MAKE_TARGET=mqtt_proxy
|
||||||
|
else ifeq ($(OPT), install)
|
||||||
|
@make $(MAKE_FLAGS) -C build -f Makefile.app.cross install DIR=$(DIR) MAKE_TARGET=mqtt_proxy
|
||||||
|
else
|
||||||
|
@make all $(MAKE_FLAGS) -C build -f Makefile.app.cross DISABLE_WARRING=$(DIS_BUILD_WARRING) MAKE_TARGET=mqtt_proxy
|
||||||
|
endif
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
# target name, the target name must have the same name of c source file
|
||||||
|
TARGET_NAME=mqtt_proxy
|
||||||
|
|
||||||
|
# target
|
||||||
|
# for linux module driver: KO
|
||||||
|
# for application: EXE
|
||||||
|
# for dynamic library: DLL
|
||||||
|
TARGET_TYPE = EXE
|
||||||
|
|
||||||
|
# target object
|
||||||
|
# for application: APP
|
||||||
|
# for device driver: DRV
|
||||||
|
TARGET_OBJ = APP
|
||||||
|
|
||||||
|
TARGET_BOX =
|
||||||
|
|
||||||
|
#debug mode or release mode
|
||||||
|
DEBUG = TRUE
|
||||||
|
|
||||||
|
PLAT_R16 ?= TRUE
|
||||||
|
PLAT_R311 ?= FALSE
|
||||||
|
PLAT_LINUX ?= FALSE
|
||||||
|
PLAT_WIN32 ?= FALSE
|
||||||
|
PLAT_WIN64 ?= FALSE
|
||||||
|
|
||||||
|
VPATH = ../Framework ../log ../
|
||||||
|
|
||||||
|
# source code
|
||||||
|
|
||||||
|
# set the source file, don't used .o because of ...
|
||||||
|
# MRS Board Source Files
|
||||||
|
PLAT_R16_SRCS = \
|
||||||
|
log.c \
|
||||||
|
hexdump.c \
|
||||||
|
http/http.c \
|
||||||
|
mqtt/mqtt.c \
|
||||||
|
hal/hal_mtk.c \
|
||||||
|
crypto/crypto.c \
|
||||||
|
json_utils/cJSON.c \
|
||||||
|
json_utils/s2j.c \
|
||||||
|
json_utils/json_struct.c \
|
||||||
|
main.c
|
||||||
|
|
||||||
|
# gcc CFLAGS
|
||||||
|
PLAT_R16_CFLAGS := -I./ -I../include -DCURRENT_VERSION=\"1.0.0\"
|
||||||
|
R16_LIBS := -lpthread -lmosquitto -lcurl -lcrypto -lnghttp2 -lssl -lcares
|
||||||
|
|
||||||
|
# this line must be at below of thus, because of...
|
||||||
|
include /opt/common/Makefile.cross
|
||||||
|
|
||||||
|
ifeq ($(MAKECMDGOALS), )
|
||||||
|
$(shell find ./ -name $(TARGET)-*.exe -delete)
|
||||||
|
else
|
||||||
|
ifeq ($(MAKECMDGOALS), all)
|
||||||
|
$(shell find ./ -name "$(TARGET)-*.exe" -delete)
|
||||||
|
endif
|
||||||
|
endif
|
|
@ -0,0 +1,4 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
source /etc/profile
|
||||||
|
make -f Makefile.cross OPT=clean && make -f Makefile.cross
|
||||||
|
#make && make OPT=install
|
|
@ -0,0 +1,285 @@
|
||||||
|
/*
|
||||||
|
Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef cJSON__h
|
||||||
|
#define cJSON__h
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32))
|
||||||
|
#define __WINDOWS__
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __WINDOWS__
|
||||||
|
|
||||||
|
/* When compiling for windows, we specify a specific calling convention to avoid issues where we are being called from a project with a different default calling convention. For windows you have 3 define options:
|
||||||
|
|
||||||
|
CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever dllexport symbols
|
||||||
|
CJSON_EXPORT_SYMBOLS - Define this on library build when you want to dllexport symbols (default)
|
||||||
|
CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol
|
||||||
|
|
||||||
|
For *nix builds that support visibility attribute, you can define similar behavior by
|
||||||
|
|
||||||
|
setting default visibility to hidden by adding
|
||||||
|
-fvisibility=hidden (for gcc)
|
||||||
|
or
|
||||||
|
-xldscope=hidden (for sun cc)
|
||||||
|
to CFLAGS
|
||||||
|
|
||||||
|
then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJSON_EXPORT_SYMBOLS does
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define CJSON_CDECL __cdecl
|
||||||
|
#define CJSON_STDCALL __stdcall
|
||||||
|
|
||||||
|
/* export symbols by default, this is necessary for copy pasting the C and header file */
|
||||||
|
#if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) && !defined(CJSON_EXPORT_SYMBOLS)
|
||||||
|
#define CJSON_EXPORT_SYMBOLS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(CJSON_HIDE_SYMBOLS)
|
||||||
|
#define CJSON_PUBLIC(type) type CJSON_STDCALL
|
||||||
|
#elif defined(CJSON_EXPORT_SYMBOLS)
|
||||||
|
#define CJSON_PUBLIC(type) __declspec(dllexport) type CJSON_STDCALL
|
||||||
|
#elif defined(CJSON_IMPORT_SYMBOLS)
|
||||||
|
#define CJSON_PUBLIC(type) __declspec(dllimport) type CJSON_STDCALL
|
||||||
|
#endif
|
||||||
|
#else /* !__WINDOWS__ */
|
||||||
|
#define CJSON_CDECL
|
||||||
|
#define CJSON_STDCALL
|
||||||
|
|
||||||
|
#if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined (__SUNPRO_C)) && defined(CJSON_API_VISIBILITY)
|
||||||
|
#define CJSON_PUBLIC(type) __attribute__((visibility("default"))) type
|
||||||
|
#else
|
||||||
|
#define CJSON_PUBLIC(type) type
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* project version */
|
||||||
|
#define CJSON_VERSION_MAJOR 1
|
||||||
|
#define CJSON_VERSION_MINOR 7
|
||||||
|
#define CJSON_VERSION_PATCH 10
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
/* cJSON Types: */
|
||||||
|
#define cJSON_Invalid (0)
|
||||||
|
#define cJSON_False (1 << 0)
|
||||||
|
#define cJSON_True (1 << 1)
|
||||||
|
#define cJSON_NULL (1 << 2)
|
||||||
|
#define cJSON_Number (1 << 3)
|
||||||
|
#define cJSON_String (1 << 4)
|
||||||
|
#define cJSON_Array (1 << 5)
|
||||||
|
#define cJSON_Object (1 << 6)
|
||||||
|
#define cJSON_Raw (1 << 7) /* raw json */
|
||||||
|
|
||||||
|
#define cJSON_IsReference 256
|
||||||
|
#define cJSON_StringIsConst 512
|
||||||
|
|
||||||
|
/* The cJSON structure: */
|
||||||
|
typedef struct cJSON
|
||||||
|
{
|
||||||
|
/* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
|
||||||
|
struct cJSON *next;
|
||||||
|
struct cJSON *prev;
|
||||||
|
/* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
|
||||||
|
struct cJSON *child;
|
||||||
|
|
||||||
|
/* The type of the item, as above. */
|
||||||
|
int type;
|
||||||
|
|
||||||
|
/* The item's string, if type==cJSON_String and type == cJSON_Raw */
|
||||||
|
char *valuestring;
|
||||||
|
/* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */
|
||||||
|
int valueint;
|
||||||
|
/* The item's number, if type==cJSON_Number */
|
||||||
|
double valuedouble;
|
||||||
|
|
||||||
|
/* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
|
||||||
|
char *string;
|
||||||
|
} cJSON;
|
||||||
|
|
||||||
|
typedef struct cJSON_Hooks
|
||||||
|
{
|
||||||
|
/* malloc/free are CDECL on Windows regardless of the default calling convention of the compiler, so ensure the hooks allow passing those functions directly. */
|
||||||
|
void *(CJSON_CDECL *malloc_fn)(size_t sz);
|
||||||
|
void (CJSON_CDECL *free_fn)(void *ptr);
|
||||||
|
} cJSON_Hooks;
|
||||||
|
|
||||||
|
typedef int cJSON_bool;
|
||||||
|
|
||||||
|
/* Limits how deeply nested arrays/objects can be before cJSON rejects to parse them.
|
||||||
|
* This is to prevent stack overflows. */
|
||||||
|
#ifndef CJSON_NESTING_LIMIT
|
||||||
|
#define CJSON_NESTING_LIMIT 1000
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* returns the version of cJSON as a string */
|
||||||
|
CJSON_PUBLIC(const char*) cJSON_Version(void);
|
||||||
|
|
||||||
|
/* Supply malloc, realloc and free functions to cJSON */
|
||||||
|
CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks);
|
||||||
|
|
||||||
|
/* Memory Management: the caller is always responsible to free the results from all variants of cJSON_Parse (with cJSON_Delete) and cJSON_Print (with stdlib free, cJSON_Hooks.free_fn, or cJSON_free as appropriate). The exception is cJSON_PrintPreallocated, where the caller has full responsibility of the buffer. */
|
||||||
|
/* Supply a block of JSON, and this returns a cJSON object you can interrogate. */
|
||||||
|
CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value);
|
||||||
|
/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
|
||||||
|
/* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error so will match cJSON_GetErrorPtr(). */
|
||||||
|
CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated);
|
||||||
|
|
||||||
|
/* Render a cJSON entity to text for transfer/storage. */
|
||||||
|
CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item);
|
||||||
|
/* Render a cJSON entity to text for transfer/storage without any formatting. */
|
||||||
|
CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item);
|
||||||
|
/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */
|
||||||
|
CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt);
|
||||||
|
/* Render a cJSON entity to text using a buffer already allocated in memory with given length. Returns 1 on success and 0 on failure. */
|
||||||
|
/* NOTE: cJSON is not always 100% accurate in estimating how much memory it will use, so to be safe allocate 5 bytes more than you actually need */
|
||||||
|
CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format);
|
||||||
|
/* Delete a cJSON entity and all subentities. */
|
||||||
|
CJSON_PUBLIC(void) cJSON_Delete(cJSON *c);
|
||||||
|
|
||||||
|
/* Returns the number of items in an array (or object). */
|
||||||
|
CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array);
|
||||||
|
/* Retrieve item number "index" from array "array". Returns NULL if unsuccessful. */
|
||||||
|
CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index);
|
||||||
|
/* Get item "string" from object. Case insensitive. */
|
||||||
|
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string);
|
||||||
|
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string);
|
||||||
|
CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string);
|
||||||
|
/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
|
||||||
|
CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void);
|
||||||
|
|
||||||
|
/* Check if the item is a string and return its valuestring */
|
||||||
|
CJSON_PUBLIC(char *) cJSON_GetStringValue(cJSON *item);
|
||||||
|
|
||||||
|
/* These functions check the type of an item */
|
||||||
|
CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item);
|
||||||
|
CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item);
|
||||||
|
CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item);
|
||||||
|
CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item);
|
||||||
|
CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item);
|
||||||
|
CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item);
|
||||||
|
CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item);
|
||||||
|
CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item);
|
||||||
|
CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item);
|
||||||
|
CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item);
|
||||||
|
|
||||||
|
/* These calls create a cJSON item of the appropriate type. */
|
||||||
|
CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void);
|
||||||
|
CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void);
|
||||||
|
CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void);
|
||||||
|
CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean);
|
||||||
|
CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num);
|
||||||
|
CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string);
|
||||||
|
/* raw json */
|
||||||
|
CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw);
|
||||||
|
CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void);
|
||||||
|
CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void);
|
||||||
|
|
||||||
|
/* Create a string where valuestring references a string so
|
||||||
|
* it will not be freed by cJSON_Delete */
|
||||||
|
CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string);
|
||||||
|
/* Create an object/arrray that only references it's elements so
|
||||||
|
* they will not be freed by cJSON_Delete */
|
||||||
|
CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child);
|
||||||
|
CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child);
|
||||||
|
|
||||||
|
/* These utilities create an Array of count items. */
|
||||||
|
CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count);
|
||||||
|
CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count);
|
||||||
|
CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count);
|
||||||
|
CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count);
|
||||||
|
|
||||||
|
/* Append item to the specified array/object. */
|
||||||
|
CJSON_PUBLIC(void) cJSON_AddItemToArray(cJSON *array, cJSON *item);
|
||||||
|
CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item);
|
||||||
|
/* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object.
|
||||||
|
* WARNING: When this function was used, make sure to always check that (item->type & cJSON_StringIsConst) is zero before
|
||||||
|
* writing to `item->string` */
|
||||||
|
CJSON_PUBLIC(void) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item);
|
||||||
|
/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */
|
||||||
|
CJSON_PUBLIC(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
|
||||||
|
CJSON_PUBLIC(void) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item);
|
||||||
|
|
||||||
|
/* Remove/Detatch items from Arrays/Objects. */
|
||||||
|
CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item);
|
||||||
|
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which);
|
||||||
|
CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which);
|
||||||
|
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string);
|
||||||
|
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string);
|
||||||
|
CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string);
|
||||||
|
CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string);
|
||||||
|
|
||||||
|
/* Update array items. */
|
||||||
|
CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */
|
||||||
|
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement);
|
||||||
|
CJSON_PUBLIC(void) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem);
|
||||||
|
CJSON_PUBLIC(void) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
|
||||||
|
CJSON_PUBLIC(void) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object,const char *string,cJSON *newitem);
|
||||||
|
|
||||||
|
/* Duplicate a cJSON item */
|
||||||
|
CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse);
|
||||||
|
/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will
|
||||||
|
need to be released. With recurse!=0, it will duplicate any children connected to the item.
|
||||||
|
The item->next and ->prev pointers are always zero on return from Duplicate. */
|
||||||
|
/* Recursively compare two cJSON items for equality. If either a or b is NULL or invalid, they will be considered unequal.
|
||||||
|
* case_sensitive determines if object keys are treated case sensitive (1) or case insensitive (0) */
|
||||||
|
CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive);
|
||||||
|
|
||||||
|
|
||||||
|
CJSON_PUBLIC(void) cJSON_Minify(char *json);
|
||||||
|
|
||||||
|
/* Helper functions for creating and adding items to an object at the same time.
|
||||||
|
* They return the added item or NULL on failure. */
|
||||||
|
CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name);
|
||||||
|
CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name);
|
||||||
|
CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name);
|
||||||
|
CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean);
|
||||||
|
CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number);
|
||||||
|
CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string);
|
||||||
|
CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw);
|
||||||
|
CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name);
|
||||||
|
CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name);
|
||||||
|
|
||||||
|
/* When assigning an integer value, it needs to be propagated to valuedouble too. */
|
||||||
|
#define cJSON_SetIntValue(object, number) ((object) ? (object)->valueint = (object)->valuedouble = (number) : (number))
|
||||||
|
/* helper for the cJSON_SetNumberValue macro */
|
||||||
|
CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number);
|
||||||
|
#define cJSON_SetNumberValue(object, number) ((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) : (number))
|
||||||
|
|
||||||
|
/* Macro for iterating over an array or object */
|
||||||
|
#define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
|
||||||
|
|
||||||
|
/* malloc/free objects using the malloc/free functions that have been set with cJSON_InitHooks */
|
||||||
|
CJSON_PUBLIC(void *) cJSON_malloc(size_t size);
|
||||||
|
CJSON_PUBLIC(void) cJSON_free(void *object);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,88 @@
|
||||||
|
/*
|
||||||
|
Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef cJSON_Utils__h
|
||||||
|
#define cJSON_Utils__h
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "cJSON.h"
|
||||||
|
|
||||||
|
/* Implement RFC6901 (https://tools.ietf.org/html/rfc6901) JSON Pointer spec. */
|
||||||
|
CJSON_PUBLIC(cJSON *) cJSONUtils_GetPointer(cJSON * const object, const char *pointer);
|
||||||
|
CJSON_PUBLIC(cJSON *) cJSONUtils_GetPointerCaseSensitive(cJSON * const object, const char *pointer);
|
||||||
|
|
||||||
|
/* Implement RFC6902 (https://tools.ietf.org/html/rfc6902) JSON Patch spec. */
|
||||||
|
/* NOTE: This modifies objects in 'from' and 'to' by sorting the elements by their key */
|
||||||
|
CJSON_PUBLIC(cJSON *) cJSONUtils_GeneratePatches(cJSON * const from, cJSON * const to);
|
||||||
|
CJSON_PUBLIC(cJSON *) cJSONUtils_GeneratePatchesCaseSensitive(cJSON * const from, cJSON * const to);
|
||||||
|
/* Utility for generating patch array entries. */
|
||||||
|
CJSON_PUBLIC(void) cJSONUtils_AddPatchToArray(cJSON * const array, const char * const operation, const char * const path, const cJSON * const value);
|
||||||
|
/* Returns 0 for success. */
|
||||||
|
CJSON_PUBLIC(int) cJSONUtils_ApplyPatches(cJSON * const object, const cJSON * const patches);
|
||||||
|
CJSON_PUBLIC(int) cJSONUtils_ApplyPatchesCaseSensitive(cJSON * const object, const cJSON * const patches);
|
||||||
|
|
||||||
|
/*
|
||||||
|
// Note that ApplyPatches is NOT atomic on failure. To implement an atomic ApplyPatches, use:
|
||||||
|
//int cJSONUtils_AtomicApplyPatches(cJSON **object, cJSON *patches)
|
||||||
|
//{
|
||||||
|
// cJSON *modme = cJSON_Duplicate(*object, 1);
|
||||||
|
// int error = cJSONUtils_ApplyPatches(modme, patches);
|
||||||
|
// if (!error)
|
||||||
|
// {
|
||||||
|
// cJSON_Delete(*object);
|
||||||
|
// *object = modme;
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// cJSON_Delete(modme);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return error;
|
||||||
|
//}
|
||||||
|
// Code not added to library since this strategy is a LOT slower.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Implement RFC7386 (https://tools.ietf.org/html/rfc7396) JSON Merge Patch spec. */
|
||||||
|
/* target will be modified by patch. return value is new ptr for target. */
|
||||||
|
CJSON_PUBLIC(cJSON *) cJSONUtils_MergePatch(cJSON *target, const cJSON * const patch);
|
||||||
|
CJSON_PUBLIC(cJSON *) cJSONUtils_MergePatchCaseSensitive(cJSON *target, const cJSON * const patch);
|
||||||
|
/* generates a patch to move from -> to */
|
||||||
|
/* NOTE: This modifies objects in 'from' and 'to' by sorting the elements by their key */
|
||||||
|
CJSON_PUBLIC(cJSON *) cJSONUtils_GenerateMergePatch(cJSON * const from, cJSON * const to);
|
||||||
|
CJSON_PUBLIC(cJSON *) cJSONUtils_GenerateMergePatchCaseSensitive(cJSON * const from, cJSON * const to);
|
||||||
|
|
||||||
|
/* Given a root object and a target object, construct a pointer from one to the other. */
|
||||||
|
CJSON_PUBLIC(char *) cJSONUtils_FindPointerFromObjectTo(const cJSON * const object, const cJSON * const target);
|
||||||
|
|
||||||
|
/* Sorts the members of the object into alphabetical order. */
|
||||||
|
CJSON_PUBLIC(void) cJSONUtils_SortObject(cJSON * const object);
|
||||||
|
CJSON_PUBLIC(void) cJSONUtils_SortObjectCaseSensitive(cJSON * const object);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,92 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the struct2json Library.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2015, Armink, <armink.ztl@gmail.com>
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
* a copy of this software and associated documentation files (the
|
||||||
|
* 'Software'), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* Function: It is an head file for this library. You can see all be called functions.
|
||||||
|
* Created on: 2015-10-14
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __S2J_H__
|
||||||
|
#define __S2J_H__
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "cJSON.h"
|
||||||
|
#include "s2jdef.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* struct2json software version number */
|
||||||
|
#define S2J_SW_VERSION "1.0.3"
|
||||||
|
|
||||||
|
/* Create JSON object */
|
||||||
|
#define s2j_create_json_obj(json_obj) \
|
||||||
|
S2J_CREATE_JSON_OBJECT(json_obj)
|
||||||
|
|
||||||
|
/* Delete JSON object */
|
||||||
|
#define s2j_delete_json_obj(json_obj) \
|
||||||
|
S2J_DELETE_JSON_OBJECT(json_obj)
|
||||||
|
|
||||||
|
/* Set basic type element for JSON object */
|
||||||
|
#define s2j_json_set_basic_element(to_json, from_struct, type, element) \
|
||||||
|
S2J_JSON_SET_BASIC_ELEMENT(to_json, from_struct, type, element)
|
||||||
|
|
||||||
|
/* Set array type element for JSON object */
|
||||||
|
#define s2j_json_set_array_element(to_json, from_struct, type, element, size) \
|
||||||
|
S2J_JSON_SET_ARRAY_ELEMENT(to_json, from_struct, type, element, size)
|
||||||
|
|
||||||
|
/* Set child structure type element for JSON object */
|
||||||
|
#define s2j_json_set_struct_element(child_json, to_json, child_struct, from_struct, type, element) \
|
||||||
|
S2J_JSON_SET_STRUCT_ELEMENT(child_json, to_json, child_struct, from_struct, type, element)
|
||||||
|
|
||||||
|
/* Create structure object */
|
||||||
|
#define s2j_create_struct_obj(struct_obj, type) \
|
||||||
|
S2J_CREATE_STRUCT_OBJECT(struct_obj, type)
|
||||||
|
|
||||||
|
/* Delete structure object */
|
||||||
|
#define s2j_delete_struct_obj(struct_obj) \
|
||||||
|
S2J_DELETE_STRUCT_OBJECT(struct_obj)
|
||||||
|
|
||||||
|
/* Get basic type element for structure object */
|
||||||
|
#define s2j_struct_get_basic_element(to_struct, from_json, type, element) \
|
||||||
|
S2J_STRUCT_GET_BASIC_ELEMENT(to_struct, from_json, type, element)
|
||||||
|
|
||||||
|
/* Get array type element for structure object */
|
||||||
|
#define s2j_struct_get_array_element(to_struct, from_json, type, element) \
|
||||||
|
S2J_STRUCT_GET_ARRAY_ELEMENT(to_struct, from_json, type, element)
|
||||||
|
|
||||||
|
/* Get child structure type element for structure object */
|
||||||
|
#define s2j_struct_get_struct_element(child_struct, to_struct, child_json, from_json, type, element) \
|
||||||
|
S2J_STRUCT_GET_STRUCT_ELEMENT(child_struct, to_struct, child_json, from_json, type, element)
|
||||||
|
|
||||||
|
/* s2j.c */
|
||||||
|
extern S2jHook s2jHook;
|
||||||
|
void s2j_init(S2jHook *hook);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __S2J_H__ */
|
|
@ -0,0 +1,150 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the struct2json Library.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2015, Armink, <armink.ztl@gmail.com>
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
* a copy of this software and associated documentation files (the
|
||||||
|
* 'Software'), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* Function: It is an head file for this library.
|
||||||
|
* Created on: 2015-10-14
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __S2JDEF_H__
|
||||||
|
#define __S2JDEF_H__
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include "cJSON.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
void *(*malloc_fn)(size_t sz);
|
||||||
|
void (*free_fn)(void *ptr);
|
||||||
|
} S2jHook, *S2jHook_t;
|
||||||
|
|
||||||
|
#define S2J_STRUCT_GET_int_ELEMENT(to_struct, from_json, _element) \
|
||||||
|
json_temp = cJSON_GetObjectItem(from_json, #_element); \
|
||||||
|
if (json_temp) (to_struct)->_element = json_temp->valueint;
|
||||||
|
|
||||||
|
#define S2J_STRUCT_GET_string_ELEMENT(to_struct, from_json, _element) \
|
||||||
|
json_temp = cJSON_GetObjectItem(from_json, #_element); \
|
||||||
|
if (json_temp) strcpy((to_struct)->_element, json_temp->valuestring);
|
||||||
|
|
||||||
|
#define S2J_STRUCT_GET_double_ELEMENT(to_struct, from_json, _element) \
|
||||||
|
json_temp = cJSON_GetObjectItem(from_json, #_element); \
|
||||||
|
if (json_temp) (to_struct)->_element = json_temp->valuedouble;
|
||||||
|
|
||||||
|
#define S2J_STRUCT_ARRAY_GET_int_ELEMENT(to_struct, from_json, _element, index) \
|
||||||
|
(to_struct)->_element[index] = from_json->valueint;
|
||||||
|
|
||||||
|
#define S2J_STRUCT_ARRAY_GET_string_ELEMENT(to_struct, from_json, _element, index) \
|
||||||
|
strcpy((to_struct)->_element[index], from_json->valuestring);
|
||||||
|
|
||||||
|
#define S2J_STRUCT_ARRAY_GET_double_ELEMENT(to_struct, from_json, _element, index) \
|
||||||
|
(to_struct)->_element[index] = from_json->valuedouble;
|
||||||
|
|
||||||
|
#define S2J_STRUCT_ARRAY_GET_ELEMENT(to_struct, from_json, type, _element, index) \
|
||||||
|
S2J_STRUCT_ARRAY_GET_##type##_ELEMENT(to_struct, from_json, _element, index)
|
||||||
|
|
||||||
|
#define S2J_JSON_SET_int_ELEMENT(to_json, from_struct, _element) \
|
||||||
|
cJSON_AddNumberToObject(to_json, #_element, (from_struct)->_element);
|
||||||
|
|
||||||
|
#define S2J_JSON_SET_double_ELEMENT(to_json, from_struct, _element) \
|
||||||
|
cJSON_AddNumberToObject(to_json, #_element, (from_struct)->_element);
|
||||||
|
|
||||||
|
#define S2J_JSON_SET_string_ELEMENT(to_json, from_struct, _element) \
|
||||||
|
cJSON_AddStringToObject(to_json, #_element, (from_struct)->_element);
|
||||||
|
|
||||||
|
#define S2J_JSON_ARRAY_SET_int_ELEMENT(to_json, from_struct, _element, index) \
|
||||||
|
cJSON_AddItemToArray(to_json, cJSON_CreateNumber((from_struct)->_element[index]));
|
||||||
|
|
||||||
|
#define S2J_JSON_ARRAY_SET_double_ELEMENT(to_json, from_struct, _element, index) \
|
||||||
|
cJSON_AddItemToArray(to_json, cJSON_CreateNumber((from_struct)->_element[index]));
|
||||||
|
|
||||||
|
#define S2J_JSON_ARRAY_SET_string_ELEMENT(to_json, from_struct, _element, index) \
|
||||||
|
cJSON_AddItemToArray(to_json, cJSON_CreateString((from_struct)->_element[index]));
|
||||||
|
|
||||||
|
#define S2J_JSON_ARRAY_SET_ELEMENT(to_json, from_struct, type, _element, index) \
|
||||||
|
S2J_JSON_ARRAY_SET_##type##_ELEMENT(to_json, from_struct, _element, index)
|
||||||
|
|
||||||
|
|
||||||
|
#define S2J_CREATE_JSON_OBJECT(json_obj) \
|
||||||
|
cJSON *json_obj = cJSON_CreateObject();
|
||||||
|
|
||||||
|
#define S2J_DELETE_JSON_OBJECT(json_obj) \
|
||||||
|
cJSON_Delete(json_obj);
|
||||||
|
|
||||||
|
#define S2J_JSON_SET_BASIC_ELEMENT(to_json, from_struct, type, _element) \
|
||||||
|
S2J_JSON_SET_##type##_ELEMENT(to_json, from_struct, _element)
|
||||||
|
|
||||||
|
#define S2J_JSON_SET_ARRAY_ELEMENT(to_json, from_struct, type, _element, size) \
|
||||||
|
{ \
|
||||||
|
cJSON *array; \
|
||||||
|
size_t index = 0; \
|
||||||
|
array = cJSON_CreateArray(); \
|
||||||
|
if (array) { \
|
||||||
|
while (index < size) { \
|
||||||
|
S2J_JSON_ARRAY_SET_ELEMENT(array, from_struct, type, _element, index++); \
|
||||||
|
} \
|
||||||
|
cJSON_AddItemToObject(to_json, #_element, array); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define S2J_JSON_SET_STRUCT_ELEMENT(child_json, to_json, child_struct, from_struct, type, _element) \
|
||||||
|
type *child_struct = &((from_struct)->_element); \
|
||||||
|
cJSON *child_json = cJSON_CreateObject(); \
|
||||||
|
if (child_json) cJSON_AddItemToObject(to_json, #_element, child_json);
|
||||||
|
|
||||||
|
#define S2J_CREATE_STRUCT_OBJECT(struct_obj, type) \
|
||||||
|
cJSON *json_temp; \
|
||||||
|
type *struct_obj = s2jHook.malloc_fn(sizeof(type)); \
|
||||||
|
if (struct_obj) memset(struct_obj, 0, sizeof(type));
|
||||||
|
|
||||||
|
#define S2J_DELETE_STRUCT_OBJECT(struct_obj) \
|
||||||
|
s2jHook.free_fn(struct_obj);
|
||||||
|
|
||||||
|
#define S2J_STRUCT_GET_BASIC_ELEMENT(to_struct, from_json, type, _element) \
|
||||||
|
S2J_STRUCT_GET_##type##_ELEMENT(to_struct, from_json, _element)
|
||||||
|
|
||||||
|
#define S2J_STRUCT_GET_ARRAY_ELEMENT(to_struct, from_json, type, _element) \
|
||||||
|
{ \
|
||||||
|
cJSON *array, *array_element; \
|
||||||
|
size_t index = 0, size = 0; \
|
||||||
|
array = cJSON_GetObjectItem(from_json, #_element); \
|
||||||
|
if (array) { \
|
||||||
|
size = cJSON_GetArraySize(array); \
|
||||||
|
while (index < size) { \
|
||||||
|
array_element = cJSON_GetArrayItem(array, index); \
|
||||||
|
if (array_element) S2J_STRUCT_ARRAY_GET_ELEMENT(to_struct, array_element, type, _element, index++); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define S2J_STRUCT_GET_STRUCT_ELEMENT(child_struct, to_struct, child_json, from_json, type, _element) \
|
||||||
|
type *child_struct = &((to_struct)->_element); \
|
||||||
|
cJSON *child_json = cJSON_GetObjectItem(from_json, #_element);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __S2JDEF_H__ */
|
|
@ -0,0 +1,20 @@
|
||||||
|
#ifndef CRYPTO_H
|
||||||
|
#define CRYPTO_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SHA1_DIGEST_LENGTH (20)
|
||||||
|
|
||||||
|
|
||||||
|
const char* rand_string(char* pRandKey, int ilen);
|
||||||
|
const char* hash_sha1(unsigned char* pData, int iSize, char* pHashCode);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,724 @@
|
||||||
|
/*
|
||||||
|
* A generic kernel FIFO implementation
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009/2010 Stefani Seibold <stefani@seibold.net>
|
||||||
|
*
|
||||||
|
* This program 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.
|
||||||
|
*
|
||||||
|
* This program 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 this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FIFO_H
|
||||||
|
#define FIFO_H
|
||||||
|
|
||||||
|
#include <uv.h>
|
||||||
|
|
||||||
|
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
|
||||||
|
#define __must_check __attribute__((warn_unused_result))
|
||||||
|
/*
|
||||||
|
* How to porting drivers to the new generic FIFO API:
|
||||||
|
*
|
||||||
|
* - Modify the declaration of the "struct kfifo *" object into a
|
||||||
|
* in-place "struct kfifo" object
|
||||||
|
* - Init the in-place object with kfifo_alloc() or kfifo_init()
|
||||||
|
* Note: The address of the in-place "struct kfifo" object must be
|
||||||
|
* passed as the first argument to this functions
|
||||||
|
* - Replace the use of __kfifo_put into kfifo_in and __kfifo_get
|
||||||
|
* into kfifo_out
|
||||||
|
* - Replace the use of kfifo_put into kfifo_in_spinlocked and kfifo_get
|
||||||
|
* into kfifo_out_spinlocked
|
||||||
|
* Note: the spinlock pointer formerly passed to kfifo_init/kfifo_alloc
|
||||||
|
* must be passed now to the kfifo_in_spinlocked and kfifo_out_spinlocked
|
||||||
|
* as the last parameter
|
||||||
|
* - The formerly __kfifo_* functions are renamed into kfifo_*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Note about locking : There is no locking required until only * one reader
|
||||||
|
* and one writer is using the fifo and no kfifo_reset() will be * called
|
||||||
|
* kfifo_reset_out() can be safely used, until it will be only called
|
||||||
|
* in the reader thread.
|
||||||
|
* For multiple writer and one reader there is only a need to lock the writer.
|
||||||
|
* And vice versa for only one writer and multiple reader there is only a need
|
||||||
|
* to lock the reader.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
struct __kfifo {
|
||||||
|
unsigned int in;
|
||||||
|
unsigned int out;
|
||||||
|
unsigned int mask;
|
||||||
|
unsigned int esize;
|
||||||
|
void *data;
|
||||||
|
uv_mutex_t lock;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define __STRUCT_KFIFO_COMMON(datatype, recsize, ptrtype) \
|
||||||
|
union { \
|
||||||
|
struct __kfifo kfifo; \
|
||||||
|
datatype *type; \
|
||||||
|
char (*rectype)[recsize]; \
|
||||||
|
ptrtype *ptr; \
|
||||||
|
const ptrtype *ptr_const; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define __STRUCT_KFIFO(type, size, recsize, ptrtype) \
|
||||||
|
{ \
|
||||||
|
__STRUCT_KFIFO_COMMON(type, recsize, ptrtype); \
|
||||||
|
type buf[((size < 2) || (size & (size - 1))) ? -1 : size]; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define STRUCT_KFIFO(type, size) \
|
||||||
|
struct __STRUCT_KFIFO(type, size, 0, type)
|
||||||
|
|
||||||
|
#define __STRUCT_KFIFO_PTR(type, recsize, ptrtype) \
|
||||||
|
{ \
|
||||||
|
__STRUCT_KFIFO_COMMON(type, recsize, ptrtype); \
|
||||||
|
type buf[0]; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define STRUCT_KFIFO_PTR(type) \
|
||||||
|
struct __STRUCT_KFIFO_PTR(type, 0, type)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* define compatibility "struct kfifo" for dynamic allocated fifos
|
||||||
|
*/
|
||||||
|
struct kfifo __STRUCT_KFIFO_PTR(unsigned char, 0, void);
|
||||||
|
|
||||||
|
#define STRUCT_KFIFO_REC_1(size) \
|
||||||
|
struct __STRUCT_KFIFO(unsigned char, size, 1, void)
|
||||||
|
|
||||||
|
#define STRUCT_KFIFO_REC_2(size) \
|
||||||
|
struct __STRUCT_KFIFO(unsigned char, size, 2, void)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* define kfifo_rec types
|
||||||
|
*/
|
||||||
|
struct kfifo_rec_ptr_1 __STRUCT_KFIFO_PTR(unsigned char, 1, void);
|
||||||
|
struct kfifo_rec_ptr_2 __STRUCT_KFIFO_PTR(unsigned char, 2, void);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* helper macro to distinguish between real in place fifo where the fifo
|
||||||
|
* array is a part of the structure and the fifo type where the array is
|
||||||
|
* outside of the fifo structure.
|
||||||
|
*/
|
||||||
|
#define __is_kfifo_ptr(fifo) (sizeof(*fifo) == sizeof(struct __kfifo))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DECLARE_KFIFO_PTR - macro to declare a fifo pointer object
|
||||||
|
* @fifo: name of the declared fifo
|
||||||
|
* @type: type of the fifo elements
|
||||||
|
*/
|
||||||
|
#define DECLARE_KFIFO_PTR(fifo, type) STRUCT_KFIFO_PTR(type) fifo
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DECLARE_KFIFO - macro to declare a fifo object
|
||||||
|
* @fifo: name of the declared fifo
|
||||||
|
* @type: type of the fifo elements
|
||||||
|
* @size: the number of elements in the fifo, this must be a power of 2
|
||||||
|
*/
|
||||||
|
#define DECLARE_KFIFO(fifo, type, size) STRUCT_KFIFO(type, size) fifo
|
||||||
|
|
||||||
|
/**
|
||||||
|
* INIT_KFIFO - Initialize a fifo declared by DECLARE_KFIFO
|
||||||
|
* @fifo: name of the declared fifo datatype
|
||||||
|
*/
|
||||||
|
#define INIT_KFIFO(fifo) \
|
||||||
|
(void)({ \
|
||||||
|
typeof(&(fifo)) __tmp = &(fifo); \
|
||||||
|
struct __kfifo *__kfifo = &__tmp->kfifo; \
|
||||||
|
__kfifo->in = 0; \
|
||||||
|
__kfifo->out = 0; \
|
||||||
|
__kfifo->mask = __is_kfifo_ptr(__tmp) ? 0 : ARRAY_SIZE(__tmp->buf) - 1;\
|
||||||
|
__kfifo->esize = sizeof(*__tmp->buf); \
|
||||||
|
__kfifo->data = __is_kfifo_ptr(__tmp) ? NULL : __tmp->buf; \
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DEFINE_KFIFO - macro to define and initialize a fifo
|
||||||
|
* @fifo: name of the declared fifo datatype
|
||||||
|
* @type: type of the fifo elements
|
||||||
|
* @size: the number of elements in the fifo, this must be a power of 2
|
||||||
|
*
|
||||||
|
* Note: the macro can be used for global and local fifo data type variables.
|
||||||
|
*/
|
||||||
|
#define DEFINE_KFIFO(fifo, type, size) \
|
||||||
|
DECLARE_KFIFO(fifo, type, size) = \
|
||||||
|
(typeof(fifo)) { \
|
||||||
|
{ \
|
||||||
|
{ \
|
||||||
|
.in = 0, \
|
||||||
|
.out = 0, \
|
||||||
|
.mask = __is_kfifo_ptr(&(fifo)) ? \
|
||||||
|
0 : \
|
||||||
|
ARRAY_SIZE((fifo).buf) - 1, \
|
||||||
|
.esize = sizeof(*(fifo).buf), \
|
||||||
|
.data = __is_kfifo_ptr(&(fifo)) ? \
|
||||||
|
NULL : \
|
||||||
|
(fifo).buf, \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline unsigned int __must_check
|
||||||
|
__kfifo_uint_must_check_helper(unsigned int val)
|
||||||
|
{
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int __must_check
|
||||||
|
__kfifo_int_must_check_helper(int val)
|
||||||
|
{
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* kfifo_initialized - Check if the fifo is initialized
|
||||||
|
* @fifo: address of the fifo to check
|
||||||
|
*
|
||||||
|
* Return %true if fifo is initialized, otherwise %false.
|
||||||
|
* Assumes the fifo was 0 before.
|
||||||
|
*/
|
||||||
|
#define kfifo_initialized(fifo) ((fifo)->kfifo.mask)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* kfifo_esize - returns the size of the element managed by the fifo
|
||||||
|
* @fifo: address of the fifo to be used
|
||||||
|
*/
|
||||||
|
#define kfifo_esize(fifo) ((fifo)->kfifo.esize)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* kfifo_recsize - returns the size of the record length field
|
||||||
|
* @fifo: address of the fifo to be used
|
||||||
|
*/
|
||||||
|
#define kfifo_recsize(fifo) (sizeof(*(fifo)->rectype))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* kfifo_size - returns the size of the fifo in elements
|
||||||
|
* @fifo: address of the fifo to be used
|
||||||
|
*/
|
||||||
|
#define kfifo_size(fifo) ((fifo)->kfifo.mask + 1)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* kfifo_reset - removes the entire fifo content
|
||||||
|
* @fifo: address of the fifo to be used
|
||||||
|
*
|
||||||
|
* Note: usage of kfifo_reset() is dangerous. It should be only called when the
|
||||||
|
* fifo is exclusived locked or when it is secured that no other thread is
|
||||||
|
* accessing the fifo.
|
||||||
|
*/
|
||||||
|
#define kfifo_reset(fifo) \
|
||||||
|
(void)({ \
|
||||||
|
typeof((fifo) + 1) __tmp = (fifo); \
|
||||||
|
__tmp->kfifo.in = __tmp->kfifo.out = 0; \
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* kfifo_reset_out - skip fifo content
|
||||||
|
* @fifo: address of the fifo to be used
|
||||||
|
*
|
||||||
|
* Note: The usage of kfifo_reset_out() is safe until it will be only called
|
||||||
|
* from the reader thread and there is only one concurrent reader. Otherwise
|
||||||
|
* it is dangerous and must be handled in the same way as kfifo_reset().
|
||||||
|
*/
|
||||||
|
#define kfifo_reset_out(fifo) \
|
||||||
|
(void)({ \
|
||||||
|
typeof((fifo) + 1) __tmp = (fifo); \
|
||||||
|
__tmp->kfifo.out = __tmp->kfifo.in; \
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* kfifo_len - returns the number of used elements in the fifo
|
||||||
|
* @fifo: address of the fifo to be used
|
||||||
|
*/
|
||||||
|
#define kfifo_len(fifo) \
|
||||||
|
({ \
|
||||||
|
typeof((fifo) + 1) __tmpl = (fifo); \
|
||||||
|
__tmpl->kfifo.in - __tmpl->kfifo.out; \
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* kfifo_is_empty - returns true if the fifo is empty
|
||||||
|
* @fifo: address of the fifo to be used
|
||||||
|
*/
|
||||||
|
#define kfifo_is_empty(fifo) \
|
||||||
|
({ \
|
||||||
|
typeof((fifo) + 1) __tmpq = (fifo); \
|
||||||
|
__tmpq->kfifo.in == __tmpq->kfifo.out; \
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* kfifo_is_full - returns true if the fifo is full
|
||||||
|
* @fifo: address of the fifo to be used
|
||||||
|
*/
|
||||||
|
#define kfifo_is_full(fifo) \
|
||||||
|
({ \
|
||||||
|
typeof((fifo) + 1) __tmpq = (fifo); \
|
||||||
|
kfifo_len(__tmpq) > __tmpq->kfifo.mask; \
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* kfifo_avail - returns the number of unused elements in the fifo
|
||||||
|
* @fifo: address of the fifo to be used
|
||||||
|
*/
|
||||||
|
#define kfifo_avail(fifo) \
|
||||||
|
__kfifo_uint_must_check_helper( \
|
||||||
|
({ \
|
||||||
|
typeof((fifo) + 1) __tmpq = (fifo); \
|
||||||
|
const unsigned int __recsize = sizeof(*__tmpq->rectype); \
|
||||||
|
unsigned int __avail = kfifo_size(__tmpq) - kfifo_len(__tmpq); \
|
||||||
|
(__recsize) ? ((__avail <= __recsize) ? 0 : \
|
||||||
|
__kfifo_max_r(__avail - __recsize, __recsize)) : \
|
||||||
|
__avail; \
|
||||||
|
}) \
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* kfifo_skip - skip output data
|
||||||
|
* @fifo: address of the fifo to be used
|
||||||
|
*/
|
||||||
|
#define kfifo_skip(fifo) \
|
||||||
|
(void)({ \
|
||||||
|
typeof((fifo) + 1) __tmp = (fifo); \
|
||||||
|
const unsigned int __recsize = sizeof(*__tmp->rectype); \
|
||||||
|
struct __kfifo *__kfifo = &__tmp->kfifo; \
|
||||||
|
if (__recsize) \
|
||||||
|
__kfifo_skip_r(__kfifo, __recsize); \
|
||||||
|
else \
|
||||||
|
__kfifo->out++; \
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* kfifo_peek_len - gets the size of the next fifo record
|
||||||
|
* @fifo: address of the fifo to be used
|
||||||
|
*
|
||||||
|
* This function returns the size of the next fifo record in number of bytes.
|
||||||
|
*/
|
||||||
|
#define kfifo_peek_len(fifo) \
|
||||||
|
__kfifo_uint_must_check_helper( \
|
||||||
|
({ \
|
||||||
|
typeof((fifo) + 1) __tmp = (fifo); \
|
||||||
|
const unsigned int __recsize = sizeof(*__tmp->rectype); \
|
||||||
|
struct __kfifo *__kfifo = &__tmp->kfifo; \
|
||||||
|
(!__recsize) ? kfifo_len(__tmp) * sizeof(*__tmp->type) : \
|
||||||
|
__kfifo_len_r(__kfifo, __recsize); \
|
||||||
|
}) \
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* kfifo_alloc - dynamically allocates a new fifo buffer
|
||||||
|
* @fifo: pointer to the fifo
|
||||||
|
* @size: the number of elements in the fifo, this must be a power of 2
|
||||||
|
* @gfp_mask: get_free_pages mask, passed to kmalloc()
|
||||||
|
*
|
||||||
|
* This macro dynamically allocates a new fifo buffer.
|
||||||
|
*
|
||||||
|
* The numer of elements will be rounded-up to a power of 2.
|
||||||
|
* The fifo will be release with kfifo_free().
|
||||||
|
* Return 0 if no error, otherwise an error code.
|
||||||
|
*/
|
||||||
|
#define kfifo_alloc(fifo, size) \
|
||||||
|
__kfifo_int_must_check_helper( \
|
||||||
|
({ \
|
||||||
|
typeof((fifo) + 1) __tmp = (fifo); \
|
||||||
|
struct __kfifo *__kfifo = &__tmp->kfifo; \
|
||||||
|
__is_kfifo_ptr(__tmp) ? \
|
||||||
|
__kfifo_alloc(__kfifo, size, sizeof(*__tmp->type)) : \
|
||||||
|
-EINVAL; \
|
||||||
|
}) \
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* kfifo_free - frees the fifo
|
||||||
|
* @fifo: the fifo to be freed
|
||||||
|
*/
|
||||||
|
#define kfifo_free(fifo) \
|
||||||
|
({ \
|
||||||
|
typeof((fifo) + 1) __tmp = (fifo); \
|
||||||
|
struct __kfifo *__kfifo = &__tmp->kfifo; \
|
||||||
|
if (__is_kfifo_ptr(__tmp)) \
|
||||||
|
__kfifo_free(__kfifo); \
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* kfifo_init - initialize a fifo using a preallocated buffer
|
||||||
|
* @fifo: the fifo to assign the buffer
|
||||||
|
* @buffer: the preallocated buffer to be used
|
||||||
|
* @size: the size of the internal buffer, this have to be a power of 2
|
||||||
|
*
|
||||||
|
* This macro initialize a fifo using a preallocated buffer.
|
||||||
|
*
|
||||||
|
* The numer of elements will be rounded-up to a power of 2.
|
||||||
|
* Return 0 if no error, otherwise an error code.
|
||||||
|
*/
|
||||||
|
#define kfifo_init(fifo, buffer, size) \
|
||||||
|
({ \
|
||||||
|
typeof((fifo) + 1) __tmp = (fifo); \
|
||||||
|
struct __kfifo *__kfifo = &__tmp->kfifo; \
|
||||||
|
__is_kfifo_ptr(__tmp) ? \
|
||||||
|
__kfifo_init(__kfifo, buffer, size, sizeof(*__tmp->type)) : \
|
||||||
|
-EINVAL; \
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* kfifo_put - put data into the fifo
|
||||||
|
* @fifo: address of the fifo to be used
|
||||||
|
* @val: the data to be added
|
||||||
|
*
|
||||||
|
* This macro copies the given value into the fifo.
|
||||||
|
* It returns 0 if the fifo was full. Otherwise it returns the number
|
||||||
|
* processed elements.
|
||||||
|
*
|
||||||
|
* Note that with only one concurrent reader and one concurrent
|
||||||
|
* writer, you don't need extra locking to use these macro.
|
||||||
|
*/
|
||||||
|
#define kfifo_put(fifo, val) \
|
||||||
|
({ \
|
||||||
|
typeof((fifo) + 1) __tmp = (fifo); \
|
||||||
|
typeof((val) + 1) __val = (val); \
|
||||||
|
unsigned int __ret; \
|
||||||
|
const unsigned int __recsize = sizeof(*__tmp->rectype); \
|
||||||
|
struct __kfifo *__kfifo = &__tmp->kfifo; \
|
||||||
|
if (0) { \
|
||||||
|
typeof(__tmp->ptr_const) __dummy __attribute__ ((unused)); \
|
||||||
|
__dummy = (typeof(__val))NULL; \
|
||||||
|
} \
|
||||||
|
if (__recsize) \
|
||||||
|
__ret = __kfifo_in_r(__kfifo, __val, sizeof(*__val), \
|
||||||
|
__recsize); \
|
||||||
|
else { \
|
||||||
|
__ret = !kfifo_is_full(__tmp); \
|
||||||
|
if (__ret) { \
|
||||||
|
(__is_kfifo_ptr(__tmp) ? \
|
||||||
|
((typeof(__tmp->type))__kfifo->data) : \
|
||||||
|
(__tmp->buf) \
|
||||||
|
)[__kfifo->in & __tmp->kfifo.mask] = \
|
||||||
|
*(typeof(__tmp->type))__val; \
|
||||||
|
__kfifo->in++; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
__ret; \
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* kfifo_get - get data from the fifo
|
||||||
|
* @fifo: address of the fifo to be used
|
||||||
|
* @val: the var where to store the data to be added
|
||||||
|
*
|
||||||
|
* This macro reads the data from the fifo.
|
||||||
|
* It returns 0 if the fifo was empty. Otherwise it returns the number
|
||||||
|
* processed elements.
|
||||||
|
*
|
||||||
|
* Note that with only one concurrent reader and one concurrent
|
||||||
|
* writer, you don't need extra locking to use these macro.
|
||||||
|
*/
|
||||||
|
#define kfifo_get(fifo, val) \
|
||||||
|
__kfifo_uint_must_check_helper( \
|
||||||
|
({ \
|
||||||
|
typeof((fifo) + 1) __tmp = (fifo); \
|
||||||
|
typeof((val) + 1) __val = (val); \
|
||||||
|
unsigned int __ret; \
|
||||||
|
const unsigned int __recsize = sizeof(*__tmp->rectype); \
|
||||||
|
struct __kfifo *__kfifo = &__tmp->kfifo; \
|
||||||
|
if (0) \
|
||||||
|
__val = (typeof(__tmp->ptr))0; \
|
||||||
|
if (__recsize) \
|
||||||
|
__ret = __kfifo_out_r(__kfifo, __val, sizeof(*__val), \
|
||||||
|
__recsize); \
|
||||||
|
else { \
|
||||||
|
__ret = !kfifo_is_empty(__tmp); \
|
||||||
|
if (__ret) { \
|
||||||
|
*(typeof(__tmp->type))__val = \
|
||||||
|
(__is_kfifo_ptr(__tmp) ? \
|
||||||
|
((typeof(__tmp->type))__kfifo->data) : \
|
||||||
|
(__tmp->buf) \
|
||||||
|
)[__kfifo->out & __tmp->kfifo.mask]; \
|
||||||
|
__kfifo->out++; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
__ret; \
|
||||||
|
}) \
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* kfifo_peek - get data from the fifo without removing
|
||||||
|
* @fifo: address of the fifo to be used
|
||||||
|
* @val: the var where to store the data to be added
|
||||||
|
*
|
||||||
|
* This reads the data from the fifo without removing it from the fifo.
|
||||||
|
* It returns 0 if the fifo was empty. Otherwise it returns the number
|
||||||
|
* processed elements.
|
||||||
|
*
|
||||||
|
* Note that with only one concurrent reader and one concurrent
|
||||||
|
* writer, you don't need extra locking to use these macro.
|
||||||
|
*/
|
||||||
|
#define kfifo_peek(fifo, val) \
|
||||||
|
__kfifo_uint_must_check_helper( \
|
||||||
|
({ \
|
||||||
|
typeof((fifo) + 1) __tmp = (fifo); \
|
||||||
|
typeof((val) + 1) __val = (val); \
|
||||||
|
unsigned int __ret; \
|
||||||
|
const unsigned int __recsize = sizeof(*__tmp->rectype); \
|
||||||
|
struct __kfifo *__kfifo = &__tmp->kfifo; \
|
||||||
|
if (0) \
|
||||||
|
__val = (typeof(__tmp->ptr))NULL; \
|
||||||
|
if (__recsize) \
|
||||||
|
__ret = __kfifo_out_peek_r(__kfifo, __val, sizeof(*__val), \
|
||||||
|
__recsize); \
|
||||||
|
else { \
|
||||||
|
__ret = !kfifo_is_empty(__tmp); \
|
||||||
|
if (__ret) { \
|
||||||
|
*(typeof(__tmp->type))__val = \
|
||||||
|
(__is_kfifo_ptr(__tmp) ? \
|
||||||
|
((typeof(__tmp->type))__kfifo->data) : \
|
||||||
|
(__tmp->buf) \
|
||||||
|
)[__kfifo->out & __tmp->kfifo.mask]; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
__ret; \
|
||||||
|
}) \
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* kfifo_in - put data into the fifo
|
||||||
|
* @fifo: address of the fifo to be used
|
||||||
|
* @buf: the data to be added
|
||||||
|
* @n: number of elements to be added
|
||||||
|
*
|
||||||
|
* This macro copies the given buffer into the fifo and returns the
|
||||||
|
* number of copied elements.
|
||||||
|
*
|
||||||
|
* Note that with only one concurrent reader and one concurrent
|
||||||
|
* writer, you don't need extra locking to use these macro.
|
||||||
|
*/
|
||||||
|
#define kfifo_in(fifo, buf, n) \
|
||||||
|
({ \
|
||||||
|
typeof((fifo) + 1) __tmp = (fifo); \
|
||||||
|
typeof((buf) + 1) __buf = (buf); \
|
||||||
|
unsigned long __n = (n); \
|
||||||
|
const unsigned int __recsize = sizeof(*__tmp->rectype); \
|
||||||
|
struct __kfifo *__kfifo = &__tmp->kfifo; \
|
||||||
|
if (0) { \
|
||||||
|
typeof(__tmp->ptr_const) __dummy __attribute__ ((unused)); \
|
||||||
|
__dummy = (typeof(__buf))NULL; \
|
||||||
|
} \
|
||||||
|
(__recsize) ?\
|
||||||
|
__kfifo_in_r(__kfifo, __buf, __n, __recsize) : \
|
||||||
|
__kfifo_in(__kfifo, __buf, __n); \
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* kfifo_in_spinlocked - put data into the fifo using a spinlock for locking
|
||||||
|
* @fifo: address of the fifo to be used
|
||||||
|
* @buf: the data to be added
|
||||||
|
* @n: number of elements to be added
|
||||||
|
* @lock: pointer to the spinlock to use for locking
|
||||||
|
*
|
||||||
|
* This macro copies the given values buffer into the fifo and returns the
|
||||||
|
* number of copied elements.
|
||||||
|
*/
|
||||||
|
#define kfifo_in_locked(fifo, buf, n) \
|
||||||
|
({ \
|
||||||
|
unsigned int __ret; \
|
||||||
|
uv_mutex_t __lock = ((struct __kfifo*)fifo)->lock; \
|
||||||
|
uv_mutex_lock(&__lock); \
|
||||||
|
__ret = kfifo_in(fifo, buf, n); \
|
||||||
|
uv_mutex_unlock(&__lock); \
|
||||||
|
__ret; \
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* kfifo_out - get data from the fifo
|
||||||
|
* @fifo: address of the fifo to be used
|
||||||
|
* @buf: pointer to the storage buffer
|
||||||
|
* @n: max. number of elements to get
|
||||||
|
*
|
||||||
|
* This macro get some data from the fifo and return the numbers of elements
|
||||||
|
* copied.
|
||||||
|
*
|
||||||
|
* Note that with only one concurrent reader and one concurrent
|
||||||
|
* writer, you don't need extra locking to use these macro.
|
||||||
|
*/
|
||||||
|
#define kfifo_out(fifo, buf, n) \
|
||||||
|
__kfifo_uint_must_check_helper( \
|
||||||
|
({ \
|
||||||
|
typeof((fifo) + 1) __tmp = (fifo); \
|
||||||
|
typeof((buf) + 1) __buf = (buf); \
|
||||||
|
unsigned long __n = (n); \
|
||||||
|
const unsigned int __recsize = sizeof(*__tmp->rectype); \
|
||||||
|
struct __kfifo *__kfifo = &__tmp->kfifo; \
|
||||||
|
if (0) { \
|
||||||
|
typeof(__tmp->ptr) __dummy = NULL; \
|
||||||
|
__buf = __dummy; \
|
||||||
|
} \
|
||||||
|
(__recsize) ?\
|
||||||
|
__kfifo_out_r(__kfifo, __buf, __n, __recsize) : \
|
||||||
|
__kfifo_out(__kfifo, __buf, __n); \
|
||||||
|
}) \
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* kfifo_out_spinlocked - get data from the fifo using a spinlock for locking
|
||||||
|
* @fifo: address of the fifo to be used
|
||||||
|
* @buf: pointer to the storage buffer
|
||||||
|
* @n: max. number of elements to get
|
||||||
|
* @lock: pointer to the spinlock to use for locking
|
||||||
|
*
|
||||||
|
* This macro get the data from the fifo and return the numbers of elements
|
||||||
|
* copied.
|
||||||
|
*/
|
||||||
|
#define kfifo_out_locked(fifo, buf, n) \
|
||||||
|
__kfifo_uint_must_check_helper( \
|
||||||
|
({ \
|
||||||
|
unsigned int __ret; \
|
||||||
|
uv_mutex_t __lock = ((struct __kfifo*)fifo)->lock; \
|
||||||
|
uv_mutex_lock(&__lock); \
|
||||||
|
__ret = kfifo_out(fifo, buf, n); \
|
||||||
|
uv_mutex_unlock(&__lock); \
|
||||||
|
__ret; \
|
||||||
|
}) \
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* kfifo_from_user - puts some data from user space into the fifo
|
||||||
|
* @fifo: address of the fifo to be used
|
||||||
|
* @from: pointer to the data to be added
|
||||||
|
* @len: the length of the data to be added
|
||||||
|
* @copied: pointer to output variable to store the number of copied bytes
|
||||||
|
*
|
||||||
|
* This macro copies at most @len bytes from the @from into the
|
||||||
|
* fifo, depending of the available space and returns -EFAULT/0.
|
||||||
|
*
|
||||||
|
* Note that with only one concurrent reader and one concurrent
|
||||||
|
* writer, you don't need extra locking to use these macro.
|
||||||
|
*/
|
||||||
|
#define kfifo_from_user(fifo, from, len, copied) \
|
||||||
|
__kfifo_uint_must_check_helper( \
|
||||||
|
({ \
|
||||||
|
typeof((fifo) + 1) __tmp = (fifo); \
|
||||||
|
const void __user *__from = (from); \
|
||||||
|
unsigned int __len = (len); \
|
||||||
|
unsigned int *__copied = (copied); \
|
||||||
|
const unsigned int __recsize = sizeof(*__tmp->rectype); \
|
||||||
|
struct __kfifo *__kfifo = &__tmp->kfifo; \
|
||||||
|
(__recsize) ? \
|
||||||
|
__kfifo_from_user_r(__kfifo, __from, __len, __copied, __recsize) : \
|
||||||
|
__kfifo_from_user(__kfifo, __from, __len, __copied); \
|
||||||
|
}) \
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* kfifo_to_user - copies data from the fifo into user space
|
||||||
|
* @fifo: address of the fifo to be used
|
||||||
|
* @to: where the data must be copied
|
||||||
|
* @len: the size of the destination buffer
|
||||||
|
* @copied: pointer to output variable to store the number of copied bytes
|
||||||
|
*
|
||||||
|
* This macro copies at most @len bytes from the fifo into the
|
||||||
|
* @to buffer and returns -EFAULT/0.
|
||||||
|
*
|
||||||
|
* Note that with only one concurrent reader and one concurrent
|
||||||
|
* writer, you don't need extra locking to use these macro.
|
||||||
|
*/
|
||||||
|
#define kfifo_to_user(fifo, to, len, copied) \
|
||||||
|
__kfifo_uint_must_check_helper( \
|
||||||
|
({ \
|
||||||
|
typeof((fifo) + 1) __tmp = (fifo); \
|
||||||
|
void __user *__to = (to); \
|
||||||
|
unsigned int __len = (len); \
|
||||||
|
unsigned int *__copied = (copied); \
|
||||||
|
const unsigned int __recsize = sizeof(*__tmp->rectype); \
|
||||||
|
struct __kfifo *__kfifo = &__tmp->kfifo; \
|
||||||
|
(__recsize) ? \
|
||||||
|
__kfifo_to_user_r(__kfifo, __to, __len, __copied, __recsize) : \
|
||||||
|
__kfifo_to_user(__kfifo, __to, __len, __copied); \
|
||||||
|
}) \
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* kfifo_out_peek - gets some data from the fifo
|
||||||
|
* @fifo: address of the fifo to be used
|
||||||
|
* @buf: pointer to the storage buffer
|
||||||
|
* @n: max. number of elements to get
|
||||||
|
*
|
||||||
|
* This macro get the data from the fifo and return the numbers of elements
|
||||||
|
* copied. The data is not removed from the fifo.
|
||||||
|
*
|
||||||
|
* Note that with only one concurrent reader and one concurrent
|
||||||
|
* writer, you don't need extra locking to use these macro.
|
||||||
|
*/
|
||||||
|
#define kfifo_out_peek(fifo, buf, n) \
|
||||||
|
__kfifo_uint_must_check_helper( \
|
||||||
|
({ \
|
||||||
|
typeof((fifo) + 1) __tmp = (fifo); \
|
||||||
|
typeof((buf) + 1) __buf = (buf); \
|
||||||
|
unsigned long __n = (n); \
|
||||||
|
const unsigned int __recsize = sizeof(*__tmp->rectype); \
|
||||||
|
struct __kfifo *__kfifo = &__tmp->kfifo; \
|
||||||
|
if (0) { \
|
||||||
|
typeof(__tmp->ptr) __dummy __attribute__ ((unused)) = NULL; \
|
||||||
|
__buf = __dummy; \
|
||||||
|
} \
|
||||||
|
(__recsize) ? \
|
||||||
|
__kfifo_out_peek_r(__kfifo, __buf, __n, __recsize) : \
|
||||||
|
__kfifo_out_peek(__kfifo, __buf, __n); \
|
||||||
|
}) \
|
||||||
|
)
|
||||||
|
|
||||||
|
#define kfifo_peek_locked(fifo, buf, n) \
|
||||||
|
__kfifo_uint_must_check_helper( \
|
||||||
|
({ \
|
||||||
|
unsigned int __ret; \
|
||||||
|
uv_mutex_t __lock = ((struct __kfifo*)fifo)->lock; \
|
||||||
|
uv_mutex_lock(&__lock); \
|
||||||
|
__ret = kfifo_out_peek(fifo, buf, n); \
|
||||||
|
uv_mutex_unlock(&__lock); \
|
||||||
|
__ret; \
|
||||||
|
}) \
|
||||||
|
)
|
||||||
|
|
||||||
|
extern int __kfifo_alloc(struct __kfifo *fifo, unsigned int size, unsigned int esize);
|
||||||
|
|
||||||
|
extern void __kfifo_free(struct __kfifo *fifo);
|
||||||
|
|
||||||
|
extern int __kfifo_init(struct __kfifo *fifo, void *buffer,
|
||||||
|
unsigned int size, unsigned int esize);
|
||||||
|
|
||||||
|
extern unsigned int __kfifo_in(struct __kfifo *fifo,
|
||||||
|
const void *buf, unsigned int len);
|
||||||
|
|
||||||
|
extern unsigned int __kfifo_out(struct __kfifo *fifo,
|
||||||
|
void *buf, unsigned int len);
|
||||||
|
|
||||||
|
extern unsigned int __kfifo_out_peek(struct __kfifo *fifo,
|
||||||
|
void *buf, unsigned int len);
|
||||||
|
|
||||||
|
extern unsigned int __kfifo_in_r(struct __kfifo *fifo,
|
||||||
|
const void *buf, unsigned int len, unsigned int recsize);
|
||||||
|
|
||||||
|
extern unsigned int __kfifo_out_r(struct __kfifo *fifo,
|
||||||
|
void *buf, unsigned int len, unsigned int recsize);
|
||||||
|
|
||||||
|
extern unsigned int __kfifo_len_r(struct __kfifo *fifo, unsigned int recsize);
|
||||||
|
|
||||||
|
extern void __kfifo_skip_r(struct __kfifo *fifo, unsigned int recsize);
|
||||||
|
|
||||||
|
extern unsigned int __kfifo_out_peek_r(struct __kfifo *fifo,
|
||||||
|
void *buf, unsigned int len, unsigned int recsize);
|
||||||
|
|
||||||
|
extern unsigned int __kfifo_max_r(unsigned int len, unsigned int recsize);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,31 @@
|
||||||
|
#ifndef HAL_MTK_H
|
||||||
|
#define HAL_MTK_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define DeviceKey "98b6e96524e8a4014ef8089e934e9e27"
|
||||||
|
#define SecuryKey "7ce57cb93ca8"
|
||||||
|
|
||||||
|
|
||||||
|
#define NETEASE_PRODUCT_KEY DeviceKey//"2c53832e7a05e6fcb52081ff3abce92c"
|
||||||
|
#define NETEASE_PRODUCT_SEC SecuryKey//"8e92003eb2f9"
|
||||||
|
|
||||||
|
#define NETEASE_MQTT_SERVER "mqtt-dev.netease.im"
|
||||||
|
#define NETEASE_MQTT_PORT 8883
|
||||||
|
#define NETEASE_API_SERVER "https://api-iot-dev.netease.im/RegisterDevice"
|
||||||
|
|
||||||
|
#define MQTT_CA_FILE_PATH ("/etc/cacert.crt")
|
||||||
|
|
||||||
|
const char* hal_get_device_id(void);
|
||||||
|
const char* hal_get_device_iot_id(void);
|
||||||
|
const char* hal_get_device_name(void);
|
||||||
|
const char* hal_get_device_secret(void);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
#ifndef HTTP_H
|
||||||
|
#define HTTP_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -0,0 +1,273 @@
|
||||||
|
/** @file log.h
|
||||||
|
@brief
|
||||||
|
@details
|
||||||
|
@version 1.0.0
|
||||||
|
*/
|
||||||
|
#ifndef LOG_H_
|
||||||
|
#define LOG_H_
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __KERNEL__
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
#else
|
||||||
|
#include <linux/string.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef TRUE
|
||||||
|
#define TRUE (1)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef FALSE
|
||||||
|
#define FALSE (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MAX
|
||||||
|
/** @def MAX
|
||||||
|
@brief 取最大值
|
||||||
|
*/
|
||||||
|
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MIN
|
||||||
|
/** @def MIN
|
||||||
|
@brief 取最小值
|
||||||
|
*/
|
||||||
|
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define TIMEZONE_EAST_8H (8 * 3600)
|
||||||
|
|
||||||
|
#ifndef __KERNEL__
|
||||||
|
#define DUMP_PREFIX_ADDRESS (1)
|
||||||
|
#define DUMP_PREFIX_OFFSET (2)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define DEBUG_SQL_CALLBACK_DATA(argc, argv, azColName) do { \
|
||||||
|
for(int i = 0; i < argc; i++) { \
|
||||||
|
fprintf(stdout, "%s = [%s], ", azColName[i], argv[i]); \
|
||||||
|
} \
|
||||||
|
fprintf(stdout, "\n"); \
|
||||||
|
} while(0);
|
||||||
|
|
||||||
|
#define print(format, ...) fprintf(stdout, format, __VA_ARGS__)
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int cfgCmd;
|
||||||
|
int iParams1;
|
||||||
|
int iParams2;
|
||||||
|
} LOG_CFG_PROTOCOL, *PLOG_CFG_PROTOCOL;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
CMD_LOG_ENABLE = 0,
|
||||||
|
CMD_LOG_FILE = 1,
|
||||||
|
CMD_LOG_MAIL = 2,
|
||||||
|
CMD_LOG_LEVEL = 3,
|
||||||
|
CMD_LOG_NETWORK = 4,
|
||||||
|
CMD_LOG_SERVER = 5
|
||||||
|
} LOG_CFG_CMD;
|
||||||
|
|
||||||
|
/** @enum _LOG_LEVEL_
|
||||||
|
* LOG等级枚举变量
|
||||||
|
*/
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
LOG_Fatal = (1 << 0),
|
||||||
|
LOG_Error = (1 << 1),
|
||||||
|
LOG_Warn = (1 << 2),
|
||||||
|
LOG_Debug = (1 << 3),
|
||||||
|
LOG_Info = (1 << 4),
|
||||||
|
LOG_Test = (1 << 5),
|
||||||
|
LOG_Call = (1 << 6),
|
||||||
|
LOG_Devp = (1 << 7),
|
||||||
|
LOG_Step = (1 << 8),
|
||||||
|
LOG_Unknown = (1 << 9),
|
||||||
|
LOG_All = (0xFFFFFFFF),
|
||||||
|
LOG_Close = 0x0,
|
||||||
|
} LOG_LEVEL;
|
||||||
|
/** @var typedef _LOG_LEVEL_ LOG_LEVEL
|
||||||
|
* @brief 错误值枚举类型
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
ERR_OK = 0,
|
||||||
|
ERR_INPUT_PARAMS,
|
||||||
|
ERR_NO_ITEMS,
|
||||||
|
ERR_GET_BUS,
|
||||||
|
ERR_DBUS_CONNECTION,
|
||||||
|
ERR_REQUEST_BUS_NAME,
|
||||||
|
ERR_SET_WATCH_FUNCTION,
|
||||||
|
ERR_SET_TIMEOUT_FUNCTION,
|
||||||
|
ERR_BUS_MATCH,
|
||||||
|
ERR_BUS_SET_MSG_CB,
|
||||||
|
ERR_DBUS_CREATE_MSG,
|
||||||
|
ERR_BUS_SEND_MSG,
|
||||||
|
ERR_DBUS_MSG_TO_LARGE,
|
||||||
|
ERR_BUS_RCV_MSG,
|
||||||
|
ERR_ADD_TASK,
|
||||||
|
ERR_UNSUP_EVP_TYPE,
|
||||||
|
|
||||||
|
ERR_CREATE_MQ,
|
||||||
|
ERR_MQ_SENDMSG,
|
||||||
|
ERR_CREATE_SHM,
|
||||||
|
ERR_MAP_SHM,
|
||||||
|
ERR_MALLOC_MEMORY,
|
||||||
|
|
||||||
|
ERR_EVP_INIT_KEY,
|
||||||
|
ERR_EVP_UPDATE,
|
||||||
|
ERR_EVP_FINALE,
|
||||||
|
ERR_EVP_KEY_SIZE,
|
||||||
|
|
||||||
|
ERR_OPEN_FILE,
|
||||||
|
ERR_READ_FILE,
|
||||||
|
ERR_WRITE_FILE,
|
||||||
|
ERR_COPY_FILE,
|
||||||
|
ERR_FILE_NOT_EXISTS,
|
||||||
|
ERR_GET_FILE_SIZE,
|
||||||
|
ERR_UNINIT_ITEM,
|
||||||
|
ERR_FILE_EMPTY,
|
||||||
|
|
||||||
|
ERR_SEND_MAIL,
|
||||||
|
ERR_NETWORK_SEND,
|
||||||
|
ERR_NETWORK_NOT_CONNECTED,
|
||||||
|
|
||||||
|
ERR_CREATE_SOCKET,
|
||||||
|
ERR_BIND_SOCKET,
|
||||||
|
|
||||||
|
ERR_UNSUPPORT,
|
||||||
|
} SYSTEM_ERROR;
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef DISABLE_LOG
|
||||||
|
#define LOG_BUF(level, buf, len)
|
||||||
|
#define LOG_EX(level, format, args...)
|
||||||
|
#define LOG_EX2(level, format, args...)
|
||||||
|
#define LOG_TAG_EX(tag, level, format, args...)
|
||||||
|
#define DEBUG_CODE_LINE()
|
||||||
|
#define DEBUG_FUNCTION_BEGIN()
|
||||||
|
#define DEBUG_FUNCTION_END()
|
||||||
|
#else
|
||||||
|
#define LOG_BUF(level, buf, len) do { \
|
||||||
|
const char* pFmtBuf = format_hex_buf("", DUMP_PREFIX_ADDRESS, 16, 1, buf, len, 1); \
|
||||||
|
IHW_LOG(level, "[%s] - %s(%d): %s[0-%d]:\n%s", basename_v2(__FILE__), __FUNCTION__, __LINE__, \
|
||||||
|
#buf, len, pFmtBuf); \
|
||||||
|
free((void*)pFmtBuf); \
|
||||||
|
} while(0);
|
||||||
|
/*! \def LOG_EX
|
||||||
|
\brief 系统日志调试宏标识
|
||||||
|
*/
|
||||||
|
#define LOG_EX(level, format, args...) (IHW_LOG(level, "[%s] - %s(%d):" format , basename_v2(__FILE__), __FUNCTION__, __LINE__, ##args))
|
||||||
|
|
||||||
|
/*! \def LOG_TAG_EX
|
||||||
|
\brief 系统日志调试宏标识
|
||||||
|
*/
|
||||||
|
#define LOG_TAG_EX(tag, level, format, args...) (IHW_LOG(level, "{%s} [%s] %s(%d):" format , tag, basename_v2(__FILE__), __FUNCTION__, __LINE__, ##args))
|
||||||
|
|
||||||
|
#define LOG_EX2(level, format, args...) (IHW_LOG_UNTAG(level, format , ##args))
|
||||||
|
|
||||||
|
/*! @def APP_BUILD_INFO
|
||||||
|
@brief 应用程序编译信息
|
||||||
|
*/
|
||||||
|
#define APP_BUILD_INFO(appname, appver) (IHW_LOG(LOG_Info, "%s Ver:%s (Build: %s %s GCC Ver:%s) With %d(bits) OS\n", \
|
||||||
|
appname, appver, __DATE__, __TIME__, __VERSION__, sizeof(int*) * 8))
|
||||||
|
|
||||||
|
|
||||||
|
/*! @def DEBUG_CODE_LINE
|
||||||
|
@brief 输出当前函数名,行号
|
||||||
|
*/
|
||||||
|
#define DEBUG_CODE_LINE() (LOG_EX(LOG_Info, "\n"))
|
||||||
|
|
||||||
|
/*! @def DEBUG_FUNCTION_BEGIN
|
||||||
|
@brief 函数入口标志
|
||||||
|
*/
|
||||||
|
#define DEBUG_FUNCTION_BEGIN() (LOG_EX(LOG_Call, "+++++\n"))
|
||||||
|
|
||||||
|
/*! @def DEBUG_FUNCTION_END
|
||||||
|
@brief 函数出口标志
|
||||||
|
*/
|
||||||
|
#define DEBUG_FUNCTION_END() (LOG_EX(LOG_Call, "-----\n"))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 输出调试信息
|
||||||
|
* @param level 调试信息开关
|
||||||
|
* @param pMsg 调试信息内容
|
||||||
|
*/
|
||||||
|
void IHW_LOG(LOG_LEVEL level, const char* pMsg, ...);
|
||||||
|
void IHW_LOG_UNTAG(LOG_LEVEL level, const char* pMsg, ...);
|
||||||
|
|
||||||
|
void IHW_LogStrWithoutPrint(int level, char* pMsg);
|
||||||
|
void IHW_LogRawString(int level, char* pMsg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置调试等级
|
||||||
|
* @param level 调试等级
|
||||||
|
* @param iEnable 1 打开调试等级, 0 关闭调试等级
|
||||||
|
*/
|
||||||
|
void IHW_EnableLogLevel(LOG_LEVEL level, int iEnable);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 初始化系统日志功能
|
||||||
|
* @param pLogTag 系统日志标志
|
||||||
|
* @param pPath 系统日志保存路径
|
||||||
|
* @param bEnable 打开/关闭调试信息
|
||||||
|
*/
|
||||||
|
void IHW_InitLOG(const char* pLogTag, const char* pPath, int bEnable);
|
||||||
|
|
||||||
|
void IHW_RunLogService(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 判断文件、路径是否存在
|
||||||
|
* @param pPath - 文件路径
|
||||||
|
* @return int 存在返回 1, 否则返回 0;
|
||||||
|
*/
|
||||||
|
int IHW_IsFileExist(const char* pPath);
|
||||||
|
|
||||||
|
void IHW_EnableLogOut(void);
|
||||||
|
void IHW_DisableLogOut(void);
|
||||||
|
|
||||||
|
char* IHW_bin2hex(char *p, const unsigned char *cp, int count);
|
||||||
|
|
||||||
|
/* Return the last part of a pathname */
|
||||||
|
static inline const char* basename_v2(const char* path)
|
||||||
|
{
|
||||||
|
const char* tail = strrchr(path, '/');
|
||||||
|
return tail ? tail + 1 : path;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int dirname_v2(const char* path, char* dir)
|
||||||
|
{
|
||||||
|
const char* tail = strrchr(path, '/');
|
||||||
|
|
||||||
|
if(tail)
|
||||||
|
{
|
||||||
|
memcpy(dir, path, tail - path);
|
||||||
|
dir[tail - path] = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
strcpy(dir, "./");
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const char* LogLeveToString(LOG_LEVEL lv);
|
||||||
|
|
||||||
|
const char* format_hex_buf(const char* prefix_str, int prefix_type,
|
||||||
|
int rowsize, int groupsize,
|
||||||
|
const void* buf, int len, int ascii);
|
||||||
|
#ifndef __KERNEL__
|
||||||
|
void print_hex_dump_bytes(const char* prefix_str, int prefix_type,
|
||||||
|
const void* buf, int len);
|
||||||
|
#endif
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif //LOG_H_
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
#ifndef MQTT_H
|
||||||
|
#define MQTT_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void mqtt_proxy_setup(void);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,93 @@
|
||||||
|
#ifndef PROTOCOL_H
|
||||||
|
#define PROTOCOL_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
CRYPTO_NONE = 0,
|
||||||
|
CRYPTO_MD5 = 1,
|
||||||
|
CRYPTO_AES = 2,
|
||||||
|
} CRYPTO_TYPE;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
CRYPTO_ENCODE = 0,
|
||||||
|
CRYPTO_DECODE = 1
|
||||||
|
} CRYPTO_OPT;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char* IotId;
|
||||||
|
char* DeviceSecret;
|
||||||
|
char* ProductKey;
|
||||||
|
char* DeviceName;
|
||||||
|
} REGIST_DEV_INFO, *PREGIST_DEV_INFO;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
REGIST_DEV_INFO data;
|
||||||
|
char* requestId;
|
||||||
|
int code;
|
||||||
|
char* msg;
|
||||||
|
} REGIST_DEVICE, *PREGIST_DEVICE;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char* mcuCmd;
|
||||||
|
} BYPASS_INFO, *PBYPASS_INFO;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int cmdId;
|
||||||
|
int cryptoType;
|
||||||
|
int timeStamp;
|
||||||
|
char* msgContent;
|
||||||
|
} CLOUND_API, *PCLOUND_API;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
BYPASS_INFO reported;
|
||||||
|
} SHADOW_STATE, *PSHADOW_STATE;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char* method;
|
||||||
|
int version;
|
||||||
|
SHADOW_STATE state;
|
||||||
|
} SHADOW_UPDATE, *PSHADOW_UPDATE;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
JE_PROMAIN = 0,
|
||||||
|
JE_BYPASS,
|
||||||
|
JE_SHADOWUP,
|
||||||
|
JE_REGDEVICE,
|
||||||
|
JE_MAX,
|
||||||
|
} JSON_ENGINE_TYPE;
|
||||||
|
|
||||||
|
typedef const char* (*JSONENCODEPROC)(void* pStruct);
|
||||||
|
typedef void* (*JSONDECODEPROC)(const char* pJsonStr);
|
||||||
|
typedef void (*CRYPTOPROC)(void *pStruct, int cryptoType, int enCode);
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
JSON_ENGINE_TYPE typeId;
|
||||||
|
JSONENCODEPROC jsonEncodeCb;
|
||||||
|
JSONDECODEPROC jsonDecodeCb;
|
||||||
|
CRYPTOPROC cryptoCb;
|
||||||
|
} JSON_ENGINE, *PJSON_ENGINE;
|
||||||
|
|
||||||
|
const char* Struct2Json(void* pStruct, JSON_ENGINE_TYPE type, int cryptoType, int* pErr);
|
||||||
|
void* Json2Struct(const char* pJsonStr, JSON_ENGINE_TYPE type, int cryptoType, int* pErr);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,285 @@
|
||||||
|
/*
|
||||||
|
Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef cJSON__h
|
||||||
|
#define cJSON__h
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32))
|
||||||
|
#define __WINDOWS__
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __WINDOWS__
|
||||||
|
|
||||||
|
/* When compiling for windows, we specify a specific calling convention to avoid issues where we are being called from a project with a different default calling convention. For windows you have 3 define options:
|
||||||
|
|
||||||
|
CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever dllexport symbols
|
||||||
|
CJSON_EXPORT_SYMBOLS - Define this on library build when you want to dllexport symbols (default)
|
||||||
|
CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol
|
||||||
|
|
||||||
|
For *nix builds that support visibility attribute, you can define similar behavior by
|
||||||
|
|
||||||
|
setting default visibility to hidden by adding
|
||||||
|
-fvisibility=hidden (for gcc)
|
||||||
|
or
|
||||||
|
-xldscope=hidden (for sun cc)
|
||||||
|
to CFLAGS
|
||||||
|
|
||||||
|
then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJSON_EXPORT_SYMBOLS does
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define CJSON_CDECL __cdecl
|
||||||
|
#define CJSON_STDCALL __stdcall
|
||||||
|
|
||||||
|
/* export symbols by default, this is necessary for copy pasting the C and header file */
|
||||||
|
#if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) && !defined(CJSON_EXPORT_SYMBOLS)
|
||||||
|
#define CJSON_EXPORT_SYMBOLS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(CJSON_HIDE_SYMBOLS)
|
||||||
|
#define CJSON_PUBLIC(type) type CJSON_STDCALL
|
||||||
|
#elif defined(CJSON_EXPORT_SYMBOLS)
|
||||||
|
#define CJSON_PUBLIC(type) __declspec(dllexport) type CJSON_STDCALL
|
||||||
|
#elif defined(CJSON_IMPORT_SYMBOLS)
|
||||||
|
#define CJSON_PUBLIC(type) __declspec(dllimport) type CJSON_STDCALL
|
||||||
|
#endif
|
||||||
|
#else /* !__WINDOWS__ */
|
||||||
|
#define CJSON_CDECL
|
||||||
|
#define CJSON_STDCALL
|
||||||
|
|
||||||
|
#if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined (__SUNPRO_C)) && defined(CJSON_API_VISIBILITY)
|
||||||
|
#define CJSON_PUBLIC(type) __attribute__((visibility("default"))) type
|
||||||
|
#else
|
||||||
|
#define CJSON_PUBLIC(type) type
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* project version */
|
||||||
|
#define CJSON_VERSION_MAJOR 1
|
||||||
|
#define CJSON_VERSION_MINOR 7
|
||||||
|
#define CJSON_VERSION_PATCH 10
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
/* cJSON Types: */
|
||||||
|
#define cJSON_Invalid (0)
|
||||||
|
#define cJSON_False (1 << 0)
|
||||||
|
#define cJSON_True (1 << 1)
|
||||||
|
#define cJSON_NULL (1 << 2)
|
||||||
|
#define cJSON_Number (1 << 3)
|
||||||
|
#define cJSON_String (1 << 4)
|
||||||
|
#define cJSON_Array (1 << 5)
|
||||||
|
#define cJSON_Object (1 << 6)
|
||||||
|
#define cJSON_Raw (1 << 7) /* raw json */
|
||||||
|
|
||||||
|
#define cJSON_IsReference 256
|
||||||
|
#define cJSON_StringIsConst 512
|
||||||
|
|
||||||
|
/* The cJSON structure: */
|
||||||
|
typedef struct cJSON
|
||||||
|
{
|
||||||
|
/* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
|
||||||
|
struct cJSON *next;
|
||||||
|
struct cJSON *prev;
|
||||||
|
/* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
|
||||||
|
struct cJSON *child;
|
||||||
|
|
||||||
|
/* The type of the item, as above. */
|
||||||
|
int type;
|
||||||
|
|
||||||
|
/* The item's string, if type==cJSON_String and type == cJSON_Raw */
|
||||||
|
char *valuestring;
|
||||||
|
/* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */
|
||||||
|
int valueint;
|
||||||
|
/* The item's number, if type==cJSON_Number */
|
||||||
|
double valuedouble;
|
||||||
|
|
||||||
|
/* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
|
||||||
|
char *string;
|
||||||
|
} cJSON;
|
||||||
|
|
||||||
|
typedef struct cJSON_Hooks
|
||||||
|
{
|
||||||
|
/* malloc/free are CDECL on Windows regardless of the default calling convention of the compiler, so ensure the hooks allow passing those functions directly. */
|
||||||
|
void *(CJSON_CDECL *malloc_fn)(size_t sz);
|
||||||
|
void (CJSON_CDECL *free_fn)(void *ptr);
|
||||||
|
} cJSON_Hooks;
|
||||||
|
|
||||||
|
typedef int cJSON_bool;
|
||||||
|
|
||||||
|
/* Limits how deeply nested arrays/objects can be before cJSON rejects to parse them.
|
||||||
|
* This is to prevent stack overflows. */
|
||||||
|
#ifndef CJSON_NESTING_LIMIT
|
||||||
|
#define CJSON_NESTING_LIMIT 1000
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* returns the version of cJSON as a string */
|
||||||
|
CJSON_PUBLIC(const char*) cJSON_Version(void);
|
||||||
|
|
||||||
|
/* Supply malloc, realloc and free functions to cJSON */
|
||||||
|
CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks);
|
||||||
|
|
||||||
|
/* Memory Management: the caller is always responsible to free the results from all variants of cJSON_Parse (with cJSON_Delete) and cJSON_Print (with stdlib free, cJSON_Hooks.free_fn, or cJSON_free as appropriate). The exception is cJSON_PrintPreallocated, where the caller has full responsibility of the buffer. */
|
||||||
|
/* Supply a block of JSON, and this returns a cJSON object you can interrogate. */
|
||||||
|
CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value);
|
||||||
|
/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
|
||||||
|
/* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error so will match cJSON_GetErrorPtr(). */
|
||||||
|
CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated);
|
||||||
|
|
||||||
|
/* Render a cJSON entity to text for transfer/storage. */
|
||||||
|
CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item);
|
||||||
|
/* Render a cJSON entity to text for transfer/storage without any formatting. */
|
||||||
|
CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item);
|
||||||
|
/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */
|
||||||
|
CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt);
|
||||||
|
/* Render a cJSON entity to text using a buffer already allocated in memory with given length. Returns 1 on success and 0 on failure. */
|
||||||
|
/* NOTE: cJSON is not always 100% accurate in estimating how much memory it will use, so to be safe allocate 5 bytes more than you actually need */
|
||||||
|
CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format);
|
||||||
|
/* Delete a cJSON entity and all subentities. */
|
||||||
|
CJSON_PUBLIC(void) cJSON_Delete(cJSON *c);
|
||||||
|
|
||||||
|
/* Returns the number of items in an array (or object). */
|
||||||
|
CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array);
|
||||||
|
/* Retrieve item number "index" from array "array". Returns NULL if unsuccessful. */
|
||||||
|
CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index);
|
||||||
|
/* Get item "string" from object. Case insensitive. */
|
||||||
|
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string);
|
||||||
|
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string);
|
||||||
|
CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string);
|
||||||
|
/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
|
||||||
|
CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void);
|
||||||
|
|
||||||
|
/* Check if the item is a string and return its valuestring */
|
||||||
|
CJSON_PUBLIC(char *) cJSON_GetStringValue(cJSON *item);
|
||||||
|
|
||||||
|
/* These functions check the type of an item */
|
||||||
|
CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item);
|
||||||
|
CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item);
|
||||||
|
CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item);
|
||||||
|
CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item);
|
||||||
|
CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item);
|
||||||
|
CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item);
|
||||||
|
CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item);
|
||||||
|
CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item);
|
||||||
|
CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item);
|
||||||
|
CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item);
|
||||||
|
|
||||||
|
/* These calls create a cJSON item of the appropriate type. */
|
||||||
|
CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void);
|
||||||
|
CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void);
|
||||||
|
CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void);
|
||||||
|
CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean);
|
||||||
|
CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num);
|
||||||
|
CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string);
|
||||||
|
/* raw json */
|
||||||
|
CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw);
|
||||||
|
CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void);
|
||||||
|
CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void);
|
||||||
|
|
||||||
|
/* Create a string where valuestring references a string so
|
||||||
|
* it will not be freed by cJSON_Delete */
|
||||||
|
CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string);
|
||||||
|
/* Create an object/arrray that only references it's elements so
|
||||||
|
* they will not be freed by cJSON_Delete */
|
||||||
|
CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child);
|
||||||
|
CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child);
|
||||||
|
|
||||||
|
/* These utilities create an Array of count items. */
|
||||||
|
CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count);
|
||||||
|
CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count);
|
||||||
|
CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count);
|
||||||
|
CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count);
|
||||||
|
|
||||||
|
/* Append item to the specified array/object. */
|
||||||
|
CJSON_PUBLIC(void) cJSON_AddItemToArray(cJSON *array, cJSON *item);
|
||||||
|
CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item);
|
||||||
|
/* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object.
|
||||||
|
* WARNING: When this function was used, make sure to always check that (item->type & cJSON_StringIsConst) is zero before
|
||||||
|
* writing to `item->string` */
|
||||||
|
CJSON_PUBLIC(void) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item);
|
||||||
|
/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */
|
||||||
|
CJSON_PUBLIC(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
|
||||||
|
CJSON_PUBLIC(void) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item);
|
||||||
|
|
||||||
|
/* Remove/Detatch items from Arrays/Objects. */
|
||||||
|
CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item);
|
||||||
|
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which);
|
||||||
|
CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which);
|
||||||
|
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string);
|
||||||
|
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string);
|
||||||
|
CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string);
|
||||||
|
CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string);
|
||||||
|
|
||||||
|
/* Update array items. */
|
||||||
|
CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */
|
||||||
|
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement);
|
||||||
|
CJSON_PUBLIC(void) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem);
|
||||||
|
CJSON_PUBLIC(void) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
|
||||||
|
CJSON_PUBLIC(void) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object,const char *string,cJSON *newitem);
|
||||||
|
|
||||||
|
/* Duplicate a cJSON item */
|
||||||
|
CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse);
|
||||||
|
/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will
|
||||||
|
need to be released. With recurse!=0, it will duplicate any children connected to the item.
|
||||||
|
The item->next and ->prev pointers are always zero on return from Duplicate. */
|
||||||
|
/* Recursively compare two cJSON items for equality. If either a or b is NULL or invalid, they will be considered unequal.
|
||||||
|
* case_sensitive determines if object keys are treated case sensitive (1) or case insensitive (0) */
|
||||||
|
CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive);
|
||||||
|
|
||||||
|
|
||||||
|
CJSON_PUBLIC(void) cJSON_Minify(char *json);
|
||||||
|
|
||||||
|
/* Helper functions for creating and adding items to an object at the same time.
|
||||||
|
* They return the added item or NULL on failure. */
|
||||||
|
CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name);
|
||||||
|
CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name);
|
||||||
|
CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name);
|
||||||
|
CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean);
|
||||||
|
CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number);
|
||||||
|
CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string);
|
||||||
|
CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw);
|
||||||
|
CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name);
|
||||||
|
CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name);
|
||||||
|
|
||||||
|
/* When assigning an integer value, it needs to be propagated to valuedouble too. */
|
||||||
|
#define cJSON_SetIntValue(object, number) ((object) ? (object)->valueint = (object)->valuedouble = (number) : (number))
|
||||||
|
/* helper for the cJSON_SetNumberValue macro */
|
||||||
|
CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number);
|
||||||
|
#define cJSON_SetNumberValue(object, number) ((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) : (number))
|
||||||
|
|
||||||
|
/* Macro for iterating over an array or object */
|
||||||
|
#define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
|
||||||
|
|
||||||
|
/* malloc/free objects using the malloc/free functions that have been set with cJSON_InitHooks */
|
||||||
|
CJSON_PUBLIC(void *) cJSON_malloc(size_t size);
|
||||||
|
CJSON_PUBLIC(void) cJSON_free(void *object);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,238 @@
|
||||||
|
/*
|
||||||
|
Copyright (c) 2008-2018, Troy D. Hanson http://troydhanson.github.com/uthash/
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||||
|
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||||
|
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* a dynamic array implementation using macros
|
||||||
|
*/
|
||||||
|
#ifndef UTARRAY_H
|
||||||
|
#define UTARRAY_H
|
||||||
|
|
||||||
|
#define UTARRAY_VERSION 2.1.0
|
||||||
|
|
||||||
|
#include <stddef.h> /* size_t */
|
||||||
|
#include <string.h> /* memset, etc */
|
||||||
|
#include <stdlib.h> /* exit */
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
#define UTARRAY_UNUSED __attribute__((__unused__))
|
||||||
|
#else
|
||||||
|
#define UTARRAY_UNUSED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef oom
|
||||||
|
#define oom() exit(-1)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef void (ctor_f)(void *dst, const void *src);
|
||||||
|
typedef void (dtor_f)(void *elt);
|
||||||
|
typedef void (init_f)(void *elt);
|
||||||
|
typedef struct {
|
||||||
|
size_t sz;
|
||||||
|
init_f *init;
|
||||||
|
ctor_f *copy;
|
||||||
|
dtor_f *dtor;
|
||||||
|
} UT_icd;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned i,n;/* i: index of next available slot, n: num slots */
|
||||||
|
UT_icd icd; /* initializer, copy and destructor functions */
|
||||||
|
char *d; /* n slots of size icd->sz*/
|
||||||
|
} UT_array;
|
||||||
|
|
||||||
|
#define utarray_init(a,_icd) do { \
|
||||||
|
memset(a,0,sizeof(UT_array)); \
|
||||||
|
(a)->icd = *(_icd); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define utarray_done(a) do { \
|
||||||
|
if ((a)->n) { \
|
||||||
|
if ((a)->icd.dtor) { \
|
||||||
|
unsigned _ut_i; \
|
||||||
|
for(_ut_i=0; _ut_i < (a)->i; _ut_i++) { \
|
||||||
|
(a)->icd.dtor(utarray_eltptr(a,_ut_i)); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
free((a)->d); \
|
||||||
|
} \
|
||||||
|
(a)->n=0; \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define utarray_new(a,_icd) do { \
|
||||||
|
(a) = (UT_array*)malloc(sizeof(UT_array)); \
|
||||||
|
if ((a) == NULL) oom(); \
|
||||||
|
utarray_init(a,_icd); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define utarray_free(a) do { \
|
||||||
|
utarray_done(a); \
|
||||||
|
free(a); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define utarray_reserve(a,by) do { \
|
||||||
|
if (((a)->i+(by)) > (a)->n) { \
|
||||||
|
char *utarray_tmp; \
|
||||||
|
while (((a)->i+(by)) > (a)->n) { (a)->n = ((a)->n ? (2*(a)->n) : 8); } \
|
||||||
|
utarray_tmp=(char*)realloc((a)->d, (a)->n*(a)->icd.sz); \
|
||||||
|
if (utarray_tmp == NULL) oom(); \
|
||||||
|
(a)->d=utarray_tmp; \
|
||||||
|
} \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define utarray_push_back(a,p) do { \
|
||||||
|
utarray_reserve(a,1); \
|
||||||
|
if ((a)->icd.copy) { (a)->icd.copy( _utarray_eltptr(a,(a)->i++), p); } \
|
||||||
|
else { memcpy(_utarray_eltptr(a,(a)->i++), p, (a)->icd.sz); }; \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define utarray_pop_back(a) do { \
|
||||||
|
if ((a)->icd.dtor) { (a)->icd.dtor( _utarray_eltptr(a,--((a)->i))); } \
|
||||||
|
else { (a)->i--; } \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define utarray_extend_back(a) do { \
|
||||||
|
utarray_reserve(a,1); \
|
||||||
|
if ((a)->icd.init) { (a)->icd.init(_utarray_eltptr(a,(a)->i)); } \
|
||||||
|
else { memset(_utarray_eltptr(a,(a)->i),0,(a)->icd.sz); } \
|
||||||
|
(a)->i++; \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define utarray_len(a) ((a)->i)
|
||||||
|
|
||||||
|
#define utarray_eltptr(a,j) (((j) < (a)->i) ? _utarray_eltptr(a,j) : NULL)
|
||||||
|
#define _utarray_eltptr(a,j) ((a)->d + ((a)->icd.sz * (j)))
|
||||||
|
|
||||||
|
#define utarray_insert(a,p,j) do { \
|
||||||
|
if ((j) > (a)->i) utarray_resize(a,j); \
|
||||||
|
utarray_reserve(a,1); \
|
||||||
|
if ((j) < (a)->i) { \
|
||||||
|
memmove( _utarray_eltptr(a,(j)+1), _utarray_eltptr(a,j), \
|
||||||
|
((a)->i - (j))*((a)->icd.sz)); \
|
||||||
|
} \
|
||||||
|
if ((a)->icd.copy) { (a)->icd.copy( _utarray_eltptr(a,j), p); } \
|
||||||
|
else { memcpy(_utarray_eltptr(a,j), p, (a)->icd.sz); }; \
|
||||||
|
(a)->i++; \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define utarray_inserta(a,w,j) do { \
|
||||||
|
if (utarray_len(w) == 0) break; \
|
||||||
|
if ((j) > (a)->i) utarray_resize(a,j); \
|
||||||
|
utarray_reserve(a,utarray_len(w)); \
|
||||||
|
if ((j) < (a)->i) { \
|
||||||
|
memmove(_utarray_eltptr(a,(j)+utarray_len(w)), \
|
||||||
|
_utarray_eltptr(a,j), \
|
||||||
|
((a)->i - (j))*((a)->icd.sz)); \
|
||||||
|
} \
|
||||||
|
if ((a)->icd.copy) { \
|
||||||
|
unsigned _ut_i; \
|
||||||
|
for(_ut_i=0;_ut_i<(w)->i;_ut_i++) { \
|
||||||
|
(a)->icd.copy(_utarray_eltptr(a, (j) + _ut_i), _utarray_eltptr(w, _ut_i)); \
|
||||||
|
} \
|
||||||
|
} else { \
|
||||||
|
memcpy(_utarray_eltptr(a,j), _utarray_eltptr(w,0), \
|
||||||
|
utarray_len(w)*((a)->icd.sz)); \
|
||||||
|
} \
|
||||||
|
(a)->i += utarray_len(w); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define utarray_resize(dst,num) do { \
|
||||||
|
unsigned _ut_i; \
|
||||||
|
if ((dst)->i > (unsigned)(num)) { \
|
||||||
|
if ((dst)->icd.dtor) { \
|
||||||
|
for (_ut_i = (num); _ut_i < (dst)->i; ++_ut_i) { \
|
||||||
|
(dst)->icd.dtor(_utarray_eltptr(dst, _ut_i)); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
} else if ((dst)->i < (unsigned)(num)) { \
|
||||||
|
utarray_reserve(dst, (num) - (dst)->i); \
|
||||||
|
if ((dst)->icd.init) { \
|
||||||
|
for (_ut_i = (dst)->i; _ut_i < (unsigned)(num); ++_ut_i) { \
|
||||||
|
(dst)->icd.init(_utarray_eltptr(dst, _ut_i)); \
|
||||||
|
} \
|
||||||
|
} else { \
|
||||||
|
memset(_utarray_eltptr(dst, (dst)->i), 0, (dst)->icd.sz*((num) - (dst)->i)); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
(dst)->i = (num); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define utarray_concat(dst,src) do { \
|
||||||
|
utarray_inserta(dst, src, utarray_len(dst)); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define utarray_erase(a,pos,len) do { \
|
||||||
|
if ((a)->icd.dtor) { \
|
||||||
|
unsigned _ut_i; \
|
||||||
|
for (_ut_i = 0; _ut_i < (len); _ut_i++) { \
|
||||||
|
(a)->icd.dtor(utarray_eltptr(a, (pos) + _ut_i)); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
if ((a)->i > ((pos) + (len))) { \
|
||||||
|
memmove(_utarray_eltptr(a, pos), _utarray_eltptr(a, (pos) + (len)), \
|
||||||
|
((a)->i - ((pos) + (len))) * (a)->icd.sz); \
|
||||||
|
} \
|
||||||
|
(a)->i -= (len); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define utarray_renew(a,u) do { \
|
||||||
|
if (a) utarray_clear(a); \
|
||||||
|
else utarray_new(a, u); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define utarray_clear(a) do { \
|
||||||
|
if ((a)->i > 0) { \
|
||||||
|
if ((a)->icd.dtor) { \
|
||||||
|
unsigned _ut_i; \
|
||||||
|
for(_ut_i=0; _ut_i < (a)->i; _ut_i++) { \
|
||||||
|
(a)->icd.dtor(_utarray_eltptr(a, _ut_i)); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
(a)->i = 0; \
|
||||||
|
} \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define utarray_sort(a,cmp) do { \
|
||||||
|
qsort((a)->d, (a)->i, (a)->icd.sz, cmp); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define utarray_find(a,v,cmp) bsearch((v),(a)->d,(a)->i,(a)->icd.sz,cmp)
|
||||||
|
|
||||||
|
#define utarray_front(a) (((a)->i) ? (_utarray_eltptr(a,0)) : NULL)
|
||||||
|
#define utarray_next(a,e) (((e)==NULL) ? utarray_front(a) : ((((a)->i) > (utarray_eltidx(a,e)+1)) ? _utarray_eltptr(a,utarray_eltidx(a,e)+1) : NULL))
|
||||||
|
#define utarray_prev(a,e) (((e)==NULL) ? utarray_back(a) : ((utarray_eltidx(a,e) > 0) ? _utarray_eltptr(a,utarray_eltidx(a,e)-1) : NULL))
|
||||||
|
#define utarray_back(a) (((a)->i) ? (_utarray_eltptr(a,(a)->i-1)) : NULL)
|
||||||
|
#define utarray_eltidx(a,e) (((char*)(e) >= (a)->d) ? (((char*)(e) - (a)->d)/(a)->icd.sz) : -1)
|
||||||
|
|
||||||
|
/* last we pre-define a few icd for common utarrays of ints and strings */
|
||||||
|
static void utarray_str_cpy(void *dst, const void *src) {
|
||||||
|
char **_src = (char**)src, **_dst = (char**)dst;
|
||||||
|
*_dst = (*_src == NULL) ? NULL : strdup(*_src);
|
||||||
|
}
|
||||||
|
static void utarray_str_dtor(void *elt) {
|
||||||
|
char **eltc = (char**)elt;
|
||||||
|
if (*eltc != NULL) free(*eltc);
|
||||||
|
}
|
||||||
|
static const UT_icd ut_str_icd UTARRAY_UNUSED = {sizeof(char*),NULL,utarray_str_cpy,utarray_str_dtor};
|
||||||
|
static const UT_icd ut_int_icd UTARRAY_UNUSED = {sizeof(int),NULL,NULL,NULL};
|
||||||
|
static const UT_icd ut_ptr_icd UTARRAY_UNUSED = {sizeof(void*),NULL,NULL,NULL};
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* UTARRAY_H */
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,108 @@
|
||||||
|
/*
|
||||||
|
Copyright (c) 2015-2018, Troy D. Hanson http://troydhanson.github.com/uthash/
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||||
|
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||||
|
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* a ring-buffer implementation using macros
|
||||||
|
*/
|
||||||
|
#ifndef UTRINGBUFFER_H
|
||||||
|
#define UTRINGBUFFER_H
|
||||||
|
|
||||||
|
#define UTRINGBUFFER_VERSION 2.1.0
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "utarray.h" // for "UT_icd"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned i; /* index of next available slot; wraps at n */
|
||||||
|
unsigned n; /* capacity */
|
||||||
|
unsigned char f; /* full */
|
||||||
|
UT_icd icd; /* initializer, copy and destructor functions */
|
||||||
|
char *d; /* n slots of size icd->sz */
|
||||||
|
} UT_ringbuffer;
|
||||||
|
|
||||||
|
#define utringbuffer_init(a, _n, _icd) do { \
|
||||||
|
memset(a, 0, sizeof(UT_ringbuffer)); \
|
||||||
|
(a)->icd = *(_icd); \
|
||||||
|
(a)->n = (_n); \
|
||||||
|
if ((a)->n) { (a)->d = (char*)malloc((a)->n * (_icd)->sz); } \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define utringbuffer_clear(a) do { \
|
||||||
|
if ((a)->icd.dtor) { \
|
||||||
|
if ((a)->f) { \
|
||||||
|
unsigned _ut_i; \
|
||||||
|
for (_ut_i = 0; _ut_i < (a)->n; ++_ut_i) { \
|
||||||
|
(a)->icd.dtor(utringbuffer_eltptr(a, _ut_i)); \
|
||||||
|
} \
|
||||||
|
} else { \
|
||||||
|
unsigned _ut_i; \
|
||||||
|
for (_ut_i = 0; _ut_i < (a)->i; ++_ut_i) { \
|
||||||
|
(a)->icd.dtor(utringbuffer_eltptr(a, _ut_i)); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
(a)->i = 0; \
|
||||||
|
(a)->f = 0; \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define utringbuffer_done(a) do { \
|
||||||
|
utringbuffer_clear(a); \
|
||||||
|
free((a)->d); (a)->d = NULL; \
|
||||||
|
(a)->n = 0; \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define utringbuffer_new(a,n,_icd) do { \
|
||||||
|
a = (UT_ringbuffer*)malloc(sizeof(UT_ringbuffer)); \
|
||||||
|
utringbuffer_init(a, n, _icd); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define utringbuffer_free(a) do { \
|
||||||
|
utringbuffer_done(a); \
|
||||||
|
free(a); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define utringbuffer_push_back(a,p) do { \
|
||||||
|
if ((a)->icd.dtor && (a)->f) { (a)->icd.dtor(_utringbuffer_internalptr(a,(a)->i)); } \
|
||||||
|
if ((a)->icd.copy) { (a)->icd.copy( _utringbuffer_internalptr(a,(a)->i), p); } \
|
||||||
|
else { memcpy(_utringbuffer_internalptr(a,(a)->i), p, (a)->icd.sz); }; \
|
||||||
|
if (++(a)->i == (a)->n) { (a)->i = 0; (a)->f = 1; } \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define utringbuffer_len(a) ((a)->f ? (a)->n : (a)->i)
|
||||||
|
#define utringbuffer_empty(a) ((a)->i == 0 && !(a)->f)
|
||||||
|
#define utringbuffer_full(a) ((a)->f != 0)
|
||||||
|
|
||||||
|
#define _utringbuffer_real_idx(a,j) ((a)->f ? ((j) + (a)->i) % (a)->n : (j))
|
||||||
|
#define _utringbuffer_internalptr(a,j) ((void*)((a)->d + ((a)->icd.sz * (j))))
|
||||||
|
#define utringbuffer_eltptr(a,j) ((0 <= (j) && (j) < utringbuffer_len(a)) ? _utringbuffer_internalptr(a,_utringbuffer_real_idx(a,j)) : NULL)
|
||||||
|
|
||||||
|
#define _utringbuffer_fake_idx(a,j) ((a)->f ? ((j) + (a)->n - (a)->i) % (a)->n : (j))
|
||||||
|
#define _utringbuffer_internalidx(a,e) (((char*)(e) >= (a)->d) ? (((char*)(e) - (a)->d)/(a)->icd.sz) : -1)
|
||||||
|
#define utringbuffer_eltidx(a,e) _utringbuffer_fake_idx(a, _utringbuffer_internalidx(a,e))
|
||||||
|
|
||||||
|
#define utringbuffer_front(a) utringbuffer_eltptr(a,0)
|
||||||
|
#define utringbuffer_next(a,e) ((e)==NULL ? utringbuffer_front(a) : utringbuffer_eltptr(a, utringbuffer_eltidx(a,e)+1))
|
||||||
|
#define utringbuffer_prev(a,e) ((e)==NULL ? utringbuffer_back(a) : utringbuffer_eltptr(a, utringbuffer_eltidx(a,e)-1))
|
||||||
|
#define utringbuffer_back(a) (utringbuffer_empty(a) ? NULL : utringbuffer_eltptr(a, utringbuffer_len(a) - 1))
|
||||||
|
|
||||||
|
#endif /* UTRINGBUFFER_H */
|
|
@ -0,0 +1,88 @@
|
||||||
|
/*
|
||||||
|
Copyright (c) 2018-2018, Troy D. Hanson http://troydhanson.github.com/uthash/
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||||
|
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||||
|
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef UTSTACK_H
|
||||||
|
#define UTSTACK_H
|
||||||
|
|
||||||
|
#define UTSTACK_VERSION 2.1.0
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file contains macros to manipulate a singly-linked list as a stack.
|
||||||
|
*
|
||||||
|
* To use utstack, your structure must have a "next" pointer.
|
||||||
|
*
|
||||||
|
* ----------------.EXAMPLE -------------------------
|
||||||
|
* struct item {
|
||||||
|
* int id;
|
||||||
|
* struct item *next;
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* struct item *stack = NULL:
|
||||||
|
*
|
||||||
|
* int main() {
|
||||||
|
* int count;
|
||||||
|
* struct item *tmp;
|
||||||
|
* struct item *item = malloc(sizeof *item);
|
||||||
|
* item->id = 42;
|
||||||
|
* STACK_COUNT(stack, tmp, count); assert(count == 0);
|
||||||
|
* STACK_PUSH(stack, item);
|
||||||
|
* STACK_COUNT(stack, tmp, count); assert(count == 1);
|
||||||
|
* STACK_POP(stack, item);
|
||||||
|
* free(item);
|
||||||
|
* STACK_COUNT(stack, tmp, count); assert(count == 0);
|
||||||
|
* }
|
||||||
|
* --------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define STACK_TOP(head) (head)
|
||||||
|
|
||||||
|
#define STACK_EMPTY(head) (!(head))
|
||||||
|
|
||||||
|
#define STACK_PUSH(head,add) \
|
||||||
|
STACK_PUSH2(head,add,next)
|
||||||
|
|
||||||
|
#define STACK_PUSH2(head,add,next) \
|
||||||
|
do { \
|
||||||
|
(add)->next = (head); \
|
||||||
|
(head) = (add); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define STACK_POP(head,result) \
|
||||||
|
STACK_POP2(head,result,next)
|
||||||
|
|
||||||
|
#define STACK_POP2(head,result,next) \
|
||||||
|
do { \
|
||||||
|
(result) = (head); \
|
||||||
|
(head) = (head)->next; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define STACK_COUNT(head,el,counter) \
|
||||||
|
STACK_COUNT2(head,el,counter,next) \
|
||||||
|
|
||||||
|
#define STACK_COUNT2(head,el,counter,next) \
|
||||||
|
do { \
|
||||||
|
(counter) = 0; \
|
||||||
|
for ((el) = (head); el; (el) = (el)->next) { ++(counter); } \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#endif /* UTSTACK_H */
|
|
@ -0,0 +1,398 @@
|
||||||
|
/*
|
||||||
|
Copyright (c) 2008-2018, Troy D. Hanson http://troydhanson.github.com/uthash/
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||||
|
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||||
|
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* a dynamic string implementation using macros
|
||||||
|
*/
|
||||||
|
#ifndef UTSTRING_H
|
||||||
|
#define UTSTRING_H
|
||||||
|
|
||||||
|
#define UTSTRING_VERSION 2.1.0
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
#define UTSTRING_UNUSED __attribute__((__unused__))
|
||||||
|
#else
|
||||||
|
#define UTSTRING_UNUSED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef oom
|
||||||
|
#define oom() exit(-1)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char *d; /* pointer to allocated buffer */
|
||||||
|
size_t n; /* allocated capacity */
|
||||||
|
size_t i; /* index of first unused byte */
|
||||||
|
} UT_string;
|
||||||
|
|
||||||
|
#define utstring_reserve(s,amt) \
|
||||||
|
do { \
|
||||||
|
if (((s)->n - (s)->i) < (size_t)(amt)) { \
|
||||||
|
char *utstring_tmp = (char*)realloc( \
|
||||||
|
(s)->d, (s)->n + (amt)); \
|
||||||
|
if (utstring_tmp == NULL) oom(); \
|
||||||
|
(s)->d = utstring_tmp; \
|
||||||
|
(s)->n += (amt); \
|
||||||
|
} \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define utstring_init(s) \
|
||||||
|
do { \
|
||||||
|
(s)->n = 0; (s)->i = 0; (s)->d = NULL; \
|
||||||
|
utstring_reserve(s,100); \
|
||||||
|
(s)->d[0] = '\0'; \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define utstring_done(s) \
|
||||||
|
do { \
|
||||||
|
if ((s)->d != NULL) free((s)->d); \
|
||||||
|
(s)->n = 0; \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define utstring_free(s) \
|
||||||
|
do { \
|
||||||
|
utstring_done(s); \
|
||||||
|
free(s); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define utstring_new(s) \
|
||||||
|
do { \
|
||||||
|
(s) = (UT_string*)malloc(sizeof(UT_string)); \
|
||||||
|
if (!(s)) oom(); \
|
||||||
|
utstring_init(s); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define utstring_renew(s) \
|
||||||
|
do { \
|
||||||
|
if (s) { \
|
||||||
|
utstring_clear(s); \
|
||||||
|
} else { \
|
||||||
|
utstring_new(s); \
|
||||||
|
} \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define utstring_clear(s) \
|
||||||
|
do { \
|
||||||
|
(s)->i = 0; \
|
||||||
|
(s)->d[0] = '\0'; \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define utstring_bincpy(s,b,l) \
|
||||||
|
do { \
|
||||||
|
utstring_reserve((s),(l)+1); \
|
||||||
|
if (l) memcpy(&(s)->d[(s)->i], b, l); \
|
||||||
|
(s)->i += (l); \
|
||||||
|
(s)->d[(s)->i]='\0'; \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define utstring_concat(dst,src) \
|
||||||
|
do { \
|
||||||
|
utstring_reserve((dst),((src)->i)+1); \
|
||||||
|
if ((src)->i) memcpy(&(dst)->d[(dst)->i], (src)->d, (src)->i); \
|
||||||
|
(dst)->i += (src)->i; \
|
||||||
|
(dst)->d[(dst)->i]='\0'; \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define utstring_len(s) ((s)->i)
|
||||||
|
|
||||||
|
#define utstring_body(s) ((s)->d)
|
||||||
|
|
||||||
|
UTSTRING_UNUSED static void utstring_printf_va(UT_string *s, const char *fmt, va_list ap) {
|
||||||
|
int n;
|
||||||
|
va_list cp;
|
||||||
|
for (;;) {
|
||||||
|
#ifdef _WIN32
|
||||||
|
cp = ap;
|
||||||
|
#else
|
||||||
|
va_copy(cp, ap);
|
||||||
|
#endif
|
||||||
|
n = vsnprintf (&s->d[s->i], s->n-s->i, fmt, cp);
|
||||||
|
va_end(cp);
|
||||||
|
|
||||||
|
if ((n > -1) && ((size_t) n < (s->n-s->i))) {
|
||||||
|
s->i += n;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Else try again with more space. */
|
||||||
|
if (n > -1) utstring_reserve(s,n+1); /* exact */
|
||||||
|
else utstring_reserve(s,(s->n)*2); /* 2x */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#ifdef __GNUC__
|
||||||
|
/* support printf format checking (2=the format string, 3=start of varargs) */
|
||||||
|
static void utstring_printf(UT_string *s, const char *fmt, ...)
|
||||||
|
__attribute__ (( format( printf, 2, 3) ));
|
||||||
|
#endif
|
||||||
|
UTSTRING_UNUSED static void utstring_printf(UT_string *s, const char *fmt, ...) {
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap,fmt);
|
||||||
|
utstring_printf_va(s,fmt,ap);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* begin substring search functions *
|
||||||
|
******************************************************************************/
|
||||||
|
/* Build KMP table from left to right. */
|
||||||
|
UTSTRING_UNUSED static void _utstring_BuildTable(
|
||||||
|
const char *P_Needle,
|
||||||
|
size_t P_NeedleLen,
|
||||||
|
long *P_KMP_Table)
|
||||||
|
{
|
||||||
|
long i, j;
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
j = i - 1;
|
||||||
|
P_KMP_Table[i] = j;
|
||||||
|
while (i < (long) P_NeedleLen)
|
||||||
|
{
|
||||||
|
while ( (j > -1) && (P_Needle[i] != P_Needle[j]) )
|
||||||
|
{
|
||||||
|
j = P_KMP_Table[j];
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
j++;
|
||||||
|
if (i < (long) P_NeedleLen)
|
||||||
|
{
|
||||||
|
if (P_Needle[i] == P_Needle[j])
|
||||||
|
{
|
||||||
|
P_KMP_Table[i] = P_KMP_Table[j];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
P_KMP_Table[i] = j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
P_KMP_Table[i] = j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Build KMP table from right to left. */
|
||||||
|
UTSTRING_UNUSED static void _utstring_BuildTableR(
|
||||||
|
const char *P_Needle,
|
||||||
|
size_t P_NeedleLen,
|
||||||
|
long *P_KMP_Table)
|
||||||
|
{
|
||||||
|
long i, j;
|
||||||
|
|
||||||
|
i = P_NeedleLen - 1;
|
||||||
|
j = i + 1;
|
||||||
|
P_KMP_Table[i + 1] = j;
|
||||||
|
while (i >= 0)
|
||||||
|
{
|
||||||
|
while ( (j < (long) P_NeedleLen) && (P_Needle[i] != P_Needle[j]) )
|
||||||
|
{
|
||||||
|
j = P_KMP_Table[j + 1];
|
||||||
|
}
|
||||||
|
i--;
|
||||||
|
j--;
|
||||||
|
if (i >= 0)
|
||||||
|
{
|
||||||
|
if (P_Needle[i] == P_Needle[j])
|
||||||
|
{
|
||||||
|
P_KMP_Table[i + 1] = P_KMP_Table[j + 1];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
P_KMP_Table[i + 1] = j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
P_KMP_Table[i + 1] = j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Search data from left to right. ( Multiple search mode. ) */
|
||||||
|
UTSTRING_UNUSED static long _utstring_find(
|
||||||
|
const char *P_Haystack,
|
||||||
|
size_t P_HaystackLen,
|
||||||
|
const char *P_Needle,
|
||||||
|
size_t P_NeedleLen,
|
||||||
|
long *P_KMP_Table)
|
||||||
|
{
|
||||||
|
long i, j;
|
||||||
|
long V_FindPosition = -1;
|
||||||
|
|
||||||
|
/* Search from left to right. */
|
||||||
|
i = j = 0;
|
||||||
|
while ( (j < (int)P_HaystackLen) && (((P_HaystackLen - j) + i) >= P_NeedleLen) )
|
||||||
|
{
|
||||||
|
while ( (i > -1) && (P_Needle[i] != P_Haystack[j]) )
|
||||||
|
{
|
||||||
|
i = P_KMP_Table[i];
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
j++;
|
||||||
|
if (i >= (int)P_NeedleLen)
|
||||||
|
{
|
||||||
|
/* Found. */
|
||||||
|
V_FindPosition = j - i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return V_FindPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Search data from right to left. ( Multiple search mode. ) */
|
||||||
|
UTSTRING_UNUSED static long _utstring_findR(
|
||||||
|
const char *P_Haystack,
|
||||||
|
size_t P_HaystackLen,
|
||||||
|
const char *P_Needle,
|
||||||
|
size_t P_NeedleLen,
|
||||||
|
long *P_KMP_Table)
|
||||||
|
{
|
||||||
|
long i, j;
|
||||||
|
long V_FindPosition = -1;
|
||||||
|
|
||||||
|
/* Search from right to left. */
|
||||||
|
j = (P_HaystackLen - 1);
|
||||||
|
i = (P_NeedleLen - 1);
|
||||||
|
while ( (j >= 0) && (j >= i) )
|
||||||
|
{
|
||||||
|
while ( (i < (int)P_NeedleLen) && (P_Needle[i] != P_Haystack[j]) )
|
||||||
|
{
|
||||||
|
i = P_KMP_Table[i + 1];
|
||||||
|
}
|
||||||
|
i--;
|
||||||
|
j--;
|
||||||
|
if (i < 0)
|
||||||
|
{
|
||||||
|
/* Found. */
|
||||||
|
V_FindPosition = j + 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return V_FindPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Search data from left to right. ( One time search mode. ) */
|
||||||
|
UTSTRING_UNUSED static long utstring_find(
|
||||||
|
UT_string *s,
|
||||||
|
long P_StartPosition, /* Start from 0. -1 means last position. */
|
||||||
|
const char *P_Needle,
|
||||||
|
size_t P_NeedleLen)
|
||||||
|
{
|
||||||
|
long V_StartPosition;
|
||||||
|
long V_HaystackLen;
|
||||||
|
long *V_KMP_Table;
|
||||||
|
long V_FindPosition = -1;
|
||||||
|
|
||||||
|
if (P_StartPosition < 0)
|
||||||
|
{
|
||||||
|
V_StartPosition = s->i + P_StartPosition;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
V_StartPosition = P_StartPosition;
|
||||||
|
}
|
||||||
|
V_HaystackLen = s->i - V_StartPosition;
|
||||||
|
if ( (V_HaystackLen >= (long) P_NeedleLen) && (P_NeedleLen > 0) )
|
||||||
|
{
|
||||||
|
V_KMP_Table = (long *)malloc(sizeof(long) * (P_NeedleLen + 1));
|
||||||
|
if (V_KMP_Table != NULL)
|
||||||
|
{
|
||||||
|
_utstring_BuildTable(P_Needle, P_NeedleLen, V_KMP_Table);
|
||||||
|
|
||||||
|
V_FindPosition = _utstring_find(s->d + V_StartPosition,
|
||||||
|
V_HaystackLen,
|
||||||
|
P_Needle,
|
||||||
|
P_NeedleLen,
|
||||||
|
V_KMP_Table);
|
||||||
|
if (V_FindPosition >= 0)
|
||||||
|
{
|
||||||
|
V_FindPosition += V_StartPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(V_KMP_Table);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return V_FindPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Search data from right to left. ( One time search mode. ) */
|
||||||
|
UTSTRING_UNUSED static long utstring_findR(
|
||||||
|
UT_string *s,
|
||||||
|
long P_StartPosition, /* Start from 0. -1 means last position. */
|
||||||
|
const char *P_Needle,
|
||||||
|
size_t P_NeedleLen)
|
||||||
|
{
|
||||||
|
long V_StartPosition;
|
||||||
|
long V_HaystackLen;
|
||||||
|
long *V_KMP_Table;
|
||||||
|
long V_FindPosition = -1;
|
||||||
|
|
||||||
|
if (P_StartPosition < 0)
|
||||||
|
{
|
||||||
|
V_StartPosition = s->i + P_StartPosition;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
V_StartPosition = P_StartPosition;
|
||||||
|
}
|
||||||
|
V_HaystackLen = V_StartPosition + 1;
|
||||||
|
if ( (V_HaystackLen >= (long) P_NeedleLen) && (P_NeedleLen > 0) )
|
||||||
|
{
|
||||||
|
V_KMP_Table = (long *)malloc(sizeof(long) * (P_NeedleLen + 1));
|
||||||
|
if (V_KMP_Table != NULL)
|
||||||
|
{
|
||||||
|
_utstring_BuildTableR(P_Needle, P_NeedleLen, V_KMP_Table);
|
||||||
|
|
||||||
|
V_FindPosition = _utstring_findR(s->d,
|
||||||
|
V_HaystackLen,
|
||||||
|
P_Needle,
|
||||||
|
P_NeedleLen,
|
||||||
|
V_KMP_Table);
|
||||||
|
|
||||||
|
free(V_KMP_Table);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return V_FindPosition;
|
||||||
|
}
|
||||||
|
/*******************************************************************************
|
||||||
|
* end substring search functions *
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#endif /* UTSTRING_H */
|
|
@ -0,0 +1,326 @@
|
||||||
|
#ifndef __KERNEL__
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <uthash/utstring.h>
|
||||||
|
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
|
static const char hex_asc[] = "0123456789abcdef";
|
||||||
|
|
||||||
|
#define hex_asc_lo(x) hex_asc[((x) & 0x0f)]
|
||||||
|
#define hex_asc_hi(x) hex_asc[((x) & 0xf0) >> 4]
|
||||||
|
|
||||||
|
char* IHW_bin2hex(char *p, const unsigned char *cp, int count)
|
||||||
|
{
|
||||||
|
while (count) {
|
||||||
|
unsigned char c = *cp++;
|
||||||
|
/* put lowercase hex digits */
|
||||||
|
*p++ = 0x20 | hex_asc[c >> 4];
|
||||||
|
*p++ = 0x20 | hex_asc[c & 0xf];
|
||||||
|
count--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hex_to_bin - convert a hex digit to its real value
|
||||||
|
* @ch: ascii character represents hex digit
|
||||||
|
*
|
||||||
|
* hex_to_bin() converts one hex digit to its actual value or -1 in case of bad
|
||||||
|
* input.
|
||||||
|
*/
|
||||||
|
int hex_to_bin(char ch)
|
||||||
|
{
|
||||||
|
if((ch >= '0') && (ch <= '9'))
|
||||||
|
{
|
||||||
|
return ch - '0';
|
||||||
|
}
|
||||||
|
|
||||||
|
ch = tolower(ch);
|
||||||
|
|
||||||
|
if((ch >= 'a') && (ch <= 'f'))
|
||||||
|
{
|
||||||
|
return ch - 'a' + 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hex_dump_to_buffer - convert a blob of data to "hex ASCII" in memory
|
||||||
|
* @buf: data blob to dump
|
||||||
|
* @len: number of bytes in the @buf
|
||||||
|
* @rowsize: number of bytes to print per line; must be 16 or 32
|
||||||
|
* @groupsize: number of bytes to print at a time (1, 2, 4, 8; default = 1)
|
||||||
|
* @linebuf: where to put the converted data
|
||||||
|
* @linebuflen: total size of @linebuf, including space for terminating NUL
|
||||||
|
* @ascii: include ASCII after the hex output
|
||||||
|
*
|
||||||
|
* hex_dump_to_buffer() works on one "line" of output at a time, i.e.,
|
||||||
|
* 16 or 32 bytes of input data converted to hex + ASCII output.
|
||||||
|
*
|
||||||
|
* Given a buffer of u8 data, hex_dump_to_buffer() converts the input data
|
||||||
|
* to a hex + ASCII dump at the supplied memory location.
|
||||||
|
* The converted output is always NUL-terminated.
|
||||||
|
*
|
||||||
|
* E.g.:
|
||||||
|
* hex_dump_to_buffer(frame->data, frame->len, 16, 1,
|
||||||
|
* linebuf, sizeof(linebuf), true);
|
||||||
|
*
|
||||||
|
* example output buffer:
|
||||||
|
* 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f @ABCDEFGHIJKLMNO
|
||||||
|
*/
|
||||||
|
void hex_dump_to_buffer(const void* buf, int len, int rowsize,
|
||||||
|
int groupsize, char* linebuf, size_t linebuflen,
|
||||||
|
int ascii)
|
||||||
|
{
|
||||||
|
const unsigned char* ptr = (const unsigned char *)buf;
|
||||||
|
unsigned char ch;
|
||||||
|
int j, lx = 0;
|
||||||
|
int ascii_column;
|
||||||
|
|
||||||
|
if(rowsize != 16 && rowsize != 32)
|
||||||
|
{
|
||||||
|
rowsize = 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!len)
|
||||||
|
{
|
||||||
|
goto nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(len > rowsize) /* limit to one line at a time */
|
||||||
|
{
|
||||||
|
len = rowsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((len % groupsize) != 0) /* no mixed size output */
|
||||||
|
{
|
||||||
|
groupsize = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(groupsize)
|
||||||
|
{
|
||||||
|
case 8:
|
||||||
|
{
|
||||||
|
const unsigned long long* ptr8 = (const unsigned long long *)buf;
|
||||||
|
int ngroups = len / groupsize;
|
||||||
|
|
||||||
|
for(j = 0; j < ngroups; j++)
|
||||||
|
lx += snprintf(linebuf + lx, linebuflen - lx,
|
||||||
|
"%s%16.16llx", j ? " " : "",
|
||||||
|
(unsigned long long) * (ptr8 + j));
|
||||||
|
|
||||||
|
ascii_column = 17 * ngroups + 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
{
|
||||||
|
const unsigned int* ptr4 = (const unsigned int *)buf;
|
||||||
|
int ngroups = len / groupsize;
|
||||||
|
|
||||||
|
for(j = 0; j < ngroups; j++)
|
||||||
|
lx += snprintf(linebuf + lx, linebuflen - lx,
|
||||||
|
"%s%8.8x", j ? " " : "", *(ptr4 + j));
|
||||||
|
|
||||||
|
ascii_column = 9 * ngroups + 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
{
|
||||||
|
const unsigned short* ptr2 = (const unsigned short *)buf;
|
||||||
|
int ngroups = len / groupsize;
|
||||||
|
|
||||||
|
for(j = 0; j < ngroups; j++)
|
||||||
|
lx += snprintf(linebuf + lx, linebuflen - lx,
|
||||||
|
"%s%4.4x", j ? " " : "", *(ptr2 + j));
|
||||||
|
|
||||||
|
ascii_column = 5 * ngroups + 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
for(j = 0; (j < len) && (lx + 3) <= linebuflen; j++)
|
||||||
|
{
|
||||||
|
ch = ptr[j];
|
||||||
|
linebuf[lx++] = hex_asc_hi(ch);
|
||||||
|
linebuf[lx++] = hex_asc_lo(ch);
|
||||||
|
linebuf[lx++] = ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
if(j)
|
||||||
|
{
|
||||||
|
lx--;
|
||||||
|
}
|
||||||
|
|
||||||
|
ascii_column = 3 * rowsize + 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!ascii)
|
||||||
|
{
|
||||||
|
goto nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
while(lx < (linebuflen - 1) && lx < (ascii_column - 1))
|
||||||
|
{
|
||||||
|
linebuf[lx++] = ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
for(j = 0; (j < len) && (lx + 2) < linebuflen; j++)
|
||||||
|
{
|
||||||
|
ch = ptr[j];
|
||||||
|
linebuf[lx++] = (isascii(ch) && isprint(ch)) ? ch : '.';
|
||||||
|
}
|
||||||
|
|
||||||
|
nil:
|
||||||
|
linebuf[lx++] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* print_hex_dump - print a text hex dump to syslog for a binary blob of data
|
||||||
|
* @level: kernel log level (e.g. KERN_DEBUG)
|
||||||
|
* @prefix_str: string to prefix each line with;
|
||||||
|
* caller supplies trailing spaces for alignment if desired
|
||||||
|
* @prefix_type: controls whether prefix of an offset, address, or none
|
||||||
|
* is printed (%DUMP_PREFIX_OFFSET, %DUMP_PREFIX_ADDRESS, %DUMP_PREFIX_NONE)
|
||||||
|
* @rowsize: number of bytes to print per line; must be 16 or 32
|
||||||
|
* @groupsize: number of bytes to print at a time (1, 2, 4, 8; default = 1)
|
||||||
|
* @buf: data blob to dump
|
||||||
|
* @len: number of bytes in the @buf
|
||||||
|
* @ascii: include ASCII after the hex output
|
||||||
|
*
|
||||||
|
* Given a buffer of u8 data, print_hex_dump() prints a hex + ASCII dump
|
||||||
|
* to the kernel log at the specified kernel log level, with an optional
|
||||||
|
* leading prefix.
|
||||||
|
*
|
||||||
|
* print_hex_dump() works on one "line" of output at a time, i.e.,
|
||||||
|
* 16 or 32 bytes of input data converted to hex + ASCII output.
|
||||||
|
* print_hex_dump() iterates over the entire input @buf, breaking it into
|
||||||
|
* "line size" chunks to format and print.
|
||||||
|
*
|
||||||
|
* E.g.:
|
||||||
|
* print_hex_dump(KERN_DEBUG, "raw data: ", DUMP_PREFIX_ADDRESS,
|
||||||
|
* 16, 1, frame->data, frame->len, true);
|
||||||
|
*
|
||||||
|
* Example output using %DUMP_PREFIX_OFFSET and 1-byte mode:
|
||||||
|
* 0009ab42: 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f @ABCDEFGHIJKLMNO
|
||||||
|
* Example output using %DUMP_PREFIX_ADDRESS and 4-byte mode:
|
||||||
|
* ffffffff88089af0: 73727170 77767574 7b7a7978 7f7e7d7c pqrstuvwxyz{|}~.
|
||||||
|
*/
|
||||||
|
void print_hex_dump(const char* prefix_str, int prefix_type,
|
||||||
|
int rowsize, int groupsize,
|
||||||
|
const void* buf, int len, int ascii)
|
||||||
|
{
|
||||||
|
const unsigned char* ptr = (const unsigned char *)buf;
|
||||||
|
int i, remaining = len;
|
||||||
|
unsigned char linebuf[32 * 3 + 2 + 32 + 1];
|
||||||
|
|
||||||
|
if(rowsize != 16 && rowsize != 32)
|
||||||
|
{
|
||||||
|
rowsize = 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i = 0; i < len; i += rowsize)
|
||||||
|
{
|
||||||
|
int linelen = MIN(remaining, rowsize);
|
||||||
|
remaining -= rowsize;
|
||||||
|
|
||||||
|
hex_dump_to_buffer(ptr + i, linelen, rowsize, groupsize,
|
||||||
|
(char *)linebuf, sizeof(linebuf), ascii);
|
||||||
|
|
||||||
|
switch(prefix_type)
|
||||||
|
{
|
||||||
|
case DUMP_PREFIX_ADDRESS:
|
||||||
|
print("%s%p: %s\n",
|
||||||
|
prefix_str, ptr + i, linebuf);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DUMP_PREFIX_OFFSET:
|
||||||
|
print("%s%.8x: %s\n", prefix_str, i, linebuf);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
print("%s%.8x: %s\n", prefix_str, i, linebuf);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
print("%s", "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* print_hex_dump_bytes - shorthand form of print_hex_dump() with default params
|
||||||
|
* @prefix_str: string to prefix each line with;
|
||||||
|
* caller supplies trailing spaces for alignment if desired
|
||||||
|
* @prefix_type: controls whether prefix of an offset, address, or none
|
||||||
|
* is printed (%DUMP_PREFIX_OFFSET, %DUMP_PREFIX_ADDRESS, %DUMP_PREFIX_NONE)
|
||||||
|
* @buf: data blob to dump
|
||||||
|
* @len: number of bytes in the @buf
|
||||||
|
*
|
||||||
|
* Calls print_hex_dump(), with log level of KERN_DEBUG,
|
||||||
|
* rowsize of 16, groupsize of 1, and ASCII output included.
|
||||||
|
*/
|
||||||
|
void print_hex_dump_bytes(const char* prefix_str, int prefix_type,
|
||||||
|
const void* buf, int len)
|
||||||
|
{
|
||||||
|
print_hex_dump(prefix_str, prefix_type, 16, 1,
|
||||||
|
buf, len, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* format_hex_buf(const char* prefix_str, int prefix_type,
|
||||||
|
int rowsize, int groupsize,
|
||||||
|
const void* buf, int len, int ascii)
|
||||||
|
{
|
||||||
|
UT_string* pLogStr = NULL;
|
||||||
|
const char* pFormatStr;
|
||||||
|
const unsigned char* ptr = (const unsigned char *)buf;
|
||||||
|
int i, remaining = len;
|
||||||
|
unsigned char linebuf[32 * 3 + 2 + 32 + 1];
|
||||||
|
|
||||||
|
if(rowsize != 16 && rowsize != 32)
|
||||||
|
{
|
||||||
|
rowsize = 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
utstring_new(pLogStr);
|
||||||
|
|
||||||
|
for(i = 0; i < len; i += rowsize)
|
||||||
|
{
|
||||||
|
int linelen = MIN(remaining, rowsize);
|
||||||
|
remaining -= rowsize;
|
||||||
|
|
||||||
|
hex_dump_to_buffer(ptr + i, linelen, rowsize, groupsize,
|
||||||
|
(char *)linebuf, sizeof(linebuf), ascii);
|
||||||
|
|
||||||
|
switch(prefix_type)
|
||||||
|
{
|
||||||
|
case DUMP_PREFIX_ADDRESS:
|
||||||
|
utstring_printf(pLogStr, "%s%p: %s\n",
|
||||||
|
prefix_str, ptr + i, linebuf);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DUMP_PREFIX_OFFSET:
|
||||||
|
utstring_printf(pLogStr, "%s%.8x: %s\n",
|
||||||
|
prefix_str, i, linebuf);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
utstring_printf(pLogStr, "%s%.8x: %s\n",
|
||||||
|
prefix_str, i, linebuf);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pFormatStr = strdup(utstring_body(pLogStr));
|
||||||
|
utstring_free(pLogStr);
|
||||||
|
|
||||||
|
return pFormatStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,514 @@
|
||||||
|
/** @file log.c
|
||||||
|
@brief 系统日志接口文件
|
||||||
|
@version 1.0.0
|
||||||
|
*/
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <uthash/utlist.h>
|
||||||
|
#include <uthash/utstring.h>
|
||||||
|
#include <uthash/utringbuffer.h>
|
||||||
|
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
|
#ifndef MAX_PATH
|
||||||
|
#define MAX_PATH (256)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SHOW_CONSOLE_RED ("\033[31;48m\033[1m%s\033[0m%c")
|
||||||
|
#define SHOW_CONSOLE_YELLOW ("\033[33;48m\033[1m%s\033[0m%c")
|
||||||
|
#define SHOW_CONSOLE_GREEN ("\033[32;48m\033[1m%s\033[0m%c")
|
||||||
|
#define SHOW_CONSOLE_BLUE ("\033[34;48m\033[1m%s\033[0m%c")
|
||||||
|
|
||||||
|
#ifdef PLATFORM_CPU
|
||||||
|
#define LOG_FILE_BASEDIR (".")
|
||||||
|
#else
|
||||||
|
#define LOG_FILE_BASEDIR ("/tmp")
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MAX_LOG_ITEM (1000)
|
||||||
|
#define MAX_LOG_FILE_SIZE (1024 * 1024)
|
||||||
|
#define LOG_PRE_SIZE (512)
|
||||||
|
|
||||||
|
#define GET_FILE_SIZE(path, size) \
|
||||||
|
do { \
|
||||||
|
struct stat st; \
|
||||||
|
memset(&st, 0, sizeof(struct stat)); \
|
||||||
|
if (stat(path, &st) != 0) { \
|
||||||
|
size = -1; \
|
||||||
|
} else { \
|
||||||
|
size = st.st_size; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
typedef struct LOG_ITEM
|
||||||
|
{
|
||||||
|
LOG_LEVEL level;
|
||||||
|
int isPrinted;
|
||||||
|
int isAddTags;
|
||||||
|
struct timeval timestamp;
|
||||||
|
char *pLogContent;
|
||||||
|
struct LOG_ITEM *next, *prev;
|
||||||
|
}*PLOG_ITEM;
|
||||||
|
|
||||||
|
typedef struct LOG_BACKUP
|
||||||
|
{
|
||||||
|
time_t timestamp;
|
||||||
|
char *plogFilePath;
|
||||||
|
char *pGzFilePath;
|
||||||
|
unsigned int sendTimes;
|
||||||
|
unsigned int tolLogs;
|
||||||
|
struct LOG_BACKUP *next, *prev;
|
||||||
|
} *PLOG_BACKUP;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
pid_t pid;
|
||||||
|
char* pChipId;
|
||||||
|
char* pChipSerial;
|
||||||
|
char exeName[MAX_PATH];
|
||||||
|
char logFilePath[MAX_PATH];
|
||||||
|
FILE *pLogFile;
|
||||||
|
} LOG_PROCESS_INFO, *PLOG_PROCESS_INFO;
|
||||||
|
|
||||||
|
static int g_bEnableLog = FALSE; // 是否启用 Log 功能
|
||||||
|
static int g_bEnLogToFile = TRUE;
|
||||||
|
static int g_bEnLogToServer = TRUE;
|
||||||
|
static char g_strLogTag[32]; // Log 标志
|
||||||
|
static unsigned int g_LogRdPos = 0;
|
||||||
|
static pthread_t g_logThreadId;
|
||||||
|
static pthread_t g_backupThreadId;
|
||||||
|
static LOG_PROCESS_INFO g_LogProcessInfo;
|
||||||
|
static pthread_mutex_t g_uvLogLock;
|
||||||
|
static PLOG_ITEM g_pLogItemList = NULL;
|
||||||
|
static PLOG_BACKUP g_pLogBackupList = NULL;
|
||||||
|
static int g_logSock = -1;
|
||||||
|
|
||||||
|
static int g_iMinLevel = LOG_Fatal | LOG_Error | LOG_Warn | LOG_Debug | LOG_Info | LOG_Step;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Log 调试等级转字符串
|
||||||
|
* @param level 调试等级
|
||||||
|
* @return 调试等级对应的字符串
|
||||||
|
*/
|
||||||
|
const char* LogLevelToStr(LOG_LEVEL level)
|
||||||
|
{
|
||||||
|
switch(level)
|
||||||
|
{
|
||||||
|
case LOG_Test:
|
||||||
|
return "T";
|
||||||
|
|
||||||
|
case LOG_Info:
|
||||||
|
return "I";
|
||||||
|
|
||||||
|
case LOG_Call:
|
||||||
|
return "C";
|
||||||
|
|
||||||
|
case LOG_Debug:
|
||||||
|
return "D";
|
||||||
|
|
||||||
|
case LOG_Warn:
|
||||||
|
return "W";
|
||||||
|
|
||||||
|
case LOG_Error:
|
||||||
|
return "E";
|
||||||
|
|
||||||
|
case LOG_Fatal:
|
||||||
|
return "F";
|
||||||
|
|
||||||
|
case LOG_Step:
|
||||||
|
return "S";
|
||||||
|
|
||||||
|
case LOG_Devp:
|
||||||
|
return "V";
|
||||||
|
|
||||||
|
case LOG_Unknown:
|
||||||
|
return "U";
|
||||||
|
|
||||||
|
case LOG_All:
|
||||||
|
return "A";
|
||||||
|
|
||||||
|
default:
|
||||||
|
return "?";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "U";
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma pack (push)
|
||||||
|
#pragma pack (1)
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
unsigned short logSeq;
|
||||||
|
unsigned int pid;
|
||||||
|
unsigned int timeStamp;
|
||||||
|
unsigned int nanotime;
|
||||||
|
unsigned int logLevel;
|
||||||
|
char logContent[0];
|
||||||
|
} LOG_PROTO_CONTENT, *PLOG_PROTO_CONTENT;
|
||||||
|
#pragma pack (pop)
|
||||||
|
|
||||||
|
static void __logColorOutput(const char* pColFmt, UT_string* pLog)
|
||||||
|
{
|
||||||
|
if(pLog == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(pColFmt == NULL)
|
||||||
|
{
|
||||||
|
print("%s", utstring_body(pLog));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(utstring_find(pLog, -1, "\n", 1) == utstring_len(pLog) - 1)
|
||||||
|
{
|
||||||
|
char* pLogArray = utstring_body(pLog);
|
||||||
|
pLogArray[utstring_len(pLog) - 1] = 0;
|
||||||
|
|
||||||
|
print(pColFmt, pLogArray, '\n');
|
||||||
|
|
||||||
|
strcat(pLogArray, "\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
print(pColFmt, utstring_body(pLog), '\0');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void* __logOutputThread(void *p)
|
||||||
|
{
|
||||||
|
while(TRUE)
|
||||||
|
{
|
||||||
|
int isWriteLog = FALSE;
|
||||||
|
PLOG_ITEM pItem = NULL, pTmp = NULL;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&g_uvLogLock);
|
||||||
|
|
||||||
|
LL_FOREACH_SAFE(g_pLogItemList, pItem, pTmp)
|
||||||
|
{
|
||||||
|
UT_string *pLogStr;
|
||||||
|
struct tm lTime;
|
||||||
|
int logFileSize = 0;
|
||||||
|
|
||||||
|
if(++g_LogRdPos % 100 == 0)
|
||||||
|
{
|
||||||
|
GET_FILE_SIZE(g_LogProcessInfo.logFilePath, logFileSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
localtime_r(&(pItem->timestamp.tv_sec), &lTime);
|
||||||
|
|
||||||
|
utstring_new(pLogStr);
|
||||||
|
|
||||||
|
if(pItem->isAddTags)
|
||||||
|
{
|
||||||
|
utstring_printf(pLogStr, "[%04d-%02d-%02d %02d:%02d:%02d.%03ld] [%s] %s",
|
||||||
|
lTime.tm_year + 1900, lTime.tm_mon + 1, lTime.tm_mday,
|
||||||
|
lTime.tm_hour, lTime.tm_min, lTime.tm_sec, pItem->timestamp.tv_usec / 1000,
|
||||||
|
LogLevelToStr(pItem->level), pItem->pLogContent);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
utstring_printf(pLogStr, "%s", pItem->pLogContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(pItem->isPrinted == FALSE)
|
||||||
|
{
|
||||||
|
if(pItem->level & LOG_Error
|
||||||
|
|| pItem->level & LOG_Fatal)
|
||||||
|
{
|
||||||
|
__logColorOutput(SHOW_CONSOLE_RED, pLogStr);
|
||||||
|
}
|
||||||
|
else if(pItem->level & LOG_Warn
|
||||||
|
|| pItem->level & LOG_Unknown)
|
||||||
|
{
|
||||||
|
__logColorOutput(SHOW_CONSOLE_YELLOW, pLogStr);
|
||||||
|
}
|
||||||
|
else if(pItem->level & LOG_Test
|
||||||
|
|| pItem->level & LOG_Call)
|
||||||
|
{
|
||||||
|
__logColorOutput(SHOW_CONSOLE_BLUE, pLogStr);
|
||||||
|
}
|
||||||
|
else if(pItem->level & LOG_Devp)
|
||||||
|
{
|
||||||
|
__logColorOutput(SHOW_CONSOLE_GREEN, pLogStr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
print("%s", utstring_body(pLogStr));
|
||||||
|
}
|
||||||
|
|
||||||
|
pItem->isPrinted = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
if(g_logSock != -1 && GetCurrWIFIConnStatus() == WIFI_CONNECTED)
|
||||||
|
{
|
||||||
|
__logNetworkSend(pItem);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if(g_LogProcessInfo.pLogFile != NULL && g_bEnLogToFile)
|
||||||
|
{
|
||||||
|
if(logFileSize >= MAX_LOG_FILE_SIZE)
|
||||||
|
{
|
||||||
|
fflush(g_LogProcessInfo.pLogFile);
|
||||||
|
fclose(g_LogProcessInfo.pLogFile);
|
||||||
|
|
||||||
|
g_LogProcessInfo.pLogFile = fopen(g_LogProcessInfo.logFilePath, "w+");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(g_LogProcessInfo.pLogFile)
|
||||||
|
{
|
||||||
|
fwrite(utstring_body(pLogStr), 1, utstring_len(pLogStr), g_LogProcessInfo.pLogFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
isWriteLog = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
LL_DELETE(g_pLogItemList, pItem);
|
||||||
|
|
||||||
|
utstring_free(pLogStr);
|
||||||
|
free(pItem->pLogContent);
|
||||||
|
free(pItem);
|
||||||
|
|
||||||
|
if(g_LogRdPos % 100 == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&g_uvLogLock);
|
||||||
|
|
||||||
|
usleep(1000);
|
||||||
|
if(g_LogProcessInfo.pLogFile != NULL && isWriteLog)
|
||||||
|
{
|
||||||
|
fflush(g_LogProcessInfo.pLogFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_detach(pthread_self());
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置调试等级
|
||||||
|
* @param level 调试等级
|
||||||
|
* @param iEnable 1 打开调试等级, 0 关闭调试等级
|
||||||
|
*/
|
||||||
|
void IHW_EnableLogLevel(LOG_LEVEL level, int iEnable)
|
||||||
|
{
|
||||||
|
if(iEnable > 0)
|
||||||
|
{
|
||||||
|
g_iMinLevel |= level;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_iMinLevel &= ~(level);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 初始化系统日志功能
|
||||||
|
* @param pLogTag 系统日志标志
|
||||||
|
* @param pPath 系统日志保存路径
|
||||||
|
* @param bEnable 打开/关闭调试信息
|
||||||
|
*/
|
||||||
|
void IHW_InitLOG(const char* pLogTag, const char* pPath, int bEnable)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
char strPath[MAX_PATH];
|
||||||
|
|
||||||
|
g_LogRdPos = 0;
|
||||||
|
memset(g_strLogTag, 0, 32);
|
||||||
|
|
||||||
|
memset(&g_LogProcessInfo, 0, sizeof(LOG_PROCESS_INFO));
|
||||||
|
|
||||||
|
if(pLogTag == NULL)
|
||||||
|
{
|
||||||
|
strcpy(g_strLogTag, "");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
strncpy(g_strLogTag, pLogTag, 31);
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(strPath, 0, MAX_PATH);
|
||||||
|
|
||||||
|
g_LogProcessInfo.pid = getpid();
|
||||||
|
if(readlink("/proc/self/exe", strPath, MAX_PATH) == -1)
|
||||||
|
{
|
||||||
|
strcpy(g_LogProcessInfo.exeName, pLogTag);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char *pExeName = strrchr(strPath, '/');
|
||||||
|
|
||||||
|
if(pExeName == NULL)
|
||||||
|
{
|
||||||
|
strncpy(g_LogProcessInfo.exeName, strPath, MAX_PATH - 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
strncpy(g_LogProcessInfo.exeName, pExeName + 1, MAX_PATH - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//fprintf(stdout, "pid = %d, name = %s\n", g_LogProcessInfo.pid, g_LogProcessInfo.exeName);
|
||||||
|
g_LogProcessInfo.pChipId = "";
|
||||||
|
g_LogProcessInfo.pChipSerial = "";
|
||||||
|
memset(g_LogProcessInfo.logFilePath, 0, MAX_PATH);
|
||||||
|
sprintf(g_LogProcessInfo.logFilePath, "%s/%s_%d.log", LOG_FILE_BASEDIR, g_LogProcessInfo.exeName, g_LogProcessInfo.pid);
|
||||||
|
|
||||||
|
memset(strPath, 0, MAX_PATH);
|
||||||
|
sprintf(strPath, "rm -f %s/%s_*.log > /dev/zero", LOG_FILE_BASEDIR, g_LogProcessInfo.exeName);
|
||||||
|
ret = system(strPath);
|
||||||
|
|
||||||
|
g_LogProcessInfo.pLogFile = fopen(g_LogProcessInfo.logFilePath, "w+");
|
||||||
|
|
||||||
|
g_bEnableLog = bEnable;
|
||||||
|
|
||||||
|
// __getCfgFromCfgFile();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void IHW_RunLogService(void)
|
||||||
|
{
|
||||||
|
pthread_create(&g_logThreadId, NULL, __logOutputThread, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __logTo(LOG_LEVEL level, int isAddTag, char* pMsg, int isPrint)
|
||||||
|
{
|
||||||
|
PLOG_ITEM pLogItem;
|
||||||
|
|
||||||
|
pLogItem = (PLOG_ITEM)malloc(sizeof(struct LOG_ITEM));
|
||||||
|
|
||||||
|
if(pLogItem == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pLogItem->pLogContent = strdup(pMsg);
|
||||||
|
pLogItem->isPrinted = isPrint ? FALSE : TRUE;
|
||||||
|
pLogItem->level = level;
|
||||||
|
pLogItem->isAddTags = isAddTag ? TRUE : FALSE;
|
||||||
|
gettimeofday(&(pLogItem->timestamp), NULL);
|
||||||
|
|
||||||
|
pthread_mutex_lock(&g_uvLogLock);
|
||||||
|
LL_APPEND(g_pLogItemList, pLogItem);
|
||||||
|
pthread_mutex_unlock(&g_uvLogLock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IHW_LogStrWithoutPrint(int level, char* pMsg)
|
||||||
|
{
|
||||||
|
__logTo(level, TRUE, pMsg, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IHW_LogRawString(int level, char* pMsg)
|
||||||
|
{
|
||||||
|
__logTo(level, TRUE, pMsg, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 输出调试信息
|
||||||
|
* @param cFlag 调试信息开关
|
||||||
|
* @param pMsg 调试信息内容
|
||||||
|
*/
|
||||||
|
void IHW_LOG_UNTAG(LOG_LEVEL level, const char* pMsg, ...)
|
||||||
|
{
|
||||||
|
va_list arg_ptr;
|
||||||
|
UT_string *pLogContent;
|
||||||
|
|
||||||
|
if(!g_bEnableLog)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查调试等级
|
||||||
|
if(!(g_iMinLevel & level))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
utstring_new(pLogContent);
|
||||||
|
va_start(arg_ptr, pMsg);
|
||||||
|
utstring_printf_va(pLogContent, pMsg, arg_ptr);
|
||||||
|
va_end(arg_ptr);
|
||||||
|
|
||||||
|
__logTo(level, FALSE, utstring_body(pLogContent), TRUE);
|
||||||
|
|
||||||
|
utstring_free(pLogContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 输出调试信息
|
||||||
|
* @param cFlag 调试信息开关
|
||||||
|
* @param pMsg 调试信息内容
|
||||||
|
*/
|
||||||
|
void IHW_LOG(LOG_LEVEL level, const char* pMsg, ...)
|
||||||
|
{
|
||||||
|
UT_string* pLogContent = NULL;
|
||||||
|
va_list arg_ptr;
|
||||||
|
|
||||||
|
if(!g_bEnableLog)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查调试等级
|
||||||
|
if(!(g_iMinLevel & level))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
utstring_new(pLogContent);
|
||||||
|
va_start(arg_ptr, pMsg);
|
||||||
|
utstring_printf_va(pLogContent, pMsg, arg_ptr);
|
||||||
|
va_end(arg_ptr);
|
||||||
|
|
||||||
|
__logTo(level, TRUE, utstring_body(pLogContent), TRUE);
|
||||||
|
|
||||||
|
utstring_free(pLogContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IHW_DisableLogOut(void)
|
||||||
|
{
|
||||||
|
g_bEnableLog = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IHW_EnableLogOut(void)
|
||||||
|
{
|
||||||
|
g_bEnableLog = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* LogLeveToString(LOG_LEVEL lv)
|
||||||
|
{
|
||||||
|
switch(lv)
|
||||||
|
{
|
||||||
|
case LOG_Fatal: return "LOG_Fatal";
|
||||||
|
case LOG_Error: return "LOG_Error";
|
||||||
|
case LOG_Warn: return "LOG_Warn";
|
||||||
|
case LOG_Debug: return "LOG_Debug";
|
||||||
|
case LOG_Info: return "LOG_Info";
|
||||||
|
case LOG_Test: return "LOG_Test";
|
||||||
|
case LOG_Call: return "LOG_Call";
|
||||||
|
case LOG_Devp: return "LOG_Devp";
|
||||||
|
case LOG_Step: return "LOG_Step";
|
||||||
|
case LOG_Unknown: return "LOG_Unknown";
|
||||||
|
case LOG_All: return "LOG_All";
|
||||||
|
case LOG_Close: return "LOG_Close";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "Unknown";
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,90 @@
|
||||||
|
/*
|
||||||
|
***************************************************************************
|
||||||
|
* Ralink Tech Inc.
|
||||||
|
* 4F, No. 2 Technology 5th Rd.
|
||||||
|
* Science-based Industrial Park
|
||||||
|
* Hsin-chu, Taiwan, R.O.C.
|
||||||
|
*
|
||||||
|
* (c) Copyright, Ralink Technology, Inc.
|
||||||
|
*
|
||||||
|
* All rights reserved. Ralink's source code is an unpublished work and the
|
||||||
|
* use of a copyright notice does not imply otherwise. This source code
|
||||||
|
* contains confidential trade secret material of Ralink Tech. Any attemp
|
||||||
|
* or participation in deciphering, decoding, reverse engineering or in any
|
||||||
|
* way altering the source code is stricitly prohibited, unless the prior
|
||||||
|
* written consent of Ralink Technology, Inc. is obtained.
|
||||||
|
***************************************************************************
|
||||||
|
*
|
||||||
|
* $Id: //WIFI_SOC/MP/SDK_4_3_0_0/RT288x_SDK/source/user/rt2880_app/gpio/gpio.c#1 $
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <curl/curl.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <openssl/evp.h>
|
||||||
|
#include <openssl/sha.h>
|
||||||
|
#include <mosquitto.h>
|
||||||
|
|
||||||
|
#include "uthash/utstring.h"
|
||||||
|
|
||||||
|
#include "mqtt.h"
|
||||||
|
#include "http.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
|
||||||
|
int evp_sha1(void)
|
||||||
|
{
|
||||||
|
unsigned char result[SHA512_DIGEST_LENGTH];
|
||||||
|
const char* pSrc = "8e92003eb2f95wYFsgJd002aO2123456";
|
||||||
|
memset(result, 0, SHA512_DIGEST_LENGTH);
|
||||||
|
|
||||||
|
size_t len = strlen(pSrc);
|
||||||
|
|
||||||
|
EVP_MD_CTX evpCtx;
|
||||||
|
EVP_MD_CTX_init(&evpCtx);
|
||||||
|
|
||||||
|
EVP_DigestInit_ex(&evpCtx, EVP_sha1(), NULL);
|
||||||
|
EVP_DigestUpdate(&evpCtx, pSrc, len);
|
||||||
|
EVP_DigestFinal_ex(&evpCtx, result, &len);
|
||||||
|
|
||||||
|
EVP_MD_CTX_cleanup(&evpCtx);
|
||||||
|
|
||||||
|
print_hex_dump_bytes("SHA1", DUMP_PREFIX_OFFSET, result, SHA512_DIGEST_LENGTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
int major, minor, rev;
|
||||||
|
struct mosquitto *pMosq = NULL;
|
||||||
|
|
||||||
|
IHW_InitLOG("MQTT", NULL, TRUE);
|
||||||
|
IHW_EnableLogLevel(LOG_Fatal | LOG_Error | LOG_Warn | LOG_Debug | LOG_Info, 1);
|
||||||
|
IHW_RunLogService();
|
||||||
|
|
||||||
|
APP_BUILD_INFO("MQTT_Proxy", CURRENT_VERSION);
|
||||||
|
|
||||||
|
curl_global_init(CURL_GLOBAL_ALL);
|
||||||
|
mosquitto_lib_init();
|
||||||
|
|
||||||
|
//evp_sha1();
|
||||||
|
//curl_init();
|
||||||
|
//device_register();
|
||||||
|
//mqtt_init();
|
||||||
|
mqtt_proxy_setup();
|
||||||
|
|
||||||
|
while(TRUE)
|
||||||
|
{
|
||||||
|
|
||||||
|
usleep(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
mosquitto_lib_cleanup();
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue