add ota algorithm for device

1. effective "Differential Upgrade" patch algorithm with high compression rate
2. effective recovery algorithm support recovery firmware in blocks which has low memory consumption and wear-leveling strategies, especially suitable for embeded devices with low RAM.
3. add sample ota bootloader project, see:
board\TencentOS_tiny_EVB_MX_Plus\KEIL\ota\ota_bootloader_recovery
4. add sample application project for download firmware through http, see:
board\TencentOS_tiny_EVB_MX_Plus\KEIL\ota\ota_application_download_through_http
5. add sample application project for download firmware through qcloud explorer console, see:
board\TencentOS_tiny_EVB_MX_Plus\KEIL\ota\ota_application_download_through_qcloud_iot_explorer
6. an OTA markdown document is pending
This commit is contained in:
daishengdong
2020-06-02 15:03:42 +08:00
parent 84faf16765
commit 5b51d50ade
177 changed files with 42367 additions and 1233 deletions

View File

@@ -0,0 +1,496 @@
/*-
* Copyright 2003-2005 Colin Percival
* All rights reserved
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted providing that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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 AUTHOR ``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 AUTHOR 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.
*/
/*----------------------------------------------------------------------------
* Tencent is pleased to support the open source community by making TencentOS
* available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
* If you have downloaded a copy of the TencentOS binary from Tencent, please
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
*
* If you have downloaded a copy of the TencentOS source code from Tencent,
* please note that TencentOS source code is licensed under the BSD 3-Clause
* License, except for the third-party components listed below which are
* subject to different license terms. Your integration of TencentOS into your
* own projects may require compliance with the BSD 3-Clause License, as well
* as the other licenses applicable to the third-party components included
* within TencentOS.
*---------------------------------------------------------------------------*/
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "bsdiff.h"
#include "wstream.h"
#include "lzma_compress.h"
#define ERROR(msg) \
printf("ERROR: line number[%d], function[%s] msg[%s]\n", __LINE__, __FUNCTION__, msg); \
rc = -1; \
goto OUT;
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
#define FOLD_N(x, n) ((n) * x)
static void split(int32_t *I, int32_t *V, int32_t start, int32_t len, int32_t h)
{
int32_t i, j, k, x, tmp, jj, kk;
if (len < 16) {
for (k = start; k < start + len; k += j) {
j = 1; x = V[I[k] + h];
for (i = 1; k + i < start + len; i++) {
if (V[I[k + i] + h] < x) {
x = V[I[k + i] + h];
j = 0;
}
if(V[I[k + i] + h] == x) {
tmp = I[k + j]; I[k + j] = I[k + i]; I[k + i] = tmp;
j++;
}
}
for (i = 0; i < j; i++) {
V[I[k + i]] = k + j - 1;
}
if (j == 1) {
I[k] = -1;
}
}
return;
}
x = V[I[start + len / 2] + h];
jj = 0; kk = 0;
for (i = start; i < start + len; i++) {
if (V[I[i] + h] < x) {
jj++;
}
if (V[I[i] + h] == x) {
kk++;
}
}
jj += start; kk += jj;
i = start; j = 0; k = 0;
while (i < jj) {
if (V[I[i] + h] < x) {
i++;
} else if (V[I[i] + h] == x) {
tmp = I[i]; I[i] = I[jj + j]; I[jj + j] = tmp;
j++;
} else {
tmp = I[i]; I[i] = I[kk + k]; I[kk + k] = tmp;
k++;
}
}
while (jj + j < kk) {
if (V[I[jj + j] + h] == x) {
j++;
} else {
tmp = I[jj + j]; I[jj + j] = I[kk + k]; I[kk + k] = tmp;
k++;
}
}
if (jj > start) {
split(I, V, start, jj - start, h);
}
for (i = 0; i < kk - jj; i++) {
V[I[jj + i]] = kk - 1;
}
if (jj == kk - 1) {
I[jj] = -1;
}
if (start + len > kk) {
split(I, V, kk, start + len - kk, h);
}
}
static void qsufsort(int32_t *I, int32_t *V, uint8_t *old, int32_t oldsize)
{
int32_t buckets[256];
int32_t i, h, len;
for (i = 0; i < 256; i++) {
buckets[i] = 0;
}
for (i = 0; i < oldsize; i++) {
buckets[old[i]]++;
}
for (i = 1; i < 256; i++) {
buckets[i] += buckets[i - 1];
}
for (i = 255; i > 0; i--) {
buckets[i] = buckets[i - 1];
}
buckets[0] = 0;
for (i = 0; i < oldsize; i++) {
I[++buckets[old[i]]] = i;
}
I[0] = oldsize;
for (i = 0; i < oldsize; i++) {
V[i] = buckets[old[i]];
}
V[oldsize] = 0;
for (i = 1; i < 256; i++) {
if (buckets[i] == buckets[i - 1] + 1) {
I[buckets[i]] = -1;
}
}
I[0] = -1;
for (h = 1; I[0] != -(oldsize + 1); h += h) {
len = 0;
for (i = 0; i < oldsize + 1; ) {
if (I[i] < 0) {
len -= I[i];
i -= I[i];
} else {
if (len) {
I[i - len] = -len;
}
len = V[I[i]] + 1 - i;
split(I, V, i, len, h);
i += len;
len = 0;
};
};
if (len) {
I[i - len] = -len;
}
};
for (i = 0; i < oldsize + 1; i++) {
I[V[i]] = i;
}
}
static int32_t matchlen(uint8_t *old, int32_t oldsize, uint8_t *new, int32_t newsize)
{
int32_t i;
for (i = 0; (i < oldsize) && (i < newsize); i++) {
if (old[i] != new[i]) {
break;
}
}
return i;
}
static int32_t search(int32_t *I, uint8_t *old, int32_t oldsize, uint8_t *new, int32_t newsize, int32_t st, int32_t en, int32_t *pos)
{
int32_t x,y;
if (en - st < 2) {
x = matchlen(old + I[st], oldsize - I[st], new, newsize);
y = matchlen(old + I[en], oldsize - I[en], new, newsize);
if (x > y) {
*pos = I[st];
return x;
} else {
*pos = I[en];
return y;
}
};
x = st + (en - st) / 2;
if (memcmp(old + I[x], new, MIN(oldsize - I[x], newsize)) < 0) {
return search(I, old, oldsize, new, newsize, x, en, pos);
} else {
return search(I, old, oldsize, new, newsize, st, x, pos);
}
}
static void offtout(int32_t x, uint8_t *buf)
{
int32_t y;
if (x < 0) {
y = -x;
} else {
y = x;
}
buf[0] = y % 256; y -= buf[0];
y = y / 256; buf[1] = y % 256; y -= buf[1];
y = y / 256; buf[2] = y % 256; y -= buf[2];
y = y / 256; buf[3] = y % 256;
if (x < 0) {
buf[3] |= 0x80;
}
}
int bsdiff(uint8_t *old, size_t oldsize, uint8_t *new, size_t newsize, uint8_t **patch, size_t *patchsize)
{
int rc = 0;
int32_t i;
int32_t *I = NULL, *V;
int32_t scan, pos = 0, len;
int32_t lastscan, lastpos, lastoffset;
int32_t oldscore, scsc;
int32_t s, Sf, lenf, Sb, lenb;
int32_t overlap, Ss, lens;
int32_t dblen, eblen;
uint8_t *db = NULL, *eb = NULL;
uint8_t buf[FOLD_N(sizeof(int32_t) / sizeof(uint8_t), 1)];
uint8_t header[FOLD_N(sizeof(int32_t) / sizeof(uint8_t), 3)];
wstream_t wstream;
uint8_t *wstream_buf, *the_patch;
size_t wstream_buf_size, the_patchsize;
wstream_buf_size = FOLD_N(newsize, 5);
if ((wstream_buf = malloc(wstream_buf_size)) == NULL) {
ERROR("malloc failed");
}
wstream_create(&wstream, wstream_buf, wstream_buf_size);
if (((I = malloc((oldsize + 1) * sizeof(int32_t))) == NULL) ||
((V = malloc((oldsize + 1) * sizeof(int32_t))) == NULL)) {
ERROR("malloc failed");
}
qsufsort(I, V, old, oldsize);
free(V);
if (((db = malloc(newsize + 1)) == NULL) ||
((eb = malloc(newsize + 1)) == NULL)) {
ERROR("malloc failed");
}
dblen = 0;
eblen = 0;
/* Header is
8 8 length of ctrl block
16 8 length of diff block
24 8 length of new file */
/* File is
0 32 Header
32 ?? ctrl block
?? ?? diff block
?? ?? extra block */
offtout(0, header + FOLD_N(sizeof(int32_t), 0));
offtout(0, header + FOLD_N(sizeof(int32_t), 1));
offtout(newsize, header + FOLD_N(sizeof(int32_t), 2));
if (wstream_write_stream(&wstream, header, sizeof(header)) != 0) {
ERROR("wstream full");
}
/* Compute the differences, writing ctrl as we go */
scan = 0; len = 0;
lastscan = 0; lastpos = 0; lastoffset = 0;
while (scan < newsize) {
oldscore = 0;
for (scsc = scan += len; scan < newsize; scan++) {
len = search(I, old, oldsize, new + scan, newsize - scan, 0, oldsize, &pos);
for (; scsc < scan + len; scsc++) {
if ((scsc + lastoffset < oldsize) &&
(old[scsc + lastoffset] == new[scsc])) {
oldscore++;
}
}
if (((len == oldscore) && (len != 0)) ||
(len > oldscore + 8)) {
break;
}
if ((scan + lastoffset < oldsize) &&
(old[scan + lastoffset] == new[scan])) {
oldscore--;
}
}
if ((len != oldscore) || (scan == newsize)) {
s = 0; Sf = 0; lenf = 0;
for (i = 0; (lastscan + i < scan) && (lastpos + i < oldsize); ) {
if (old[lastpos + i] == new[lastscan + i]) {
s++;
}
i++;
if (s * 2 - i > Sf * 2 - lenf) {
Sf = s; lenf = i;
}
}
lenb = 0;
if (scan < newsize) {
s = 0; Sb = 0;
for (i = 1; (scan >= lastscan + i) && (pos >= i); i++) {
if (old[pos - i] == new[scan - i]) {
s++;
}
if (s * 2 - i > Sb * 2 - lenb) {
Sb = s; lenb = i;
}
}
}
if (lastscan + lenf > scan - lenb) {
overlap = (lastscan + lenf) - (scan - lenb);
s = 0; Ss = 0; lens = 0;
for (i = 0; i < overlap; i++) {
if (new[lastscan + lenf - overlap + i] == old[lastpos + lenf - overlap + i]) {
s++;
}
if (new[scan - lenb + i] == old[pos - lenb + i]) {
s--;
}
if (s > Ss) {
Ss = s; lens = i + 1;
}
}
lenf += lens - overlap;
lenb -= lens;
}
for (i = 0; i < lenf; i++) {
db[dblen + i] = new[lastscan + i] - old[lastpos + i];
}
for (i = 0; i < (scan - lenb) - (lastscan + lenf); i++) {
eb[eblen + i] = new[lastscan + lenf + i];
}
dblen += lenf;
eblen += (scan - lenb) - (lastscan + lenf);
offtout(lenf, buf);
if (wstream_write_stream(&wstream, buf, sizeof(buf)) != 0) {
ERROR("wstream full");
}
offtout((scan - lenb) - (lastscan + lenf), buf);
if (wstream_write_stream(&wstream, buf, sizeof(buf)) != 0) {
ERROR("wstream full");
}
offtout((pos - lenb) - (lastpos + lenf), buf);
if (wstream_write_stream(&wstream, buf, sizeof(buf)) != 0) {
ERROR("wstream full");
}
lastscan = scan - lenb;
lastpos = pos - lenb;
lastoffset = pos - scan;
};
};
/* Compute size of ctrl data */
/* ATTENTION: we DONNOT do data compress here */
len = wstream_length_get(&wstream);
if (len == -1) {
ERROR("wstream invalid");
}
/* write size of ctrl data */
offtout(len - sizeof(header), header + FOLD_N(sizeof(int32_t), 0));
/* Write diff data */
/* ATTENTION: we DONNOT do data compress here */
if (wstream_write_stream(&wstream, db, dblen) != 0) {
ERROR("wstream full");
}
/* Compute size of diff data */
/* ATTENTION: we DONNOT do data compress here */
newsize = wstream_length_get(&wstream);
if (newsize == -1) {
ERROR("wstream invalid");
}
/* write size of diff data */
offtout(newsize - len, header + FOLD_N(sizeof(int32_t), 1));
/* Write extra data */
/* ATTENTION: we DONNOT do data compress here */
if (wstream_write_stream(&wstream, eb, eblen) != 0) {
ERROR("wstream full");
}
/* write header */
if (wstream_write_stream_at(&wstream, 0, header, sizeof(header)) != 0) {
ERROR("wsream full");
}
the_patchsize = wstream_length_get(&wstream);
if (the_patchsize == -1) {
ERROR("wstream invalid!\n");
}
if ((the_patch = malloc(the_patchsize)) == NULL) {
ERROR("malloc failed");
}
memcpy(the_patch, wstream_buf_get(&wstream), the_patchsize);
*patch = the_patch;
*patchsize = the_patchsize;
OUT:
/* Free the memory we used */
if (db) {
free(db);
}
if (eb) {
free(eb);
}
if (I) {
free(I);
}
if (wstream_buf) {
free(wstream_buf);
wstream_destroy(&wstream);
}
if (rc) {
*patch = NULL;
*patchsize = 0;
}
return rc;
}

