/** * Get result and related info * @param bott Original Bott info * @return Result Bott file */ Bott * NJUPTJudger::getStatus(Bott * bott) { time_t begin_time = time(NULL); Bott * result_bott; while (true) { // check wait time if (time(NULL) - begin_time > info->GetMax_wait_time()) { throw Exception("Failed to get current result, judge time out."); } prepareCurl(); curl_easy_setopt( curl, CURLOPT_URL, ((string) "http://acm.njupt.edu.cn/acmhome/showstatus.do").c_str()); string post = (string) "problemId=" + bott->Getvid() + "&languageS=" + convertLanguage(bott->Getlanguage()) + "&userName="******"&resultS=All"; curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post.c_str()); performCurl(); string html = charsetConvert("GBK", "UTF-8", loadAllFromFile(tmpfilename)); string status; string runid, result, time_used, memory_used; // get first row if (!RE2::PartialMatch(html, "(?s)<table.*?</thead>.*?(<tr.*?</tr>)", &status)) { throw Exception("Failed to get status row."); } // get result if (!RE2::PartialMatch( status, "(?s)method=showdetail.*?value=\"(.*?)\".*?<b acc=\"acc\"></b>\\s*(.*?)" "\\s*<b acc=\"acc\"></b>", &runid, &result)) { throw Exception("Failed to get current result."); } result = convertResult(trim(result)); if (isFinalResult(result)) { // result is the final one, get details if (result == "Accepted") { // only accepted run has details if (!RE2::PartialMatch( status, "(?s)([0-9]*)<b ms=\"ms\"></b>MS.*?([0-9]*)<b k=\"k\"></b>K", &time_used, &memory_used)) { throw Exception("Failed to parse details from status row."); } } else { memory_used = time_used = "0"; } result_bott = new Bott; result_bott->Settype(RESULT_REPORT); result_bott->Setresult(convertResult(result)); result_bott->Settime_used(stringToInt(time_used)); result_bott->Setmemory_used(stringToInt(memory_used)); result_bott->Setremote_runid(trim(runid)); break; } } return result_bott; }
/** * Get result and related info * @param bott Original Bott info * @return Result Bott file */ Bott * CFJudger::getStatus(Bott * bott) { time_t begin_time = time(NULL); Bott * result_bott; while (true) { // check wait time if (time(NULL) - begin_time > info->GetMax_wait_time()) { throw Exception("Failed to get current result, judge time out."); } prepareCurl(); curl_easy_setopt(curl, CURLOPT_URL, ((string) "http://codeforces.com/submissions/" + info->GetUsername()).c_str()); performCurl(); string html = loadAllFromFile(tmpfilename); string status; string runid, result, time_used, memory_used; // get first result row if (!RE2::PartialMatch(html, "(?s)<tr.*first-row.*?(<tr.*?</tr>)", &status)) { throw Exception("Failed to get status row."); } // get result if (!RE2::PartialMatch(status, "(?s)status-cell.*?>(.*?)</td>", &result)) { throw Exception("Failed to get current result."); } if (isFinalResult(result)) { // if result if final, get details if (!RE2::PartialMatch( status, "(?s)data-submission-id=\"([0-9]*)\".*submissionVerdict" "=\"(.*?)\".*time-consumed-cell.*?>(.*?) ms.*memory-consumed" "-cell.*?>(.*?) KB", &runid, &result, &time_used, &memory_used)) { // try api when failed log("Failed to parse details from status row, try API."); prepareCurl(); curl_easy_setopt( curl, CURLOPT_URL, ((string) "http://codeforces.com/api/user.status?handle=" + info->GetUsername() + "&from=1&count=1").c_str()); performCurl(); string json = loadAllFromFile(tmpfilename); if (!RE2::PartialMatch( json, "(?s)\"id\":([0-9]*)\"verdict\":\"(.*?)\".*\"timeConsumed" "Millis\":([0-9]*),\"memeryConsumedBytes\":([0-9]*)", &runid, &result, &time_used, &memory_used)) { throw Exception("Failed to parse details from API."); } } result_bott = new Bott; result_bott->Settype(RESULT_REPORT); result_bott->Setresult(convertResult(result)); result_bott->Settime_used(stringToInt(time_used)); result_bott->Setmemory_used(stringToInt(memory_used)); result_bott->Setremote_runid(trim(runid)); break; } } // for CodeForces, we can store extra infos in ce_info column string contest; // no need to check fail or not, since submit function has already done it RE2::PartialMatch(bott->Getvid(), "(^[0-9]{1,6})", &contest); if (result_bott->Getresult() != "Accepted" && result_bott->Getresult() != "Compile Error") { result_bott->Setce_info( getVerdict(contest, result_bott->Getremote_runid())); } return result_bott; }
PrologToken getToken(const std::string& str, unsigned int& idx, const std::string& fileName, int& line, int& col) { top: const char normalOperatorChars[] = "+-*/\\^<>=`~:.?@#&"; if (idx == str.size()) { // End of string return endOfFile(fileName, line, col); } int oldLine = line, oldCol = col; #define STAR_P (str[idx]) #define P_SUB_1 (idx + 1 == str.size() ? 0 : str[idx + 1]) #define INC_INDEX do { \ if (STAR_P == '\n') { \ ++line; \ col = 1; \ } else { \ ++col; \ } \ ++idx; \ } while (false) if (islower(STAR_P)) { // Normal atoms unsigned int oldIdx = idx; do {INC_INDEX;} while (isalnum(STAR_P) || STAR_P == '_'); bool startOfTerm = false; if (STAR_P == '(') {startOfTerm = true; INC_INDEX;} return atom(str.substr(oldIdx, idx - oldIdx - startOfTerm), startOfTerm, fileName, oldLine, oldCol); } else if (STAR_P == '_' && !isalnum(P_SUB_1)) { // Wildcard INC_INDEX; return wildcard(fileName, oldLine, oldCol); } else if (isupper(STAR_P) || STAR_P == '_' || STAR_P == '$') { // Variables unsigned int oldIdx = idx; do {INC_INDEX;} while (isalnum(STAR_P) || STAR_P == '_' || STAR_P == '$'); return variable(str.substr(oldIdx, idx - oldIdx), fileName, oldLine, oldCol); } else if (isdigit(STAR_P) || STAR_P == '-' && isdigit(P_SUB_1)) { // Numbers int isNegative = 1; if (STAR_P == '-') {isNegative = -1; INC_INDEX;} unsigned int oldIdx = idx; do {INC_INDEX;} while (isdigit(STAR_P)); std::string tokenString; if (STAR_P == '.' && isdigit(P_SUB_1)) { // Floating point INC_INDEX; while (isdigit(STAR_P)) INC_INDEX; if (STAR_P == 'e' || STAR_P == 'E') { INC_INDEX; if (STAR_P == '-') INC_INDEX; while (isdigit(STAR_P)) INC_INDEX; } return floatingPoint(isNegative * stringToDouble(str.substr(oldIdx, idx - oldIdx), fileName, oldLine, oldCol), fileName, oldLine, oldCol); } else if (STAR_P == '\'') { // Base or character definition int base = stringToInt(str.substr(oldIdx, idx - oldIdx), 10); if (base == 0 && P_SUB_1) { // Character INC_INDEX; return integer(isNegative * (STAR_P), fileName, oldLine, oldCol); } else if (base >= 2 && base <= 36) { INC_INDEX; oldIdx = idx; while (isalnum(STAR_P)) INC_INDEX; return integer(isNegative * stringToInt(str.substr(oldIdx, idx - oldIdx), base), fileName, oldLine, oldCol); } else { std::cerr << "Invalid number base " << base << std::endl; abort(); } } else { // Normal integer return integer(isNegative * stringToInt(str.substr(oldIdx, idx - oldIdx), 10), fileName, oldLine, oldCol); } } else if (STAR_P == '.' && P_SUB_1 && !strchr(normalOperatorChars, P_SUB_1)) { INC_INDEX; return period(fileName, oldLine, oldCol); } else if (strchr(normalOperatorChars, STAR_P)) { // Operators unsigned int oldIdx = idx; do {INC_INDEX;} while (strchr(normalOperatorChars, STAR_P)); bool startOfTerm = false; if (STAR_P == '(') {startOfTerm = true; INC_INDEX;} return atom(str.substr(oldIdx, idx - oldIdx - startOfTerm), startOfTerm, fileName, oldLine, oldCol); } else if (STAR_P == '!' || STAR_P == ';') { // Single-character operators char c = STAR_P; INC_INDEX; bool startOfTerm = false; if (STAR_P == '(') {startOfTerm = true; INC_INDEX;} return atom(std::string(1, c), startOfTerm, fileName, oldLine, oldCol); } else if (STAR_P == '\'') { // Quoted atoms std::string result; INC_INDEX; unsigned int oldIdx = idx; get_more_chars_atom: while (STAR_P != '\'') INC_INDEX; result += str.substr(oldIdx, idx - oldIdx); if (P_SUB_1 == '\'') { // Escaped single quote result += "'"; INC_INDEX; INC_INDEX; goto get_more_chars_atom; } else { // End of atom INC_INDEX; bool startOfTerm = false; if (STAR_P == '(') {startOfTerm = true; INC_INDEX;} return atom(result, startOfTerm, fileName, oldLine, oldCol); } } else if (STAR_P == '"') { // Strings std::string result; INC_INDEX; unsigned int oldIdx = idx; get_more_chars_string: while (STAR_P && STAR_P != '"' && STAR_P != '\\') INC_INDEX; result += str.substr(oldIdx, idx - oldIdx); if (STAR_P == '"') { if (P_SUB_1 == '"') { // Escaped double quote result += "\""; INC_INDEX; INC_INDEX; oldIdx = idx; goto get_more_chars_string; } else { // End of string INC_INDEX; return stringToken(result, fileName, oldLine, oldCol); } } else if (STAR_P == '\\') { std::cerr << "Cannot handle backslash escapes in strings yet" << std::endl; abort(); } else if (!STAR_P) { std::cerr << "Unterminated string constant" << std::endl; abort(); } } else if (STAR_P == '(') { INC_INDEX; return leftParen(fileName, oldLine, oldCol); } else if (STAR_P == ')') { INC_INDEX; return rightParen(fileName, oldLine, oldCol); } else if (STAR_P == '[') { if (P_SUB_1 == ']') { INC_INDEX; INC_INDEX; bool startOfTerm = false; if (STAR_P == '(') {startOfTerm = true; INC_INDEX;} return atom("[]", startOfTerm, fileName, oldLine, oldCol); } else { INC_INDEX; return leftBracket(fileName, oldLine, oldCol); } } else if (STAR_P == ']') { INC_INDEX; return rightBracket(fileName, oldLine, oldCol); } else if (STAR_P == '|') { INC_INDEX; return verticalBar(fileName, oldLine, oldCol); } else if (STAR_P == ',') { INC_INDEX; return comma(fileName, oldLine, oldCol); } else if (isspace(STAR_P)) { // White space INC_INDEX; goto top; } else if (STAR_P == '%') { // Comment do {INC_INDEX;} while (STAR_P && STAR_P != '\n' && STAR_P != '\r'); if (!STAR_P) { std::cerr << "Unterminated comment" << std::endl; abort(); } goto top; } else { std::cerr << "Bad character '" << STAR_P << "'" << std::endl; abort(); } #undef STAR_P #undef P_SUB_1 #undef INC_INDEX std::cerr << "Should not get here" << std::endl; abort(); return endOfFile(fileName, line, col); // Should not get here }
enum sexType stringToSex(std::string str) { return intToSex(stringToInt(str)); }
bool saveMeasurementToCollectionFileAtRow(std::string& p_filePath, float p_average, float p_std, int p_rowIdx) { std::string exePathPrefix = GetExecutablePathDirectory(); std::string path = exePathPrefix + p_filePath; std::vector<std::string> rows; // existing file std::ifstream is; is.open(path.c_str(), std::ios::in); if (!is.good() || !is.is_open()) return false; //is>>length; // read size std::string tmpStr; // read all while (!is.eof()) { std::getline(is, tmpStr); if (tmpStr!="") rows.push_back(tmpStr); } is.close(); // Find the row with the right index (the first character denotes the index) int vectorIdx = -1; int lastIdx = 0; for (int i = 0; i < rows.size(); i++) { std::string firstChars = rows[i].substr(0, rows[i].find(" ")); if (firstChars != "#" && firstChars != "") { int idx = stringToInt(firstChars); lastIdx = idx; if (p_rowIdx == idx) { vectorIdx = i; break; } } } if (vectorIdx == -1) // not found { vectorIdx=rows.size()-1; while (lastIdx<p_rowIdx) { lastIdx++; vectorIdx++; rows.push_back(ToString(lastIdx) + " 0 0 0 0"); } } float ylow = p_average - p_std, yhigh = p_average + p_std; std::string newRow = ToString(p_rowIdx) + " " + ToString(p_average) + " " + ToString(p_std) + " " + ToString(ylow) + " " + ToString(yhigh); // replace rows[vectorIdx] = newRow; // now write std::ofstream os; os.open(path, std::ios::out); if (!os.good() || !os.is_open()) return false; for (int i = 0; i < rows.size(); i++) { os << rows[i]<<"\n"; } //os<<length; // write size //size_t length = p_inData->size(); //os.write(reinterpret_cast<char*>(&(*p_inData)[0]), // std::streamsize(length*sizeof(float))); // write data os.close(); }
ML_START_NAMESPACE //*********************************************************************************** void SaveU3D::PreProcessPointSetData(U3DPointSetInfoVector &U3DPointSetInfoVector, ModelBoundingBoxStruct& boundingBox) { StringVector pointSetSpecificationsVector; if (_simpleModePointSetFld->getBoolValue()) { pointSetSpecificationsVector.push_back("<U3DPointSet><PositionTypes>all</PositionTypes>"); } else { pointSetSpecificationsVector = getObjectSpecificationsStringFromUI(_pointCloudSpecificationFld, "<PointSet>"); } const MLuint32 numberOfPointSetSpecifications = (MLuint32)pointSetSpecificationsVector.size(); if (0 == numberOfPointSetSpecifications) { return; } _statusFld->setStringValue("Analyzing point cloud specification."); for (MLuint32 i = 0; i < numberOfPointSetSpecifications; i++) { SpecificationParametersStruct thisSpecificationParameters = getAllSpecificationParametersFromString(pointSetSpecificationsVector[i]); // Override default object name if (thisSpecificationParameters.ObjectName == "Object") { thisSpecificationParameters.ObjectName = "Point Set " + intToString(i+1); } U3DObjectInfoStruct thisU3DObjectInfo = CreateNewU3DObjectInfo(i, U3DOBJECTTYPE_POINTSET, thisSpecificationParameters.ObjectName, defaultValues); thisU3DObjectInfo.GroupPath = thisSpecificationParameters.GroupPath; thisU3DObjectInfo.DiffuseColor = getColorVec4(thisSpecificationParameters.Color, defaultValues.defaultMaterialDiffuseColorWithTransparency); thisU3DObjectInfo.SpecularColor = getColorVec3(thisSpecificationParameters.SpecularColor, defaultValues.defaultMaterialSpecularColor); thisU3DObjectInfo.Visibility = (MLuint32)stringToInt(thisSpecificationParameters.ModelVisibility); _u3dObjectInfoVector.push_back(thisU3DObjectInfo); PointSetSpecificationStruct thisPointSetGeometry; thisPointSetGeometry.internalName = thisU3DObjectInfo.InternalName; thisPointSetGeometry.positions = getAllPositionsFromXMarkerList(_inPointPositions, thisSpecificationParameters.PositionTypes, thisSpecificationParameters.PointSize); _pointSetsGeometryVector.push_back(thisPointSetGeometry); // Collect point set info U3DPointSetInfoStruct thisPointSetInfo; thisPointSetInfo.DiffuseColorCount = 0; // This is not really needed in this version thisPointSetInfo.SpecularColorCount = 0; // This is not really needed in this version thisPointSetInfo.TextureCoordCount = 0; // This is not really needed in this version thisPointSetInfo.DefaultAmbientColor = defaultValues.defaultMaterialAmbientColor; thisPointSetInfo.DefaultSpecularColor = defaultValues.defaultMaterialSpecularColor; thisPointSetInfo.DefaultDiffuseColor = defaultValues.defaultMaterialDiffuseColorWithTransparency; thisPointSetInfo.DefaultEmissiveColor = defaultValues.defaultMaterialEmissiveColor; thisPointSetInfo.PointCount = (MLuint32)thisPointSetGeometry.positions.size(); thisPointSetInfo.NormalCount = 0; // thisPointSetInfo.PointCount; // No normals in this version since normals are not used by Acrobat thisPointSetInfo.ShadingAttributes = U3D_SHADINGATTRIBUTES_NONE; thisPointSetInfo.ShadingAttributes |= ( (thisPointSetInfo.DiffuseColorCount > 0) ? U3D_SHADINGATTRIBUTES_DIFFUSECOLORS : 0 ); // Should not happen in this version thisPointSetInfo.ShadingAttributes |= ( (thisPointSetInfo.SpecularColorCount > 0) ? U3D_SHADINGATTRIBUTES_SPECULARCOLORS : 0 ); // Should not happen in this version thisPointSetInfo.DisplayName = thisU3DObjectInfo.DisplayName; thisPointSetInfo.ResourceName = thisU3DObjectInfo.ResourceName; U3DPointSetInfoVector.push_back(thisPointSetInfo); ModelBoundingBoxStruct newboundingBox = GetBoundingBoxFomPositions(thisPointSetGeometry.positions); UpdateBoundingBox(boundingBox, newboundingBox); } }
void ICubeXDevice::init() { for (int i=0;i<32;i++) _channelData[i] = 0.0; Array<std::string> channelList = splitStringIntoArray(_activeChannelsStr); for (int i=0;i<channelList.size();i++) { int channel = stringToInt(channelList[i]); debugAssert(channel <= 32); debugAssert(channel >= 1); _activeChannels.append(channel-1); } if (_debug) { printMidiDevices(); cout << "ICubeX:: Active Channels = [ "; for (int i=0;i<_activeChannels.size();i++) cout << intToString(_activeChannels[i]+1) << " "; cout << "]" << endl; } // Open Midi Out device _out = MidiOutDevice::fromMidiDeviceNumber(_outDevNum); // Send config messages to Midi-Out // Reset the device each time to avoid bad initial data unsigned char resetMsg[] = {0xF0, 0x7D, 0x00, 0x22, 0xF7}; _out->sendMessage(resetMsg, sizeof(resetMsg)); if (_mode == STAND_ALONE_MODE) { // Set device to stand-alone mode unsigned char setStandAloneModeMsg[] = {0xF0, 0x7D, 0x00, 0x5A, 0x01, 0xF7}; _out->sendMessage(setStandAloneModeMsg, sizeof(setStandAloneModeMsg)); } else { // Set device to host mode unsigned char setHostModeMsg[] = {0xF0, 0x7D, 0x00, 0x5A, 0x00, 0xF7}; _out->sendMessage(setHostModeMsg, sizeof(setHostModeMsg)); // Set the resolution for each channel to 12-bit rather than the 7-bit default unsigned char hiResMsg[] = {0xF0, 0x7D, 0x00, 0x02, 0x40, 0xF7}; for (int i=0;i<32;i++) { hiResMsg[4] = 0x40 + i; _out->sendMessage(hiResMsg, sizeof(hiResMsg)); } } // Set the sampling interval, hardware default is 100ms unsigned char msb = _samplingInterval / 128; unsigned char lsb = _samplingInterval % 128; unsigned char setIntervalMsg[] = {0xF0, 0x7D, 0x00, 0x03, 0x00, 0x64, 0xF7}; setIntervalMsg[4] = msb; setIntervalMsg[5] = lsb; _out->sendMessage(setIntervalMsg, sizeof(setIntervalMsg)); // Send the STREAM command to each active channel, turn off streaming for non-active channels unsigned char enableChannelMsg[] = {0xF0, 0x7D, 0x00, 0x01, 0x40, 0xF7}; for (int i=0;i<32;i++) { if (_activeChannels.contains(i)) { enableChannelMsg[4] = 0x40 + i; } else { enableChannelMsg[4] = 0x00 + i; } _out->sendMessage(enableChannelMsg, sizeof(enableChannelMsg)); } // Open MidiIn for listening _in = MidiInDevice::fromMidiDeviceNumber(_inDevNum); }
void ShaderBuild::parseLog(std::string* errStr, std::string log, int baseFile, bool readLineNumbers) { std::string line, first, second; std::stringstream reader(log); int prevFile = -1; int prevLine = -1; while (getline(reader, line)) { //attempt to read two ints - file ane line numbers int end = extractInt(line, first); if (readLineNumbers && end > 0) end = extractInt(line.substr(end), second); //if found, replace the error line with the file info if (end > 0) { //read/convert line numbers int filenum = stringToInt(first); //I could swear nvidia's compiler is reporting bad line numbers when #line is used int linenum = stringToInt(second); //stupid ATI drivers don't like #line before #version, so the root file never has a #line //this workaround replaces file 0 with the REAL file. thanks, AMD. real helpful if (filenum == 0) filenum = baseFile; //extract error message end = (int)line.find(":", end); std::string errormsg; if (end >= 0) errormsg = line.substr(end + 1); else errormsg = line; //add file/line number info if available line = ""; if (filenum >= 0 && filenum < (int)allfilebits.size()) line += allfilebits[filenum].filename + ":"; else line += "<unknown file " + intToString(filenum) + ">"; if (readLineNumbers && linenum >= 0) line += intToString(linenum) + ":"; //if both are available and valid, attempt to include the source line from the file int tabw = (int)line.size(); std::string faultline; if (filenum >= 0 && linenum >= 0 && filenum < (int)allfilebits.size()) { std::string sourceLine; if (!getFileLine(allfilebits[filenum].filename, linenum, sourceLine)) sourceLine = "<I'm stupid and can't read the source>"; if (sourceLine.size() == 0) sourceLine = "<empty line>"; faultline = " " + sourceLine; } else faultline = " <line not given>"; line += faultline; //add the actual error message to the end if (prevLine == linenum && prevFile == filenum) line = std::string(tabw, ' ') + errormsg; else line += "\n" + std::string(tabw, ' ') + errormsg; prevLine = linenum; //if this is the first time the file was mentioned, give the include path //FIXME: this is incorrect. each occurance of an include should be marked // as a separate file so as to distinguish the include path!!! if (prevFile != filenum) { if (filenum >= 0 && filenum < (int)allfilebits.size()) line = printPath(allfilebits[filenum].path) + line; else line = "<error in file number>\n" + line; prevFile = filenum; } } //print the line if (errStr) *errStr += line + "\n"; else std::cout << line << std::endl; } }
static void jslLexString() { char delim = lex->currCh; lex->tokenValue = jsvNewFromEmptyString(); if (!lex->tokenValue) { lex->tk = LEX_EOF; return; } JsvStringIterator it; jsvStringIteratorNew(&it, lex->tokenValue, 0); // strings... jslGetNextCh(); while (lex->currCh && lex->currCh!=delim) { if (lex->currCh == '\\') { jslGetNextCh(); char ch = lex->currCh; switch (lex->currCh) { case 'n' : ch = 0x0A; jslGetNextCh(); break; case 'b' : ch = 0x08; jslGetNextCh(); break; case 'f' : ch = 0x0C; jslGetNextCh(); break; case 'r' : ch = 0x0D; jslGetNextCh(); break; case 't' : ch = 0x09; jslGetNextCh(); break; case 'v' : ch = 0x0B; jslGetNextCh(); break; case 'u' : case 'x' : { // hex digits char buf[5] = "0x??"; if (lex->currCh == 'u') { // We don't support unicode, so we just take the bottom 8 bits // of the unicode character jslGetNextCh(); jslGetNextCh(); } jslGetNextCh(); buf[2] = lex->currCh; jslGetNextCh(); buf[3] = lex->currCh; jslGetNextCh(); ch = (char)stringToInt(buf); } break; default: if (lex->currCh>='0' && lex->currCh<='7') { // octal digits char buf[5] = "0"; buf[1] = lex->currCh; int n=2; jslGetNextCh(); if (lex->currCh>='0' && lex->currCh<='7') { buf[n++] = lex->currCh; jslGetNextCh(); if (lex->currCh>='0' && lex->currCh<='7') { buf[n++] = lex->currCh; jslGetNextCh(); } } buf[n]=0; ch = (char)stringToInt(buf); } else { // for anything else, just push the character through jslGetNextCh(); } break; } jslTokenAppendChar(ch); jsvStringIteratorAppend(&it, ch); } else if (lex->currCh=='\n' && delim!='`') { /* Was a newline - this is now allowed * unless we're a template string */ break; } else { jslTokenAppendChar(lex->currCh); jsvStringIteratorAppend(&it, lex->currCh); jslGetNextCh(); } } jsvStringIteratorFree(&it); if (delim=='`') lex->tk = LEX_TEMPLATE_LITERAL; else lex->tk = LEX_STR; // unfinished strings if (lex->currCh!=delim) lex->tk++; // +1 gets you to 'unfinished X' jslGetNextCh(); }
JsVar *jswrap_json_parse_internal(JsLex *lex) { switch (lex->tk) { case LEX_R_TRUE: jslGetNextToken(lex); return jsvNewFromBool(true); case LEX_R_FALSE: jslGetNextToken(lex); return jsvNewFromBool(false); case LEX_R_NULL: jslGetNextToken(lex); return jsvNewWithFlags(JSV_NULL); case LEX_INT: { long long v = stringToInt(jslGetTokenValueAsString(lex)); jslGetNextToken(lex); return jsvNewFromLongInteger(v); } case LEX_FLOAT: { JsVarFloat v = stringToFloat(jslGetTokenValueAsString(lex)); jslGetNextToken(lex); return jsvNewFromFloat(v); } case LEX_STR: { JsVar *a = jslGetTokenValueAsVar(lex); jslGetNextToken(lex); return a; } case '[': { JsVar *arr = jsvNewWithFlags(JSV_ARRAY); if (!arr) return 0; jslGetNextToken(lex); // [ while (lex->tk != ']') { JsVar *value = jswrap_json_parse_internal(lex); if (!value || (lex->tk!=']' && !jslMatch(lex, ','))) { jsvUnLock(value); jsvUnLock(arr); return 0; } jsvArrayPush(arr, value); jsvUnLock(value); } if (!jslMatch(lex, ']')) { jsvUnLock(arr); return 0; } return arr; } case '{': { JsVar *obj = jsvNewWithFlags(JSV_OBJECT); if (!obj) return 0; jslGetNextToken(lex); // { while (lex->tk == LEX_STR) { JsVar *key = jsvAsArrayIndexAndUnLock(jslGetTokenValueAsVar(lex)); jslGetNextToken(lex); JsVar *value = 0; if (!jslMatch(lex, ':') || !(value=jswrap_json_parse_internal(lex)) || (lex->tk!='}' && !jslMatch(lex, ','))) { jsvUnLock(key); jsvUnLock(value); jsvUnLock(obj); return 0; } jsvAddName(obj, jsvMakeIntoVariableName(key, value)); jsvUnLock(value); jsvUnLock(key); } if (!jslMatch(lex, '}')) { jsvUnLock(obj); return 0; } return obj; } default: return 0; // undefined = error } }