<commit_before>/* ***************************************************************************
 * LCUI_Queue.c -- basic queue processing
 * 
 * Copyright (C) 2012 by
 * <NAME>
 * 
 * This file is part of the LCUI project, and may only be used, modified, and
 * distributed under the terms of the GPLv2.
 * 
 * (GPLv2 is abbreviation of GNU General Public License Version 2)
 * 
 * By continuing to use, modify, or distribute this file you indicate that you
 * have read the license and understand and accept it fully.
 *  
 * The LCUI project is distributed in the hope that it will be useful, but 
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
 * or FITNESS FOR A PARTICULAR PURPOSE. See the GPL v2 for more details.
 * 
 * You should have received a copy of the GPLv2 along with this file. It is 
 * usually in the LICENSE.TXT file, If not, see <http://www.gnu.org/licenses/>.
 * ****************************************************************************/
 
/* ****************************************************************************
 * LCUI_Queue.c -- 基本的队列处理
 *
 * 版权所有 (C) 2012 归属于 
 * 刘超
 * 
 * 这个文件是LCUI项目的一部分，并且只可以根据GPLv2许可协议来使用、更改和发布。
 *
 * (GPLv2 是 GNU通用公共许可证第二版 的英文缩写)
 * 
 * 继续使用、修改或发布本文件，表明您已经阅读并完全理解和接受这个许可协议。
 * 
 * LCUI 项目是基于使用目的而加以散布的，但不负任何担保责任，甚至没有适销性或特
 * 定用途的隐含担保，详情请参照GPLv2许可协议。
 *
 * 您应已收到附随于本文件的GPLv2许可协议的副本，它通常在LICENSE.TXT文件中，如果
 * 没有，请查看：<http://www.gnu.org/licenses/>. 
 * ****************************************************************************/
 
/*
 * 队列设计方案：
 * 队列有“已用”和“未用”这两种空间，element_size保存队列成员占用空间大小，总成员个数
 * 由max_num表示，包含有效数据的成员个数由total_num表示。
 * 当删除一个队列成员后，total_num会减1，max_num不变，该队列成员占用的空间不会被释放，
 * 以备后续使用，而该队列成员会移动至队列末尾，成为“未用”空间。
 * 当往队列里添加数据时，如果total_num小于max_num，则使用“未用”空间里的队列成员来保存
 * 该数据。
 * member_type保存队列的成员数据类型：指针 或者 变量；如果队列主要用于存放指针，那么，
 * 在删除，销毁队列时，不会释放数据指针指向的内存空间；否则，会释放。
 * 部件的子部件队列的成员数据类型就是指针，主要用于引用主部件队列里的部件，销毁子部件队列
 * 时不会影响到主队列里的部件。
 * 
 * 队列的数据存储方式有两种：数组 和 链表；
 * 前者的读写速度较快，但数据插入效率较慢，因为在指定位置插入数据后，该位置后面的所有数
 * 据的位置需要向后移动，后面的数据元素越多，耗时越多。
 * 后者适合频繁的进行数据插入和删除，因为只需要找到目标位置的结点，然后插入新结点即可。
 * LCUI的文本位图层的处理就用到了后者，因为编辑文本主要是添加和删除文字。
 * */

//#define DEBUG
#include <LCUI_Build.h>
#include LC_LCUI_H
#include LC_MISC_H
#include LC_GRAPH_H
#include LC_WIDGET_H 
#include LC_ERROR_H
#include <unistd.h>

/************************ LCUI_Queue **********************************/
int Queue_Lock (LCUI_Queue *queue)
/* 功能：锁定一个队列，使之只能被一个线程使用 */
{ 
	return thread_mutex_lock(&queue->lock);
}

int Queue_UnLock (LCUI_Queue *queue)
/* 功能：解开队列锁 */
{
	return thread_mutex_unlock(&queue->lock);
}

