[C.C++] 【C语言开源库】C语言必备实用第三方库Melon(包括数据结构算法)_c melon

363 0
Honkers 2025-5-23 10:48:51 来自手机 | 显示全部楼层 |阅读模式



既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

mln_string_nset
  1. mln_string_nset(pstr, s, n)
复制代码

描述:与mln_string_set功能一样,只是pstr所指向的mln_string_t仅记录了s的前n个字节。

返回值:无

举例:

  1. void foo()
  2. {
  3. char text[] = "hello world";
  4. mln_string_t s;
  5. mln\_string\_nset(&s, text, 5); //利用mln\_log的%S进行输出时,仅会输出hello
  6. }
复制代码
mln_string_ref
  1. mln_string_ref(pstr)
复制代码

描述:将pstr所指向的mln_string_t结构的ref成员累加1,用于直接引用pstr这个内存结构。在释放内存时,引用计数大于1时是不会实际释放内存的。

返回值:mln_string_t类型指针

  1. void foo(mln_string_t s)
  2. {
  3. mln_string_t \*ref = mln\_string\_ref(s); //此时ref与s的内存地址完全相同
  4. ...
  5. }
复制代码
mln_string_free
  1. mln_string_free(pstr)
复制代码

描述:释放ptrs所指向的mln_string_t结构内存,若ref大于1则仅递减引用计数,若data_ref为1,则不释放data成员指向的内存,否则释放data成员内存,随后释放pstr内存。释放时,会根据pool成员判断是释放回内存池,还是返还malloc库。

返回值:无

mln_string_new
  1. mln_string_t *mln_string_new(const char *s);
复制代码

描述:根据字符串常量s创建字符串结构,此时新字符串结构及其数据部分内存均由malloc库进行分配,并将s的内容拷贝进data成员中。

返回值:成功则返回mln_string_t指针,否则返回NULL。

mln_string_pool_new
  1. mln_string_t *mln_string_pool_new(mln_alloc_t *pool, const char *s);
复制代码

描述:与mln_string_new功能一致,仅内存是由pool所指向的内存池中分配而来。

返回值:成功则返回mln_string_t指针,否则返回NULL。

mln_string_dup
  1. mln_string_t *mln_string_dup(mln_string_t *str);
复制代码

描述:完全复制一份str,其内存均由malloc进行分配。

返回值:成功则返回mln_string_t指针,否则返回NULL。

mln_string_pool_dup
  1. mln_string_t *mln_string_pool_dup(mln_alloc_t *pool, mln_string_t *str);
复制代码

描述:与mln_string_dup功能一致,仅内存是从pool所指向的内存池中分配而来。

返回值:成功则返回mln_string_t指针,否则返回NULL。

mln_string_ndup
  1. mln_string_t *mln_string_ndup(mln_string_t *str, mln_s32_t size);
复制代码

描述:创建一个新字符串对象,并仅复制str中前size个字节数据。

返回值:成功则返回mln_string_t指针,否则返回NULL。

mln_string_const_ndup
  1. mln_string_t *mln_string_const_ndup(char *str, mln_s32_t size);
复制代码

描述:创建一个新字符串对象,并仅复制str中前size个字节数据。

返回值:成功则返回mln_string_t指针,否则返回NULL。

mln_string_ref_dup
  1. mln_string_t *mln_string_ref_dup(mln_string_t *str);
复制代码

描述:创建一个新的字符串结构,但结构中的data成员指向str中data成员所指向的地址,且新结构中data_ref会被置位。

返回值:成功则返回mln_string_t指针,否则返回NULL。

mln_string_const_ref_dup
  1. mln_string_t *mln_string_const_ref_dup(char *s);
复制代码

描述:创建一个新的字符串结构,但结构中的data成员指向s,且新结构中data_ref会被置位。

返回值:成功则返回mln_string_t指针,否则返回NULL。

mln_string_strseqcmp
  1. int mln_string_strseqcmp(mln_string_t *s1, mln_string_t *s2);
复制代码

描述:比较s1与s2的数据,如果短的一方刚好与长的一方的前面完全匹配,则长的一方大于短的一方。

返回值:

  • -1 - s1比s2小
  • 1 - s1比s2大
  • 0 - 二者相同

举例:

  1. int main(void)
  2. {
  3. mln_string_t s1 = mln\_string("abcd");
  4. mln_string_t s2 = mln\_string("abcdefg");
  5. printf("%d", mln\_string\_strseqcmp(&s1, &s2)); //-1
  6. return 0;
  7. }
复制代码
mln_string_strcmp
  1. int mln_string_strcmp(mln_string_t *s1, mln_string_t *s2);
复制代码

描述:比较s1与s2中数据的大小。

返回值:

  • -1 - s1比s2小
  • 1 - s1比s2大
  • 0 - 二者相同
mln_string_const_strcmp
  1. int mln_string_const_strcmp(mln_string_t *s1, char *s2);
复制代码

描述:比较s1所记录的数据与s2的大小。

返回值:

  • -1 - s1比s2小
  • 1 - s1比s2大
  • 0 - 二者相同
mln_string_strncmp
  1. int mln_string_strncmp(mln_string_t *s1, mln_string_t *s2, mln_u32_t n);
复制代码

描述:比较s1与s2的前n个字节的大小。

返回值:

  • -1 - s1比s2小
  • 1 - s1比s2大
  • 0 - 二者相同
mln_string_const_strncmp
  1. int mln_string_const_strncmp(mln_string_t *s1, char *s2, mln_u32_t n);
复制代码

描述:比较s1所记录的数据与s2的前n个字节的大小。

返回值:

  • -1 - s1比s2小
  • 1 - s1比s2大
  • 0 - 二者相同
mln_string_strcasecmp
  1. int mln_string_strcasecmp(mln_string_t *s1, mln_string_t *s2);
复制代码

描述:比较s1与s2数据的大小,且忽略大小写。

返回值:

  • -1 - s1比s2小
  • 1 - s1比s2大
  • 0 - 二者相同
mln_string_const_strcasecmp
  1. int mln_string_const_strcasecmp(mln_string_t *s1, char *s2);
复制代码

描述:比较s1所记录的数据与s2的大小,且忽略大小写。

返回值:

  • -1 - s1比s2小
  • 1 - s1比s2大
  • 0 - 二者相同
mln_string_const_strncasecmp
  1. int mln_string_const_strncasecmp(mln_string_t *s1, char *s2, mln_u32_t n);
复制代码

描述:比较s1所记录的数据与s2的前n个字节的大小,且忽略大小写。

返回值:

  • -1 - s1比s2小
  • 1 - s1比s2大
  • 0 - 二者相同
mln_string_strncasecmp
  1. int mln_string_strncasecmp(mln_string_t *s1, mln_string_t *s2, mln_u32_t n);
复制代码

描述:比较s1与s2所记录数据的前n个字节的大小,且忽略大小写。

返回值:

  • -1 - s1比s2小
  • 1 - s1比s2大
  • 0 - 二者相同
mln_string_strstr
  1. char *mln_string_strstr(mln_string_t *text, mln_string_t *pattern);
复制代码

描述:匹配text所记录的数据中与pattern中数据一样的起始地址。

返回值:若匹配成功,则返回text的data成员所指向地址中的对应地址;否则返回NULL。

mln_string_const_strstr
  1. char *mln_string_const_strstr(mln_string_t *text, char *pattern);
复制代码

描述:匹配text所记录的数据中与pattern一样的起始地址。

返回值:若匹配成功,则返回text的data成员所指向地址中的对应地址;否则返回NULL。

mln_string_new_strstr
  1. mln_string_t *mln_string_new_strstr(mln_string_t *text, mln_string_t *pattern);
复制代码

描述:与mln_string_strstr功能一致,但返回的是由mln_string_t结构包装后的字符串。

返回值:成功则返回mln_string_t指针,否则返回NULL。

mln_string_new_const_strstr
  1. mln_string_t *mln_string_new_const_strstr(mln_string_t *text, char *pattern);
复制代码

描述:与mln_string_const_strstr功能一致,但返回的是由mln_string_t结构包装后的字符串。

返回值:成功则返回mln_string_t指针,否则返回NULL。

mln_string_kmp
  1. char *mln_string_kmp(mln_string_t *text, mln_string_t *pattern);
复制代码

描述:与mln_string_strstr功能一致,但是是由KMP算法实现的。KMP算法适用场景是,text中有较多与pattern前缀相同的字符串的情况。例如: text中包含aaaaaaaaaabc,pattern中包含ab,此时,KMP算法性能将高于朴素算法。

返回值:若匹配成功,则返回text的data成员所指向地址中的对应地址;否则返回NULL。

mln_string_const_kmp
  1. char *mln_string_const_kmp(mln_string_t *text, char *pattern);
复制代码

描述:与mln_string_kmp功能一致,但pattern为字符指针类型。