View File

@@ -0,0 +1,26 @@
/*----------------------------------------------------------------------------
* Tencent is pleased to support the open source community by making TencentOS
* available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
* If you have downloaded a copy of the TencentOS binary from Tencent, please
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
*
* If you have downloaded a copy of the TencentOS source code from Tencent,
* please note that TencentOS source code is licensed under the BSD 3-Clause
* License, except for the third-party components listed below which are
* subject to different license terms. Your integration of TencentOS into your
* own projects may require compliance with the BSD 3-Clause License, as well
* as the other licenses applicable to the third-party components included
* within TencentOS.
*---------------------------------------------------------------------------*/
#ifndef _BSDIFF_H_
#define _BSDIFF_H_
#include "stdint.h"
int bsdiff(uint8_t *old, size_t oldsize, uint8_t *new, size_t newsize, uint8_t **patch, size_t *patchsize);
#endif /* _BSDIFF_H_ */

View File

@@ -0,0 +1,561 @@
/*----------------------------------------------------------------------------
* Tencent is pleased to support the open source community by making TencentOS
* available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
* If you have downloaded a copy of the TencentOS binary from Tencent, please
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
*
* If you have downloaded a copy of the TencentOS source code from Tencent,
* please note that TencentOS source code is licensed under the BSD 3-Clause
* License, except for the third-party components listed below which are
* subject to different license terms. Your integration of TencentOS into your
* own projects may require compliance with the BSD 3-Clause License, as well
* as the other licenses applicable to the third-party components included
* within TencentOS.
*---------------------------------------------------------------------------*/
#include "assert.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "graph.h"
int graph_create(graph_t *graph, int vertexs_n)
{
int i = 0;
vertex_t *vertexs;
if (!graph || vertexs_n <= 0) {
return -1;
}
memset(graph, 0, sizeof(graph_t));
if ((vertexs = malloc(vertexs_n * sizeof(vertex_t))) == NULL) {
return -1;
}
memset(vertexs, 0, vertexs_n * sizeof(vertex_t));
for (i = 0; i < vertexs_n; ++i) {
list_init(&vertexs[i].first_in);
list_init(&vertexs[i].first_out);
}
graph->edges_n = 0;
graph->vertexs_n = vertexs_n;
graph->vertexs = vertexs;
return 0;
}
int graph_destroy(graph_t *graph)
{
int i = 0;
vertex_t *vertex;
edge_t *edge, *tmp;
if (!graph || !graph->vertexs || !graph->vertexs_n) {
return -1;
}
for (i = 0; i < graph->vertexs_n; ++i) {
vertex = &graph->vertexs[i];
LIST_FOR_EACH_ENTRY_SAFE(edge, tmp, edge_t, tail_list, &vertex->first_out) {
list_del(&edge->tail_list);
free(edge);
}
}
free(graph->vertexs);
graph->edges_n = 0;
graph->vertexs_n = 0;
graph->vertexs = NULL;
return 0;
}
int graph_edge_add(graph_t *graph, int tail_vertex, int head_vertex)
{
edge_t *edge;
vertex_t *tail_v, *head_v;
if (!graph || !graph->vertexs || !graph->vertexs_n) {
return -1;
}
if (tail_vertex >= graph->vertexs_n ||
head_vertex >= graph->vertexs_n ||
tail_vertex < 0 ||
head_vertex < 0) {
return -1;
}
if ((edge = malloc(sizeof(edge_t))) == NULL) {
return -1;
}
edge->head_vertex = head_vertex;
edge->tail_vertex = tail_vertex;
list_init(&edge->head_list);
list_init(&edge->tail_list);
tail_v = &graph->vertexs[tail_vertex];
head_v = &graph->vertexs[head_vertex];
list_add(&edge->tail_list, &tail_v->first_out);
++tail_v->out_degree;
list_add(&edge->head_list, &head_v->first_in);
++head_v->in_degree;
++graph->edges_n;
return 0;
}
int graph_edge_rmv(graph_t *graph, int tail_vertex, int head_vertex)
{
edge_t *edge, *tmp;
vertex_t *tail_v, *head_v;
if (!graph || !graph->vertexs || !graph->vertexs_n) {
return -1;
}
if (tail_vertex >= graph->vertexs_n ||
head_vertex >= graph->vertexs_n ||
tail_vertex < 0 ||
head_vertex < 0) {
return -1;
}
tail_v = &graph->vertexs[tail_vertex];
head_v = &graph->vertexs[head_vertex];
LIST_FOR_EACH_ENTRY_SAFE(edge, tmp, edge_t, tail_list, &tail_v->first_out) {
if (edge->tail_vertex == tail_vertex &&
edge->head_vertex == head_vertex) {
list_del(&edge->tail_list);
--tail_v->out_degree;
list_del(&edge->head_list);
--head_v->in_degree;
free(edge);
--graph->edges_n;
return 0;
}
}
return -1;
}
int graph_edge_rmv_by_tail(graph_t *graph, int tail_vertex, graph_edge_delete_cb del_cb, void *cb_arg)
{
edge_t *edge, *tmp;
vertex_t *tail_v, *head_v;
if (!graph || !graph->vertexs || !graph->vertexs_n) {
return -1;
}
if (tail_vertex >= graph->vertexs_n || tail_vertex < 0) {
return -1;
}
tail_v = &graph->vertexs[tail_vertex];
LIST_FOR_EACH_ENTRY_SAFE(edge, tmp, edge_t, tail_list, &tail_v->first_out) {
if (edge->tail_vertex == tail_vertex) {
list_del(&edge->tail_list);
--tail_v->out_degree;
list_del(&edge->head_list);
head_v = &graph->vertexs[edge->head_vertex];
--head_v->in_degree;
if (del_cb) {
del_cb(edge->tail_vertex, edge->head_vertex, cb_arg);
}
free(edge);
--graph->edges_n;
}
}
return 0;
}
int graph_edge_rmv_one_by_tail(graph_t *graph, int tail_vertex)
{
edge_t *edge, *tmp;
vertex_t *tail_v, *head_v;
if (!graph || !graph->vertexs || !graph->vertexs_n) {
return -1;
}
if (tail_vertex >= graph->vertexs_n || tail_vertex < 0) {
return -1;
}
tail_v = &graph->vertexs[tail_vertex];
LIST_FOR_EACH_ENTRY_SAFE(edge, tmp, edge_t, tail_list, &tail_v->first_out) {
if (edge->tail_vertex == tail_vertex) {
list_del(&edge->tail_list);
--tail_v->out_degree;
list_del(&edge->head_list);
head_v = &graph->vertexs[edge->head_vertex];
--head_v->in_degree;
free(edge);
--graph->edges_n;
return 0;
}
}
return -1;
}
int graph_edge_rmv_by_head(graph_t *graph, int head_vertex, graph_edge_delete_cb del_cb, void *cb_arg)
{
edge_t *edge, *tmp;
vertex_t *tail_v, *head_v;
if (!graph || !graph->vertexs || !graph->vertexs_n) {
return -1;
}
if (head_vertex >= graph->vertexs_n || head_vertex < 0) {
return -1;
}
head_v = &graph->vertexs[head_vertex];
LIST_FOR_EACH_ENTRY_SAFE(edge, tmp, edge_t, head_list, &head_v->first_in) {
if (edge->head_vertex == head_vertex) {
list_del(&edge->tail_list);
tail_v = &graph->vertexs[edge->tail_vertex];
--tail_v->out_degree;
list_del(&edge->head_list);
--head_v->in_degree;
if (del_cb) {
del_cb(edge->tail_vertex, edge->head_vertex, cb_arg);
}
free(edge);
--graph->edges_n;
}
}
return 0;
}
int graph_edge_rmv_one_by_head(graph_t *graph, int head_vertex)
{
edge_t *edge, *tmp;
vertex_t *tail_v, *head_v;
if (!graph || !graph->vertexs || !graph->vertexs_n) {
return -1;
}
if (head_vertex >= graph->vertexs_n || head_vertex < 0) {
return -1;
}
head_v = &graph->vertexs[head_vertex];
LIST_FOR_EACH_ENTRY_SAFE(edge, tmp, edge_t, head_list, &head_v->first_in) {
if (edge->head_vertex == head_vertex) {
list_del(&edge->tail_list);
tail_v = &graph->vertexs[edge->tail_vertex];
--tail_v->out_degree;
list_del(&edge->head_list);
--head_v->in_degree;
free(edge);
--graph->edges_n;
return 0;
}
}
return -1;
}
int graph_edgesn_get(graph_t *graph)
{
if (!graph || !graph->vertexs || !graph->vertexs_n) {
return -1;
}
return graph->edges_n;
}
int graph_vertex_max(graph_t *graph)
{
if (!graph || !graph->vertexs || !graph->vertexs_n) {
return -1;
}
return graph->vertexs_n;
}
int graph_indegree_get(graph_t *graph, int vertex)
{
if (!graph || !graph->vertexs || !graph->vertexs_n) {
return -1;
}
if (vertex >= graph->vertexs_n || vertex < 0) {
return -1;
}
return graph->vertexs[vertex].in_degree;
}
int graph_outdegree_get(graph_t *graph, int vertex)
{
if (!graph || !graph->vertexs || !graph->vertexs_n) {
return -1;
}
if (vertex >= graph->vertexs_n || vertex < 0) {
return -1;
}
return graph->vertexs[vertex].out_degree;
}
int graph_tag_set(graph_t *graph, int vertex, v_tag_t tag)
{
if (!graph || !graph->vertexs || !graph->vertexs_n) {
return -1;
}
if (vertex >= graph->vertexs_n || vertex < 0) {
return -1;
}
graph->vertexs[vertex].tag = tag;
return 0;
}
int graph_tag_reset(graph_t *graph, int vertex)
{
if (!graph || !graph->vertexs || !graph->vertexs_n) {
return -1;
}
if (vertex >= graph->vertexs_n || vertex < 0) {
return -1;
}
graph->vertexs[vertex].tag = 0;
return 0;
}
v_tag_t graph_tag_get(graph_t *graph, int vertex)
{
if (!graph || !graph->vertexs || !graph->vertexs_n) {
return (v_tag_t)-1;
}
if (vertex >= graph->vertexs_n || vertex < 0) {
return (v_tag_t)-1;
}
return graph->vertexs[vertex].tag;
}
int graph_dfs_create(dfs_t *dfs, graph_t *graph)
{
if (!dfs || !graph) {
return -1;
}
if (graph_vertex_max(graph) == 0) {
return -1;
}
memset(dfs, 0, sizeof(dfs_t));
if (stack_create(&dfs->stack, graph_vertex_max(graph)) != 0) {
return 0;
}
if (stack_push(&dfs->stack, 0) != 0) {
// push the first vertex of the graph into the stack
return -1;
}
graph_vertex_set_visited(graph, 0);
dfs->graph = graph;
return 0;
}
int graph_dfs_destroy(dfs_t *dfs)
{
int i = 0;
if (!dfs || !dfs->graph) {
return -1;
}
for (i = 0; i < graph_vertex_max(dfs->graph); ++i) {
graph_tag_reset(dfs->graph, i);
}
stack_destroy(&dfs->stack);
dfs->graph = NULL;
return 0;
}
int graph_dfs_has_next(dfs_t *dfs)
{
if (!dfs || !dfs->graph) {
return 0;
}
return !stack_is_empty(&dfs->stack);
}
int graph_dfs_ring_detect(dfs_t *dfs, int *ring_size)
{
int i = 0;
edge_t *edge;
graph_t *graph;
vertex_t *vertex;
int vertex_idx, the_ring_size = 0, is_found = 0;
assert(sizeof(int) == sizeof(element_type_t));
if (!dfs || !dfs->graph || !ring_size) {
return -1;
}
graph = dfs->graph;
while (!stack_is_empty(&dfs->stack)) {
vertex_idx = stack_top(&dfs->stack);
vertex = &graph->vertexs[vertex_idx];
is_found = 0;
LIST_FOR_EACH_ENTRY(edge, edge_t, tail_list, &vertex->first_out) {
if (!graph_vertex_is_visited(graph, edge->head_vertex)) {
// still fresh neighbors here
stack_push(&dfs->stack, edge->head_vertex);
graph_vertex_set_visited(graph, edge->head_vertex);
is_found = 1;
break;
}
if (graph_vertex_is_tnode(graph, edge->head_vertex) ||
graph_vertex_is_rnode(graph, edge->head_vertex)) {
// already detected as a ring or a terminal node
continue;
}
// set DFS_RING_NODE tag
graph_vertex_set_rnode(graph, edge->head_vertex);
// if reach here, a ring is detected
stack_peek_init(&dfs->stack);
while ((vertex_idx = stack_peek(&dfs->stack)) != -1) {
++the_ring_size;
if (vertex_idx == edge->head_vertex) {
*ring_size = the_ring_size;
return 0;
}
}
}
// no fresh neighbors anymore
if (!is_found) {
stack_pop(&dfs->stack);
graph_vertex_set_tnode(graph, vertex_idx);
}
}
/* if here, graph may still has isolated nodes there: multi-connected-component in the graph */
for (i = 0; i < graph_vertex_max(graph); ++i) {
if (!graph_vertex_is_visited(graph, i)) {
stack_push(&dfs->stack, i);
graph_vertex_set_visited(graph, i);
break;
}
}
return -1;
}
int graph_out_print(graph_t *graph)
{
int i = 0;
edge_t *edge;
vertex_t *vertex;
if (!graph || !graph->vertexs || !graph->vertexs_n) {
return -1;
}
for (i = 0; i < graph->vertexs_n; ++i) {
vertex = &graph->vertexs[i];
if (vertex->out_degree == 0) {
continue;
}
printf("\nvertex: %d\n", i);
LIST_FOR_EACH_ENTRY(edge, edge_t, tail_list, &vertex->first_out) {
printf(" - %d -> %d\n", edge->tail_vertex, edge->head_vertex);
}
}
return 0;
}
int graph_in_print(graph_t *graph)
{
int i = 0;
edge_t *edge;
vertex_t *vertex;
if (!graph || !graph->vertexs || !graph->vertexs_n) {
return -1;
}
for (i = 0; i < graph->vertexs_n; ++i) {
vertex = &graph->vertexs[i];
if (vertex->in_degree == 0) {
continue;
}
printf("\nvertex: %d\n", i);
LIST_FOR_EACH_ENTRY(edge, edge_t, head_list, &vertex->first_in) {
printf(" - %d -> %d\n", edge->tail_vertex, edge->head_vertex);
}
}
return 0;
}

