ALib C++ Library
Library Version: 2510 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
ftree.cpp
1// #################################################################################################
2// ALib C++ Library
3//
4// Copyright 2013-2025 A-Worx GmbH, Germany
5// Published under 'Boost Software License' (a free software license, see LICENSE.txt)
6// #################################################################################################
7#include "alib_precompile.hpp"
8#if !defined(ALIB_C20_MODULES) || ((ALIB_C20_MODULES != 0) && (ALIB_C20_MODULES != 1))
9# error "Symbol ALIB_C20_MODULES has to be given to the compiler as either 0 or 1"
10#endif
11#if ALIB_C20_MODULES
12 module;
13#endif
14// ====================================== Global Fragment ======================================
17#if !defined ( _WIN32 )
18# include <pwd.h>
19# include <grp.h>
20#endif
21
22
23// =========================================== Module ==========================================
24#if ALIB_C20_MODULES
25 module ALib.Files;
26 import ALib.Lang;
28 import ALib.Strings;
29# if ALIB_ALOX
30 import ALib.ALox;
31 import ALib.ALox.Impl;
32# endif
33# if ALIB_EXPRESSIONS
34 import ALib.Expressions;
35# endif
36#if ALIB_DEBUG
37# include "ALib.Format.H"
38#endif
39#else
40# include "ALib.Lang.H"
42# include "ALib.Strings.H"
43# include "ALib.ALox.H"
44# include "ALib.ALox.Impl.H"
45# include "ALib.Expressions.H"
46#if ALIB_DEBUG
47# include "ALib.Format.H"
48#endif
49# include "ALib.Files.H"
50#endif
51// ====================================== Implementation =======================================
52
53using namespace alib::system;
54namespace alib::files {
55
56//==================================================================================================
57//=== FTreeNodeHandler
58//==================================================================================================
59namespace detail {
60
63 const PathString& symLinkDest,
64 const PathString& symLinkRealPath )
65{
67 || node->Type() == FInfo::Types::SYMBOLIC_LINK
68 || node->Type() == FInfo::Types::SYMBOLIC_LINK_DIR,
69 "FILES", "Given node is not a directory or symbolic link." )
70
72 == symLinkDest.IsEmpty(),
73 "FILES", "Error in symbolic link parameter" )
74
75
76 auto& v = *node;
77 ALIB_ASSERT_ERROR( v.GetExtendedInfo() == nullptr, "FILES", "Already set" )
78
79 auto pool= node.Tree<FTree>().Pool();
81 switch (v.Type())
82 {
84 {
85 v.SetExtendedInfo( pool.New<FInfo::EIDirectory>() );
86 }
87 return;
88
90 {
91 v.SetExtendedInfo( pool.New<FInfo::EISymLinkFile>() );
92 v.SetLinkTarget( node.Tree<FTree>(), symLinkDest, symLinkRealPath);
93 }
94 return;
95
97 {
98 v.SetExtendedInfo( pool.New<FInfo::EISymLinkDir>() );
99 v.SetLinkTarget( node.Tree<FTree>(), symLinkDest, symLinkRealPath);
100 }
101 return;
102
103 default:
104 return;
105 }
107}
108# include "ALib.Lang.CIMethods.H"
109
110} // namespace alib::files[::detail]
111
112//==================================================================================================
113//=== FTree
114//==================================================================================================
116: StringTree( allocator, DIRECTORY_SEPARATOR )
117, Pool ( allocator )
118, ogResolver( Pool )
119, listeners ( allocator )
120{
122 numberFormat.FractionalPartWidth= 1;
123
124 DbgSetDCSName("FTree");
125
126 ALIB_DBG( if( alib::FILES.IsBootstrapped())
127 {
128 Log_SetDomain( "ALIB/FILES", Scope::Path)
129 Log_SetDomain( "FTREE" , Scope::Filename)
130 } )
131}
132
134{
135 #if ALIB_DEBUG
136 for( auto& node : nodeTable )
137 if( node.data.custom )
138 {
139 Path path;
140 createCursor(node).AssemblePath(path);
141 ALIB_ERROR( "FILES",
142 "CustomData not deleted before destruction of class FTree.\n"
143 " First node found: {}.\n"
144 " Attached data type: {}" , path, node.data.dbgCustomType )
145 }
146 #endif
147
148 // we have to delete all nodes before the invocation of the base destructor, because
149 // this would use our pool allocator on existing nodes (which is then destructed already).
150 Clear();
151
152 // delete root value
153 auto* extendedInfo= Root()->GetExtendedInfo();
154 if( extendedInfo )
155 Pool().Delete( reinterpret_cast<FInfo::EIDirectory*>(extendedInfo) );
156
158}
159
161 lang::ContainerOp insertOrRemove,
163 const File* file,
164 const StringTree::Cursor* subTree,
165 const PathString& fileName,
166 const PathString& pathPrefix,
167 const PathString& pathSubstring )
168{
169 // checks
170 ALIB_ASSERT_ERROR( file ==nullptr || &file->AsCursor().Tree() == this,"FILES","Given file does not belong to this FTree." )
171 ALIB_ASSERT_ERROR( subTree ==nullptr || subTree->IsValid() ,"FILES","Invalid cursor given." )
172 ALIB_ASSERT_ERROR( subTree ==nullptr || &subTree ->Tree() == this,"FILES","Given cursor does not belong to this FTree." )
173
174 // ---------------- registration ---------------------
175 if( insertOrRemove == lang::ContainerOp::Insert)
176 {
177 listeners.emplace_back( ListenerRecord{ listener,
178 event,
179 (file ? file->AsCursor().Export() : ConstCursorHandle()),
180 (subTree ? subTree-> Export() : ConstCursorHandle()),
183 PathStringPA(Pool) } );
184 listeners.back().fileName << fileName;
185 listeners.back().pathPrefix << pathPrefix;
186 listeners.back().pathSubstring<< pathSubstring;
187
188 return;
189 }
190
191 // ---------------- de-registration ---------------------
192 for (auto it= listeners.begin() ; it != listeners.end() ; ++it )
193 if( it->listener == listener
194 && it->event == event
195 && it->file == ( file ? file->AsCursor().Export() : ConstCursorHandle() )
196 && it->subTree == ( subTree ? subTree ->Export() : ConstCursorHandle() )
197 && it->fileName .Equals( fileName )
198 && it->pathPrefix .Equals( pathPrefix )
199 && it->pathSubstring.Equals( pathSubstring ) )
200 {
201 (void) listeners.erase( it );
202 return;
203 }
204
205 ALIB_WARNING("FILES", "Listener with matching set of parameters not found with deregistration.")
206
207} // FTree::registerListener
208
209
211{
212 // checks
213 ALIB_ASSERT_ERROR( listener!=nullptr, "FILES", "Given listener is nullptr." )
214
215 // ---------------- de-registration ---------------------
216 int cnt= 0;
217 for (auto it= listeners.begin() ; it != listeners.end() ; )
218 if( it->listener == listener )
219 {
220 Log_Verbose("Removing listener")
221 it= listeners.erase( it );
222 ++cnt;
223 }
224 else
225 ++it;
226
227 Log_If(cnt==0, Verbosity::Warning, "No listener found to be removed." )
228
229 return cnt;
230} // FTree::registerListener
231
233 File& file
234 IF_ALIB_THREADS( , SharedLock* lock) ,
235 const PathString& filePathGiven )
236{
237 Path filePathBuffer;
238 const PathString* filePath= &filePathGiven;
239 for (auto it= listeners.begin() ; it != listeners.end() ; ++it )
240 if( event == it->event )
241 {
242 // if needed generate file path
243 if( filePath->IsEmpty()
244 && ( it->fileName .IsNotEmpty()
245 || it->pathPrefix .IsNotEmpty()
246 || it->pathSubstring.IsNotEmpty() ) )
247 {
249 (file.AsCursor().IsRoot() ? file.AsCursor()
250 : file.AsCursor().Parent() )
251 .AssemblePath(filePathBuffer);
253 filePath= &filePathBuffer;
254 }
255
256 if( ( it->file .IsValid() && ( it->file == file.AsCursor().Export() ) )
257 || ( it->subTree .IsValid() && ( file.AsCursor().Distance( ImportCursor(it->subTree) ) >= 0 ) )
258 || ( it->fileName .IsNotEmpty() && it->fileName.Equals(file.AsCursor().Name()) )
259 || ( it->pathPrefix .IsNotEmpty() && filePath->StartsWith(it->pathPrefix) )
260 || ( it->pathSubstring.IsNotEmpty() && filePath->IndexOf(it->pathSubstring) >= 0 )
261 )
262 {
263 Log_Verbose("Notifying listener. Event=", event == FTreeListener::Event::CreateNode
264 ? "CreateNode" : "DeleteNode" )
265 it->listener->Notify( file, event );
266 }
267 }
268} // FTree::notifyListeners
269
270
271# include "ALib.Lang.CIFunctions.H"
272void FTree::FixSums( Cursor directory)
273{
274 ALIB_ASSERT_ERROR( directory->Type() == FInfo::Types::DIRECTORY,
275 "FILES", "Given node is not a directory." )
276
277 FInfo::DirectorySums& sums= directory->Sums();
278 sums= FInfo::DirectorySums();
279 directory.GoToFirstChild();
280 while( directory.IsValid())
281 {
282 FInfo& v= *directory;
283 sums.TypeCounters[size_t(v.Type())]++;
284 if( v.IsDirectory() )
285 sums+= v.Sums();
286
287 directory.GoToNextSibling();
288 }
289}
290
291//==================================================================================================
292//=== Debug Dump
293//==================================================================================================
294
295#if ALIB_DEBUG && !DOXYGEN
296
298 A_CHAR("{:ta h{2,r} on{10,r} gn{10,r} s(IEC){10,r} dm qqq FxFa (rd{3r}' D' rf{3r}' F' re{2r}' EA' rb{2r}'BL) 'nf l}\n");
299
300AString& DbgDump( AString& target,
301 FTree& tree,
302 EnumBitSet<FInfo::Types> includedTypes,
303 FTree::Cursor startNode ,
304 unsigned int depth )
305
306{
307 if( startNode.IsInvalid() )
308 startNode= tree.Root().AsCursor();
309
312 fmt.Reset();
314 rit.SetPathGeneration(lang::Switch::Off);
315
316 // loop over all nodes and dump
317 fmt.Format( target, DBG_DUMP_FORMAT, File(startNode) );
318
319 rit.Initialize( startNode, depth );
320 while( rit.IsValid())
321 {
322 if( includedTypes.Test(rit.Node()->Type()))
323 fmt.Format( target, DBG_DUMP_FORMAT, File(rit.Node()) );
324 rit.Next();
325 }
326
327 return target;
328}
329
330#endif // ALIB_DEBUG && !DOXYGEN (dump methods)
331# include "ALib.Lang.CIMethods.H"
332
333} // namespace alib::files
334
335
336
StringTree(AllocatorType &allocator, CharacterType pathSeparator)
The entry type which is embedded in each tree node.
Definition finfo.inl:15
constexpr Types Type() const noexcept
Definition finfo.inl:383
constexpr ExtendedEntryInfo * GetExtendedInfo() const
Definition finfo.inl:418
constexpr bool IsDirectory() const noexcept
Definition finfo.inl:385
@ DIRECTORY
Directory/folder.
Definition finfo.inl:26
constexpr DirectorySums & Sums() const
Definition finfo.inl:432
ALIB_DLL FTree(MonoAllocator &allocator)
Definition ftree.cpp:115
PoolAllocator Pool
Definition ftree.inl:163
ALIB_DLL void notifyListeners(FTreeListener::Event event, File &file, SharedLock *lock, const system::PathString &filePath)
Definition ftree.cpp:232
NumberFormat numberFormat
Definition ftree.inl:174
OwnerAndGroupResolver ogResolver
Definition ftree.inl:178
ALIB_DLL int MonitorStop(FTreeListener *listener)
Definition ftree.cpp:210
friend class files::File
Friendship declaration.
Definition ftree.inl:170
ALIB_DLL void registerListener(FTreeListener *listener, lang::ContainerOp insertOrRemove, FTreeListener::Event event, const File *file, const StringTree::Cursor *subTree, const system::PathString &fileName, const system::PathString &pathPrefix, const system::PathString &pathSubstring)
Definition ftree.cpp:160
ALIB_DLL ~FTree()
Destructor.
Definition ftree.cpp:133
static ALIB_DLL void FixSums(Cursor directory)
Definition ftree.cpp:272
List< MonoAllocator, ListenerRecord > listeners
The list of registered listeners.
Definition ftree.inl:195
Cursor & AsCursor()
Definition ftree.inl:737
static ALIB_DLL threads::RecursiveLock DefaultLock
Formatter & Format(AString &target, TArgs &&... args)
static ALIB_DLL SPFormatter Default
virtual BoxesMA & Reset()
constexpr bool Test(TInterface bit) noexcept
Definition bitset.inl:336
constexpr bool IsEmpty() const
Definition string.inl:367
integer IndexOf(TChar needle, integer startIdx=0) const
Definition string.inl:844
bool StartsWith(const TString &needle) const
Definition string.inl:772
ALIB_DLL void ReleaseShared(ALIB_DBG_TAKE_CI)
Definition locks.cpp:535
ALIB_DLL void AcquireShared(ALIB_DBG_TAKE_CI)
Definition locks.cpp:478
#define IF_ALIB_THREADS(...)
Definition alib.inl:401
#define A_CHAR(STR)
#define ALIB_WARNINGS_RESTORE
Definition alib.inl:705
#define ALIB_WARNING(domain,...)
Definition alib.inl:1046
#define Log_If(...)
#define ALIB_ERROR(domain,...)
Definition alib.inl:1045
#define Log_Verbose(...)
#define ALIB_WARNINGS_ALLOW_SPARSE_ENUM_SWITCH
Definition alib.inl:637
#define ALIB_LOCK_RECURSIVE_WITH(lock)
Definition alib.inl:1323
#define Log_SetDomain(...)
#define ALIB_DBG(...)
Definition alib.inl:836
#define ALIB_ASSERT_ERROR(cond, domain,...)
Definition alib.inl:1049
#define ALIB_CALLER_PRUNED
Definition alib.inl:1007
This namespace implements internals of namespace alib::files.
Definition ftree.cpp:59
ALIB_DLL AString & DbgDump(AString &target, FTree &tree, EnumBitSet< FInfo::Types > includedTypes=EnumBitSet< FInfo::Types >(true), FTree::Cursor startNode=FTree::Cursor(), unsigned int depth=(std::numeric_limits< unsigned int >::max)())
String DBG_DUMP_FORMAT
ContainerOp
Denotes standard container operations.
@ Insert
Denotes insertions.
@ Off
Switch it off, switched off, etc.
strings::TString< PathCharType > PathString
The string-type used with this ALib Module.
Definition path.inl:33
strings::TAString< PathCharType, PoolAllocator > PathStringPA
A pool-allocated string representing a path.
Definition path.inl:46
constexpr PathCharType DIRECTORY_SEPARATOR
The standard path separator character. Defaults to '\' on Windows OS, '/' else.
Definition path.inl:63
threads::SharedLock SharedLock
Type alias in namespace alib.
files::File File
Type alias in namespace alib.
Definition ftree.inl:1036
strings::TAString< character, lang::HeapAllocator > AString
Type alias in namespace alib.
lang::TBitSet< TEnum, enumops::IterableTraits< TEnum >::End, enumops::IterableTraits< TEnum >::Begin > EnumBitSet
monomem::TMonoAllocator< lang::HeapAllocator > MonoAllocator
system::Path Path
Type alias in namespace alib.
Definition path.inl:392
format::Formatter Formatter
Type alias in namespace alib.
files::FilesCamp FILES
The singleton instance of ALib Camp class FilesCamp.
Definition filescamp.cpp:47
strings::TString< character > String
Type alias in namespace alib.
Definition string.inl:2381
HashTable< TAllocator, typename NodeKey::ValueDescriptor, typename NodeKey::Hash, typename NodeKey::EqualTo, lang::Caching::Enabled, TRecycling > nodeTable
Recursively accumulated values for directories.
Definition finfo.inl:185
std::array< uint32_t, size_t(Types::MARKER_TYPES_END)> TypeCounters
Per-type counters.
Definition finfo.inl:187
Event
The type of change that imposes the notification of a listener.
Definition ftree.inl:97
@ CreateNode
A file or directory entry was created.
Definition ftree.inl:98
Record used to manage registered listeners.
Definition ftree.inl:182
static ALIB_DLL void AllocateExtendedInfo(StringTree< MonoAllocator, FInfo, detail::FTreeNodeHandler >::Cursor &node, const system::PathString &symLinkDest, const system::PathString &symLinkRealPath)
Definition ftree.cpp:62