-
Notifications
You must be signed in to change notification settings - Fork 7.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add FileUtils::getContents(). #15479
Conversation
c374605
to
d17a636
Compare
typename T, | ||
typename std::enable_if< | ||
std::is_base_of< ResizableBuffer, ResizableBufferAdapter<T> >::value | ||
>::type* = nullptr |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know the effect of enable_if<>, but i don't know the effect of
typename std::enable_if<xx>::type* = nullptr
What does it mean? I can not find the document for it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
http://en.cppreference.com/w/cpp/types/enable_if See Example section #4
usage.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, i have seen it, but don't understand, why can not use
typename std::enable_if<xx>::type
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It will cause Substitution Failure if ResizableBufferAdapter<T>
is not a subcalss of ResizableBuffer
.
I only defined ResizableBufferAdapter< std::vector<> >
ResizableBufferAdapter< std::string<> >
and ResizableBufferAdapter< Data >
inherited form ResizableBuffer
. So the template version of getContents()
will enabled only for std::vector<>
std::string<>
and Data
.
If user defined his own version ResizableBufferAdapter< UserType >
, that type UserType
will also suitable for calling template version of getContents()
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know the meaning, but don't understand why need to assign to nullptr. Ok, i will do more research about it.
Thanks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
template <
typename T,
typename X = std::enable_if<
std::is_base_of< ResizableBuffer, ResizableBufferAdapter<T> >::value
>::type
>
will not compile:
CCFileUtils.h:206:22: error: need 'typename' before 'std::enable_if<std::is_base_of<cocos2d::ResizableBuffer, cocos2d::ResizableBufferAdapter<T> >::value>::type' because 'std::enable_if<std::is_base_of<cocos2d::ResizableBuffer, cocos2d::ResizableBufferAdapter<T> >::value>' is a dependent scope
typename X = std::enable_if<
^
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got it, thanks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But the #5
section of http://en.cppreference.com/w/cpp/types/enable_if can work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This works:
template <
typename T,
typename X = typename std::enable_if<
std::is_base_of< ResizableBuffer, ResizableBufferAdapter<T> >::value
>::type
>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#5
section of http://en.cppreference.com/w/cpp/types/enable_if uses enable_if_t
(note the tailling _t
) is a C++14 feature.
I found only Android platform implements |
There is default: |
Sorry about my careless. I will continue viewing it tomorrow. |
@minggo |
template<typename T, typename A> | ||
class ResizableBufferAdapter< std::vector<T, A> > : public ResizableBuffer { | ||
typedef std::vector<T, A> BufferType; | ||
BufferType* buffer_; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
buffer_ -> _buffer to obey the cocos2d-x coding style
I run the test case on Mac, it said And can we use FileUtils::getContents() to implement FileUtils::getDataFromFile() and FileUtils::getStringFromFile()? Then it will remove duplicated codes. |
Does the new code of |
@xpol What i mean is use FileUtils::getContents() internally in FileUtils::getStringFromFile(), for example FileUtils::getStringFromFile()
{
...
getContents(...); // use getContents() to get needed result
} |
Yes.
|
@xpol I think it is better to keep compatibility and fix bugs in other pull request. |
public: | ||
explicit ResizableBufferAdapter(BufferType* buffer) : _buffer(buffer) {} | ||
virtual void resize(size_t size) override { | ||
_buffer->resize((size + sizeof(C) - 1) / sizeof(C)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why the size is (size + sizeof(C) - 1) / sizeof(C)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
because that the char type for string and member type for vector may not 8 bit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But i think std::basic_string<> has already handles it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
std::basic_string<>::size()
and std::basic_string<>::resize()
is talking about the number of elements (yes the name make users think it's bytes size).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So the size here is not the number of element? Why?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The ResizableBuffer::resize()
is about file bytes.
When C
is 8 bit. std::basic_string<char>::size() == file bytes
When C
is not 8 bit: std::basic_string<wchar_t>::size() != file bytes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What i mean is why size in ResizableBuffer::resize()
is bytes. If you want to read wchar_t, then developers should calculate the size of bytes itself?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ResizableBuffer::resize()
is not for user calling, FileUtils::getContents()
calls it internally:
ResizableBuffer::resize()
is called by ``at cocos/platform/CCFileUtils.cpp[line 687](https://github.com/cocos2d/cocos2d-x/pull/15479/files#diff-cb65223cd3edf30671fefad4a1883edfR687) in
FileUtils::getContents()` when the file size is determined, and thus, the file size is passed to `ResizableBuffer::resize()`.ResizableBufferAdapter
convert bytes to number of elements need.
Example Usage:
std::string<char32_t> buf;
fs->getContents(file, &buf); // resize buf automatically inside getContents()
std::cout << "I got " << buf.size() << " of wchar32_t" << std::endl;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got it, thanks.
methods are: * FileUtils::getDataFromFile() * FileUtils::getStringFromFile() * FileUtils::getFileData() and follow Android methods are now just calls FileUtils' ones. * FileUtilsAndroid::getDataFromFile() * FileUtilsAndroid::getStringFromFile() * FileUtilsAndroid::getFileData()
{ | ||
// TODO: move this function to StringUtils. | ||
// http://stackoverflow.com/a/7724536/87021 | ||
static inline std::string replaceAll( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think static is not need here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@xpol I think static is not needed when it is in an anonymous namespace.
…tils-get-contents
…os2d-x into file-utils-get-contents # Conflicts: # cocos/platform/CCFileUtils.cpp # tests/cpp-tests/Classes/FileUtilsTest/FileUtilsTest.cpp
@minggo
|
Remove the last |
Status must defined in some header, so move FileUtils.h up.
About the linux error, i think it is because some header files define a macro named
|
Yes, I have moved the include of |
ping |
bool textmode = strchr(mode, 't') != NULL; | ||
if (textmode) | ||
textFormCRLF(s); | ||
#endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think these codes should be applied to WIN32 too. Sorry for my previous answer about it. And NULL -> nullptr
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
According to comments above in our current code base :
- For
FileUtils::getStringFromFile()
: do not convert CRLF to LF on all platform including Win32 and WinRT. - For
FileUtils::getFileData()
: Only WinRT do CRLF to LF conversion (mode
arg is not used on Win32 ). And I guess this is a bug.
Did you mean in this PR, we shall do support CRLF to LF on Win32 and WinRT for both FileUtils::getStringFromFile()
and FileUtils::getFileData()
?
IMHO, we shold remove all support of CRLF to LF behavior as:
- it's not portable (and cocos2d-x is a cross platform engine).
- currently only
FileUtils::getFileData()
on WinRT support CRLF to LF. - all other case (non WinRT or not
FileUtils::getFileData()
), the current behavior is not convert CRLF to LF.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, i misunderstood of the logic of textFormCRLF
. Yep, i agree with you, we should not convert CRLF to LF. So i think we can remove these codes.
@xpol I added comments above. I think i can merge it when it is resolved. Thanks. |
I updated the line note, I just want to make it sure. Would please inspect the the links in above line note link to current |
@xpol I think we can remove the codes
And static is not needed if a function is in an anonymous namespace. |
OK then all platform has the same behavior: no text mode support for file reading. BTW, the static and NULL issues is gone as they are in the CRLF to LF support code. |
Thanks. I think it is ok to do it like this. And let's fix it if we met issues in future. |
Glad I can help. |
* Add FileUtils::getContents(). * skip FileUtils::getContents() in binding generator config. * use FileUtils::getContents in CCDataReaderHelper. * obey the cocos2d-x coding style. * Explicit constructor. * More docs. * More tests. * Move FileError to FileUtils::Error. * Fixes wrong buffer size for reading into string and vector. * Update tests. * Add note on padding for output buffers. * FileUtils: implements old methods by using `getContents()`. methods are: * FileUtils::getDataFromFile() * FileUtils::getStringFromFile() * FileUtils::getFileData() and follow Android methods are now just calls FileUtils' ones. * FileUtilsAndroid::getDataFromFile() * FileUtilsAndroid::getStringFromFile() * FileUtilsAndroid::getFileData() * Fixes build error. * FileUtils::getFileData: Return the size of data. * Remove old methods form FileUtilsAndroid they are now done in FileUtils. * Fixes for win32 code. * Fixes build error in test and add more test. * Better error message. * Make template type name more readable. * Update comments. * Move internal functions to anonymous namespace. * Refactor FileUtils test. * Fix warning about compare signed and unsigned. * Win32 and WinRT does not use text mode. That is we don't need simulate convert CRLF to LF. * Fixes for Win32 and WinRT. * Update for Win32 and WinRT. * Win32: return FileUtils:Error::TooLarge when file is large than 2^32-1. * Win32: remove checkFileName() which has no effect at all. * WinRT: add FileUtilsWinRT::getContents() using ::CreateFile2. * WinRT: add override keyword for FileUtilsWinRT::getFileSize(). * Update for coding styles. * More error strings. * check read and malloc return codes. * rename FileUtils::Error to FileUtils::Status. * Fixes for WinRT, use GetFileInformationByHandleEx to get file size. * Fixes build error for winrt and cleanup FileUtils::Status. * Try to fix the build error on Linux. Status must defined in some header, so move FileUtils.h up. * Remove support of text mode on WinRT (it is the last platform support text mode).
* Add FileUtils::getContents(). * skip FileUtils::getContents() in binding generator config. * use FileUtils::getContents in CCDataReaderHelper. * obey the cocos2d-x coding style. * Explicit constructor. * More docs. * More tests. * Move FileError to FileUtils::Error. * Fixes wrong buffer size for reading into string and vector. * Update tests. * Add note on padding for output buffers. * FileUtils: implements old methods by using `getContents()`. methods are: * FileUtils::getDataFromFile() * FileUtils::getStringFromFile() * FileUtils::getFileData() and follow Android methods are now just calls FileUtils' ones. * FileUtilsAndroid::getDataFromFile() * FileUtilsAndroid::getStringFromFile() * FileUtilsAndroid::getFileData() * Fixes build error. * FileUtils::getFileData: Return the size of data. * Remove old methods form FileUtilsAndroid they are now done in FileUtils. * Fixes for win32 code. * Fixes build error in test and add more test. * Better error message. * Make template type name more readable. * Update comments. * Move internal functions to anonymous namespace. * Refactor FileUtils test. * Fix warning about compare signed and unsigned. * Win32 and WinRT does not use text mode. That is we don't need simulate convert CRLF to LF. * Fixes for Win32 and WinRT. * Update for Win32 and WinRT. * Win32: return FileUtils:Error::TooLarge when file is large than 2^32-1. * Win32: remove checkFileName() which has no effect at all. * WinRT: add FileUtilsWinRT::getContents() using ::CreateFile2. * WinRT: add override keyword for FileUtilsWinRT::getFileSize(). * Update for coding styles. * More error strings. * check read and malloc return codes. * rename FileUtils::Error to FileUtils::Status. * Fixes for WinRT, use GetFileInformationByHandleEx to get file size. * Fixes build error for winrt and cleanup FileUtils::Status. * Try to fix the build error on Linux. Status must defined in some header, so move FileUtils.h up. * Remove support of text mode on WinRT (it is the last platform support text mode).
Why another file read API?
Current APIs has some problem:
FileUtils::getDataFormFile()
can't return string, convert from Data to string will make extra copy.FileUtils::getStringFormFile()
can't read binary file, and it truncate contents.FileUtils::getDataFormFile()
andFileUtils::getStringFormFile()
does not tell different from empty file and io errors.Advantage of
FileUtils::getContents()
cocos2d::Data
std::basic_string
andstd::vector
ResizableBuffer
.