View File

@@ -0,0 +1,161 @@
/*----------------------------------------------------------------------------
* Tencent is pleased to support the open source community by making TencentOS
* available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
* If you have downloaded a copy of the TencentOS binary from Tencent, please
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
*
* If you have downloaded a copy of the TencentOS source code from Tencent,
* please note that TencentOS source code is licensed under the BSD 3-Clause
* License, except for the third-party components listed below which are
* subject to different license terms. Your integration of TencentOS into your
* own projects may require compliance with the BSD 3-Clause License, as well
* as the other licenses applicable to the third-party components included
* within TencentOS.
*---------------------------------------------------------------------------*/
#ifndef _GRAPH_H_
#define _GRAPH_H_
#include "list.h"
#include "stack.h"
// visited
#define DFS_VISITED (1 << 0)
// ring node
#define DFS_R_NODE (1 << 1)
// terminal node
#define DFS_T_NODE (1 << 2)
#define IS_VISITED(tag) ((tag) & DFS_VISITED)
#define IS_T_NODE(tag) ((tag) & DFS_R_NODE)
#define IS_R_NODE(tag) ((tag) & DFS_T_NODE)
#define SET_VISITED(tag) ((tag) | DFS_VISITED)
#define SET_R_NODE(tag) ((tag) | DFS_R_NODE)
#define SET_T_NODE(tag) ((tag) | DFS_T_NODE)
typedef uint8_t vertex_tag_t;
typedef vertex_tag_t v_tag_t;
/*
head
^
|
|
|
tail
*/
typedef struct edge_st {
int tail_vertex;
int head_vertex;
list_t tail_list; /* all the egdes with the same tail with us */
list_t head_list; /* with same head */
} edge_t;
typedef struct vertex_st {
list_t first_in;
list_t first_out;
int in_degree;
int out_degree;
v_tag_t tag;
} vertex_t;
typedef struct graph_st {
vertex_t *vertexs;
int vertexs_n;
int edges_n;
} graph_t;
typedef struct depth_first_search_st {
stack_t stack;
graph_t *graph;
} dfs_t;
typedef void (*graph_edge_delete_cb)(int tail_vertex, int head_vertex, void *cb_arg);
int graph_create(graph_t *graph, int vertexs_n);
int graph_destroy(graph_t *graph);
int graph_edge_add(graph_t *graph, int tail_vertex, int head_vertex);
int graph_edge_rmv(graph_t *graph, int tail_vertex, int head_vertex);
int graph_edge_rmv_by_tail(graph_t *graph, int tail_vertex, graph_edge_delete_cb del_cb, void *cb_arg);
int graph_edge_rmv_one_by_tail(graph_t *graph, int tail_vertex);
int graph_edge_rmv_by_head(graph_t *graph, int head_vertex, graph_edge_delete_cb del_cb, void *cb_arg);
int graph_edge_rmv_one_by_head(graph_t *graph, int head_vertex);
int graph_edgesn_get(graph_t *graph);
int graph_vertex_max(graph_t *graph);
int graph_indegree_get(graph_t *graph, int vertex);
int graph_outdegree_get(graph_t *graph, int vertex);
int graph_tag_set(graph_t *graph, int vertex, v_tag_t tag);
int graph_tag_reset(graph_t *graph, int vertex);
v_tag_t graph_tag_get(graph_t *graph, int vertex);
int graph_dfs_create(dfs_t *dfs, graph_t *graph);
int graph_dfs_destroy(dfs_t *dfs);
int graph_dfs_has_next(dfs_t *dfs);
int graph_dfs_ring_detect(dfs_t *dfs, int *ring_size);
int graph_out_print(graph_t *graph);
int graph_in_print(graph_t *graph);
static inline void graph_vertex_set_visited(graph_t *graph, int vertex)
{
graph_tag_set(graph, vertex, SET_VISITED(graph_tag_get(graph, vertex)));
}
static inline void graph_vertex_set_rnode(graph_t *graph, int vertex)
{
graph_tag_set(graph, vertex, SET_R_NODE(graph_tag_get(graph, vertex)));
}
static inline void graph_vertex_set_tnode(graph_t *graph, int vertex)
{
graph_tag_set(graph, vertex, SET_T_NODE(graph_tag_get(graph, vertex)));
}
static inline int graph_vertex_is_visited(graph_t *graph, int vertex)
{
return IS_VISITED(graph_tag_get(graph, vertex));
}
static inline int graph_vertex_is_rnode(graph_t *graph, int vertex)
{
return IS_R_NODE(graph_tag_get(graph, vertex));
}
static inline int graph_vertex_is_tnode(graph_t *graph, int vertex)
{
return IS_T_NODE(graph_tag_get(graph, vertex));
}
#endif