返回值:若匹配成功,则返回text的data成员所指向地址中的对应地址;否则返回NULL。

mln_string_new_kmp
  1. mln_string_t *mln_string_new_kmp(mln_string_t *text, mln_string_t *pattern);
复制代码

描述:与mln_string_kmp功能一致,但返回的是由mln_string_t结构包装后的数据。

返回值:成功则返回mln_string_t指针,失败则返回NULL。

mln_string_new_const_kmp
  1. mln_string_t *mln_string_new_const_kmp(mln_string_t *text, char *pattern);
复制代码

描述:与mln_string_const_kmp功能一致,但返回的是由mln_string_t结构包装后的数据。

返回值:成功则返回mln_string_t指针,失败则返回NULL。

mln_string_slice
  1. mln_string_t *mln_string_slice(mln_string_t *s, const char *sep_array/*ended by \0*/);
复制代码

描述:seq_array是一个字符数组且以0结尾,该数组的每一个字符都是一个分隔标志。函数会扫描s的数据部分,当数据中遇到seq_array中的任意一个字符时都会被进行分割,连续遇到多个时仅分割一次,且分割后,分隔符不会出现在被分割后的字符串中。

返回值:成功则返回mln_string_t数组,否则返回NULL。数组的最后一个元素的len为0,且data为NULL。

举例:

  1. int main(void)
  2. {
  3. mln_string_t s = mln\_string("abc-def-=ghi");
  4. mln_string_t \*str, \*arr = mln\_string\_slice(&s, "-=");
  5. for (str = arr; str->data != NULL; ++str) {
  6. mln\_log(debug, "%S", str);
  7. }
  8. mln\_string\_slice\_free(arr);
  9. return 0;
  10. }
复制代码
mln_string_slice_free
  1. void mln_string_slice_free(mln_string_t *array);
复制代码

描述:释放由mln_string_slice函数创建的mln_string_t数组。

返回值:无

mln_string_strcat
  1. mln_string_t *mln_string_strcat(mln_string_t *s1, mln_string_t *s2);
复制代码

描述:创建一个新的mln_string_t结构,其数据为s1和s2依此顺序拼接后的结果。

返回值:成功则返回mln_string_t指针,否则返回NULL。

mln_string_pool_strcat
  1. mln_string_t *mln_string_pool_strcat(mln_alloc_t *pool, mln_string_t *s1, mln_string_t *s2);
复制代码

描述:与mln_string_strcat功能一致,仅新的结构所使用内存由pool指向的内存池分配。

返回值:成功则返回mln_string_t指针,否则返回NULL。

双向链表

头文件
  1. #include "mln_defs.h"
复制代码
函数/宏
MLN_CHAIN_FUNC_DECLARE
  1. MLN_CHAIN_FUNC_DECLARE(prefix,type,ret_attr,func_attr);
复制代码

描述:本宏用于对双向链表的添加操作和删除操作函数进行声明,其中:

  • prefix:为两个函数名的前缀,这是为了允许在一个源文件内为多个双向链表进行函数声明。
  • type:链表节点的类型
  • ret_attr:两个函数的操作域类型和返回值类型
  • func_attr:对函数参数的约束(仅限于Linux中),若无则留空即可
MLN_CHAIN_FUNC_DEFINE
  1. MLN_CHAIN_FUNC_DEFINE(prefix,type,ret_attr,prev_ptr,next_ptr);
  2. ret_attr prefix##_chain_add(type **head, type **tail, type *node);
  3. ret_attr prefix##_chain_del(type **head, type **tail, type *node);
复制代码

描述:本宏用于定义双向链表的添加和删除操作函数,其中:

  • prefix:为两个函数名的前缀,这是为了允许在一个源文件内为多个双向链表进行函数声明。
  • type:链表节点的类型
  • ret_attr:两个函数的操作域类型和返回值类型
  • prev_ptr:链表节点中指向前一节点的指针名
  • next_ptr:链表节点中指向后一节点的指针名

chain_add和chain_del分别为添加和删除节点函数,两个函数的参数为:

  • head:二级指针,用于在操作函数内对头指针自动修改
  • tail:二级指针,用于在操作函数内对尾指针自动修改
  • node:被加入的节点指针,其前后指向的指针可能会被修改
示例
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include "mln\_defs.h"
  4. typedef struct chain_s {
  5. int val;
  6. struct chain_s \*prev;
  7. struct chain_s \*next;
  8. } chain_t;
  9. MLN\_CHAIN\_FUNC\_DECLARE(test, chain_t, static inline void, );
  10. MLN\_CHAIN\_FUNC\_DEFINE(test, chain_t, static inline void, prev, next);
  11. int main(void)
  12. {
  13. int i;
  14. chain_t \*head = NULL, \*tail = NULL, \*c;
  15. for (i = 0; i < 10; ++i) {
  16. c = (chain_t \*)malloc(sizeof(chain_t));
  17. if (c == NULL) {
  18. fprintf(stderr, "malloc failed.\n");
  19. return -1;
  20. }
  21. c->val = i;
  22. c->prev = c->next = NULL;
  23. test\_chain\_add(&head, &tail, c);
  24. }
  25. for (c = head; c != NULL; c = c->next) {
  26. printf("%d\n", c->val);
  27. }
  28. return 0;
  29. }
复制代码

头文件
  1. #include "mln_stack.h"
复制代码
函数/宏
mln_stack_init
  1. mln_stack_t \*mln\_stack\_init(struct mln_stack_attr \*attr);
  2. struct mln_stack_attr {
  3. stack_free free_handler;//栈节点数据释放函数
  4. stack_copy copy_handler;//栈节点数据复制函数
  5. mln_u32_t cache:1;//是否缓存栈节点结构
  6. };
  7. typedef void (\*stack_free)(void \*);
  8. typedef void \*(\*stack_copy)(void \*, void \*);
复制代码

描述:

初始化栈结构。

free_handler:是入栈数据的释放函数,由于入栈数据可能为自定义数据结构,因此若需释放,可对此进行设置否则置NULL。

copy_handler:复制栈节点数据。

cache:是否缓存全部栈节点结构内存以提升效率(非用户数据)。

stack_free的参数为用户自定义数据的数据结构指针。

stack_copy的参数分别为:被复制的栈节点数据的数据结构指针 和 mln_stack_dup函数的第二个参数(即用户自定义数据),这个回调函数仅在mln_stack_dup函数中被调用。

返回值:成功则返回栈指针,否则为NULL

mln_stack_destroy
  1. void mln_stack_destroy(mln_stack_t *st);
复制代码

描述:销毁栈结构,并释放栈节点内数据资源。

返回值:无

mln_stack_push
  1. int mln_stack_push(mln_stack_t *st, void *data);
复制代码

描述:将数据data压入栈st中。

返回值:成功返回0,否则返回-1

mln_stack_pop
  1. void *mln_stack_pop(mln_stack_t *st);
复制代码

描述:将栈st的栈顶元素数据弹出。

返回值:若栈内无元素则为NULL,否则为栈节点内的数据指针

mln_stack_empty
  1. mln_stack_empty(s)
复制代码

描述:判断栈是否为空。

返回值:空为非0,否则为0

mln_stack_top
  1. mln_stack_top(st)
复制代码

描述:获取栈顶元素数据。

返回值:若栈st为空则返回NULL,否则为栈顶节点内的数据指针

mln_stack_dup
  1. mln_stack_t *mln_stack_dup(mln_stack_t *st, void *udata);
复制代码

描述:完全复制栈st。udata为用户提供的额外数据。

返回值:若成功则返回新栈指针,否则返回NULL

mln_stack_scan_all
  1. int mln_stack_scan_all(mln_stack_t *st, stack_scan scanner, void *data);
  2. typedef int (*stack_scan)(void *, void *);
复制代码

描述:

从栈顶向栈底遍历栈st的每一个栈内元素数据。scanner为数据访问函数,data为遍历时的额外用户数据。

stack_scan有两个参数,分别为:栈节点内数据指针 和 data参数。

返回值:

  • mln_stack_scan_all:全部遍历完则返回0,否则返回-1
  • stack_scan:若想中断遍历则返回小于0的值,否则返回值大于等于0

队列

头文件
  1. #include "mln_queue.h"
复制代码
函数/宏
mln_queue_init
  1. mln_queue_t \*mln\_queue\_init(struct mln_queue_attr \*attr);
  2. struct mln_queue_attr {
  3. mln_uauto_t qlen; //队列长度
  4. queue_free free_handler; //队列节点数据的释放函数
  5. };
  6. typedef void (\*queue_free)(void \*);
复制代码

描述:创建队列。

本队列为固定长度队列,因此attr.qlen就是队列的长度。free_handler为释放函数,用于释放队列内每个成员中的数据。若不需要释放则置NULL即可。

释放函数的参数即为队列每个成员的数据结构指针。

返回值:成功则返回mln_queue_t类型的队列指针,失败则返回NULL

