From 6555b6c8f0227f80e0c4cc1fae98f49d2faa3b50 Mon Sep 17 00:00:00 2001 From: zontreck Date: Sat, 24 Aug 2024 00:01:12 -0700 Subject: [PATCH] Adds some more IO Helpers --- compile.sh | 4 +- lib/utils/IOTools.dart | 219 +++++++++++++++++++++++++++++++++++++++++ publish.sh | 6 ++ pubspec.yaml | 2 +- test/io_test.dart | 32 ++++++ 5 files changed, 260 insertions(+), 3 deletions(-) create mode 100644 publish.sh create mode 100644 test/io_test.dart diff --git a/compile.sh b/compile.sh index b7dff5b..36bf4a3 100755 --- a/compile.sh +++ b/compile.sh @@ -4,7 +4,7 @@ rm -rf doc dart doc mkdir out rm -rf out/* -flutter pub publish -f --skip-validation dart compile exe -o out/server_test bin/server_test.dart dart compile exe -o out/client_test bin/client_test.dart -dart compile exe -o out/dbikc.bin bin/dbikc.dart \ No newline at end of file +dart compile exe -o out/dbikc.bin bin/dbikc.dart +dart compile exe -o out/mkfsreport.bin bin/mkfsreport.dart \ No newline at end of file diff --git a/lib/utils/IOTools.dart b/lib/utils/IOTools.dart index c704c16..d14331d 100644 --- a/lib/utils/IOTools.dart +++ b/lib/utils/IOTools.dart @@ -2,6 +2,8 @@ import 'dart:convert'; import 'dart:io'; import 'dart:typed_data'; +import 'package:libac_dart/consts.dart'; + class PathHelper { String pth = ""; PathHelper({required this.pth}); @@ -122,3 +124,220 @@ void tailAndPrint(File file) { }); } catch (E) {} } + +class FileInformationCache { + static FileInformationCache? _inst; + FileInformationCache._(); + + Map _registry = {}; + + factory FileInformationCache.obtain() { + if (_inst == null) _inst = FileInformationCache._(); + + return _inst!; + } + + /// Flushes the cache and clears it + static void flush() { + FileInformationCache.obtain()._registry.clear(); + } + + /// Adds the specified file's information to the cache + void addFile(String path, FileInfo info) { + _registry[path] = info; + } + + Future generateHTMLReport( + {bool ascending = false, String VERSION = ""}) async { + String header = ''' + + MKFSReport + +

File System Report


+ Generated by mkfsreport v${VERSION}
+ Bundled LibAC Version: ${Constants.VERSION}
+
+    MKFSREPORT and LibAC are provided free of charge with no implied warranties. The software is provided as-is.
+    
+    This program was created by Tara Piccari, as a part of the Aria's Creations common code library as a helper utility.
+    Aria's Creations is a alias for online-only works. Aria is an anagram derived from my name. piccARI, tarA. You place my last name first, take the last 3, skip the first 3 in my first name and take the remaining character(s) and you have my alias.
+    
+    This utility analyzed the specified folder path to generate a detailed report of directory and file sizes as seen below.
+    

+ '''; + + header += ''' + + + + + + + '''; + + for (var entry in (await getOrderedList(ascending: ascending))) { + header += ''' + + + + + + '''; + } + + header += ''' +
TypePathSize
${entry.isFile ? "FILE" : "DIR"}${entry.path}${entry.toString()}
+ '''; + + header += ''' + + + '''; + return header; + } + + Future> getOrderedList({bool ascending = false}) async { + List infoList = []; + for (var entry in _registry.entries) { + infoList.add(entry.value); + } + + if (ascending) + infoList.sort((A, B) => A.size.compareTo(B.size)); + else + infoList.sort((A, B) => B.size.compareTo(A.size)); + + return infoList; + } +} + +class FileInfo { + String path; + int size; + bool isFile; + + FileInfo({required this.path, required this.size, required this.isFile}); + + double kb() { + return (size / 1024); + } + + double mb() { + return (kb() / 1024); + } + + double gb() { + return (mb() / 1024); + } + + double tb() { + return (gb() / 1024); + } + + @override + String toString() { + if (tb() > 0.5) + return "${tb()} TB"; + else if (gb() > 0.5) + return "${gb()} GB"; + else if (mb() > 0.5) + return "${mb()} MB"; + else if (kb() > 0.5) + return "${kb()} KB"; + else + return "$size bytes"; + } + + /// This automatically picks TB, GB, MB, KB, or bytes depending on which returns larger than 0.5 + /// + /// This provides no way to know what it returns, if you need to know, use the toString method, or the individual functions to get various size types + double getSize() { + if (tb() > 0.5) + return tb(); + else if (gb() > 0.5) + return gb(); + else if (mb() > 0.5) + return mb(); + else if (kb() > 0.5) + return kb(); + else + return size.toDouble(); + } +} + +Future getFileSize(String path, + {bool cacheSize = false, bool verbose = false}) async { + if (verbose) prnt("> Checking size of file $path\r"); + /*final fileBytes = await File(path).readAsBytes(); + int size = fileBytes.lengthInBytes;*/ + final size = await File(path).length(); + + if (verbose) prnt(">> Size of file $path is $size bytes\r"); + + if (cacheSize) { + FileInformationCache FIC = FileInformationCache.obtain(); + FIC.addFile(path, FileInfo(path: path, size: size, isFile: true)); + } + + return size; +} + +Future getDirectorySize(String path, + {bool recursive = false, + bool cacheSize = false, + bool verbose = false}) async { + int totalSize = 0; + if (verbose) prnt("> Check dir size of $path\r"); + final entityList = await Directory(path) + .list(recursive: recursive, followLinks: true) + .toList(); + + await Future.forEach(entityList, (entity) async { + if (entity is File) { + totalSize += await getFileSize(entity.path, + cacheSize: cacheSize, verbose: verbose); + } else if (entity is Directory) { + totalSize += await getDirectorySize(entity.path, + recursive: true, cacheSize: cacheSize, verbose: verbose); + } + }); + + if (verbose) prnt(">> Size of dir $path is $totalSize bytes\r"); + + if (cacheSize) { + FileInformationCache FIC = FileInformationCache.obtain(); + FileInfo FI = FileInfo(path: path, size: totalSize, isFile: false); + FIC.addFile(path, FI); + } + + return totalSize; +} + +void prnt(String text) { + // Convert the string to a list of runes to handle escape sequences properly. + final runes = text.runes.toList(); + + for (var i = 0; i < runes.length; i++) { + final char = runes[i]; + + // Check for escape sequences + if (char == 0x5C && i + 1 < runes.length) { + // '\\' character in UTF-16 + final nextChar = runes[i + 1]; + if (nextChar == 0x72) { + // 'r' character in UTF-16 + // Handle '\r' escape sequence + stdout.write('\r'); // Move the cursor back to the beginning of the line + stdout.write( + ' ' * stdout.terminalColumns); // Erase the entire line with spaces + stdout.write( + '\r'); // Move the cursor back to the start of the line again after clearing + i++; // Skip the 'r' character + continue; + } + } + + // Write the character as-is + stdout.write(String.fromCharCode(char)); + } +} diff --git a/publish.sh b/publish.sh new file mode 100644 index 0000000..edf936b --- /dev/null +++ b/publish.sh @@ -0,0 +1,6 @@ +#!/bin/bash + + +./compile.sh + +flutter pub publish -f --skip-validation \ No newline at end of file diff --git a/pubspec.yaml b/pubspec.yaml index 6e810c9..ebdf0ad 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: libac_dart description: "Aria's Creations code library" -version: 1.2.082324+0758 +version: 1.2.082324+2223 homepage: "https://zontreck.com" diff --git a/test/io_test.dart b/test/io_test.dart new file mode 100644 index 0000000..b86acae --- /dev/null +++ b/test/io_test.dart @@ -0,0 +1,32 @@ +import 'package:libac_dart/utils/IOTools.dart'; +import 'package:test/expect.dart'; +import 'package:test/scaffolding.dart'; + +Future main() async { + test("Test file size checking", () async { + expect(await getFileSize("test/hello_world.nbt"), 33); + expect(await getFileSize("test/bigtest.nbt"), 507); + }); + + test("Test directory size checking", () async { + expect(await getDirectorySize("test"), 9046); + }); + + test("Test file info methods", () async { + FileInfo fi = FileInfo(path: "C:\\test.txt", size: 4096, isFile: true); + expect(fi.toString(), "4.0 KB"); + }); + + test("Test ordered file info lists", () async { + await getDirectorySize("test", cacheSize: true); + FileInformationCache FIC = FileInformationCache.obtain(); + var list = await FIC.getOrderedList(ascending: false); + var ascList = await FIC.getOrderedList(ascending: true); + + print(list); + print(ascList); + + expect(list[0].size > ascList[0].size, true); + expect(list[list.length - 1].size == ascList[0].size, true); + }); +}