View File

@@ -0,0 +1,150 @@
/*----------------------------------------------------------------------------
* Tencent is pleased to support the open source community by making TencentOS
* available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
* If you have downloaded a copy of the TencentOS binary from Tencent, please
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
*
* If you have downloaded a copy of the TencentOS source code from Tencent,
* please note that TencentOS source code is licensed under the BSD 3-Clause
* License, except for the third-party components listed below which are
* subject to different license terms. Your integration of TencentOS into your
* own projects may require compliance with the BSD 3-Clause License, as well
* as the other licenses applicable to the third-party components included
* within TencentOS.
*---------------------------------------------------------------------------*/
#ifndef _LIST_H_
#define _LIST_H_
#include "stdint.h"
typedef struct list_node_st {
struct list_node_st *next;
struct list_node_st *prev;
} list_t;
#define OFFSET_OF_FIELD(type, field) \
((uint32_t)&(((type *)0)->field))
#define CONTAINER_OF_FIELD(ptr, type, field) \
((type *)((uint8_t *)(ptr) - OFFSET_OF_FIELD(type, field)))
#define LIST_NODE(node) \
{ &(node), &(node) }
#define LIST_DEFINE(list) \
dlist_t list = { &(list), &(list) }
#define LIST_ENTRY(node, type, field) \
CONTAINER_OF_FIELD(node, type, field)
#define LIST_FIRST_ENTRY(list, type, field) \
LIST_ENTRY((list)->next, type, field)
#define LIST_FIRST_ENTRY_OR_NULL(list, type, field) \
(list_empty(list) ? K_NULL : LIST_FIRST_ENTRY(list, type, field))
#define LIST_FOR_EACH(curr, list) \
for (curr = (list)->next; curr != (list); curr = curr->next)
#define LIST_FOR_EACH_PREV(curr, list) \
for (curr = (list)->prev; curr != (list); curr = curr->prev)
#define LIST_FOR_EACH_SAFE(curr, next, list) \
for (curr = (list)->next, next = curr->next; curr != (list); \
curr = next, next = curr->next)
#define LIST_FOR_EACH_PREV_SAFE(curr, next, list) \
for (curr = (list)->prev, next = curr->prev; \
curr != (list); \
curr = next, next = curr->prev)
#define LIST_FOR_EACH_ENTRY(entry, type, field, list) \
for (entry = LIST_ENTRY((list)->next, type, field); \
&entry->field != (list); \
entry = LIST_ENTRY(entry->field.next, type, field))
#define LIST_FOR_EACH_ENTRY_REVERSE(entry, type, field, list) \
for (entry = LIST_ENTRY((list)->prev, type, field); \
&entry->field != (list); \
entry = LIST_ENTRY(entry->field.prev, type, field))
#define LIST_FOR_EACH_ENTRY_SAFE(entry, tmp, type, field, list) \
for (entry = LIST_ENTRY((list)->next, type, field), \
tmp = LIST_ENTRY(entry->field.next, type, field); \
&entry->field != (list); \
entry = tmp, tmp = LIST_ENTRY(entry->field.next, type, field))
#define LIST_FOR_EACH_ENTRY_SAFE_REVERSE(entry, tmp, type, field, list) \
for (entry = LIST_ENTRY((list)->prev, type, field), \
tmp = LIST_ENTRY(entry->field.prev, type, field); \
&entry->field != (list); \
entry = tmp, tmp = LIST_ENTRY(entry->field.prev, type, field))
static inline void _list_add(list_t *node, list_t *prev, list_t *next)
{
next->prev = node;
node->next = next;
node->prev = prev;
prev->next = node;
}
static inline void _list_del(list_t *prev, list_t *next)
{
next->prev = prev;
prev->next = next;
}
static inline void _list_del_node(list_t *node)
{
_list_del(node->prev, node->next);
}
static inline void list_init(list_t *list)
{
list->next = list;
list->prev = list;
}
static inline void list_add(list_t *node, list_t *list)
{
_list_add(node, list, list->next);
}
static inline void list_add_tail(list_t *node, list_t *list)
{
_list_add(node, list->prev, list);
}
static inline void list_del(list_t *node)
{
_list_del(node->prev, node->next);
}
static inline void list_del_init(list_t *node)
{
_list_del_node(node);
list_init(node);
}
static inline void list_move(list_t *node, list_t *list)
{
_list_del_node(node);
list_add(node, list);
}
static inline void list_move_tail(list_t *node, list_t *list)
{
_list_del_node(node);
list_add_tail(node, list);
}
static inline int list_empty(const list_t *list)
{
return list->next == list;
}
#endif /* _LIST_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,154 @@
/*----------------------------------------------------------------------------
* Tencent is pleased to support the open source community by making TencentOS
* available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
* If you have downloaded a copy of the TencentOS binary from Tencent, please
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
*
* If you have downloaded a copy of the TencentOS source code from Tencent,
* please note that TencentOS source code is licensed under the BSD 3-Clause
* License, except for the third-party components listed below which are
* subject to different license terms. Your integration of TencentOS into your
* own projects may require compliance with the BSD 3-Clause License, as well
* as the other licenses applicable to the third-party components included
* within TencentOS.
*---------------------------------------------------------------------------*/
#ifndef _OTA_DIFF_H_
#define _OTA_DIFF_H_
#include "list.h"
#define ERROR(msg) \
printf("ERROR: line number[%d], function[%s] msg[%s]\n", __LINE__, __FUNCTION__, msg); \
rc = -1; \
goto OUT;
#ifndef INT_MAX
#define INT_MAX ((~(unsigned int)0) >> 1)
#endif
#define BLK_CNT(size, blk_len) (((size) + (blk_len) - 1) / (blk_len))
#define BLK_EXTRA(size, blk_len) ((size) % (blk_len))
#define THE_BUF(buf, idx, blk_len) ((buf) + (idx) * (blk_len))
#define BLK_IDX(off, blk_len) ((off) / (blk_len))
#define ALIGN_UP(v, align) (((v) + ((align) - 1)) & ~((align) - 1))
#define BLK_UPPER_BOUND(off, blk_len) (ALIGN_UP((off) + 1, (blk_len)))
#define BLK_LOWER_BOUND(idx, blk_len) ((idx) * (blk_len))
#define FOLD_N(x, n) ((n) * (x))
#define MIN(x, y) ((x) < (y) ? (x) : (y))
#define MIN_TRIPLE(x, y, z) (MIN(x, MIN(y, z)))
#define FREE(p) if (p) { free(p); }
#define CMD_COPY 0
#define CMD_DIFF 1
#define CMD_EXTRA 2
typedef struct backup_map_t {
uint16_t *cache;
uint16_t backup_n;
uint16_t cursor;
uint16_t blk_len;
uint8_t *buf;
} bkup_map_t;
typedef struct relied_detail_st {
list_t list;
int32_t new_blk_idx;
int32_t new_from;
int32_t old_from;
int32_t diff_from;
int32_t step;
} relied_detail_t;
typedef struct simplified_relied_detail_st {
list_t list;
int32_t new_blk_idx;
} smpl_relied_detail_t;
typedef struct old_block_info_st {
list_t relied_list;
int relied_cnt;
list_t simplified_relied_list;
int simplified_relied_cnt;
int is_safe;
} old_blk_info_t;
typedef enum cmd_type_en {
CMD_TYPE_DIFF,
CMD_TYPE_EXTRA,
} cmd_type_t;
typedef struct diff_detail_st {
int32_t old_from;
int32_t diff_from;
} diff_detail_t;
typedef struct extra_detail_st {
int32_t extra_from;
} extra_detail_t;
typedef union cmd_detail_un {
diff_detail_t diff_detail;
extra_detail_t extra_detail;
} cmd_detail_t;
typedef struct cmd_st {
list_t list;
int32_t new_from;
int32_t step;
cmd_type_t type;
cmd_detail_t detail;
} cmd_t;
typedef struct new_block_info_st {
list_t cmd_list;
int cmd_cnt;
} new_blk_info_t;
typedef struct summary_st {
int ring_cnt;
int ring_size_max;
int ring_size_min;
int patch_size;
int block_len;
int block_cnt;
int zipped_patch4block_size_max;
int zipped_patch4block_size_min;
int patch4block_size_max;
int patch4block_size_min;
int safe_block_cnt;
int is_safe_block_ignored;
} summary_t;
int ota_diff(uint8_t *old, size_t oldsize, uint8_t *new, size_t newsize, size_t blk_len, int is_safe_ignored, int is_verbose, uint8_t **patch, size_t *patchsize);
#endif /* _OTA_DIFF_H_ */