int Queue_Using (LCUI_Queue * queue, int mode) 
/* 
 * 功能：设定队列的状态为“使用” 
 * 说明：参数mode需要是QUEUE_MODE_READ和QUEUE_MODE_WRITE这两种之一。
 * QUEUE_MODE_READ 表示“读”模式，由于是读，可以和其它以“读”模式访问本队列的线程共享。
 * QUEUE_MODE_WRITE 表示“写”模式，写只能由一个线程写，其它线程既不能读也不能写。
 * */
{ 
	if(mode == QUEUE_MODE_READ) {
	//	printf("use, queue: %p, mode: read\n", queue);
		return thread_rwlock_rdlock(&queue->lock); 
	} else {
		//printf("use, queue: %p, mode: write\n", queue);
		return thread_rwlock_wrlock(&queue->lock);  
	}
}

int Queue_End_Use (LCUI_Queue * queue) 
/* 功能：储存矩形数据的队列为空闲状态 */
{
	//switch(queue->lock.status) {
	    //case RWLOCK_WRITE:printf("end use, queue: %p, befor mode: write\n", queue);break;
	    //case RWLOCK_READ:printf("end use, queue: %p, befor mode: read\n", queue);break;
	    //case RWLOCK_FREE:printf("end use, queue: %p, befor mode: free\n", queue);break;
	//}
	return thread_rwlock_unlock(&queue->lock); 
}

void Queue_Init (LCUI_Queue * queue, size_t element_size, void (*func) ()) 
/* 功能：初始化队列 */
{
	thread_rwlock_init(&queue->lock);
	queue->member_type	= 0;
	queue->data_mode	= 0;
	queue->data_array	= NULL;
	queue->data_head_node.data = NULL;
	queue->data_head_node.prev = NULL;
	queue->data_head_node.next = NULL;
	queue->total_num	= 0;
	queue->max_num		= 0;
	queue->element_size	= element_size;
	queue->destroy_func	= func; 
}

void Queue_Using_Pointer(LCUI_Queue * queue)
/* 
 * 功能：设定队列成员类型为指针 
 * 说明：如果队列只是用于存放指针，并且不希望队列销毁后，指针指向的内存空间也被释放，可
 * 使用该函数设置。
 * */
{
	queue->member_type = 1;
}

int Queue_Get_Total(LCUI_Queue * queue)
/* 说明：获取队列当前总成员数量 */
{
	return queue->total_num;
}

int Queue_Set_DataMode(LCUI_Queue * queue, Queue_DataMode mode)
/* 
 * 功能：设定队列使用的数据储存模式
 * 说明：只能在初始化后且未加入成员时使用该函数
 * */
{
	if(queue->total_num > 0 || queue->max_num > 0) {
		return -1;
	}
	queue->data_mode = 1;
	return 0;
}


int Queue_Swap(LCUI_Queue * queue, int pos_a, int pos_b)
/* 功能：交换队列中指定位置两个成员的位置 */
{
	void *temp;
	if (pos_a < queue->total_num && pos_b < queue->total_num 
	 && pos_a != pos_b && queue->total_num > 0) {
		if(queue->data_mode == QUEUE_DATA_MODE_ARRAY) {
			temp = queue->data_array[pos_a];
			queue->data_array[pos_a] = queue->data_array[pos_b];
			queue->data_array[pos_b] = temp;
		} else {
			int i, pos;
			LCUI_Node *a, *b, *temp;
			if(pos_a < pos_b) {
				pos = pos_a;
			} else {
				pos = pos_b;
			}
			a = &queue->data_head_node;
			for(i=0; i<=pos; ++i) {
				a = a->next;
			}
			if(pos_a < pos_b) {
				pos = pos_b;
			}
			b = &queue->data_head_node;
			for(i=0; i<=pos; ++i) {
				b = b->next;
			}
			/* 交换两个结点的指向上结点的指针 */
			temp = a->prev;
			a->prev = b->prev;
			b->prev = temp; 
			/* 交换两个结点的指向下结点的指针 */
			temp = a->next;
			a->next = b->next;
			b->next = temp;
		}
		return 0;
	}
	return -1;
}

