C++独立游戏存档模块 VERSION_1.9

TANXL_DATABASE VERSION_1_9

更新简述

1.9版本对上一版本进行了诸多改进,并提出了第四版数据单元结构修改方案(支持一个单元存储多组数据)。作为过渡版本对之前存在的遗留问题进行了大量改进,以下为头文件修改内容图示,左边为1.7版本右边为1.9版本,此模块的接口除构造函数外相较于1.7版本没有任何改变,详细介绍将包含于TANXL_GAMEENGINE并一同发布。
头文件改进A
头文件使用了与标准库中相同的办法避免重复包含。
头文件改进B
新增两种整理模式,FILE_UNITED与MEMO_UNITED功能类似,都会在处理完数据后删除掉每一组数据的<TDB_Item></TDB_Item>标签,不同之处在于一个用于文件输出一个用于内存中数据修改。(可能存在问题,未验证新功能)
头文件改进C
第四版数据单元结构预览,未实装且后续可能修改。
头文件改进D
零合法功能被移除,数据序号改为15进制,0xF仅用于表示不可用。
头文件改进E
为原有匿名结构体修改初始化内容并增加第四版匿名结构体预览。
头文件改进F
内部私有成员增加版本序号。移除四个用于修改各位的内联函数。
头文件改进G
为几个全局的函数限定名称空间。修改默认数据的功能,去掉零/满合法数据,增加可自定义输出数据长度。

头文件代码

//_VERSION_1_9_ UPDATE LOG
// LAST_UPDATE 2023-01-06 12:27
#pragma once

#ifndef _TANXL_DATABASE_
#define _TANXL_DATABASE_

#include<iostream>
#include<fstream>
#include<string>
#include<sstream>
#include<vector>
#include"Tanxl_DataDefine.h"

enum ESort_Mode//为SortDataBase函数提供的功能枚举
{
	SORT_LOCALF = 0,
	FILE_UNITED = 1,
	SORT_MEMORY = 2,
	MEMO_UNITED = 3
};

enum EDivid_Mode//为Divid_Char函数提供的功能枚举
{
	GET_STATUS_DAT = 0,
	GET_STORAG_DAT = 1,
	GET_STATUS_TAG = 2,
	GET_STATUS_STR = 3,
	GET_OLDSTY_DAT = 4
};

enum ESet_Specified
{
	SET_TYPE_STATUS = 0,
	SET_EXAC_STATUS = 1,
	SET_OTH1_STATUS = 2,
	SET_OTH2_STATUS = 3,
	SET_OTH3_STATUS = 4,
};

struct Data_Unit
{
	Data_Unit(int Id, std::string Data) :_Id(Id), _Data(Data), _Next(nullptr) {};

	int _Id;
	std::string _Data;
	Data_Unit* _Next;
};

struct Data_Vector_V4//数据表V4
{
	explicit Data_Vector_V4(int Id, std::string Data)
	{
		_Data_Units.push_back(Data_Unit(Id, Data));
	}

	explicit Data_Vector_V4(Data_Unit Data)
	{
		_Data_Units.push_back(Data);
	}

	void Append_Data(int Id, std::string Data)
	{
		_Data_Units.push_back(Data_Unit(Id, Data));
	}

	void Append_Data(Data_Unit Data)
	{
		_Data_Units.push_back(Data);
	}

	std::vector<Data_Unit> _Data_Units;
};

struct Data_Vector//短数据表(Vector)
{
	explicit Data_Vector(int I_A = 0xFF, std::string D_A = NULL, int I_B = 0xFF, std::string D_B = NULL, int I_C = 0xFF, std::string D_C = NULL) :
		Id_1(I_A), Id_2(I_B), Id_3(I_C), Sd_1(D_A), Sd_2(D_B), Sd_3(D_C) {}
	int Id_1, Id_2, Id_3;
	std::string Sd_1, Sd_2, Sd_3;
};

struct Id_Vector//短类型表(Vector)
{
	explicit Id_Vector(int Type, int Exac, std::string Code = "NULL", std::string Name = "NULL") :
		Type(Type), Exac(Exac), StrA(Code), StrB(Name), exac(new std::vector<Data_Vector*>) {}
	int Type, Exac;
	std::string StrA, StrB;
	std::vector<Data_Vector*>* exac;//用于支持折半查找
};

class TANXL_DataBase
{
private:
	struct
	{
		unsigned long Item_Status{ 0xFFFFFFFF };
		unsigned Status_1{ 0xF }; std::string Code{};
		unsigned Status_2{ 0xF }; std::string Name{};
		unsigned Status_3{ 0xFF }; std::string Oth1{};
		unsigned Status_4{ 0xFF }; std::string Oth2{};
		unsigned Status_5{ 0xFF }; std::string Oth3{};
	}Item_Instance;

	struct
	{
		unsigned int Item_Status{ 0xFFFF };//Type 8位 Exac 8位
		std::string Type{ "" };
		std::string Exac{ "" };
		Data_Unit* Data{ nullptr };
	};//Item_Instance V4