View File

@@ -0,0 +1,60 @@
/*----------------------------------------------------------------------------
* Tencent is pleased to support the open source community by making TencentOS
* available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
* If you have downloaded a copy of the TencentOS binary from Tencent, please
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
*
* If you have downloaded a copy of the TencentOS source code from Tencent,
* please note that TencentOS source code is licensed under the BSD 3-Clause
* License, except for the third-party components listed below which are
* subject to different license terms. Your integration of TencentOS into your
* own projects may require compliance with the BSD 3-Clause License, as well
* as the other licenses applicable to the third-party components included
* within TencentOS.
*---------------------------------------------------------------------------*/
#include "stdio.h"
#include "string.h"
#include "proc_bar.h"
int proc_bar_init(proc_bar_t *proc_bar, int max)
{
const char *stat = { "-\\|/" };
if (!proc_bar || max <= 0) {
return -1;
}
memset(proc_bar->buf, 0, sizeof(proc_bar->buf));
proc_bar->cursor = 0;
proc_bar->max = max;
printf("[%-101s][%%%d]%c\r", proc_bar->buf, 0, stat[proc_bar->cursor % 4]);
fflush(stdout);
return 0;
}
int proc_bar_update(proc_bar_t *proc_bar)
{
int percentage, i = 0;
const char *stat = { "-\\|/" };
if (!proc_bar || proc_bar->cursor >= proc_bar->max) {
return -1;
}
percentage = (++proc_bar->cursor) * 100 / proc_bar->max;
for (i = 0; i <= percentage; ++i) {
proc_bar->buf[i] = '#';
}
printf("[%-101s][%%%d]%c\r", proc_bar->buf, percentage, stat[proc_bar->cursor % 4]);
fflush(stdout);
return 0;
}

