first commit for opensource
first commit for opensource
This commit is contained in:
@@ -0,0 +1,317 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making IoT Hub available.
|
||||
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
|
||||
* Licensed under the MIT License (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://opensource.org/licenses/MIT
|
||||
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is
|
||||
* distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
#ifndef QCLOUD_IOT_UTILS_AES_H_
|
||||
#define QCLOUD_IOT_UTILS_AES_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
//========Platform================================//
|
||||
#define UTILS_AES_C
|
||||
#define UTILS_CIPHER_MODE_CBC
|
||||
//#define UTILS_SELF_TEST
|
||||
|
||||
#define UTILS_ERR_PLATFORM_HW_ACCEL_FAILED -0x0070 /**< Hardware accelerator failed */
|
||||
#define UTILS_ERR_PLATFORM_FEATURE_UNSUPPORTED -0x0072 /**< The requested feature is not supported by the platform */
|
||||
|
||||
/* Internal macros meant to be called only from within the library. */
|
||||
#define UTILS_INTERNAL_VALIDATE_RET( cond, ret ) do { } while( 0 )
|
||||
#define UTILS_INTERNAL_VALIDATE( cond ) do { } while( 0 )
|
||||
//==============================================//
|
||||
|
||||
/* padlock.c and aesni.c rely on these values! */
|
||||
#define UTILS_AES_ENCRYPT 1 /**< AES encryption. */
|
||||
#define UTILS_AES_DECRYPT 0 /**< AES decryption. */
|
||||
|
||||
#define UTILS_AES_BLOCK_LEN 16
|
||||
#define AES_KEY_BITS_128 128
|
||||
#define AES_KEY_BITS_192 192
|
||||
#define AES_KEY_BITS_256 256
|
||||
|
||||
|
||||
/* Error codes in range 0x0020-0x0022 */
|
||||
#define UTILS_ERR_AES_INVALID_KEY_LENGTH -0x0020 /**< Invalid key length. */
|
||||
#define UTILS_ERR_AES_INVALID_INPUT_LENGTH -0x0022 /**< Invalid data input length. */
|
||||
|
||||
/* Error codes in range 0x0021-0x0025 */
|
||||
#define UTILS_ERR_AES_BAD_INPUT_DATA -0x0021 /**< Invalid input data. */
|
||||
|
||||
/* UTILS_ERR_AES_FEATURE_UNAVAILABLE is deprecated and should not be used. */
|
||||
#define UTILS_ERR_AES_FEATURE_UNAVAILABLE -0x0023 /**< Feature not available. For example, an unsupported AES key size. */
|
||||
|
||||
/* UTILS_ERR_AES_HW_ACCEL_FAILED is deprecated and should not be used. */
|
||||
#define UTILS_ERR_AES_HW_ACCEL_FAILED -0x0025 /**< AES hardware accelerator failed. */
|
||||
|
||||
|
||||
#if !defined(UTILS_AES_ALT)
|
||||
// Regular implementation
|
||||
//
|
||||
|
||||
/**
|
||||
* \brief The AES context-type definition.
|
||||
*/
|
||||
typedef struct utils_aes_context
|
||||
{
|
||||
int nr; /*!< The number of rounds. */
|
||||
uint32_t *rk; /*!< AES round keys. */
|
||||
uint32_t buf[68]; /*!< Unaligned data buffer. This buffer can
|
||||
hold 32 extra Bytes, which can be used for
|
||||
one of the following purposes:
|
||||
<ul><li>Alignment if VIA padlock is
|
||||
used.</li>
|
||||
<li>Simplifying key expansion in the 256-bit
|
||||
case by generating an extra round key.
|
||||
</li></ul> */
|
||||
}
|
||||
utils_aes_context;
|
||||
|
||||
#else /* UTILS_AES_ALT */
|
||||
#include "aes_alt.h"
|
||||
#endif /* UTILS_AES_ALT */
|
||||
|
||||
/**
|
||||
* \brief This function initializes the specified AES context.
|
||||
*
|
||||
* It must be the first API called before using
|
||||
* the context.
|
||||
*
|
||||
* \param ctx The AES context to initialize. This must not be \c NULL.
|
||||
*/
|
||||
void utils_aes_init( utils_aes_context *ctx );
|
||||
|
||||
/**
|
||||
* \brief This function releases and clears the specified AES context.
|
||||
*
|
||||
* \param ctx The AES context to clear.
|
||||
* If this is \c NULL, this function does nothing.
|
||||
* Otherwise, the context must have been at least initialized.
|
||||
*/
|
||||
void utils_aes_free( utils_aes_context *ctx );
|
||||
|
||||
|
||||
/**
|
||||
* \brief This function sets the encryption key.
|
||||
*
|
||||
* \param ctx The AES context to which the key should be bound.
|
||||
* It must be initialized.
|
||||
* \param key The encryption key.
|
||||
* This must be a readable buffer of size \p keybits bits.
|
||||
* \param keybits The size of data passed in bits. Valid options are:
|
||||
* <ul><li>128 bits</li>
|
||||
* <li>192 bits</li>
|
||||
* <li>256 bits</li></ul>
|
||||
*
|
||||
* \return \c 0 on success.
|
||||
* \return #UTILS_ERR_AES_INVALID_KEY_LENGTH on failure.
|
||||
*/
|
||||
int utils_aes_setkey_enc( utils_aes_context *ctx, const unsigned char *key,
|
||||
unsigned int keybits );
|
||||
|
||||
/**
|
||||
* \brief This function sets the decryption key.
|
||||
*
|
||||
* \param ctx The AES context to which the key should be bound.
|
||||
* It must be initialized.
|
||||
* \param key The decryption key.
|
||||
* This must be a readable buffer of size \p keybits bits.
|
||||
* \param keybits The size of data passed. Valid options are:
|
||||
* <ul><li>128 bits</li>
|
||||
* <li>192 bits</li>
|
||||
* <li>256 bits</li></ul>
|
||||
*
|
||||
* \return \c 0 on success.
|
||||
* \return #UTILS_ERR_AES_INVALID_KEY_LENGTH on failure.
|
||||
*/
|
||||
int utils_aes_setkey_dec( utils_aes_context *ctx, const unsigned char *key,
|
||||
unsigned int keybits );
|
||||
|
||||
|
||||
/**
|
||||
* \brief This function performs an AES single-block encryption or
|
||||
* decryption operation.
|
||||
*
|
||||
* It performs the operation defined in the \p mode parameter
|
||||
* (encrypt or decrypt), on the input data buffer defined in
|
||||
* the \p input parameter.
|
||||
*
|
||||
* utils_aes_init(), and either utils_aes_setkey_enc() or
|
||||
* utils_aes_setkey_dec() must be called before the first
|
||||
* call to this API with the same context.
|
||||
*
|
||||
* \param ctx The AES context to use for encryption or decryption.
|
||||
* It must be initialized and bound to a key.
|
||||
* \param mode The AES operation: #UTILS_AES_ENCRYPT or
|
||||
* #UTILS_AES_DECRYPT.
|
||||
* \param input The buffer holding the input data.
|
||||
* It must be readable and at least \c 16 Bytes long.
|
||||
* \param output The buffer where the output data will be written.
|
||||
* It must be writeable and at least \c 16 Bytes long.
|
||||
|
||||
* \return \c 0 on success.
|
||||
*/
|
||||
int utils_aes_crypt_ecb( utils_aes_context *ctx,
|
||||
int mode,
|
||||
const unsigned char input[16],
|
||||
unsigned char output[16] );
|
||||
|
||||
#if defined(UTILS_CIPHER_MODE_CBC)
|
||||
/**
|
||||
* \brief This function performs an AES-CBC encryption or decryption operation
|
||||
* on full blocks.
|
||||
*
|
||||
* It performs the operation defined in the \p mode
|
||||
* parameter (encrypt/decrypt), on the input data buffer defined in
|
||||
* the \p input parameter.
|
||||
*
|
||||
* It can be called as many times as needed, until all the input
|
||||
* data is processed. utils_aes_init(), and either
|
||||
* utils_aes_setkey_enc() or utils_aes_setkey_dec() must be called
|
||||
* before the first call to this API with the same context.
|
||||
*
|
||||
* \note This function operates on full blocks, that is, the input size
|
||||
* must be a multiple of the AES block size of \c 16 Bytes.
|
||||
*
|
||||
* \note Upon exit, the content of the IV is updated so that you can
|
||||
* call the same function again on the next
|
||||
* block(s) of data and get the same result as if it was
|
||||
* encrypted in one call. This allows a "streaming" usage.
|
||||
* If you need to retain the contents of the IV, you should
|
||||
* either save it manually or use the cipher module instead.
|
||||
*
|
||||
*
|
||||
* \param ctx The AES context to use for encryption or decryption.
|
||||
* It must be initialized and bound to a key.
|
||||
* \param mode The AES operation: #UTILS_AES_ENCRYPT or
|
||||
* #UTILS_AES_DECRYPT.
|
||||
* \param length The length of the input data in Bytes. This must be a
|
||||
* multiple of the block size (\c 16 Bytes).
|
||||
* \param iv Initialization vector (updated after use).
|
||||
* It must be a readable and writeable buffer of \c 16 Bytes.
|
||||
* \param input The buffer holding the input data.
|
||||
* It must be readable and of size \p length Bytes.
|
||||
* \param output The buffer holding the output data.
|
||||
* It must be writeable and of size \p length Bytes.
|
||||
*
|
||||
* \return \c 0 on success.
|
||||
* \return #UTILS_ERR_AES_INVALID_INPUT_LENGTH
|
||||
* on failure.
|
||||
*/
|
||||
int utils_aes_crypt_cbc( utils_aes_context *ctx,
|
||||
int mode,
|
||||
size_t length,
|
||||
unsigned char iv[16],
|
||||
const unsigned char *input,
|
||||
unsigned char *output );
|
||||
#endif /* UTILS_CIPHER_MODE_CBC */
|
||||
|
||||
|
||||
/**
|
||||
* \brief Internal AES block encryption function. This is only
|
||||
* exposed to allow overriding it using
|
||||
* \c UTILS_AES_ENCRYPT_ALT.
|
||||
*
|
||||
* \param ctx The AES context to use for encryption.
|
||||
* \param input The plaintext block.
|
||||
* \param output The output (ciphertext) block.
|
||||
*
|
||||
* \return \c 0 on success.
|
||||
*/
|
||||
int utils_internal_aes_encrypt( utils_aes_context *ctx,
|
||||
const unsigned char input[16],
|
||||
unsigned char output[16] );
|
||||
|
||||
/**
|
||||
* \brief Internal AES block decryption function. This is only
|
||||
* exposed to allow overriding it using see
|
||||
* \c UTILS_AES_DECRYPT_ALT.
|
||||
*
|
||||
* \param ctx The AES context to use for decryption.
|
||||
* \param input The ciphertext block.
|
||||
* \param output The output (plaintext) block.
|
||||
*
|
||||
* \return \c 0 on success.
|
||||
*/
|
||||
int utils_internal_aes_decrypt( utils_aes_context *ctx,
|
||||
const unsigned char input[16],
|
||||
unsigned char output[16] );
|
||||
|
||||
#if !defined(UTILS_DEPRECATED_REMOVED)
|
||||
#if defined(UTILS_DEPRECATED_WARNING)
|
||||
#define UTILS_DEPRECATED __attribute__((deprecated))
|
||||
#else
|
||||
#define UTILS_DEPRECATED
|
||||
#endif
|
||||
/**
|
||||
* \brief Deprecated internal AES block encryption function
|
||||
* without return value.
|
||||
*
|
||||
* \deprecated Superseded by utils_internal_aes_encrypt()
|
||||
*
|
||||
* \param ctx The AES context to use for encryption.
|
||||
* \param input Plaintext block.
|
||||
* \param output Output (ciphertext) block.
|
||||
*/
|
||||
UTILS_DEPRECATED void utils_aes_encrypt( utils_aes_context *ctx,
|
||||
const unsigned char input[16],
|
||||
unsigned char output[16] );
|
||||
|
||||
/**
|
||||
* \brief Deprecated internal AES block decryption function
|
||||
* without return value.
|
||||
*
|
||||
* \deprecated Superseded by utils_internal_aes_decrypt()
|
||||
*
|
||||
* \param ctx The AES context to use for decryption.
|
||||
* \param input Ciphertext block.
|
||||
* \param output Output (plaintext) block.
|
||||
*/
|
||||
UTILS_DEPRECATED void utils_aes_decrypt( utils_aes_context *ctx,
|
||||
const unsigned char input[16],
|
||||
unsigned char output[16] );
|
||||
|
||||
#undef UTILS_DEPRECATED
|
||||
#endif /* !UTILS_DEPRECATED_REMOVED */
|
||||
|
||||
|
||||
#if defined(UTILS_SELF_TEST)
|
||||
/**
|
||||
* \brief Checkup routine.
|
||||
*
|
||||
* \return \c 0 on success.
|
||||
* \return \c 1 on failure.
|
||||
*/
|
||||
int utils_aes_self_test( int verbose );
|
||||
|
||||
#endif /* UTILS_SELF_TEST */
|
||||
|
||||
int aes_sample(int verbose);
|
||||
|
||||
|
||||
int utils_aes_cbc(uint8_t *pInData, uint32_t datalen,
|
||||
uint8_t *pOutData, uint32_t outBuffLen,
|
||||
uint8_t mode, uint8_t *pKey,
|
||||
uint16_t keybits, uint8_t *iv);
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making IoT Hub available.
|
||||
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
|
||||
* Licensed under the MIT License (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://opensource.org/licenses/MIT
|
||||
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is
|
||||
* distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef QCLOUD_IOT_UTILS_BASE64_H_
|
||||
#define QCLOUD_IOT_UTILS_BASE64_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "qcloud.h"
|
||||
|
||||
int qcloud_utils_base64_encode( unsigned char *dst, size_t dlen, size_t *olen,
|
||||
const unsigned char *src, size_t slen );
|
||||
|
||||
int qcloud_utils_base64_decode( unsigned char *dst, size_t dlen, size_t *olen,
|
||||
const unsigned char *src, size_t slen );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* QCLOUD_IOT_UTILS_BASE64_H_ */
|
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making IoT Hub available.
|
||||
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
|
||||
* Licensed under the MIT License (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://opensource.org/licenses/MIT
|
||||
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is
|
||||
* distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef QCLOUD_IOT_UTILS_HMAC_H_
|
||||
#define QCLOUD_IOT_UTILS_HMAC_H_
|
||||
|
||||
#include <string.h>
|
||||
|
||||
void utils_hmac_md5(const char *msg, int msg_len, char *digest, const char *key, int key_len);
|
||||
|
||||
void utils_hmac_sha1(const char *msg, int msg_len, char *digest, const char *key, int key_len);
|
||||
|
||||
#endif
|
||||
|
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making IoT Hub available.
|
||||
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
|
||||
* Licensed under the MIT License (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://opensource.org/licenses/MIT
|
||||
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is
|
||||
* distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef QCLOUD_IOT_UTILS_HTTPC_H_
|
||||
#define QCLOUD_IOT_UTILS_HTTPC_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#define HTTP_PORT 80
|
||||
#define HTTPS_PORT 443
|
||||
|
||||
typedef enum {
|
||||
HTTP_GET,
|
||||
HTTP_POST,
|
||||
HTTP_PUT,
|
||||
HTTP_DELETE,
|
||||
HTTP_HEAD
|
||||
} HttpMethod;
|
||||
|
||||
typedef struct {
|
||||
int remote_port; // 端口号
|
||||
int response_code; // 响应码
|
||||
char *header; // 自定义头部
|
||||
char *auth_user; // 身份验证的用户名
|
||||
char *auth_password; // 身份验证的密码
|
||||
qcloud_network_t network;
|
||||
} HTTPClient;
|
||||
|
||||
typedef struct {
|
||||
bool is_more; // 是否需要检索更多的数据
|
||||
bool is_chunked; // 响应数据是否以分块进行编码
|
||||
int retrieve_len; // 要检索的内容长度
|
||||
int response_content_len; // 响应内容长度
|
||||
int post_buf_len; // post data length
|
||||
int response_buf_len; // 响应包缓冲区长度
|
||||
char *post_content_type; // post数据的内容类型
|
||||
char *post_buf; // post的数据
|
||||
char *response_buf; // 存储响应数据的缓冲区
|
||||
} HTTPClientData;
|
||||
|
||||
/**
|
||||
* @brief http 网络请求
|
||||
*
|
||||
* @param client http client
|
||||
* @param url 请求url
|
||||
* @param port 请求端口
|
||||
* @param ca_crt_dir ca证书路径
|
||||
* @param method 请求方法
|
||||
* @param client_data http数据负载
|
||||
* @return 返回QCLOUD_ERR_SUCCESS, 表示设置成功
|
||||
*/
|
||||
int qcloud_http_client_common(HTTPClient *client, const char *url, int port, const char *ca_crt, HttpMethod method, HTTPClientData *client_data);
|
||||
|
||||
int qcloud_http_recv_data(HTTPClient *client, uint32_t timeout_ms, HTTPClientData *client_data);
|
||||
|
||||
int qcloud_http_client_connect(HTTPClient *client, const char *url, int port, const char *ca_crt);
|
||||
|
||||
void qcloud_http_client_close(HTTPClient *client);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* QCLOUD_IOT_UTILS_HTTPC_H_ */
|
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
* Copyright (c) 2017-2019 Tencent Group. All rights reserved.
|
||||
* License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __JSON_PARSER_H__
|
||||
#define __JSON_PARSER_H__
|
||||
|
||||
/**
|
||||
The descriptions of the json value node type
|
||||
**/
|
||||
enum JSONTYPE {
|
||||
JSNONE = -1,
|
||||
JSSTRING = 0,
|
||||
JSOBJECT,
|
||||
JSARRAY,
|
||||
JSNUMBER,
|
||||
JSBOOLEAN,
|
||||
JSNULL,
|
||||
JSTYPEMAX
|
||||
};
|
||||
|
||||
/**
|
||||
The error codes produced by the JSON parsers
|
||||
**/
|
||||
enum JSON_PARSE_CODE {
|
||||
JSON_PARSE_ERR,
|
||||
JSON_PARSE_OK,
|
||||
JSON_PARSE_FINISH
|
||||
};
|
||||
|
||||
/**
|
||||
The return codes produced by the JSON parsers
|
||||
**/
|
||||
enum JSON_PARSE_RESULT {
|
||||
JSON_RESULT_ERR = -1,
|
||||
JSON_RESULT_OK
|
||||
};
|
||||
|
||||
typedef int (*json_parse_cb)(char *p_cName, int iNameLen, char *p_cValue, int iValueLen, int iValueType,
|
||||
void *p_Result);
|
||||
|
||||
/**
|
||||
* @brief Parse the JSON string, and iterate through all keys and values,
|
||||
* then handle the keys and values by callback function.
|
||||
*
|
||||
* @param[in] p_cJsonStr @n The JSON string
|
||||
* @param[in] iStrLen @n The JSON string length
|
||||
* @param[in] pfnCB @n Callback function
|
||||
* @param[out] p_CBData @n User data
|
||||
* @return JSON_RESULT_OK success, JSON_RESULT_ERR failed
|
||||
* @see None.
|
||||
* @note None.
|
||||
**/
|
||||
int json_parse_name_value(char *p_cJsonStr, int iStrLen, json_parse_cb pfnCB, void *p_CBData);
|
||||
|
||||
/**
|
||||
* @brief Get the value by a specified key from a json string
|
||||
*
|
||||
* @param[in] p_cJsonStr @n the JSON string
|
||||
* @param[in] iStrLen @n the JSON string length
|
||||
* @param[in] p_cName @n the specified key string
|
||||
* @param[out] p_iValueLen @n the value length
|
||||
* @param[out] p_iValueType @n the value type
|
||||
* @return A pointer to the value
|
||||
* @see None.
|
||||
* @note None.
|
||||
**/
|
||||
char *json_get_value_by_name(char *p_cJsonStr, int iStrLen, char *p_cName, int *p_iValueLen, int *p_iValueType);
|
||||
|
||||
/**
|
||||
* @brief Get the JSON object point associate with a given type.
|
||||
*
|
||||
* @param[in] type @n The object type
|
||||
* @param[in] str @n The JSON string
|
||||
* @returns The json object point with the given field type.
|
||||
* @see None.
|
||||
* @note None.
|
||||
*/
|
||||
char *json_get_object(int type, char *str);
|
||||
char *json_get_next_object(int type, char *str, char **key, int *key_len, char **val, int *val_len, int *val_type);
|
||||
|
||||
/**
|
||||
* @brief retrieve each key&value pair from the json string
|
||||
*
|
||||
* @param[in] str @n Json string to revolve
|
||||
* @param[in] pos @n cursor
|
||||
* @param[out] key @n pointer to the next Key object
|
||||
* @param[out] klen @n Key object length
|
||||
* @param[out] val @n pointer to the next Value object
|
||||
* @param[out] vlen @n Value object length
|
||||
* @param[out] vtype @n Value object type(digital, string, object, array)
|
||||
* @see None.
|
||||
* @note None.
|
||||
*/
|
||||
#define json_object_for_each_kv(str, pos, key, klen, val, vlen, vtype) \
|
||||
for (pos = json_get_object(JSOBJECT, str); \
|
||||
pos!=0 && *pos!=0 && (pos=json_get_next_object(JSOBJECT, pos, &key, &klen, &val, &vlen, &vtype))!=0; )
|
||||
|
||||
/**
|
||||
* @brief retrieve each entry from the json array
|
||||
*
|
||||
* @param[in] str @n Json array to revolve
|
||||
* @param[in] pos @n cursor
|
||||
* @param[out] entry @n pointer to the next entry from the array
|
||||
* @param[out] len @n entry length
|
||||
* @param[out] type @n entry type(digital, string, object, array)
|
||||
* @see None.
|
||||
* @note None.
|
||||
*/
|
||||
#define json_array_for_each_entry(str, pos, entry, len, type) \
|
||||
for (pos = json_get_object(JSARRAY, str); \
|
||||
pos!=0 && *pos!=0 && (pos=json_get_next_object(JSARRAY, ++pos, 0, 0, &entry, &len, &type))!=0; )
|
||||
|
||||
|
||||
/**
|
||||
* @brief backup the last character to register parameters,
|
||||
* and set the end character with '\0'
|
||||
*
|
||||
* @param[in] json_str @n json string
|
||||
* @param[in] str_len @n json string lenth
|
||||
* @param[out] register @n used to backup the last character
|
||||
* @see None.
|
||||
* @note None.
|
||||
*/
|
||||
#define backup_json_str_last_char(json_str, str_len, register) { \
|
||||
register = *((char *)json_str + str_len); \
|
||||
*((char *)json_str + str_len) = '\0'; \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief restore the last character from register parameters
|
||||
*
|
||||
* @param[in] json_str @n json string
|
||||
* @param[in] str_len @n json string lenth
|
||||
* @param[in] register @n used to restore the last character
|
||||
* @see None.
|
||||
* @note None.
|
||||
*/
|
||||
#define restore_json_str_last_char(json_str, str_len, register) { \
|
||||
*((char *)json_str + str_len) = register; \
|
||||
}
|
||||
|
||||
#endif /* __JSON_PARSER_H__ */
|
@@ -0,0 +1,109 @@
|
||||
#ifndef _QCLOUD_LIST_H_
|
||||
#define _QCLOUD_LIST_H_
|
||||
|
||||
typedef struct qcloud_list_node_st {
|
||||
struct qcloud_list_node_st *next;
|
||||
struct qcloud_list_node_st *prev;
|
||||
} qcloud_list_t;
|
||||
|
||||
#define QCLOUD_OFFSET_OF_FIELD(type, field) \
|
||||
((uint32_t)&(((type *)0)->field))
|
||||
|
||||
#define QCLOUD_CONTAINER_OF_FIELD(ptr, type, field) \
|
||||
((type *)((uint8_t *)(ptr) - QCLOUD_OFFSET_OF_FIELD(type, field)))
|
||||
|
||||
#define QCLOUD_LIST_NODE(node) \
|
||||
{ &(node), &(node) }
|
||||
|
||||
#define QCLOUD_LIST_DEFINE(list) \
|
||||
qcloud_list_t list = { &(list), &(list) }
|
||||
|
||||
#define QCLOUD_LIST_ENTRY(list, type, field) \
|
||||
QCLOUD_CONTAINER_OF_FIELD(list, type, field)
|
||||
|
||||
#define QCLOUD_LIST_FIRST_ENTRY(list, type, field) \
|
||||
QCLOUD_LIST_ENTRY((list)->next, type, field)
|
||||
|
||||
#define QCLOUD_LIST_FIRST_ENTRY_OR_NULL(list, type, field) \
|
||||
(qcloud_list_empty(list) ? NULL : QCLOUD_LIST_FIRST_ENTRY(list, type, field))
|
||||
|
||||
#define QCLOUD_LIST_FOR_EACH(curr, list) \
|
||||
for (curr = (list)->next; curr != (list); curr = curr->next)
|
||||
|
||||
#define QCLOUD_LIST_FOR_EACH_PREV(curr, list) \
|
||||
for (curr = (list)->prev; curr != (list); curr = curr->prev)
|
||||
|
||||
#define QCLOUD_LIST_FOR_EACH_SAFE(curr, next, list) \
|
||||
for (curr = (list)->next, next = curr->next; curr != (list); \
|
||||
curr = next, next = curr->next)
|
||||
|
||||
#define QCLOUD_LIST_FOR_EACH_PREV_SAFE(curr, next, list) \
|
||||
for (curr = (list)->prev, next = curr->prev; \
|
||||
curr != (list); \
|
||||
curr = next, next = curr->prev)
|
||||
|
||||
__QCLOUD_STATIC__ void _qcloud_list_add(qcloud_list_t *node, qcloud_list_t *prev, qcloud_list_t *next)
|
||||
{
|
||||
next->prev = node;
|
||||
node->next = next;
|
||||
node->prev = prev;
|
||||
prev->next = node;
|
||||
}
|
||||
|
||||
__QCLOUD_STATIC__ void _qcloud_list_del(qcloud_list_t *prev, qcloud_list_t *next)
|
||||
{
|
||||
next->prev = prev;
|
||||
prev->next = next;
|
||||
}
|
||||
|
||||
__QCLOUD_STATIC__ void _qcloud_list_del_entry(qcloud_list_t *entry)
|
||||
{
|
||||
_qcloud_list_del(entry->prev, entry->next);
|
||||
}
|
||||
|
||||
__QCLOUD_API__ __QCLOUD_STATIC__ void qcloud_list_init(qcloud_list_t *list)
|
||||
{
|
||||
list->next = list;
|
||||
list->prev = list;
|
||||
}
|
||||
|
||||
__QCLOUD_API__ __QCLOUD_STATIC__ void qcloud_list_add(qcloud_list_t *node, qcloud_list_t *list)
|
||||
{
|
||||
_qcloud_list_add(node, list, list->next);
|
||||
}
|
||||
|
||||
__QCLOUD_API__ __QCLOUD_STATIC__ void qcloud_list_add_tail(qcloud_list_t *node, qcloud_list_t *list)
|
||||
{
|
||||
_qcloud_list_add(node, list->prev, list);
|
||||
}
|
||||
|
||||
__QCLOUD_API__ __QCLOUD_STATIC__ void qcloud_list_del(qcloud_list_t *entry)
|
||||
{
|
||||
_qcloud_list_del(entry->prev, entry->next);
|
||||
}
|
||||
|
||||
__QCLOUD_API__ __QCLOUD_STATIC__ void qcloud_list_del_init(qcloud_list_t *entry)
|
||||
{
|
||||
_qcloud_list_del_entry(entry);
|
||||
qcloud_list_init(entry);
|
||||
}
|
||||
|
||||
__QCLOUD_API__ __QCLOUD_STATIC__ void qcloud_list_move(qcloud_list_t *node, qcloud_list_t *list)
|
||||
{
|
||||
_qcloud_list_del_entry(node);
|
||||
qcloud_list_add(node, list);
|
||||
}
|
||||
|
||||
__QCLOUD_API__ __QCLOUD_STATIC__ void qcloud_list_move_tail(qcloud_list_t *node, qcloud_list_t *list)
|
||||
{
|
||||
_qcloud_list_del_entry(node);
|
||||
qcloud_list_add_tail(node, list);
|
||||
}
|
||||
|
||||
__QCLOUD_API__ __QCLOUD_STATIC__ int qcloud_list_empty(const qcloud_list_t *list)
|
||||
{
|
||||
return list->next == list;
|
||||
}
|
||||
|
||||
#endif /* _QCLOUD_LIST_H_ */
|
||||
|
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (c) 2017-2019 Tencent Group. All rights reserved.
|
||||
* License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __LITE_UTILS_H__
|
||||
#define __LITE_UTILS_H__
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#if defined(_PLATFORM_IS_LINUX_)
|
||||
#include <assert.h>
|
||||
#endif
|
||||
|
||||
#include "qcloud_lite_list.h"
|
||||
|
||||
#define LITE_TRUE (1)
|
||||
#define LITE_FALSE (0)
|
||||
|
||||
#ifndef container_of
|
||||
#define container_of(ptr, type, member) \
|
||||
((type *) ((char *) (ptr) - offsetof(type, member)))
|
||||
#endif
|
||||
|
||||
#define LITE_MINIMUM(a, b) (((a) <= (b)) ? (a) : (b))
|
||||
#define LITE_MAXIMUM(a, b) (((a) >= (b)) ? (a) : (b))
|
||||
#define LITE_isdigit(c) (((c) <= '9' && (c) >= '0') ? (LITE_TRUE) : (LITE_FALSE))
|
||||
|
||||
#if defined(_PLATFORM_IS_LINUX_)
|
||||
#define LITE_ASSERT(expr) assert(expr)
|
||||
#else
|
||||
#define LITE_ASSERT(expr) \
|
||||
do { \
|
||||
if (!(expr)) { \
|
||||
osal_printf("### %s | %s(%d): ASSERT FAILED ###: %s is FALSE\r\n", \
|
||||
__FILE__, __func__, __LINE__, #expr); \
|
||||
} \
|
||||
} while(0)
|
||||
#endif
|
||||
|
||||
char *LITE_strdup(const char *src);
|
||||
char *LITE_format_string(const char *fmt, ...);
|
||||
char *LITE_format_nstring(const int len, const char *fmt, ...);
|
||||
void LITE_hexbuf_convert(unsigned char *digest, char *out, int buflen, int uppercase);
|
||||
void LITE_hexstr_convert(char *hexstr, uint8_t *out_buf, int len);
|
||||
void LITE_replace_substr(char orig[], char key[], char swap[]);
|
||||
|
||||
char *LITE_json_value_of(char *key, char *src);
|
||||
list_head_t *LITE_json_keys_of(char *src, char *prefix);
|
||||
void LITE_json_keys_release(list_head_t *keylist);
|
||||
|
||||
qcloud_err_t LITE_get_int32(int32_t *value, char *src);
|
||||
qcloud_err_t LITE_get_int16(int16_t *value, char *src);
|
||||
qcloud_err_t LITE_get_int8(int8_t *value, char *src);
|
||||
qcloud_err_t LITE_get_uint32(uint32_t *value, char *src);
|
||||
qcloud_err_t LITE_get_uint16(uint16_t *value, char *src);
|
||||
qcloud_err_t LITE_get_uint8(uint8_t *value, char *src);
|
||||
qcloud_err_t LITE_get_float(float *value, char *src);
|
||||
qcloud_err_t LITE_get_double(double *value, char *src);
|
||||
qcloud_err_t LITE_get_boolean(bool *value, char *src);
|
||||
|
||||
typedef struct _json_key_t {
|
||||
char *key;
|
||||
list_head_t list;
|
||||
} json_key_t;
|
||||
|
||||
#define foreach_json_keys_in(src, iter_key, keylist, pos) \
|
||||
for(keylist = (void *)LITE_json_keys_of((char *)src, ""), \
|
||||
pos = (void *)list_first_entry((list_head_t *)keylist, json_key_t, list), \
|
||||
iter_key = ((json_key_t *)pos)->key; \
|
||||
(iter_key = ((json_key_t *)pos)->key); \
|
||||
pos = list_next_entry((json_key_t *)pos, list, json_key_t))
|
||||
|
||||
#endif /* __LITE_UTILS_H__ */
|
||||
|
@@ -0,0 +1,495 @@
|
||||
/*
|
||||
* Copyright (c) 2017-2019 Tencent Group. All rights reserved.
|
||||
* License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_LIST_H
|
||||
#define _LINUX_LIST_H
|
||||
|
||||
#define inline __inline
|
||||
|
||||
typedef struct list_head list_head_t;
|
||||
|
||||
struct list_head {
|
||||
struct list_head *next, *prev;
|
||||
};
|
||||
|
||||
/*
|
||||
* Simple doubly linked list implementation.
|
||||
*
|
||||
* Some of the internal functions ("__xxx") are useful when
|
||||
* manipulating whole lists rather than single entries, as
|
||||
* sometimes we already know the next/prev entries and we can
|
||||
* generate better code by using them directly rather than
|
||||
* using the generic single-entry routines.
|
||||
*/
|
||||
|
||||
#define LIST_HEAD_INIT(name) { &(name), &(name) }
|
||||
|
||||
#define LIST_HEAD(name) \
|
||||
struct list_head name = LIST_HEAD_INIT(name)
|
||||
|
||||
static inline void INIT_LIST_HEAD(struct list_head *list)
|
||||
{
|
||||
list->next = list;
|
||||
list->prev = list;
|
||||
}
|
||||
|
||||
/*
|
||||
* Insert a new_ptr entry between two known consecutive entries.
|
||||
*
|
||||
* This is only for internal list manipulation where we know
|
||||
* the prev/next entries already!
|
||||
*/
|
||||
static inline void __list_add(struct list_head *new_ptr,
|
||||
struct list_head *prev,
|
||||
struct list_head *next)
|
||||
{
|
||||
next->prev = new_ptr;
|
||||
new_ptr->next = next;
|
||||
new_ptr->prev = prev;
|
||||
prev->next = new_ptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* list_add - add a new_ptr entry
|
||||
* @new_ptr: new_ptr entry to be added
|
||||
* @head: list head to add it after
|
||||
*
|
||||
* Insert a new_ptr entry after the specified head.
|
||||
* This is good for implementing stacks.
|
||||
*/
|
||||
static inline void list_add(struct list_head *new_ptr, struct list_head *head)
|
||||
{
|
||||
__list_add(new_ptr, head, head->next);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* list_add_tail - add a new_ptr entry
|
||||
* @new_ptr: new_ptr entry to be added
|
||||
* @head: list head to add it before
|
||||
*
|
||||
* Insert a new_ptr entry before the specified head.
|
||||
* This is useful for implementing queues.
|
||||
*/
|
||||
static inline void list_add_tail(struct list_head *new_ptr, struct list_head *head)
|
||||
{
|
||||
__list_add(new_ptr, head->prev, head);
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete a list entry by making the prev/next entries
|
||||
* point to each other.
|
||||
*
|
||||
* This is only for internal list manipulation where we know
|
||||
* the prev/next entries already!
|
||||
*/
|
||||
static inline void __list_del(struct list_head *prev, struct list_head *next)
|
||||
{
|
||||
next->prev = prev;
|
||||
prev->next = next;
|
||||
}
|
||||
|
||||
/**
|
||||
* list_del - deletes entry from list.
|
||||
* @entry: the element to delete from the list.
|
||||
* Note: list_empty() on entry does not return true after this, the entry is
|
||||
* in an undefined state.
|
||||
*/
|
||||
static inline void __list_del_entry(struct list_head *entry)
|
||||
{
|
||||
__list_del(entry->prev, entry->next);
|
||||
}
|
||||
|
||||
static inline void list_del(struct list_head *entry)
|
||||
{
|
||||
__list_del(entry->prev, entry->next);
|
||||
}
|
||||
|
||||
/**
|
||||
* list_replace - replace old entry by new_ptr one
|
||||
* @old : the element to be replaced
|
||||
* @new_ptr : the new_ptr element to insert
|
||||
*
|
||||
* If @old was empty, it will be overwritten.
|
||||
*/
|
||||
static inline void list_replace(struct list_head *old,
|
||||
struct list_head *new_ptr)
|
||||
{
|
||||
new_ptr->next = old->next;
|
||||
new_ptr->next->prev = new_ptr;
|
||||
new_ptr->prev = old->prev;
|
||||
new_ptr->prev->next = new_ptr;
|
||||
}
|
||||
|
||||
static inline void list_replace_init(struct list_head *old,
|
||||
struct list_head *new_ptr)
|
||||
{
|
||||
list_replace(old, new_ptr);
|
||||
INIT_LIST_HEAD(old);
|
||||
}
|
||||
|
||||
/**
|
||||
* list_del_init - deletes entry from list and reinitialize it.
|
||||
* @entry: the element to delete from the list.
|
||||
*/
|
||||
static inline void list_del_init(struct list_head *entry)
|
||||
{
|
||||
__list_del_entry(entry);
|
||||
INIT_LIST_HEAD(entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* list_move - delete from one list and add as another's head
|
||||
* @list: the entry to move
|
||||
* @head: the head that will precede our entry
|
||||
*/
|
||||
static inline void list_move(struct list_head *list, struct list_head *head)
|
||||
{
|
||||
__list_del_entry(list);
|
||||
list_add(list, head);
|
||||
}
|
||||
|
||||
/**
|
||||
* list_move_tail - delete from one list and add as another's tail
|
||||
* @list: the entry to move
|
||||
* @head: the head that will follow our entry
|
||||
*/
|
||||
static inline void list_move_tail(struct list_head *list,
|
||||
struct list_head *head)
|
||||
{
|
||||
__list_del_entry(list);
|
||||
list_add_tail(list, head);
|
||||
}
|
||||
|
||||
/**
|
||||
* list_is_last - tests whether @list is the last entry in list @head
|
||||
* @list: the entry to test
|
||||
* @head: the head of the list
|
||||
*/
|
||||
static inline int list_is_last(const struct list_head *list,
|
||||
const struct list_head *head)
|
||||
{
|
||||
return list->next == head;
|
||||
}
|
||||
|
||||
/**
|
||||
* list_empty - tests whether a list is empty
|
||||
* @head: the list to test.
|
||||
*/
|
||||
static inline int list_empty(const struct list_head *head)
|
||||
{
|
||||
return head->next == head;
|
||||
}
|
||||
|
||||
/**
|
||||
* list_empty_careful - tests whether a list is empty and not being modified
|
||||
* @head: the list to test
|
||||
*
|
||||
* Description:
|
||||
* tests whether a list is empty _and_ checks that no other CPU might be
|
||||
* in the process of modifying either member (next or prev)
|
||||
*
|
||||
* NOTE: using list_empty_careful() without synchronization
|
||||
* can only be safe if the only activity that can happen
|
||||
* to the list entry is list_del_init(). Eg. it cannot be used
|
||||
* if another CPU could re-list_add() it.
|
||||
*/
|
||||
static inline int list_empty_careful(const struct list_head *head)
|
||||
{
|
||||
struct list_head *next = head->next;
|
||||
return (next == head) && (next == head->prev);
|
||||
}
|
||||
|
||||
/**
|
||||
* list_rotate_left - rotate the list to the left
|
||||
* @head: the head of the list
|
||||
*/
|
||||
static inline void list_rotate_left(struct list_head *head)
|
||||
{
|
||||
struct list_head *first;
|
||||
|
||||
if (!list_empty(head)) {
|
||||
first = head->next;
|
||||
list_move_tail(first, head);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* list_is_singular - tests whether a list has just one entry.
|
||||
* @head: the list to test.
|
||||
*/
|
||||
static inline int list_is_singular(const struct list_head *head)
|
||||
{
|
||||
return !list_empty(head) && (head->next == head->prev);
|
||||
}
|
||||
|
||||
/**
|
||||
* list_entry - get the struct for this entry
|
||||
* @ptr: the &struct list_head pointer.
|
||||
* @type: the type of the struct this is embedded in.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*/
|
||||
#define list_entry(ptr, type, member) \
|
||||
container_of(ptr, type, member)
|
||||
|
||||
/**
|
||||
* list_first_entry - get the first element from a list
|
||||
* @ptr: the list head to take the element from.
|
||||
* @type: the type of the struct this is embedded in.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*
|
||||
* Note, that list is expected to be not empty.
|
||||
*/
|
||||
#define list_first_entry(ptr, type, member) \
|
||||
list_entry((ptr)->next, type, member)
|
||||
|
||||
/**
|
||||
* list_last_entry - get the last element from a list
|
||||
* @ptr: the list head to take the element from.
|
||||
* @type: the type of the struct this is embedded in.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*
|
||||
* Note, that list is expected to be not empty.
|
||||
*/
|
||||
#define list_last_entry(ptr, type, member) \
|
||||
list_entry((ptr)->prev, type, member)
|
||||
|
||||
/**
|
||||
* list_first_entry_or_null - get the first element from a list
|
||||
* @ptr: the list head to take the element from.
|
||||
* @type: the type of the struct this is embedded in.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*
|
||||
* Note that if the list is empty, it returns NULL.
|
||||
*/
|
||||
#define list_first_entry_or_null(ptr, type, member) \
|
||||
(!list_empty(ptr) ? list_first_entry(ptr, type, member) : NULL)
|
||||
|
||||
/**
|
||||
* list_next_entry - get the next element in list
|
||||
* @pos: the type * to cursor
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*/
|
||||
#define list_next_entry(pos, member, type) \
|
||||
list_entry((pos)->member.next, type, member)
|
||||
|
||||
/**
|
||||
* list_prev_entry - get the prev element in list
|
||||
* @pos: the type * to cursor
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*/
|
||||
#define list_prev_entry(pos, member, type) \
|
||||
list_entry((pos)->member.prev, type, member)
|
||||
|
||||
/**
|
||||
* list_for_each - iterate over a list
|
||||
* @pos: the &struct list_head to use as a loop cursor.
|
||||
* @head: the head for your list.
|
||||
*/
|
||||
#define list_for_each(pos, head) \
|
||||
for (pos = (head)->next; pos != (head); pos = pos->next)
|
||||
|
||||
/**
|
||||
* __list_for_each - iterate over a list
|
||||
* @pos: the &struct list_head to use as a loop cursor.
|
||||
* @head: the head for your list.
|
||||
*
|
||||
* This variant doesn't differ from list_for_each() any more.
|
||||
* We don't do prefetching in either case.
|
||||
*/
|
||||
#define __list_for_each(pos, head) \
|
||||
for (pos = (head)->next; pos != (head); pos = pos->next)
|
||||
|
||||
/**
|
||||
* list_for_each_prev - iterate over a list backwards
|
||||
* @pos: the &struct list_head to use as a loop cursor.
|
||||
* @head: the head for your list.
|
||||
*/
|
||||
#define list_for_each_prev(pos, head) \
|
||||
for (pos = (head)->prev; pos != (head); pos = pos->prev)
|
||||
|
||||
/**
|
||||
* list_for_each_safe - iterate over a list safe against removal of list entry
|
||||
* @pos: the &struct list_head to use as a loop cursor.
|
||||
* @n: another &struct list_head to use as temporary storage
|
||||
* @head: the head for your list.
|
||||
*/
|
||||
#define list_for_each_safe(pos, n, head) \
|
||||
for (pos = (head)->next, n = pos->next; pos != (head); \
|
||||
pos = n, n = pos->next)
|
||||
|
||||
/**
|
||||
* list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry
|
||||
* @pos: the &struct list_head to use as a loop cursor.
|
||||
* @n: another &struct list_head to use as temporary storage
|
||||
* @head: the head for your list.
|
||||
*/
|
||||
#define list_for_each_prev_safe(pos, n, head) \
|
||||
for (pos = (head)->prev, n = pos->prev; \
|
||||
pos != (head); \
|
||||
pos = n, n = pos->prev)
|
||||
|
||||
/**
|
||||
* list_for_each_entry - iterate over list of given type
|
||||
* @pos: the type * to use as a loop cursor.
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*/
|
||||
#define list_for_each_entry(pos, head, member, type) \
|
||||
for (pos = list_entry((head)->next, type, member); \
|
||||
&pos->member != (head); \
|
||||
pos = list_entry(pos->member.next, type, member))
|
||||
|
||||
/**
|
||||
* list_for_each_entry_reverse - iterate backwards over list of given type.
|
||||
* @pos: the type * to use as a loop cursor.
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*/
|
||||
#define list_for_each_entry_reverse(pos, head, member, type) \
|
||||
for (pos = list_entry((head)->prev, type, member); \
|
||||
&pos->member != (head); \
|
||||
pos = list_entry(pos->member.prev, type, member))
|
||||
|
||||
/**
|
||||
* list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue()
|
||||
* @pos: the type * to use as a start point
|
||||
* @head: the head of the list
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*
|
||||
* Prepares a pos entry for use as a start point in list_for_each_entry_continue().
|
||||
*/
|
||||
#define list_prepare_entry(pos, head, member, type) \
|
||||
((pos) ? : list_entry(head, type, member))
|
||||
|
||||
/**
|
||||
* list_for_each_entry_continue - continue iteration over list of given type
|
||||
* @pos: the type * to use as a loop cursor.
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*
|
||||
* Continue to iterate over list of given type, continuing after
|
||||
* the current position.
|
||||
*/
|
||||
#define list_for_each_entry_continue(pos, head, member, type) \
|
||||
for (pos = list_entry(pos->member.next, type, member); \
|
||||
&pos->member != (head); \
|
||||
pos = list_entry(pos->member.next, type, member))
|
||||
|
||||
/**
|
||||
* list_for_each_entry_continue_reverse - iterate backwards from the given point
|
||||
* @pos: the type * to use as a loop cursor.
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*
|
||||
* Start to iterate over list of given type backwards, continuing after
|
||||
* the current position.
|
||||
*/
|
||||
#define list_for_each_entry_continue_reverse(pos, head, member, type) \
|
||||
for (pos = list_entry(pos->member.prev, type, member); \
|
||||
&pos->member != (head); \
|
||||
pos = list_entry(pos->member.prev, type, member))
|
||||
|
||||
/**
|
||||
* list_for_each_entry_from - iterate over list of given type from the current point
|
||||
* @pos: the type * to use as a loop cursor.
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*
|
||||
* Iterate over list of given type, continuing from current position.
|
||||
*/
|
||||
#define list_for_each_entry_from(pos, head, member, type) \
|
||||
for (; &pos->member != (head); \
|
||||
pos = list_entry(pos->member.next, type, member))
|
||||
|
||||
/**
|
||||
* list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
|
||||
* @pos: the type * to use as a loop cursor.
|
||||
* @n: another type * to use as temporary storage
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*/
|
||||
#define list_for_each_entry_safe(pos, n, head, member, type) \
|
||||
for (pos = list_entry((head)->next, type, member), \
|
||||
n = list_entry(pos->member.next, type, member); \
|
||||
&pos->member != (head); \
|
||||
pos = n, n = list_entry(n->member.next, type, member))
|
||||
|
||||
/**
|
||||
* list_for_each_entry_safe_continue - continue list iteration safe against removal
|
||||
* @pos: the type * to use as a loop cursor.
|
||||
* @n: another type * to use as temporary storage
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*
|
||||
* Iterate over list of given type, continuing after current point,
|
||||
* safe against removal of list entry.
|
||||
*/
|
||||
#define list_for_each_entry_safe_continue(pos, n, head, member, type) \
|
||||
for (pos = list_entry(pos->member.next, type, member), \
|
||||
n = list_entry(pos->member.next, type, member); \
|
||||
&pos->member != (head); \
|
||||
pos = n, n = list_entry(n->member.next, type, member))
|
||||
|
||||
/**
|
||||
* list_for_each_entry_safe_from - iterate over list from current point safe against removal
|
||||
* @pos: the type * to use as a loop cursor.
|
||||
* @n: another type * to use as temporary storage
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*
|
||||
* Iterate over list of given type from current point, safe against
|
||||
* removal of list entry.
|
||||
*/
|
||||
#define list_for_each_entry_safe_from(pos, n, head, member, type) \
|
||||
for (n = list_entry(pos->member.next, type, member); \
|
||||
&pos->member != (head); \
|
||||
pos = n, n = list_entry(n->member.next, type, member))
|
||||
|
||||
/**
|
||||
* list_for_each_entry_safe_reverse - iterate backwards over list safe against removal
|
||||
* @pos: the type * to use as a loop cursor.
|
||||
* @n: another type * to use as temporary storage
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*
|
||||
* Iterate backwards over list of given type, safe against removal
|
||||
* of list entry.
|
||||
*/
|
||||
#define list_for_each_entry_safe_reverse(pos, n, head, member, type) \
|
||||
for (pos = list_entry((head)->prev, type, member), \
|
||||
n = list_entry(pos->member.prev, type, member); \
|
||||
&pos->member != (head); \
|
||||
pos = n, n = list_entry(n->member.prev, type, member))
|
||||
|
||||
/**
|
||||
* list_safe_reset_next - reset a stale list_for_each_entry_safe loop
|
||||
* @pos: the loop cursor used in the list_for_each_entry_safe loop
|
||||
* @n: temporary storage used in list_for_each_entry_safe
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*
|
||||
* list_safe_reset_next is not safe to use in general if the list may be
|
||||
* modified concurrently (eg. the lock is dropped in the loop body). An
|
||||
* exception to this is if the cursor element (pos) is pinned in the list,
|
||||
* and list_safe_reset_next is called after re-taking the lock and before
|
||||
* completing the current iteration of the loop body.
|
||||
*/
|
||||
#define list_safe_reset_next(pos, n, member, type) \
|
||||
n = list_entry(pos->member.next, type, member)
|
||||
|
||||
#endif
|
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making IoT Hub available.
|
||||
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
|
||||
* Licensed under the MIT License (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://opensource.org/licenses/MIT
|
||||
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is
|
||||
* distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef QCLOUD_IOT_UTILS_MD5_H_
|
||||
#define QCLOUD_IOT_UTILS_MD5_H_
|
||||
|
||||
typedef struct {
|
||||
uint32_t total[2]; /*!< number of bytes processed */
|
||||
uint32_t state[4]; /*!< intermediate digest state */
|
||||
unsigned char buffer[64]; /*!< data block being processed */
|
||||
} iot_md5_context;
|
||||
|
||||
|
||||
/**
|
||||
* @brief 初始化MD5上下文
|
||||
*
|
||||
* @param ctx MD5上下文指针
|
||||
*/
|
||||
void utils_md5_init(iot_md5_context *ctx);
|
||||
|
||||
/**
|
||||
* @brief 清空MD5上下文
|
||||
*
|
||||
* @param ctx MD5上下文指针
|
||||
*/
|
||||
void utils_md5_free(iot_md5_context *ctx);
|
||||
|
||||
/**
|
||||
* @brief 拷贝MD5上下文
|
||||
*
|
||||
* @param dst 目标MD5上下文
|
||||
* @param src 源MD5上下文
|
||||
*/
|
||||
void utils_md5_clone(iot_md5_context *dst,
|
||||
const iot_md5_context *src);
|
||||
|
||||
/**
|
||||
* @brief 设置MD5上下文
|
||||
*
|
||||
* @param ctx MD5上下文指针
|
||||
*/
|
||||
void utils_md5_starts(iot_md5_context *ctx);
|
||||
|
||||
/**
|
||||
* @brief MD5过程缓冲区
|
||||
*
|
||||
* @param ctx MD5上下文指针
|
||||
* @param input 输入数据
|
||||
* @param ilen 输入数据长度
|
||||
*/
|
||||
void utils_md5_update(iot_md5_context *ctx, const unsigned char *input, size_t ilen);
|
||||
|
||||
/**
|
||||
* @brief MD5数据
|
||||
*
|
||||
* @param ctx MD5上下文指针
|
||||
* @param output MD5校验和结果
|
||||
*/
|
||||
void utils_md5_finish(iot_md5_context *ctx, unsigned char output[16]);
|
||||
|
||||
/* 内部使用 */
|
||||
void utils_md5_process(iot_md5_context *ctx, const unsigned char data[64]);
|
||||
|
||||
/**
|
||||
* @brief Output = MD5( input buffer )
|
||||
*
|
||||
* @param input 输入数据
|
||||
* @param ilen 输入数据长度
|
||||
* @param output MD5校验和结果
|
||||
*/
|
||||
void utils_md5(const unsigned char *input, size_t ilen, unsigned char output[16]);
|
||||
|
||||
|
||||
int8_t utils_hb2hex(uint8_t hb);
|
||||
|
||||
|
||||
#endif
|
||||
|
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making IoT Hub available.
|
||||
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
|
||||
* Licensed under the MIT License (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://opensource.org/licenses/MIT
|
||||
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is
|
||||
* distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef QCLOUD_IOT_UTILS_SHA1_H_
|
||||
#define QCLOUD_IOT_UTILS_SHA1_H_
|
||||
|
||||
/**
|
||||
* \brief SHA-1 context structure
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t total[2]; /*!< number of bytes processed */
|
||||
uint32_t state[5]; /*!< intermediate digest state */
|
||||
unsigned char buffer[64]; /*!< data block being processed */
|
||||
} iot_sha1_context;
|
||||
|
||||
/**
|
||||
* \brief Initialize SHA-1 context
|
||||
*
|
||||
* \param ctx SHA-1 context to be initialized
|
||||
*/
|
||||
void utils_sha1_init(iot_sha1_context *ctx);
|
||||
|
||||
/**
|
||||
* \brief Clear SHA-1 context
|
||||
*
|
||||
* \param ctx SHA-1 context to be cleared
|
||||
*/
|
||||
void utils_sha1_free(iot_sha1_context *ctx);
|
||||
|
||||
/**
|
||||
* \brief Clone (the state of) a SHA-1 context
|
||||
*
|
||||
* \param dst The destination context
|
||||
* \param src The context to be cloned
|
||||
*/
|
||||
void utils_sha1_clone(iot_sha1_context *dst,
|
||||
const iot_sha1_context *src);
|
||||
|
||||
/**
|
||||
* \brief SHA-1 context setup
|
||||
*
|
||||
* \param ctx context to be initialized
|
||||
*/
|
||||
void utils_sha1_starts(iot_sha1_context *ctx);
|
||||
|
||||
/**
|
||||
* \brief SHA-1 process buffer
|
||||
*
|
||||
* \param ctx SHA-1 context
|
||||
* \param input buffer holding the data
|
||||
* \param ilen length of the input data
|
||||
*/
|
||||
void utils_sha1_update(iot_sha1_context *ctx, const unsigned char *input, size_t ilen);
|
||||
|
||||
/**
|
||||
* \brief SHA-1 final digest
|
||||
*
|
||||
* \param ctx SHA-1 context
|
||||
* \param output SHA-1 checksum result
|
||||
*/
|
||||
void utils_sha1_finish(iot_sha1_context *ctx, unsigned char output[20]);
|
||||
|
||||
/* Internal use */
|
||||
void utils_sha1_process(iot_sha1_context *ctx, const unsigned char data[64]);
|
||||
|
||||
/**
|
||||
* \brief Output = SHA-1( input buffer )
|
||||
*
|
||||
* \param input buffer holding the data
|
||||
* \param ilen length of the input data
|
||||
* \param output SHA-1 checksum result
|
||||
*/
|
||||
void utils_sha1(const unsigned char *input, size_t ilen, unsigned char output[20]);
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user