mirror of
https://github.com/jam422470459/EPD-nRF52-hema213.git
synced 2025-12-16 21:38:14 +08:00
add nrf51 DFU project
This commit is contained in:
21
SDK/12.3.0_d7731ad/external/micro-ecc/license.txt
vendored
Normal file
21
SDK/12.3.0_d7731ad/external/micro-ecc/license.txt
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
Copyright (c) 2014, Kenneth MacKay
|
||||
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.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
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 HOLDER 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.
|
||||
21
SDK/12.3.0_d7731ad/external/micro-ecc/micro-ecc/LICENSE.txt
vendored
Normal file
21
SDK/12.3.0_d7731ad/external/micro-ecc/micro-ecc/LICENSE.txt
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
Copyright (c) 2014, Kenneth MacKay
|
||||
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.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
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 HOLDER 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.
|
||||
820
SDK/12.3.0_d7731ad/external/micro-ecc/micro-ecc/asm_arm.inc
vendored
Normal file
820
SDK/12.3.0_d7731ad/external/micro-ecc/micro-ecc/asm_arm.inc
vendored
Normal file
@@ -0,0 +1,820 @@
|
||||
/* Copyright 2015, Kenneth MacKay. Licensed under the BSD 2-clause license. */
|
||||
|
||||
#ifndef _UECC_ASM_ARM_H_
|
||||
#define _UECC_ASM_ARM_H_
|
||||
|
||||
#if (uECC_SUPPORTS_secp256r1 || uECC_SUPPORTS_secp256k1)
|
||||
#define uECC_MIN_WORDS 8
|
||||
#endif
|
||||
#if uECC_SUPPORTS_secp224r1
|
||||
#undef uECC_MIN_WORDS
|
||||
#define uECC_MIN_WORDS 7
|
||||
#endif
|
||||
#if uECC_SUPPORTS_secp192r1
|
||||
#undef uECC_MIN_WORDS
|
||||
#define uECC_MIN_WORDS 6
|
||||
#endif
|
||||
#if uECC_SUPPORTS_secp160r1
|
||||
#undef uECC_MIN_WORDS
|
||||
#define uECC_MIN_WORDS 5
|
||||
#endif
|
||||
|
||||
#if (uECC_PLATFORM == uECC_arm_thumb)
|
||||
#define REG_RW "+&l"
|
||||
#define REG_WRITE "=&l"
|
||||
#else
|
||||
#define REG_RW "+&r"
|
||||
#define REG_WRITE "=&r"
|
||||
#endif
|
||||
|
||||
#if (uECC_PLATFORM == uECC_arm_thumb || uECC_PLATFORM == uECC_arm_thumb2)
|
||||
#define REG_RW_LO "+&l"
|
||||
#define REG_WRITE_LO "=&l"
|
||||
#else
|
||||
#define REG_RW_LO "+&r"
|
||||
#define REG_WRITE_LO "=&r"
|
||||
#endif
|
||||
|
||||
#if (uECC_PLATFORM == uECC_arm_thumb2)
|
||||
#define RESUME_SYNTAX
|
||||
#else
|
||||
#define RESUME_SYNTAX ".syntax divided \n\t"
|
||||
#endif
|
||||
|
||||
#if (uECC_OPTIMIZATION_LEVEL >= 2)
|
||||
|
||||
uECC_VLI_API uECC_word_t uECC_vli_add(uECC_word_t *result,
|
||||
const uECC_word_t *left,
|
||||
const uECC_word_t *right,
|
||||
wordcount_t num_words) {
|
||||
#if (uECC_MAX_WORDS != uECC_MIN_WORDS)
|
||||
#if (uECC_PLATFORM == uECC_arm_thumb) || (uECC_PLATFORM == uECC_arm_thumb2)
|
||||
uint32_t jump = (uECC_MAX_WORDS - num_words) * 4 * 2 + 1;
|
||||
#else /* ARM */
|
||||
uint32_t jump = (uECC_MAX_WORDS - num_words) * 4 * 4;
|
||||
#endif
|
||||
#endif
|
||||
uint32_t carry;
|
||||
uint32_t left_word;
|
||||
uint32_t right_word;
|
||||
|
||||
__asm__ volatile (
|
||||
".syntax unified \n\t"
|
||||
"movs %[carry], #0 \n\t"
|
||||
#if (uECC_MAX_WORDS != uECC_MIN_WORDS)
|
||||
"adr %[left], 1f \n\t"
|
||||
".align 4 \n\t"
|
||||
"adds %[jump], %[left] \n\t"
|
||||
#endif
|
||||
|
||||
"ldmia %[lptr]!, {%[left]} \n\t"
|
||||
"ldmia %[rptr]!, {%[right]} \n\t"
|
||||
"adds %[left], %[right] \n\t"
|
||||
"stmia %[dptr]!, {%[left]} \n\t"
|
||||
|
||||
#if (uECC_MAX_WORDS != uECC_MIN_WORDS)
|
||||
"bx %[jump] \n\t"
|
||||
#endif
|
||||
"1: \n\t"
|
||||
REPEAT(DEC(uECC_MAX_WORDS),
|
||||
"ldmia %[lptr]!, {%[left]} \n\t"
|
||||
"ldmia %[rptr]!, {%[right]} \n\t"
|
||||
"adcs %[left], %[right] \n\t"
|
||||
"stmia %[dptr]!, {%[left]} \n\t")
|
||||
|
||||
"adcs %[carry], %[carry] \n\t"
|
||||
RESUME_SYNTAX
|
||||
: [dptr] REG_RW_LO (result), [lptr] REG_RW_LO (left), [rptr] REG_RW_LO (right),
|
||||
#if (uECC_MAX_WORDS != uECC_MIN_WORDS)
|
||||
[jump] REG_RW_LO (jump),
|
||||
#endif
|
||||
[carry] REG_WRITE_LO (carry), [left] REG_WRITE_LO (left_word),
|
||||
[right] REG_WRITE_LO (right_word)
|
||||
:
|
||||
: "cc", "memory"
|
||||
);
|
||||
return carry;
|
||||
}
|
||||
#define asm_add 1
|
||||
|
||||
uECC_VLI_API uECC_word_t uECC_vli_sub(uECC_word_t *result,
|
||||
const uECC_word_t *left,
|
||||
const uECC_word_t *right,
|
||||
wordcount_t num_words) {
|
||||
#if (uECC_MAX_WORDS != uECC_MIN_WORDS)
|
||||
#if (uECC_PLATFORM == uECC_arm_thumb) || (uECC_PLATFORM == uECC_arm_thumb2)
|
||||
uint32_t jump = (uECC_MAX_WORDS - num_words) * 4 * 2 + 1;
|
||||
#else /* ARM */
|
||||
uint32_t jump = (uECC_MAX_WORDS - num_words) * 4 * 4;
|
||||
#endif
|
||||
#endif
|
||||
uint32_t carry;
|
||||
uint32_t left_word;
|
||||
uint32_t right_word;
|
||||
|
||||
__asm__ volatile (
|
||||
".syntax unified \n\t"
|
||||
"movs %[carry], #0 \n\t"
|
||||
#if (uECC_MAX_WORDS != uECC_MIN_WORDS)
|
||||
"adr %[left], 1f \n\t"
|
||||
".align 4 \n\t"
|
||||
"adds %[jump], %[left] \n\t"
|
||||
#endif
|
||||
|
||||
"ldmia %[lptr]!, {%[left]} \n\t"
|
||||
"ldmia %[rptr]!, {%[right]} \n\t"
|
||||
"subs %[left], %[right] \n\t"
|
||||
"stmia %[dptr]!, {%[left]} \n\t"
|
||||
|
||||
#if (uECC_MAX_WORDS != uECC_MIN_WORDS)
|
||||
"bx %[jump] \n\t"
|
||||
#endif
|
||||
"1: \n\t"
|
||||
REPEAT(DEC(uECC_MAX_WORDS),
|
||||
"ldmia %[lptr]!, {%[left]} \n\t"
|
||||
"ldmia %[rptr]!, {%[right]} \n\t"
|
||||
"sbcs %[left], %[right] \n\t"
|
||||
"stmia %[dptr]!, {%[left]} \n\t")
|
||||
|
||||
"adcs %[carry], %[carry] \n\t"
|
||||
RESUME_SYNTAX
|
||||
: [dptr] REG_RW_LO (result), [lptr] REG_RW_LO (left), [rptr] REG_RW_LO (right),
|
||||
#if (uECC_MAX_WORDS != uECC_MIN_WORDS)
|
||||
[jump] REG_RW_LO (jump),
|
||||
#endif
|
||||
[carry] REG_WRITE_LO (carry), [left] REG_WRITE_LO (left_word),
|
||||
[right] REG_WRITE_LO (right_word)
|
||||
:
|
||||
: "cc", "memory"
|
||||
);
|
||||
return !carry; /* Note that on ARM, carry flag set means "no borrow" when subtracting
|
||||
(for some reason...) */
|
||||
}
|
||||
#define asm_sub 1
|
||||
|
||||
#endif /* (uECC_OPTIMIZATION_LEVEL >= 2) */
|
||||
|
||||
#if (uECC_OPTIMIZATION_LEVEL >= 3)
|
||||
|
||||
#if (uECC_PLATFORM != uECC_arm_thumb)
|
||||
|
||||
#if uECC_ARM_USE_UMAAL
|
||||
#include "asm_arm_mult_square_umaal.inc"
|
||||
#else
|
||||
#include "asm_arm_mult_square.inc"
|
||||
#endif
|
||||
|
||||
#if (uECC_OPTIMIZATION_LEVEL == 3)
|
||||
|
||||
uECC_VLI_API void uECC_vli_mult(uint32_t *result,
|
||||
const uint32_t *left,
|
||||
const uint32_t *right,
|
||||
wordcount_t num_words) {
|
||||
register uint32_t *r0 __asm__("r0") = result;
|
||||
register const uint32_t *r1 __asm__("r1") = left;
|
||||
register const uint32_t *r2 __asm__("r2") = right;
|
||||
register uint32_t r3 __asm__("r3") = num_words;
|
||||
|
||||
__asm__ volatile (
|
||||
".syntax unified \n\t"
|
||||
#if (uECC_MIN_WORDS == 5)
|
||||
FAST_MULT_ASM_5
|
||||
#if (uECC_MAX_WORDS > 5)
|
||||
FAST_MULT_ASM_5_TO_6
|
||||
#endif
|
||||
#if (uECC_MAX_WORDS > 6)
|
||||
FAST_MULT_ASM_6_TO_7
|
||||
#endif
|
||||
#if (uECC_MAX_WORDS > 7)
|
||||
FAST_MULT_ASM_7_TO_8
|
||||
#endif
|
||||
#elif (uECC_MIN_WORDS == 6)
|
||||
FAST_MULT_ASM_6
|
||||
#if (uECC_MAX_WORDS > 6)
|
||||
FAST_MULT_ASM_6_TO_7
|
||||
#endif
|
||||
#if (uECC_MAX_WORDS > 7)
|
||||
FAST_MULT_ASM_7_TO_8
|
||||
#endif
|
||||
#elif (uECC_MIN_WORDS == 7)
|
||||
FAST_MULT_ASM_7
|
||||
#if (uECC_MAX_WORDS > 7)
|
||||
FAST_MULT_ASM_7_TO_8
|
||||
#endif
|
||||
#elif (uECC_MIN_WORDS == 8)
|
||||
FAST_MULT_ASM_8
|
||||
#endif
|
||||
"1: \n\t"
|
||||
RESUME_SYNTAX
|
||||
: "+r" (r0), "+r" (r1), "+r" (r2)
|
||||
: "r" (r3)
|
||||
: "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory"
|
||||
);
|
||||
}
|
||||
#define asm_mult 1
|
||||
|
||||
#if uECC_SQUARE_FUNC
|
||||
uECC_VLI_API void uECC_vli_square(uECC_word_t *result,
|
||||
const uECC_word_t *left,
|
||||
wordcount_t num_words) {
|
||||
register uint32_t *r0 __asm__("r0") = result;
|
||||
register const uint32_t *r1 __asm__("r1") = left;
|
||||
register uint32_t r2 __asm__("r2") = num_words;
|
||||
|
||||
__asm__ volatile (
|
||||
".syntax unified \n\t"
|
||||
#if (uECC_MIN_WORDS == 5)
|
||||
FAST_SQUARE_ASM_5
|
||||
#if (uECC_MAX_WORDS > 5)
|
||||
FAST_SQUARE_ASM_5_TO_6
|
||||
#endif
|
||||
#if (uECC_MAX_WORDS > 6)
|
||||
FAST_SQUARE_ASM_6_TO_7
|
||||
#endif
|
||||
#if (uECC_MAX_WORDS > 7)
|
||||
FAST_SQUARE_ASM_7_TO_8
|
||||
#endif
|
||||
#elif (uECC_MIN_WORDS == 6)
|
||||
FAST_SQUARE_ASM_6
|
||||
#if (uECC_MAX_WORDS > 6)
|
||||
FAST_SQUARE_ASM_6_TO_7
|
||||
#endif
|
||||
#if (uECC_MAX_WORDS > 7)
|
||||
FAST_SQUARE_ASM_7_TO_8
|
||||
#endif
|
||||
#elif (uECC_MIN_WORDS == 7)
|
||||
FAST_SQUARE_ASM_7
|
||||
#if (uECC_MAX_WORDS > 7)
|
||||
FAST_SQUARE_ASM_7_TO_8
|
||||
#endif
|
||||
#elif (uECC_MIN_WORDS == 8)
|
||||
FAST_SQUARE_ASM_8
|
||||
#endif
|
||||
|
||||
"1: \n\t"
|
||||
RESUME_SYNTAX
|
||||
: "+r" (r0), "+r" (r1)
|
||||
: "r" (r2)
|
||||
: "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory"
|
||||
);
|
||||
}
|
||||
#define asm_square 1
|
||||
#endif /* uECC_SQUARE_FUNC */
|
||||
|
||||
#else /* (uECC_OPTIMIZATION_LEVEL > 3) */
|
||||
|
||||
uECC_VLI_API void uECC_vli_mult(uint32_t *result,
|
||||
const uint32_t *left,
|
||||
const uint32_t *right,
|
||||
wordcount_t num_words) {
|
||||
register uint32_t *r0 __asm__("r0") = result;
|
||||
register const uint32_t *r1 __asm__("r1") = left;
|
||||
register const uint32_t *r2 __asm__("r2") = right;
|
||||
register uint32_t r3 __asm__("r3") = num_words;
|
||||
|
||||
#if uECC_SUPPORTS_secp160r1
|
||||
if (num_words == 5) {
|
||||
__asm__ volatile (
|
||||
".syntax unified \n\t"
|
||||
FAST_MULT_ASM_5
|
||||
RESUME_SYNTAX
|
||||
: "+r" (r0), "+r" (r1), "+r" (r2)
|
||||
: "r" (r3)
|
||||
: "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory"
|
||||
);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#if uECC_SUPPORTS_secp192r1
|
||||
if (num_words == 6) {
|
||||
__asm__ volatile (
|
||||
".syntax unified \n\t"
|
||||
FAST_MULT_ASM_6
|
||||
RESUME_SYNTAX
|
||||
: "+r" (r0), "+r" (r1), "+r" (r2)
|
||||
: "r" (r3)
|
||||
: "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory"
|
||||
);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#if uECC_SUPPORTS_secp224r1
|
||||
if (num_words == 7) {
|
||||
__asm__ volatile (
|
||||
".syntax unified \n\t"
|
||||
FAST_MULT_ASM_7
|
||||
RESUME_SYNTAX
|
||||
: "+r" (r0), "+r" (r1), "+r" (r2)
|
||||
: "r" (r3)
|
||||
: "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory"
|
||||
);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#if (uECC_SUPPORTS_secp256r1 || uECC_SUPPORTS_secp256k1)
|
||||
if (num_words == 8) {
|
||||
__asm__ volatile (
|
||||
".syntax unified \n\t"
|
||||
FAST_MULT_ASM_8
|
||||
RESUME_SYNTAX
|
||||
: "+r" (r0), "+r" (r1), "+r" (r2)
|
||||
: "r" (r3)
|
||||
: "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory"
|
||||
);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#define asm_mult 1
|
||||
|
||||
#if uECC_SQUARE_FUNC
|
||||
uECC_VLI_API void uECC_vli_square(uECC_word_t *result,
|
||||
const uECC_word_t *left,
|
||||
wordcount_t num_words) {
|
||||
register uint32_t *r0 __asm__("r0") = result;
|
||||
register const uint32_t *r1 __asm__("r1") = left;
|
||||
register uint32_t r2 __asm__("r2") = num_words;
|
||||
|
||||
#if uECC_SUPPORTS_secp160r1
|
||||
if (num_words == 5) {
|
||||
__asm__ volatile (
|
||||
".syntax unified \n\t"
|
||||
FAST_SQUARE_ASM_5
|
||||
RESUME_SYNTAX
|
||||
: "+r" (r0), "+r" (r1)
|
||||
: "r" (r2)
|
||||
: "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory"
|
||||
);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#if uECC_SUPPORTS_secp192r1
|
||||
if (num_words == 6) {
|
||||
__asm__ volatile (
|
||||
".syntax unified \n\t"
|
||||
FAST_SQUARE_ASM_6
|
||||
RESUME_SYNTAX
|
||||
: "+r" (r0), "+r" (r1)
|
||||
: "r" (r2)
|
||||
: "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory"
|
||||
);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#if uECC_SUPPORTS_secp224r1
|
||||
if (num_words == 7) {
|
||||
__asm__ volatile (
|
||||
".syntax unified \n\t"
|
||||
FAST_SQUARE_ASM_7
|
||||
RESUME_SYNTAX
|
||||
: "+r" (r0), "+r" (r1)
|
||||
: "r" (r2)
|
||||
: "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory"
|
||||
);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#if (uECC_SUPPORTS_secp256r1 || uECC_SUPPORTS_secp256k1)
|
||||
if (num_words == 8) {
|
||||
__asm__ volatile (
|
||||
".syntax unified \n\t"
|
||||
FAST_SQUARE_ASM_8
|
||||
RESUME_SYNTAX
|
||||
: "+r" (r0), "+r" (r1)
|
||||
: "r" (r2)
|
||||
: "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory"
|
||||
);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#define asm_square 1
|
||||
#endif /* uECC_SQUARE_FUNC */
|
||||
|
||||
#endif /* (uECC_OPTIMIZATION_LEVEL > 3) */
|
||||
|
||||
#endif /* uECC_PLATFORM != uECC_arm_thumb */
|
||||
|
||||
#endif /* (uECC_OPTIMIZATION_LEVEL >= 3) */
|
||||
|
||||
/* ---- "Small" implementations ---- */
|
||||
|
||||
#if !asm_add
|
||||
uECC_VLI_API uECC_word_t uECC_vli_add(uECC_word_t *result,
|
||||
const uECC_word_t *left,
|
||||
const uECC_word_t *right,
|
||||
wordcount_t num_words) {
|
||||
uint32_t carry = 0;
|
||||
uint32_t left_word;
|
||||
uint32_t right_word;
|
||||
|
||||
__asm__ volatile (
|
||||
".syntax unified \n\t"
|
||||
"1: \n\t"
|
||||
"ldmia %[lptr]!, {%[left]} \n\t" /* Load left word. */
|
||||
"ldmia %[rptr]!, {%[right]} \n\t" /* Load right word. */
|
||||
"lsrs %[carry], #1 \n\t" /* Set up carry flag (carry = 0 after this). */
|
||||
"adcs %[left], %[left], %[right] \n\t" /* Add with carry. */
|
||||
"adcs %[carry], %[carry], %[carry] \n\t" /* Store carry bit. */
|
||||
"stmia %[dptr]!, {%[left]} \n\t" /* Store result word. */
|
||||
"subs %[ctr], #1 \n\t" /* Decrement counter. */
|
||||
"bne 1b \n\t" /* Loop until counter == 0. */
|
||||
RESUME_SYNTAX
|
||||
: [dptr] REG_RW (result), [lptr] REG_RW (left), [rptr] REG_RW (right),
|
||||
[ctr] REG_RW (num_words), [carry] REG_RW (carry),
|
||||
[left] REG_WRITE (left_word), [right] REG_WRITE (right_word)
|
||||
:
|
||||
: "cc", "memory"
|
||||
);
|
||||
return carry;
|
||||
}
|
||||
#define asm_add 1
|
||||
#endif
|
||||
|
||||
#if !asm_sub
|
||||
uECC_VLI_API uECC_word_t uECC_vli_sub(uECC_word_t *result,
|
||||
const uECC_word_t *left,
|
||||
const uECC_word_t *right,
|
||||
wordcount_t num_words) {
|
||||
uint32_t carry = 1; /* carry = 1 initially (means don't borrow) */
|
||||
uint32_t left_word;
|
||||
uint32_t right_word;
|
||||
|
||||
__asm__ volatile (
|
||||
".syntax unified \n\t"
|
||||
"1: \n\t"
|
||||
"ldmia %[lptr]!, {%[left]} \n\t" /* Load left word. */
|
||||
"ldmia %[rptr]!, {%[right]} \n\t" /* Load right word. */
|
||||
"lsrs %[carry], #1 \n\t" /* Set up carry flag (carry = 0 after this). */
|
||||
"sbcs %[left], %[left], %[right] \n\t" /* Subtract with borrow. */
|
||||
"adcs %[carry], %[carry], %[carry] \n\t" /* Store carry bit. */
|
||||
"stmia %[dptr]!, {%[left]} \n\t" /* Store result word. */
|
||||
"subs %[ctr], #1 \n\t" /* Decrement counter. */
|
||||
"bne 1b \n\t" /* Loop until counter == 0. */
|
||||
RESUME_SYNTAX
|
||||
: [dptr] REG_RW (result), [lptr] REG_RW (left), [rptr] REG_RW (right),
|
||||
[ctr] REG_RW (num_words), [carry] REG_RW (carry),
|
||||
[left] REG_WRITE (left_word), [right] REG_WRITE (right_word)
|
||||
:
|
||||
: "cc", "memory"
|
||||
);
|
||||
return !carry;
|
||||
}
|
||||
#define asm_sub 1
|
||||
#endif
|
||||
|
||||
#if !asm_mult
|
||||
uECC_VLI_API void uECC_vli_mult(uECC_word_t *result,
|
||||
const uECC_word_t *left,
|
||||
const uECC_word_t *right,
|
||||
wordcount_t num_words) {
|
||||
#if (uECC_PLATFORM != uECC_arm_thumb)
|
||||
uint32_t c0 = 0;
|
||||
uint32_t c1 = 0;
|
||||
uint32_t c2 = 0;
|
||||
uint32_t k = 0;
|
||||
uint32_t i;
|
||||
uint32_t t0, t1;
|
||||
|
||||
__asm__ volatile (
|
||||
".syntax unified \n\t"
|
||||
|
||||
"1: \n\t" /* outer loop (k < num_words) */
|
||||
"movs %[i], #0 \n\t" /* i = 0 */
|
||||
"b 3f \n\t"
|
||||
|
||||
"2: \n\t" /* outer loop (k >= num_words) */
|
||||
"movs %[i], %[k] \n\t" /* i = k */
|
||||
"subs %[i], %[last_word] \n\t" /* i = k - (num_words - 1) (times 4) */
|
||||
|
||||
"3: \n\t" /* inner loop */
|
||||
"subs %[t0], %[k], %[i] \n\t" /* t0 = k-i */
|
||||
|
||||
"ldr %[t1], [%[right], %[t0]] \n\t" /* t1 = right[k - i] */
|
||||
"ldr %[t0], [%[left], %[i]] \n\t" /* t0 = left[i] */
|
||||
|
||||
"umull %[t0], %[t1], %[t0], %[t1] \n\t" /* (t0, t1) = left[i] * right[k - i] */
|
||||
|
||||
"adds %[c0], %[c0], %[t0] \n\t" /* add low word to c0 */
|
||||
"adcs %[c1], %[c1], %[t1] \n\t" /* add high word to c1, including carry */
|
||||
"adcs %[c2], %[c2], #0 \n\t" /* add carry to c2 */
|
||||
|
||||
"adds %[i], #4 \n\t" /* i += 4 */
|
||||
"cmp %[i], %[last_word] \n\t" /* i > (num_words - 1) (times 4)? */
|
||||
"bgt 4f \n\t" /* if so, exit the loop */
|
||||
"cmp %[i], %[k] \n\t" /* i <= k? */
|
||||
"ble 3b \n\t" /* if so, continue looping */
|
||||
|
||||
"4: \n\t" /* end inner loop */
|
||||
|
||||
"str %[c0], [%[result], %[k]] \n\t" /* result[k] = c0 */
|
||||
"mov %[c0], %[c1] \n\t" /* c0 = c1 */
|
||||
"mov %[c1], %[c2] \n\t" /* c1 = c2 */
|
||||
"movs %[c2], #0 \n\t" /* c2 = 0 */
|
||||
"adds %[k], #4 \n\t" /* k += 4 */
|
||||
"cmp %[k], %[last_word] \n\t" /* k <= (num_words - 1) (times 4) ? */
|
||||
"ble 1b \n\t" /* if so, loop back, start with i = 0 */
|
||||
"cmp %[k], %[last_word], lsl #1 \n\t" /* k <= (num_words * 2 - 2) (times 4) ? */
|
||||
"ble 2b \n\t" /* if so, loop back, start with i = (k + 1) - num_words */
|
||||
/* end outer loop */
|
||||
|
||||
"str %[c0], [%[result], %[k]] \n\t" /* result[num_words * 2 - 1] = c0 */
|
||||
RESUME_SYNTAX
|
||||
: [c0] "+r" (c0), [c1] "+r" (c1), [c2] "+r" (c2),
|
||||
[k] "+r" (k), [i] "=&r" (i), [t0] "=&r" (t0), [t1] "=&r" (t1)
|
||||
: [result] "r" (result), [left] "r" (left), [right] "r" (right),
|
||||
[last_word] "r" ((num_words - 1) * 4)
|
||||
: "cc", "memory"
|
||||
);
|
||||
|
||||
#else /* Thumb-1 */
|
||||
uint32_t r4, r5, r6, r7;
|
||||
|
||||
__asm__ volatile (
|
||||
".syntax unified \n\t"
|
||||
"subs %[r3], #1 \n\t" /* r3 = num_words - 1 */
|
||||
"lsls %[r3], #2 \n\t" /* r3 = (num_words - 1) * 4 */
|
||||
"mov r8, %[r3] \n\t" /* r8 = (num_words - 1) * 4 */
|
||||
"lsls %[r3], #1 \n\t" /* r3 = (num_words - 1) * 8 */
|
||||
"mov r9, %[r3] \n\t" /* r9 = (num_words - 1) * 8 */
|
||||
"movs %[r3], #0 \n\t" /* c0 = 0 */
|
||||
"movs %[r4], #0 \n\t" /* c1 = 0 */
|
||||
"movs %[r5], #0 \n\t" /* c2 = 0 */
|
||||
"movs %[r6], #0 \n\t" /* k = 0 */
|
||||
|
||||
"push {%[r0]} \n\t" /* keep result on the stack */
|
||||
|
||||
"1: \n\t" /* outer loop (k < num_words) */
|
||||
"movs %[r7], #0 \n\t" /* r7 = i = 0 */
|
||||
"b 3f \n\t"
|
||||
|
||||
"2: \n\t" /* outer loop (k >= num_words) */
|
||||
"movs %[r7], %[r6] \n\t" /* r7 = k */
|
||||
"mov %[r0], r8 \n\t" /* r0 = (num_words - 1) * 4 */
|
||||
"subs %[r7], %[r0] \n\t" /* r7 = i = k - (num_words - 1) (times 4) */
|
||||
|
||||
"3: \n\t" /* inner loop */
|
||||
"mov r10, %[r3] \n\t"
|
||||
"mov r11, %[r4] \n\t"
|
||||
"mov r12, %[r5] \n\t"
|
||||
"mov r14, %[r6] \n\t"
|
||||
"subs %[r0], %[r6], %[r7] \n\t" /* r0 = k - i */
|
||||
|
||||
"ldr %[r4], [%[r2], %[r0]] \n\t" /* r4 = right[k - i] */
|
||||
"ldr %[r0], [%[r1], %[r7]] \n\t" /* r0 = left[i] */
|
||||
|
||||
"lsrs %[r3], %[r0], #16 \n\t" /* r3 = a1 */
|
||||
"uxth %[r0], %[r0] \n\t" /* r0 = a0 */
|
||||
|
||||
"lsrs %[r5], %[r4], #16 \n\t" /* r5 = b1 */
|
||||
"uxth %[r4], %[r4] \n\t" /* r4 = b0 */
|
||||
|
||||
"movs %[r6], %[r3] \n\t" /* r6 = a1 */
|
||||
"muls %[r6], %[r5], %[r6] \n\t" /* r6 = a1 * b1 */
|
||||
"muls %[r3], %[r4], %[r3] \n\t" /* r3 = b0 * a1 */
|
||||
"muls %[r5], %[r0], %[r5] \n\t" /* r5 = a0 * b1 */
|
||||
"muls %[r0], %[r4], %[r0] \n\t" /* r0 = a0 * b0 */
|
||||
|
||||
/* Add middle terms */
|
||||
"lsls %[r4], %[r3], #16 \n\t"
|
||||
"lsrs %[r3], %[r3], #16 \n\t"
|
||||
"adds %[r0], %[r4] \n\t"
|
||||
"adcs %[r6], %[r3] \n\t"
|
||||
|
||||
"lsls %[r4], %[r5], #16 \n\t"
|
||||
"lsrs %[r5], %[r5], #16 \n\t"
|
||||
"adds %[r0], %[r4] \n\t"
|
||||
"adcs %[r6], %[r5] \n\t"
|
||||
|
||||
"mov %[r3], r10\n\t"
|
||||
"mov %[r4], r11\n\t"
|
||||
"mov %[r5], r12\n\t"
|
||||
"adds %[r3], %[r0] \n\t" /* add low word to c0 */
|
||||
"adcs %[r4], %[r6] \n\t" /* add high word to c1, including carry */
|
||||
"movs %[r0], #0 \n\t" /* r0 = 0 (does not affect carry bit) */
|
||||
"adcs %[r5], %[r0] \n\t" /* add carry to c2 */
|
||||
|
||||
"mov %[r6], r14\n\t" /* r6 = k */
|
||||
|
||||
"adds %[r7], #4 \n\t" /* i += 4 */
|
||||
"cmp %[r7], r8 \n\t" /* i > (num_words - 1) (times 4)? */
|
||||
"bgt 4f \n\t" /* if so, exit the loop */
|
||||
"cmp %[r7], %[r6] \n\t" /* i <= k? */
|
||||
"ble 3b \n\t" /* if so, continue looping */
|
||||
|
||||
"4: \n\t" /* end inner loop */
|
||||
|
||||
"ldr %[r0], [sp, #0] \n\t" /* r0 = result */
|
||||
|
||||
"str %[r3], [%[r0], %[r6]] \n\t" /* result[k] = c0 */
|
||||
"mov %[r3], %[r4] \n\t" /* c0 = c1 */
|
||||
"mov %[r4], %[r5] \n\t" /* c1 = c2 */
|
||||
"movs %[r5], #0 \n\t" /* c2 = 0 */
|
||||
"adds %[r6], #4 \n\t" /* k += 4 */
|
||||
"cmp %[r6], r8 \n\t" /* k <= (num_words - 1) (times 4) ? */
|
||||
"ble 1b \n\t" /* if so, loop back, start with i = 0 */
|
||||
"cmp %[r6], r9 \n\t" /* k <= (num_words * 2 - 2) (times 4) ? */
|
||||
"ble 2b \n\t" /* if so, loop back, with i = (k + 1) - num_words */
|
||||
/* end outer loop */
|
||||
|
||||
"str %[r3], [%[r0], %[r6]] \n\t" /* result[num_words * 2 - 1] = c0 */
|
||||
"pop {%[r0]} \n\t" /* pop result off the stack */
|
||||
|
||||
RESUME_SYNTAX
|
||||
: [r3] "+l" (num_words), [r4] "=&l" (r4),
|
||||
[r5] "=&l" (r5), [r6] "=&l" (r6), [r7] "=&l" (r7)
|
||||
: [r0] "l" (result), [r1] "l" (left), [r2] "l" (right)
|
||||
: "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory"
|
||||
);
|
||||
#endif
|
||||
}
|
||||
#define asm_mult 1
|
||||
#endif
|
||||
|
||||
#if uECC_SQUARE_FUNC
|
||||
#if !asm_square
|
||||
uECC_VLI_API void uECC_vli_square(uECC_word_t *result,
|
||||
const uECC_word_t *left,
|
||||
wordcount_t num_words) {
|
||||
#if (uECC_PLATFORM != uECC_arm_thumb)
|
||||
uint32_t c0 = 0;
|
||||
uint32_t c1 = 0;
|
||||
uint32_t c2 = 0;
|
||||
uint32_t k = 0;
|
||||
uint32_t i, tt;
|
||||
uint32_t t0, t1;
|
||||
|
||||
__asm__ volatile (
|
||||
".syntax unified \n\t"
|
||||
|
||||
"1: \n\t" /* outer loop (k < num_words) */
|
||||
"movs %[i], #0 \n\t" /* i = 0 */
|
||||
"b 3f \n\t"
|
||||
|
||||
"2: \n\t" /* outer loop (k >= num_words) */
|
||||
"movs %[i], %[k] \n\t" /* i = k */
|
||||
"subs %[i], %[last_word] \n\t" /* i = k - (num_words - 1) (times 4) */
|
||||
|
||||
"3: \n\t" /* inner loop */
|
||||
"subs %[tt], %[k], %[i] \n\t" /* tt = k-i */
|
||||
|
||||
"ldr %[t1], [%[left], %[tt]] \n\t" /* t1 = left[k - i] */
|
||||
"ldr %[t0], [%[left], %[i]] \n\t" /* t0 = left[i] */
|
||||
|
||||
"umull %[t0], %[t1], %[t0], %[t1] \n\t" /* (t0, t1) = left[i] * right[k - i] */
|
||||
|
||||
"cmp %[i], %[tt] \n\t" /* (i < k - i) ? */
|
||||
"bge 4f \n\t" /* if i >= k - i, skip */
|
||||
"adds %[c0], %[c0], %[t0] \n\t" /* add low word to c0 */
|
||||
"adcs %[c1], %[c1], %[t1] \n\t" /* add high word to c1, including carry */
|
||||
"adcs %[c2], %[c2], #0 \n\t" /* add carry to c2 */
|
||||
|
||||
"4: \n\t"
|
||||
"adds %[c0], %[c0], %[t0] \n\t" /* add low word to c0 */
|
||||
"adcs %[c1], %[c1], %[t1] \n\t" /* add high word to c1, including carry */
|
||||
"adcs %[c2], %[c2], #0 \n\t" /* add carry to c2 */
|
||||
|
||||
"adds %[i], #4 \n\t" /* i += 4 */
|
||||
"cmp %[i], %[k] \n\t" /* i >= k? */
|
||||
"bge 5f \n\t" /* if so, exit the loop */
|
||||
"subs %[tt], %[k], %[i] \n\t" /* tt = k - i */
|
||||
"cmp %[i], %[tt] \n\t" /* i <= k - i? */
|
||||
"ble 3b \n\t" /* if so, continue looping */
|
||||
|
||||
"5: \n\t" /* end inner loop */
|
||||
|
||||
"str %[c0], [%[result], %[k]] \n\t" /* result[k] = c0 */
|
||||
"mov %[c0], %[c1] \n\t" /* c0 = c1 */
|
||||
"mov %[c1], %[c2] \n\t" /* c1 = c2 */
|
||||
"movs %[c2], #0 \n\t" /* c2 = 0 */
|
||||
"adds %[k], #4 \n\t" /* k += 4 */
|
||||
"cmp %[k], %[last_word] \n\t" /* k <= (num_words - 1) (times 4) ? */
|
||||
"ble 1b \n\t" /* if so, loop back, start with i = 0 */
|
||||
"cmp %[k], %[last_word], lsl #1 \n\t" /* k <= (num_words * 2 - 2) (times 4) ? */
|
||||
"ble 2b \n\t" /* if so, loop back, start with i = (k + 1) - num_words */
|
||||
/* end outer loop */
|
||||
|
||||
"str %[c0], [%[result], %[k]] \n\t" /* result[num_words * 2 - 1] = c0 */
|
||||
RESUME_SYNTAX
|
||||
: [c0] "+r" (c0), [c1] "+r" (c1), [c2] "+r" (c2),
|
||||
[k] "+r" (k), [i] "=&r" (i), [tt] "=&r" (tt), [t0] "=&r" (t0), [t1] "=&r" (t1)
|
||||
: [result] "r" (result), [left] "r" (left), [last_word] "r" ((num_words - 1) * 4)
|
||||
: "cc", "memory"
|
||||
);
|
||||
|
||||
#else
|
||||
uint32_t r3, r4, r5, r6, r7;
|
||||
|
||||
__asm__ volatile (
|
||||
".syntax unified \n\t"
|
||||
"subs %[r2], #1 \n\t" /* r2 = num_words - 1 */
|
||||
"lsls %[r2], #2 \n\t" /* r2 = (num_words - 1) * 4 */
|
||||
"mov r8, %[r2] \n\t" /* r8 = (num_words - 1) * 4 */
|
||||
"lsls %[r2], #1 \n\t" /* r2 = (num_words - 1) * 8 */
|
||||
"mov r9, %[r2] \n\t" /* r9 = (num_words - 1) * 8 */
|
||||
"movs %[r2], #0 \n\t" /* c0 = 0 */
|
||||
"movs %[r3], #0 \n\t" /* c1 = 0 */
|
||||
"movs %[r4], #0 \n\t" /* c2 = 0 */
|
||||
"movs %[r5], #0 \n\t" /* k = 0 */
|
||||
|
||||
"push {%[r0]} \n\t" /* keep result on the stack */
|
||||
|
||||
"1: \n\t" /* outer loop (k < num_words) */
|
||||
"movs %[r6], #0 \n\t" /* r6 = i = 0 */
|
||||
"b 3f \n\t"
|
||||
|
||||
"2: \n\t" /* outer loop (k >= num_words) */
|
||||
"movs %[r6], %[r5] \n\t" /* r6 = k */
|
||||
"mov %[r0], r8 \n\t" /* r0 = (num_words - 1) * 4 */
|
||||
"subs %[r6], %[r0] \n\t" /* r6 = i = k - (num_words - 1) (times 4) */
|
||||
|
||||
"3: \n\t" /* inner loop */
|
||||
"mov r10, %[r2] \n\t"
|
||||
"mov r11, %[r3] \n\t"
|
||||
"mov r12, %[r4] \n\t"
|
||||
"mov r14, %[r5] \n\t"
|
||||
"subs %[r7], %[r5], %[r6] \n\t" /* r7 = k - i */
|
||||
|
||||
"ldr %[r3], [%[r1], %[r7]] \n\t" /* r3 = left[k - i] */
|
||||
"ldr %[r0], [%[r1], %[r6]] \n\t" /* r0 = left[i] */
|
||||
|
||||
"lsrs %[r2], %[r0], #16 \n\t" /* r2 = a1 */
|
||||
"uxth %[r0], %[r0] \n\t" /* r0 = a0 */
|
||||
|
||||
"lsrs %[r4], %[r3], #16 \n\t" /* r4 = b1 */
|
||||
"uxth %[r3], %[r3] \n\t" /* r3 = b0 */
|
||||
|
||||
"movs %[r5], %[r2] \n\t" /* r5 = a1 */
|
||||
"muls %[r5], %[r4], %[r5] \n\t" /* r5 = a1 * b1 */
|
||||
"muls %[r2], %[r3], %[r2] \n\t" /* r2 = b0 * a1 */
|
||||
"muls %[r4], %[r0], %[r4] \n\t" /* r4 = a0 * b1 */
|
||||
"muls %[r0], %[r3], %[r0] \n\t" /* r0 = a0 * b0 */
|
||||
|
||||
/* Add middle terms */
|
||||
"lsls %[r3], %[r2], #16 \n\t"
|
||||
"lsrs %[r2], %[r2], #16 \n\t"
|
||||
"adds %[r0], %[r3] \n\t"
|
||||
"adcs %[r5], %[r2] \n\t"
|
||||
|
||||
"lsls %[r3], %[r4], #16 \n\t"
|
||||
"lsrs %[r4], %[r4], #16 \n\t"
|
||||
"adds %[r0], %[r3] \n\t"
|
||||
"adcs %[r5], %[r4] \n\t"
|
||||
|
||||
/* Add to acc, doubling if necessary */
|
||||
"mov %[r2], r10\n\t"
|
||||
"mov %[r3], r11\n\t"
|
||||
"mov %[r4], r12\n\t"
|
||||
|
||||
"cmp %[r6], %[r7] \n\t" /* (i < k - i) ? */
|
||||
"bge 4f \n\t" /* if i >= k - i, skip */
|
||||
"movs %[r7], #0 \n\t" /* r7 = 0 */
|
||||
"adds %[r2], %[r0] \n\t" /* add low word to c0 */
|
||||
"adcs %[r3], %[r5] \n\t" /* add high word to c1, including carry */
|
||||
"adcs %[r4], %[r7] \n\t" /* add carry to c2 */
|
||||
"4: \n\t"
|
||||
"movs %[r7], #0 \n\t" /* r7 = 0 */
|
||||
"adds %[r2], %[r0] \n\t" /* add low word to c0 */
|
||||
"adcs %[r3], %[r5] \n\t" /* add high word to c1, including carry */
|
||||
"adcs %[r4], %[r7] \n\t" /* add carry to c2 */
|
||||
|
||||
"mov %[r5], r14\n\t" /* r5 = k */
|
||||
|
||||
"adds %[r6], #4 \n\t" /* i += 4 */
|
||||
"cmp %[r6], %[r5] \n\t" /* i >= k? */
|
||||
"bge 5f \n\t" /* if so, exit the loop */
|
||||
"subs %[r7], %[r5], %[r6] \n\t" /* r7 = k - i */
|
||||
"cmp %[r6], %[r7] \n\t" /* i <= k - i? */
|
||||
"ble 3b \n\t" /* if so, continue looping */
|
||||
|
||||
"5: \n\t" /* end inner loop */
|
||||
|
||||
"ldr %[r0], [sp, #0] \n\t" /* r0 = result */
|
||||
|
||||
"str %[r2], [%[r0], %[r5]] \n\t" /* result[k] = c0 */
|
||||
"mov %[r2], %[r3] \n\t" /* c0 = c1 */
|
||||
"mov %[r3], %[r4] \n\t" /* c1 = c2 */
|
||||
"movs %[r4], #0 \n\t" /* c2 = 0 */
|
||||
"adds %[r5], #4 \n\t" /* k += 4 */
|
||||
"cmp %[r5], r8 \n\t" /* k <= (num_words - 1) (times 4) ? */
|
||||
"ble 1b \n\t" /* if so, loop back, start with i = 0 */
|
||||
"cmp %[r5], r9 \n\t" /* k <= (num_words * 2 - 2) (times 4) ? */
|
||||
"ble 2b \n\t" /* if so, loop back, with i = (k + 1) - num_words */
|
||||
/* end outer loop */
|
||||
|
||||
"str %[r2], [%[r0], %[r5]] \n\t" /* result[num_words * 2 - 1] = c0 */
|
||||
"pop {%[r0]} \n\t" /* pop result off the stack */
|
||||
|
||||
RESUME_SYNTAX
|
||||
: [r2] "+l" (num_words), [r3] "=&l" (r3), [r4] "=&l" (r4),
|
||||
[r5] "=&l" (r5), [r6] "=&l" (r6), [r7] "=&l" (r7)
|
||||
: [r0] "l" (result), [r1] "l" (left)
|
||||
: "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory"
|
||||
);
|
||||
#endif
|
||||
}
|
||||
#define asm_square 1
|
||||
#endif
|
||||
#endif /* uECC_SQUARE_FUNC */
|
||||
|
||||
#endif /* _UECC_ASM_ARM_H_ */
|
||||
1248
SDK/12.3.0_d7731ad/external/micro-ecc/micro-ecc/curve-specific.inc
vendored
Normal file
1248
SDK/12.3.0_d7731ad/external/micro-ecc/micro-ecc/curve-specific.inc
vendored
Normal file
File diff suppressed because it is too large
Load Diff
94
SDK/12.3.0_d7731ad/external/micro-ecc/micro-ecc/platform-specific.inc
vendored
Normal file
94
SDK/12.3.0_d7731ad/external/micro-ecc/micro-ecc/platform-specific.inc
vendored
Normal file
@@ -0,0 +1,94 @@
|
||||
/* Copyright 2015, Kenneth MacKay. Licensed under the BSD 2-clause license. */
|
||||
|
||||
#ifndef _UECC_PLATFORM_SPECIFIC_H_
|
||||
#define _UECC_PLATFORM_SPECIFIC_H_
|
||||
|
||||
#include "types.h"
|
||||
|
||||
#if (defined(_WIN32) || defined(_WIN64))
|
||||
/* Windows */
|
||||
|
||||
// use pragma syntax to prevent tweaking the linker script for getting CryptXYZ function
|
||||
#pragma comment(lib, "crypt32.lib")
|
||||
#pragma comment(lib, "advapi32.lib")
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include <wincrypt.h>
|
||||
|
||||
static int default_RNG(uint8_t *dest, unsigned size) {
|
||||
HCRYPTPROV prov;
|
||||
if (!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
CryptGenRandom(prov, size, (BYTE *)dest);
|
||||
CryptReleaseContext(prov, 0);
|
||||
return 1;
|
||||
}
|
||||
#define default_RNG_defined 1
|
||||
|
||||
#elif defined(unix) || defined(__linux__) || defined(__unix__) || defined(__unix) || \
|
||||
(defined(__APPLE__) && defined(__MACH__)) || defined(uECC_POSIX)
|
||||
|
||||
/* Some POSIX-like system with /dev/urandom or /dev/random. */
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifndef O_CLOEXEC
|
||||
#define O_CLOEXEC 0
|
||||
#endif
|
||||
|
||||
static int default_RNG(uint8_t *dest, unsigned size) {
|
||||
int fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC);
|
||||
if (fd == -1) {
|
||||
fd = open("/dev/random", O_RDONLY | O_CLOEXEC);
|
||||
if (fd == -1) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
char *ptr = (char *)dest;
|
||||
size_t left = size;
|
||||
while (left > 0) {
|
||||
ssize_t bytes_read = read(fd, ptr, left);
|
||||
if (bytes_read <= 0) { // read failed
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
left -= bytes_read;
|
||||
ptr += bytes_read;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return 1;
|
||||
}
|
||||
#define default_RNG_defined 1
|
||||
|
||||
#elif defined(RIOT_VERSION)
|
||||
|
||||
#include <random.h>
|
||||
|
||||
static int default_RNG(uint8_t *dest, unsigned size) {
|
||||
random_bytes(dest, size);
|
||||
return 1;
|
||||
}
|
||||
#define default_RNG_defined 1
|
||||
|
||||
#elif defined(NRF52_SERIES)
|
||||
|
||||
#include "app_error.h"
|
||||
#include "nrf_crypto_rng.h"
|
||||
|
||||
static int default_RNG(uint8_t *dest, unsigned size)
|
||||
{
|
||||
// make sure to call nrf_crypto_init and nrf_crypto_rng_init first
|
||||
ret_code_t ret_code = nrf_crypto_rng_vector_generate(dest, size);
|
||||
return (ret_code == NRF_SUCCESS) ? 1 : 0;
|
||||
}
|
||||
#define default_RNG_defined 1
|
||||
|
||||
#endif /* platform */
|
||||
|
||||
#endif /* _UECC_PLATFORM_SPECIFIC_H_ */
|
||||
108
SDK/12.3.0_d7731ad/external/micro-ecc/micro-ecc/types.h
vendored
Normal file
108
SDK/12.3.0_d7731ad/external/micro-ecc/micro-ecc/types.h
vendored
Normal file
@@ -0,0 +1,108 @@
|
||||
/* Copyright 2015, Kenneth MacKay. Licensed under the BSD 2-clause license. */
|
||||
|
||||
#ifndef _UECC_TYPES_H_
|
||||
#define _UECC_TYPES_H_
|
||||
|
||||
#ifndef uECC_PLATFORM
|
||||
#if __AVR__
|
||||
#define uECC_PLATFORM uECC_avr
|
||||
#elif defined(__thumb2__) || defined(_M_ARMT) /* I think MSVC only supports Thumb-2 targets */
|
||||
#define uECC_PLATFORM uECC_arm_thumb2
|
||||
#elif defined(__thumb__)
|
||||
#define uECC_PLATFORM uECC_arm_thumb
|
||||
#elif defined(__arm__) || defined(_M_ARM)
|
||||
#define uECC_PLATFORM uECC_arm
|
||||
#elif defined(__aarch64__)
|
||||
#define uECC_PLATFORM uECC_arm64
|
||||
#elif defined(__i386__) || defined(_M_IX86) || defined(_X86_) || defined(__I86__)
|
||||
#define uECC_PLATFORM uECC_x86
|
||||
#elif defined(__amd64__) || defined(_M_X64)
|
||||
#define uECC_PLATFORM uECC_x86_64
|
||||
#else
|
||||
#define uECC_PLATFORM uECC_arch_other
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef uECC_ARM_USE_UMAAL
|
||||
#if (uECC_PLATFORM == uECC_arm) && (__ARM_ARCH >= 6)
|
||||
#define uECC_ARM_USE_UMAAL 1
|
||||
#elif (uECC_PLATFORM == uECC_arm_thumb2) && (__ARM_ARCH >= 6) && !__ARM_ARCH_7M__
|
||||
#define uECC_ARM_USE_UMAAL 1
|
||||
#else
|
||||
#define uECC_ARM_USE_UMAAL 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef uECC_WORD_SIZE
|
||||
#if uECC_PLATFORM == uECC_avr
|
||||
#define uECC_WORD_SIZE 1
|
||||
#elif (uECC_PLATFORM == uECC_x86_64 || uECC_PLATFORM == uECC_arm64)
|
||||
#define uECC_WORD_SIZE 8
|
||||
#else
|
||||
#define uECC_WORD_SIZE 4
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if (uECC_WORD_SIZE != 1) && (uECC_WORD_SIZE != 4) && (uECC_WORD_SIZE != 8)
|
||||
#error "Unsupported value for uECC_WORD_SIZE"
|
||||
#endif
|
||||
|
||||
#if ((uECC_PLATFORM == uECC_avr) && (uECC_WORD_SIZE != 1))
|
||||
#pragma message ("uECC_WORD_SIZE must be 1 for AVR")
|
||||
#undef uECC_WORD_SIZE
|
||||
#define uECC_WORD_SIZE 1
|
||||
#endif
|
||||
|
||||
#if ((uECC_PLATFORM == uECC_arm || uECC_PLATFORM == uECC_arm_thumb || \
|
||||
uECC_PLATFORM == uECC_arm_thumb2) && \
|
||||
(uECC_WORD_SIZE != 4))
|
||||
#pragma message ("uECC_WORD_SIZE must be 4 for ARM")
|
||||
#undef uECC_WORD_SIZE
|
||||
#define uECC_WORD_SIZE 4
|
||||
#endif
|
||||
|
||||
#if defined(__SIZEOF_INT128__) || ((__clang_major__ * 100 + __clang_minor__) >= 302)
|
||||
#define SUPPORTS_INT128 1
|
||||
#else
|
||||
#define SUPPORTS_INT128 0
|
||||
#endif
|
||||
|
||||
typedef int8_t wordcount_t;
|
||||
typedef int16_t bitcount_t;
|
||||
typedef int8_t cmpresult_t;
|
||||
|
||||
#if (uECC_WORD_SIZE == 1)
|
||||
|
||||
typedef uint8_t uECC_word_t;
|
||||
typedef uint16_t uECC_dword_t;
|
||||
|
||||
#define HIGH_BIT_SET 0x80
|
||||
#define uECC_WORD_BITS 8
|
||||
#define uECC_WORD_BITS_SHIFT 3
|
||||
#define uECC_WORD_BITS_MASK 0x07
|
||||
|
||||
#elif (uECC_WORD_SIZE == 4)
|
||||
|
||||
typedef uint32_t uECC_word_t;
|
||||
typedef uint64_t uECC_dword_t;
|
||||
|
||||
#define HIGH_BIT_SET 0x80000000
|
||||
#define uECC_WORD_BITS 32
|
||||
#define uECC_WORD_BITS_SHIFT 5
|
||||
#define uECC_WORD_BITS_MASK 0x01F
|
||||
|
||||
#elif (uECC_WORD_SIZE == 8)
|
||||
|
||||
typedef uint64_t uECC_word_t;
|
||||
#if SUPPORTS_INT128
|
||||
typedef unsigned __int128 uECC_dword_t;
|
||||
#endif
|
||||
|
||||
#define HIGH_BIT_SET 0x8000000000000000ull
|
||||
#define uECC_WORD_BITS 64
|
||||
#define uECC_WORD_BITS_SHIFT 6
|
||||
#define uECC_WORD_BITS_MASK 0x03F
|
||||
|
||||
#endif /* uECC_WORD_SIZE */
|
||||
|
||||
#endif /* _UECC_TYPES_H_ */
|
||||
1673
SDK/12.3.0_d7731ad/external/micro-ecc/micro-ecc/uECC.c
vendored
Normal file
1673
SDK/12.3.0_d7731ad/external/micro-ecc/micro-ecc/uECC.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
367
SDK/12.3.0_d7731ad/external/micro-ecc/micro-ecc/uECC.h
vendored
Normal file
367
SDK/12.3.0_d7731ad/external/micro-ecc/micro-ecc/uECC.h
vendored
Normal file
@@ -0,0 +1,367 @@
|
||||
/* Copyright 2014, Kenneth MacKay. Licensed under the BSD 2-clause license. */
|
||||
|
||||
#ifndef _UECC_H_
|
||||
#define _UECC_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* Platform selection options.
|
||||
If uECC_PLATFORM is not defined, the code will try to guess it based on compiler macros.
|
||||
Possible values for uECC_PLATFORM are defined below: */
|
||||
#define uECC_arch_other 0
|
||||
#define uECC_x86 1
|
||||
#define uECC_x86_64 2
|
||||
#define uECC_arm 3
|
||||
#define uECC_arm_thumb 4
|
||||
#define uECC_arm_thumb2 5
|
||||
#define uECC_arm64 6
|
||||
#define uECC_avr 7
|
||||
|
||||
/* If desired, you can define uECC_WORD_SIZE as appropriate for your platform (1, 4, or 8 bytes).
|
||||
If uECC_WORD_SIZE is not explicitly defined then it will be automatically set based on your
|
||||
platform. */
|
||||
|
||||
/* Optimization level; trade speed for code size.
|
||||
Larger values produce code that is faster but larger.
|
||||
Currently supported values are 0 - 4; 0 is unusably slow for most applications.
|
||||
Optimization level 4 currently only has an effect ARM platforms where more than one
|
||||
curve is enabled. */
|
||||
#ifndef uECC_OPTIMIZATION_LEVEL
|
||||
#define uECC_OPTIMIZATION_LEVEL 2
|
||||
#endif
|
||||
|
||||
/* uECC_SQUARE_FUNC - If enabled (defined as nonzero), this will cause a specific function to be
|
||||
used for (scalar) squaring instead of the generic multiplication function. This can make things
|
||||
faster somewhat faster, but increases the code size. */
|
||||
#ifndef uECC_SQUARE_FUNC
|
||||
#define uECC_SQUARE_FUNC 0
|
||||
#endif
|
||||
|
||||
/* uECC_VLI_NATIVE_LITTLE_ENDIAN - If enabled (defined as nonzero), this will switch to native
|
||||
little-endian format for *all* arrays passed in and out of the public API. This includes public
|
||||
and private keys, shared secrets, signatures and message hashes.
|
||||
Using this switch reduces the amount of call stack memory used by uECC, since less intermediate
|
||||
translations are required.
|
||||
Note that this will *only* work on native little-endian processors and it will treat the uint8_t
|
||||
arrays passed into the public API as word arrays, therefore requiring the provided byte arrays
|
||||
to be word aligned on architectures that do not support unaligned accesses.
|
||||
IMPORTANT: Keys and signatures generated with uECC_VLI_NATIVE_LITTLE_ENDIAN=1 are incompatible
|
||||
with keys and signatures generated with uECC_VLI_NATIVE_LITTLE_ENDIAN=0; all parties must use
|
||||
the same endianness. */
|
||||
#ifndef uECC_VLI_NATIVE_LITTLE_ENDIAN
|
||||
#define uECC_VLI_NATIVE_LITTLE_ENDIAN 0
|
||||
#endif
|
||||
|
||||
/* Curve support selection. Set to 0 to remove that curve. */
|
||||
#ifndef uECC_SUPPORTS_secp160r1
|
||||
#define uECC_SUPPORTS_secp160r1 1
|
||||
#endif
|
||||
#ifndef uECC_SUPPORTS_secp192r1
|
||||
#define uECC_SUPPORTS_secp192r1 1
|
||||
#endif
|
||||
#ifndef uECC_SUPPORTS_secp224r1
|
||||
#define uECC_SUPPORTS_secp224r1 1
|
||||
#endif
|
||||
#ifndef uECC_SUPPORTS_secp256r1
|
||||
#define uECC_SUPPORTS_secp256r1 1
|
||||
#endif
|
||||
#ifndef uECC_SUPPORTS_secp256k1
|
||||
#define uECC_SUPPORTS_secp256k1 1
|
||||
#endif
|
||||
|
||||
/* Specifies whether compressed point format is supported.
|
||||
Set to 0 to disable point compression/decompression functions. */
|
||||
#ifndef uECC_SUPPORT_COMPRESSED_POINT
|
||||
#define uECC_SUPPORT_COMPRESSED_POINT 1
|
||||
#endif
|
||||
|
||||
struct uECC_Curve_t;
|
||||
typedef const struct uECC_Curve_t * uECC_Curve;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#if uECC_SUPPORTS_secp160r1
|
||||
uECC_Curve uECC_secp160r1(void);
|
||||
#endif
|
||||
#if uECC_SUPPORTS_secp192r1
|
||||
uECC_Curve uECC_secp192r1(void);
|
||||
#endif
|
||||
#if uECC_SUPPORTS_secp224r1
|
||||
uECC_Curve uECC_secp224r1(void);
|
||||
#endif
|
||||
#if uECC_SUPPORTS_secp256r1
|
||||
uECC_Curve uECC_secp256r1(void);
|
||||
#endif
|
||||
#if uECC_SUPPORTS_secp256k1
|
||||
uECC_Curve uECC_secp256k1(void);
|
||||
#endif
|
||||
|
||||
/* uECC_RNG_Function type
|
||||
The RNG function should fill 'size' random bytes into 'dest'. It should return 1 if
|
||||
'dest' was filled with random data, or 0 if the random data could not be generated.
|
||||
The filled-in values should be either truly random, or from a cryptographically-secure PRNG.
|
||||
|
||||
A correctly functioning RNG function must be set (using uECC_set_rng()) before calling
|
||||
uECC_make_key() or uECC_sign().
|
||||
|
||||
Setting a correctly functioning RNG function improves the resistance to side-channel attacks
|
||||
for uECC_shared_secret() and uECC_sign_deterministic().
|
||||
|
||||
A correct RNG function is set by default when building for Windows, Linux, or OS X.
|
||||
If you are building on another POSIX-compliant system that supports /dev/random or /dev/urandom,
|
||||
you can define uECC_POSIX to use the predefined RNG. For embedded platforms there is no predefined
|
||||
RNG function; you must provide your own.
|
||||
*/
|
||||
typedef int (*uECC_RNG_Function)(uint8_t *dest, unsigned size);
|
||||
|
||||
/* uECC_set_rng() function.
|
||||
Set the function that will be used to generate random bytes. The RNG function should
|
||||
return 1 if the random data was generated, or 0 if the random data could not be generated.
|
||||
|
||||
On platforms where there is no predefined RNG function (eg embedded platforms), this must
|
||||
be called before uECC_make_key() or uECC_sign() are used.
|
||||
|
||||
Inputs:
|
||||
rng_function - The function that will be used to generate random bytes.
|
||||
*/
|
||||
void uECC_set_rng(uECC_RNG_Function rng_function);
|
||||
|
||||
/* uECC_get_rng() function.
|
||||
|
||||
Returns the function that will be used to generate random bytes.
|
||||
*/
|
||||
uECC_RNG_Function uECC_get_rng(void);
|
||||
|
||||
/* uECC_curve_private_key_size() function.
|
||||
|
||||
Returns the size of a private key for the curve in bytes.
|
||||
*/
|
||||
int uECC_curve_private_key_size(uECC_Curve curve);
|
||||
|
||||
/* uECC_curve_public_key_size() function.
|
||||
|
||||
Returns the size of a public key for the curve in bytes.
|
||||
*/
|
||||
int uECC_curve_public_key_size(uECC_Curve curve);
|
||||
|
||||
/* uECC_make_key() function.
|
||||
Create a public/private key pair.
|
||||
|
||||
Outputs:
|
||||
public_key - Will be filled in with the public key. Must be at least 2 * the curve size
|
||||
(in bytes) long. For example, if the curve is secp256r1, public_key must be 64
|
||||
bytes long.
|
||||
private_key - Will be filled in with the private key. Must be as long as the curve order; this
|
||||
is typically the same as the curve size, except for secp160r1. For example, if the
|
||||
curve is secp256r1, private_key must be 32 bytes long.
|
||||
|
||||
For secp160r1, private_key must be 21 bytes long! Note that the first byte will
|
||||
almost always be 0 (there is about a 1 in 2^80 chance of it being non-zero).
|
||||
|
||||
Returns 1 if the key pair was generated successfully, 0 if an error occurred.
|
||||
*/
|
||||
int uECC_make_key(uint8_t *public_key, uint8_t *private_key, uECC_Curve curve);
|
||||
|
||||
/* uECC_shared_secret() function.
|
||||
Compute a shared secret given your secret key and someone else's public key. If the public key
|
||||
is not from a trusted source and has not been previously verified, you should verify it first
|
||||
using uECC_valid_public_key().
|
||||
Note: It is recommended that you hash the result of uECC_shared_secret() before using it for
|
||||
symmetric encryption or HMAC.
|
||||
|
||||
Inputs:
|
||||
public_key - The public key of the remote party.
|
||||
private_key - Your private key.
|
||||
|
||||
Outputs:
|
||||
secret - Will be filled in with the shared secret value. Must be the same size as the
|
||||
curve size; for example, if the curve is secp256r1, secret must be 32 bytes long.
|
||||
|
||||
Returns 1 if the shared secret was generated successfully, 0 if an error occurred.
|
||||
*/
|
||||
int uECC_shared_secret(const uint8_t *public_key,
|
||||
const uint8_t *private_key,
|
||||
uint8_t *secret,
|
||||
uECC_Curve curve);
|
||||
|
||||
#if uECC_SUPPORT_COMPRESSED_POINT
|
||||
/* uECC_compress() function.
|
||||
Compress a public key.
|
||||
|
||||
Inputs:
|
||||
public_key - The public key to compress.
|
||||
|
||||
Outputs:
|
||||
compressed - Will be filled in with the compressed public key. Must be at least
|
||||
(curve size + 1) bytes long; for example, if the curve is secp256r1,
|
||||
compressed must be 33 bytes long.
|
||||
*/
|
||||
void uECC_compress(const uint8_t *public_key, uint8_t *compressed, uECC_Curve curve);
|
||||
|
||||
/* uECC_decompress() function.
|
||||
Decompress a compressed public key.
|
||||
|
||||
Inputs:
|
||||
compressed - The compressed public key.
|
||||
|
||||
Outputs:
|
||||
public_key - Will be filled in with the decompressed public key.
|
||||
*/
|
||||
void uECC_decompress(const uint8_t *compressed, uint8_t *public_key, uECC_Curve curve);
|
||||
#endif /* uECC_SUPPORT_COMPRESSED_POINT */
|
||||
|
||||
/* uECC_valid_public_key() function.
|
||||
Check to see if a public key is valid.
|
||||
|
||||
Note that you are not required to check for a valid public key before using any other uECC
|
||||
functions. However, you may wish to avoid spending CPU time computing a shared secret or
|
||||
verifying a signature using an invalid public key.
|
||||
|
||||
Inputs:
|
||||
public_key - The public key to check.
|
||||
|
||||
Returns 1 if the public key is valid, 0 if it is invalid.
|
||||
*/
|
||||
int uECC_valid_public_key(const uint8_t *public_key, uECC_Curve curve);
|
||||
|
||||
/* uECC_compute_public_key() function.
|
||||
Compute the corresponding public key for a private key.
|
||||
|
||||
Inputs:
|
||||
private_key - The private key to compute the public key for
|
||||
|
||||
Outputs:
|
||||
public_key - Will be filled in with the corresponding public key
|
||||
|
||||
Returns 1 if the key was computed successfully, 0 if an error occurred.
|
||||
*/
|
||||
int uECC_compute_public_key(const uint8_t *private_key, uint8_t *public_key, uECC_Curve curve);
|
||||
|
||||
/* uECC_sign() function.
|
||||
Generate an ECDSA signature for a given hash value.
|
||||
|
||||
Usage: Compute a hash of the data you wish to sign (SHA-2 is recommended) and pass it in to
|
||||
this function along with your private key.
|
||||
|
||||
Inputs:
|
||||
private_key - Your private key.
|
||||
message_hash - The hash of the message to sign.
|
||||
hash_size - The size of message_hash in bytes.
|
||||
|
||||
Outputs:
|
||||
signature - Will be filled in with the signature value. Must be at least 2 * curve size long.
|
||||
For example, if the curve is secp256r1, signature must be 64 bytes long.
|
||||
|
||||
Returns 1 if the signature generated successfully, 0 if an error occurred.
|
||||
*/
|
||||
int uECC_sign(const uint8_t *private_key,
|
||||
const uint8_t *message_hash,
|
||||
unsigned hash_size,
|
||||
uint8_t *signature,
|
||||
uECC_Curve curve);
|
||||
|
||||
/* uECC_HashContext structure.
|
||||
This is used to pass in an arbitrary hash function to uECC_sign_deterministic().
|
||||
The structure will be used for multiple hash computations; each time a new hash
|
||||
is computed, init_hash() will be called, followed by one or more calls to
|
||||
update_hash(), and finally a call to finish_hash() to produce the resulting hash.
|
||||
|
||||
The intention is that you will create a structure that includes uECC_HashContext
|
||||
followed by any hash-specific data. For example:
|
||||
|
||||
typedef struct SHA256_HashContext {
|
||||
uECC_HashContext uECC;
|
||||
SHA256_CTX ctx;
|
||||
} SHA256_HashContext;
|
||||
|
||||
void init_SHA256(uECC_HashContext *base) {
|
||||
SHA256_HashContext *context = (SHA256_HashContext *)base;
|
||||
SHA256_Init(&context->ctx);
|
||||
}
|
||||
|
||||
void update_SHA256(uECC_HashContext *base,
|
||||
const uint8_t *message,
|
||||
unsigned message_size) {
|
||||
SHA256_HashContext *context = (SHA256_HashContext *)base;
|
||||
SHA256_Update(&context->ctx, message, message_size);
|
||||
}
|
||||
|
||||
void finish_SHA256(uECC_HashContext *base, uint8_t *hash_result) {
|
||||
SHA256_HashContext *context = (SHA256_HashContext *)base;
|
||||
SHA256_Final(hash_result, &context->ctx);
|
||||
}
|
||||
|
||||
... when signing ...
|
||||
{
|
||||
uint8_t tmp[32 + 32 + 64];
|
||||
SHA256_HashContext ctx = {{&init_SHA256, &update_SHA256, &finish_SHA256, 64, 32, tmp}};
|
||||
uECC_sign_deterministic(key, message_hash, &ctx.uECC, signature);
|
||||
}
|
||||
*/
|
||||
typedef struct uECC_HashContext {
|
||||
void (*init_hash)(const struct uECC_HashContext *context);
|
||||
void (*update_hash)(const struct uECC_HashContext *context,
|
||||
const uint8_t *message,
|
||||
unsigned message_size);
|
||||
void (*finish_hash)(const struct uECC_HashContext *context, uint8_t *hash_result);
|
||||
unsigned block_size; /* Hash function block size in bytes, eg 64 for SHA-256. */
|
||||
unsigned result_size; /* Hash function result size in bytes, eg 32 for SHA-256. */
|
||||
uint8_t *tmp; /* Must point to a buffer of at least (2 * result_size + block_size) bytes. */
|
||||
} uECC_HashContext;
|
||||
|
||||
/* uECC_sign_deterministic() function.
|
||||
Generate an ECDSA signature for a given hash value, using a deterministic algorithm
|
||||
(see RFC 6979). You do not need to set the RNG using uECC_set_rng() before calling
|
||||
this function; however, if the RNG is defined it will improve resistance to side-channel
|
||||
attacks.
|
||||
|
||||
Usage: Compute a hash of the data you wish to sign (SHA-2 is recommended) and pass it to
|
||||
this function along with your private key and a hash context. Note that the message_hash
|
||||
does not need to be computed with the same hash function used by hash_context.
|
||||
|
||||
Inputs:
|
||||
private_key - Your private key.
|
||||
message_hash - The hash of the message to sign.
|
||||
hash_size - The size of message_hash in bytes.
|
||||
hash_context - A hash context to use.
|
||||
|
||||
Outputs:
|
||||
signature - Will be filled in with the signature value.
|
||||
|
||||
Returns 1 if the signature generated successfully, 0 if an error occurred.
|
||||
*/
|
||||
int uECC_sign_deterministic(const uint8_t *private_key,
|
||||
const uint8_t *message_hash,
|
||||
unsigned hash_size,
|
||||
const uECC_HashContext *hash_context,
|
||||
uint8_t *signature,
|
||||
uECC_Curve curve);
|
||||
|
||||
/* uECC_verify() function.
|
||||
Verify an ECDSA signature.
|
||||
|
||||
Usage: Compute the hash of the signed data using the same hash as the signer and
|
||||
pass it to this function along with the signer's public key and the signature values (r and s).
|
||||
|
||||
Inputs:
|
||||
public_key - The signer's public key.
|
||||
message_hash - The hash of the signed data.
|
||||
hash_size - The size of message_hash in bytes.
|
||||
signature - The signature value.
|
||||
|
||||
Returns 1 if the signature is valid, 0 if it is invalid.
|
||||
*/
|
||||
int uECC_verify(const uint8_t *public_key,
|
||||
const uint8_t *message_hash,
|
||||
unsigned hash_size,
|
||||
const uint8_t *signature,
|
||||
uECC_Curve curve);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* _UECC_H_ */
|
||||
172
SDK/12.3.0_d7731ad/external/micro-ecc/micro-ecc/uECC_vli.h
vendored
Normal file
172
SDK/12.3.0_d7731ad/external/micro-ecc/micro-ecc/uECC_vli.h
vendored
Normal file
@@ -0,0 +1,172 @@
|
||||
/* Copyright 2015, Kenneth MacKay. Licensed under the BSD 2-clause license. */
|
||||
|
||||
#ifndef _UECC_VLI_H_
|
||||
#define _UECC_VLI_H_
|
||||
|
||||
#include "uECC.h"
|
||||
#include "types.h"
|
||||
|
||||
/* Functions for raw large-integer manipulation. These are only available
|
||||
if uECC.c is compiled with uECC_ENABLE_VLI_API defined to 1. */
|
||||
#ifndef uECC_ENABLE_VLI_API
|
||||
#define uECC_ENABLE_VLI_API 0
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#if uECC_ENABLE_VLI_API
|
||||
|
||||
void uECC_vli_clear(uECC_word_t *vli, wordcount_t num_words);
|
||||
|
||||
/* Constant-time comparison to zero - secure way to compare long integers */
|
||||
/* Returns 1 if vli == 0, 0 otherwise. */
|
||||
uECC_word_t uECC_vli_isZero(const uECC_word_t *vli, wordcount_t num_words);
|
||||
|
||||
/* Returns nonzero if bit 'bit' of vli is set. */
|
||||
uECC_word_t uECC_vli_testBit(const uECC_word_t *vli, bitcount_t bit);
|
||||
|
||||
/* Counts the number of bits required to represent vli. */
|
||||
bitcount_t uECC_vli_numBits(const uECC_word_t *vli, const wordcount_t max_words);
|
||||
|
||||
/* Sets dest = src. */
|
||||
void uECC_vli_set(uECC_word_t *dest, const uECC_word_t *src, wordcount_t num_words);
|
||||
|
||||
/* Constant-time comparison function - secure way to compare long integers */
|
||||
/* Returns one if left == right, zero otherwise */
|
||||
uECC_word_t uECC_vli_equal(const uECC_word_t *left,
|
||||
const uECC_word_t *right,
|
||||
wordcount_t num_words);
|
||||
|
||||
/* Constant-time comparison function - secure way to compare long integers */
|
||||
/* Returns sign of left - right, in constant time. */
|
||||
cmpresult_t uECC_vli_cmp(const uECC_word_t *left, const uECC_word_t *right, wordcount_t num_words);
|
||||
|
||||
/* Computes vli = vli >> 1. */
|
||||
void uECC_vli_rshift1(uECC_word_t *vli, wordcount_t num_words);
|
||||
|
||||
/* Computes result = left + right, returning carry. Can modify in place. */
|
||||
uECC_word_t uECC_vli_add(uECC_word_t *result,
|
||||
const uECC_word_t *left,
|
||||
const uECC_word_t *right,
|
||||
wordcount_t num_words);
|
||||
|
||||
/* Computes result = left - right, returning borrow. Can modify in place. */
|
||||
uECC_word_t uECC_vli_sub(uECC_word_t *result,
|
||||
const uECC_word_t *left,
|
||||
const uECC_word_t *right,
|
||||
wordcount_t num_words);
|
||||
|
||||
/* Computes result = left * right. Result must be 2 * num_words long. */
|
||||
void uECC_vli_mult(uECC_word_t *result,
|
||||
const uECC_word_t *left,
|
||||
const uECC_word_t *right,
|
||||
wordcount_t num_words);
|
||||
|
||||
/* Computes result = left^2. Result must be 2 * num_words long. */
|
||||
void uECC_vli_square(uECC_word_t *result, const uECC_word_t *left, wordcount_t num_words);
|
||||
|
||||
/* Computes result = (left + right) % mod.
|
||||
Assumes that left < mod and right < mod, and that result does not overlap mod. */
|
||||
void uECC_vli_modAdd(uECC_word_t *result,
|
||||
const uECC_word_t *left,
|
||||
const uECC_word_t *right,
|
||||
const uECC_word_t *mod,
|
||||
wordcount_t num_words);
|
||||
|
||||
/* Computes result = (left - right) % mod.
|
||||
Assumes that left < mod and right < mod, and that result does not overlap mod. */
|
||||
void uECC_vli_modSub(uECC_word_t *result,
|
||||
const uECC_word_t *left,
|
||||
const uECC_word_t *right,
|
||||
const uECC_word_t *mod,
|
||||
wordcount_t num_words);
|
||||
|
||||
/* Computes result = product % mod, where product is 2N words long.
|
||||
Currently only designed to work for mod == curve->p or curve_n. */
|
||||
void uECC_vli_mmod(uECC_word_t *result,
|
||||
uECC_word_t *product,
|
||||
const uECC_word_t *mod,
|
||||
wordcount_t num_words);
|
||||
|
||||
/* Calculates result = product (mod curve->p), where product is up to
|
||||
2 * curve->num_words long. */
|
||||
void uECC_vli_mmod_fast(uECC_word_t *result, uECC_word_t *product, uECC_Curve curve);
|
||||
|
||||
/* Computes result = (left * right) % mod.
|
||||
Currently only designed to work for mod == curve->p or curve_n. */
|
||||
void uECC_vli_modMult(uECC_word_t *result,
|
||||
const uECC_word_t *left,
|
||||
const uECC_word_t *right,
|
||||
const uECC_word_t *mod,
|
||||
wordcount_t num_words);
|
||||
|
||||
/* Computes result = (left * right) % curve->p. */
|
||||
void uECC_vli_modMult_fast(uECC_word_t *result,
|
||||
const uECC_word_t *left,
|
||||
const uECC_word_t *right,
|
||||
uECC_Curve curve);
|
||||
|
||||
/* Computes result = left^2 % mod.
|
||||
Currently only designed to work for mod == curve->p or curve_n. */
|
||||
void uECC_vli_modSquare(uECC_word_t *result,
|
||||
const uECC_word_t *left,
|
||||
const uECC_word_t *mod,
|
||||
wordcount_t num_words);
|
||||
|
||||
/* Computes result = left^2 % curve->p. */
|
||||
void uECC_vli_modSquare_fast(uECC_word_t *result, const uECC_word_t *left, uECC_Curve curve);
|
||||
|
||||
/* Computes result = (1 / input) % mod.*/
|
||||
void uECC_vli_modInv(uECC_word_t *result,
|
||||
const uECC_word_t *input,
|
||||
const uECC_word_t *mod,
|
||||
wordcount_t num_words);
|
||||
|
||||
#if uECC_SUPPORT_COMPRESSED_POINT
|
||||
/* Calculates a = sqrt(a) (mod curve->p) */
|
||||
void uECC_vli_mod_sqrt(uECC_word_t *a, uECC_Curve curve);
|
||||
#endif
|
||||
|
||||
/* Converts an integer in uECC native format to big-endian bytes. */
|
||||
void uECC_vli_nativeToBytes(uint8_t *bytes, int num_bytes, const uECC_word_t *native);
|
||||
/* Converts big-endian bytes to an integer in uECC native format. */
|
||||
void uECC_vli_bytesToNative(uECC_word_t *native, const uint8_t *bytes, int num_bytes);
|
||||
|
||||
unsigned uECC_curve_num_words(uECC_Curve curve);
|
||||
unsigned uECC_curve_num_bytes(uECC_Curve curve);
|
||||
unsigned uECC_curve_num_bits(uECC_Curve curve);
|
||||
unsigned uECC_curve_num_n_words(uECC_Curve curve);
|
||||
unsigned uECC_curve_num_n_bytes(uECC_Curve curve);
|
||||
unsigned uECC_curve_num_n_bits(uECC_Curve curve);
|
||||
|
||||
const uECC_word_t *uECC_curve_p(uECC_Curve curve);
|
||||
const uECC_word_t *uECC_curve_n(uECC_Curve curve);
|
||||
const uECC_word_t *uECC_curve_G(uECC_Curve curve);
|
||||
const uECC_word_t *uECC_curve_b(uECC_Curve curve);
|
||||
|
||||
int uECC_valid_point(const uECC_word_t *point, uECC_Curve curve);
|
||||
|
||||
/* Multiplies a point by a scalar. Points are represented by the X coordinate followed by
|
||||
the Y coordinate in the same array, both coordinates are curve->num_words long. Note
|
||||
that scalar must be curve->num_n_words long (NOT curve->num_words). */
|
||||
void uECC_point_mult(uECC_word_t *result,
|
||||
const uECC_word_t *point,
|
||||
const uECC_word_t *scalar,
|
||||
uECC_Curve curve);
|
||||
|
||||
/* Generates a random integer in the range 0 < random < top.
|
||||
Both random and top have num_words words. */
|
||||
int uECC_generate_random_int(uECC_word_t *random,
|
||||
const uECC_word_t *top,
|
||||
wordcount_t num_words);
|
||||
|
||||
#endif /* uECC_ENABLE_VLI_API */
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* _UECC_VLI_H_ */
|
||||
70
SDK/12.3.0_d7731ad/external/micro-ecc/nrf51_armgcc/armgcc/Makefile
vendored
Normal file
70
SDK/12.3.0_d7731ad/external/micro-ecc/nrf51_armgcc/armgcc/Makefile
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
PROJECT_NAME := ext_micro_ecc_nrf51_library_armgcc
|
||||
TARGETS := micro_ecc_lib
|
||||
OUTPUT_DIRECTORY := _build
|
||||
|
||||
SDK_ROOT := ../../../..
|
||||
PROJ_DIR := ../..
|
||||
|
||||
|
||||
# Source files common to all targets
|
||||
SRC_FILES += \
|
||||
$(PROJ_DIR)/micro-ecc/uECC.c \
|
||||
|
||||
# Include folders common to all targets
|
||||
INC_FOLDERS += \
|
||||
|
||||
# Libraries common to all targets
|
||||
LIB_FILES += \
|
||||
|
||||
# C flags common to all targets
|
||||
CFLAGS += -DuECC_ENABLE_VLI_API
|
||||
CFLAGS += -DuECC_VLI_NATIVE_LITTLE_ENDIAN=1
|
||||
CFLAGS += -DuECC_SQUARE_FUNC=1
|
||||
CFLAGS += -DuECC_SUPPORTS_secp256r1=1
|
||||
CFLAGS += -DuECC_SUPPORT_COMPRESSED_POINT=0
|
||||
CFLAGS += -DuECC_OPTIMIZATION_LEVEL=3
|
||||
CFLAGS += -mcpu=cortex-m0
|
||||
CFLAGS += -mthumb -mabi=aapcs
|
||||
CFLAGS += -Wall -Werror -Os -g3
|
||||
CFLAGS += -mfloat-abi=soft
|
||||
# keep every function in separate section, this allows linker to discard unused ones
|
||||
CFLAGS += -ffunction-sections -fdata-sections -fno-strict-aliasing
|
||||
CFLAGS += -fno-builtin --short-enums
|
||||
|
||||
# C++ flags common to all targets
|
||||
CXXFLAGS += \
|
||||
|
||||
# Assembler flags common to all targets
|
||||
ASMFLAGS += -x assembler-with-cpp
|
||||
ASMFLAGS += -DuECC_ENABLE_VLI_API
|
||||
ASMFLAGS += -DuECC_VLI_NATIVE_LITTLE_ENDIAN=1
|
||||
ASMFLAGS += -DuECC_SQUARE_FUNC=1
|
||||
ASMFLAGS += -DuECC_SUPPORTS_secp256r1=1
|
||||
ASMFLAGS += -DuECC_SUPPORT_COMPRESSED_POINT=0
|
||||
ASMFLAGS += -DuECC_OPTIMIZATION_LEVEL=3
|
||||
|
||||
|
||||
|
||||
.PHONY: $(TARGETS) default all clean help flash
|
||||
|
||||
# Default target - first one defined
|
||||
default: micro_ecc_lib
|
||||
|
||||
# Print all targets that can be built
|
||||
help:
|
||||
@echo following targets are available:
|
||||
@echo micro_ecc_lib
|
||||
|
||||
TEMPLATE_PATH := $(SDK_ROOT)/components/toolchain/gcc
|
||||
|
||||
include $(TEMPLATE_PATH)/Makefile.common
|
||||
|
||||
$(call define_library, $(TARGETS), $(PROJ_DIR)/nrf51_armgcc/armgcc/micro_ecc_lib_nrf51.a)
|
||||
|
||||
define create_library
|
||||
@echo Creating library: $($@)
|
||||
$(NO_ECHO)$(AR) $($@) $^
|
||||
@echo Done
|
||||
endef
|
||||
micro_ecc_lib:
|
||||
$(create_library)
|
||||
28
SDK/12.3.0_d7731ad/external/micro-ecc/nrf51_armgcc/armgcc/ext_micro_ecc_gcc_nRF5x.ld
vendored
Normal file
28
SDK/12.3.0_d7731ad/external/micro-ecc/nrf51_armgcc/armgcc/ext_micro_ecc_gcc_nRF5x.ld
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
/* Linker script to configure memory regions. */
|
||||
|
||||
SEARCH_DIR(.)
|
||||
GROUP(-lgcc -lc -lnosys)
|
||||
|
||||
MEMORY
|
||||
{
|
||||
FLASH (rx) : ORIGIN = 0x0, LENGTH = 0x0
|
||||
RAM (rwx) : ORIGIN = 0x0, LENGTH = 0x0
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.fs_data :
|
||||
{
|
||||
PROVIDE(__start_fs_data = .);
|
||||
KEEP(*(.fs_data))
|
||||
PROVIDE(__stop_fs_data = .);
|
||||
} > RAM
|
||||
.pwr_mgmt_data :
|
||||
{
|
||||
PROVIDE(__start_pwr_mgmt_data = .);
|
||||
KEEP(*(.pwr_mgmt_data))
|
||||
PROVIDE(__stop_pwr_mgmt_data = .);
|
||||
} > RAM
|
||||
} INSERT AFTER .data;
|
||||
|
||||
INCLUDE "nrf5x_common.ld"
|
||||
BIN
SDK/12.3.0_d7731ad/external/micro-ecc/nrf51_armgcc/armgcc/micro_ecc_lib_nrf51.a
vendored
Normal file
BIN
SDK/12.3.0_d7731ad/external/micro-ecc/nrf51_armgcc/armgcc/micro_ecc_lib_nrf51.a
vendored
Normal file
Binary file not shown.
70
SDK/12.3.0_d7731ad/external/micro-ecc/nrf51_keil/armgcc/Makefile
vendored
Normal file
70
SDK/12.3.0_d7731ad/external/micro-ecc/nrf51_keil/armgcc/Makefile
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
PROJECT_NAME := ext_micro_ecc_nrf51_library_keil
|
||||
TARGETS := micro_ecc_lib
|
||||
OUTPUT_DIRECTORY := _build
|
||||
|
||||
SDK_ROOT := ../../../..
|
||||
PROJ_DIR := ../..
|
||||
|
||||
|
||||
# Source files common to all targets
|
||||
SRC_FILES += \
|
||||
$(PROJ_DIR)/micro-ecc/uECC.c \
|
||||
|
||||
# Include folders common to all targets
|
||||
INC_FOLDERS += \
|
||||
|
||||
# Libraries common to all targets
|
||||
LIB_FILES += \
|
||||
|
||||
# C flags common to all targets
|
||||
CFLAGS += -DuECC_ENABLE_VLI_API
|
||||
CFLAGS += -DuECC_VLI_NATIVE_LITTLE_ENDIAN=1
|
||||
CFLAGS += -DuECC_SQUARE_FUNC=1
|
||||
CFLAGS += -DuECC_SUPPORTS_secp256r1=1
|
||||
CFLAGS += -DuECC_SUPPORT_COMPRESSED_POINT=0
|
||||
CFLAGS += -DuECC_OPTIMIZATION_LEVEL=3
|
||||
CFLAGS += -mcpu=cortex-m0
|
||||
CFLAGS += -mthumb -mabi=aapcs
|
||||
CFLAGS += -Wall -Werror -Os -g3
|
||||
CFLAGS += -mfloat-abi=soft
|
||||
# keep every function in separate section, this allows linker to discard unused ones
|
||||
CFLAGS += -ffunction-sections -fdata-sections -fno-strict-aliasing
|
||||
CFLAGS += -fno-builtin --short-enums -fshort-wchar
|
||||
|
||||
# C++ flags common to all targets
|
||||
CXXFLAGS += \
|
||||
|
||||
# Assembler flags common to all targets
|
||||
ASMFLAGS += -x assembler-with-cpp
|
||||
ASMFLAGS += -DuECC_ENABLE_VLI_API
|
||||
ASMFLAGS += -DuECC_VLI_NATIVE_LITTLE_ENDIAN=1
|
||||
ASMFLAGS += -DuECC_SQUARE_FUNC=1
|
||||
ASMFLAGS += -DuECC_SUPPORTS_secp256r1=1
|
||||
ASMFLAGS += -DuECC_SUPPORT_COMPRESSED_POINT=0
|
||||
ASMFLAGS += -DuECC_OPTIMIZATION_LEVEL=3
|
||||
|
||||
|
||||
|
||||
.PHONY: $(TARGETS) default all clean help flash
|
||||
|
||||
# Default target - first one defined
|
||||
default: micro_ecc_lib
|
||||
|
||||
# Print all targets that can be built
|
||||
help:
|
||||
@echo following targets are available:
|
||||
@echo micro_ecc_lib
|
||||
|
||||
TEMPLATE_PATH := $(SDK_ROOT)/components/toolchain/gcc
|
||||
|
||||
include $(TEMPLATE_PATH)/Makefile.common
|
||||
|
||||
$(call define_library, $(TARGETS), $(PROJ_DIR)/nrf51_keil/armgcc/micro_ecc_lib_nrf51.lib)
|
||||
|
||||
define create_library
|
||||
@echo Creating library: $($@)
|
||||
$(NO_ECHO)$(AR) $($@) $^
|
||||
@echo Done
|
||||
endef
|
||||
micro_ecc_lib:
|
||||
$(create_library)
|
||||
28
SDK/12.3.0_d7731ad/external/micro-ecc/nrf51_keil/armgcc/ext_micro_ecc_gcc_nRF5x.ld
vendored
Normal file
28
SDK/12.3.0_d7731ad/external/micro-ecc/nrf51_keil/armgcc/ext_micro_ecc_gcc_nRF5x.ld
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
/* Linker script to configure memory regions. */
|
||||
|
||||
SEARCH_DIR(.)
|
||||
GROUP(-lgcc -lc -lnosys)
|
||||
|
||||
MEMORY
|
||||
{
|
||||
FLASH (rx) : ORIGIN = 0x0, LENGTH = 0x0
|
||||
RAM (rwx) : ORIGIN = 0x0, LENGTH = 0x0
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.fs_data :
|
||||
{
|
||||
PROVIDE(__start_fs_data = .);
|
||||
KEEP(*(.fs_data))
|
||||
PROVIDE(__stop_fs_data = .);
|
||||
} > RAM
|
||||
.pwr_mgmt_data :
|
||||
{
|
||||
PROVIDE(__start_pwr_mgmt_data = .);
|
||||
KEEP(*(.pwr_mgmt_data))
|
||||
PROVIDE(__stop_pwr_mgmt_data = .);
|
||||
} > RAM
|
||||
} INSERT AFTER .data;
|
||||
|
||||
INCLUDE "nrf5x_common.ld"
|
||||
BIN
SDK/12.3.0_d7731ad/external/micro-ecc/nrf51_keil/armgcc/micro_ecc_lib_nrf51.lib
vendored
Normal file
BIN
SDK/12.3.0_d7731ad/external/micro-ecc/nrf51_keil/armgcc/micro_ecc_lib_nrf51.lib
vendored
Normal file
Binary file not shown.
20
SDK/12.3.0_d7731ad/external/nano-pb/LICENSE.txt
vendored
Normal file
20
SDK/12.3.0_d7731ad/external/nano-pb/LICENSE.txt
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
Copyright (c) 2011 Petteri Aimonen <jpa at nanopb.mail.kapsi.fi>
|
||||
|
||||
This software is provided 'as-is', without any express or
|
||||
implied warranty. In no event will the authors be held liable
|
||||
for any damages arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any
|
||||
purpose, including commercial applications, and to alter it and
|
||||
redistribute it freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you
|
||||
must not claim that you wrote the original software. If you use
|
||||
this software in a product, an acknowledgment in the product
|
||||
documentation would be appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and
|
||||
must not be misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
556
SDK/12.3.0_d7731ad/external/nano-pb/pb.h
vendored
Normal file
556
SDK/12.3.0_d7731ad/external/nano-pb/pb.h
vendored
Normal file
@@ -0,0 +1,556 @@
|
||||
/* Common parts of the nanopb library. Most of these are quite low-level
|
||||
* stuff. For the high-level interface, see pb_encode.h and pb_decode.h.
|
||||
*/
|
||||
|
||||
#ifndef PB_H_INCLUDED
|
||||
#define PB_H_INCLUDED
|
||||
|
||||
/*****************************************************************
|
||||
* Nanopb compilation time options. You can change these here by *
|
||||
* uncommenting the lines, or on the compiler command line. *
|
||||
*****************************************************************/
|
||||
|
||||
/* Enable support for dynamically allocated fields */
|
||||
/* #define PB_ENABLE_MALLOC 1 */
|
||||
|
||||
/* Define this if your CPU / compiler combination does not support
|
||||
* unaligned memory access to packed structures. */
|
||||
#define PB_NO_PACKED_STRUCTS 1
|
||||
|
||||
/* Increase the number of required fields that are tracked.
|
||||
* A compiler warning will tell if you need this. */
|
||||
/* #define PB_MAX_REQUIRED_FIELDS 256 */
|
||||
|
||||
/* Add support for tag numbers > 255 and fields larger than 255 bytes. */
|
||||
/* #define PB_FIELD_16BIT 1 */
|
||||
|
||||
/* Add support for tag numbers > 65536 and fields larger than 65536 bytes. */
|
||||
/* #define PB_FIELD_32BIT 1 */
|
||||
|
||||
/* Disable support for error messages in order to save some code space. */
|
||||
#define PB_NO_ERRMSG 1
|
||||
|
||||
/* Disable support for custom streams (support only memory buffers). */
|
||||
/* #define PB_BUFFER_ONLY 1 */
|
||||
|
||||
/* Switch back to the old-style callback function signature.
|
||||
* This was the default until nanopb-0.2.1. */
|
||||
/* #define PB_OLD_CALLBACK_STYLE */
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* You usually don't need to change anything below this line. *
|
||||
* Feel free to look around and use the defined macros, though. *
|
||||
******************************************************************/
|
||||
|
||||
|
||||
/* Version of the nanopb library. Just in case you want to check it in
|
||||
* your own program. */
|
||||
#define NANOPB_VERSION nanopb-0.3.6-dev
|
||||
|
||||
/* Include all the system headers needed by nanopb. You will need the
|
||||
* definitions of the following:
|
||||
* - strlen, memcpy, memset functions
|
||||
* - [u]int_least8_t, uint_fast8_t, [u]int_least16_t, [u]int32_t, [u]int64_t
|
||||
* - size_t
|
||||
* - bool
|
||||
*
|
||||
* If you don't have the standard header files, you can instead provide
|
||||
* a custom header that defines or includes all this. In that case,
|
||||
* define PB_SYSTEM_HEADER to the path of this file.
|
||||
*/
|
||||
#ifdef PB_SYSTEM_HEADER
|
||||
#include PB_SYSTEM_HEADER
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef PB_ENABLE_MALLOC
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Macro for defining packed structures (compiler dependent).
|
||||
* This just reduces memory requirements, but is not required.
|
||||
*/
|
||||
#if defined(PB_NO_PACKED_STRUCTS)
|
||||
/* Disable struct packing */
|
||||
# define PB_PACKED_STRUCT_START
|
||||
# define PB_PACKED_STRUCT_END
|
||||
# define pb_packed
|
||||
#elif defined(__GNUC__) || defined(__clang__)
|
||||
/* For GCC and clang */
|
||||
# define PB_PACKED_STRUCT_START
|
||||
# define PB_PACKED_STRUCT_END
|
||||
# define pb_packed __attribute__((packed))
|
||||
#elif defined(__ICCARM__) || defined(__CC_ARM)
|
||||
/* For IAR ARM and Keil MDK-ARM compilers */
|
||||
# define PB_PACKED_STRUCT_START _Pragma("pack(push, 1)")
|
||||
# define PB_PACKED_STRUCT_END _Pragma("pack(pop)")
|
||||
# define pb_packed
|
||||
#elif defined(_MSC_VER) && (_MSC_VER >= 1500)
|
||||
/* For Microsoft Visual C++ */
|
||||
# define PB_PACKED_STRUCT_START __pragma(pack(push, 1))
|
||||
# define PB_PACKED_STRUCT_END __pragma(pack(pop))
|
||||
# define pb_packed
|
||||
#else
|
||||
/* Unknown compiler */
|
||||
# define PB_PACKED_STRUCT_START
|
||||
# define PB_PACKED_STRUCT_END
|
||||
# define pb_packed
|
||||
#endif
|
||||
|
||||
/* Handly macro for suppressing unreferenced-parameter compiler warnings. */
|
||||
#ifndef PB_UNUSED
|
||||
#define PB_UNUSED(x) (void)(x)
|
||||
#endif
|
||||
|
||||
/* Compile-time assertion, used for checking compatible compilation options.
|
||||
* If this does not work properly on your compiler, use
|
||||
* #define PB_NO_STATIC_ASSERT to disable it.
|
||||
*
|
||||
* But before doing that, check carefully the error message / place where it
|
||||
* comes from to see if the error has a real cause. Unfortunately the error
|
||||
* message is not always very clear to read, but you can see the reason better
|
||||
* in the place where the PB_STATIC_ASSERT macro was called.
|
||||
*/
|
||||
#ifndef PB_NO_STATIC_ASSERT
|
||||
#ifndef PB_STATIC_ASSERT
|
||||
#define PB_STATIC_ASSERT(COND,MSG) typedef char PB_STATIC_ASSERT_MSG(MSG, __LINE__, __COUNTER__)[(COND)?1:-1];
|
||||
#define PB_STATIC_ASSERT_MSG(MSG, LINE, COUNTER) PB_STATIC_ASSERT_MSG_(MSG, LINE, COUNTER)
|
||||
#define PB_STATIC_ASSERT_MSG_(MSG, LINE, COUNTER) pb_static_assertion_##MSG##LINE##COUNTER
|
||||
#endif
|
||||
#else
|
||||
#define PB_STATIC_ASSERT(COND,MSG)
|
||||
#endif
|
||||
|
||||
/* Number of required fields to keep track of. */
|
||||
#ifndef PB_MAX_REQUIRED_FIELDS
|
||||
#define PB_MAX_REQUIRED_FIELDS 64
|
||||
#endif
|
||||
|
||||
#if PB_MAX_REQUIRED_FIELDS < 64
|
||||
#error You should not lower PB_MAX_REQUIRED_FIELDS from the default value (64).
|
||||
#endif
|
||||
|
||||
/* List of possible field types. These are used in the autogenerated code.
|
||||
* Least-significant 4 bits tell the scalar type
|
||||
* Most-significant 4 bits specify repeated/required/packed etc.
|
||||
*/
|
||||
|
||||
typedef uint_least8_t pb_type_t;
|
||||
|
||||
/**** Field data types ****/
|
||||
|
||||
/* Numeric types */
|
||||
#define PB_LTYPE_VARINT 0x00 /* int32, int64, enum, bool */
|
||||
#define PB_LTYPE_UVARINT 0x01 /* uint32, uint64 */
|
||||
#define PB_LTYPE_SVARINT 0x02 /* sint32, sint64 */
|
||||
#define PB_LTYPE_FIXED32 0x03 /* fixed32, sfixed32, float */
|
||||
#define PB_LTYPE_FIXED64 0x04 /* fixed64, sfixed64, double */
|
||||
|
||||
/* Marker for last packable field type. */
|
||||
#define PB_LTYPE_LAST_PACKABLE 0x04
|
||||
|
||||
/* Byte array with pre-allocated buffer.
|
||||
* data_size is the length of the allocated PB_BYTES_ARRAY structure. */
|
||||
#define PB_LTYPE_BYTES 0x05
|
||||
|
||||
/* String with pre-allocated buffer.
|
||||
* data_size is the maximum length. */
|
||||
#define PB_LTYPE_STRING 0x06
|
||||
|
||||
/* Submessage
|
||||
* submsg_fields is pointer to field descriptions */
|
||||
#define PB_LTYPE_SUBMESSAGE 0x07
|
||||
|
||||
/* Extension pseudo-field
|
||||
* The field contains a pointer to pb_extension_t */
|
||||
#define PB_LTYPE_EXTENSION 0x08
|
||||
|
||||
/* Number of declared LTYPES */
|
||||
#define PB_LTYPES_COUNT 9
|
||||
#define PB_LTYPE_MASK 0x0F
|
||||
|
||||
/**** Field repetition rules ****/
|
||||
|
||||
#define PB_HTYPE_REQUIRED 0x00
|
||||
#define PB_HTYPE_OPTIONAL 0x10
|
||||
#define PB_HTYPE_REPEATED 0x20
|
||||
#define PB_HTYPE_ONEOF 0x30
|
||||
#define PB_HTYPE_MASK 0x30
|
||||
|
||||
/**** Field allocation types ****/
|
||||
|
||||
#define PB_ATYPE_STATIC 0x00
|
||||
#define PB_ATYPE_POINTER 0x80
|
||||
#define PB_ATYPE_CALLBACK 0x40
|
||||
#define PB_ATYPE_MASK 0xC0
|
||||
|
||||
#define PB_ATYPE(x) ((x) & PB_ATYPE_MASK)
|
||||
#define PB_HTYPE(x) ((x) & PB_HTYPE_MASK)
|
||||
#define PB_LTYPE(x) ((x) & PB_LTYPE_MASK)
|
||||
|
||||
/* Data type used for storing sizes of struct fields
|
||||
* and array counts.
|
||||
*/
|
||||
#if defined(PB_FIELD_32BIT)
|
||||
typedef uint32_t pb_size_t;
|
||||
typedef int32_t pb_ssize_t;
|
||||
#elif defined(PB_FIELD_16BIT)
|
||||
typedef uint_least16_t pb_size_t;
|
||||
typedef int_least16_t pb_ssize_t;
|
||||
#else
|
||||
typedef uint_least8_t pb_size_t;
|
||||
typedef int_least8_t pb_ssize_t;
|
||||
#endif
|
||||
#define PB_SIZE_MAX ((pb_size_t)-1)
|
||||
|
||||
/* Data type for storing encoded data and other byte streams.
|
||||
* This typedef exists to support platforms where uint8_t does not exist.
|
||||
* You can regard it as equivalent on uint8_t on other platforms.
|
||||
*/
|
||||
typedef uint_least8_t pb_byte_t;
|
||||
|
||||
/* This structure is used in auto-generated constants
|
||||
* to specify struct fields.
|
||||
* You can change field sizes if you need structures
|
||||
* larger than 256 bytes or field tags larger than 256.
|
||||
* The compiler should complain if your .proto has such
|
||||
* structures. Fix that by defining PB_FIELD_16BIT or
|
||||
* PB_FIELD_32BIT.
|
||||
*/
|
||||
PB_PACKED_STRUCT_START
|
||||
typedef struct pb_field_s pb_field_t;
|
||||
struct pb_field_s {
|
||||
pb_size_t tag;
|
||||
pb_type_t type;
|
||||
pb_size_t data_offset; /* Offset of field data, relative to previous field. */
|
||||
pb_ssize_t size_offset; /* Offset of array size or has-boolean, relative to data */
|
||||
pb_size_t data_size; /* Data size in bytes for a single item */
|
||||
pb_size_t array_size; /* Maximum number of entries in array */
|
||||
|
||||
/* Field definitions for submessage
|
||||
* OR default value for all other non-array, non-callback types
|
||||
* If null, then field will zeroed. */
|
||||
const void *ptr;
|
||||
} pb_packed;
|
||||
PB_PACKED_STRUCT_END
|
||||
|
||||
/* Make sure that the standard integer types are of the expected sizes.
|
||||
* Otherwise fixed32/fixed64 fields can break.
|
||||
*
|
||||
* If you get errors here, it probably means that your stdint.h is not
|
||||
* correct for your platform.
|
||||
*/
|
||||
PB_STATIC_ASSERT(sizeof(int64_t) == 2 * sizeof(int32_t), INT64_T_WRONG_SIZE)
|
||||
PB_STATIC_ASSERT(sizeof(uint64_t) == 2 * sizeof(uint32_t), UINT64_T_WRONG_SIZE)
|
||||
|
||||
/* This structure is used for 'bytes' arrays.
|
||||
* It has the number of bytes in the beginning, and after that an array.
|
||||
* Note that actual structs used will have a different length of bytes array.
|
||||
*/
|
||||
#define PB_BYTES_ARRAY_T(n) struct { pb_size_t size; pb_byte_t bytes[n]; }
|
||||
#define PB_BYTES_ARRAY_T_ALLOCSIZE(n) ((size_t)n + offsetof(pb_bytes_array_t, bytes))
|
||||
|
||||
struct pb_bytes_array_s {
|
||||
pb_size_t size;
|
||||
pb_byte_t bytes[1];
|
||||
};
|
||||
typedef struct pb_bytes_array_s pb_bytes_array_t;
|
||||
|
||||
/* This structure is used for giving the callback function.
|
||||
* It is stored in the message structure and filled in by the method that
|
||||
* calls pb_decode.
|
||||
*
|
||||
* The decoding callback will be given a limited-length stream
|
||||
* If the wire type was string, the length is the length of the string.
|
||||
* If the wire type was a varint/fixed32/fixed64, the length is the length
|
||||
* of the actual value.
|
||||
* The function may be called multiple times (especially for repeated types,
|
||||
* but also otherwise if the message happens to contain the field multiple
|
||||
* times.)
|
||||
*
|
||||
* The encoding callback will receive the actual output stream.
|
||||
* It should write all the data in one call, including the field tag and
|
||||
* wire type. It can write multiple fields.
|
||||
*
|
||||
* The callback can be null if you want to skip a field.
|
||||
*/
|
||||
typedef struct pb_istream_s pb_istream_t;
|
||||
typedef struct pb_ostream_s pb_ostream_t;
|
||||
typedef struct pb_callback_s pb_callback_t;
|
||||
struct pb_callback_s {
|
||||
#ifdef PB_OLD_CALLBACK_STYLE
|
||||
/* Deprecated since nanopb-0.2.1 */
|
||||
union {
|
||||
bool (*decode)(pb_istream_t *stream, const pb_field_t *field, void *arg);
|
||||
bool (*encode)(pb_ostream_t *stream, const pb_field_t *field, const void *arg);
|
||||
} funcs;
|
||||
#else
|
||||
/* New function signature, which allows modifying arg contents in callback. */
|
||||
union {
|
||||
bool (*decode)(pb_istream_t *stream, const pb_field_t *field, void **arg);
|
||||
bool (*encode)(pb_ostream_t *stream, const pb_field_t *field, void * const *arg);
|
||||
} funcs;
|
||||
#endif
|
||||
|
||||
/* Free arg for use by callback */
|
||||
void *arg;
|
||||
};
|
||||
|
||||
/* Wire types. Library user needs these only in encoder callbacks. */
|
||||
typedef enum {
|
||||
PB_WT_VARINT = 0,
|
||||
PB_WT_64BIT = 1,
|
||||
PB_WT_STRING = 2,
|
||||
PB_WT_32BIT = 5
|
||||
} pb_wire_type_t;
|
||||
|
||||
/* Structure for defining the handling of unknown/extension fields.
|
||||
* Usually the pb_extension_type_t structure is automatically generated,
|
||||
* while the pb_extension_t structure is created by the user. However,
|
||||
* if you want to catch all unknown fields, you can also create a custom
|
||||
* pb_extension_type_t with your own callback.
|
||||
*/
|
||||
typedef struct pb_extension_type_s pb_extension_type_t;
|
||||
typedef struct pb_extension_s pb_extension_t;
|
||||
struct pb_extension_type_s {
|
||||
/* Called for each unknown field in the message.
|
||||
* If you handle the field, read off all of its data and return true.
|
||||
* If you do not handle the field, do not read anything and return true.
|
||||
* If you run into an error, return false.
|
||||
* Set to NULL for default handler.
|
||||
*/
|
||||
bool (*decode)(pb_istream_t *stream, pb_extension_t *extension,
|
||||
uint32_t tag, pb_wire_type_t wire_type);
|
||||
|
||||
/* Called once after all regular fields have been encoded.
|
||||
* If you have something to write, do so and return true.
|
||||
* If you do not have anything to write, just return true.
|
||||
* If you run into an error, return false.
|
||||
* Set to NULL for default handler.
|
||||
*/
|
||||
bool (*encode)(pb_ostream_t *stream, const pb_extension_t *extension);
|
||||
|
||||
/* Free field for use by the callback. */
|
||||
const void *arg;
|
||||
};
|
||||
|
||||
struct pb_extension_s {
|
||||
/* Type describing the extension field. Usually you'll initialize
|
||||
* this to a pointer to the automatically generated structure. */
|
||||
const pb_extension_type_t *type;
|
||||
|
||||
/* Destination for the decoded data. This must match the datatype
|
||||
* of the extension field. */
|
||||
void *dest;
|
||||
|
||||
/* Pointer to the next extension handler, or NULL.
|
||||
* If this extension does not match a field, the next handler is
|
||||
* automatically called. */
|
||||
pb_extension_t *next;
|
||||
|
||||
/* The decoder sets this to true if the extension was found.
|
||||
* Ignored for encoding. */
|
||||
bool found;
|
||||
};
|
||||
|
||||
/* Memory allocation functions to use. You can define pb_realloc and
|
||||
* pb_free to custom functions if you want. */
|
||||
#ifdef PB_ENABLE_MALLOC
|
||||
# ifndef pb_realloc
|
||||
# define pb_realloc(ptr, size) realloc(ptr, size)
|
||||
# endif
|
||||
# ifndef pb_free
|
||||
# define pb_free(ptr) free(ptr)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* This is used to inform about need to regenerate .pb.h/.pb.c files. */
|
||||
#define PB_PROTO_HEADER_VERSION 30
|
||||
|
||||
/* These macros are used to declare pb_field_t's in the constant array. */
|
||||
/* Size of a structure member, in bytes. */
|
||||
#define pb_membersize(st, m) (sizeof ((st*)0)->m)
|
||||
/* Number of entries in an array. */
|
||||
#define pb_arraysize(st, m) (pb_membersize(st, m) / pb_membersize(st, m[0]))
|
||||
/* Delta from start of one member to the start of another member. */
|
||||
#define pb_delta(st, m1, m2) ((int)offsetof(st, m1) - (int)offsetof(st, m2))
|
||||
/* Marks the end of the field list */
|
||||
#define PB_LAST_FIELD {0,(pb_type_t) 0,0,0,0,0,0}
|
||||
|
||||
/* Macros for filling in the data_offset field */
|
||||
/* data_offset for first field in a message */
|
||||
#define PB_DATAOFFSET_FIRST(st, m1, m2) (offsetof(st, m1))
|
||||
/* data_offset for subsequent fields */
|
||||
#define PB_DATAOFFSET_OTHER(st, m1, m2) (offsetof(st, m1) - offsetof(st, m2) - pb_membersize(st, m2))
|
||||
/* Choose first/other based on m1 == m2 (deprecated, remains for backwards compatibility) */
|
||||
#define PB_DATAOFFSET_CHOOSE(st, m1, m2) (int)(offsetof(st, m1) == offsetof(st, m2) \
|
||||
? PB_DATAOFFSET_FIRST(st, m1, m2) \
|
||||
: PB_DATAOFFSET_OTHER(st, m1, m2))
|
||||
|
||||
/* Required fields are the simplest. They just have delta (padding) from
|
||||
* previous field end, and the size of the field. Pointer is used for
|
||||
* submessages and default values.
|
||||
*/
|
||||
#define PB_REQUIRED_STATIC(tag, st, m, fd, ltype, ptr) \
|
||||
{tag, PB_ATYPE_STATIC | PB_HTYPE_REQUIRED | ltype, \
|
||||
fd, 0, pb_membersize(st, m), 0, ptr}
|
||||
|
||||
/* Optional fields add the delta to the has_ variable. */
|
||||
#define PB_OPTIONAL_STATIC(tag, st, m, fd, ltype, ptr) \
|
||||
{tag, PB_ATYPE_STATIC | PB_HTYPE_OPTIONAL | ltype, \
|
||||
fd, \
|
||||
pb_delta(st, has_ ## m, m), \
|
||||
pb_membersize(st, m), 0, ptr}
|
||||
|
||||
/* Repeated fields have a _count field and also the maximum number of entries. */
|
||||
#define PB_REPEATED_STATIC(tag, st, m, fd, ltype, ptr) \
|
||||
{tag, PB_ATYPE_STATIC | PB_HTYPE_REPEATED | ltype, \
|
||||
fd, \
|
||||
pb_delta(st, m ## _count, m), \
|
||||
pb_membersize(st, m[0]), \
|
||||
pb_arraysize(st, m), ptr}
|
||||
|
||||
/* Allocated fields carry the size of the actual data, not the pointer */
|
||||
#define PB_REQUIRED_POINTER(tag, st, m, fd, ltype, ptr) \
|
||||
{tag, PB_ATYPE_POINTER | PB_HTYPE_REQUIRED | ltype, \
|
||||
fd, 0, pb_membersize(st, m[0]), 0, ptr}
|
||||
|
||||
/* Optional fields don't need a has_ variable, as information would be redundant */
|
||||
#define PB_OPTIONAL_POINTER(tag, st, m, fd, ltype, ptr) \
|
||||
{tag, PB_ATYPE_POINTER | PB_HTYPE_OPTIONAL | ltype, \
|
||||
fd, 0, pb_membersize(st, m[0]), 0, ptr}
|
||||
|
||||
/* Repeated fields have a _count field and a pointer to array of pointers */
|
||||
#define PB_REPEATED_POINTER(tag, st, m, fd, ltype, ptr) \
|
||||
{tag, PB_ATYPE_POINTER | PB_HTYPE_REPEATED | ltype, \
|
||||
fd, pb_delta(st, m ## _count, m), \
|
||||
pb_membersize(st, m[0]), 0, ptr}
|
||||
|
||||
/* Callbacks are much like required fields except with special datatype. */
|
||||
#define PB_REQUIRED_CALLBACK(tag, st, m, fd, ltype, ptr) \
|
||||
{tag, PB_ATYPE_CALLBACK | PB_HTYPE_REQUIRED | ltype, \
|
||||
fd, 0, pb_membersize(st, m), 0, ptr}
|
||||
|
||||
#define PB_OPTIONAL_CALLBACK(tag, st, m, fd, ltype, ptr) \
|
||||
{tag, PB_ATYPE_CALLBACK | PB_HTYPE_OPTIONAL | ltype, \
|
||||
fd, 0, pb_membersize(st, m), 0, ptr}
|
||||
|
||||
#define PB_REPEATED_CALLBACK(tag, st, m, fd, ltype, ptr) \
|
||||
{tag, PB_ATYPE_CALLBACK | PB_HTYPE_REPEATED | ltype, \
|
||||
fd, 0, pb_membersize(st, m), 0, ptr}
|
||||
|
||||
/* Optional extensions don't have the has_ field, as that would be redundant. */
|
||||
#define PB_OPTEXT_STATIC(tag, st, m, fd, ltype, ptr) \
|
||||
{tag, PB_ATYPE_STATIC | PB_HTYPE_OPTIONAL | ltype, \
|
||||
0, \
|
||||
0, \
|
||||
pb_membersize(st, m), 0, ptr}
|
||||
|
||||
#define PB_OPTEXT_POINTER(tag, st, m, fd, ltype, ptr) \
|
||||
PB_OPTIONAL_POINTER(tag, st, m, fd, ltype, ptr)
|
||||
|
||||
#define PB_OPTEXT_CALLBACK(tag, st, m, fd, ltype, ptr) \
|
||||
PB_OPTIONAL_CALLBACK(tag, st, m, fd, ltype, ptr)
|
||||
|
||||
/* The mapping from protobuf types to LTYPEs is done using these macros. */
|
||||
#define PB_LTYPE_MAP_BOOL PB_LTYPE_VARINT
|
||||
#define PB_LTYPE_MAP_BYTES PB_LTYPE_BYTES
|
||||
#define PB_LTYPE_MAP_DOUBLE PB_LTYPE_FIXED64
|
||||
#define PB_LTYPE_MAP_ENUM PB_LTYPE_VARINT
|
||||
#define PB_LTYPE_MAP_UENUM PB_LTYPE_UVARINT
|
||||
#define PB_LTYPE_MAP_FIXED32 PB_LTYPE_FIXED32
|
||||
#define PB_LTYPE_MAP_FIXED64 PB_LTYPE_FIXED64
|
||||
#define PB_LTYPE_MAP_FLOAT PB_LTYPE_FIXED32
|
||||
#define PB_LTYPE_MAP_INT32 PB_LTYPE_VARINT
|
||||
#define PB_LTYPE_MAP_INT64 PB_LTYPE_VARINT
|
||||
#define PB_LTYPE_MAP_MESSAGE PB_LTYPE_SUBMESSAGE
|
||||
#define PB_LTYPE_MAP_SFIXED32 PB_LTYPE_FIXED32
|
||||
#define PB_LTYPE_MAP_SFIXED64 PB_LTYPE_FIXED64
|
||||
#define PB_LTYPE_MAP_SINT32 PB_LTYPE_SVARINT
|
||||
#define PB_LTYPE_MAP_SINT64 PB_LTYPE_SVARINT
|
||||
#define PB_LTYPE_MAP_STRING PB_LTYPE_STRING
|
||||
#define PB_LTYPE_MAP_UINT32 PB_LTYPE_UVARINT
|
||||
#define PB_LTYPE_MAP_UINT64 PB_LTYPE_UVARINT
|
||||
#define PB_LTYPE_MAP_EXTENSION PB_LTYPE_EXTENSION
|
||||
|
||||
/* This is the actual macro used in field descriptions.
|
||||
* It takes these arguments:
|
||||
* - Field tag number
|
||||
* - Field type: BOOL, BYTES, DOUBLE, ENUM, UENUM, FIXED32, FIXED64,
|
||||
* FLOAT, INT32, INT64, MESSAGE, SFIXED32, SFIXED64
|
||||
* SINT32, SINT64, STRING, UINT32, UINT64 or EXTENSION
|
||||
* - Field rules: REQUIRED, OPTIONAL or REPEATED
|
||||
* - Allocation: STATIC or CALLBACK
|
||||
* - Placement: FIRST or OTHER, depending on if this is the first field in structure.
|
||||
* - Message name
|
||||
* - Field name
|
||||
* - Previous field name (or field name again for first field)
|
||||
* - Pointer to default value or submsg fields.
|
||||
*/
|
||||
|
||||
#define PB_FIELD(tag, type, rules, allocation, placement, message, field, prevfield, ptr) \
|
||||
PB_ ## rules ## _ ## allocation(tag, message, field, \
|
||||
PB_DATAOFFSET_ ## placement(message, field, prevfield), \
|
||||
PB_LTYPE_MAP_ ## type, ptr)
|
||||
|
||||
/* Field description for oneof fields. This requires taking into account the
|
||||
* union name also, that's why a separate set of macros is needed.
|
||||
*/
|
||||
#define PB_ONEOF_STATIC(u, tag, st, m, fd, ltype, ptr) \
|
||||
{tag, PB_ATYPE_STATIC | PB_HTYPE_ONEOF | ltype, \
|
||||
fd, pb_delta(st, which_ ## u, u.m), \
|
||||
pb_membersize(st, u.m), 0, ptr}
|
||||
|
||||
#define PB_ONEOF_POINTER(u, tag, st, m, fd, ltype, ptr) \
|
||||
{tag, PB_ATYPE_POINTER | PB_HTYPE_ONEOF | ltype, \
|
||||
fd, pb_delta(st, which_ ## u, u.m), \
|
||||
pb_membersize(st, u.m[0]), 0, ptr}
|
||||
|
||||
#define PB_ONEOF_FIELD(union_name, tag, type, rules, allocation, placement, message, field, prevfield, ptr) \
|
||||
PB_ONEOF_ ## allocation(union_name, tag, message, field, \
|
||||
PB_DATAOFFSET_ ## placement(message, union_name.field, prevfield), \
|
||||
PB_LTYPE_MAP_ ## type, ptr)
|
||||
|
||||
#define PB_ANONYMOUS_ONEOF_STATIC(u, tag, st, m, fd, ltype, ptr) \
|
||||
{tag, PB_ATYPE_STATIC | PB_HTYPE_ONEOF | ltype, \
|
||||
fd, pb_delta(st, which_ ## u, m), \
|
||||
pb_membersize(st, m), 0, ptr}
|
||||
|
||||
#define PB_ANONYMOUS_ONEOF_POINTER(u, tag, st, m, fd, ltype, ptr) \
|
||||
{tag, PB_ATYPE_POINTER | PB_HTYPE_ONEOF | ltype, \
|
||||
fd, pb_delta(st, which_ ## u, m), \
|
||||
pb_membersize(st, m[0]), 0, ptr}
|
||||
|
||||
#define PB_ANONYMOUS_ONEOF_FIELD(union_name, tag, type, rules, allocation, placement, message, field, prevfield, ptr) \
|
||||
PB_ANONYMOUS_ONEOF_ ## allocation(union_name, tag, message, field, \
|
||||
PB_DATAOFFSET_ ## placement(message, field, prevfield), \
|
||||
PB_LTYPE_MAP_ ## type, ptr)
|
||||
|
||||
/* These macros are used for giving out error messages.
|
||||
* They are mostly a debugging aid; the main error information
|
||||
* is the true/false return value from functions.
|
||||
* Some code space can be saved by disabling the error
|
||||
* messages if not used.
|
||||
*
|
||||
* PB_SET_ERROR() sets the error message if none has been set yet.
|
||||
* msg must be a constant string literal.
|
||||
* PB_GET_ERROR() always returns a pointer to a string.
|
||||
* PB_RETURN_ERROR() sets the error and returns false from current
|
||||
* function.
|
||||
*/
|
||||
#ifdef PB_NO_ERRMSG
|
||||
#define PB_SET_ERROR(stream, msg) PB_UNUSED(stream)
|
||||
#define PB_GET_ERROR(stream) "(errmsg disabled)"
|
||||
#else
|
||||
#define PB_SET_ERROR(stream, msg) (stream->errmsg = (stream)->errmsg ? (stream)->errmsg : (msg))
|
||||
#define PB_GET_ERROR(stream) ((stream)->errmsg ? (stream)->errmsg : "(none)")
|
||||
#endif
|
||||
|
||||
#define PB_RETURN_ERROR(stream, msg) return PB_SET_ERROR(stream, msg), false
|
||||
|
||||
#endif
|
||||
97
SDK/12.3.0_d7731ad/external/nano-pb/pb_common.c
vendored
Normal file
97
SDK/12.3.0_d7731ad/external/nano-pb/pb_common.c
vendored
Normal file
@@ -0,0 +1,97 @@
|
||||
/* pb_common.c: Common support functions for pb_encode.c and pb_decode.c.
|
||||
*
|
||||
* 2014 Petteri Aimonen <jpa@kapsi.fi>
|
||||
*/
|
||||
|
||||
#include "pb_common.h"
|
||||
|
||||
bool pb_field_iter_begin(pb_field_iter_t *iter, const pb_field_t *fields, void *dest_struct)
|
||||
{
|
||||
iter->start = fields;
|
||||
iter->pos = fields;
|
||||
iter->required_field_index = 0;
|
||||
iter->dest_struct = dest_struct;
|
||||
iter->pData = (char*)dest_struct + iter->pos->data_offset;
|
||||
iter->pSize = (char*)iter->pData + iter->pos->size_offset;
|
||||
|
||||
return (iter->pos->tag != 0);
|
||||
}
|
||||
|
||||
bool pb_field_iter_next(pb_field_iter_t *iter)
|
||||
{
|
||||
const pb_field_t *prev_field = iter->pos;
|
||||
|
||||
if (prev_field->tag == 0)
|
||||
{
|
||||
/* Handle empty message types, where the first field is already the terminator.
|
||||
* In other cases, the iter->pos never points to the terminator. */
|
||||
return false;
|
||||
}
|
||||
|
||||
iter->pos++;
|
||||
|
||||
if (iter->pos->tag == 0)
|
||||
{
|
||||
/* Wrapped back to beginning, reinitialize */
|
||||
(void)pb_field_iter_begin(iter, iter->start, iter->dest_struct);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Increment the pointers based on previous field size */
|
||||
size_t prev_size = prev_field->data_size;
|
||||
|
||||
if (PB_HTYPE(prev_field->type) == PB_HTYPE_ONEOF &&
|
||||
PB_HTYPE(iter->pos->type) == PB_HTYPE_ONEOF)
|
||||
{
|
||||
/* Don't advance pointers inside unions */
|
||||
prev_size = 0;
|
||||
iter->pData = (char*)iter->pData - prev_field->data_offset;
|
||||
}
|
||||
else if (PB_ATYPE(prev_field->type) == PB_ATYPE_STATIC &&
|
||||
PB_HTYPE(prev_field->type) == PB_HTYPE_REPEATED)
|
||||
{
|
||||
/* In static arrays, the data_size tells the size of a single entry and
|
||||
* array_size is the number of entries */
|
||||
prev_size *= prev_field->array_size;
|
||||
}
|
||||
else if (PB_ATYPE(prev_field->type) == PB_ATYPE_POINTER)
|
||||
{
|
||||
/* Pointer fields always have a constant size in the main structure.
|
||||
* The data_size only applies to the dynamically allocated area. */
|
||||
prev_size = sizeof(void*);
|
||||
}
|
||||
|
||||
if (PB_HTYPE(prev_field->type) == PB_HTYPE_REQUIRED)
|
||||
{
|
||||
/* Count the required fields, in order to check their presence in the
|
||||
* decoder. */
|
||||
iter->required_field_index++;
|
||||
}
|
||||
|
||||
iter->pData = (char*)iter->pData + prev_size + iter->pos->data_offset;
|
||||
iter->pSize = (char*)iter->pData + iter->pos->size_offset;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool pb_field_iter_find(pb_field_iter_t *iter, uint32_t tag)
|
||||
{
|
||||
const pb_field_t *start = iter->pos;
|
||||
|
||||
do {
|
||||
if (iter->pos->tag == tag &&
|
||||
PB_LTYPE(iter->pos->type) != PB_LTYPE_EXTENSION)
|
||||
{
|
||||
/* Found the wanted field */
|
||||
return true;
|
||||
}
|
||||
|
||||
(void)pb_field_iter_next(iter);
|
||||
} while (iter->pos != start);
|
||||
|
||||
/* Searched all the way back to start, and found nothing. */
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
42
SDK/12.3.0_d7731ad/external/nano-pb/pb_common.h
vendored
Normal file
42
SDK/12.3.0_d7731ad/external/nano-pb/pb_common.h
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
/* pb_common.h: Common support functions for pb_encode.c and pb_decode.c.
|
||||
* These functions are rarely needed by applications directly.
|
||||
*/
|
||||
|
||||
#ifndef PB_COMMON_H_INCLUDED
|
||||
#define PB_COMMON_H_INCLUDED
|
||||
|
||||
#include "pb.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Iterator for pb_field_t list */
|
||||
struct pb_field_iter_s {
|
||||
const pb_field_t *start; /* Start of the pb_field_t array */
|
||||
const pb_field_t *pos; /* Current position of the iterator */
|
||||
unsigned required_field_index; /* Zero-based index that counts only the required fields */
|
||||
void *dest_struct; /* Pointer to start of the structure */
|
||||
void *pData; /* Pointer to current field value */
|
||||
void *pSize; /* Pointer to count/has field */
|
||||
};
|
||||
typedef struct pb_field_iter_s pb_field_iter_t;
|
||||
|
||||
/* Initialize the field iterator structure to beginning.
|
||||
* Returns false if the message type is empty. */
|
||||
bool pb_field_iter_begin(pb_field_iter_t *iter, const pb_field_t *fields, void *dest_struct);
|
||||
|
||||
/* Advance the iterator to the next field.
|
||||
* Returns false when the iterator wraps back to the first field. */
|
||||
bool pb_field_iter_next(pb_field_iter_t *iter);
|
||||
|
||||
/* Advance the iterator until it points at a field with the given tag.
|
||||
* Returns false if no such field exists. */
|
||||
bool pb_field_iter_find(pb_field_iter_t *iter, uint32_t tag);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
1340
SDK/12.3.0_d7731ad/external/nano-pb/pb_decode.c
vendored
Normal file
1340
SDK/12.3.0_d7731ad/external/nano-pb/pb_decode.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
152
SDK/12.3.0_d7731ad/external/nano-pb/pb_decode.h
vendored
Normal file
152
SDK/12.3.0_d7731ad/external/nano-pb/pb_decode.h
vendored
Normal file
@@ -0,0 +1,152 @@
|
||||
/* pb_decode.h: Functions to decode protocol buffers. Depends on pb_decode.c.
|
||||
* The main function is pb_decode. You also need an input stream, and the
|
||||
* field descriptions created by nanopb_generator.py.
|
||||
*/
|
||||
|
||||
#ifndef PB_DECODE_H_INCLUDED
|
||||
#define PB_DECODE_H_INCLUDED
|
||||
|
||||
#include "pb.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Structure for defining custom input streams. You will need to provide
|
||||
* a callback function to read the bytes from your storage, which can be
|
||||
* for example a file or a network socket.
|
||||
*
|
||||
* The callback must conform to these rules:
|
||||
*
|
||||
* 1) Return false on IO errors. This will cause decoding to abort.
|
||||
* 2) You can use state to store your own data (e.g. buffer pointer),
|
||||
* and rely on pb_read to verify that no-body reads past bytes_left.
|
||||
* 3) Your callback may be used with substreams, in which case bytes_left
|
||||
* is different than from the main stream. Don't use bytes_left to compute
|
||||
* any pointers.
|
||||
*/
|
||||
struct pb_istream_s
|
||||
{
|
||||
#ifdef PB_BUFFER_ONLY
|
||||
/* Callback pointer is not used in buffer-only configuration.
|
||||
* Having an int pointer here allows binary compatibility but
|
||||
* gives an error if someone tries to assign callback function.
|
||||
*/
|
||||
int *callback;
|
||||
#else
|
||||
bool (*callback)(pb_istream_t *stream, pb_byte_t *buf, size_t count);
|
||||
#endif
|
||||
|
||||
void *state; /* Free field for use by callback implementation */
|
||||
size_t bytes_left;
|
||||
|
||||
/* Informative callback for field decoding */
|
||||
void (* decoding_callback)(pb_istream_t *strem, uint32_t tag, pb_wire_type_t wire_type, void *iter);
|
||||
|
||||
#ifndef PB_NO_ERRMSG
|
||||
const char *errmsg;
|
||||
#endif
|
||||
};
|
||||
|
||||
/***************************
|
||||
* Main decoding functions *
|
||||
***************************/
|
||||
|
||||
/* Decode a single protocol buffers message from input stream into a C structure.
|
||||
* Returns true on success, false on any failure.
|
||||
* The actual struct pointed to by dest must match the description in fields.
|
||||
* Callback fields of the destination structure must be initialized by caller.
|
||||
* All other fields will be initialized by this function.
|
||||
*
|
||||
* Example usage:
|
||||
* MyMessage msg = {};
|
||||
* uint8_t buffer[64];
|
||||
* pb_istream_t stream;
|
||||
*
|
||||
* // ... read some data into buffer ...
|
||||
*
|
||||
* stream = pb_istream_from_buffer(buffer, count);
|
||||
* pb_decode(&stream, MyMessage_fields, &msg);
|
||||
*/
|
||||
bool pb_decode(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct);
|
||||
|
||||
/* Same as pb_decode, except does not initialize the destination structure
|
||||
* to default values. This is slightly faster if you need no default values
|
||||
* and just do memset(struct, 0, sizeof(struct)) yourself.
|
||||
*
|
||||
* This can also be used for 'merging' two messages, i.e. update only the
|
||||
* fields that exist in the new message.
|
||||
*
|
||||
* Note: If this function returns with an error, it will not release any
|
||||
* dynamically allocated fields. You will need to call pb_release() yourself.
|
||||
*/
|
||||
bool pb_decode_noinit(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct);
|
||||
|
||||
/* Same as pb_decode, except expects the stream to start with the message size
|
||||
* encoded as varint. Corresponds to parseDelimitedFrom() in Google's
|
||||
* protobuf API.
|
||||
*/
|
||||
bool pb_decode_delimited(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct);
|
||||
|
||||
#ifdef PB_ENABLE_MALLOC
|
||||
/* Release any allocated pointer fields. If you use dynamic allocation, you should
|
||||
* call this for any successfully decoded message when you are done with it. If
|
||||
* pb_decode() returns with an error, the message is already released.
|
||||
*/
|
||||
void pb_release(const pb_field_t fields[], void *dest_struct);
|
||||
#endif
|
||||
|
||||
|
||||
/**************************************
|
||||
* Functions for manipulating streams *
|
||||
**************************************/
|
||||
|
||||
/* Create an input stream for reading from a memory buffer.
|
||||
*
|
||||
* Alternatively, you can use a custom stream that reads directly from e.g.
|
||||
* a file or a network socket.
|
||||
*/
|
||||
pb_istream_t pb_istream_from_buffer(const pb_byte_t *buf, size_t bufsize);
|
||||
|
||||
/* Function to read from a pb_istream_t. You can use this if you need to
|
||||
* read some custom header data, or to read data in field callbacks.
|
||||
*/
|
||||
bool pb_read(pb_istream_t *stream, pb_byte_t *buf, size_t count);
|
||||
|
||||
|
||||
/************************************************
|
||||
* Helper functions for writing field callbacks *
|
||||
************************************************/
|
||||
|
||||
/* Decode the tag for the next field in the stream. Gives the wire type and
|
||||
* field tag. At end of the message, returns false and sets eof to true. */
|
||||
bool pb_decode_tag(pb_istream_t *stream, pb_wire_type_t *wire_type, uint32_t *tag, bool *eof);
|
||||
|
||||
/* Skip the field payload data, given the wire type. */
|
||||
bool pb_skip_field(pb_istream_t *stream, pb_wire_type_t wire_type);
|
||||
|
||||
/* Decode an integer in the varint format. This works for bool, enum, int32,
|
||||
* int64, uint32 and uint64 field types. */
|
||||
bool pb_decode_varint(pb_istream_t *stream, uint64_t *dest);
|
||||
|
||||
/* Decode an integer in the zig-zagged svarint format. This works for sint32
|
||||
* and sint64. */
|
||||
bool pb_decode_svarint(pb_istream_t *stream, int64_t *dest);
|
||||
|
||||
/* Decode a fixed32, sfixed32 or float value. You need to pass a pointer to
|
||||
* a 4-byte wide C variable. */
|
||||
bool pb_decode_fixed32(pb_istream_t *stream, void *dest);
|
||||
|
||||
/* Decode a fixed64, sfixed64 or double value. You need to pass a pointer to
|
||||
* a 8-byte wide C variable. */
|
||||
bool pb_decode_fixed64(pb_istream_t *stream, void *dest);
|
||||
|
||||
/* Make a limited-length substream for reading a PB_WT_STRING field. */
|
||||
bool pb_make_string_substream(pb_istream_t *stream, pb_istream_t *substream);
|
||||
void pb_close_string_substream(pb_istream_t *stream, pb_istream_t *substream);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif
|
||||
689
SDK/12.3.0_d7731ad/external/nano-pb/pb_encode.c
vendored
Normal file
689
SDK/12.3.0_d7731ad/external/nano-pb/pb_encode.c
vendored
Normal file
@@ -0,0 +1,689 @@
|
||||
/* pb_encode.c -- encode a protobuf using minimal resources
|
||||
*
|
||||
* 2011 Petteri Aimonen <jpa@kapsi.fi>
|
||||
*/
|
||||
|
||||
#include "pb.h"
|
||||
#include "pb_encode.h"
|
||||
#include "pb_common.h"
|
||||
|
||||
/* Use the GCC warn_unused_result attribute to check that all return values
|
||||
* are propagated correctly. On other compilers and gcc before 3.4.0 just
|
||||
* ignore the annotation.
|
||||
*/
|
||||
#if !defined(__GNUC__) || ( __GNUC__ < 3) || (__GNUC__ == 3 && __GNUC_MINOR__ < 4)
|
||||
#define checkreturn
|
||||
#else
|
||||
#define checkreturn __attribute__((warn_unused_result))
|
||||
#endif
|
||||
|
||||
/**************************************
|
||||
* Declarations internal to this file *
|
||||
**************************************/
|
||||
typedef bool (*pb_encoder_t)(pb_ostream_t *stream, const pb_field_t *field, const void *src) checkreturn;
|
||||
|
||||
static bool checkreturn buf_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count);
|
||||
static bool checkreturn encode_array(pb_ostream_t *stream, const pb_field_t *field, const void *pData, size_t count, pb_encoder_t func);
|
||||
static bool checkreturn encode_field(pb_ostream_t *stream, const pb_field_t *field, const void *pData);
|
||||
static bool checkreturn default_extension_encoder(pb_ostream_t *stream, const pb_extension_t *extension);
|
||||
static bool checkreturn encode_extension_field(pb_ostream_t *stream, const pb_field_t *field, const void *pData);
|
||||
static bool checkreturn pb_enc_varint(pb_ostream_t *stream, const pb_field_t *field, const void *src);
|
||||
static bool checkreturn pb_enc_uvarint(pb_ostream_t *stream, const pb_field_t *field, const void *src);
|
||||
static bool checkreturn pb_enc_svarint(pb_ostream_t *stream, const pb_field_t *field, const void *src);
|
||||
static bool checkreturn pb_enc_fixed32(pb_ostream_t *stream, const pb_field_t *field, const void *src);
|
||||
static bool checkreturn pb_enc_fixed64(pb_ostream_t *stream, const pb_field_t *field, const void *src);
|
||||
static bool checkreturn pb_enc_bytes(pb_ostream_t *stream, const pb_field_t *field, const void *src);
|
||||
static bool checkreturn pb_enc_string(pb_ostream_t *stream, const pb_field_t *field, const void *src);
|
||||
static bool checkreturn pb_enc_submessage(pb_ostream_t *stream, const pb_field_t *field, const void *src);
|
||||
|
||||
/* --- Function pointers to field encoders ---
|
||||
* Order in the array must match pb_action_t LTYPE numbering.
|
||||
*/
|
||||
static const pb_encoder_t PB_ENCODERS[PB_LTYPES_COUNT] = {
|
||||
&pb_enc_varint,
|
||||
&pb_enc_uvarint,
|
||||
&pb_enc_svarint,
|
||||
&pb_enc_fixed32,
|
||||
&pb_enc_fixed64,
|
||||
|
||||
&pb_enc_bytes,
|
||||
&pb_enc_string,
|
||||
&pb_enc_submessage,
|
||||
NULL /* extensions */
|
||||
};
|
||||
|
||||
/*******************************
|
||||
* pb_ostream_t implementation *
|
||||
*******************************/
|
||||
|
||||
static bool checkreturn buf_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count)
|
||||
{
|
||||
pb_byte_t *dest = (pb_byte_t*)stream->state;
|
||||
stream->state = dest + count;
|
||||
|
||||
while (count--)
|
||||
*dest++ = *buf++;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
pb_ostream_t pb_ostream_from_buffer(pb_byte_t *buf, size_t bufsize)
|
||||
{
|
||||
pb_ostream_t stream;
|
||||
#ifdef PB_BUFFER_ONLY
|
||||
stream.callback = (void*)1; /* Just a marker value */
|
||||
#else
|
||||
stream.callback = &buf_write;
|
||||
#endif
|
||||
stream.state = buf;
|
||||
stream.max_size = bufsize;
|
||||
stream.bytes_written = 0;
|
||||
#ifndef PB_NO_ERRMSG
|
||||
stream.errmsg = NULL;
|
||||
#endif
|
||||
return stream;
|
||||
}
|
||||
|
||||
bool checkreturn pb_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count)
|
||||
{
|
||||
if (stream->callback != NULL)
|
||||
{
|
||||
if (stream->bytes_written + count > stream->max_size)
|
||||
PB_RETURN_ERROR(stream, "stream full");
|
||||
|
||||
#ifdef PB_BUFFER_ONLY
|
||||
if (!buf_write(stream, buf, count))
|
||||
PB_RETURN_ERROR(stream, "io error");
|
||||
#else
|
||||
if (!stream->callback(stream, buf, count))
|
||||
PB_RETURN_ERROR(stream, "io error");
|
||||
#endif
|
||||
}
|
||||
|
||||
stream->bytes_written += count;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*************************
|
||||
* Encode a single field *
|
||||
*************************/
|
||||
|
||||
/* Encode a static array. Handles the size calculations and possible packing. */
|
||||
static bool checkreturn encode_array(pb_ostream_t *stream, const pb_field_t *field,
|
||||
const void *pData, size_t count, pb_encoder_t func)
|
||||
{
|
||||
size_t i;
|
||||
const void *p;
|
||||
size_t size;
|
||||
|
||||
if (count == 0)
|
||||
return true;
|
||||
|
||||
if (PB_ATYPE(field->type) != PB_ATYPE_POINTER && count > field->array_size)
|
||||
PB_RETURN_ERROR(stream, "array max size exceeded");
|
||||
|
||||
/* We always pack arrays if the datatype allows it. */
|
||||
if (PB_LTYPE(field->type) <= PB_LTYPE_LAST_PACKABLE)
|
||||
{
|
||||
if (!pb_encode_tag(stream, PB_WT_STRING, field->tag))
|
||||
return false;
|
||||
|
||||
/* Determine the total size of packed array. */
|
||||
if (PB_LTYPE(field->type) == PB_LTYPE_FIXED32)
|
||||
{
|
||||
size = 4 * count;
|
||||
}
|
||||
else if (PB_LTYPE(field->type) == PB_LTYPE_FIXED64)
|
||||
{
|
||||
size = 8 * count;
|
||||
}
|
||||
else
|
||||
{
|
||||
pb_ostream_t sizestream = PB_OSTREAM_SIZING;
|
||||
p = pData;
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
if (!func(&sizestream, field, p))
|
||||
return false;
|
||||
p = (const char*)p + field->data_size;
|
||||
}
|
||||
size = sizestream.bytes_written;
|
||||
}
|
||||
|
||||
if (!pb_encode_varint(stream, (uint64_t)size))
|
||||
return false;
|
||||
|
||||
if (stream->callback == NULL)
|
||||
return pb_write(stream, NULL, size); /* Just sizing.. */
|
||||
|
||||
/* Write the data */
|
||||
p = pData;
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
if (!func(stream, field, p))
|
||||
return false;
|
||||
p = (const char*)p + field->data_size;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
p = pData;
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
if (!pb_encode_tag_for_field(stream, field))
|
||||
return false;
|
||||
|
||||
/* Normally the data is stored directly in the array entries, but
|
||||
* for pointer-type string and bytes fields, the array entries are
|
||||
* actually pointers themselves also. So we have to dereference once
|
||||
* more to get to the actual data. */
|
||||
if (PB_ATYPE(field->type) == PB_ATYPE_POINTER &&
|
||||
(PB_LTYPE(field->type) == PB_LTYPE_STRING ||
|
||||
PB_LTYPE(field->type) == PB_LTYPE_BYTES))
|
||||
{
|
||||
if (!func(stream, field, *(const void* const*)p))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!func(stream, field, p))
|
||||
return false;
|
||||
}
|
||||
p = (const char*)p + field->data_size;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Encode a field with static or pointer allocation, i.e. one whose data
|
||||
* is available to the encoder directly. */
|
||||
static bool checkreturn encode_basic_field(pb_ostream_t *stream,
|
||||
const pb_field_t *field, const void *pData)
|
||||
{
|
||||
pb_encoder_t func;
|
||||
const void *pSize;
|
||||
bool implicit_has = true;
|
||||
|
||||
func = PB_ENCODERS[PB_LTYPE(field->type)];
|
||||
|
||||
if (field->size_offset)
|
||||
pSize = (const char*)pData + field->size_offset;
|
||||
else
|
||||
pSize = &implicit_has;
|
||||
|
||||
if (PB_ATYPE(field->type) == PB_ATYPE_POINTER)
|
||||
{
|
||||
/* pData is a pointer to the field, which contains pointer to
|
||||
* the data. If the 2nd pointer is NULL, it is interpreted as if
|
||||
* the has_field was false.
|
||||
*/
|
||||
|
||||
pData = *(const void* const*)pData;
|
||||
implicit_has = (pData != NULL);
|
||||
}
|
||||
|
||||
switch (PB_HTYPE(field->type))
|
||||
{
|
||||
case PB_HTYPE_REQUIRED:
|
||||
if (!pData)
|
||||
PB_RETURN_ERROR(stream, "missing required field");
|
||||
if (!pb_encode_tag_for_field(stream, field))
|
||||
return false;
|
||||
if (!func(stream, field, pData))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case PB_HTYPE_OPTIONAL:
|
||||
if (*(const bool*)pSize)
|
||||
{
|
||||
if (!pb_encode_tag_for_field(stream, field))
|
||||
return false;
|
||||
|
||||
if (!func(stream, field, pData))
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case PB_HTYPE_REPEATED:
|
||||
if (!encode_array(stream, field, pData, *(const pb_size_t*)pSize, func))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case PB_HTYPE_ONEOF:
|
||||
if (*(const pb_size_t*)pSize == field->tag)
|
||||
{
|
||||
if (!pb_encode_tag_for_field(stream, field))
|
||||
return false;
|
||||
|
||||
if (!func(stream, field, pData))
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
PB_RETURN_ERROR(stream, "invalid field type");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Encode a field with callback semantics. This means that a user function is
|
||||
* called to provide and encode the actual data. */
|
||||
static bool checkreturn encode_callback_field(pb_ostream_t *stream,
|
||||
const pb_field_t *field, const void *pData)
|
||||
{
|
||||
const pb_callback_t *callback = (const pb_callback_t*)pData;
|
||||
|
||||
#ifdef PB_OLD_CALLBACK_STYLE
|
||||
const void *arg = callback->arg;
|
||||
#else
|
||||
void * const *arg = &(callback->arg);
|
||||
#endif
|
||||
|
||||
if (callback->funcs.encode != NULL)
|
||||
{
|
||||
if (!callback->funcs.encode(stream, field, arg))
|
||||
PB_RETURN_ERROR(stream, "callback error");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Encode a single field of any callback or static type. */
|
||||
static bool checkreturn encode_field(pb_ostream_t *stream,
|
||||
const pb_field_t *field, const void *pData)
|
||||
{
|
||||
switch (PB_ATYPE(field->type))
|
||||
{
|
||||
case PB_ATYPE_STATIC:
|
||||
case PB_ATYPE_POINTER:
|
||||
return encode_basic_field(stream, field, pData);
|
||||
|
||||
case PB_ATYPE_CALLBACK:
|
||||
return encode_callback_field(stream, field, pData);
|
||||
|
||||
default:
|
||||
PB_RETURN_ERROR(stream, "invalid field type");
|
||||
}
|
||||
}
|
||||
|
||||
/* Default handler for extension fields. Expects to have a pb_field_t
|
||||
* pointer in the extension->type->arg field. */
|
||||
static bool checkreturn default_extension_encoder(pb_ostream_t *stream,
|
||||
const pb_extension_t *extension)
|
||||
{
|
||||
const pb_field_t *field = (const pb_field_t*)extension->type->arg;
|
||||
|
||||
if (PB_ATYPE(field->type) == PB_ATYPE_POINTER)
|
||||
{
|
||||
/* For pointer extensions, the pointer is stored directly
|
||||
* in the extension structure. This avoids having an extra
|
||||
* indirection. */
|
||||
return encode_field(stream, field, &extension->dest);
|
||||
}
|
||||
else
|
||||
{
|
||||
return encode_field(stream, field, extension->dest);
|
||||
}
|
||||
}
|
||||
|
||||
/* Walk through all the registered extensions and give them a chance
|
||||
* to encode themselves. */
|
||||
static bool checkreturn encode_extension_field(pb_ostream_t *stream,
|
||||
const pb_field_t *field, const void *pData)
|
||||
{
|
||||
const pb_extension_t *extension = *(const pb_extension_t* const *)pData;
|
||||
PB_UNUSED(field);
|
||||
|
||||
while (extension)
|
||||
{
|
||||
bool status;
|
||||
if (extension->type->encode)
|
||||
status = extension->type->encode(stream, extension);
|
||||
else
|
||||
status = default_extension_encoder(stream, extension);
|
||||
|
||||
if (!status)
|
||||
return false;
|
||||
|
||||
extension = extension->next;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*********************
|
||||
* Encode all fields *
|
||||
*********************/
|
||||
|
||||
static void *remove_const(const void *p)
|
||||
{
|
||||
/* Note: this casts away const, in order to use the common field iterator
|
||||
* logic for both encoding and decoding. */
|
||||
union {
|
||||
void *p1;
|
||||
const void *p2;
|
||||
} t;
|
||||
t.p2 = p;
|
||||
return t.p1;
|
||||
}
|
||||
|
||||
bool checkreturn pb_encode(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct)
|
||||
{
|
||||
pb_field_iter_t iter;
|
||||
if (!pb_field_iter_begin(&iter, fields, remove_const(src_struct)))
|
||||
return true; /* Empty message type */
|
||||
|
||||
do {
|
||||
if (PB_LTYPE(iter.pos->type) == PB_LTYPE_EXTENSION)
|
||||
{
|
||||
/* Special case for the extension field placeholder */
|
||||
if (!encode_extension_field(stream, iter.pos, iter.pData))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Regular field */
|
||||
if (!encode_field(stream, iter.pos, iter.pData))
|
||||
return false;
|
||||
}
|
||||
} while (pb_field_iter_next(&iter));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool pb_encode_delimited(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct)
|
||||
{
|
||||
return pb_encode_submessage(stream, fields, src_struct);
|
||||
}
|
||||
|
||||
bool pb_get_encoded_size(size_t *size, const pb_field_t fields[], const void *src_struct)
|
||||
{
|
||||
pb_ostream_t stream = PB_OSTREAM_SIZING;
|
||||
|
||||
if (!pb_encode(&stream, fields, src_struct))
|
||||
return false;
|
||||
|
||||
*size = stream.bytes_written;
|
||||
return true;
|
||||
}
|
||||
|
||||
/********************
|
||||
* Helper functions *
|
||||
********************/
|
||||
bool checkreturn pb_encode_varint(pb_ostream_t *stream, uint64_t value)
|
||||
{
|
||||
pb_byte_t buffer[10];
|
||||
size_t i = 0;
|
||||
|
||||
if (value <= 0x7F)
|
||||
{
|
||||
pb_byte_t v = (pb_byte_t)value;
|
||||
return pb_write(stream, &v, 1);
|
||||
}
|
||||
|
||||
while (value)
|
||||
{
|
||||
buffer[i] = (pb_byte_t)((value & 0x7F) | 0x80);
|
||||
value >>= 7;
|
||||
i++;
|
||||
}
|
||||
buffer[i-1] &= 0x7F; /* Unset top bit on last byte */
|
||||
|
||||
return pb_write(stream, buffer, i);
|
||||
}
|
||||
|
||||
bool checkreturn pb_encode_svarint(pb_ostream_t *stream, int64_t value)
|
||||
{
|
||||
uint64_t zigzagged;
|
||||
if (value < 0)
|
||||
zigzagged = ~((uint64_t)value << 1);
|
||||
else
|
||||
zigzagged = (uint64_t)value << 1;
|
||||
|
||||
return pb_encode_varint(stream, zigzagged);
|
||||
}
|
||||
|
||||
bool checkreturn pb_encode_fixed32(pb_ostream_t *stream, const void *value)
|
||||
{
|
||||
uint32_t val = *(const uint32_t*)value;
|
||||
pb_byte_t bytes[4];
|
||||
bytes[0] = (pb_byte_t)(val & 0xFF);
|
||||
bytes[1] = (pb_byte_t)((val >> 8) & 0xFF);
|
||||
bytes[2] = (pb_byte_t)((val >> 16) & 0xFF);
|
||||
bytes[3] = (pb_byte_t)((val >> 24) & 0xFF);
|
||||
return pb_write(stream, bytes, 4);
|
||||
}
|
||||
|
||||
bool checkreturn pb_encode_fixed64(pb_ostream_t *stream, const void *value)
|
||||
{
|
||||
uint64_t val = *(const uint64_t*)value;
|
||||
pb_byte_t bytes[8];
|
||||
bytes[0] = (pb_byte_t)(val & 0xFF);
|
||||
bytes[1] = (pb_byte_t)((val >> 8) & 0xFF);
|
||||
bytes[2] = (pb_byte_t)((val >> 16) & 0xFF);
|
||||
bytes[3] = (pb_byte_t)((val >> 24) & 0xFF);
|
||||
bytes[4] = (pb_byte_t)((val >> 32) & 0xFF);
|
||||
bytes[5] = (pb_byte_t)((val >> 40) & 0xFF);
|
||||
bytes[6] = (pb_byte_t)((val >> 48) & 0xFF);
|
||||
bytes[7] = (pb_byte_t)((val >> 56) & 0xFF);
|
||||
return pb_write(stream, bytes, 8);
|
||||
}
|
||||
|
||||
bool checkreturn pb_encode_tag(pb_ostream_t *stream, pb_wire_type_t wiretype, uint32_t field_number)
|
||||
{
|
||||
uint64_t tag = ((uint64_t)field_number << 3) | wiretype;
|
||||
return pb_encode_varint(stream, tag);
|
||||
}
|
||||
|
||||
bool checkreturn pb_encode_tag_for_field(pb_ostream_t *stream, const pb_field_t *field)
|
||||
{
|
||||
pb_wire_type_t wiretype;
|
||||
switch (PB_LTYPE(field->type))
|
||||
{
|
||||
case PB_LTYPE_VARINT:
|
||||
case PB_LTYPE_UVARINT:
|
||||
case PB_LTYPE_SVARINT:
|
||||
wiretype = PB_WT_VARINT;
|
||||
break;
|
||||
|
||||
case PB_LTYPE_FIXED32:
|
||||
wiretype = PB_WT_32BIT;
|
||||
break;
|
||||
|
||||
case PB_LTYPE_FIXED64:
|
||||
wiretype = PB_WT_64BIT;
|
||||
break;
|
||||
|
||||
case PB_LTYPE_BYTES:
|
||||
case PB_LTYPE_STRING:
|
||||
case PB_LTYPE_SUBMESSAGE:
|
||||
wiretype = PB_WT_STRING;
|
||||
break;
|
||||
|
||||
default:
|
||||
PB_RETURN_ERROR(stream, "invalid field type");
|
||||
}
|
||||
|
||||
return pb_encode_tag(stream, wiretype, field->tag);
|
||||
}
|
||||
|
||||
bool checkreturn pb_encode_string(pb_ostream_t *stream, const pb_byte_t *buffer, size_t size)
|
||||
{
|
||||
if (!pb_encode_varint(stream, (uint64_t)size))
|
||||
return false;
|
||||
|
||||
return pb_write(stream, buffer, size);
|
||||
}
|
||||
|
||||
bool checkreturn pb_encode_submessage(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct)
|
||||
{
|
||||
/* First calculate the message size using a non-writing substream. */
|
||||
pb_ostream_t substream = PB_OSTREAM_SIZING;
|
||||
size_t size;
|
||||
bool status;
|
||||
|
||||
if (!pb_encode(&substream, fields, src_struct))
|
||||
{
|
||||
#ifndef PB_NO_ERRMSG
|
||||
stream->errmsg = substream.errmsg;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
size = substream.bytes_written;
|
||||
|
||||
if (!pb_encode_varint(stream, (uint64_t)size))
|
||||
return false;
|
||||
|
||||
if (stream->callback == NULL)
|
||||
return pb_write(stream, NULL, size); /* Just sizing */
|
||||
|
||||
if (stream->bytes_written + size > stream->max_size)
|
||||
PB_RETURN_ERROR(stream, "stream full");
|
||||
|
||||
/* Use a substream to verify that a callback doesn't write more than
|
||||
* what it did the first time. */
|
||||
substream.callback = stream->callback;
|
||||
substream.state = stream->state;
|
||||
substream.max_size = size;
|
||||
substream.bytes_written = 0;
|
||||
#ifndef PB_NO_ERRMSG
|
||||
substream.errmsg = NULL;
|
||||
#endif
|
||||
|
||||
status = pb_encode(&substream, fields, src_struct);
|
||||
|
||||
stream->bytes_written += substream.bytes_written;
|
||||
stream->state = substream.state;
|
||||
#ifndef PB_NO_ERRMSG
|
||||
stream->errmsg = substream.errmsg;
|
||||
#endif
|
||||
|
||||
if (substream.bytes_written != size)
|
||||
PB_RETURN_ERROR(stream, "submsg size changed");
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Field encoders */
|
||||
|
||||
static bool checkreturn pb_enc_varint(pb_ostream_t *stream, const pb_field_t *field, const void *src)
|
||||
{
|
||||
int64_t value = 0;
|
||||
|
||||
if (field->data_size == sizeof(int_least8_t))
|
||||
value = *(const int_least8_t*)src;
|
||||
else if (field->data_size == sizeof(int_least16_t))
|
||||
value = *(const int_least16_t*)src;
|
||||
else if (field->data_size == sizeof(int32_t))
|
||||
value = *(const int32_t*)src;
|
||||
else if (field->data_size == sizeof(int64_t))
|
||||
value = *(const int64_t*)src;
|
||||
else
|
||||
PB_RETURN_ERROR(stream, "invalid data_size");
|
||||
|
||||
return pb_encode_varint(stream, (uint64_t)value);
|
||||
}
|
||||
|
||||
static bool checkreturn pb_enc_uvarint(pb_ostream_t *stream, const pb_field_t *field, const void *src)
|
||||
{
|
||||
uint64_t value = 0;
|
||||
|
||||
if (field->data_size == sizeof(uint_least8_t))
|
||||
value = *(const uint_least8_t*)src;
|
||||
else if (field->data_size == sizeof(uint_least16_t))
|
||||
value = *(const uint_least16_t*)src;
|
||||
else if (field->data_size == sizeof(uint32_t))
|
||||
value = *(const uint32_t*)src;
|
||||
else if (field->data_size == sizeof(uint64_t))
|
||||
value = *(const uint64_t*)src;
|
||||
else
|
||||
PB_RETURN_ERROR(stream, "invalid data_size");
|
||||
|
||||
return pb_encode_varint(stream, value);
|
||||
}
|
||||
|
||||
static bool checkreturn pb_enc_svarint(pb_ostream_t *stream, const pb_field_t *field, const void *src)
|
||||
{
|
||||
int64_t value = 0;
|
||||
|
||||
if (field->data_size == sizeof(int_least8_t))
|
||||
value = *(const int_least8_t*)src;
|
||||
else if (field->data_size == sizeof(int_least16_t))
|
||||
value = *(const int_least16_t*)src;
|
||||
else if (field->data_size == sizeof(int32_t))
|
||||
value = *(const int32_t*)src;
|
||||
else if (field->data_size == sizeof(int64_t))
|
||||
value = *(const int64_t*)src;
|
||||
else
|
||||
PB_RETURN_ERROR(stream, "invalid data_size");
|
||||
|
||||
return pb_encode_svarint(stream, value);
|
||||
}
|
||||
|
||||
static bool checkreturn pb_enc_fixed64(pb_ostream_t *stream, const pb_field_t *field, const void *src)
|
||||
{
|
||||
PB_UNUSED(field);
|
||||
return pb_encode_fixed64(stream, src);
|
||||
}
|
||||
|
||||
static bool checkreturn pb_enc_fixed32(pb_ostream_t *stream, const pb_field_t *field, const void *src)
|
||||
{
|
||||
PB_UNUSED(field);
|
||||
return pb_encode_fixed32(stream, src);
|
||||
}
|
||||
|
||||
static bool checkreturn pb_enc_bytes(pb_ostream_t *stream, const pb_field_t *field, const void *src)
|
||||
{
|
||||
const pb_bytes_array_t *bytes = (const pb_bytes_array_t*)src;
|
||||
|
||||
if (src == NULL)
|
||||
{
|
||||
/* Threat null pointer as an empty bytes field */
|
||||
return pb_encode_string(stream, NULL, 0);
|
||||
}
|
||||
|
||||
if (PB_ATYPE(field->type) == PB_ATYPE_STATIC &&
|
||||
PB_BYTES_ARRAY_T_ALLOCSIZE(bytes->size) > field->data_size)
|
||||
{
|
||||
PB_RETURN_ERROR(stream, "bytes size exceeded");
|
||||
}
|
||||
|
||||
return pb_encode_string(stream, bytes->bytes, bytes->size);
|
||||
}
|
||||
|
||||
static bool checkreturn pb_enc_string(pb_ostream_t *stream, const pb_field_t *field, const void *src)
|
||||
{
|
||||
size_t size = 0;
|
||||
size_t max_size = field->data_size;
|
||||
const char *p = (const char*)src;
|
||||
|
||||
if (PB_ATYPE(field->type) == PB_ATYPE_POINTER)
|
||||
max_size = (size_t)-1;
|
||||
|
||||
if (src == NULL)
|
||||
{
|
||||
size = 0; /* Threat null pointer as an empty string */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* strnlen() is not always available, so just use a loop */
|
||||
while (size < max_size && *p != '\0')
|
||||
{
|
||||
size++;
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
return pb_encode_string(stream, (const pb_byte_t*)src, size);
|
||||
}
|
||||
|
||||
static bool checkreturn pb_enc_submessage(pb_ostream_t *stream, const pb_field_t *field, const void *src)
|
||||
{
|
||||
if (field->ptr == NULL)
|
||||
PB_RETURN_ERROR(stream, "invalid field descriptor");
|
||||
|
||||
return pb_encode_submessage(stream, (const pb_field_t*)field->ptr, src);
|
||||
}
|
||||
|
||||
154
SDK/12.3.0_d7731ad/external/nano-pb/pb_encode.h
vendored
Normal file
154
SDK/12.3.0_d7731ad/external/nano-pb/pb_encode.h
vendored
Normal file
@@ -0,0 +1,154 @@
|
||||
/* pb_encode.h: Functions to encode protocol buffers. Depends on pb_encode.c.
|
||||
* The main function is pb_encode. You also need an output stream, and the
|
||||
* field descriptions created by nanopb_generator.py.
|
||||
*/
|
||||
|
||||
#ifndef PB_ENCODE_H_INCLUDED
|
||||
#define PB_ENCODE_H_INCLUDED
|
||||
|
||||
#include "pb.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Structure for defining custom output streams. You will need to provide
|
||||
* a callback function to write the bytes to your storage, which can be
|
||||
* for example a file or a network socket.
|
||||
*
|
||||
* The callback must conform to these rules:
|
||||
*
|
||||
* 1) Return false on IO errors. This will cause encoding to abort.
|
||||
* 2) You can use state to store your own data (e.g. buffer pointer).
|
||||
* 3) pb_write will update bytes_written after your callback runs.
|
||||
* 4) Substreams will modify max_size and bytes_written. Don't use them
|
||||
* to calculate any pointers.
|
||||
*/
|
||||
struct pb_ostream_s
|
||||
{
|
||||
#ifdef PB_BUFFER_ONLY
|
||||
/* Callback pointer is not used in buffer-only configuration.
|
||||
* Having an int pointer here allows binary compatibility but
|
||||
* gives an error if someone tries to assign callback function.
|
||||
* Also, NULL pointer marks a 'sizing stream' that does not
|
||||
* write anything.
|
||||
*/
|
||||
int *callback;
|
||||
#else
|
||||
bool (*callback)(pb_ostream_t *stream, const pb_byte_t *buf, size_t count);
|
||||
#endif
|
||||
void *state; /* Free field for use by callback implementation. */
|
||||
size_t max_size; /* Limit number of output bytes written (or use SIZE_MAX). */
|
||||
size_t bytes_written; /* Number of bytes written so far. */
|
||||
|
||||
#ifndef PB_NO_ERRMSG
|
||||
const char *errmsg;
|
||||
#endif
|
||||
};
|
||||
|
||||
/***************************
|
||||
* Main encoding functions *
|
||||
***************************/
|
||||
|
||||
/* Encode a single protocol buffers message from C structure into a stream.
|
||||
* Returns true on success, false on any failure.
|
||||
* The actual struct pointed to by src_struct must match the description in fields.
|
||||
* All required fields in the struct are assumed to have been filled in.
|
||||
*
|
||||
* Example usage:
|
||||
* MyMessage msg = {};
|
||||
* uint8_t buffer[64];
|
||||
* pb_ostream_t stream;
|
||||
*
|
||||
* msg.field1 = 42;
|
||||
* stream = pb_ostream_from_buffer(buffer, sizeof(buffer));
|
||||
* pb_encode(&stream, MyMessage_fields, &msg);
|
||||
*/
|
||||
bool pb_encode(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct);
|
||||
|
||||
/* Same as pb_encode, but prepends the length of the message as a varint.
|
||||
* Corresponds to writeDelimitedTo() in Google's protobuf API.
|
||||
*/
|
||||
bool pb_encode_delimited(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct);
|
||||
|
||||
/* Encode the message to get the size of the encoded data, but do not store
|
||||
* the data. */
|
||||
bool pb_get_encoded_size(size_t *size, const pb_field_t fields[], const void *src_struct);
|
||||
|
||||
/**************************************
|
||||
* Functions for manipulating streams *
|
||||
**************************************/
|
||||
|
||||
/* Create an output stream for writing into a memory buffer.
|
||||
* The number of bytes written can be found in stream.bytes_written after
|
||||
* encoding the message.
|
||||
*
|
||||
* Alternatively, you can use a custom stream that writes directly to e.g.
|
||||
* a file or a network socket.
|
||||
*/
|
||||
pb_ostream_t pb_ostream_from_buffer(pb_byte_t *buf, size_t bufsize);
|
||||
|
||||
/* Pseudo-stream for measuring the size of a message without actually storing
|
||||
* the encoded data.
|
||||
*
|
||||
* Example usage:
|
||||
* MyMessage msg = {};
|
||||
* pb_ostream_t stream = PB_OSTREAM_SIZING;
|
||||
* pb_encode(&stream, MyMessage_fields, &msg);
|
||||
* printf("Message size is %d\n", stream.bytes_written);
|
||||
*/
|
||||
#ifndef PB_NO_ERRMSG
|
||||
#define PB_OSTREAM_SIZING {0,0,0,0,0}
|
||||
#else
|
||||
#define PB_OSTREAM_SIZING {0,0,0,0}
|
||||
#endif
|
||||
|
||||
/* Function to write into a pb_ostream_t stream. You can use this if you need
|
||||
* to append or prepend some custom headers to the message.
|
||||
*/
|
||||
bool pb_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count);
|
||||
|
||||
|
||||
/************************************************
|
||||
* Helper functions for writing field callbacks *
|
||||
************************************************/
|
||||
|
||||
/* Encode field header based on type and field number defined in the field
|
||||
* structure. Call this from the callback before writing out field contents. */
|
||||
bool pb_encode_tag_for_field(pb_ostream_t *stream, const pb_field_t *field);
|
||||
|
||||
/* Encode field header by manually specifing wire type. You need to use this
|
||||
* if you want to write out packed arrays from a callback field. */
|
||||
bool pb_encode_tag(pb_ostream_t *stream, pb_wire_type_t wiretype, uint32_t field_number);
|
||||
|
||||
/* Encode an integer in the varint format.
|
||||
* This works for bool, enum, int32, int64, uint32 and uint64 field types. */
|
||||
bool pb_encode_varint(pb_ostream_t *stream, uint64_t value);
|
||||
|
||||
/* Encode an integer in the zig-zagged svarint format.
|
||||
* This works for sint32 and sint64. */
|
||||
bool pb_encode_svarint(pb_ostream_t *stream, int64_t value);
|
||||
|
||||
/* Encode a string or bytes type field. For strings, pass strlen(s) as size. */
|
||||
bool pb_encode_string(pb_ostream_t *stream, const pb_byte_t *buffer, size_t size);
|
||||
|
||||
/* Encode a fixed32, sfixed32 or float value.
|
||||
* You need to pass a pointer to a 4-byte wide C variable. */
|
||||
bool pb_encode_fixed32(pb_ostream_t *stream, const void *value);
|
||||
|
||||
/* Encode a fixed64, sfixed64 or double value.
|
||||
* You need to pass a pointer to a 8-byte wide C variable. */
|
||||
bool pb_encode_fixed64(pb_ostream_t *stream, const void *value);
|
||||
|
||||
/* Encode a submessage field.
|
||||
* You need to pass the pb_field_t array and pointer to struct, just like
|
||||
* with pb_encode(). This internally encodes the submessage twice, first to
|
||||
* calculate message size and then to actually write it out.
|
||||
*/
|
||||
bool pb_encode_submessage(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user