View File

@@ -0,0 +1,32 @@
/*----------------------------------------------------------------------------
* Tencent is pleased to support the open source community by making TencentOS
* available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
* If you have downloaded a copy of the TencentOS binary from Tencent, please
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
*
* If you have downloaded a copy of the TencentOS source code from Tencent,
* please note that TencentOS source code is licensed under the BSD 3-Clause
* License, except for the third-party components listed below which are
* subject to different license terms. Your integration of TencentOS into your
* own projects may require compliance with the BSD 3-Clause License, as well
* as the other licenses applicable to the third-party components included
* within TencentOS.
*---------------------------------------------------------------------------*/
#ifndef _PROC_BAR_H_
#define _PROC_BAR_H_
typedef struct process_bar_st {
int cursor;
int max;
char buf[102];
} proc_bar_t;
int proc_bar_init(proc_bar_t *proc_bar, int max);
int proc_bar_update(proc_bar_t *proc_bar);
#endif

View File

@@ -0,0 +1,233 @@
/*----------------------------------------------------------------------------
* Tencent is pleased to support the open source community by making TencentOS
* available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
* If you have downloaded a copy of the TencentOS binary from Tencent, please
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
*
* If you have downloaded a copy of the TencentOS source code from Tencent,
* please note that TencentOS source code is licensed under the BSD 3-Clause
* License, except for the third-party components listed below which are
* subject to different license terms. Your integration of TencentOS into your
* own projects may require compliance with the BSD 3-Clause License, as well
* as the other licenses applicable to the third-party components included
* within TencentOS.
*---------------------------------------------------------------------------*/
#include "stdlib.h"
#include "string.h"
#include "segment_tree.h"
#define ROOT 1
#define NODES_N(len) (3 * len)
static void segtree_build(stree_node_t *nodes, int left, int right, int root)
{
stree_node_t *node;
node = &nodes[root];
node->left = left;
node->right = right;
node->mid = (left + right) / 2;
node->is_covered = 0;
if (left + 1 != right) {
segtree_build(nodes, left, node->mid, 2 * root);
segtree_build(nodes, node->mid, right, 2 * root + 1);
}
}
int segtree_create(stree_t *stree, int left, int right)
{
int length;
stree_node_t *nodes;
if (!stree) {
return -1;
}
length = right - left;
if (length <= 0) {
return -1;
}
memset(stree, 0, sizeof(stree_t));
if ((nodes = (stree_node_t *)malloc(NODES_N(length) * sizeof(stree_node_t))) == NULL) {
return -1;
}
memset(nodes, 0, NODES_N(length) * sizeof(stree_node_t));
segtree_build(nodes, left, right, ROOT);
stree->nodes = nodes;
stree->length = length;
stree->left = left;
stree->right = right;
return 0;
}
int segtree_destroy(stree_t *stree)
{
if (!stree || !stree->nodes || !stree->length) {
return -1;
}
free(stree->nodes);
return 0;
}
int segtree_reset(stree_t *stree)
{
if (!stree || !stree->nodes || !stree->length) {
return -1;
}
memset(stree->nodes, 0, NODES_N(stree->length) * sizeof(stree_node_t));
segtree_build(stree->nodes, stree->left, stree->right, ROOT);
return 0;
}
static void segtree_do_insert(stree_node_t *nodes, int left, int right, int root)
{
stree_node_t *node;
node = &nodes[root];
if (node->left == left && node->right == right) {
node->is_covered = 1;
return;
}
if (right <= node->mid) {
segtree_do_insert(nodes, left, right, 2 * root);
} else if (left >= node->mid) {
segtree_do_insert(nodes, left, right, 2 * root + 1);
} else {
segtree_do_insert(nodes, left, node->mid, 2 * root);
segtree_do_insert(nodes, node->mid, right, 2 * root + 1);
}
}
int segtree_insert(stree_t *stree, int left, int right)
{
if (!stree || !stree->nodes) {
return -1;
}
if (right - left < 0) {
return -1;
}
segtree_do_insert(stree->nodes, left, right, ROOT);
return 0;
}
static int segtree_do_delete(stree_node_t *nodes, int left, int right, int root)
{
int is_covered = 0;
stree_node_t *node;
node = &nodes[root];
if (node->left + 1 == node->right) {
is_covered = node->is_covered;
node->is_covered = 0;
return is_covered;
}
if (node->is_covered) {
node->is_covered = 0;
nodes[2 * root].is_covered = 1;
nodes[2 * root + 1].is_covered = 1;
}
if (right <= node->mid) {
return segtree_do_delete(nodes, left, right, 2 * root);
} else if (left >= node->mid) {
return segtree_do_delete(nodes, left, right, 2 * root + 1);
} else {
return segtree_do_delete(nodes, left, node->mid, 2 * root) &&
segtree_do_delete(nodes, node->mid, right, 2 * root + 1);
}
}
int segtree_delete(stree_t *stree, int left, int right)
{
if (!stree || !stree->nodes) {
return -1;
}
if (right - left < 0) {
return -1;
}
return segtree_do_delete(stree->nodes, left, right, ROOT);
}
static int segtree_do_query(stree_node_t *nodes, int left, int right, int root)
{
stree_node_t *node;
node = &nodes[root];
if (node->left + 1 == node->right) {
return node->is_covered;
}
if (right <= node->mid) {
return segtree_do_query(nodes, left, right, 2 * root);
} else if (left >= node->mid) {
return segtree_do_query(nodes, left, right, 2 * root + 1);
} else {
return segtree_do_query(nodes, left, node->mid, 2 * root) &&
segtree_do_query(nodes, node->mid, right, 2 * root + 1);
}
}
int segtree_query(stree_t *stree, int left, int right)
{
if (!stree || !stree->nodes) {
return -1;
}
if (right - left < 0) {
return -1;
}
return segtree_do_query(stree->nodes, left, right, ROOT);
}
static int segtree_do_cal(stree_node_t *nodes, int root)
{
stree_node_t *node;
node = &nodes[root];
if (node->is_covered) {
return node->right - node->left;
}
if (node->left + 1 == node->right) {
return 0;
}
return segtree_do_cal(nodes, 2 * root ) + segtree_do_cal(nodes, 2 * root + 1);
}
int segtree_cal(stree_t *stree)
{
if (!stree || !stree->nodes) {
return -1;
}
return segtree_do_cal(stree->nodes, ROOT);
}