	const std::string _Version{ "1.9" };
	std::vector<Id_Vector*>* IC_Vector;
	int Current_Location;
	bool Is_Instance_Data;//用来判断Item_Instance中是否有数据
	bool Is_Chain_Empty;//用来判断链表是否为空
	Id_Vector* Id_Chain_Locate(int Type, int Exac);//时间复杂度为logN的Id_Chain快速定位函数 Type Exac 指Id_Chain的同名变量
	Data_Vector* Data_Chain_Locate(int Type, int Exac, int Depth);//借由Id_Chain_Locate函数对不同深度的Data_Chain定位
	void Replace_Chain(int OldType, int OldExac, int OldDepth, int Type, int Exac);//转移Data_Chain到另一个Id_Chain下
	void Append_Chain(Data_Vector& New_Data, Id_Vector& New_Id);//链表添加内容V3 添加到Vector中
	void Get_Item_Status();//获取物品数值 并加载到结构中
	void Clear_Chain();//清理链表
	void ResetInstance();//重置Item结构的内容
	inline void OstreamSpace(std::ostream& os, int Before = 0, int After = 0);//根据级别输出空格 Before用于执行前对级别数值进行修改 After用于执行后
	inline void Combine_Status();//组合Status各物品级别并合并到Item_Instance中
public:
	TANXL_DataBase();//构造函数
	bool Get_LocalData(std::string File_Name);//获取本地数据 并新建一个链表 支持打开任意格式的文件(.usd .sd)
	//↓编辑实例 0x12030405 1代表Code位 2代表Name位 03代表Oth1位 依此类推
	//↓在1.7版本中考虑到零合法的操作一致性 最大值已被作为不可选标志即 Code/Name位的F 或Oth位的FF
	void Set_Instance(unsigned Num, std::string Set);
	//↓读取指定Type(A)_Exac(B)级别的物品 并载入到单例结构中 Nums表示该级别下的第几个物品(从0开始)
	void Get_Specified(int Type, int Exac, int Nums);
	//↓修改指定Type(A)_Exac(B)级别的物品 Nums表示链表中的第几个(从0开始) level取值范围为1~5 用于选定Type Exac Oth1 ...
	//↓修改OTH1 OTH2 OTH3的时候直接更改相关内容 修改TYPE-EXAC时 会转移当前Data_Chain到新的符合修改后的TYPE-EXAC的Id_Chain下
	void Set_Specified(int Type, int Exac, int Nums, int level, int Id, std::string Data);
	void Remove_Chain(int Type, int Exac);//删除某一节点与其下所有内容
	//↓输出当前内存中的链表的所有内容 仅支持输出Id_Vector和Data_Vector中的内容 当前内存为空时会抛出错误
	void Print_Data();
	//↓向本地文件中(.usd)添加Item物品 此函数会导致Item单例重置
	void AppendItem(bool To_File = true, std::string File_Name = "Tanxl_DataBase");
	//↓使本地(.usd)文件的内容合理化 In_File_Name为输入文件名 Out_File_Name为输出文件名 现在具有保存链表修改功能
	//↓Mode为true时从文件中读取数据 需要提供In/Out_File_Name 执行后清空内存中的链表  Mode为false时直接对当前内存中的链表进行整理 可以使现有链表改为升序 执行后不清空
	//↓Delete_After_Sort为true时 在数据处理完成之后会删除处理前的原文件 为false则不会删除
	void SortDataBase(int Mode = SORT_LOCALF, std::string Out_File_Name = "Tanxl_Data", std::string In_File_Name = "Tanxl_DataBase",bool Delete_After_Sort = false);
	//↓获取当前存储模块的版本信息
	const std::string Get_Version();
	friend std::ostream& operator<<(std::ostream& fot, TANXL_DataBase& Taxnl_Data);//用于直接输出当前Item单例内的信息
};

namespace TanxlDB
{
	std::string Combine_Char(std::string data, int Start, int End);//拆分char数组获取指定内容,Start为开始位置End为结束位置(结束位置不保留)

	std::string Divid_Char(std::string data, int Mode = GET_STATUS_DAT);//拆分单行内容获取信息

	void Reset_Chain(TANXL_DataBase& TDB, int Type, int Exac, int Nums);//重置链表某一单元 Nums表示A,B level下的第几个(从0开始)

	void Data(bool Mode = true, unsigned Length_Each = 5);//测试用默认数据 为true时每次添加的同时还会在屏幕上打印 Length_Each为每个分类数据的长度 总共四个分类

	void Combine_File(std::string FileA, std::string FileB);//将FileA和FileB的内容整合到FileA中 仅限USD格式文件使用
}

#endif

更新详情

// 移除五个不必要的内部接口inline设置
// 修复三十二位的获取Status函数采用二十位操作方式的错误
// 储存模块设置物品函数执行效率提升
// 修改一个私有变量名称使之贴合意思
// Reset_Chain接口现在需要传入地址
// 重新修订重复包含检查
// 为匿名结构体成员增加初始化
// 增加版本变量与获取接口
// AppendItem接口默认添加文件到usd格式下
// 修改数据结构体的默认Id为0xF 即不可用状态
// AppendItem任何形式的添加都会导致私有结构体重置
// 结构体重置函数现在默认重置所有值到0xF
// 修正一些判断仍然以0合法为准的问题
// 设置私有结构体功能去掉不必要的判断
// 设置匿名结构体的函数性能优化
// 文件整理函数新增两个特殊处理功能
// 提供数据结构体Data_Vector的V4版本
// 数据整理功能可选择是否处理完成后删除原文件
// 修复设置存储结构体的OTH3位以及按位异或错误的问题
// 移除零/满合法的设定(数据为15进制,忽略0xF)
// 为五个额外的特殊功能限定名称空间
// 指针初始化采用nullptr替代NULL
// 增加stoi的异常处理机制
// 默认数据功能现在可设置输出数量

