contributed by < ericlin1231
>
q_new
宣告 head
指標指向 malloc
配置的記憶體空間,其大小為 sizeof(struct list_head)
,透過 INIT_LIST_HEAD
將其初始化
q_free
先對 head
為 NULL
和 queue
為空的狀況進行檢查,再使用巨集 list_for_each_safe
逐一走訪內嵌於 element_t
中的 struct list_head list
,再透過 container_of
推算節點的記憶體位址,然後使用 free
將節點釋放
q_insert_head
替節點配置記憶體空間並且替 value
配置記憶體空間,要注意若 value
的記憶體空間配置失敗,需要將配置給節點的記憶體空間釋放以免造成記憶體洩漏,透過 snprintf
將輸入字串複製到 value
中,因為原本由 string.h
提供的 strncpy
不會對字串長度進行檢查,可能產生安全問題,透過作業腳本提供的資訊,我找到提供字串長度檢查的 snprintf
,可以找到 FreeBSD 類似的實作,最後透過 list.h
提供的 list_add
將節點加到佇列的頭
q_insert_tail
跟 q_insert_head
的概念相同,但是最後是用 list_add_tail
q_remove_head
使用 container_of
得知內嵌 list_head
的節點的記憶體位址,然後再用 snprintf
將節點中 value
的內容複製到 sp
當中,最後用 list.h
提供的 list_del
將節點從佇列中移除
q_remove_tail
概念和 q_remove_head
相同,q_remove_head
透過 head->next
移除節點,而 q_remove_tail
透過 head->prev
移除節點
q_delete_mid
透過兩個指標 next
和 prev
分別往右和左訪問節點,直到重疊就可以找到中間節點將其刪除,要注意除了節點以外,value
佔用的記憶體空間也要釋放
q_delete_dup
q_swap
使用類似快慢指標的技巧,把第一個節點當作 head
,第二個節點當作佇列的第一個元素,使用 list_move
將第三個節點移動到佇列的頭,等同於 Swap 操作
q_reverse
反轉佇列只需要將每一個節點的 next
和 prev
指標交換就好,我嘗試使用 Bit Wise XOR
交換,發現對於指標型態的資料,直接用 XOR
對其中的資料進行運算是不合法的,將其強制轉型為 uintptr_t
的指標型態,就可以對其進行運算,而 uintptr_t
定義在 stdint.h
中,其相當於 unsigned long int
q_reverseK
q_sort
q_ascend
q_descend
q_merge