mln_queue_destroy
  1. void mln_queue_destroy(mln_queue_t *q);
复制代码

描述:销毁队列。

队列销毁时,会根据free_handler的设置而自动释放队列成员的数据。

返回值:无

mln_queue_append
  1. int mln_queue_append(mln_queue_t *q, void *data);
复制代码

描述:将数据data追加进队列q的末尾。

返回值:若队列已满则返回-1,成功返回0

mln_queue_get
  1. void *mln_queue_get(mln_queue_t *q);
复制代码

描述:获取队首成员的数据。

返回值:成功则返回数据指针,若队列为空则返回NULL

mln_queue_remove
  1. void mln_queue_remove(mln_queue_t *q);
复制代码

描述:删除队首元素,但不释放资源。

返回值:无

mln_queue_search
  1. void *mln_queue_search(mln_queue_t *q, mln_uauto_t index);
复制代码

描述:查找并返回从队列q队首开始的第index成员的数据,下标从0开始。

返回值:成功则返回数据指针,否则为NULL

mln_queue_free_index
  1. void mln_queue_free_index(mln_queue_t *q, mln_uauto_t index);
复制代码

描述:释放队列q内指定下标index的成员,并根据free_handler释放其数据。

返回值:无

mln_queue_scan_all
  1. int mln_queue_scan_all(mln_queue_t *q, queue_scan scan_handler, void *udata);
  2. typedef int (*queue_scan)(void *, void *);
复制代码

描述:遍历每一个队列成员。

udata为辅助遍历的自定义结构指针,若不需要可置NULL。

scan_handler的两个参数分别为:成员数据,udata。

返回值:遍历完成返回0,被中断则返回-1

mln_queue_empty
  1. mln_queue_empty(q)
复制代码

描述:判断队列q是否为空队列。

返回值:空则为非0,否则为0

mln_queue_full
  1. mln_queue_full(q)
复制代码

描述:判断队列是否已满。

返回值:满则为非0,否则为0

mln_queue_length
  1. mln_queue_length(q)
复制代码

描述:获取队列q的总长度。

返回值:无符号整型长度值

mln_queue_element
  1. mln_queue_element(q)
复制代码

描述:获取队列q中当前的成员数量。

返回值:无符号整型数量值

示例
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include "mln\_core.h"
  4. #include "mln\_log.h"
  5. #include "mln\_queue.h"
  6. int main(int argc, char \*argv[])
  7. {
  8. int i = 10;
  9. mln_queue_t \*q;
  10. struct mln_queue_attr qattr;
  11. struct mln_core_attr cattr;
  12. cattr.argc = argc;
  13. cattr.argv = argv;
  14. cattr.global_init = NULL;
  15. cattr.worker_process = NULL;
  16. if (mln\_core\_init(&cattr) < 0) {
  17. fprintf(stderr, "init failed\n");
  18. return -1;
  19. }
  20. qattr.qlen = 10;
  21. qattr.free_handler = NULL;
  22. q = mln\_queue\_init(&qattr);
  23. if (q == NULL) {
  24. mln\_log(error, "queue init failed.\n");
  25. return -1;
  26. }
  27. mln\_queue\_append(q, &i);
  28. mln\_log(debug, "%d\n", \*(int \*)mln\_queue\_get(q));
  29. mln\_queue\_destroy(q);
  30. return 0;
  31. }
复制代码

内存池

Melon中,内存池分为两类:

  • 堆内存
  • 共享内存

其中,共享内存内存池只允许主子进程之间共享数据(兄弟进程之间也共享)。即使用时,由主进程创建共享内存内存池,然后创建子进程。

头文件

  1. #include "mln_alloc.h"
复制代码

函数

mln_alloc_init

  1. mln_alloc_t *mln_alloc_init(void);
复制代码

描述:创建堆内存内存池。

返回值:成功则返回内存池结构指针,否则返回NULL

mln_alloc_shm_init

  1. mln_alloc_t *mln_alloc_shm_init(mln_size_t size);
复制代码

描述:创建共享内存内存池。本池建立时需要给出池大小size(单位字节),一旦创建完毕后则后续无法再扩大。

返回值:成功则返回内存池结构指针,否则返回NULL

mln_alloc_destroy

  1. void mln_alloc_destroy(mln_alloc_t *pool);
复制代码

描述:销毁内存池。销毁操作会将内存池中管理的所有内存进行统一释放。

返回值:无

mln_alloc_m

  1. void *mln_alloc_m(mln_alloc_t *pool, mln_size_t size);
复制代码

描述:从内存池pool中分配一个size大小的内存。如果内存池是共享内存内存池,则会从共享内存中进行分配,否则从堆内存中进行分配。

返回值:成功则返回内存起始地址,否则返回NULL

mln_alloc_c

  1. void *mln_alloc_c(mln_alloc_t *pool, mln_size_t size);
复制代码

描述:从内存池pool中分配一个size大小的内存,且该内存会被清零。

返回值:成功则返回内存起始地址,否则返回NULL

mln_alloc_re

  1. void *mln_alloc_re(mln_alloc_t *pool, void *ptr, mln_size_t size);
复制代码

描述:从内存池pool中分配一个size大小的内存,并将ptr指向的内存中的数据拷贝到新的内存中。

ptr必须为内存池分配的内存起始地址。若size为0,ptr指向的内存会被释放。

返回值:成功则返回内存起始地址,否则返回NULL

mln_alloc_free

  1. void mln_alloc_free(void *ptr);
复制代码

描述:释放ptr指向的内存。注意:ptr必须为分配函数返回的地址,而不可以是分配的内存中某一个位置。

返回值:无

mln_alloc_shm_rdlock

  1. int mln_alloc_shm_rdlock(mln_alloc_t *pool);
复制代码

描述:读锁定。本函数会等待直到锁资源可用,并将之锁定。

本函数及后续锁相关函数均用于共享内存内存池。

出于对读多写少的场景考虑,给共享内存配备的是读写锁,而非互斥锁。

返回值:成功返回0,否则返回非0

mln_alloc_shm_tryrdlock

  1. int mln_alloc_shm_tryrdlock(mln_alloc_t *pool);
复制代码

描述:尝试读锁定。本函数不会挂起等待锁资源可用。

返回值:成功返回0,否则返回非0

mln_alloc_shm_wrlock

  1. int mln_alloc_shm_wrlock(mln_alloc_t *pool);
复制代码

描述:写锁定。本函数会等待直到锁资源可用,并将之锁定。

返回值:成功返回0,否则返回非0

mln_alloc_shm_trywrlock

  1. int mln_alloc_shm_trywrlock(mln_alloc_t *pool);
复制代码

描述:尝试写锁定。本函数不会挂起等待锁资源可用。

返回值:成功返回0,否则返回非0

mln_alloc_shm_unlock

  1. int mln_alloc_shm_unlock(mln_alloc_t *pool);
复制代码

描述:解除锁定。

返回值:成功返回0,否则返回非0

示例

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include "mln\_core.h"
  4. #include "mln\_log.h"
  5. #include "mln\_alloc.h"
  6. int main(int argc, char \*argv[])
  7. {
  8. char \*p;
  9. mln_alloc_t \*pool;
  10. struct mln_core_attr cattr;
  11. cattr.argc = argc;
  12. cattr.argv = argv;
  13. cattr.global_init = NULL;
  14. cattr.worker_process = NULL;
  15. if (mln\_core\_init(&cattr) < 0) {
  16. fprintf(stderr, "init failed\n");
  17. return -1;
  18. }
  19. pool = mln\_alloc\_init();
  20. if (pool == NULL) {
  21. mln\_log(error, "pool init failed\n");
  22. return -1;
  23. }
  24. p = (char \*)mln\_alloc\_m(pool, 6);
  25. if (p == NULL) {
  26. mln\_log(error, "alloc failed\n");
  27. return -1;
  28. }
  29. memcpy(p, "hello", 5);
  30. p[5] = 0;
  31. mln\_log(debug, "%s\n", p);
  32. mln\_alloc\_free(p);
  33. return 0;
  34. }
复制代码

线程池

在Melon中支持两种多线程模式,线程池是其中一种,另一种请参见后续的多线程框架文章。

注意:在每个进程中仅允许存在一个线程池。

头文件
  1. #include "mln_thread_pool.h"
复制代码
函数
mln_thread_pool_run
  1. int mln\_thread\_pool\_run(struct mln_thread_pool_attr \*tpattr);
  2. struct mln_thread_pool_attr {
  3. void \*main_data;
  4. mln_thread_process child_process_handler;
  5. mln_thread_process main_process_handler;
  6. mln_thread_dataFree free_handler;
  7. mln_u64_t cond_timeout; /\*ms\*/
  8. mln_u32_t max;
  9. mln_u32_t concurrency;
  10. };
  11. typedef int (\*mln_thread_process)(void \*);
  12. typedef void (\*mln_thread_dataFree)(void \*);