源文件代码

#pragma once

#include "Tanxl_DataBase.h"

namespace TanxlDB
{
	std::string Combine_Char(std::string data, int Start, int End)
	{
		if (End < Start)
		{
			throw "错误 : Combine_Char 的输入值Start大于End的值";
			return "";
		}
		std::string New_data{};
		for (int i = Start, j = 0; i < End; ++i, ++j)
		{
			if (data[i] == '\t' || data[i] == '<')
			{
				End++; j--;
				continue;
			}
			if (j < 0)j = 0;
			New_data = New_data + data[i];
		}
		return New_data;
	}

	std::string Divid_Char(std::string data, int Mode)
	{
		int Lock{ -1 }, Last{ -1 };
		char Left, Right;
		switch (Mode)
		{
		case GET_STATUS_DAT://获取单例数据0~15
			Left = '/'; Right = '>';
			break;
		case GET_STORAG_DAT://获取储存的信息
			Left = '>'; Right = '<';
			break;
		case GET_STATUS_TAG://信息条目
			Left = '<'; Right = ':';
			break;
		case GET_STATUS_STR://V3链表主副键String
			Left = ':'; Right = '/';
			break;
		case GET_OLDSTY_DAT:
			Left = ':'; Right = '>';
			break;
		default:
			throw "错误 : Divid_Char 没有此条目的功能(0~4 为合法内容,而你输入了" + std::to_string(Mode) + ")";
			return "";
		}
		for (int i = 0; i < data.length(); ++i)//获取内容
		{
			if ((data[i] == Left && Lock == -1) || (data[i] == Right && Lock != -1))
			{
				if (Lock == -1)
				{
					Lock = i + 1;
					continue;
				}
				else
					Last = i;
			}
			if (Lock != -1 && Last != -1)
				return Combine_Char(data, Lock, Last);
		}
		throw "失败 : Divid_Char 读取错误 不存在满足条件的内容";
		return "";
	}

	void Reset_Chain(TANXL_DataBase& TDB, int A, int B, int Nums)
	{
		TDB.Set_Specified(A, B, Nums, 3, -1, "NULL");
		TDB.Set_Specified(A, B, Nums, 4, -1, "NULL");
		TDB.Set_Specified(A, B, Nums, 5, -1, "NULL");
	}

	void Data(bool Mode, unsigned Length_Each)
	{
		TANXL_DataBase TDB_Instance;
		for (unsigned Content = (0x11112000 - Length_Each); Content != 0x11112000; ++Content)
		{
			TDB_Instance.Set_Instance(0x10000000 | 0x0fffffff, "手枪");
			TDB_Instance.Set_Instance((Content & 0x0f000000) | 0xf0ffffff, "地下水");
			TDB_Instance.Set_Instance((Content & 0x00ff0000) | 0xff00ffff, std::to_string(rand() % 100));
			TDB_Instance.Set_Instance((Content & 0x0000ff00) | 0xffff00ff, std::to_string(rand() % 100));
			TDB_Instance.Set_Instance((Content & 0x000000ff) | 0xffffff00, std::to_string(rand() % 100));
			if (Mode)std::cout << TDB_Instance;
			TDB_Instance.AppendItem();
		}
		for (unsigned Content = 0x22222000 - Length_Each; Content != 0x22222000; ++Content)
		{
			TDB_Instance.Set_Instance(0x20000000 | 0x0fffffff, "步枪");
			TDB_Instance.Set_Instance(Content & 0x0f000000 | 0xf0ffffff, "M4A1-S");
			TDB_Instance.Set_Instance(Content & 0x00ff0000 | 0xff00ffff, std::to_string(rand() % 100));
			TDB_Instance.Set_Instance(Content & 0x0000ff00 | 0xffff00ff, std::to_string(rand() % 100));
			TDB_Instance.Set_Instance(Content & 0x000000ff | 0xffffff00, std::to_string(rand() % 100));
			if (Mode)std::cout << TDB_Instance;
			TDB_Instance.AppendItem();
		}
		for (unsigned Content = 0x33332000 - Length_Each; Content != 0x33332000; ++Content)
		{
			TDB_Instance.Set_Instance(0x30000000 | 0x0fffffff, "重型武器");
			TDB_Instance.Set_Instance(Content & 0x0f000000 | 0xf0ffffff, "Nova");
			TDB_Instance.Set_Instance(Content & 0x00ff0000 | 0xff00ffff, std::to_string(rand() % 100));
			TDB_Instance.Set_Instance(Content & 0x0000ff00 | 0xffff00ff, std::to_string(rand() % 100));
			TDB_Instance.Set_Instance(Content & 0x000000ff | 0xffffff00, std::to_string(rand() % 100));
			if (Mode)std::cout << TDB_Instance;
			TDB_Instance.AppendItem();
		}
		for (unsigned Content = 0x44442000 - Length_Each; Content != 0x44442000; ++Content)
		{
			TDB_Instance.Set_Instance(0x40000000 | 0x0fffffff, "微型冲锋枪");
			TDB_Instance.Set_Instance(Content & 0x0f000000 | 0xf0ffffff, "MP9");
			TDB_Instance.Set_Instance(Content & 0x00ff0000 | 0xff00ffff, std::to_string(rand() % 100));
			TDB_Instance.Set_Instance(Content & 0x0000ff00 | 0xffff00ff, std::to_string(rand() % 100));
			TDB_Instance.Set_Instance(Content & 0x000000ff | 0xffffff00, std::to_string(rand() % 100));
			if (Mode)std::cout << TDB_Instance;
			TDB_Instance.AppendItem();
		}
	}

