Skip to content

Commit 0c9fa3d

Browse files
committed
Added DirectoryReader.
1 parent 8397b51 commit 0c9fa3d

File tree

3 files changed

+213
-30
lines changed

3 files changed

+213
-30
lines changed

include/bx/file.h

+34-7
Original file line numberDiff line numberDiff line change
@@ -75,23 +75,50 @@ namespace bx
7575
BX_ALIGN_DECL(16, uint8_t) m_internal[64];
7676
};
7777

78-
///
79-
struct FileInfo
78+
struct FileType
8079
{
8180
enum Enum
8281
{
83-
Regular,
84-
Directory,
82+
File,
83+
Dir,
8584

8685
Count
8786
};
87+
};
88+
89+
///
90+
struct FileInfo
91+
{
92+
FilePath filePath;
93+
uint64_t size;
94+
FileType::Enum type;
95+
};
96+
97+
///
98+
class DirectoryReader : public ReaderOpenI, public CloserI, public ReaderI
99+
{
100+
public:
101+
///
102+
DirectoryReader();
88103

89-
uint64_t m_size;
90-
Enum m_type;
104+
///
105+
virtual ~DirectoryReader();
106+
107+
///
108+
virtual bool open(const FilePath& _filePath, Error* _err) override;
109+
110+
///
111+
virtual void close() override;
112+
113+
///
114+
virtual int32_t read(void* _data, int32_t _size, Error* _err) override;
115+
116+
private:
117+
BX_ALIGN_DECL(16, uint8_t) m_internal[sizeof(FilePath)+sizeof(FileInfo)+16];
91118
};
92119

93120
///
94-
bool stat(const FilePath& _filePath, FileInfo& _outFileInfo);
121+
bool stat(FileInfo& _outFileInfo, const FilePath& _filePath);
95122

96123
} // namespace bx
97124

src/file.cpp

+163-8
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#if BX_CRT_NONE
1010
# include "crt0.h"
1111
#else
12+
# include <dirent.h>
1213
# include <stdio.h>
1314
# include <sys/stat.h>
1415
#endif // !BX_CRT_NONE
@@ -553,14 +554,168 @@ namespace bx
553554
return impl->write(_data, _size, _err);
554555
}
555556

