@@ -257,6 +257,38 @@ struct obj_shape {
257257 std::vector<float > vt;
258258};
259259
260+ // See
261+ // http://stackoverflow.com/questions/6089231/getting-std-ifstream-to-handle-lf-cr-and-crlf
262+ static std::istream &safeGetline (std::istream &is, std::string &t) {
263+ t.clear ();
264+
265+ // The characters in the stream are read one-by-one using a std::streambuf.
266+ // That is faster than reading them one-by-one using the std::istream.
267+ // Code that uses streambuf this way must be guarded by a sentry object.
268+ // The sentry object performs various tasks,
269+ // such as thread synchronization and updating the stream state.
270+
271+ std::istream::sentry se (is, true );
272+ std::streambuf *sb = is.rdbuf ();
273+
274+ for (;;) {
275+ int c = sb->sbumpc ();
276+ switch (c) {
277+ case ' \n ' :
278+ return is;
279+ case ' \r ' :
280+ if (sb->sgetc () == ' \n ' ) sb->sbumpc ();
281+ return is;
282+ case EOF :
283+ // Also handle the case when the last line has no line ending
284+ if (t.empty ()) is.setstate (std::ios::eofbit);
285+ return is;
286+ default :
287+ t += static_cast <char >(c);
288+ }
289+ }
290+ }
291+
260292#define IS_SPACE (x ) (((x) == ' ' ) || ((x) == ' \t ' ))
261293#define IS_DIGIT (x ) \
262294 (static_cast <unsigned int >((x) - ' 0' ) < static_cast <unsigned int >(10 ))
@@ -646,12 +678,10 @@ void LoadMtl(std::map<std::string, int> *material_map,
646678 material_t material;
647679 InitMaterial (&material);
648680
649- size_t maxchars = 8192 ; // Alloc enough size.
650- std::vector<char > buf (maxchars); // Alloc enough size.
651681 while (inStream->peek () != -1 ) {
652- inStream-> getline (&buf[ 0 ], static_cast < std::streamsize>(maxchars)) ;
682+ std::string linebuf ;
653683
654- std::string linebuf (&buf[ 0 ] );
684+ safeGetline (*inStream, linebuf);
655685
656686 // Trim trailing whitespace.
657687 if (linebuf.size () > 0 ) {
@@ -1031,7 +1061,7 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
10311061
10321062 while (inStream->peek () != -1 ) {
10331063 std::string linebuf;
1034- std::getline (( *inStream) , linebuf);
1064+ safeGetline ( *inStream, linebuf);
10351065
10361066 // Trim newline '\r\n' or '\n'
10371067 if (linebuf.size () > 0 ) {
@@ -1312,7 +1342,7 @@ bool LoadObjWithCallback(std::istream &inStream, const callback_t &callback,
13121342
13131343 std::string linebuf;
13141344 while (inStream.peek () != -1 ) {
1315- std::getline (inStream, linebuf);
1345+ safeGetline (inStream, linebuf);
13161346
13171347 // Trim newline '\r\n' or '\n'
13181348 if (linebuf.size () > 0 ) {
0 commit comments