// http://dev.w3.org/csswg/css-syntax/#consume-a-string-token MediaQueryToken MediaQueryTokenizer::consumeStringTokenUntil(UChar endingCodePoint) { StringBuilder output; while (true) { UChar cc = consume(); if (cc == endingCodePoint || cc == kEndOfFileMarker) { // The "reconsume" here deviates from the spec, but is required to avoid consuming past the EOF if (cc == kEndOfFileMarker) reconsume(cc); return MediaQueryToken(StringToken, output.toString()); } if (isNewLine(cc)) { reconsume(cc); return MediaQueryToken(BadStringToken); } if (cc == '\\') { if (m_input.nextInputChar() == kEndOfFileMarker) continue; if (isNewLine(m_input.nextInputChar())) consume(); else output.append(consumeEscape()); } else { output.append(cc); } } }
/* * Delete the new line chars. * TODO: each chunk must be ended ';' */ ptrdiff_t LuaObfuscator::removeNewLines(char *szLuaCode) { char const *arrClearChar = "{}()[].,;+-*/^%<>~=#\n"; char *p = szLuaCode; if (!p || !p[0]) return 0; char *pDest = p; while (*p && isNewLine(*p)) ++p; while (*p) { if (isSingleStringStart(p)) { size_t size = skipStringAndMove(&p, NULL); // &pDest char *end = p; p -= size; char cPrev = 0; for ( ; p < end; ++p) { if (isNewLine(*p) && cPrev == '\\') { *(pDest++) = 'n'; } else { *(pDest++) = *p; } cPrev = *p; } continue; } if (isMultilineStringStart(p)) { skipStringAndMove(&p, &pDest); } if (isNewLine(*p)) { char cPrev = *(p - 1); while (*p && isNewLine(*p)) ++p; if (cPrev == '\\') { *(pDest++) = 'n'; // within string here } else if (cPrev == '"') { // TODO: hack to locale string *(pDest++) = ';'; } else if (!strchr(arrClearChar, cPrev)) { // cPrev != ';' && cPrev != ')' *(pDest++) = ' '; } if (isSpace(*p)) ++p; continue; } *(pDest++) = *p++; } if (isSpace(*(pDest - 1))) { --pDest; } *pDest = 0; return pDest - p; }
static void lex_scanNewLine(z_lexstate *ls) { if(isNewLine(nc)) { char nlc = nc; lex_nextchar(ls); if(isNewLine(nc) && nc != nlc) // treat LF + CR newlines lex_nextchar(ls); lex_incline(ls); } }
bool Tokenizer::goToNextLine(){ if (end < length){ start = end; while (end < length && !isNewLine(str[end])) end++; if (isNewLine(str[end + 1]) && str[end] != str[end + 1]) end += 2; else end++; return true; } return false; }
Int16u GetNewLineLength (const char far * string) { Int16u result = 0; if (isNewLine (string)) { if (string [1] != string [0] && isNewLine (&string [1])) ++result; ++result; } return result; }
char *OpenDDLParser::parseIdentifier( char *in, char *end, Text **id ) { *id = ddl_nullptr; if( ddl_nullptr == in || in == end ) { return in; } // ignore blanks in = lookForNextToken( in, end ); // staring with a number is forbidden if( isNumeric<const char>( *in ) ) { return in; } // get size of id size_t idLen( 0 ); char *start( in ); while( !isSeparator( *in ) && !isNewLine( *in ) && ( in != end ) && *in != Grammar::OpenPropertyToken[ 0 ] && *in != Grammar::ClosePropertyToken[ 0 ] && *in != '$' ) { ++in; ++idLen; } const size_t len( idLen ); *id = new Text( start, len ); return in; }
void Preprocessor::parseMultiLineComment() { advance(2); setFirstOnLine(false); for (;;) { if (!hasMore()) { logError("%s:%u: Unexpected end of file in multi-line comment", files.back().name, files.back().line); throw Exception("Unexpected end of file in multi-line comment"); } if (c(0) == '*' && c(1) == '/') { advance(2); break; } else if (isNewLine()) parseNewLine(); else advance(1); } appendToOutput(); }
// ------------------------------------------------------------------- // Creates a material from loaded data. void ObjFileMtlImporter::createMaterial() { std::string line( "" ); while ( !isNewLine( *m_DataIt ) ) { line += *m_DataIt; ++m_DataIt; } std::vector<std::string> token; const unsigned int numToken = tokenize<std::string>( line, token, " " ); std::string name( "" ); if ( numToken == 1 ) { name = AI_DEFAULT_MATERIAL_NAME; } else { name = token[ 1 ]; } std::map<std::string, ObjFile::Material*>::iterator it = m_pModel->m_MaterialMap.find( name ); if ( m_pModel->m_MaterialMap.end() == it) { // New Material created m_pModel->m_pCurrentMaterial = new ObjFile::Material(); m_pModel->m_pCurrentMaterial->MaterialName.Set( name ); m_pModel->m_MaterialLib.push_back( name ); m_pModel->m_MaterialMap[ name ] = m_pModel->m_pCurrentMaterial; } else { // Use older material m_pModel->m_pCurrentMaterial = (*it).second; } }
// ------------------------------------------------------------------- // Get material library from file. void ObjFileParser::getMaterialLib() { // Translate tuple m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd); if (m_DataIt == m_DataItEnd) return; char *pStart = &(*m_DataIt); while (m_DataIt != m_DataItEnd && !isNewLine(*m_DataIt)) m_DataIt++; // Check for existence const std::string strMatName(pStart, &(*m_DataIt)); IOStream *pFile = m_pIO->Open(strMatName); if (!pFile ) { DefaultLogger::get()->error("OBJ: Unable to locate material file " + strMatName); m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine ); return; } // Import material library data from file std::vector<char> buffer; BaseImporter::TextFileToBuffer(pFile,buffer); m_pIO->Close( pFile ); // Importing the material library ObjFileMtlImporter mtlImporter( buffer, strMatName, m_pModel ); }
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- プロトタイプ:char *fgetLine(FILE *); 引数 :FILE *rfp 読み込むファイルへのポインタ 返り値 char * 読み込んだ1行 ※ファイルの終わりの場合はNULL 説明 :rfpで指定されたファイルから1行読み込み、その文字列を格納した 領域へのポインタを返す。 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ char *fgetLine(FILE *rfp) { char buf[BUFSIZE]; char *tmp = NULL; while(fgets(buf, BUFSIZE, rfp) != NULL) { if(!tmp) { tmp = (char *)malloc(strlen(buf) + 1); if(tmp == NULL) { perror("Memory allocation error."); return NULL; } strcpy(tmp, buf); } else { tmp = (char *)realloc((char *)tmp, strlen(tmp) + strlen(buf) + 1); if(tmp == NULL) { perror("Memory reallocation error."); return NULL; } strcat(tmp, buf); } if(isNewLine(buf)) return tmp; else if(strlen(buf) < BUFSIZE) return tmp; } return NULL; }
Int16u GetWordLength (const char far * string) { Int16u result = 0; #if defined (DBCS) if (IsDBCSEnabled () && !isascii (*string)) { result = (AnsiNext (string)) - ((char *)string); string += result; return result; } #endif //(DBCS) while (*string != '\0' && !isWhite (*string) && !isNewLine (string) #if defined (DBCS) && (!IsDBCSEnabled () || isascii (*string)) #endif //(DBCS) ) { ++result; ++string; } return result; }
void OpenDDLParser::normalizeBuffer( std::vector<char> &buffer) { if( buffer.empty() ) { return; } std::vector<char> newBuffer; const size_t len( buffer.size() ); char *end( &buffer[ len-1 ] + 1 ); for( size_t readIdx = 0; readIdx<len; ++readIdx ) { char *c( &buffer[readIdx] ); // check for a comment if (isCommentOpenTag(c, end)) { ++readIdx; while (!isCommentCloseTag(&buffer[readIdx], end)) { ++readIdx; } ++readIdx; ++readIdx; } else if( !isComment<char>( c, end ) && !isNewLine( *c ) ) { newBuffer.push_back( buffer[ readIdx ] ); } else { if( isComment<char>( c, end ) ) { ++readIdx; // skip the comment and the rest of the line while( !isEndofLine( buffer[ readIdx ] ) ) { ++readIdx; } } } } buffer = newBuffer; }
// http://dev.w3.org/csswg/css-syntax/#consume-an-escaped-code-point UChar CSSTokenizer::consumeEscape() { UChar cc = consume(); ASSERT(!isNewLine(cc)); if (isASCIIHexDigit(cc)) { unsigned consumedHexDigits = 1; StringBuilder hexChars; hexChars.append(cc); while (consumedHexDigits < 6 && isASCIIHexDigit(m_input.nextInputChar())) { cc = consume(); hexChars.append(cc); consumedHexDigits++; }; consumeSingleWhitespaceIfNext(); bool ok = false; UChar codePoint = hexChars.toString().toUIntStrict(&ok, 16); if (!ok) return WTF::Unicode::replacementCharacter; return codePoint; } // Replaces NULLs with replacement characters, since we do not perform preprocessing if (cc == kEndOfFileMarker) return WTF::Unicode::replacementCharacter; return cc; }
// http://dev.w3.org/csswg/css-syntax/#consume-an-escaped-code-point UChar32 CSSTokenizer::consumeEscape() { UChar cc = consume(); ASSERT(!isNewLine(cc)); if (isASCIIHexDigit(cc)) { unsigned consumedHexDigits = 1; StringBuilder hexChars; hexChars.append(cc); while (consumedHexDigits < 6 && isASCIIHexDigit(m_input.nextInputChar())) { cc = consume(); hexChars.append(cc); consumedHexDigits++; }; consumeSingleWhitespaceIfNext(); bool ok = false; UChar32 codePoint = hexChars.toString().toUIntStrict(&ok, 16); ASSERT(ok); if (codePoint == 0 || (0xD800 <= codePoint && codePoint <= 0xDFFF) || codePoint > 0x10FFFF) return replacementCharacter; return codePoint; } if (cc == kEndOfFileMarker) return replacementCharacter; return cc; }
ptrdiff_t LuaObfuscator::removeComments(char *szLuaCode) { char *p = szLuaCode; char *pDest = szLuaCode; while (*p) { if (isStringStart(p)) { skipStringAndMove(&p, &pDest); continue; } // TODO: endians if (*((uint32_t*)p) == 0x5B5B2D2D) { // 0x5B5B2D2D== '[[--' while (*p && *(uint16_t*)p != 0x5D5D) // 0x5D5D == ']]' ++p; if (*p) p += 2; ++m_statistic.multilineCommentCount; } else if (*((uint16_t*)p) == 0x2D2D) { // 0x == '--' p += 2; while (*p && !isNewLine(*p)) ++p; ++m_statistic.singleCommentCount; } *pDest = *p; ++p; ++pDest; } *pDest = 0; return pDest - p; }
/** * Lex the string into tokens, each of which has a given offset into the string. * Lexing is done by the following algorithm: * (1) If the current character is a space, and if it is then check the next: * (a) If it is another space, then the token is a tab. * (b) If it is some other character, the token is a space. * (2) If the current character is a character (either upper or lower case), or a digit, * then continue until the first non-matching character and that is an ident. * (3) If the current character is a #, then ignore everything until the end of the line. * (4) If the current character is a newline, then the token is a newline. * (5) If the current character is a colon, then the token is just a colon. * (6) If the current character is a quote, then read until the endquote and * declare the string as the contents of the string. */ Token* lex(char* input, int len) { Token* first = newToken(0, 0, 0); Token* last = first; int index = 0; while (index < len-1) { //printf("*"); int start = index; char cur = input[index]; if (isSpace(cur)) { if (isSpace(input[index+1])) { index++; addNewToken(last, TAB, start, index); } else { addNewToken(last, SPACE, index, index); } index++; } else if (isTab(cur)) { index++; addNewToken(last, TAB, start, index); } else if (isChar(cur)) { while (isChar(input[++index])); addNewToken(last, IDENT, start, index); } else if (isComment(cur)) { while (!isNewLine(input[++index])); } else if (isNewLine(cur)) { index++; addNewToken(last, NEWLINE, index, index); } else if (isColon(cur)) { index++; addNewToken(last, COLON, index, index); } else if (isQuote(cur)) { while (!isQuote(input[++index])); addNewToken(last, STRING, start+1, index); index++; /* Pass by the end quote. */ } if (last->next != NULL) last = last->next; } addNewToken(last, NEWLINE, index, index); return first->next; }
char* skipLine(char* it, char* end, std::size_t& num) { std::size_t cnt = 0; while (!isEndOfStream(it, end) && !isNewLine(*it)) { ++it; ++cnt; } while (it != end && isNewLine(*it)) { ++it; ++cnt; } num = cnt; return it; }
/* * delete dublicated spaces */ ptrdiff_t LuaObfuscator::removeDumplicatedChars(char *szLuaCode) { char *pDest = szLuaCode; char *p = szLuaCode; while (*p) { if (isStringStart(p)) { skipStringAndMove(&p, &pDest); continue; } if (!((isSpace(*p) && isSpace(*(p - 1))) || (isNewLine(*p) && isNewLine(*(p - 1))))) { *pDest = *p; ++pDest; } ++p; } *pDest = 0; return pDest - p; }
// http://dev.w3.org/csswg/css-syntax/#consume-a-string-token CSSParserToken CSSTokenizer::consumeStringTokenUntil(UChar endingCodePoint) { // Strings without escapes get handled without allocations for (unsigned size = 0; ; size++) { UChar cc = m_input.peekWithoutReplacement(size); if (cc == endingCodePoint) { unsigned startOffset = m_input.offset(); m_input.advance(size + 1); return CSSParserToken(StringToken, m_input.rangeAsCSSParserString(startOffset, size)); } if (isNewLine(cc)) { m_input.advance(size); return CSSParserToken(BadStringToken); } if (cc == '\0' || cc == '\\') break; } StringBuilder output; while (true) { UChar cc = consume(); if (cc == endingCodePoint || cc == kEndOfFileMarker) return CSSParserToken(StringToken, registerString(output.toString())); if (isNewLine(cc)) { reconsume(cc); return CSSParserToken(BadStringToken); } if (cc == '\\') { if (m_input.nextInputChar() == kEndOfFileMarker) continue; if (isNewLine(m_input.nextInputChar())) consumeSingleWhitespaceIfNext(); // This handles \r\n for us else output.append(consumeEscape()); } else { output.append(cc); } } }
void Preprocessor::parseSingleLineComment() { advance(2); setFirstOnLine(false); while (hasMore()) { if (isNewLine()) break; else advance(1); } appendToOutput(); }
String Preprocessor::passShaderName() { char terminator; if (c(0) == '<') terminator = '>'; else if (c(0) == '\"') terminator = '\"'; else { logError("%s:%u: Expected \'<\' or \'\"\' after #include", files.back().name, files.back().line); throw Exception("Expected \'<\' or \'\"\' after #include"); } advance(1); String name; while (hasMore()) { if (!hasMore() || isNewLine()) { logError("%s:%u: Expected \'%c\' after shader name", files.back().name, files.back().line, terminator); throw Exception("Expected \'<\' or \'\"\' after shader name"); } if (c(0) == terminator) { advance(1); break; } else { name.append(1, c(0)); advance(1); } } return name; }
void Preprocessor::parse(const char* name, const char* text) { if (std::find(names.begin(), names.end(), name) != names.end()) return; files.push_back(File(name, text)); names.push_back(name); list += format("( file %u: %s )\n", (uint) names.size(), name); output.reserve(output.size() + std::strlen(text)); appendToOutput(format("#line 0 %u /* entering %s */\n", (uint) files.size(), files.back().name).c_str()); while (hasMore()) { if (isMultiLineComment()) parseMultiLineComment(); else if (isSingleLineComment()) parseSingleLineComment(); else if (isNewLine()) parseNewLine(); else if (isWhitespace()) parseWhitespace(); else if (isCommand()) parseCommand(); else { advance(1); appendToOutput(); setFirstOnLine(false); } } files.pop_back(); if (!files.empty()) { appendToOutput(format("\n#line %u %u /* returning to %s */", files.back().line, (uint) files.size(), files.back().name).c_str()); } }
void Preprocessor::parseCommand() { advance(1); setFirstOnLine(false); passWhitespace(); const String command = passIdentifier(); if (command == "include") { passWhitespace(); const String name = passShaderName(); discard(); parse(name.c_str()); } else if (command == "version") { if (!version.empty()) { logError("%s:%u: Duplicate #version directive", files.back().name, files.back().line); throw Exception("Duplicate #version directive"); } passWhitespace(); version = passNumber(); discard(); } while (hasMore()) { if (isNewLine() || isSingleLineComment() || isMultiLineComment()) break; advance(1); } appendToOutput(); }
BAMtlLibrary* BAMtlLibraryNew(const char* filename) { char path[PATH_MAX] = {0}; if(MCFileGetPath(filename, path)) { return null; } const char* assetbuff = MCFileCopyContentWithPath(path); if (assetbuff != null) { BAMtlLibrary* lib = BAMtlLibraryAlloc(); if (lib == null) { error_log("BAMtlParser - MC3DMtlLibraryAlloc failed.\n"); return null; } char line[LINE_MAX]; char* c = (char*)assetbuff; while (*c!=NUL) { //skip '\n' '\r\n' '\t' ' ' if (*c==MCNewLineN || *c==MCNewLineR || *c==MCTab || *c==MCWhiteSpace) { c++; continue; } for (int i=0; !isNewLine(c); c++) { line[i++] = *c; line[i] = NUL; } processMtlLine(lib, line); } free((void*)assetbuff); MCStringFill(lib->name, filename); return lib; }else{ error_log("BAMtlParser - AAssetManager_open %s failed\n", filename); return null; } }
// http://dev.w3.org/csswg/css-syntax/#check-if-two-code-points-are-a-valid-escape static bool twoCharsAreValidEscape(UChar first, UChar second) { return first == '\\' && !isNewLine(second) && second != kEndOfFileMarker; }
// http://dev.w3.org/csswg/css-syntax/#check-if-two-code-points-are-a-valid-escape static bool twoCharsAreValidEscape(UChar first, UChar second) { return first == '\\' && !isNewLine(second); }
void ObjectParser( TArray<FVector>& positions, TArray<FVector>& normals, TArray<FVector2D>& uvs, TArray<int32>& indices ) { char filepath[1024]; sprintf_s(filepath, "../../../../../../Siggraph2017/assets/Simplygon/InfinityBlade/InfinityBladeAdversaries/Enemy_Bear/clean_Enemy_Bear_099.obj"); std::ifstream ifs(filepath); if (!ifs) { UE_LOG(LogTemp, Warning, TEXT("output : %s"), L"オブジェクトファイルの読み込みに失敗しました"); } int maxchars = 8192; // Alloc enough size. std::vector<char> buf(maxchars); // Alloc enough size. while (ifs.peek() != -1) { ifs.getline(&buf[0], maxchars); std::string linebuf(&buf[0]); // Trim newline '\r\n' or '\r' if (linebuf.size() > 0) { if (linebuf[linebuf.size() - 1] == '\n') linebuf.erase(linebuf.size() - 1); } if (linebuf.size() > 0) { if (linebuf[linebuf.size() - 1] == '\n') linebuf.erase(linebuf.size() - 1); } // Skip if empty line. if (linebuf.empty()) { continue; } // Skip leading space. const char* token = linebuf.c_str(); token += strspn(token, " \t"); assert(token); if (token[0] == '\0') continue; // empty line if (token[0] == '#') continue; // comment line // vertex if (token[0] == 'v' && isSpace((token[1]))) { token += 2; float xyz[3]; parseFloat3(xyz[0], xyz[1], xyz[2], token); positions.Add(FVector(xyz[0], xyz[1], xyz[2])); continue; } // normal if (token[0] == 'v' && token[1] == 'n' && isSpace((token[2]))) { token += 3; float xyz[3]; parseFloat3(xyz[0], xyz[1], xyz[2], token); normals.Add(FVector(xyz[0], xyz[1], xyz[2])); continue; } // texcoord if (token[0] == 'v' && token[1] == 't' && isSpace((token[2]))) { token += 3; float uv[2]; parseFloat2(uv[0], uv[1], token); uvs.Add(FVector2D(uv[0], 1.0f - uv[1])); continue; } // face if (token[0] == 'f' && isSpace((token[1]))) { token += 2; token += strspn(token, " \t"); std::vector<vertex_index> face; int tmp[3]; int tmp_index = 0; while (!isNewLine(token[0])) { vertex_index vi = parseTriple(token, 3, 3, 2); tmp[tmp_index] = vi.v_idx; tmp_index++; int n = strspn(token, " \t\r"); token += n; } indices.Add(tmp[2]); indices.Add(tmp[1]); indices.Add(tmp[0]); continue; } // use mtl if ((0 == strncmp(token, "usemtl", 6)) && isSpace((token[6]))) { continue; } // load mtl if ((0 == strncmp(token, "mtllib", 6)) && isSpace((token[6]))) { continue; } // group name if (token[0] == 'g' && isSpace((token[1]))) { continue; } // object name if (token[0] == 'o' && isSpace((token[1]))) { continue; } // Ignore unknown command. } }
std::string ObjLoader::LoadObj(shapes_t& shapes, const char* filename, const char* mtl_basepath) { shapes.reset(); std::stringstream err; std::istringstream ifs(FileUtils::getInstance()->getStringFromFile(filename)); std::map<vertex_index, ssize_t> vertexCache; //std::ifstream ifs(filename); if (!ifs) { err << "Cannot open file [" << filename << "]" << std::endl; return err.str(); } std::vector<float> v; std::vector<float> vn; std::vector<float> vt; std::vector<std::vector<vertex_index> > faceGroup; std::string name; // material std::map<std::string, material_t> material_map; material_t material; int maxchars = 8192; // Alloc enough size. std::vector<char> buf(maxchars); // Alloc enough size. while (ifs.peek() != -1) { ifs.getline(&buf[0], maxchars); std::string linebuf(&buf[0]); // Trim newline '\r\n' or '\r' if (linebuf.size() > 0) { if (linebuf[linebuf.size()-1] == '\n') linebuf.erase(linebuf.size()-1); } if (linebuf.size() > 0) { if (linebuf[linebuf.size()-1] == '\n') linebuf.erase(linebuf.size()-1); } // Skip if empty line. if (linebuf.empty()) { continue; } // Skip leading space. const char* token = linebuf.c_str(); token += strspn(token, " \t"); assert(token); if (token[0] == '\0') continue; // empty line if (token[0] == '#') continue; // comment line // vertex if (token[0] == 'v' && isSpace((token[1]))) { token += 2; float x, y, z; parseFloat3(x, y, z, token); v.push_back(x); v.push_back(y); v.push_back(z); continue; } // normal if (token[0] == 'v' && token[1] == 'n' && isSpace((token[2]))) { token += 3; float x, y, z; parseFloat3(x, y, z, token); vn.push_back(x); vn.push_back(y); vn.push_back(z); continue; } // texcoord if (token[0] == 'v' && token[1] == 't' && isSpace((token[2]))) { token += 3; float x, y; parseFloat2(x, y, token); vt.push_back(x); vt.push_back(y); continue; } // face if (token[0] == 'f' && isSpace((token[1]))) { token += 2; token += strspn(token, " \t"); std::vector<vertex_index> face; while (!isNewLine(token[0])) { // fix warning, cast to int, i think int is enough vertex_index vi = parseTriple(token, (int)v.size() / 3, (int)vn.size() / 3, (int)vt.size() / 2); face.push_back(vi); auto n = strspn(token, " \t\r"); token += n; } faceGroup.push_back(face); continue; } // use mtl if ((0 == strncmp(token, "usemtl", 6)) && isSpace((token[6]))) { exportFaceGroupToShape(vertexCache, shapes, v, vn, vt, faceGroup, material, name); faceGroup.clear(); char namebuf[4096]; token += 7; sscanf(token, "%s", namebuf); if (material_map.find(namebuf) != material_map.end()) { material = material_map[namebuf]; } else { // { error!! material not found } InitMaterial(material); } continue; } // load mtl if ((0 == strncmp(token, "mtllib", 6)) && isSpace((token[6]))) { char namebuf[4096]; token += 7; sscanf(token, "%s", namebuf); std::string err_mtl = LoadMtl(material_map, namebuf, mtl_basepath); if (!err_mtl.empty()) { faceGroup.clear(); // for safety //return err_mtl; } continue; } // group name if (token[0] == 'g' && isSpace((token[1]))) { // flush previous face group. shape_t shape; exportFaceGroupToShape(vertexCache, shapes, v, vn, vt, faceGroup, material, name); faceGroup.clear(); std::vector<std::string> names; while (!isNewLine(token[0])) { std::string str = parseString(token); names.push_back(str); token += strspn(token, " \t\r"); // skip tag } assert(names.size() > 0); // names[0] must be 'g', so skipt 0th element. if (names.size() > 1) { name = names[1]; } else { name = ""; } continue; } // object name if (token[0] == 'o' && isSpace((token[1]))) { // flush previous face group. shape_t shape; exportFaceGroupToShape(vertexCache, shapes, v, vn, vt, faceGroup, material, name); faceGroup.clear(); // @todo { multiple object name? } char namebuf[4096]; token += 2; sscanf(token, "%s", namebuf); name = std::string(namebuf); continue; } // Ignore unknown command. } shape_t shape; exportFaceGroupToShape(vertexCache, shapes, v, vn, vt, faceGroup, material, name); faceGroup.clear(); // for safety return err.str(); }
std::string LoadObj( std::vector<shape_t>& shapes, std::vector<material_t>& materials, // [output] std::istream& inStream, MaterialReader& readMatFn) { std::stringstream err; std::vector<float> v; std::vector<float> vn; std::vector<float> vt; std::vector<std::vector<vertex_index> > faceGroup; std::string name; // material std::map<std::string, int> material_map; std::map<vertex_index, unsigned int> vertexCache; int material = -1; shape_t shape; int maxchars = 8192; // Alloc enough size. std::vector<char> buf(maxchars); // Alloc enough size. while (inStream.peek() != -1) { inStream.getline(&buf[0], maxchars); std::string linebuf(&buf[0]); // Trim newline '\r\n' or '\n' if (linebuf.size() > 0) { if (linebuf[linebuf.size()-1] == '\n') linebuf.erase(linebuf.size()-1); } if (linebuf.size() > 0) { if (linebuf[linebuf.size()-1] == '\r') linebuf.erase(linebuf.size()-1); } // Skip if empty line. if (linebuf.empty()) { continue; } // Skip leading space. const char* token = linebuf.c_str(); token += strspn(token, " \t"); assert(token); if (token[0] == '\0') continue; // empty line if (token[0] == '#') continue; // comment line // vertex if (token[0] == 'v' && isSpace((token[1]))) { token += 2; float x, y, z; parseFloat3(x, y, z, token); v.push_back(x); v.push_back(y); v.push_back(z); continue; } // normal if (token[0] == 'v' && token[1] == 'n' && isSpace((token[2]))) { token += 3; float x, y, z; parseFloat3(x, y, z, token); vn.push_back(x); vn.push_back(y); vn.push_back(z); continue; } // texcoord if (token[0] == 'v' && token[1] == 't' && isSpace((token[2]))) { token += 3; float x, y; parseFloat2(x, y, token); vt.push_back(x); vt.push_back(y); continue; } // face if (token[0] == 'f' && isSpace((token[1]))) { token += 2; token += strspn(token, " \t"); std::vector<vertex_index> face; while (!isNewLine(token[0])) { vertex_index vi = parseTriple(token, v.size() / 3, vn.size() / 3, vt.size() / 2); face.push_back(vi); int n = strspn(token, " \t\r"); token += n; } faceGroup.push_back(face); continue; } // use mtl if ((0 == strncmp(token, "usemtl", 6)) && isSpace((token[6]))) { char namebuf[4096]; token += 7; sscanf(token, "%s", namebuf); faceGroup.clear(); if (material_map.find(namebuf) != material_map.end()) { material = material_map[namebuf]; } else { // { error!! material not found } material = -1; } continue; } // load mtl if ((0 == strncmp(token, "mtllib", 6)) && isSpace((token[6]))) { char namebuf[4096]; token += 7; sscanf(token, "%s", namebuf); std::string err_mtl = readMatFn(namebuf, materials, material_map); if (!err_mtl.empty()) { faceGroup.clear(); // for safety return err_mtl; } continue; } // group name if (token[0] == 'g' && isSpace((token[1]))) { // flush previous face group. bool ret = exportFaceGroupToShape(shape, vertexCache, v, vn, vt, faceGroup, material, name, true); if (ret) { shapes.push_back(shape); } shape = shape_t(); //material = -1; faceGroup.clear(); std::vector<std::string> names; while (!isNewLine(token[0])) { std::string str = parseString(token); names.push_back(str); token += strspn(token, " \t\r"); // skip tag } assert(names.size() > 0); // names[0] must be 'g', so skipt 0th element. if (names.size() > 1) { name = names[1]; } else { name = ""; } continue; } // object name if (token[0] == 'o' && isSpace((token[1]))) { // flush previous face group. bool ret = exportFaceGroupToShape(shape, vertexCache, v, vn, vt, faceGroup, material, name, true); if (ret) { shapes.push_back(shape); } //material = -1; faceGroup.clear(); shape = shape_t(); // @todo { multiple object name? } char namebuf[4096]; token += 2; sscanf(token, "%s", namebuf); name = std::string(namebuf); continue; } // Ignore unknown command. } bool ret = exportFaceGroupToShape(shape, vertexCache, v, vn, vt, faceGroup, material, name, true); if (ret) { shapes.push_back(shape); } faceGroup.clear(); // for safety return err.str(); }
static z_token lex_scan(z_lexstate *ls) { if(ls->cur.eof) { lex_save(ls); return lex_newToken(ls, T_EOF, 0); } if(isWhite(nc)) { while(isWhite(nc)) { if(isNewLine(nc)) { lex_scanNewLine(ls); return lex_newToken(ls, T_NL, tk_generic); } else lex_nextchar(ls); } return lex_scan(ls); } /* line comment */ if(nc == '/') { if(nnc == '/') { while(!isNewLine(nc)) lex_nextchar(ls); return lex_scan(ls); } } /* multi line comment */ if(nc == '/') { if(nnc == '*') { lex_nextchar(ls); lex_nextchar(ls); for(;;) { if(ls->cur.eof) { syntaxError(ls, "unterminated comment reached end of file"); break; } else if(nc == '*') { lex_nextchar(ls); if(nc == '/') { lex_nextchar(ls); return lex_scan(ls); } } else if(isNewLine(nc)) { lex_scanNewLine(ls); } else lex_nextchar(ls); } } } lex_save(ls); /* numerical constants */ if(isDigit(nc)) { parse_number: while(isDigit(nc)) lex_nextchar(ls); if(nc == '.') { lex_nextchar(ls); while(isDigit(nc)) lex_nextchar(ls); if(nc == '.') syntaxError(ls, "invalid numerical constant"); } return lex_newToken(ls, T_NUMBER, tk_numeric); } /* identifiers */ else if(isAlpha(nc)) { parse_ident: while(isAlNum(nc) || nc == '_') lex_nextchar(ls); /* check if it matches a keyword token */ z_token tk = lex_newToken(ls, T_IDENT, tk_identifier); lex_matchKeyword(ls, &tk); return tk; } /* string literals */ else if(nc == '"' || nc == '\''){ //parse_string: char q = nc; lex_nextchar(ls); while(nc != q) { if(ls->cur.eof) { syntaxError(ls, "unterminated string literal reached end of file"); break; } /* skip escaped chars */ if(nc == '\\') { lex_nextchar(ls); continue; } if(isNewLine(nc)) { lex_scanNewLine(ls); } lex_nextchar(ls); } lex_nextchar(ls); // skip the closing cc return lex_newToken(ls, T_STRING, tk_string); } /* other multi char tokens */ switch(nc) { case '.': // may be numeric? lex_nextchar(ls); if(isDigit(nc)) goto parse_number; return lex_newToken(ls, '.', 0); case '_': // may be ident? lex_nextchar(ls); if(isAlNum(nc)) goto parse_ident; return lex_newToken(ls, '_', 0); case '+': lex_nextchar(ls); if(nc == '+') { lex_nextchar(ls); return lex_newToken(ls, T_INC, tk_op); } else if(nc == '=') { lex_nextchar(ls); return lex_newToken(ls, T_AA, tk_op); } return lex_newToken(ls, '+', tk_op); case '-': lex_nextchar(ls); if(nc == '-') { lex_nextchar(ls); return lex_newToken(ls, T_DEC, tk_op); } else if(nc == '=') { lex_nextchar(ls); return lex_newToken(ls, T_SA, tk_op); } return lex_newToken(ls, '-', tk_op); case '*': lex_nextchar(ls); if(nc == '=') { lex_nextchar(ls); return lex_newToken(ls, T_MA, tk_op); } return lex_newToken(ls, '*', tk_op); case '/': lex_nextchar(ls); if(nc == '=') { lex_nextchar(ls); return lex_newToken(ls, T_DA, tk_op); } return lex_newToken(ls, '/', tk_op); case '>': lex_nextchar(ls); if(nc == '=') { lex_nextchar(ls); return lex_newToken(ls, T_GTE, tk_op); } return lex_newToken(ls, '>', tk_op); case '<': lex_nextchar(ls); if(nc == '=') { lex_nextchar(ls); return lex_newToken(ls, T_LTE, tk_op); } else if(nc == '>') { lex_nextchar(ls); return lex_newToken(ls, T_NE, tk_op); } return lex_newToken(ls, '<', tk_op); case '=': lex_nextchar(ls); if(nc == '=') { lex_nextchar(ls); return lex_newToken(ls, T_EQ, tk_op); } return lex_newToken(ls, '=', tk_op); case '&': lex_nextchar(ls); if(nc == '&') { lex_nextchar(ls); return lex_newToken(ls, T_AND, tk_op); } return lex_newToken(ls, '&', tk_op); case '|': lex_nextchar(ls); if(nc == '|') { lex_nextchar(ls); return lex_newToken(ls, T_OR, tk_op); } return lex_newToken(ls, '|', tk_op); case '^': lex_nextchar(ls); if(nc == '^') { lex_nextchar(ls); return lex_newToken(ls, T_XOR, tk_op); } return lex_newToken(ls, '^', tk_op); case '!': lex_nextchar(ls); return lex_newToken(ls, T_NOT, tk_op); case ':': lex_nextchar(ls); if(nc == '=') { lex_nextchar(ls); return lex_newToken(ls, T_DE, tk_op); } return lex_newToken(ls, ':', 0); } char c = nc; lex_nextchar(ls); return lex_newToken(ls, c, 0); }