复制代码

描述:创建并运行内存池。

线程池由主线程进行管理和做一部分处理后下发任务,子线程组则接受任务进行处理。

初始状态下,是不存在子线程的,当有任务需要下发时会自动创建子线程。当任务处理完后,子线程会延迟释放,避免频繁分配释放资源。

其中参数结构体的每个成员含义如下:

  • main_data 为主线程的用户自定义数据。
  • child_process_handler 每个子线程的处理函数,该函数有一个参数为主线程下发任务时给出的数据结构指针,返回值为0表示处理正常,非0表示处理异常,异常时会有日志输出。
  • main_process_handler 主线程的处理函数,该函数有一个参数为main_data,返回值为0表示处理正常,非0表示处理异常,异常时会有日志输出。一般情况下,主线程处理函数不应随意自行返回,一旦返回代表线程池处理结束,线程池会被销毁
  • free_handler 为资源释放函数。其资源为主线程下发给子线程的数据结构指针所指向的内容。
  • cond_timeout为闲置子线程回收定时器,单位为毫秒。当子线程无任务处理,且等待时间超过该定时器时长后,会自行退出。
  • max线程池允许的最大子线程数量。
  • concurrency用于pthread_setconcurrency设置并行级别参考值,但部分系统并为实现该功能,因此不应该过多依赖该值。在Linux下,该值设为零表示交由本系统实现自行确定并行度。

返回值:本函数返回值与主线程处理函数的返回值保持一致

mln_thread_pool_addResource
  1. int mln_thread_pool_addResource(void *data);
复制代码

描述:将资源data放入到资源池中。本函数仅应由主线程调用,用于主线程向子线程下发任务所用。

返回值:成功则返回0,否则返回非0

mln_thread_quit
  1. void mln_thread_quit(void);
复制代码

描述:本函数用于告知线程池,关闭并销毁线程池。

返回值:无

mln_thread_ResourceInfo
  1. void mln\_thread\_ResourceInfo(struct mln_thread_pool_info \*info);
  2. struct mln_thread_pool_info {
  3. mln_u32_t max_num;
  4. mln_u32_t idle_num;
  5. mln_u32_t cur_num;
  6. mln_size_t res_num;
  7. };
复制代码

描述:获取当前线程池信息。信息会写入参数结构体中,结构体每个参数含义如下:

  • max_num:线程池最大子线程数量
  • idle_num:当前闲置子线程数量
  • cur_num:当前子线程数量(包含闲置和工作中的子线程)
  • res_num:当前尚未被处理的资源数量

返回值:无

示例
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include "mln\_core.h"
  5. #include "mln\_thread\_pool.h"
  6. #include "mln\_log.h"
  7. static int main\_process\_handler(void \*data);
  8. static int child\_process\_handler(void \*data);
  9. static void free\_handler(void \*data);
  10. int main(int argc, char \*argv[])
  11. {
  12. struct mln_core_attr cattr;
  13. struct mln_thread_pool_attr tpattr;
  14. cattr.argc = argc;
  15. cattr.argv = argv;
  16. cattr.global_init = NULL;
  17. cattr.worker_process = NULL;
  18. if (mln\_core\_init(&cattr) < 0) {
  19. return -1;
  20. }
  21. tpattr.dataForMain = NULL;
  22. tpattr.child_process_handler = child_process_handler;
  23. tpattr.main_process_handler = main_process_handler;
  24. tpattr.free_handler = free_handler;
  25. tpattr.condTimeout = 10;
  26. tpattr.max = 10;
  27. tpattr.concurrency = 10;
  28. return mln\_thread\_pool\_run(&tpattr);
  29. }
  30. static int child\_process\_handler(void \*data)
  31. {
  32. mln\_log(none, "%s\n", (char \*)data);
  33. return 0;
  34. }
  35. static int main\_process\_handler(void \*data)
  36. {
  37. int n;
  38. char \*text;
  39. while (1) {
  40. if ((text = (char \*)malloc(16)) == NULL) {
  41. return -1;
  42. }
  43. n = snprintf(text, 15, "hello world");
  44. text[n] = 0;
  45. mln\_thread\_pool\_addResource(text);
  46. usleep(1000);
  47. }
  48. }
  49. static void free\_handler(void \*data)
  50. {
  51. free(data);
  52. }
复制代码

JSON

头文件
  1. #include "mln_json.h"
复制代码
函数/宏
mln_json_new
  1. mln_json_t *mln_json_new(void);
复制代码

描述:新建json节点,用于生成json字符串之用。

返回值:成功则返回mln_json_t指针,否则返回NULL

mln_json_parse
  1. mln_json_t *mln_json_parse(mln_string_t *jstr);
复制代码

描述:将JSON字符串jstr解析成数据结构。

返回值:成功则返回mln_json_t指针,否则返回NULL

mln_json_free
  1. void mln_json_free(void *json);
复制代码

描述:释放mln_json_t类型的json节点内存。

返回值:无

mln_json_dump
  1. void mln_json_dump(mln_json_t *j, int n_space, char *prefix);
复制代码

描述:将json节点j的详细信息输出到标准输出。n_space表示当前缩进空格数,prefix为输出内容的前缀。

返回值:无

mln_json_generate
  1. mln_string_t *mln_json_generate(mln_json_t *j);
复制代码

描述:由mln_json_t节点结构生成JSON字符串。

返回值:成功返回mln_string_t字符串指针,否则返回NULL

mln_json_search_value
  1. mln_json_t *mln_json_search_value(mln_json_t *j, mln_string_t *key);
复制代码

描述:从节点j中搜索key为key的value内容。此时,j必须为对象类型(有key: value对的字典)。

返回值:成功则返回mln_json_t类型的value,否则返回NULL

mln_json_search_element
  1. mln_json_t *mln_json_search_element(mln_json_t *j, mln_uauto_t index);
复制代码

描述:从节点j中搜索下标为index的元素内容。此时,j必须为数组类型。

返回值:成功则返回mln_json_t类型的元素节点,否则返回NULL

mln_json_get_array_length
  1. mln_uauto_t mln_json_get_array_length(mln_json_t *j);
复制代码

描述:获取数组的长度。此时j必须为数组类型。

返回值:数组长度

mln_json_update_obj
  1. int mln_json_update_obj(mln_json_t *j, mln_json_t *key, mln_json_t *val);
复制代码

描述:将key与val对添加到j JSON节点中。此时,j需为对象类型。若key已经存在,则将原本value替换为val。

返回值:成功则返回0,否则返回-1

mln_json_add_element
  1. int mln_json_add_element(mln_json_t *j, mln_json_t *value);
复制代码

描述:将value加入到数组类型的JSON结构j中。

返回值:成功则返回0,否则返回-1

mln_json_update_element
  1. int mln_json_update_element(mln_json_t *j, mln_json_t *value, mln_uauto_t index);
复制代码

描述:将value更新到数组类型JSON结构j的下标为index的位置上。

返回值:成功则返回0,否则返回-1

mln_json_reset
  1. void mln_json_reset(mln_json_t *j);
复制代码

描述:重置JSON节点j数据结构,将其内存进行释放。

返回值:无

mln_json_remove_object
  1. mln_json_t *mln_json_remove_object(mln_json_t *j, mln_string_t *key);
复制代码

描述:将key值为key的键值对从对象类型的JSON结构j中删除,并将相应value返回。

返回值:存在则返回对应value部分的JSON节点,否则返回NULL

mln_json_remove_element
  1. mln_json_t *mln_json_remove_element(mln_json_t *j, mln_uauto_t index);
复制代码

描述:将下标为index的元素从数组类型JSON节点上删除并返回。

返回值:存在则返回元素指针,否则返回NULL

is_type
  1. M\_JSON\_IS\_OBJECT(json)
  2. M\_JSON\_IS\_ARRAY(json)
  3. M\_JSON\_IS\_STRING(json)
  4. M\_JSON\_IS\_NUMBER(json)
  5. M\_JSON\_IS\_TRUE(json)
  6. M\_JSON\_IS\_FALSE(json)
  7. M\_JSON\_IS\_NULL(json)
  8. M\_JSON\_IS\_NONE(json)
复制代码

描述:判断mln_json_t结构的json类型,依次分别为:对象、数组、字符串、数字、布尔真、布尔假、NULL、无类型。

返回值:满足条件返回非0,否则返回0

set_type
  1. M\_JSON\_SET\_TYPE\_NONE(json)
  2. M\_JSON\_SET\_TYPE\_OBJECT(json)
  3. M\_JSON\_SET\_TYPE\_ARRAY(json)
  4. M\_JSON\_SET\_TYPE\_STRING(json)
  5. M\_JSON\_SET\_TYPE\_NUMBER(json)
  6. M\_JSON\_SET\_TYPE\_TRUE(json)
  7. M\_JSON\_SET\_TYPE\_FALSE(json)
  8. M\_JSON\_SET\_TYPE\_NULL(json)
