Various improvements: Toolbox, Updater and Unit Tests. (#2250)
* Toolbox: add seek to character stream method. UpdateUtils: reverse manifest iterator. UnitTests: more unit tests. * Target: bump API version. Updater: delete empty folders from manifest before resource deployment. * UnitTests: use manifest from unit_tests folder instead of global one * Make PVS happy * sector cache: allocate always * Better PVS config for manifest.c * PVS: Move exception outside of condition * PVS: remove confusing condition Co-authored-by: SG <who.just.the.doctor@gmail.com>
This commit is contained in:
@@ -60,6 +60,12 @@ ResourceManifestEntry* resource_manifest_reader_next(ResourceManifestReader* res
|
||||
|
||||
char type_code = furi_string_get_char(resource_manifest->linebuf, 0);
|
||||
switch(type_code) {
|
||||
case 'V':
|
||||
resource_manifest->entry.type = ResourceManifestEntryTypeVersion;
|
||||
break;
|
||||
case 'T':
|
||||
resource_manifest->entry.type = ResourceManifestEntryTypeTimestamp;
|
||||
break;
|
||||
case 'F':
|
||||
resource_manifest->entry.type = ResourceManifestEntryTypeFile;
|
||||
break;
|
||||
@@ -98,9 +104,9 @@ ResourceManifestEntry* resource_manifest_reader_next(ResourceManifestReader* res
|
||||
furi_string_right(resource_manifest->linebuf, offs + 1);
|
||||
|
||||
furi_string_set(resource_manifest->entry.name, resource_manifest->linebuf);
|
||||
} else if(resource_manifest->entry.type == ResourceManifestEntryTypeDirectory) { //-V547
|
||||
/* Parse directory entry
|
||||
D:<name> */
|
||||
} else { //-V547
|
||||
/* Everything else is plain key value. Parse version, timestamp or directory entry
|
||||
<Type>:<Value> */
|
||||
|
||||
/* Remove entry type code */
|
||||
furi_string_right(resource_manifest->linebuf, 2);
|
||||
@@ -113,3 +119,45 @@ ResourceManifestEntry* resource_manifest_reader_next(ResourceManifestReader* res
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ResourceManifestEntry*
|
||||
resource_manifest_reader_previous(ResourceManifestReader* resource_manifest) {
|
||||
furi_assert(resource_manifest);
|
||||
|
||||
// Snapshot position for rollback
|
||||
const size_t previous_position = stream_tell(resource_manifest->stream);
|
||||
|
||||
// We need to jump 2 lines back
|
||||
size_t jumps = 2;
|
||||
// Special case: end of the file.
|
||||
const bool was_eof = stream_eof(resource_manifest->stream);
|
||||
if(was_eof) {
|
||||
jumps = 1;
|
||||
}
|
||||
while(jumps) {
|
||||
if(!stream_seek_to_char(resource_manifest->stream, '\n', StreamDirectionBackward)) {
|
||||
break;
|
||||
}
|
||||
if(stream_tell(resource_manifest->stream) < (previous_position - 1)) {
|
||||
jumps--;
|
||||
}
|
||||
}
|
||||
|
||||
// Special case: first line. Force seek to zero
|
||||
if(jumps == 1) {
|
||||
jumps = 0;
|
||||
stream_seek(resource_manifest->stream, 0, StreamOffsetFromStart);
|
||||
}
|
||||
|
||||
if(jumps == 0) {
|
||||
ResourceManifestEntry* entry = resource_manifest_reader_next(resource_manifest);
|
||||
// Special case: was end of the file, prevent loop
|
||||
if(was_eof) {
|
||||
stream_seek(resource_manifest->stream, -1, StreamOffsetFromCurrent);
|
||||
}
|
||||
return entry;
|
||||
} else {
|
||||
stream_seek(resource_manifest->stream, previous_position, StreamOffsetFromStart);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
@@ -11,6 +11,8 @@ extern "C" {
|
||||
|
||||
typedef enum {
|
||||
ResourceManifestEntryTypeUnknown = 0,
|
||||
ResourceManifestEntryTypeVersion,
|
||||
ResourceManifestEntryTypeTimestamp,
|
||||
ResourceManifestEntryTypeDirectory,
|
||||
ResourceManifestEntryTypeFile,
|
||||
} ResourceManifestEntryType;
|
||||
@@ -52,6 +54,18 @@ bool resource_manifest_reader_open(ResourceManifestReader* resource_manifest, co
|
||||
*/
|
||||
ResourceManifestEntry* resource_manifest_reader_next(ResourceManifestReader* resource_manifest);
|
||||
|
||||
/** Read previous file/dir entry from manifest
|
||||
*
|
||||
* You must be at the end of the manifest to use this function.
|
||||
* Intended to be used after reaching end with resource_manifest_reader_next
|
||||
*
|
||||
* @param resource_manifest Pointer to the ResourceManifestReader instance
|
||||
*
|
||||
* @return entry or NULL if end of file
|
||||
*/
|
||||
ResourceManifestEntry*
|
||||
resource_manifest_reader_previous(ResourceManifestReader* resource_manifest);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
Reference in New Issue
Block a user