blob: c0f1153af5baaf8ad004eb8b0eba729cd79df218 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
#include <map>
#include "AutoLock.h"
#include <bfc/platform/types.h>
class ProgressTracker
{
public:
static const uint64_t null_position;
ProgressTracker()
{
current_position=0;
current_chunk=0;
chunks[0]=0;
chunks[null_position]=null_position;
};
void Write(uint64_t bytes_written)
{
Nullsoft::Utility::AutoLock list_lock(list_guard);
ChunkList::iterator next, itr = chunks.find(current_chunk);
current_position += bytes_written;
if (itr->second < current_position)
itr->second = current_position;
for (;;)
{
next = itr;
++next;
if (next != chunks.end() && (next->first <= itr->second))
{
itr->second = next->second;
chunks.erase(next);
}
else
break;
}
}
bool Valid(uint64_t requested_position, uint64_t requested_end)
{
Nullsoft::Utility::AutoLock list_lock(list_guard);
for (ChunkList::iterator itr=chunks.begin();itr!=chunks.end();itr++)
{
if (requested_position >= itr->first)
{
if (requested_position < itr->second)
{
if (requested_end <= itr->second)
{
return true;
}
else
{
return false;
}
}
}
}
return false;
}
bool Seek(uint64_t requested_position, uint64_t requested_end, uint64_t *new_start, uint64_t *new_end)
{
Nullsoft::Utility::AutoLock list_lock(list_guard);
uint64_t last_good_start=0;
ChunkList::iterator itr;
for (itr=chunks.begin();itr!=chunks.end();itr++)
{
if (requested_position >= itr->first)
{
current_chunk = itr->first;
if (requested_position <= itr->second)
{
ChunkList::iterator next = itr;
++next;
*new_end = next->first;
*new_start = current_position = itr->second;
if (requested_end <= itr->second)
{
return true;
}
else
{
return false;
}
}
else
{
last_good_start = itr->second;
}
}
}
if (last_good_start > requested_position)
*new_start = current_position = last_good_start;
else
{
*new_start = current_chunk = current_position = requested_position;
chunks[current_chunk] = current_chunk;
}
*new_end = null_position;
return false;
}
#if 0
void Dump()
{
ChunkList::iterator itr;
for (itr=chunks.begin();itr!=chunks.end();itr++)
{
printf("%I64u - %I64u\n", itr->first, itr->second);
}
}
#endif
typedef std::map<uint64_t, uint64_t> ChunkList;
ChunkList chunks;
uint64_t current_chunk;
uint64_t current_position;
Nullsoft::Utility::LockGuard list_guard;
};
const uint64_t ProgressTracker::null_position = (uint64_t)-1;
|