1 #pragma once
2 
3 #include <functional>
4 #include <vector>
5 #include <map>
6 #include "uv_helper.h"
7 #include "compress.h"
8 #include "cso.h"
9 #include "sector.h"
10 
11 namespace maxcso {
12 
13 typedef std::function<void (int64_t pos, int64_t total, int64_t written)> OutputCallback;
14 typedef std::function<void (bool status, const char *reason)> OutputFinishCallback;
15 
16 class Output {
17 public:
18 	Output(uv_loop_t *loop, const Task &task);
19 	~Output();
20 
21 	void SetFile(uv_file file, int64_t srcSize, uint32_t blockSize, CSOFormat fmt);
22 	void Enqueue(int64_t pos, uint8_t *buffer);
23 	bool QueueFull();
24 
25 	void OnProgress(OutputCallback callback);
26 	void OnFinish(OutputFinishCallback callback);
27 
28 private:
29 	void CheckFinish();
30 	void Flush();
31 	void WriteCSOIndex();
32 	void WriteDAXIndex();
33 	void HandleReadySector(Sector *sector);
34 	bool ShouldCompress(int64_t pos, uint8_t *buffer);
35 
36 	int32_t Align(int64_t &pos);
37 	inline int64_t SrcSizeAligned();
38 	int64_t DstFirstSectorPos(uint32_t totalSectors);
39 
40 	bool UpdateIndex(int64_t srcPos, int64_t dstPos, uint32_t compressedSize, SectorFormat compressedFmt);
41 
42 	enum State {
43 		STATE_INIT = 0x00,
44 		STATE_HAS_FILE = 0x01,
45 		STATE_INDEX_READY = 0x02,
46 		STATE_INDEX_WRITTEN = 0x04,
47 		STATE_DATA_WRITTEN = 0x08,
48 	};
49 
50 	UVHelper uv_;
51 	uv_loop_t *loop_;
52 	uint32_t flags_;
53 	uint32_t state_;
54 	CSOFormat fmt_;
55 	double origMaxCostPercent_;
56 	double lz4MaxCostPercent_;
57 
58 	uv_file file_;
59 	uv_fs_t flush_;
60 
61 	int64_t srcSize_;
62 	int64_t srcPos_;
63 	int64_t dstPos_;
64 
65 	uint32_t *index_;
66 	uint8_t indexShift_;
67 	uint32_t indexAlign_;
68 	uint32_t blockSize_;
69 	uint8_t blockShift_;
70 
71 	OutputCallback progress_;
72 	OutputFinishCallback finish_;
73 
74 	std::vector<Sector *> freeSectors_;
75 	std::map<int64_t, Sector *> pendingSectors_;
76 	std::unordered_map<uint32_t, Sector *> partialSectors_;
77 };
78 
79 };
80