ALib C++ Library
Library Version: 2412 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
ftree.cpp
1// #################################################################################################
2// ALib C++ Library
3//
4// Copyright 2013-2024 A-Worx GmbH, Germany
5// Published under 'Boost Software License' (a free software license, see LICENSE.txt)
6// #################################################################################################
9#include "alib/alox.hpp"
10
11#if ALIB_DEBUG
13#endif
14
15#if !defined ( _WIN32 )
16# include <pwd.h>
17# include <grp.h>
18#endif
19
20using namespace alib::lang::system;
21namespace alib::files {
22
23//==================================================================================================
24//=== FTreeNodeHandler
25//==================================================================================================
26namespace detail {
27
30 const PathString& symLinkDest,
31 const PathString& symLinkRealPath )
32{
34 || node->Type() == FInfo::Types::SYMBOLIC_LINK
35 || node->Type() == FInfo::Types::SYMBOLIC_LINK_DIR,
36 "FILES", "Given node is not a directory or symbolic link.")
37
39 == symLinkDest.IsEmpty(),
40 "FILES", "Error in symbolic link parameter" )
41
42
43 auto& v = *node;
44 ALIB_ASSERT_ERROR( v.GetExtendedInfo() == nullptr, "FILES", "Already set")
45
46 auto pool= node.Tree<FTree>().Pool();
48 switch (v.Type())
49 {
51 {
52 v.SetExtendedInfo( pool.New<FInfo::EIDirectory>() );
53 }
54 return;
55
57 {
58 v.SetExtendedInfo( pool.New<FInfo::EISymLinkFile>() );
59 v.SetLinkTarget( node.Tree<FTree>(), symLinkDest, symLinkRealPath);
60 }
61 return;
62
64 {
65 v.SetExtendedInfo( pool.New<FInfo::EISymLinkDir>() );
66 v.SetLinkTarget( node.Tree<FTree>(), symLinkDest, symLinkRealPath);
67 }
68 return;
69
70 default:
71 return;
72 }
74}
76
77} // namespace alib::files[::detail]
78
79//==================================================================================================
80//=== FTree
81//==================================================================================================
83: StringTree( allocator, DIRECTORY_SEPARATOR )
84, Pool ( allocator )
85, ogResolver( Pool )
86, listeners ( allocator )
87{
90
91 DbgSetDCSName("FTree");
92
93 ALIB_DBG( if( alib::FILES.IsBootstrapped())
94 {
95 Log_SetDomain( "ALIB/FILES", Scope::Path)
96 Log_SetDomain( "FTREE" , Scope::Filename)
97 } )
98}
99
101{
102 #if ALIB_DEBUG
103 for( auto& node : nodeTable )
104 if( node.data.custom )
105 {
106 Path path;
107 createCursor(node).AssemblePath(path);
108 ALIB_ERROR( "FILES",
109 "CustomData not deleted before destruction of class FTree.\n"
110 " First node found: {}.\n"
111 " Attached data type: {}" , path, node.data.dbgCustomType )
112 }
113 #endif
114
115 // we have to delete all nodes before the invocation of the base destructor, because
116 // this would use our pool allocator on existing nodes (which is then destructed already).
117 Clear();
118
119 // delete root value
120 auto* extendedInfo= Root()->GetExtendedInfo();
121 if( extendedInfo )
122 Pool().Delete( reinterpret_cast<FInfo::EIDirectory*>(extendedInfo) );
123
125}
126
128 lang::ContainerOp insertOrRemove,
130 const File* file,
131 const StringTree::Cursor* subTree,
132 const PathString& fileName,
133 const PathString& pathPrefix,
134 const PathString& pathSubstring )
135{
136 // checks
137 ALIB_ASSERT_ERROR( file ==nullptr || &file->AsCursor().Tree() == this, "FILES", "Given file does not belong to this FTree.")
138 ALIB_ASSERT_ERROR( subTree ==nullptr || subTree->IsValid() , "FILES", "Invalid cursor given." )
139 ALIB_ASSERT_ERROR( subTree ==nullptr || &subTree ->Tree() == this , "FILES", "Given cursor does not belong to this FTree.")
140
141 // ---------------- registration ---------------------
142 if( insertOrRemove == lang::ContainerOp::Insert)
143 {
144 listeners.EmplaceBack( ListenerRecord{ listener,
145 event,
146 (file ? file->AsCursor().Export() : ConstCursorHandle()),
147 (subTree ? subTree-> Export() : ConstCursorHandle()),
150 PathStringPA(Pool) } );
151 listeners.Back().fileName << fileName;
152 listeners.Back().pathPrefix << pathPrefix;
153 listeners.Back().pathSubstring<< pathSubstring;
154
155 return;
156 }
157
158 // ---------------- de-registration ---------------------
159 for (auto it= listeners.begin() ; it != listeners.end() ; ++it )
160 if( it->listener == listener
161 && it->event == event
162 && it->file == ( file ? file->AsCursor().Export() : ConstCursorHandle() )
163 && it->subTree == ( subTree ? subTree ->Export() : ConstCursorHandle() )
164 && it->fileName .Equals( fileName )
165 && it->pathPrefix .Equals( pathPrefix )
166 && it->pathSubstring.Equals( pathSubstring ) )
167 {
168 (void) listeners.Erase( it );
169 return;
170 }
171
172 ALIB_WARNING( "FILES", "Listener with matching set of parameters not found with deregistration." )
173
174} // FTree::registerListener
175
176
178{
179 // checks
180 ALIB_ASSERT_ERROR( listener!=nullptr, "FILES", "Given listener is nullptr.")
181
182 // ---------------- de-registration ---------------------
183 int cnt= 0;
184 for (auto it= listeners.begin() ; it != listeners.end() ; )
185 if( it->listener == listener )
186 {
187 Log_Verbose("Removing listener")
188 it= listeners.Erase( it );
189 ++cnt;
190 }
191 else
192 ++it;
193
194 Log_If(cnt==0, Verbosity::Warning, "No listener found to be removed.")
195
196 return cnt;
197} // FTree::registerListener
198
200 File& file
201 IF_ALIB_THREADS( , SharedLock* lock) ,
202 const PathString& filePathGiven )
203{
204 Path filePathBuffer;
205 const PathString* filePath= &filePathGiven;
206 for (auto it= listeners.begin() ; it != listeners.end() ; ++it )
207 if( event == it->event )
208 {
209 // if needed generate file path
210 if( filePath->IsEmpty()
211 && ( it->fileName .IsNotEmpty()
212 || it->pathPrefix .IsNotEmpty()
213 || it->pathSubstring.IsNotEmpty() ) )
214 {
216 (file.AsCursor().IsRoot() ? file.AsCursor()
217 : file.AsCursor().Parent() )
218 .AssemblePath(filePathBuffer);
220 filePath= &filePathBuffer;
221 }
222
223 if( ( it->file .IsValid() && ( it->file == file.AsCursor().Export() ) )
224 || ( it->subTree .IsValid() && ( file.AsCursor().Distance( ImportCursor(it->subTree) ) >= 0 ) )
225 || ( it->fileName .IsNotEmpty() && it->fileName.Equals(file.AsCursor().Name()) )
226 || ( it->pathPrefix .IsNotEmpty() && filePath->StartsWith(it->pathPrefix) )
227 || ( it->pathSubstring.IsNotEmpty() && filePath->IndexOf(it->pathSubstring) >= 0 )
228 )
229 {
230 Log_Verbose("Notifying listener. Event=", event == FTreeListener::Event::CreateNode
231 ? "CreateNode" : "DeleteNode" )
232 it->listener->Notify( file, event );
233 }
234 }
235} // FTree::notifyListeners
236
237
239void FTree::FixSums( Cursor directory)
240{
241 ALIB_ASSERT_ERROR( directory->Type() == FInfo::Types::DIRECTORY,
242 "FILES", "Given node is not a directory.")
243
244 FInfo::DirectorySums& sums= directory->Sums();
245 sums= FInfo::DirectorySums();
246 directory.GoToFirstChild();
247 while( directory.IsValid())
248 {
249 FInfo& v= *directory;
250 sums.TypeCounters[int(v.Type())]++;
251 if( v.IsDirectory() )
252 sums+= v.Sums();
253
254 directory.GoToNextSibling();
255 }
256}
257
258//==================================================================================================
259//=== Debug Dump
260//==================================================================================================
261
262#if ALIB_DEBUG && !DOXYGEN
263
265 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");
266
267AString& DbgDump( AString& target,
268 FTree& tree,
269 EnumBitSet<FInfo::Types> includedTypes,
270 FTree::Cursor startNode ,
271 unsigned int depth )
272
273{
274 if( startNode.IsInvalid() )
275 startNode= tree.Root().AsCursor();
276
279 fmt.Reset();
282
283 // loop over all nodes and dump
284 fmt.Format( target, DBG_DUMP_FORMAT, File(startNode) );
285
286 rit.Initialize( startNode, depth );
287 while( rit.IsValid())
288 {
289 if( includedTypes.Test(rit.Node()->Type()))
290 fmt.Format( target, DBG_DUMP_FORMAT, File(rit.Node()) );
291 rit.Next();
292 }
293
294 return target;
295}
296
297#endif // ALIB_DEBUG && !DOXYGEN (dump methods)
299
300} // namespace alib::files
301
302
303
strings::TAString< typename cmTree::CharacterType, lang::HeapAllocator > & AssemblePath(strings::TAString< typename cmTree::CharacterType, lang::HeapAllocator > &targetString, lang::CurrentData targetData=lang::CurrentData::Clear) const
void Initialize(cmTree &pTree, unsigned int depth=(std::numeric_limits< unsigned int >::max)())
void SetPathGeneration(lang::Switch pathGeneration)
void ConstructRootValue(TArgs &&... args)
Cursor createCursor(baseNode &node)
void DbgSetDCSName(const char *name) const
Cursor ImportCursor(CursorHandle handle)
The entry type which is embedded in each tree node.
Definition finfo.hpp:26
constexpr DirectorySums & Sums() const
Definition finfo.hpp:444
constexpr ExtendedEntryInfo * GetExtendedInfo() const
Definition finfo.hpp:430
constexpr bool IsDirectory() const noexcept
Definition finfo.hpp:397
constexpr Types Type() const noexcept
Definition finfo.hpp:395
@ DIRECTORY
Directory/folder.
NumberFormat numberFormat
Definition ftree.hpp:189
ALIB_API ~FTree()
Destructor.
Definition ftree.cpp:100
ALIB_API int MonitorStop(FTreeListener *listener)
Definition ftree.cpp:177
List< MonoAllocator, ListenerRecord > listeners
The list of registered listeners.
Definition ftree.hpp:210
ALIB_API FTree(MonoAllocator &allocator)
Definition ftree.cpp:82
ALIB_API void notifyListeners(FTreeListener::Event event, File &file, SharedLock *lock, const lang::system::PathString &filePath)
Definition ftree.cpp:199
static ALIB_API void FixSums(Cursor directory)
Definition ftree.cpp:239
ALIB_API void registerListener(FTreeListener *listener, lang::ContainerOp insertOrRemove, FTreeListener::Event event, const File *file, const StringTree::Cursor *subTree, const lang::system::PathString &fileName, const lang::system::PathString &pathPrefix, const lang::system::PathString &pathSubstring)
Definition ftree.cpp:127
PoolAllocator Pool
Definition ftree.hpp:178
Cursor & AsCursor()
Definition ftree.hpp:749
constexpr bool Test(TInterface bit) noexcept
Definition bitset.hpp:350
static ALIB_API threads::RecursiveLock DefaultLock
static ALIB_API SPFormatter Default
virtual BoxesMA & Reset()
Formatter & Format(AString &target, TArgs &&... args)
integer IndexOf(TChar needle, integer startIdx=0) const
Definition string.hpp:896
constexpr bool IsEmpty() const
Definition string.hpp:383
bool StartsWith(const TString &needle) const
Definition string.hpp:820
ALIB_API void AcquireShared(ALIB_DBG_TAKE_CI)
Definition locks.cpp:713
ALIB_API void ReleaseShared(ALIB_DBG_TAKE_CI)
Definition locks.cpp:769
#define ALIB_WARNING(...)
Definition alib.hpp:1268
#define IF_ALIB_THREADS(...)
Definition alib.hpp:352
#define A_CHAR(STR)
#define ALIB_WARNINGS_RESTORE
Definition alib.hpp:849
#define Log_If(...)
Definition macros.inl:79
#define ALIB_ERROR(...)
Definition alib.hpp:1267
#define Log_Verbose(...)
Definition macros.inl:74
#define ALIB_WARNINGS_ALLOW_SPARSE_ENUM_SWITCH
Definition alib.hpp:785
#define ALIB_LOCK_RECURSIVE_WITH(lock)
Definition owner.hpp:457
#define ALIB_ASSERT_ERROR(cond,...)
Definition alib.hpp:1271
#define Log_SetDomain(...)
Definition macros.inl:67
#define ALIB_DBG(...)
Definition alib.hpp:390
#define ALIB_CALLER_PRUNED
Definition alib.hpp:1170
String DBG_DUMP_FORMAT
ALIB_API 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)())
This is the reference documentation of sub-namespace system of module ALib BaseCamp.
Definition basecamp.cpp:75
strings::TAString< PathCharType, PoolAllocator > PathStringPA
A pool-allocated string representing a path.
Definition path.hpp:83
static constexpr PathCharType DIRECTORY_SEPARATOR
The standard path separator character. Defaults to '\' on Windows OS, '/' else.
Definition path.hpp:99
@ Off
Switch it off, switched off, etc.
ContainerOp
Denotes standard container operations.
@ Insert
Denotes insertions.
files::File File
Type alias in namespace alib.
Definition ftree.hpp:1046
files::FilesCamp FILES
The singleton instance of ALib Camp class FilesCamp.
Definition filescamp.cpp:23
A handle type used with methods TCursor::Export and ImportCursor.
HashTable< TAllocator, typename NodeKey::ValueDescriptor, typename NodeKey::Hash, typename NodeKey::EqualTo, lang::Caching::Enabled, TRecycling > nodeTable
Recursively accumulated values for directories.
Definition finfo.hpp:196
uint32_t TypeCounters[int(Types::MARKER_TYPES_END)]
Per-type counters.
Definition finfo.hpp:199
Event
The type of change that imposes the notification of a listener.
Definition ftree.hpp:112
@ CreateNode
A file or directory entry was created.
Record used to manage registered listeners.
Definition ftree.hpp:197
static ALIB_API void AllocateExtendedInfo(StringTree< MonoAllocator, FInfo, detail::FTreeNodeHandler >::Cursor &node, const lang::system::PathString &symLinkDest, const lang::system::PathString &symLinkRealPath)
Definition ftree.cpp:29