鸿蒙源码分析(六十)

common.c文件

这里的common.c是在samgr下面source一个子文件,samgr的作用是Manages system capabilities,也就是管理系统功能它主要提供面向服务的体系结构(SOA)的开发框架基础。还提供了服务的基本模型、特性模型、功能模型和注册模型以及发现功能,我们还可以基于samgr框架节构开发自己的接口等功能,而common在里扮演什么角色呢?--------就是提供Samgr和外部模块的常用对象和函数,具体一点就是这个文件提供了简化的矢量容器和向下转换函数。

背景知识

1.C++ 中vector介绍

vector是一个线性顺序结构。相当于数组,但其大小可以不预先指定,并且自动扩展。它可以像数组一样被操作,由于它的特性我们完全可以将vector 看作动态数组。

在创建一个vector 后,它会自动在内存中分配一块连续的内存空间进行数据存储,初始的空间大小可以预先指定也可以由vector 默认指定,这个大小即capacity ()函数的返回值。当存储的数据超过分配的空间时vector 会重新分配一块内存块,但这样的分配是很耗时的,在重新分配空间时它会做这样的动作:

  • 首先,vector 会申请一块更大的内存块;
  • 然后,将原来的数据拷贝到新的内存块中;
  • 其次,销毁掉原内存块中的对象(调用对象的析构函数);
  • 最后,将原来的内存空间释放掉。

如果vector 保存的数据量很大时,这样的操作一定会导致糟糕的性能(这也是vector 被设计成比较容易拷贝的值类型的原因)。所以说vector 不是在什么情况下性能都好,只有在预先知道它大小的情况下vector 的性能才是最优的。

vector特点

(1) 指定一块如同数组一样的连续存储,但空间可以动态扩展。即它可以像数组一样操作,并且可以进行动态操作。通常体现在push_back() pop_back() 。

(2) 随机访问方便,它像数组一样被访问,即支持[ ] 操作符和vector.at()

(3) 节省空间,因为它是连续存储,在存储数据的区域都是没有被浪费的,但是要明确一点vector 大多情况下并不是满存的,在未存储的区域实际是浪费的。

(4) 在内部进行插入、删除操作效率非常低,这样的操作基本上是被禁止的。Vector 被设计成只能在后端进行追加和删除操作,其原因是vector 内部的实现是按照顺序表的原理。

(5) 只能在vector 的最后进行push 和pop ,不能在vector 的头进行push 和pop 。

(6) 当动态添加的数据超过vector 默认分配的大小时要进行内存的重新分配、拷贝与释放,这个操作非常消耗性能。 所以要vector 达到最优的性能,最好在创建vector 时就指定其空间大小。

Vectors 包含着一系列连续存储的元素,其行为和数组类似。访问Vector中的任意元素或从末尾添加元素都可以在常量级时间复杂度内完成,而查找特定值的元素所处的位置或是在Vector中插入元素则是线性时间复杂度。

我们这里的vector是自己建立的一个容器,并不是c++自带的封装好的,而是原理一样,使用c语言的进行封装的定义。下面来看代码部分

代码分析

1.VECTOR_Make

函数功能:创建一个vector容器

//这里是制作一个容器
Vector VECTOR_Make(VECTOR_Key key, VECTOR_Compare compare)
{
    
    
    Vector vector = {
    
    0, 0, 0, NULL, key, compare};
    return vector;
}

2.VECTOR_Clear

函数功能:容器中元素和各个属性的清除

//容器的清楚
void VECTOR_Clear(Vector *vector)
{
    
    
    if (vector == NULL) {
    
    
        return;
    }
    if (vector->data == NULL) {
    
    
        return;
    }
    //对容器判空或者容器中数据判空,如果是空值就返回
    SAMGR_Free(vector->data);
    vector->max = 0;
    vector->top = 0;
    vector->free = 0;
    vector->data = NULL;
}

3.VECTOR_Add

函数功能:在容器中添加一个元素