复制代码

描述:给mln_json_t类型的json节点设置类型,依次分别为:无类型、对象、数组、字符串、数字、布尔真、布尔假、NULL。

返回值:无

get_data
  1. M\_JSON\_GET\_DATA\_OBJECT(json)
  2. M\_JSON\_GET\_DATA\_ARRAY(json)
  3. M\_JSON\_GET\_DATA\_STRING(json)
  4. M\_JSON\_GET\_DATA\_NUMBER(json)
  5. M\_JSON\_GET\_DATA\_TRUE(json)
  6. M\_JSON\_GET\_DATA\_FALSE(json)
  7. M\_JSON\_GET\_DATA\_NULL(json)
复制代码

描述:获取mln_json_t类型的json节点中对应类型的数据部分。类型依次为:对象、数组、字符串、数字、布尔真、布尔假、NULL。

返回值:

  • 对象类型为mln_hash_t类型指针
  • 数组类型为mln_rbtree_t类型指针
  • 字符串类型为mln_string_t类型指针
  • 数字类型为double类型值
  • 布尔真为mln_u8_t类型值
  • 布尔假为mln_u8_t类型值
  • NULL类型为mln_u8ptr_t类型的NULL值
set_data
  1. M_JSON_SET_DATA_STRING(json,str)
  2. M_JSON_SET_DATA_NUMBER(json,num)
  3. M_JSON_SET_DATA_TRUE(json)
  4. M_JSON_SET_DATA_FALSE(json)
  5. M_JSON_SET_DATA_NULL(json)
复制代码

描述:给不同类型的JSON节点json设置数据值。对象和数组类型分别使用哈希表和红黑树函数进行操作,其余类型用上述宏进行设置。

注意:这里设置的字符串必须是从内存池或堆中分配的内存,栈中内存会出现段错误,因为赋值时不会在宏内自动复制一份而是直接使用。

返回值:无

M_JSON_SET_INDEX
  1. M_JSON_SET_INDEX(json,i)
复制代码

描述:设置mln_json_t类型节点json的下标为index。该宏用于生成JSON字符串中数组的部分。

返回值:无

示例
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include "mln\_core.h"
  4. #include "mln\_log.h"
  5. #include "mln\_string.h"
  6. #include "mln\_json.h"
  7. int main(int argc, char \*argv[])
  8. {
  9. mln_json_t \*j = NULL, \*key = NULL, \*val = NULL;
  10. mln_string_t s1 = mln\_string("name");
  11. mln_string_t s2 = mln\_string("Tom");
  12. mln_string_t \*res;
  13. struct mln_core_attr cattr;
  14. cattr.argc = argc;
  15. cattr.argv = argv;
  16. cattr.global_init = NULL;
  17. cattr.worker_process = NULL;
  18. if (mln\_core\_init(&cattr) < 0) {
  19. fprintf(stderr, "init failed\n");
  20. return -1;
  21. }
  22. key = mln\_json\_new();
  23. if (key == NULL) {
  24. mln\_log(error, "init key failed\n");
  25. goto err;
  26. }
  27. M\_JSON\_SET\_TYPE\_STRING(key);
  28. M\_JSON\_SET\_DATA\_STRING(key, mln\_string\_dup(&s1));//注意,一定是要自行分配内存,不可直接使用栈中内存
  29. val = mln\_json\_new();
  30. if (val == NULL) {
  31. mln\_log(error, "init val failed\n");
  32. goto err;
  33. }
  34. M\_JSON\_SET\_TYPE\_STRING(val);
  35. M\_JSON\_SET\_DATA\_STRING(val, mln\_string\_dup(&s2));//注意,一定是要自行分配内存,不可直接使用栈中内存
  36. j = mln\_json\_new();
  37. if (j == NULL) {
  38. mln\_log(error, "init object failed\n");
  39. goto err;
  40. }
  41. if (mln\_json\_update\_obj(j, key, val) < 0) {
  42. mln\_log(error, "update object failed\n");
  43. goto err;
  44. }
  45. key = val = NULL;
  46. res = mln\_json\_generate(j);
  47. mln\_json\_free(j);
  48. if (res == NULL) {
  49. mln\_log(error, "generate failed\n");
  50. goto err;
  51. }
  52. mln\_log(debug, "%S\n", res);
  53. j = mln\_json\_parse(res);
  54. mln\_string\_free(res);
  55. mln\_json\_dump(j, 0, NULL);
  56. mln\_json\_free(j);
  57. return 0;
  58. err:
  59. if (j != NULL) mln\_json\_free(j);
  60. if (key != NULL) mln\_json\_free(key);
  61. if (val != NULL) mln\_json\_free(val);
  62. return -1;
  63. }
复制代码

HTTP

头文件
  1. #include "mln_http.h"
复制代码
函数/宏
mln_http_init
  1. mln_http_t *mln_http_init(mln_tcp_conn_t *connection, void *data, mln_http_handler body_handler);
  2. typedef int (*mln_http_handler)(mln_http_t *, mln_chain_t **, mln_chain_t **);
复制代码

描述:创建并初始化mln_http_t结构。connection是TCP结构,内含TCP套接字。data为体处理函数的用户自定义数据部分,用于辅助请求或响应体的处理。body_handler是体处理函数,该函数会在每次调用mln_http_parse或mln_http_generate函数时被调用。体处理函数有三个参数,分别为:http结构,用于解析或生成HTTP报文的双向链表的头和尾节点。

返回值:成功则返回mln_http_t结构指针,否则返回NULL

mln_http_destroy
  1. void mln_http_destroy(mln_http_t *http);
复制代码

描述:销毁http结构并释放资源。

返回值:无

mln_http_reset
  1. void mln_http_reset(mln_http_t *http);
复制代码

描述:重置http结构,但不会将结构释放,可用于下一次处理。

返回值:无

mln_http_parse
  1. int mln_http_parse(mln_http_t *http, mln_chain_t **in);
复制代码

描述:用于解析HTTP报文,并将解析的结果写入http中。

返回值:

  • M_HTTP_RET_DONE 解析完成
  • M_HTTP_RET_OK 解析未完成但未出错,继续传入新的数据使解析完成
  • M_HTTP_RET_ERROR 解析失败
mln_http_generate
  1. int mln_http_generate(mln_http_t *http, mln_chain_t **out_head, mln_chain_t **out_tail);
复制代码

描述:将http中HTTP相关信息生成HTTP报文。报文可能不会一次性生成完全,因此可以多次调用。已生成的报文将会存放在out_head和out_tail指定的双向链表中。

返回值:

  • M_HTTP_RET_DONE 生成完成
  • M_HTTP_RET_OK 生成未完成但未出错
  • M_HTTP_RET_ERROR 生成失败
mln_http_set_field
  1. int mln_http_set_field(mln_http_t *http, mln_string_t *key, mln_string_t *val);
复制代码

描述:设置HTTP头字段。若头字段key存在,则会将val替换原有值。

返回值:

  • M_HTTP_RET_OK 处理成功
  • M_HTTP_RET_ERROR处理失败
mln_http_get_field
  1. mln_string_t *mln_http_get_field(mln_http_t *http, mln_string_t *key);
复制代码

描述:获取HTTP头字段中键为key的值。

返回值:成功则返回值字符串结构指针,否则返回NULL

mln_http_field_iterator
  1. mln_string_t *mln_http_field_iterator(mln_http_t *http, mln_string_t *key);
复制代码

描述:每次返回一个键为key的头字段值(即假设存在多个相同键名的头字段)。

返回值:成功则返回值字符串结构指针,否则返回NULL

mln_http_drop_field
  1. void mln_http_drop_field(mln_http_t *http, mln_string_t *key);
复制代码

描述:移除头字段key及其值。

返回值:无

mln_http_dump
  1. void mln_http_dump(mln_http_t *http);
复制代码

描述:将HTTP信息输出到标准输出,用于调试之用。

返回值:无

mln_http_get_connection
  1. mln_http_get_connection(h)
复制代码

描述:获取类型为mln_http_t的h中TCP链接结构。

返回值:mln_tcp_conn_t类型指针

mln_http_set_connection
  1. mln_http_set_connection(h,c)
复制代码

描述:将mln_http_t类型的h中TCP链接结构设置为mln_tcp_conn_t类型的c。

返回值:无

mln_http_get_pool
  1. mln_http_get_pool(h)
复制代码

描述:获取类型为mln_http_t的h中内存池结构。

返回值:mln_alloc_t类型指针

mln_http_set_pool
  1. mln_http_set_pool(h,p)
复制代码

描述:将mln_http_t类型的h中内存池设置为mln_alloc_t类型的p。

返回值:无

mln_http_get_data
  1. mln_http_get_data(h)
复制代码

描述:获取类型为mln_http_t的h中辅助体处理函数的用户自定义数据。

返回值:用户自定义数据指针