556-
bool stat(const FilePath& _filePath, FileInfo& _outFileInfo)
557+
class DirectoryReaderImpl : public ReaderOpenI, public CloserI, public ReaderI
558+
{
559+
public:
560+
///
561+
DirectoryReaderImpl();
562+
563+
///
564+
virtual ~DirectoryReaderImpl();
565+
566+
///
567+
virtual bool open(const FilePath& _filePath, Error* _err) override;
568+
569+
///
570+
virtual void close() override;
571+
572+
///
573+
virtual int32_t read(void* _data, int32_t _size, Error* _err) override;
574+
575+
private:
576+
FileInfo m_cache;
577+
DIR* m_dir;
578+
int32_t m_pos;
579+
};
580+
581+
DirectoryReaderImpl::DirectoryReaderImpl()
582+
: m_dir(NULL)
583+
, m_pos(0)
584+
{
585+
}
586+
587+
DirectoryReaderImpl::~DirectoryReaderImpl()
588+
{
589+
close();
590+
}
591+
592+
static bool fetch(FileInfo& _out, DIR* _dir)
593+
{
594+
for (;;)
595+
{
596+
const dirent* item = readdir(_dir);
597+
598+
if (NULL == item)
599+
{
600+
return false;
601+
}
602+
603+
if (0 != (item->d_type & DT_DIR) )
604+
{
605+
_out.type = FileType::Dir;
606+
_out.size = UINT64_MAX;
607+
_out.filePath.set(item->d_name);
608+
return true;
609+
}
610+
611+
if (0 != (item->d_type & DT_REG) )
612+
{
613+
_out.type = FileType::File;
614+
_out.size = UINT64_MAX;
615+
_out.filePath.set(item->d_name);
616+
return true;
617+
}
618+
}
619+
620+
return false;
621+
}
622+
623+
bool DirectoryReaderImpl::open(const FilePath& _filePath, Error* _err)
624+
{
625+
BX_CHECK(NULL != _err, "Reader/Writer interface calling functions must handle errors.");
626+
627+
m_dir = opendir(_filePath.get() );
628+
629+
if (NULL == m_dir)
630+
{
631+
BX_ERROR_SET(_err, BX_ERROR_READERWRITER_OPEN, "DirectoryReader: Failed to open directory.");
632+
return false;
633+
}
634+
635+
m_pos = 0;
636+
637+
return true;
638+
}
639+
640+
void DirectoryReaderImpl::close()
641+
{
642+
if (NULL != m_dir)
643+
{
644+
closedir(m_dir);
645+
m_dir = NULL;
646+
}
647+
}
648+
649+
int32_t DirectoryReaderImpl::read(void* _data, int32_t _size, Error* _err)
650+
{
651+
BX_CHECK(NULL != _err, "Reader/Writer interface calling functions must handle errors.");
652+
653+
int32_t total = 0;
654+
655+
uint8_t* out = (uint8_t*)_data;
656+
657+
for (; 0 < _size;)
658+
{
659+
if (0 == m_pos)
660+
{
661+
if (!fetch(m_cache, m_dir) )
662+
{
663+
BX_ERROR_SET(_err, BX_ERROR_READERWRITER_EOF, "DirectoryReader: EOF.");
664+
return total;
665+
}
666+
}
667+
668+
const uint8_t* src = (const uint8_t*)&m_cache;
669+
int32_t size = min<int32_t>(_size, sizeof(m_cache)-m_pos);
670+
memCopy(&out[total], &src[m_pos], size);
671+
total += size;
672+
_size -= size;
673+
674+
m_pos += size;
675+
m_pos %= sizeof(m_cache);
676+
}
677+
678+
return total;
679+
}
680+
681+
DirectoryReader::DirectoryReader()
682+
{
683+
BX_STATIC_ASSERT(sizeof(DirectoryReaderImpl) <= sizeof(m_internal) );
684+
BX_PLACEMENT_NEW(m_internal, DirectoryReaderImpl);
685+
}
686+
687+
DirectoryReader::~DirectoryReader()
688+
{
689+
DirectoryReaderImpl* impl = reinterpret_cast<DirectoryReaderImpl*>(m_internal);
690+
impl->~DirectoryReaderImpl();
691+
}
692+
693+
bool DirectoryReader::open(const FilePath& _filePath, Error* _err)
694+
{
695+
DirectoryReaderImpl* impl = reinterpret_cast<DirectoryReaderImpl*>(m_internal);
696+
return impl->open(_filePath, _err);
697+
}
698+
699+
void DirectoryReader::close()
700+
{
701+
DirectoryReaderImpl* impl = reinterpret_cast<DirectoryReaderImpl*>(m_internal);
702+
impl->close();
703+
}
704+
705+
int32_t DirectoryReader::read(void* _data, int32_t _size, Error* _err)
706+
{
707+
DirectoryReaderImpl* impl = reinterpret_cast<DirectoryReaderImpl*>(m_internal);
708+
return impl->read(_data, _size, _err);
709+
}
710+
711+
bool stat(FileInfo& _outFileInfo, const FilePath& _filePath)
557712
{
558713
#if BX_CRT_NONE
559714
BX_UNUSED(_filePath, _outFileInfo);
560715
return false;
561716
#else
562-
_outFileInfo.m_size = 0;
563-
_outFileInfo.m_type = FileInfo::Count;
717+
_outFileInfo.size = 0;
718+
_outFileInfo.type = FileType::Count;
564719

565720
# if BX_COMPILER_MSVC
566721
struct ::_stat64 st;
@@ -573,11 +728,11 @@ namespace bx
573728

574729
if (0 != (st.st_mode & _S_IFREG) )
575730
{
576-
_outFileInfo.m_type = FileInfo::Regular;
731+
_outFileInfo.type = FileType::File;
577732
}
578733
else if (0 != (st.st_mode & _S_IFDIR) )
579734
{
580-
_outFileInfo.m_type = FileInfo::Directory;
735+
_outFileInfo.type = FileType::Dir;
581736
}
582737
# else
583738
struct ::stat st;
@@ -589,15 +744,15 @@ namespace bx
589744

590745
if (0 != (st.st_mode & S_IFREG) )
591746
{
592-
_outFileInfo.m_type = FileInfo::Regular;
747+
_outFileInfo.type = FileType::File;
593748
}
594749
else if (0 != (st.st_mode & S_IFDIR) )
595750
{
596-
_outFileInfo.m_type = FileInfo::Directory;
751+
_outFileInfo.type = FileType::Dir;
597752
}
598753
# endif // BX_COMPILER_MSVC
599754

600-
_outFileInfo.m_size = st.st_size;
755+
_outFileInfo.size = st.st_size;
601756

602757
return true;
603758
#endif // BX_CRT_NONE

src/filepath.cpp

+16-15
Original file line numberDiff line numberDiff line change
@@ -154,16 +154,16 @@ namespace bx
154154
return size;
155155
}
156156