	void Combine_File(std::string FileA, std::string FileB)
	{
		std::string Line{};
		std::fstream in(FileB + ".usd", std::ios::in);
		if (!in.is_open())
			std::fstream in(FileB + ".sd", std::ios::in);
		std::fstream out(FileA + ".sd", std::ios::app);
		if (in.is_open() && out.is_open())
		{
			out << std::endl;
			while (std::getline(in, Line))
				out << Line << std::endl;
		}
		else
			throw "失败 : Combine_File 无法打开的指定文件";
	}
}

std::ostream& operator<<(std::ostream& fot, TANXL_DataBase& s)
{
	if (s.Item_Instance.Status_1 + s.Item_Instance.Status_2 + s.Item_Instance.Status_3 + s.Item_Instance.Status_4 + s.Item_Instance.Status_5)
	{
		//s.Get_Item_Status();
		fot << "<Type_Status : " << s.Item_Instance.Code << " / " << s.Item_Instance.Status_1 << ">" << std::endl;
		s.OstreamSpace(fot, 1); fot << "<Exac_Status : " << s.Item_Instance.Name << " / " << s.Item_Instance.Status_2 << ">" << std::endl;
		s.OstreamSpace(fot, 1, 1); fot << "<TDBS_Item>" << std::endl;
		if (s.Item_Instance.Status_3 != 0xFF) {
			s.OstreamSpace(fot);
			fot << "<Oth1: " << s.Item_Instance.Status_3 << ">" << s.Item_Instance.Oth1 << "</Oth1>" << std::endl;
		}
		if (s.Item_Instance.Status_4 != 0xFF) {
			s.OstreamSpace(fot);
			fot << "<Oth2: " << s.Item_Instance.Status_4 << ">" << s.Item_Instance.Oth2 << "</Oth2>" << std::endl;
		}
		if (s.Item_Instance.Status_5 != 0xFF) {
			s.OstreamSpace(fot);
			fot << "<Oth3: " << s.Item_Instance.Status_5 << ">" << s.Item_Instance.Oth3 << "</Oth3>" << std::endl;
		}
		s.OstreamSpace(fot, -1); fot << "</TDBS_Item>" << std::endl;
		s.OstreamSpace(fot, -1); fot << "</Exac_Status>" << std::endl;
		s.OstreamSpace(fot, -1); fot << "</Type_Status>" << std::endl;
	}
	return fot;
}

TANXL_DataBase::TANXL_DataBase() :
	Is_Instance_Data(false), Is_Chain_Empty(true),
	IC_Vector(new std::vector<Id_Vector*>),Current_Location(0) {}

inline void TANXL_DataBase::OstreamSpace(std::ostream& os, int Before, int After)
{
	static int TDB_Status = 0;//级别数值 用于记录当前行的Tab数量
	TDB_Status += Before;
	for (int i = 0; i < TDB_Status; ++i)os << "\t";
	TDB_Status += After;
}

inline void TANXL_DataBase::Combine_Status()
{
	Item_Instance.Item_Status = 
		  (Item_Instance.Status_1 << 28)
		+ (Item_Instance.Status_2 << 24)
		+ (Item_Instance.Status_3 << 16)
		+ (Item_Instance.Status_4 << 8 )
		+  Item_Instance.Status_5;
}

void TANXL_DataBase::ResetInstance()
{
	Item_Instance.Status_1 = 0xF;
	Item_Instance.Status_2 = 0xF;
	Item_Instance.Status_3 = 0xFF;
	Item_Instance.Status_4 = 0xFF;
	Item_Instance.Status_5 = 0xFF;
	Item_Instance.Item_Status = 0xFFFFFFFF;
	Combine_Status();
	Is_Instance_Data = false;
}

