bool ParseOBJ::maybeReadWhitespace() { bool changedLines = false; while (remainingCharacters > 0) { switch (*nextCharacter) { case '\n': case '\r': { char c = *nextCharacter; consumeCharacter(); ++m_line; changedLines = true; if ((remainingCharacters > 0) && (c != *nextCharacter) && ((*nextCharacter == '\r') || (*nextCharacter == '\n'))) { // This is part of a two-character, e.g., Mac or // Windows. Consume the next character as well. consumeCharacter(); } } break; case ' ': case '\t': // Consume whitespace consumeCharacter(); break; case '#': // Consume comment readUntilNewline(); // Don't consume the newline; we'll catch it on the next // iteration break; default: return changedLines; } } return true; }
void ParseOBJ::processCommand(const Command command) { switch (command) { case VERTEX: maybeReadWhitespace(); vertexArray.append(readVector3()); // Consume anything else on this line readUntilNewline(); break; case TEXCOORD: maybeReadWhitespace(); texCoord0Array.append(readVector2()); if (m_objOptions.texCoord1Mode == ParseOBJ::Options::UNPACK_FROM_TEXCOORD0_Z) { float w = readFloat(); Vector2 texCoord1; texCoord1.x = floor(w / (2.0f * 2048.0f)) / 2048.0f; texCoord1.y = (w - 2.0f * 2048.0f * floor(w / (2.0f * 2048.0f))) / 2048.0f; texCoord1Array.append(texCoord1); } else if (m_objOptions.texCoord1Mode == ParseOBJ::Options::TEXCOORD0_ZW) { texCoord1Array.append(readVector2()); } // Consume anything else on this line readUntilNewline(); break; case NORMAL: maybeReadWhitespace(); normalArray.append(readVector3()); // Consume anything else on this line readUntilNewline(); break; case FACE: readFace(); // Faces consume newlines by themselves break; case GROUP: { // Change group const String& groupName = readName(); shared_ptr<Group>& g = groupTable.getCreate(groupName); if (isNull(g)) { // Newly created g = Group::create(); g->name = groupName; } m_currentGroup = g; } // Consume anything else on this line readUntilNewline(); break; case USEMTL: { // Change the mesh within the group const String& materialName = readName(); m_currentMaterial = getMaterial(materialName); // Force re-obtaining or creating of the appropriate mesh m_currentMesh.reset(); } // Consume anything else on this line readUntilNewline(); break; case MTLLIB: { // Specify material library String mtlFilename = readName(); mtlArray.append(mtlFilename); mtlFilename = FilePath::concat(m_basePath, mtlFilename); TextInput ti2(mtlFilename); m_currentMaterialLibrary.parse(ti2); } // Consume anything else on this line readUntilNewline(); break; case UNKNOWN: // Nothing to do readUntilNewline(); break; } }
bool PowerTapDevice::download( const QDir &tmpdir, QList<DeviceDownloadFile> &files, QString &err) { if (!dev->open(err)) { err = tr("ERROR: open failed: ") + err; return false; } // make several attempts at reading the version int attempts = 3; int veridx = -1; int version_len; char vbuf[256]; QByteArray version; do { if (!doWrite(dev, 0x56, false, err)) // 'V' return false; emit updateStatus( tr("Reading version...") ); if(m_Cancelled) { err = tr("download cancelled"); return false; } version_len = readUntilNewline(dev, vbuf, sizeof(vbuf), err); if (version_len < 0) { err = tr("Error reading version: ") + err; return false; } if (PT_DEBUG) { printf("read version \"%s\"\n", cEscape(vbuf, version_len).toLatin1().constData()); } version = QByteArray(vbuf, version_len); // We expect the version string to be something like // "VER 02.21 PRO...", so if we see two V's, it's probably // because there's a hardware echo going on. veridx = version.indexOf("VER"); } while ((--attempts > 0) && (veridx < 0)); if (veridx < 0) { err = QString(tr("Unrecognized version \"%1\"")) .arg(cEscape(vbuf, version_len)); return false; } bool hwecho = version.indexOf('V') < veridx; if (PT_DEBUG) printf("hwecho=%s\n", hwecho ? "true" : "false"); emit updateStatus( tr("Reading header...") ); if(m_Cancelled) { err = tr("download cancelled"); return false; } if (!doWrite(dev, 0x44, hwecho, err)) // 'D' return false; unsigned char header[6]; int header_len = dev->read(header, sizeof(header), err); if (header_len != 6) { if (header_len < 0) err = tr("ERROR: reading header: ") + err; else err = tr("ERROR: timeout reading header"); return false; } if (PT_DEBUG) { printf("read header \"%s\"\n", cEscape((char*) header, sizeof(header)).toLatin1().constData()); } QVector<unsigned char> records; for (size_t i = 0; i < sizeof(header); ++i) records.append(header[i]); emit updateStatus( tr("Reading data...") ); if(m_Cancelled) { err = tr("download cancelled"); return false; } double recIntSecs = 0.0; fflush(stdout); while (true) { if (PT_DEBUG) printf("reading block\n"); unsigned char buf[256 * 6 + 1]; int n = dev->read(buf, 2, err); if (n < 2) { if (n < 0) err = tr("ERROR: reading first two: ") + err; else err = tr("ERROR: timeout reading first two"); return false; } if (PT_DEBUG) { printf("read 2 bytes: \"%s\"\n", cEscape((char*) buf, 2).toLatin1().constData()); } if (hasNewline((char*) buf, 2)) break; unsigned count = 2; while (count < sizeof(buf)) { n = dev->read(buf + count, sizeof(buf) - count, err); if (n < 0) { err = tr("ERROR: reading block: ") + err; return false; } if (n == 0) { err = tr("ERROR: timeout reading block"); return false; } if (PT_DEBUG) { printf("read %d bytes: \"%s\"\n", n, cEscape((char*) buf + count, n).toLatin1().constData()); } count += n; } unsigned csum = 0; for (int i = 0; i < ((int) sizeof(buf)) - 1; ++i) csum += buf[i]; if ((csum % 256) != buf[sizeof(buf) - 1]) { err = tr("ERROR: bad checksum"); return false; } if (PT_DEBUG) printf("good checksum\n"); for (size_t i = 0; i < sizeof(buf) - 1; ++i) records.append(buf[i]); if (recIntSecs == 0.0) { unsigned char *data = records.data(); bool bIsVer81 = PowerTapUtil::is_Ver81(data); for (int i = 0; i < records.size(); i += 6) { if (PowerTapUtil::is_config(data + i, bIsVer81)) { unsigned unused1, unused2, unused3; PowerTapUtil::unpack_config( data + i, &unused1, &unused2, &recIntSecs, &unused3, bIsVer81); } } } if (recIntSecs != 0.0) { int min = (int) round(records.size() / 6 * recIntSecs); emit updateProgress( QString(tr("progress: %1:%2")) .arg(min / 60) .arg(min % 60, 2, 10, QLatin1Char('0'))); } if(m_Cancelled){ err = tr("download cancelled"); return false; } if (!doWrite(dev, 0x71, hwecho, err)) // 'q' return false; } QString tmpl = tmpdir.absoluteFilePath(".ptdl.XXXXXX"); QTemporaryFile tmp(tmpl); tmp.setAutoRemove(false); if (!tmp.open()) { err = tr("Failed to create temporary file ") + tmpl + ": " + tmp.error(); return false; } // QTemporaryFile initially has permissions set to 0600. // Make it readable by everyone. tmp.setPermissions(tmp.permissions() | QFile::ReadOwner | QFile::ReadUser | QFile::ReadGroup | QFile::ReadOther); DeviceDownloadFile file; file.extension = "raw"; file.name = tmp.fileName(); QTextStream os(&tmp); os << hex; os.setPadChar('0'); bool time_set = false; unsigned char *data = records.data(); bool bIsVer81 = PowerTapUtil::is_Ver81(data); for (int i = 0; i < records.size(); i += 6) { if (data[i] == 0 && !bIsVer81) continue; for (int j = 0; j < 6; ++j) { os.setFieldWidth(2); os << data[i+j]; os.setFieldWidth(1); os << ((j == 5) ? "\n" : " "); } if (!time_set && PowerTapUtil::is_time(data + i, bIsVer81)) { struct tm time; time_t timet = PowerTapUtil::unpack_time(data + i, &time, bIsVer81); file.startTime.setTime_t( timet ); time_set = true; } } if (!time_set) { err = tr("Failed to find start time."); tmp.setAutoRemove(true); return false; } // hack for CERVO bug dates >= 2016 set the year to 2000 (!) if (file.startTime.date().year() == 2000) { // it's in the past... so set year to this QDate date(QDate::currentDate().year(), file.startTime.date().month(), file.startTime.date().day()); // is that a future date? if (date > QDate::currentDate()) date = date.addYears(-1); // now update for file, if it's valid otherwise keep as it is if(date.isValid()) file.startTime.setDate(date); } files << file; return true; }