mln_http_set_data
  1. mln_http_set_data(h,d)
复制代码

描述:将mln_http_t类型的h中辅助体处理函数的用户自定义数据设置为d。

返回值:无

mln_http_get_uri
  1. mln_http_get_uri(h)
复制代码

描述:获取类型为mln_http_t的h中URI字符串。

返回值:mln_string_t类型指针

mln_http_set_uri
  1. mln_http_set_uri(h,u)
复制代码

描述:将mln_http_t类型的h中URI设置为mln_string_t类型指针的u。

返回值:无

mln_http_get_args
  1. mln_http_get_args(h)
复制代码

描述:获取类型为mln_http_t的h中参数字符串。

返回值:mln_string_t类型指针

mln_http_set_args
  1. mln_http_set_args(h,a)
复制代码

描述:将mln_http_t类型的h中参数设置为mln_string_t类型指针的a。

返回值:无

mln_http_get_status
  1. mln_http_get_status(h)
复制代码

描述:获取类型为mln_http_t的h中响应状态字,例如200 400等。

返回值:整型状态字

mln_http_set_status
  1. mln_http_set_status(h,s)
复制代码

描述:将mln_http_t类型的h中响应状态字设置为整型的s。

返回值:无

mln_http_get_method
  1. mln_http_get_method(h)
复制代码

描述:获取类型为mln_http_t的h中方法字段

返回值:

  • M_HTTP_GET
  • M_HTTP_POST
  • M_HTTP_HEAD
  • M_HTTP_PUT
  • M_HTTP_DELETE
  • M_HTTP_TRACE
  • M_HTTP_CONNECT
  • M_HTTP_OPTIONS
mln_http_set_method
  1. mln_http_set_method(h,m)
复制代码

描述:将mln_http_t类型的h中请求方法设置为m,m的可用值参考mln_http_get_method的返回值部分。

返回值:无

mln_http_get_version
  1. mln_http_get_version(h)
复制代码

描述:获取类型为mln_http_t的h中HTTP版本

返回值:

  • M_HTTP_VERSION_1_0 HTTP 1.0
  • M_HTTP_VERSION_1_1 HTTP 1.1
mln_http_set_version
  1. mln_http_set_version(h,v)
复制代码

描述:将mln_http_t类型的h中的HTTP版本号为v,v的取值参考mln_http_get_version的返回值。

返回值:无

mln_http_get_type
  1. mln_http_get_type(h)
复制代码

描述:获取类型为mln_http_t的h中HTTP类型,即请求还是响应。

返回值:

  • M_HTTP_UNKNOWN未知类型
  • M_HTTP_REQUEST请求
  • M_HTTP_RESPONSE响应
mln_http_set_type
  1. mln_http_set_type(h,t)
复制代码

描述:将mln_http_t类型的h中报文类型设置为t,t的取值参考mln_http_get_type的返回值。

返回值:无

mln_http_get_handler
  1. mln_http_get_handler(h)
复制代码

描述:获取类型为mln_http_t的h中体处理函数指针。

返回值:类型为mln_http_handler的函数指针

mln_http_set_handler
  1. mln_http_set_handler(h,hlr)
复制代码

描述:将mln_http_t类型的h中提处理函数设置为mln_http_handler类型的hlr。

返回值:无

mln_http_get_response_msg
  1. mln_http_get_response_msg(h)
复制代码

描述:获取类型为mln_http_t的h中响应信息,即类似:Bad Request 或 Internal Server Error等字符串。

返回值:mln_string_t类型指针

mln_http_set_response_msg
  1. mln_http_set_response_msg(h,m)
复制代码

描述:将mln_http_t类型的h中响应信息设置为mln_string_t类型指针的m。

返回值:无

mln_http_get_error
  1. mln\_http\_get\_error(h)
  2. #define M\_HTTP\_CONTINUE 100
  3. #define M\_HTTP\_SWITCHING\_PROTOCOLS 101
  4. #define M\_HTTP\_PROCESSING 102
  5. #define M\_HTTP\_OK 200
  6. #define M\_HTTP\_CREATED 201
  7. #define M\_HTTP\_ACCEPTED 202
  8. #define M\_HTTP\_NON\_AUTHORITATIVE\_INFORMATION 203
  9. #define M\_HTTP\_NO\_CONTENT 204
  10. #define M\_HTTP\_RESET\_CONTENT 205
  11. #define M\_HTTP\_PARTIAL\_CONTENT 206
  12. #define M\_HTTP\_MULTI\_STATUS 207
  13. #define M\_HTTP\_MULTIPLE\_CHOICES 300
  14. #define M\_HTTP\_MOVED\_PERMANENTLY 301
  15. #define M\_HTTP\_MOVED\_TEMPORARILY 302
  16. #define M\_HTTP\_SEE\_OTHER 303
  17. #define M\_HTTP\_NOT\_MODIFIED 304
  18. #define M\_HTTP\_USE\_PROXY 305
  19. #define M\_HTTP\_SWITCH\_PROXY 306
  20. #define M\_HTTP\_TEMPORARY\_REDIRECT 307
  21. #define M\_HTTP\_BAD\_REQUEST 400
  22. #define M\_HTTP\_UNAUTHORIZED 401
  23. #define M\_HTTP\_PAYMENT\_REQUIRED 402
  24. #define M\_HTTP\_FORBIDDEN 403
  25. #define M\_HTTP\_NOT\_FOUND 404
  26. #define M\_HTTP\_METHOD\_NOT\_ALLOWED 405
  27. #define M\_HTTP\_NOT\_ACCEPTABLE 406
  28. #define M\_HTTP\_PROXY\_AUTHENTICATION\_REQUIRED 407
  29. #define M\_HTTP\_REQUEST\_TIMEOUT 408
  30. #define M\_HTTP\_CONFLICT 409
  31. #define M\_HTTP\_GONE 410
  32. #define M\_HTTP\_LENGTH\_REQUIRED 411
  33. #define M\_HTTP\_PRECONDITION\_FAILED 412
  34. #define M\_HTTP\_REQUEST\_ENTITY\_TOO\_LARGE 413
  35. #define M\_HTTP\_REQUEST\_URI\_TOO\_LARGE 414
  36. #define M\_HTTP\_UNSUPPORTED\_MEDIA\_TYPE 415
  37. #define M\_HTTP\_REQUESTED\_RANGE\_NOT\_SATISFIABLE 416
  38. #define M\_HTTP\_EXPECTATION\_FAILED 417
  39. #define M\_HTTP\_TOO\_MANY\_CONNECTIONS 421
  40. #define M\_HTTP\_UNPROCESSABLE\_ENTITY 422
  41. #define M\_HTTP\_LOCKED 423
  42. #define M\_HTTP\_FAILED\_DEPENDENCY 424
  43. #define M\_HTTP\_UNORDERED\_COLLECTION 425
  44. #define M\_HTTP\_UPGRADE\_REQUIRED 426
  45. #define M\_HTTP\_RETRY\_WITH 449
  46. #define M\_HTTP\_INTERNAL\_SERVER\_ERROR 500
  47. #define M\_HTTP\_NOT\_IMPLEMENTED 501
  48. #define M\_HTTP\_BAD\_GATEWAY 502
  49. #define M\_HTTP\_SERVICE\_UNAVAILABLE 503
  50. #define M\_HTTP\_GATEWAY\_TIMEOUT 504
  51. #define M\_HTTP\_VERSION\_NOT\_SUPPORTED 505
  52. #define M\_HTTP\_VARIANT\_ALSO\_NEGOTIATES 506
  53. #define M\_HTTP\_INSUFFICIENT\_STORAGE 507
  54. #define M\_HTTP\_BANDWIDTH\_LIMIT\_EXCEEDED 509
  55. #define M\_HTTP\_NOT\_EXTENDED 510
  56. #define M\_HTTP\_UNPARSEABLE\_RESPONSE\_HEADERS 600
复制代码

描述:获取类型为mln_http_t的h中错误信息。

返回值:宏定义的错误值

mln_http_set_error
  1. mln_http_set_error(h,e)
复制代码

描述:将mln_http_t类型的h中错误信息设置为e,e的取值参见mln_http_get_error中的宏定义。

返回值:无

mln_http_get_header
  1. mln_http_get_header(h)
复制代码

描述:获取类型为mln_http_t的h中头字段结构。

返回值:mln_hash_t类型结构