void TANXL_DataBase::Set_Instance(unsigned Num, std::string Set)
{
	bool SetTimes{ false };
	if ((Num >> 28) < 15) {
		Item_Instance.Code = Set;
		Item_Instance.Status_1 = (Num >> 28);
		Item_Instance.Item_Status ^= (0xF << 28);
		Item_Instance.Item_Status |= Item_Instance.Status_1 << 28;
		SetTimes = true;
	}
	if (((Num & 0x0f000000) >> 24) < 15) {
		Item_Instance.Name = Set;
		Item_Instance.Status_2 = ((Num & 0x0f000000) >> 24);
		Item_Instance.Item_Status ^= (0xF << 24);
		Item_Instance.Item_Status |= Item_Instance.Status_2 << 24;
		SetTimes = true;
	}
	if (((Num & 0x00ff0000) >> 16) < 255) {
		Item_Instance.Oth1 = Set;
		Item_Instance.Status_3 = ((Num & 0x00ff0000) >> 16);
		Item_Instance.Item_Status ^= (0xFF << 16);
		Item_Instance.Item_Status |= Item_Instance.Status_3 << 16;
		SetTimes = true;
	}
	if (((Num & 0x0000ff00) >> 8) < 255) {
		Item_Instance.Oth2 = Set;
		Item_Instance.Status_4 = ((Num & 0x0000ff00) >> 8);
		Item_Instance.Item_Status ^= (0xFF << 8);
		Item_Instance.Item_Status |= Item_Instance.Status_4 << 8;
		SetTimes = true;
	}
	if ((Num & 0x000000ff) < 255) {
		Item_Instance.Oth3 = Set;
		Item_Instance.Status_5 = (Num & 0x000000ff);
		Item_Instance.Item_Status ^= 0xFF;
		Item_Instance.Item_Status |= Item_Instance.Status_5;
		SetTimes = true;
	}
	if (SetTimes)
		Is_Instance_Data = true;
}

void TANXL_DataBase::AppendItem(bool To_File, std::string File_Name)
{
	if (!Is_Instance_Data)
	{
		throw "添加失败! 结构内容为空";
		return;
	}
	else if (To_File)
	{
		Is_Instance_Data = true;
		std::fstream out(File_Name + ".usd", std::ios::app);
		if (out.is_open())
		{
			out << *this;
			this->ResetInstance();
			out.close();
		}
	}
	else
	{
		Data_Vector* DTemp = new Data_Vector(
			Item_Instance.Status_3, Item_Instance.Oth1,
			Item_Instance.Status_4, Item_Instance.Oth2,
			Item_Instance.Status_5, Item_Instance.Oth3);
		Id_Vector* ITemp = new Id_Vector(
			Item_Instance.Status_1, Item_Instance.Status_2,
			Item_Instance.Code, Item_Instance.Name);
		this->ResetInstance();
		if (DTemp && ITemp)//判断是否申请空间成功
			Append_Chain(*DTemp, *ITemp);
		else
			throw "添加失败! 申请内存空间失败";
	}
}

void TANXL_DataBase::SortDataBase(int Mode, std::string Out_File_Name, std::string In_File_Name, bool Delete_After_Sort)
{
	if (Mode == SORT_LOCALF || Mode == FILE_UNITED)
		if (!Get_LocalData(In_File_Name))
		{
			throw "SortDataBase() Failed ! : 未能成功匹配文件";
			return;
		}
	if (Is_Chain_Empty)
	{
		throw "SortDataBase() Failed ! : 获取到的数据为空";
		return;
	}
	std::fstream out(Out_File_Name + ".sd", std::ios::out | std::ios::trunc);
	Id_Vector* PIC{ this->IC_Vector->at(0) };
	out << "<Tanxl_DataBase Information>" << std::endl;
	std::vector<Id_Vector*>::iterator IOIE{ IC_Vector->end() };
	std::vector<Id_Vector*>::iterator IOIB{ IC_Vector->begin() };
	do
	{
		std::vector<Data_Vector*>::iterator IODE{ (*IOIB)->exac->end() };
		std::vector<Data_Vector*>::iterator IODB{ (*IOIB)->exac->begin() };
		std::cout << "\t<Type_Status : " << (*IOIB)->StrA << " / " << (*IOIB)->Type << ">" << std::endl;
		std::cout << "\t\t<Exac_Status : " << (*IOIB)->StrB << " / " << (*IOIB)->Exac << ">" << std::endl;
		out << "\t<Type_Status : " << (*IOIB)->StrA << " / " << (*IOIB)->Type << ">" << std::endl;
		out << "\t\t<Exac_Status : " << (*IOIB)->StrB << " / " << (*IOIB)->Exac << ">" << std::endl;
		do
		{
			std::string TAG = DataTag((*IOIB)->Type, (*IOIB)->Exac, (*IODB)->Id_1);
			std::string TAG_OTH1 = TAG == "" ? "OTH1" : TAG;
			TAG = DataTag((*IOIB)->Type, (*IOIB)->Exac, (*IODB)->Id_2);
			std::string TAG_OTH2 = TAG == "" ? "OTH2" : TAG;
			TAG = DataTag((*IOIB)->Type, (*IOIB)->Exac, (*IODB)->Id_3);
			std::string TAG_OTH3 = TAG == "" ? "OTH3" : TAG;
			if ((*IODB)->Id_1 + (*IODB)->Id_2 + (*IODB)->Id_3 == -3)
				continue;
			if (Mode ^ 0x1)
				out << "\t\t\t<TDB_Item>" << std::endl;
			if ((*IODB)->Id_1 != 0xFF)
			{
				if (Mode ^ 0x1)out << "\t";
				out << "\t\t\t<" + TAG_OTH1 + ": " << (*IODB)->Id_1 << ">" << (*IODB)->Sd_1 << "</Oth1>" << std::endl;
			}
			if ((*IODB)->Id_2 != 0xFF)
			{
				if (Mode ^ 0x1)out << "\t";
				out << "\t\t\t<" + TAG_OTH2 + ": " << (*IODB)->Id_2 << ">" << (*IODB)->Sd_2 << "</Oth2>" << std::endl;
			}
			if ((*IODB)->Id_3 != 0xFF)
			{
				if (Mode ^ 0x1)out << "\t";
				out << "\t\t\t<" + TAG_OTH3 + ": " << (*IODB)->Id_3 << ">" << (*IODB)->Sd_3 << "</Oth3>" << std::endl;
			}
			if (Mode ^ 0x1)
				out << "\t\t\t</TDB_Item>" << std::endl;
			++IODB;
		} while (IODB != IODE);
		out << "\t\t</Exac_Status>" << std::endl;
		out << "\t</Type_Status>" << std::endl;
		++IOIB;
	} while (IOIB != IOIE);
	out << "</Tanxl_DataBase Information>" << std::endl;
	out.close();
	Clear_Chain();
	if (Delete_After_Sort)
	{
		if (Mode == SORT_LOCALF || Mode == FILE_UNITED)
		{
			std::string s = In_File_Name + ".usd";
			remove(s.c_str());
		}
	}
}

