项目简介
基于c语言实现的仿node库,主要实现js的事件循环机制(单线程异步)和几大主要模块(event、socket、fs等)。这只是一个练手的项目,不能保证代码的绝对可靠性,如果发现bug,欢迎提issue,项目地址:https://gitee.com/lyxfj/async。
数据结构
- JavaScript常用的数据类型,先来看下和C语言数据类型的差异和拟定的替代方案:
js | c语言 | 替代方案 |
---|---|---|
number | int | 直接使用 |
string | char * | 字符串数组 |
boolean | enum | 使用枚举类型定义 |
object | struct | 定义结构体 |
array | [] | 通过动态分配内存解决 |
function | 函数 | 函数指针 |
- 基本结构的实现
-
Number类型
JavaScript中number类型包括了整型和浮点型两种,而C语言中整型(int)和浮点型(double)是分开的,使用联合类型定义如下:typedef union { int Int; double Double; }Number;
*注:
float
类型精度不够,所以只采用了double -
Boolean类型
enum Boolean { True = 1, False = 0 };
-
字符串类型
实际上就是char *指针类型的别名:typedef string char *;
-
object类型
JavaScript中object类型有很多种情况,null
和undefined
直接使用全局宏NULL
即可,多数情况写可以用关键字struct
定义一个结构体解决,但是当添加属性和删除属性时就会很不方便,所以先实现一个HashMap结构,首先定义键值对结构体Entry
,为了解决哈希冲突添加了一个指针,将冲突值以链表的形式挂在后面:typedef struct entry { void * key; // 键 void * value; // 值 struct entry * next; // 冲突链表 }*Entry; #define newEntry() NEW(struct entry) #define newEntryList(length) (Entry)malloc(length * sizeof(struct entry))
接着定义HashMap结构体,实现思路很简单,建立一个
Entry
数组作为存储空间,然后根据传入的key
计算出一个哈希地址,当做数组的索引存入,读取的时候通过计算出的索引可以在数组中直接取出值,时间复杂度为O(1)
。size
是当前存储键值对的数量,而listSize
是当前数组的大小,数组的每一项其实都是链表的头节点,这就有可能导致size
大于listSize
,当size
大于listSize
的时候一定发生了冲突,所以在调用存储方法hashMap->put
的时候会判断size
是否超过了listSize
,如果超过了会扩充空间,减少冲突,加快索引速度。// 哈希结构 typedef struct hashMap *HashMap; #define newHashMap() NEW(struct hashMap) // 哈希函数类型 typedef int(*HashCode)(HashMap, void * key); // 判等函数类型 typedef Boolean(*Equal)(void * key1, void * key2); // 添加键函数类型 typedef void(*Put)(HashMap hashMap, void * key, void * value); // 获取键对应值的函数类型 typedef void * (*Get)(HashMap hashMap, void * key); // 删除键的函数类型 typedef Boolean(*Remove)(HashMap hashMap, void * key); // 清空Map的函数类型 typedef void(*Clear)(HashMap hashMap); // 判断键值是否存在的函数类型 typedef Boolean(*Exists)(HashMap hashMap, void * key); typedef struct hashMap { int size; // 当前大小 int listSize; // 有效空间大小 HashCode hashCode; // 哈希函数 Equal equal; // 判等函数 Entry list; // 存储区域 Put put; // 添加键的函数 Get get; // 获取键对应值的函数 Remove remove; // 删除键 Clear clear; // 清空Map Exists exists; // 判断键是否存在 }*HashMap; // 默认哈希函数 static int defaultHashCode(HashMap hashMap, void * key); // 默认判断键值是否相等 static Boolean defaultEqual(void * key1, void * key2); // 默认添加键值对 static void defaultPut(HashMap hashMap, void * key, void * value); // 默认获取键对应值 static void * defaultGet(HashMap hashMap, void * key); // 默认删除键 static Boolean defaultRemove(HashMap hashMap, void * key); // 默认判断键是否存在 static Boolean defaultExists(HashMap hashMap, void * key); // 默认清空Map static void defaultClear(HashMap hashMap); // 创建一个哈希结构 HashMap createHashMap(HashCode hashCode, Equal equal);
这里的一些方法定义成了static,为的是在文件外不可访问,只能通过实例化的HashMap的属性去调用他们,这样用户可以随时更换其中的模块而不影响整体功能。
还要给HashMap实现一个iterator接口,这是后续实现对象属性遍历的基础:
// 创建一个哈希结构 HashMap createHashMap(HashCode hashCode, Equal equal); // 创建哈希结构迭代器 Iterator createIterator(HashMap hashMap); // 迭代器是否有下一个 Boolean hasNextIterator(Iterator iterator); // 迭代到下一次 Iterator nextIterator(Iterator iterator); // 释放迭代器内存 void freeIterator(Iterator iterator);
完整的实现如下:
#include"hashMap.h" int defaultHashCode(HashMap hashMap, void * key) { char * k = (char *)key; unsigned long h = 0; while (*k) { h = (h << 4) + *k++; unsigned long g = h & 0xF0000000L; if (g) { h ^= g >> 24; } h &= ~g; } return h % hashMap->listSize; } Boolean defaultEqual(void * key1, void * key2) { return strcmp((char *)key1, (char *)key2) ? False : True; } void defaultPut(HashMap hashMap, void * key, void * value) { int index = hashMap->hashCode(hashMap, key); if (hashMap->list[index].key == NULL) { hashMap->size++; // 该地址为空时直接存储 hashMap->list[index].key = key; hashMap->list[index].value = value; } else { Entry current = &hashMap->list[index]; while (current!= NULL) { if (hashMap->equal(key, current->key)) { // 对于键值已经存在的直接覆盖 hashMap->list[index].value = value; return; } current = current->next; }; // 发生冲突则创建节点挂到相应位置的next上 Entry entry = newEntry(); entry->key = key; entry->value = value; entry->next = hashMap->list[index].next; hashMap->list[index].next = entry; hashMap->size++; } if (hashMap->size > hashMap->listSize) { Entry tempList = newEntryList(hashMap->size); Iterator iterator = createIterator(hashMap); int length = hashMap->size; for (int index = 0; hasNextIterator(iterator); index++) { // 迭代取出所有键值对 iterator = nextIterator(iterator); tempList[index].key = iterator->entry->key; tempList[index].value = iterator->entry->value; tempList[index].next = NULL; } freeIterator(iterator); // 清除原有键值对数据 hashMap->size = 0; for (int i = 0; i < hashMap->listSize; i++) { Entry current = &hashMap->list[i]; current->key = NULL; current->value = NULL; if (current->next != NULL) { while (current->next != NULL) { Entry temp = current->next->next; free(current->next); current->next = temp; } } } // 内存扩充至原来的两倍 // *注: 扩充时考虑的是当前存储元素数量与存储空间的大小关系,而不是存储空间是否已经存满, // 例如: 存储空间为10,存入了10个键值对,但是全部冲突了,所以存储空间空着9个,其余的全部挂在一个上面, // 这样检索的时候和遍历查询没有什么区别了,可以简单这样理解,当我存入第11个键值对的时候一定会发生冲突, // 这是由哈希函数本身的特性(取模)决定的,冲突就会导致检索变慢,所以这时候扩充存储空间,对原有键值对进行 // 再次散列,会把冲突的数据再次分散开,加快索引定位速度。 hashMap->listSize *= 2; Entry relist = (Entry)realloc(hashMap->list, hashMap->listSize * sizeof(struct entry)); if (relist != NULL) { hashMap->list = relist; relist = NULL; } // 初始化数据 for (int i = 0; i < hashMap->listSize; i++) { hashMap->list[i].key = NULL; hashMap->list[i].value = NULL; hashMap->list[i].next = NULL; } // 将所有键值对重新写入内存 for (int i = 0; i < length; i++) { hashMap->put(hashMap, tempList[i].key, tempList[i].value); } free(tempList); // 将新键值对写入 hashMap->put(hashMap, key, value); } } void * defaultGet(HashMap hashMap, void * key) { int index = hashMap->hashCode(hashMap, key); Entry entry = &hashMap->list[index]; while (entry->key != NULL && !hashMap->equal(entry->key, key)) { entry = entry->next; } return entry->value; } Boolean defaultRemove(HashMap hashMap, void * key) { int index = hashMap->hashCode(hashMap, key); Entry entry = &hashMap->list[index]; if (entry->key == NULL) { return False; } if (hashMap->equal(entry->key, key)) { hashMap->size--; if (entry->next != NULL) { entry->key = entry->next->key; entry->value = entry->next->value; entry->next = entry->next->next; free(entry->next); } else { entry->key = entry->value = NULL; } return True; } else { Entry p = entry; entry = entry->next; while (entry != NULL) { if (hashMap->equal(entry->key, key)) { hashMap->size--; p->next = entry->next; free(entry); return True; } p = entry; entry = entry->next; }; return False; } if (hashMap->exists(hashMap, key)) { } else { return False; } } Boolean defaultExists(HashMap hashMap, void * key) { int index = hashMap->hashCode(hashMap, key); Entry entry = &hashMap->list[index]; if (entry->key == NULL) { return False; } if (hashMap->equal(entry->key, key)) { return True; } if (entry->next != NULL) { do { if (hashMap->equal(entry->key, key)) { return True; } entry = entry->next; } while (entry != NULL); return False; } else { return False; } } void defaultClear(HashMap hashMap) { for (int i = 0; i < hashMap->listSize; i++) { // 释放冲突值内存 Entry entry = hashMap->list[i].next; while (entry != NULL) { Entry next = entry->next; free(entry); entry = next; } hashMap->list[i].next = NULL; } // 释放存储空间 free(hashMap->list); hashMap->list = NULL; hashMap->size = -1; hashMap->listSize = 0; } HashMap createHashMap(HashCode hashCode, Equal equal) { HashMap hashMap = newHashMap(); hashMap->size = 0; hashMap->listSize = 10; hashMap->hashCode = hashCode == NULL ? defaultHashCode : hashCode; hashMap->equal = equal == NULL ? defaultEqual : equal; hashMap->exists = defaultExists; hashMap->get = defaultGet; hashMap->put = defaultPut; hashMap->remove = defaultRemove; hashMap->clear = defaultClear; // 起始分配10个内存空间,溢出时会自动扩充 hashMap->list = newEntryList(hashMap->listSize); Entry p = hashMap->list; for (int i = 0; i < hashMap->listSize; i++) { p[i].key = p[i].value = p[i].next = NULL; } return hashMap; } Iterator createIterator(HashMap hashMap) { Iterator iterator = newIterator(); iterator->hashMap = hashMap; iterator->count = 0; iterator->hashCode = -1; iterator->entry = NULL; return iterator; } Boolean hasNextIterator(Iterator iterator) { return iterator->count < iterator->hashMap->size ? True : False; } Iterator nextIterator(Iterator iterator) { if (hasNextIterator(iterator)) { if (iterator->entry != NULL && iterator->entry->next != NULL) { iterator->count++; iterator->entry = iterator->entry->next; return iterator; } while (++iterator->hashCode < iterator->hashMap->listSize) { Entry entry = &iterator->hashMap->list[iterator->hashCode]; if (entry->key != NULL) { iterator->count++; iterator->entry = entry; break; } } } return iterator; } void freeIterator(Iterator iterator) { free(iterator); }
-
Array结构类型
未完待续…