int16 VECTOR_Add(Vector *vector, void *element)
{
    
    
    if (vector == NULL || element == NULL) {
    
    
        return INVALID_INDEX;
    }

    if (vector->top >= vector->max) {
    
    
        int16 i;
        // use released data elements preferentially
        for (i = vector->top - (int16)1; i >= 0; --i) {
    
    
            if (vector->data[i] == NULL) {
    
    
                vector->data[i] = element;
                vector->free--;
                return i;
            }
        }

        if (vector->max + GROW_STEP < 0) {
    
    
            return INVALID_INDEX;
        }

        void **data = (void **)SAMGR_Malloc(sizeof(void *) * (vector->max + GROW_STEP));
        if (data == NULL) {
    
    
            return INVALID_INDEX;
        }

        if (vector->data != NULL) {
    
    
            // data's length is bigger than vector->data's length and only copy vector->data's length's memory;
            // no need to check return value
            (void)memcpy_s(data, sizeof(void *) * (vector->max + GROW_STEP),
                           vector->data, sizeof(void *) * vector->max);
            SAMGR_Free(vector->data);
        }
        vector->data = data;
        vector->max += GROW_STEP;
    }

    vector->data[vector->top] = element;
    return vector->top++;
}

void *VECTOR_At(Vector *vector, int16 index)
{
    
    
    if (vector == NULL || vector->top <= index || index < 0) {
    
    
        return NULL;
    }

    return vector->data[index];
}

4.VECTOR_At

函数功能:这里的at函数主要是根据索引值在容器的data对应区域拿出相应值
如果参数都合法,就是去除index对应的数据域的数据。

void *VECTOR_At(Vector *vector, int16 index)
{
    
    
    if (vector == NULL || vector->top <= index || index < 0) {
    
    
        return NULL;
    }

    return vector->data[index];
}

5.VECTOR_Swap

函数参数:

  1. vector:传入一个容器
  2. element:要替换位置的元素
  3. index:数据域的索引值,也是要交换的另一个数

函数原理:就是根据index对印的数据和函数传入的数据element进行swap,函数最后返回之前data[index]
函数功能:在容器数据与实现数据替换

void *VECTOR_Swap(Vector *vector, int16 index, void *element)
{
    
    
    if (vector == NULL || vector->top <= index || index < 0) {
    
    
        return NULL;
    }
    //先检查对应参数
    if (element == NULL) {
    
    
        vector->free++;
    }
    //查看要交换的数据是否为空
    void *oldElement = vector->data[index];
    vector->data[index] = element;
    return oldElement;
    //实现替换函数返回之前的值
}

6.VECTOR_Find

函数功能:函数元素的查找
函数实现:这个函数的原理就是调用findbykey函数,就是findbykey函数的封装

int16 VECTOR_Find(Vector *vector, const void *element)
{
    
    
    if (vector == NULL || element == NULL) {
    
    
        return INVALID_INDEX;
    }
    return VECTOR_FindByKey(vector, (vector->key == NULL) ? element : vector->key(element));
}

7.VECTOR_FindByKey

函数功能:根据传入的key值在容器中找到对应的元素索引
函数原理,就是遍历所有容器键值对,看哪个key值满足要求,拿出对应键值元素的索引

int16 VECTOR_FindByKey(Vector *vector, const void *key)
{
    
    
    if (vector == NULL || key == NULL) {
    
    
        return INVALID_INDEX;
    }
    //第一步是检查参数是否合法
    int16 i;
    for (i = 0; i < vector->top; ++i) {
    
    
        if (vector->data[i] == NULL) {
    
    
            continue;
        }

        void *first = (vector->key != NULL) ? vector->key(vector->data[i]) : vector->data[i];
        //获取元素的key值
        if (first == key) {
    
    
            return i;
        }

        if (vector->compare == NULL || first == NULL) {
    
    
            continue;
        }
        //判断上一步是否成功
        if (vector->compare(first, key) == 0) {
    
    
            return i;
        }
        //比较first获取的key值和函数传入key比对,看是否一样。
    }
    return INVALID_INDEX;
}

8.VECTOR_Size&VECTOR_Num

函数功能:这两个函数都是容器相关属性的计算,一个是计算容器的size(就决定于top),另一个是计算元素个数,就是top减去free
这两个函数都相对简单,就是容器一些属性的计算。

//容器size的计算
int16 VECTOR_Size(Vector *vector)
{
    
    
    if (vector == NULL) {
    
    
        return INVALID_INDEX;
    }
    return vector->top;
}
//容器元素的计数
int16 VECTOR_Num(Vector *vector)
{
    
    
    if (vector == NULL) {
    
    
        return INVALID_INDEX;
    }
    return vector->top - vector->free;
}

感谢阅读和点赞!

猜你喜欢

转载自blog.csdn.net/m0_46976252/article/details/120611975