示例
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <sys/socket.h>
  4. #include <netinet/in.h>
  5. #include <errno.h>
  6. #include <arpa/inet.h>
  7. #include <sys/time.h>
  8. #include "mln\_core.h"
  9. #include "mln\_log.h"
  10. #include "mln\_http.h"
  11. #include "mln\_file.h"
  12. static void mln\_accept(mln_event_t \*ev, int fd, void \*data);
  13. static int mln\_http\_recv\_body\_handler(mln_http_t \*http, mln_chain_t \*\*in, mln_chain_t \*\*nil);
  14. static void mln\_recv(mln_event_t \*ev, int fd, void \*data);
  15. static void mln\_quit(mln_event_t \*ev, int fd, void \*data);
  16. static void mln\_send(mln_event_t \*ev, int fd, void \*data);
  17. static int mln\_http\_send\_body\_handler(mln_http_t \*http, mln_chain_t \*\*body_head, mln_chain_t \*\*body_tail);
  18. static void worker\_process(mln_event_t \*ev)
  19. {
  20. mln_u16_t port = 1234;
  21. mln_s8_t ip[] = "0.0.0.0";
  22. struct sockaddr_in addr;
  23. int val = 1;
  24. int listenfd = socket(AF_INET, SOCK_STREAM, 0);
  25. if (listenfd < 0) {
  26. mln\_log(error, "listen socket error\n");
  27. return;
  28. }
  29. if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0) {
  30. mln\_log(error, "setsockopt error\n");
  31. close(listenfd);
  32. return;
  33. }
  34. addr.sin_family = AF_INET;
  35. addr.sin_port = htons(port);
  36. addr.sin_addr.s_addr = inet\_addr(ip);
  37. if (bind(listenfd, (struct sockaddr \*)&addr, sizeof(addr)) < 0) {
  38. mln\_log(error, "bind error\n");
  39. close(listenfd);
  40. return;
  41. }
  42. if (listen(listenfd, 511) < 0) {
  43. mln\_log(error, "listen error\n");
  44. close(listenfd);
  45. return;
  46. }
  47. if (mln\_event\_set\_fd(ev, \
  48. listenfd, \
  49. M_EV_RECV|M_EV_NONBLOCK, \
  50. M_EV_UNLIMITED, \
  51. NULL, \
  52. mln_accept) < 0)
  53. {
  54. mln\_log(error, "listen sock set event error\n");
  55. close(listenfd);
  56. return;
  57. }
  58. }
  59. static void mln\_accept(mln_event_t \*ev, int fd, void \*data)
  60. {
  61. mln_tcp_conn_t \*connection;
  62. mln_http_t \*http;
  63. int connfd;
  64. socklen_t len;
  65. struct sockaddr_in addr;
  66. while (1) {
  67. memset(&addr, 0, sizeof(addr));
  68. len = sizeof(addr);
  69. connfd = accept(fd, (struct sockaddr \*)&addr, &len);
  70. if (connfd < 0) {
  71. if (errno == EAGAIN) break;
  72. if (errno == EINTR) continue;
  73. perror("accept");
  74. exit(1);
  75. }
  76. connection = (mln_tcp_conn_t \*)malloc(sizeof(mln_tcp_conn_t));
  77. if (connection == NULL) {
  78. fprintf(stderr, "3No memory.\n");
  79. close(connfd);
  80. continue;
  81. }
  82. if (mln\_tcp\_conn\_init(connection, connfd) < 0) {
  83. fprintf(stderr, "4No memory.\n");
  84. close(connfd);
  85. free(connection);
  86. continue;
  87. }
  88. http = mln\_http\_init(connection, NULL, mln_http_recv_body_handler);
  89. if (http == NULL) {
  90. fprintf(stderr, "5No memory.\n");
  91. mln\_tcp\_conn\_destroy(connection);
  92. free(connection);
  93. close(connfd);
  94. continue;
  95. }
  96. if (mln\_event\_set\_fd(ev, \
  97. connfd, \
  98. M_EV_RECV|M_EV_NONBLOCK, \
  99. M_EV_UNLIMITED, \
  100. http, \
  101. mln_recv) < 0)
  102. {
  103. fprintf(stderr, "6No memory.\n");
  104. mln\_http\_destroy(http);
  105. mln\_tcp\_conn\_destroy(connection);
  106. free(connection);
  107. close(connfd);
  108. continue;
  109. }
  110. }
  111. }
  112. static void mln\_quit(mln_event_t \*ev, int fd, void \*data)
  113. {
  114. mln_http_t \*http = (mln_http_t \*)data;
  115. mln_tcp_conn_t \*connection = mln\_http\_get\_connection(http);
  116. mln\_event\_set\_fd(ev, fd, M_EV_CLR, M_EV_UNLIMITED, NULL, NULL);
  117. mln\_http\_destroy(http);
  118. mln\_tcp\_conn\_destroy(connection);
  119. free(connection);
  120. close(fd);
  121. }
  122. static void mln\_recv(mln_event_t \*ev, int fd, void \*data)
  123. {
  124. mln_http_t \*http = (mln_http_t \*)data;
  125. mln_tcp_conn_t \*connection = mln\_http\_get\_connection(http);
  126. int ret, rc;
  127. mln_chain_t \*c;
  128. while (1) {
  129. ret = mln\_tcp\_conn\_recv(connection, M_C_TYPE_MEMORY);
  130. if (ret == M_C_FINISH) {
  131. continue;
  132. } else if (ret == M_C_NOTYET) {
  133. c = mln\_tcp\_conn\_remove(connection, M_C_RECV);
  134. if (c != NULL) {
  135. rc = mln\_http\_parse(http, &c);
  136. if (c != NULL) {
  137. mln\_tcp\_conn\_append\_chain(connection, c, NULL, M_C_RECV);
  138. }
  139. if (rc == M_HTTP_RET_OK) {
  140. return;
  141. } else if (rc == M_HTTP_RET_DONE) {
  142. mln\_send(ev, fd, data);
  143. } else {
  144. fprintf(stderr, "Http parse error. error\_code:%u\n", mln\_http\_get\_error(http));
  145. mln\_quit(ev, fd, data);
  146. return;
  147. }
  148. }
  149. break;
  150. } else if (ret == M_C_CLOSED) {
  151. c = mln\_tcp\_conn\_remove(connection, M_C_RECV);
  152. if (c != NULL) {
  153. rc = mln\_http\_parse(http, &c);
  154. if (c != NULL) {
  155. mln\_tcp\_conn\_append\_chain(connection, c, NULL, M_C_RECV);
  156. }
  157. if (rc == M_HTTP_RET_ERROR) {
  158. fprintf(stderr, "Http parse error. error\_code:%u\n", mln\_http\_get\_error(http));
  159. }
  160. }
  161. mln\_quit(ev, fd, data);
  162. return;
  163. } else if (ret == M_C_ERROR) {
  164. mln\_quit(ev, fd, data);
  165. return;
  166. }
  167. }
  168. }
  169. static int mln\_http\_recv\_body\_handler(mln_http_t \*http, mln_chain_t \*\*in, mln_chain_t \*\*nil)
  170. {
  171. mln_u32_t method = mln\_http\_get\_method(http);
  172. if (method == M_HTTP_GET)
  173. return M_HTTP_RET_DONE;
  174. mln\_http\_set\_error(http, M_HTTP_NOT_IMPLEMENTED);
  175. return M_HTTP_RET_ERROR;
  176. }
  177. static void mln\_send(mln_event_t \*ev, int fd, void \*data)
  178. {
  179. mln_http_t \*http = (mln_http_t \*)data;
  180. mln_tcp_conn_t \*connection = mln\_http\_get\_connection(http);
  181. mln_chain_t \*c = mln\_tcp\_conn\_get\_head(connection, M_C_SEND);
  182. int ret;
  183. if (c == NULL) {
  184. mln\_http\_reset(http);
  185. mln\_http\_set\_status(http, M_HTTP_OK);
  186. mln\_http\_set\_version(http, M_HTTP_VERSION_1_0);
  187. mln\_http\_set\_type(http, M_HTTP_RESPONSE);
  188. mln\_http\_set\_handler(http, mln_http_send_body_handler);
  189. mln_chain_t \*body_head = NULL, \*body_tail = NULL;
  190. if (mln\_http\_generate(http, &body_head, &body_tail) == M_HTTP_RET_ERROR) {
  191. fprintf(stderr, "mln\_http\_generate() failed. %u\n", mln\_http\_get\_error(http));
  192. mln\_quit(ev, fd, data);
  193. return;
  194. }
  195. mln\_tcp\_conn\_append\_chain(connection, body_head, body_tail, M_C_SEND);
  196. }
  197. while ((c = mln\_tcp\_conn\_get\_head(connection, M_C_SEND)) != NULL) {
  198. ret = mln\_tcp\_conn\_send(connection);
  199. if (ret == M_C_FINISH) {
  200. mln\_quit(ev, fd, data);
  201. break;
  202. } else if (ret == M_C_NOTYET) {
  203. mln\_chain\_pool\_release\_all(mln\_tcp\_conn\_remove(connection, M_C_SENT));
  204. mln\_event\_set\_fd(ev, fd, M_EV_SEND|M_EV_APPEND|M_EV_NONBLOCK, M_EV_UNLIMITED, data, mln_send);
  205. return;
  206. } else if (ret == M_C_ERROR) {
  207. mln\_quit(ev, fd, data);
  208. return;
  209. } else {
  210. fprintf(stderr, "Shouldn't be here.\n");
  211. abort();
  212. }
  213. }
  214. }
  215. static int mln\_http\_send\_body\_handler(mln_http_t \*http, mln_chain_t \*\*body_head, mln_chain_t \*\*body_tail)
  216. {
  217. mln_u8ptr_t buf;
  218. mln_alloc_t \*pool = mln\_http\_get\_pool(http);
  219. mln_string_t cttype_key = mln\_string("Content-Type");
  220. mln_string_t cttype_val = mln\_string("text/html");
  221. buf = mln\_alloc\_m(pool, 5);
  222. if (buf == NULL) {
  223. mln\_http\_set\_error(http, M_HTTP_INTERNAL_SERVER_ERROR);
  224. return M_HTTP_RET_ERROR;
  225. }
  226. memcpy(buf, "hello", 5);
  227. if (mln\_http\_set\_field(http, &cttype_key, &cttype_val) == M_HTTP_RET_ERROR) {
  228. mln\_http\_set\_error(http, M_HTTP_INTERNAL_SERVER_ERROR);
  229. return M_HTTP_RET_ERROR;
  230. }
  231. mln_string_t ctlen_key = mln\_string("Content-Length");
  232. mln_string_t ctlen_val = mln\_string("5");
  233. if (mln\_http\_set\_field(http, &ctlen_key, &ctlen_val) == M_HTTP_RET_ERROR) {
  234. mln\_http\_set\_error(http, M_HTTP_INTERNAL_SERVER_ERROR);
  235. return M_HTTP_RET_ERROR;
  236. }
  237. mln_chain_t \*c = mln\_chain\_new(pool);
  238. if (c == NULL) {
  239. mln\_http\_set\_error(http, M_HTTP_INTERNAL_SERVER_ERROR);
  240. return M_HTTP_RET_ERROR;
  241. }
  242. mln_buf_t \*b = mln\_buf\_new(pool);
  243. if (b == NULL) {
  244. mln\_chain\_pool\_release(c);
  245. mln\_http\_set\_error(http, M_HTTP_INTERNAL_SERVER_ERROR);
  246. return M_HTTP_RET_ERROR;
  247. }
  248. c->buf = b;
  249. b->left_pos = b->pos = b->start = buf;
  250. b->last = b->end = buf + 5;
  251. b->in_memory = 1;
  252. b->last_buf = 1;
  253. b->last_in_chain = 1;
  254. if (\*body_head == NULL) {
  255. \*body_head = \*body_tail = c;
  256. } else {
  257. (\*body_tail)->next = c;
  258. \*body_tail = c;
  259. }
  260. return M_HTTP_RET_DONE;
  261. }
  262. int main(int argc, char \*argv[])
  263. {
  264. struct mln_core_attr cattr;
  265. cattr.argc = argc;
  266. cattr.argv = argv;
  267. cattr.global_init = NULL;
  268. cattr.worker_process = worker_process;
  269. return mln\_core\_init(&cattr);
  270. }
