|  |  |  |  | /*****************************************************************************
 | 
					
						
							|  |  |  |  |  * file    lib/management/array.c   | 
					
						
							|  |  |  |  |  * author  YuLiang | 
					
						
							|  |  |  |  |  * version 1.0.0 | 
					
						
							|  |  |  |  |  * date    22-Sep-2021 | 
					
						
							|  |  |  |  |  * brief   This file provides all the array related operation functions. | 
					
						
							|  |  |  |  |  ****************************************************************************** | 
					
						
							|  |  |  |  |  * Attention | 
					
						
							|  |  |  |  |  * | 
					
						
							|  |  |  |  |  * <h2><center>© COPYRIGHT(c) 2021 LandPower</center></h2> | 
					
						
							|  |  |  |  |  * | 
					
						
							|  |  |  |  |  * Redistribution and use in source and binary forms, with or without modification, | 
					
						
							|  |  |  |  |  * are permitted provided 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. | 
					
						
							|  |  |  |  |  *   3. Neither the name of LandPower nor the names of its contributors may be used to  | 
					
						
							|  |  |  |  |  *      endorse or promote products derived from this software without specific | 
					
						
							|  |  |  |  |  *      prior written permission. | 
					
						
							|  |  |  |  |  * | 
					
						
							|  |  |  |  |  * 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. | 
					
						
							|  |  |  |  |  * | 
					
						
							|  |  |  |  |  ******************************************************************************/ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /* Includes ------------------------------------------------------------------*/ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | //#ifdef HAVE_CONFIG_H
 | 
					
						
							|  |  |  |  | #include "config.h"
 | 
					
						
							|  |  |  |  | //#endif
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /* 标准C库头文件. */ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /* 用户代码头文件. */ | 
					
						
							|  |  |  |  | #include "array.h"
 | 
					
						
							|  |  |  |  | /* Private typedef -----------------------------------------------------------*/ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /* Private define ------------------------------------------------------------*/ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /* Private macro -------------------------------------------------------------*/ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /* Private variables ---------------------------------------------------------*/ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /* Private function prototypes -----------------------------------------------*/ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /* Internal functions --------------------------------------------------------*/ | 
					
						
							|  |  |  |  | /* 确保设置的数组成员没有内存越界,如果超出数组长度,则重新realloc: 
 | 
					
						
							|  |  |  |  |    a        --  数组结构 | 
					
						
							|  |  |  |  |    len      --  需要申请的长度 | 
					
						
							|  |  |  |  |    mem_type --  使用的内存模块 | 
					
						
							|  |  |  |  |     | 
					
						
							|  |  |  |  |    return: void */ | 
					
						
							|  |  |  |  | static void _array_len_ensure(array_t *a, uint32_t len, int32_t mem_type) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |     if (a->alloced > len) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |         return; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     a->index = XREALLOC(mem_type, a->index, sizeof(void *) * (a->alloced * 2)); | 
					
						
							|  |  |  |  |     memset(&a->index[a->alloced], 0, sizeof(void *) * a->alloced); | 
					
						
							|  |  |  |  |     a->alloced *= 2; | 
					
						
							|  |  |  |  |    | 
					
						
							|  |  |  |  |     if (a->alloced <= len) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |         _array_len_ensure(a, len, mem_type); | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /* 查找数组a的第一个空位置.
 | 
					
						
							|  |  |  |  |    a    -- 数组结构 | 
					
						
							|  |  |  |  |     | 
					
						
							|  |  |  |  |    return: 第一个空位置索引 */ | 
					
						
							|  |  |  |  | uint32_t _array_empty_slot(array_t *a) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |     uint32_t i = 0; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     for(i = 0; i < a->active; i++) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |         if (NULL == a->index[i]) | 
					
						
							|  |  |  |  |         { | 
					
						
							|  |  |  |  |             return i; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     return i; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /* Interface functions -------------------------------------------------------*/ | 
					
						
							|  |  |  |  | /* 初始化数组:
 | 
					
						
							|  |  |  |  |    size     --  数组初始大小 | 
					
						
							|  |  |  |  |    mem_type --  使用的内存模块 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |    return: 数组指针 */ | 
					
						
							|  |  |  |  | array_t *array_init(uint32_t size, int32_t mem_type) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |     array_t *a = XMALLOC(mem_type, sizeof(array_t)); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     /* 如果大小为0,设置默认大小. */ | 
					
						
							|  |  |  |  |     if (0 == size) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |         size = ARRAY_MIN_SIZE; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     a->alloced = size; | 
					
						
							|  |  |  |  |     a->active = 0; | 
					
						
							|  |  |  |  |     a->index = XMALLOC(mem_type, sizeof(void *) * size); | 
					
						
							|  |  |  |  |    | 
					
						
							|  |  |  |  |     return a; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /* 设置数组相应索引位置的值:
 | 
					
						
							|  |  |  |  |    a        --  数组 | 
					
						
							|  |  |  |  |    i        --  索引 | 
					
						
							|  |  |  |  |    val      --  值 | 
					
						
							|  |  |  |  |    mem_type --  使用的内存模块 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |    return: void */ | 
					
						
							|  |  |  |  | void array_set(array_t *a, uint32_t i, void *val, int32_t mem_type) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |     _array_len_ensure(a, i, mem_type); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     a->index[i] = val; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     if (a->active <= i) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |         a->active = i + 1; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /* 删除数组相应索引位置的值:
 | 
					
						
							|  |  |  |  |    a    -- 数组 | 
					
						
							|  |  |  |  |    i    -- 索引  | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |    return: void */ | 
					
						
							|  |  |  |  | void array_unset(array_t *a, uint32_t i) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |     if (i >= a->alloced) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |         return; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     a->index[i] = NULL; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     /* 不是最后一个元素直接返回. */ | 
					
						
							|  |  |  |  |     if (i + 1 != a->active) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |         return; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     /* 如果是最后一个元素,则将当前可使用指针前移. */ | 
					
						
							|  |  |  |  |     while(--a->active) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |         if (a->index[a->active - 1] != NULL) | 
					
						
							|  |  |  |  |         { | 
					
						
							|  |  |  |  |             break; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /* 将数据放入数组的第一个空位置:
 | 
					
						
							|  |  |  |  |    a        --  数组 | 
					
						
							|  |  |  |  |    val      --  值 | 
					
						
							|  |  |  |  |    mem_type --  使用的内存模块 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |    return: 数据放入位置的索引值 */ | 
					
						
							|  |  |  |  | uint32_t array_append(array_t *a, void *val, int32_t mem_type) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |     uint32_t i = 0; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     i = _array_empty_slot(a); | 
					
						
							|  |  |  |  |     _array_len_ensure(a, i, mem_type); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     a->index[i] = val; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     if (a->active <= i) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |         a->active = i + 1; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     return i; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /* 复制数组a:
 | 
					
						
							|  |  |  |  |    a        --  数组 | 
					
						
							|  |  |  |  |    mem_type --  使用的内存模块 | 
					
						
							|  |  |  |  |     | 
					
						
							|  |  |  |  |    return: 新数组指针 */ | 
					
						
							|  |  |  |  | array_t *array_copy(array_t *a, int32_t mem_type) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |     unsigned int size = 0; | 
					
						
							|  |  |  |  |     array_t *array = XMALLOC(mem_type, sizeof(array_t)); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     array->active = a->active; | 
					
						
							|  |  |  |  |     array->alloced = a->alloced; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     size = sizeof(void *) * (a->alloced); | 
					
						
							|  |  |  |  |     array->index = XMALLOC(mem_type, size); | 
					
						
							|  |  |  |  |     memcpy(array->index, a->index, size); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     return array; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /* 将数组a和数组b合并成数组a:
 | 
					
						
							|  |  |  |  |    a        --  数组1 | 
					
						
							|  |  |  |  |    b        --  数组2 | 
					
						
							|  |  |  |  |    mem_type --  使用的内存模块 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |    return: void */ | 
					
						
							|  |  |  |  | void array_merge(array_t *a, array_t *b, int32_t mem_type) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |     uint32_t size = 0; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     if (0 == b->alloced) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |         return; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     size = sizeof(void *) * (a->alloced + b->alloced); | 
					
						
							|  |  |  |  |     a->index = XREALLOC(mem_type, a->index, size); | 
					
						
							|  |  |  |  |     memcpy(&a->index[a->active], b->index, sizeof(void *) * b->active); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     a->active = a->active + b->active; | 
					
						
							|  |  |  |  |     a->alloced = a->alloced + b->alloced; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /* 释放array_t:
 | 
					
						
							|  |  |  |  |    a        --  数组 | 
					
						
							|  |  |  |  |    mem_type --  使用的内存模块 | 
					
						
							|  |  |  |  |     | 
					
						
							|  |  |  |  |    return: void */ | 
					
						
							|  |  |  |  | void array_free_wrapper(array_t *a, int32_t mem_type) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |     XFREE(mem_type, a); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /* 释放array_t->index:
 | 
					
						
							|  |  |  |  |    a        --  数组 | 
					
						
							|  |  |  |  |    mem_type --  使用的内存模块 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |    return: void */ | 
					
						
							|  |  |  |  | void array_free_index(array_t *a, int32_t mem_type) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |     XFREE(mem_type, a->index); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /* 释放array_t和array_t->index:
 | 
					
						
							|  |  |  |  |    a        --  数组 | 
					
						
							|  |  |  |  |    mem_type --  使用的内存模块 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |    return: void */ | 
					
						
							|  |  |  |  | void array_free(array_t *a, int32_t mem_type) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |     XFREE(mem_type, a->index); | 
					
						
							|  |  |  |  |     XFREE(mem_type, a); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /* 查询数组a的数据i:
 | 
					
						
							|  |  |  |  |    a    -- 数组 | 
					
						
							|  |  |  |  |    i    -- 元素索引 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |    return: 元素指针 */ | 
					
						
							|  |  |  |  | void *array_lookup(array_t *a, uint32_t i) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |     return (i >= a->active) ? NULL : a->index[i]; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /* 获取数组a中有效数据的个数:
 | 
					
						
							|  |  |  |  |    a    -- 数组 | 
					
						
							|  |  |  |  |     | 
					
						
							|  |  |  |  |    return: void */ | 
					
						
							|  |  |  |  | uint32_t array_count(array_t *a) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |     uint32_t i = 0; | 
					
						
							|  |  |  |  |     uint32_t count = 0; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     for (i = 0; i < a->active; i++) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |         if (a->index[i] != NULL) | 
					
						
							|  |  |  |  |         { | 
					
						
							|  |  |  |  |             count++; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     return count; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | /************************ (C) COPYRIGHT LandPower ***** END OF FILE ****/ |