View File

@@ -0,0 +1,50 @@
/*----------------------------------------------------------------------------
* Tencent is pleased to support the open source community by making TencentOS
* available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
* If you have downloaded a copy of the TencentOS binary from Tencent, please
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
*
* If you have downloaded a copy of the TencentOS source code from Tencent,
* please note that TencentOS source code is licensed under the BSD 3-Clause
* License, except for the third-party components listed below which are
* subject to different license terms. Your integration of TencentOS into your
* own projects may require compliance with the BSD 3-Clause License, as well
* as the other licenses applicable to the third-party components included
* within TencentOS.
*---------------------------------------------------------------------------*/
#ifndef _SEGMENT_TREE_H_
#define _SEGMENT_TREE_H_
typedef struct segment_tree_node_st {
int left;
int right;
int mid;
int is_covered;
} stree_node_t;
typedef struct segment_tree_st {
stree_node_t *nodes;
int length;
int left;
int right;
} stree_t;
int segtree_create(stree_t *stree, int left, int right);
int segtree_destroy(stree_t *stree);
int segtree_reset(stree_t *stree);
int segtree_insert(stree_t *stree, int left, int right);
int segtree_delete(stree_t *stree, int left, int right);
int segtree_query(stree_t *stree, int left, int right);
int segtree_cal(stree_t *stree);
#endif

View File

@@ -0,0 +1,137 @@
/*----------------------------------------------------------------------------
* Tencent is pleased to support the open source community by making TencentOS
* available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
* If you have downloaded a copy of the TencentOS binary from Tencent, please
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
*
* If you have downloaded a copy of the TencentOS source code from Tencent,
* please note that TencentOS source code is licensed under the BSD 3-Clause
* License, except for the third-party components listed below which are
* subject to different license terms. Your integration of TencentOS into your
* own projects may require compliance with the BSD 3-Clause License, as well
* as the other licenses applicable to the third-party components included
* within TencentOS.
*---------------------------------------------------------------------------*/
#include "stdlib.h"
#include "string.h"
#include "stack.h"
int stack_create(stack_t *stack, int element_max)
{
e_type_t *elements;
if (!stack || element_max <= 0) {
return -1;
}
memset(stack, 0, sizeof(stack_t));
if ((elements = malloc(element_max * sizeof(e_type_t))) == NULL) {
return -1;
}
stack->top = 0;
stack->element_max = element_max;
stack->elements = elements;
return 0;
}
int stack_destroy(stack_t *stack)
{
if (!stack || !stack->elements) {
return -1;
}
free(stack->elements);
return 0;
}
int stack_push(stack_t *stack, e_type_t element)
{
if (!stack || !stack->elements) {
return -1;
}
if (stack_is_full(stack)) {
return -1;
}
stack->elements[stack->top++] = element;
return 0;
}
e_type_t stack_pop(stack_t *stack)
{
if (!stack || !stack->elements) {
return -1;
}
if (stack_is_empty(stack)) {
return -1;
}
return stack->elements[--stack->top];
}
e_type_t stack_top(stack_t *stack)
{
if (!stack || !stack->elements) {
return -1;
}
if (stack_is_empty(stack)) {
return -1;
}
return stack->elements[stack->top - 1];
}
int stack_peek_init(stack_t *stack)
{
if (!stack || !stack->elements) {
return -1;
}
stack->peek_top = stack->top;
return 0;
}
e_type_t stack_peek(stack_t *stack)
{
if (!stack || !stack->elements) {
return -1;
}
if (stack->peek_top == 0) {
return -1;
}
return stack->elements[--stack->peek_top];
}
int stack_is_empty(stack_t *stack)
{
if (!stack || !stack->elements) {
return 0;
}
return stack->top == 0;
}
int stack_is_full(stack_t *stack)
{
if (!stack || !stack->elements) {
return 0;
}
return stack->top == stack->element_max;
}

View File

@@ -0,0 +1,51 @@
/*----------------------------------------------------------------------------
* Tencent is pleased to support the open source community by making TencentOS
* available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
* If you have downloaded a copy of the TencentOS binary from Tencent, please
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
*
* If you have downloaded a copy of the TencentOS source code from Tencent,
* please note that TencentOS source code is licensed under the BSD 3-Clause
* License, except for the third-party components listed below which are
* subject to different license terms. Your integration of TencentOS into your
* own projects may require compliance with the BSD 3-Clause License, as well
* as the other licenses applicable to the third-party components included
* within TencentOS.
*---------------------------------------------------------------------------*/
#ifndef _STACK_H_
#define _STACK_H_
typedef int element_type_t;
typedef element_type_t e_type_t;
typedef struct stack_st {
e_type_t *elements;
int element_max;
int peek_top;
int top;
} stack_t;
int stack_create(stack_t *stack, int element_max);
int stack_destroy(stack_t *stack);
int stack_push(stack_t *stack, e_type_t element);
e_type_t stack_pop(stack_t *stack);
e_type_t stack_top(stack_t *stack);
int stack_peek_init(stack_t *stack);
e_type_t stack_peek(stack_t *stack);
int stack_is_empty(stack_t *stack);
int stack_is_full(stack_t *stack);
#endif

View File