void TANXL_DataBase::Append_Chain(Data_Vector& New_Data, Id_Vector& New_Id)
{
	if (Is_Chain_Empty)
	{
		IC_Vector->push_back(&New_Id);
		IC_Vector->at(0)->exac->push_back(&New_Data);
		Is_Chain_Empty = false;
		return;
	}
	int Left{ 0 }, Value{ New_Id.Type * 16 + New_Id.Exac },
		Right{ static_cast<int>(IC_Vector->size()) - 1 <= 0 ? 0 : static_cast<int>(IC_Vector->size()) - 1 };
	while (true)
	{
		int Mid{ (Left + Right) / 2 };
		Id_Vector* PIC = IC_Vector->at(Mid);
		int PIC_Value{ PIC->Type * 16 + PIC->Exac };
		if (PIC_Value == Value)//Type B匹配时
		{
			PIC->exac->push_back(&New_Data);
			Is_Chain_Empty = false;
			return;
		}
		else if (Left == Right && PIC_Value != Value)//Type B不匹配 但已经是最接近的值时
		{
			if (PIC_Value < Value)
				Left += 1;
			this->IC_Vector->insert(IC_Vector->begin() + Left, &New_Id);
			IC_Vector->at(Left)->exac->push_back(&New_Data);
			Is_Chain_Empty = false;
			return;
		}
		else if (PIC_Value < Value)
			Left = Mid;
		else if (PIC_Value > Value)
			Right = Mid;
		if (Left + 1 == Right)
		{
			if (PIC_Value < Value)
				Left = Right;
			else Right = Left;
		}
	}
	throw "Append() Failed ! : 未知原因";
	return;
}