157-
static bool getEnv(char* _out, uint32_t* _inOutSize, const StringView& _name, FileInfo::Enum _type)
157+
static bool getEnv(char* _out, uint32_t* _inOutSize, const StringView& _name, FileType::Enum _type)
158158
{
159159
uint32_t len = *_inOutSize;
160160
*_out = '\0';
161161

162162
if (getEnv(_out, &len, _name) )
163163
{
164164
FileInfo fi;
165-
if (stat(_out, fi)
166-
&& _type == fi.m_type)
165+
if (stat(fi, _out)
166+
&& _type == fi.type)
167167
{
168168
*_inOutSize = len;
169169
return true;
@@ -204,9 +204,9 @@ namespace bx
204204
{
205205
return false
206206
#if BX_PLATFORM_WINDOWS
207-
|| getEnv(_out, _inOutSize, "USERPROFILE", FileInfo::Directory)
207+
|| getEnv(_out, _inOutSize, "USERPROFILE", FileType::Dir)
208208
#endif // BX_PLATFORM_WINDOWS
209-
|| getEnv(_out, _inOutSize, "HOME", FileInfo::Directory)
209+
|| getEnv(_out, _inOutSize, "HOME", FileType::Dir)
210210
;
211211
}
212212

@@ -232,7 +232,7 @@ namespace bx
232232
{
233233
uint32_t len = *_inOutSize;
234234
*_out = '\0';
235-
bool ok = getEnv(_out, &len, *tmp, FileInfo::Directory);
235+
bool ok = getEnv(_out, &len, *tmp, FileType::Dir);
236236

237237
if (ok
238238
&& len != 0
@@ -244,8 +244,8 @@ namespace bx
244244
}
245245

246246
FileInfo fi;
247-
if (stat("/tmp", fi)
248-
&& FileInfo::Directory == fi.m_type)
247+
if (stat(fi, "/tmp")
248+
&& FileType::Dir == fi.type)
249249
{
250250
strCopy(_out, *_inOutSize, "/tmp");
251251
*_inOutSize = 4;
@@ -385,7 +385,8 @@ namespace bx
385385
const StringView fileName = getFileName();
386386
if (!fileName.isEmpty() )
387387
{
388-
return strFind(fileName, '.');
388+
const StringView dot = strFind(fileName, '.');
389+
return StringView(dot.getPtr(), fileName.getTerm() );
389390
}
390391

391392
return StringView();
@@ -443,9 +444,9 @@ namespace bx
443444

444445
FileInfo fi;
445446

446-
if (stat(_filePath, fi) )
447+
if (stat(fi, _filePath) )
447448
{
448-
if (FileInfo::Directory == fi.m_type)
449+
if (FileType::Dir == fi.type)
449450
{
450451
return true;
451452
}
@@ -482,9 +483,9 @@ namespace bx
482483
#if BX_CRT_MSVC
483484
int32_t result = -1;
484485
FileInfo fi;
485-
if (stat(_filePath, fi) )
486+
if (stat(fi, _filePath) )
486487
{
487-
if (FileInfo::Directory == fi.m_type)
488+
if (FileType::Dir == fi.type)
488489
{
489490
result = ::_rmdir(_filePath.get() );
490491
}
@@ -522,13 +523,13 @@ namespace bx
522523

523524
FileInfo fi;
524525

525-
if (!stat(_filePath, fi) )
526+
if (!stat(fi, _filePath) )
526527
{
527528
BX_ERROR_SET(_err, BX_ERROR_ACCESS, "The parent directory does not allow write permission to the process.");
528529
return false;
529530
}
530531

531-
if (FileInfo::Directory != fi.m_type)
532+
if (FileType::Dir != fi.type)
532533
{
533534
BX_ERROR_SET(_err, BX_ERROR_NOT_DIRECTORY, "File already exist, and is not directory.");
534535
return false;

0 commit comments

Comments
 (0)