@@ -0,0 +1,148 @@
/*----------------------------------------------------------------------------
* Tencent is pleased to support the open source community by making TencentOS
* available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
* If you have downloaded a copy of the TencentOS binary from Tencent, please
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
*
* If you have downloaded a copy of the TencentOS source code from Tencent,
* please note that TencentOS source code is licensed under the BSD 3-Clause
* License, except for the third-party components listed below which are
* subject to different license terms. Your integration of TencentOS into your
* own projects may require compliance with the BSD 3-Clause License, as well
* as the other licenses applicable to the third-party components included
* within TencentOS.
*---------------------------------------------------------------------------*/
#include "assert.h"
#include "string.h"
#include "topo_sorting.h"
int topo_sorting_create(topo_sorting_t *topo_sorting, graph_t *graph)
{
int i = 0;
if (!topo_sorting || !graph) {
return -1;
}
memset(topo_sorting, 0, sizeof(topo_sorting_t));
if (stack_create(&topo_sorting->stack, graph_vertex_max(graph)) != 0) {
return 0;
}
for (i = 0; i < graph_vertex_max(graph); ++i) {
if (graph_indegree_get(graph, i) == 0 &&
graph_tag_get(graph, i) != TOPO_VISITED) {
stack_push(&topo_sorting->stack, i);
graph_tag_set(graph, i, TOPO_VISITED);
}
}
topo_sorting->graph = graph;
return 0;
}
int topo_sorting_destroy(topo_sorting_t *topo_sorting)
{
int i = 0;
if (!topo_sorting || !topo_sorting->graph) {
return -1;
}
for (i = 0; i < graph_vertex_max(topo_sorting->graph); ++i) {
graph_tag_reset(topo_sorting->graph, i);
}
stack_destroy(&topo_sorting->stack);
topo_sorting->graph = NULL;
return 0;
}
int topo_sorting_has_next(topo_sorting_t *topo_sorting)
{
if (!topo_sorting || !topo_sorting->graph) {
return 0;
}
return !stack_is_empty(&topo_sorting->stack);
}
static void push2stack(int tail_vertex, int head_vertex, void *arg)
{
topo_sorting_t *topo_sorting = (topo_sorting_t *)arg;
if (graph_indegree_get(topo_sorting->graph, head_vertex) == 0) {
stack_push(&topo_sorting->stack, head_vertex);
graph_tag_set(topo_sorting->graph, head_vertex, TOPO_VISITED);
}
}
int topo_sorting_next(topo_sorting_t *topo_sorting)
{
int vertex;
assert(sizeof(e_type_t) == sizeof(int));
if (!topo_sorting || !topo_sorting->graph) {
return -1;
}
if (stack_is_empty(&topo_sorting->stack)) {
return -1;
}
vertex = stack_pop(&topo_sorting->stack);
graph_edge_rmv_by_tail(topo_sorting->graph, vertex, push2stack, (void *)topo_sorting);
return vertex;
}
int topo_has_ring(topo_sorting_t *topo_sorting)
{
if (!topo_sorting || !topo_sorting->graph) {
return -1;
}
return graph_edgesn_get(topo_sorting->graph) != 0;
}
int topo_ring_break(topo_sorting_t *topo_sorting)
{
int i = 0;
graph_t *graph;
if (!topo_sorting || !topo_sorting->graph) {
return -1;
}
graph = topo_sorting->graph;
for (i = 0; i < graph_vertex_max(graph); ++i) {
if (graph_indegree_get(graph, i) != 0 &&
graph_outdegree_get(graph, i) != 0 &&
graph_tag_get(graph, i) != TOPO_VISITED) {
/* remove one edge from the graph */
graph_edge_rmv_one_by_head(graph, i);
break;
}
}
for (i = 0; i < graph_vertex_max(graph); ++i) {
if (graph_indegree_get(graph, i) == 0 &&
graph_tag_get(graph, i) != TOPO_VISITED) {
stack_push(&topo_sorting->stack, i);
graph_tag_set(graph, i, TOPO_VISITED);
}
}
return 0;
}

View File

@@ -0,0 +1,44 @@
/*----------------------------------------------------------------------------
* Tencent is pleased to support the open source community by making TencentOS
* available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
* If you have downloaded a copy of the TencentOS binary from Tencent, please
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
*
* If you have downloaded a copy of the TencentOS source code from Tencent,
* please note that TencentOS source code is licensed under the BSD 3-Clause
* License, except for the third-party components listed below which are
* subject to different license terms. Your integration of TencentOS into your
* own projects may require compliance with the BSD 3-Clause License, as well
* as the other licenses applicable to the third-party components included
* within TencentOS.
*---------------------------------------------------------------------------*/
#ifndef _TOPO_SORTING_H_
#define _TOPO_SORTING_H_
#include "stack.h"
#include "graph.h"
#define TOPO_VISITED 1
typedef struct topo_sorting_st {
stack_t stack;
graph_t *graph;
} topo_sorting_t;
int topo_sorting_create(topo_sorting_t *topo_sorting, graph_t *graph);
int topo_sorting_destroy(topo_sorting_t *topo_sorting);
int topo_sorting_has_next(topo_sorting_t *topo_sorting);
int topo_sorting_next(topo_sorting_t *topo_sorting);
int topo_has_ring(topo_sorting_t *topo_sorting);
int topo_ring_break(topo_sorting_t *topo_sorting);
#endif

View File

@@ -0,0 +1 @@
4.3

View File

@@ -0,0 +1,126 @@
/*----------------------------------------------------------------------------
* Tencent is pleased to support the open source community by making TencentOS
* available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
* If you have downloaded a copy of the TencentOS binary from Tencent, please
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
*
* If you have downloaded a copy of the TencentOS source code from Tencent,
* please note that TencentOS source code is licensed under the BSD 3-Clause
* License, except for the third-party components listed below which are
* subject to different license terms. Your integration of TencentOS into your
* own projects may require compliance with the BSD 3-Clause License, as well
* as the other licenses applicable to the third-party components included
* within TencentOS.
*---------------------------------------------------------------------------*/
#include "stdlib.h"
#include "wstream.h"
int wstream_create(wstream_t *wstream, uint8_t *buf, int buf_size)
{
if (!wstream || !buf) {
return -1;
}
wstream->buf = buf;
wstream->buf_size = buf_size;
wstream->cursor = 0;
return 0;
}
int wstream_destroy(wstream_t *wstream)
{
WSTREAM_SANITY_CHECK(wstream);
wstream->buf = (uint8_t *)0;
wstream->buf_size = 0;
wstream->cursor = 0;
return 0;
}
int wstream_reset(wstream_t *wstream)
{
WSTREAM_SANITY_CHECK(wstream);
wstream->cursor = 0;
return 0;
}
int wstream_write_byte(wstream_t *wstream, uint8_t byte)
{
WSTREAM_SANITY_CHECK(wstream);
if (wstream->buf_size == wstream->cursor) {
return -1;
}
wstream->buf[wstream->cursor++] = byte;
return 0;
}
int wstream_write_byte_at(wstream_t *wstream, int offset, uint8_t byte)
{
WSTREAM_SANITY_CHECK(wstream);
if (offset >= wstream->buf_size) {
return -1;
}
wstream->buf[offset] = byte;
return 0;
}
int wstream_write_stream(wstream_t *wstream, uint8_t *stream, int stream_size)
{
int i = 0;
WSTREAM_SANITY_CHECK(wstream);
if (wstream->buf_size - wstream->cursor < stream_size) {
return -1;
}
for (i = 0; i < stream_size; ++i) {
wstream_write_byte(wstream, stream[i]);
}
return 0;
}
int wstream_write_stream_at(wstream_t *wstream, int offset, uint8_t *stream, int stream_size)
{
int i = 0;
WSTREAM_SANITY_CHECK(wstream);
if (wstream->buf_size - offset < stream_size) {
return -1;
}
for (i = 0; i < stream_size; ++i) {
wstream_write_byte_at(wstream, offset++, stream[i]);
}
return 0;
}
int wstream_length_get(wstream_t *wstream)
{
WSTREAM_SANITY_CHECK(wstream);
return wstream->cursor;
}
uint8_t *wstream_buf_get(wstream_t *wstream)
{
WSTREAM_SANITY_CHECK_RC(wstream, NULL);
return wstream->buf;
}

View File

@@ -0,0 +1,58 @@
/*----------------------------------------------------------------------------
* Tencent is pleased to support the open source community by making TencentOS
* available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
* If you have downloaded a copy of the TencentOS binary from Tencent, please
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
*
* If you have downloaded a copy of the TencentOS source code from Tencent,
* please note that TencentOS source code is licensed under the BSD 3-Clause
* License, except for the third-party components listed below which are
* subject to different license terms. Your integration of TencentOS into your
* own projects may require compliance with the BSD 3-Clause License, as well
* as the other licenses applicable to the third-party components included
* within TencentOS.
*---------------------------------------------------------------------------*/
#ifndef _WSTREAM_H_
#define _WSTREAM_H_
#include "stdint.h"
typedef struct write_stream_st {
int buf_size;
uint8_t *buf;
int cursor;
} wstream_t;
#define WSTREAM_SANITY_CHECK(wstream) \
if (!wstream || !wstream->buf) { \
return -1; \
}
#define WSTREAM_SANITY_CHECK_RC(wstream, rc) \
if (!wstream || !wstream->buf) { \
return rc; \
}
int wstream_create(wstream_t *wstream, uint8_t *buf, int buf_size);
int wstream_destroy(wstream_t *wstream);
int wstream_reset(wstream_t *wstream);
int wstream_write_byte(wstream_t *wstream, uint8_t byte);
int wstream_write_byte_at(wstream_t *wstream, int offset, uint8_t byte);
int wstream_write_stream(wstream_t *wstream, uint8_t *stream, int stream_size);
int wstream_write_stream_at(wstream_t *wstream, int offset, uint8_t *stream, int stream_size);
int wstream_length_get(wstream_t *wstream);
uint8_t *wstream_buf_get(wstream_t *wstream);
#endif /*
_WSTREAM_H_ */