bool TANXL_DataBase::Get_LocalData(std::string File_Name)
{
	std::fstream in(File_Name + ".usd", std::ios::in);
	if (!in.is_open())
		std::fstream in(File_Name + ".sd", std::ios::in);
	if (in.is_open())
	{
		std::string Type_Data{}, Exac_Data{};//需要使用时再定义
		int  Type_Stat{}, Exac_Stat{};
		int IData[3]{ 0xFF,0xFF,0xFF }, Target{ -1 };
		std::string SData[3]{};
		std::string Line{};
		while (std::getline(in, Line))
		{
			std::string Tag{ TanxlDB::Combine_Char(Line, 1, 5) };
			if (Tag == "Type")
			{
				try
				{
					Type_Stat = std::stoi(TanxlDB::Divid_Char(Line, GET_STATUS_DAT));
					Type_Data = TanxlDB::Divid_Char(Line, GET_STATUS_STR);
					std::getline(in, Line);
					Exac_Stat = std::stoi(TanxlDB::Divid_Char(Line, GET_STATUS_DAT));
					Exac_Data = TanxlDB::Divid_Char(Line, GET_STATUS_STR);
				}
				catch (std::invalid_argument&)
				{
					std::cout << "Invalid argument :" << TanxlDB::Divid_Char(Line, GET_STATUS_DAT) << ", Reset to zero" << std::endl;
					Type_Stat = 0;
					Exac_Stat = 0;
				}
				catch (std::out_of_range&)
				{
					std::cout << "Out of range :" << TanxlDB::Divid_Char(Line, GET_STATUS_DAT) << ", Reset to zero" << std::endl;
					Type_Stat = 0;
					Exac_Stat = 0;
				}
				while (std::getline(in, Line))
				{
					Tag = TanxlDB::Combine_Char(Line, 1, 5);
					if (Tag == "Type")
					{
						try
						{
							Type_Stat = std::stoi(TanxlDB::Divid_Char(Line, GET_STATUS_DAT));
						}
						catch (std::invalid_argument&)
						{
							std::cout << "Invalid argument :" << TanxlDB::Divid_Char(Line, GET_STATUS_DAT) << ", Reset to zero" << std::endl;
							Type_Stat = 0;
						}
						catch (std::out_of_range&)
						{
							std::cout << "Out of range :" << TanxlDB::Divid_Char(Line, GET_STATUS_DAT) << ", Reset to zero" << std::endl;
							Type_Stat = 0;
						}
						Type_Data = TanxlDB::Divid_Char(Line, GET_STATUS_STR);
					}
					else if (Tag == "Exac")
					{
						try
						{
							Exac_Stat = std::stoi(TanxlDB::Divid_Char(Line, GET_STATUS_DAT));
						}
						catch (std::invalid_argument&)
						{
							std::cout << "Invalid argument :" << TanxlDB::Divid_Char(Line, GET_STATUS_DAT) << ", Reset to zero" << std::endl;
							Exac_Stat = 0;
						}
						catch (std::out_of_range&)
						{
							std::cout << "Out of range :" << TanxlDB::Divid_Char(Line, GET_STATUS_DAT) << ", Reset to zero" << std::endl;
							Exac_Stat = 0;
						}
						Exac_Data = TanxlDB::Divid_Char(Line, GET_STATUS_STR);
					}
					else if (Tag == "/TDB")
					{
						Data_Vector* Data_Temp = new Data_Vector(IData[0], SData[0], IData[1], SData[1], IData[2], SData[2]);
						Id_Vector* Id_Temp = new Id_Vector(Type_Stat, Exac_Stat, Type_Data, Exac_Data);
						IData[0] = 0xFF; IData[1] = 0xFF; IData[2] = 0xFF; SData[0] = ""; SData[1] = ""; SData[2] = "";
						if (Data_Temp && Id_Temp)
							Append_Chain(*Data_Temp, *Id_Temp);
						else
							throw "添加失败! 申请内存空间失败";
						continue;
					}
					else if (Tag == "Oth1")
						Target = 0;
					else if (Tag == "Oth2")
						Target = 1;
					else if (Tag == "Oth3")
						Target = 2;
					if (Target == -1)
						continue;
					try
					{
						IData[Target] = std::stoi(TanxlDB::Divid_Char(Line, GET_OLDSTY_DAT));
					}
					catch (std::invalid_argument&)
					{
						std::cout << "Invalid argument :" << TanxlDB::Divid_Char(Line, GET_OLDSTY_DAT) << ", Reset to zero" << std::endl;
						IData[Target] = 0;
					}
					catch (std::out_of_range&)
					{
						std::cout << "Out of range :" << TanxlDB::Divid_Char(Line, GET_OLDSTY_DAT) << ", Reset to zero" << std::endl;
						IData[Target] = 0;
					}
					SData[Target] = TanxlDB::Divid_Char(Line, GET_STORAG_DAT);
					Target = -1;
				}
			}
		}
		in.close();
		return true;
	}
	else
		return false;
}

void TANXL_DataBase::Clear_Chain()
{
	for (int i = 0; i < IC_Vector->size(); ++i)
		Remove_Chain(IC_Vector->at(i)->Type, IC_Vector->at(i)->Exac);
	Is_Chain_Empty = true;
}

void TANXL_DataBase::Get_Specified(int Type, int Exac, int Nums)
{
	if (Data_Vector * PDC{ Data_Chain_Locate(Type, Exac, Nums) })
	{
		Id_Vector* PIC = { Id_Chain_Locate(Type, Exac) };
		Item_Instance.Status_1 = PIC->Type;  Item_Instance.Code = PIC->StrA;
		Item_Instance.Status_2 = PIC->Exac;  Item_Instance.Name = PIC->StrB;
		Item_Instance.Status_3 = PDC->Id_1;  Item_Instance.Oth1 = PDC->Sd_1;
		Item_Instance.Status_4 = PDC->Id_2;  Item_Instance.Oth2 = PDC->Sd_2;
		Item_Instance.Status_5 = PDC->Id_3;  Item_Instance.Oth3 = PDC->Sd_3;
		Combine_Status();
		return;
	}
	throw "Get_Specified() Failed ! : 未能成功匹配相同值";
}

void TANXL_DataBase::Get_Item_Status()
{
	Item_Instance.Status_1 = ((Item_Instance.Item_Status & 0xf0000000) >> 28);
	Item_Instance.Status_2 = ((Item_Instance.Item_Status & 0x0f000000) >> 24);
	Item_Instance.Status_3 = ((Item_Instance.Item_Status & 0x00ff0000) >> 16);
	Item_Instance.Status_4 = ((Item_Instance.Item_Status & 0x0000ff00) >>  8);
	Item_Instance.Status_5 = ( Item_Instance.Item_Status & 0x000000ff       );
}