复制代码

矩阵运算

头文件
  1. #include "mln_matrix.h"
复制代码
相关结构
  1. typedef struct {
  2. mln_size_t row;//矩阵的行数
  3. mln_size_t col;//矩阵的列数
  4. double *data;//一个一维数组,包含了矩阵内所有元素,按行一次排列
  5. mln_u32_t is_ref:1;//标识data是否为外部引用,该标记用于释放矩阵结构时忽略对data的释放
  6. } mln_matrix_t;
复制代码
函数
mln_matrix_new
  1. mln_matrix_t *mln_matrix_new(mln_size_t row, mln_size_t col, double *data, mln_u32_t is_ref);
复制代码

描述:创建一个row行col列,数据为data的矩阵。若is_ref为0则表示矩阵结构会完全复制一个data在其中,否则直接引用data。

返回值:成功则返回矩阵结构指针,否则返回NULL

mln_matrix_free
  1. void mln_matrix_free(mln_matrix_t *matrix);
复制代码

描述:释放矩阵结构内存。

返回值:无

mln_matrix_mul
  1. mln_matrix_t *mln_matrix_mul(mln_matrix_t *m1, mln_matrix_t *m2);
复制代码

描述:矩阵乘法。


网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

t *pool = mln_http_get_pool(http);
mln_string_t cttype_key = mln_string(“Content-Type”);
mln_string_t cttype_val = mln_string(“text/html”);

  1. buf = mln\_alloc\_m(pool, 5);
  2. if (buf == NULL) {
  3. mln\_http\_set\_error(http, M_HTTP_INTERNAL_SERVER_ERROR);
  4. return M_HTTP_RET_ERROR;
  5. }
  6. memcpy(buf, "hello", 5);
  7. if (mln\_http\_set\_field(http, &cttype_key, &cttype_val) == M_HTTP_RET_ERROR) {
  8. mln\_http\_set\_error(http, M_HTTP_INTERNAL_SERVER_ERROR);
  9. return M_HTTP_RET_ERROR;
  10. }
  11. mln_string_t ctlen_key = mln\_string("Content-Length");
  12. mln_string_t ctlen_val = mln\_string("5");
  13. if (mln\_http\_set\_field(http, &ctlen_key, &ctlen_val) == M_HTTP_RET_ERROR) {
  14. mln\_http\_set\_error(http, M_HTTP_INTERNAL_SERVER_ERROR);
  15. return M_HTTP_RET_ERROR;
  16. }
  17. mln_chain_t \*c = mln\_chain\_new(pool);
  18. if (c == NULL) {
  19. mln\_http\_set\_error(http, M_HTTP_INTERNAL_SERVER_ERROR);
  20. return M_HTTP_RET_ERROR;
  21. }
  22. mln_buf_t \*b = mln\_buf\_new(pool);
  23. if (b == NULL) {
  24. mln\_chain\_pool\_release(c);
  25. mln\_http\_set\_error(http, M_HTTP_INTERNAL_SERVER_ERROR);
  26. return M_HTTP_RET_ERROR;
  27. }
  28. c->buf = b;
  29. b->left_pos = b->pos = b->start = buf;
  30. b->last = b->end = buf + 5;
  31. b->in_memory = 1;
  32. b->last_buf = 1;
  33. b->last_in_chain = 1;
  34. if (\*body_head == NULL) {
  35. \*body_head = \*body_tail = c;
  36. } else {
  37. (\*body_tail)->next = c;
  38. \*body_tail = c;
  39. }
  40. return M_HTTP_RET_DONE;
复制代码

}

int main(int argc, char *argv[])
{
struct mln_core_attr cattr;

  1. cattr.argc = argc;
  2. cattr.argv = argv;
  3. cattr.global_init = NULL;
  4. cattr.worker_process = worker_process;
  5. return mln\_core\_init(&cattr);
复制代码

}

  1. ### 矩阵运算
  2. #### 头文件
复制代码

#include “mln_matrix.h”

  1. #### 相关结构
复制代码

typedef struct {
mln_size_t row;//矩阵的行数
mln_size_t col;//矩阵的列数
double *data;//一个一维数组,包含了矩阵内所有元素,按行一次排列
mln_u32_t is_ref:1;//标识data是否为外部引用,该标记用于释放矩阵结构时忽略对data的释放
} mln_matrix_t;

  1. #### 函数
  2. ##### mln\_matrix\_new
复制代码

mln_matrix_t *mln_matrix_new(mln_size_t row, mln_size_t col, double *data, mln_u32_t is_ref);

  1. 描述:创建一个`row`行`col`列,数据为`data`的矩阵。若`is_ref`为`0`则表示矩阵结构会完全复制一个`data`在其中,否则直接引用`data`。
  2. 返回值:成功则返回矩阵结构指针,否则返回`NULL`
  3. ##### mln\_matrix\_free
复制代码

void mln_matrix_free(mln_matrix_t *matrix);

  1. 描述:释放矩阵结构内存。
  2. 返回值:无
  3. ##### mln\_matrix\_mul
复制代码

mln_matrix_t *mln_matrix_mul(mln_matrix_t *m1, mln_matrix_t *m2);

  1. 描述:矩阵乘法。
  2. [外链图片转存中...(img-nEwXyAon-1715534546972)]
  3. [外链图片转存中...(img-3yNhKcUk-1715534546972)]
  4. **网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**
  5. **[需要这份系统化的资料的朋友,可以添加戳这里获取](https://bbs.csdn.net/topics/618658159)**
  6. **一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**
复制代码

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Honkers

荣誉红客

关注
  • 4013
    主题
  • 36
    粉丝
  • 0
    关注
这家伙很懒,什么都没留下!

中国红客联盟公众号

联系站长QQ:5520533

admin@chnhonker.com
Copyright © 2001-2025 Discuz Team. Powered by Discuz! X3.5 ( 粤ICP备13060014号 )|天天打卡 本站已运行