1 /* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
2 /* If you are missing that file, acquire a complete release at teeworlds.com. */
6 #include <engine/storage.h>
8 #include "filecollection.h"
10 bool CFileCollection::IsFilenameValid(const char *pFilename
)
12 if(str_length(pFilename
) != m_FileDescLength
+TIMESTAMP_LENGTH
+m_FileExtLength
||
13 str_comp_num(pFilename
, m_aFileDesc
, m_FileDescLength
) ||
14 str_comp(pFilename
+m_FileDescLength
+TIMESTAMP_LENGTH
, m_aFileExt
))
17 pFilename
+= m_FileDescLength
;
18 if(pFilename
[0] == '_' &&
19 pFilename
[1] >= '0' && pFilename
[1] <= '9' &&
20 pFilename
[2] >= '0' && pFilename
[2] <= '9' &&
21 pFilename
[3] >= '0' && pFilename
[3] <= '9' &&
22 pFilename
[4] >= '0' && pFilename
[4] <= '9' &&
23 pFilename
[5] == '-' &&
24 pFilename
[6] >= '0' && pFilename
[6] <= '9' &&
25 pFilename
[7] >= '0' && pFilename
[7] <= '9' &&
26 pFilename
[8] == '-' &&
27 pFilename
[9] >= '0' && pFilename
[9] <= '9' &&
28 pFilename
[10] >= '0' && pFilename
[10] <= '9' &&
29 pFilename
[11] == '_' &&
30 pFilename
[12] >= '0' && pFilename
[12] <= '9' &&
31 pFilename
[13] >= '0' && pFilename
[13] <= '9' &&
32 pFilename
[14] == '-' &&
33 pFilename
[15] >= '0' && pFilename
[15] <= '9' &&
34 pFilename
[16] >= '0' && pFilename
[16] <= '9' &&
35 pFilename
[17] == '-' &&
36 pFilename
[18] >= '0' && pFilename
[18] <= '9' &&
37 pFilename
[19] >= '0' && pFilename
[19] <= '9')
43 int64
CFileCollection::ExtractTimestamp(const char *pTimestring
)
45 int64 Timestamp
= pTimestring
[0]-'0'; Timestamp
<<= 4;
46 Timestamp
+= pTimestring
[1]-'0'; Timestamp
<<= 4;
47 Timestamp
+= pTimestring
[2]-'0'; Timestamp
<<= 4;
48 Timestamp
+= pTimestring
[3]-'0'; Timestamp
<<= 4;
49 Timestamp
+= pTimestring
[5]-'0'; Timestamp
<<= 4;
50 Timestamp
+= pTimestring
[6]-'0'; Timestamp
<<= 4;
51 Timestamp
+= pTimestring
[8]-'0'; Timestamp
<<= 4;
52 Timestamp
+= pTimestring
[9]-'0'; Timestamp
<<= 4;
53 Timestamp
+= pTimestring
[11]-'0'; Timestamp
<<= 4;
54 Timestamp
+= pTimestring
[12]-'0'; Timestamp
<<= 4;
55 Timestamp
+= pTimestring
[14]-'0'; Timestamp
<<= 4;
56 Timestamp
+= pTimestring
[15]-'0'; Timestamp
<<= 4;
57 Timestamp
+= pTimestring
[17]-'0'; Timestamp
<<= 4;
58 Timestamp
+= pTimestring
[18]-'0';
63 void CFileCollection::BuildTimestring(int64 Timestamp
, char *pTimestring
)
66 pTimestring
[18] = (Timestamp
&0xF)+'0'; Timestamp
>>= 4;
67 pTimestring
[17] = (Timestamp
&0xF)+'0'; Timestamp
>>= 4;
68 pTimestring
[16] = '-';
69 pTimestring
[15] = (Timestamp
&0xF)+'0'; Timestamp
>>= 4;
70 pTimestring
[14] = (Timestamp
&0xF)+'0'; Timestamp
>>= 4;
71 pTimestring
[13] = '-';
72 pTimestring
[12] = (Timestamp
&0xF)+'0'; Timestamp
>>= 4;
73 pTimestring
[11] = (Timestamp
&0xF)+'0'; Timestamp
>>= 4;
74 pTimestring
[10] = '_';
75 pTimestring
[9] = (Timestamp
&0xF)+'0'; Timestamp
>>= 4;
76 pTimestring
[8] = (Timestamp
&0xF)+'0'; Timestamp
>>= 4;
78 pTimestring
[6] = (Timestamp
&0xF)+'0'; Timestamp
>>= 4;
79 pTimestring
[5] = (Timestamp
&0xF)+'0'; Timestamp
>>= 4;
81 pTimestring
[3] = (Timestamp
&0xF)+'0'; Timestamp
>>= 4;
82 pTimestring
[2] = (Timestamp
&0xF)+'0'; Timestamp
>>= 4;
83 pTimestring
[1] = (Timestamp
&0xF)+'0'; Timestamp
>>= 4;
84 pTimestring
[0] = (Timestamp
&0xF)+'0';
87 void CFileCollection::Init(IStorage
*pStorage
, const char *pPath
, const char *pFileDesc
, const char *pFileExt
, int MaxEntries
)
89 mem_zero(m_aTimestamps
, sizeof(m_aTimestamps
));
91 m_MaxEntries
= clamp(MaxEntries
, 1, static_cast<int>(MAX_ENTRIES
));
92 str_copy(m_aFileDesc
, pFileDesc
, sizeof(m_aFileDesc
));
93 m_FileDescLength
= str_length(m_aFileDesc
);
94 str_copy(m_aFileExt
, pFileExt
, sizeof(m_aFileExt
));
95 m_FileExtLength
= str_length(m_aFileExt
);
96 str_copy(m_aPath
, pPath
, sizeof(m_aPath
));
97 m_pStorage
= pStorage
;
99 m_pStorage
->ListDirectory(IStorage::TYPE_SAVE
, m_aPath
, FilelistCallback
, this);
102 void CFileCollection::AddEntry(int64 Timestamp
)
104 if(m_NumTimestamps
== 0)
107 m_aTimestamps
[m_NumTimestamps
++] = Timestamp
;
112 if(m_NumTimestamps
== m_MaxEntries
)
115 char aTimestring
[TIMESTAMP_LENGTH
];
116 BuildTimestring(m_aTimestamps
[0], aTimestring
);
117 str_format(aBuf
, sizeof(aBuf
), "%s/%s_%s%s", m_aPath
, m_aFileDesc
, aTimestring
, m_aFileExt
);
118 m_pStorage
->RemoveFile(aBuf
, IStorage::TYPE_SAVE
);
121 // add entry to the sorted list
122 if(m_aTimestamps
[0] > Timestamp
)
125 if(m_NumTimestamps
< m_MaxEntries
)
127 mem_move(m_aTimestamps
+1, m_aTimestamps
, m_NumTimestamps
*sizeof(int64
));
128 m_aTimestamps
[0] = Timestamp
;
132 else if(m_aTimestamps
[m_NumTimestamps
-1] <= Timestamp
)
135 if(m_NumTimestamps
== m_MaxEntries
)
137 mem_move(m_aTimestamps
, m_aTimestamps
+1, (m_NumTimestamps
-1)*sizeof(int64
));
138 m_aTimestamps
[m_NumTimestamps
-1] = Timestamp
;
141 m_aTimestamps
[m_NumTimestamps
++] = Timestamp
;
146 int Left
= 0, Right
= m_NumTimestamps
-1;
147 while(Right
-Left
> 1)
149 int Mid
= (Left
+Right
)/2;
150 if(m_aTimestamps
[Mid
] > Timestamp
)
156 if(m_NumTimestamps
== m_MaxEntries
)
158 mem_move(m_aTimestamps
, m_aTimestamps
+1, (Right
-1)*sizeof(int64
));
159 m_aTimestamps
[Right
-1] = Timestamp
;
163 mem_move(m_aTimestamps
+Right
+1, m_aTimestamps
+Right
, (m_NumTimestamps
-Right
)*sizeof(int64
));
164 m_aTimestamps
[Right
] = Timestamp
;
171 int CFileCollection::FilelistCallback(const char *pFilename
, int IsDir
, int StorageType
, void *pUser
)
173 CFileCollection
*pThis
= static_cast<CFileCollection
*>(pUser
);
175 // check for valid file name format
176 if(IsDir
|| !pThis
->IsFilenameValid(pFilename
))
179 // extract the timestamp
180 int64 Timestamp
= pThis
->ExtractTimestamp(pFilename
+pThis
->m_FileDescLength
+1);
183 pThis
->AddEntry(Timestamp
);