void TANXL_DataBase::Print_Data()//输出当前链表中的所有内容 V3 Updated
{
	if (!Is_Chain_Empty)
	{
		Id_Vector* PIC{ nullptr };
		Data_Vector* PDC{ nullptr };
		int PIC_Count{ 0 };
		std::vector<Id_Vector*>::iterator IOI = (IC_Vector->end() - 1);
		do
		{
			int PDC_Count{ 0 };
			PIC = this->IC_Vector->at(PIC_Count++);
			std::vector<Data_Vector*>::iterator IOD = (PIC->exac->end() - 1);
			std::cout << "Id_Vector :" << PIC->Type << " - " << PIC->StrA << " - " << PIC->Exac << " - " << PIC->StrB << std::endl;
			do
			{
				PDC = PIC->exac->at(PDC_Count++);
				std::cout << "\tData_Vector :" << PDC->Id_1 << "-" << PDC->Id_2 << "-" << PDC->Id_3 << std::endl;
			} while (PDC != *IOD);
		} while (PIC != *IOI);
		return;
	}
	throw "Print_Data() Failed ! : 链表内容为空";
}

void TANXL_DataBase::Set_Specified(int Type, int Exac, int Nums, int level, int Id, std::string Data) //V3 Updated
{
	if (Data_Vector * PDC{ Data_Chain_Locate(Type, Exac, Nums) })
		switch (level)
		{
		case SET_TYPE_STATUS:
			Replace_Chain(Type, Exac, Nums, Id, Exac);
			return;
		case SET_EXAC_STATUS:
			Replace_Chain(Type, Exac, Nums, Type, Id);
			return;
		case SET_OTH1_STATUS:
			PDC->Id_1 = Id;
			PDC->Sd_1 = Data;
			return;
		case SET_OTH2_STATUS:
			PDC->Id_2 = Id;
			PDC->Sd_2 = Data;
			return;
		case SET_OTH3_STATUS:
			PDC->Id_3 = Id;
			PDC->Sd_3 = Data;
			return;
		}
	throw "Set_Specified() Failed ! : 查找相关内容不成功或链表内容为空";
}

void TANXL_DataBase::Remove_Chain(int Type, int Exac)
{
	if (Id_Vector * PIC{ Id_Chain_Locate(Type, Exac) })
	{
		for (int i{ 0 }; i < PIC->exac->size(); ++i)
			delete PIC->exac->at(i);//释放 Data_Vector
		PIC->exac->clear();
		delete PIC;//释放 Id_Vector
		IC_Vector->erase(IC_Vector->begin() + Current_Location);
	}
}

Id_Vector* TANXL_DataBase::Id_Chain_Locate(int Type, int Exac)
{
	int Left{ 0 },Value{ Type * 16 + Exac },
		Right{ static_cast<int>(IC_Vector->size()) - 1 >= 0 ? static_cast<int>(IC_Vector->size()) - 1 : 0 };;
	if (Left == Right)
	{
		if (Value == IC_Vector->at(0)->Type * 16 + IC_Vector->at(0)->Exac)
		{
			Current_Location = 0;
			return IC_Vector->at(0);
		}
		throw "Id_Chain_Locate Failed ! : 未能成功匹配相同值";
		return nullptr;
	}
	else
	{
		while (Left != Right)
		{
			int Mid{ (Left + Right) / 2 };
			int Mid_Value{ IC_Vector->at(Mid)->Type * 16 + IC_Vector->at(Mid)->Exac };
			if (Mid_Value == Value)
			{
				Current_Location = Mid;
				return IC_Vector->at(Mid);
			}
			else if (Mid_Value > Value)
				Right = Mid;
			else if (Mid_Value < Value)
				Left = Mid;
			if (Left == Right)
			{
				throw "Id_Chain_Locate Failed ! : 未能成功匹配相同值";
				return nullptr;
			}
		}
	}
	throw "Id_Chain_Locate Failed ! : 未知原因";
	return nullptr;
}

Data_Vector* TANXL_DataBase::Data_Chain_Locate(int Type, int Exac, int Depth)
{
	Id_Vector* PIC{ Id_Chain_Locate(Type, Exac) };
	if (PIC->exac->size() < Depth)
	{
		throw "Data_Chain_Locate Failed ! : 超出当前容器最大深度";
		return nullptr;
	}
	else if (Depth < 0 && Depth + static_cast<int>(PIC->exac->size()) >= 0)
		return PIC->exac->at(Depth + PIC->exac->size());
	while (Depth + static_cast<int>(PIC->exac->size() < 0))
		Depth += static_cast<int>(PIC->exac->size());
	return PIC->exac->at(Depth);
}

void TANXL_DataBase::Replace_Chain(int OldType, int OldExac, int OldDepth, int Type, int Exac)
{
	Id_Vector* PIC{ Id_Chain_Locate(OldType, OldExac) };
	Append_Chain(*PIC->exac->at(OldDepth), *new Id_Vector(Type, Exac));
	if (PIC->exac->size() > OldDepth && OldDepth >= 0)
		PIC->exac->erase(PIC->exac->begin() + OldDepth);
	else if (PIC->exac->size() + OldDepth >= 0 && PIC->exac->size() + OldDepth < PIC->exac->size())
		PIC->exac->erase(PIC->exac->begin() + PIC->exac->size() + OldDepth);
}

const std::string TANXL_DataBase::Get_Version()
{
	return this->_Version;
}

此模块已应用于TANXL_GAMEENGINE///VERSION 0.1 BUILD 64
TANXL///WiChG_2023/01/31-11:51

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

WiChP

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值