void Destroy_Queue(LCUI_Queue * queue) 
/* 功能：释放队列占用的内存资源 */
{
	if(queue->member_type == 0) {
	/* 如果成员是普通类型，释放队列成员占用的内存空间 */ <commit_msg>更新解决Queue_Swap函数的问题<commit_after>/* ***************************************************************************
 * LCUI_Queue.c -- basic queue processing
 * 
 * Copyright (C) 2012 by
 * <NAME>
 * 
 * This file is part of the LCUI project, and may only be used, modified, and
 * distributed under the terms of the GPLv2.
 * 
 * (GPLv2 is abbreviation of GNU General Public License Version 2)
 * 
 * By continuing to use, modify, or distribute this file you indicate that you
 * have read the license and understand and accept it fully.
 *  
 * The LCUI project is distributed in the hope that it will be useful, but 
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
 * or FITNESS FOR A PARTICULAR PURPOSE. See the GPL v2 for more details.
 * 
 * You should have received a copy of the GPLv2 along with this file. It is 
 * usually in the LICENSE.TXT file, If not, see <http://www.gnu.org/licenses/>.
 * ****************************************************************************/
 
/* ****************************************************************************
 * LCUI_Queue.c -- 基本的队列处理
 *
 * 版权所有 (C) 2012 归属于 
 * 刘超
 * 
 * 这个文件是LCUI项目的一部分，并且只可以根据GPLv2许可协议来使用、更改和发布。
 *
 * (GPLv2 是 GNU通用公共许可证第二版 的英文缩写)
 * 
 * 继续使用、修改或发布本文件，表明您已经阅读并完全理解和接受这个许可协议。
 * 
 * LCUI 项目是基于使用目的而加以散布的，但不负任何担保责任，甚至没有适销性或特
 * 定用途的隐含担保，详情请参照GPLv2许可协议。
 *
 * 您应已收到附随于本文件的GPLv2许可协议的副本，它通常在LICENSE.TXT文件中，如果
 * 没有，请查看：<http://www.gnu.org/licenses/>. 
 * ****************************************************************************/
 
/*
 * 队列设计方案：
 * 队列有“已用”和“未用”这两种空间，element_size保存队列成员占用空间大小，总成员个数
 * 由max_num表示，包含有效数据的成员个数由total_num表示。
 * 当删除一个队列成员后，total_num会减1，max_num不变，该队列成员占用的空间不会被释放，
 * 以备后续使用，而该队列成员会移动至队列末尾，成为“未用”空间。
 * 当往队列里添加数据时，如果total_num小于max_num，则使用“未用”空间里的队列成员来保存
 * 该数据。
 * member_type保存队列的成员数据类型：指针 或者 变量；如果队列主要用于存放指针，那么，
 * 在删除，销毁队列时，不会释放数据指针指向的内存空间；否则，会释放。
 * 部件的子部件队列的成员数据类型就是指针，主要用于引用主部件队列里的部件，销毁子部件队列
 * 时不会影响到主队列里的部件。
 * 
 * 队列的数据存储方式有两种：数组 和 链表；
 * 前者的读写速度较快，但数据插入效率较慢，因为在指定位置插入数据后，该位置后面的所有数
 * 据的位置需要向后移动，后面的数据元素越多，耗时越多。
 * 后者适合频繁的进行数据插入和删除，因为只需要找到目标位置的结点，然后插入新结点即可。
 * LCUI的文本位图层的处理就用到了后者，因为编辑文本主要是添加和删除文字。
 * */

//#define DEBUG
#include <LCUI_Build.h>
#include LC_LCUI_H
#include LC_MISC_H
#include LC_GRAPH_H
#include LC_WIDGET_H 
#include LC_ERROR_H
#include <unistd.h>

/************************ LCUI_Queue **********************************/
int Queue_Lock (LCUI_Queue *queue)
/* 功能：锁定一个队列，使之只能被一个线程使用 */
{ 
	return thread_mutex_lock(&queue->lock);
}

int Queue_UnLock (LCUI_Queue *queue)
/* 功能：解开队列锁 */
{
	return thread_mutex_unlock(&queue->lock);
}

int Queue_Using (LCUI_Queue * queue, int mode) 
/* 
 * 功能：设定队列的状态为“使用” 
 * 说明：参数mode需要是QUEUE_MODE_READ和QUEUE_MODE_WRITE这两种之一。
 * QUEUE_MODE_READ 表示“读”模式，由于是读，可以和其它以“读”模式访问本队列的线程共享。
 * QUEUE_MODE_WRITE 表示“写”模式，写只能由一个线程写，其它线程既不能读也不能写。
 * */
{ 
	if(mode == QUEUE_MODE_READ) {
	//	printf("use, queue: %p, mode: read\n", queue);
		return thread_rwlock_rdlock(&queue->lock); 
	} else {
		//printf("use, queue: %p, mode: write\n", queue);
		return thread_rwlock_wrlock(&queue->lock);  
	}
}

int Queue_End_Use (LCUI_Queue * queue) 
/* 功能：储存矩形数据的队列为空闲状态 */
{
	//switch(queue->lock.status) {
	    //case RWLOCK_WRITE:printf("end use, queue: %p, befor mode: write\n", queue);break;
	    //case RWLOCK_READ:printf("end use, queue: %p, befor mode: read\n", queue);break;
	    //case RWLOCK_FREE:printf("end use, queue: %p, befor mode: free\n", queue);break;
	//}
	return thread_rwlock_unlock(&queue->lock); 
}

void Queue_Init (LCUI_Queue * queue, size_t element_size, void (*func) ()) 
/* 功能：初始化队列 */
{
	thread_rwlock_init(&queue->lock);
	queue->member_type	= 0;
	queue->data_mode	= 0;
	queue->data_array	= NULL;
	queue->data_head_node.data = NULL;
	queue->data_head_node.prev = NULL;
	queue->data_head_node.next = NULL;
	queue->total_num	= 0;
	queue->max_num		= 0;
	queue->element_size	= element_size;
	queue->destroy_func	= func; 
}

void Queue_Using_Pointer(LCUI_Queue * queue)
/* 
 * 功能：设定队列成员类型为指针 
 * 说明：如果队列只是用于存放指针，并且不希望队列销毁后，指针指向的内存空间也被释放，可
 * 使用该函数设置。
 * */
{
	queue->member_type = 1;
}

int Queue_Get_Total(LCUI_Queue * queue)
/* 说明：获取队列当前总成员数量 */
{
	return queue->total_num;
}

int Queue_Set_DataMode(LCUI_Queue * queue, Queue_DataMode mode)
/* 
 * 功能：设定队列使用的数据储存模式
 * 说明：只能在初始化后且未加入成员时使用该函数
 * */
{
	if(queue->total_num > 0 || queue->max_num > 0) {
		return -1;
	}
	queue->data_mode = 1;
	return 0;
}


int Queue_Swap(LCUI_Queue * queue, int pos_a, int pos_b)
/* 功能：交换队列中指定位置两个成员的位置 */
{
	void *temp;
	
	if (pos_a >= queue->total_num || pos_b >= queue->total_num 
	 || pos_a == pos_b || queue->total_num <= 0) {
		return -1;
	}
	
	if(queue->data_mode == QUEUE_DATA_MODE_ARRAY) {
		temp = queue->data_array[pos_a];
		queue->data_array[pos_a] = queue->data_array[pos_b];
		queue->data_array[pos_b] = temp;
	} else {
		int i;
		LCUI_Node *a, *b;
		/* 找到两个位置的结点 */
		a = &queue->data_head_node;
		for(i=0; i<=pos_a; ++i) {
			a = a->next;
		}
		b = &queue->data_head_node;
		for(i=0; i<=pos_b; ++i) {
			b = b->next;
		}
		/* 交换指针 */
		temp = a->data;
		a->data = b->data;
		b->data = temp;
	}
	return 0;
}

void Destroy_Queue(LCUI_Queue * queue) 
/* 功能：释放队列占用的内存资源 */
{
	if(queue->member_type == 0) {
	/* 如果成员是普通类型，释放队列成员占用的内存空间 */ 
{'fraction_non_alphanumeric': 0.1994178950333302, 'fraction_numerical': 0.006384377053797766, 'mean_word_length': 4.479423868312757, 'pattern_counts': {'":': 0, '<': 22, '<?xml version=': 0, '>': 102, 'https://': 0, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5348638', 'n_tokens_mistral': 5474, 'n_tokens_neox': 5663, 'n_words': 795}