void CFI::Component::Parse(const string &str) { if ( str.empty() ) throw std::invalid_argument("Empty string supplied to CFI::Component"); std::string utf8 = str.stl_str(); std::istringstream iss(utf8); // read an integer iss >> nodeIndex; if ( nodeIndex == 0 && iss.fail() ) throw std::invalid_argument(_Str("No node value at start of CFI::Component string '", str, "'")); while ( !iss.eof() ) { char next = 0; iss >> next; switch ( next ) { case '[': { size_t pos = static_cast<size_t>(iss.tellg()); iss.ignore(std::numeric_limits<std::streamsize>::max(), ']'); size_t end = ((size_t)iss.tellg()) - 1; if ( iss.eof() ) throw std::invalid_argument(_Str("Invalid string supplied to CFI::Component: ", str)); if ( characterOffset != 0 ) { // this is a text qualifier textQualifier = utf8.substr(pos, end-pos); flags |= TextQualifier; } else { // it's a position qualifier qualifier = utf8.substr(pos, end-pos); flags |= Qualifier; } break; } case '~': { // character offsets and spatial/temporal offsets are mutually exclusive if ( HasCharacterOffset() ) break; // read a numeral iss >> temporalOffset; flags |= TemporalOffset; break; } case '@': { // character offsets and spatial/temporal offsets are mutually exclusive if ( HasCharacterOffset() ) break; // two floats, separated by a colon float x, y; // read x iss >> x; // check for and skip delimiter if ( iss.peek() != ':' ) break; iss.ignore(1); // read y iss >> y; spatialOffset.x = x; spatialOffset.y = y; flags |= SpatialOffset; break; } case ':': { // character offsets and spatial/temporal offsets are mutually exclusive if ( HasSpatialTemporalOffset() ) break; iss >> characterOffset; flags |= CharacterOffset; break; } case '!': { // must be the last character, and no offsets if ( ((int)iss.peek()) != -1 || HasSpatialTemporalOffset() || HasCharacterOffset() ) break; flags |= Indirector; break; } default: break; } } }
void CFI::Component::Parse(const string &str) { if ( str.empty() ) { HandleError(EPUBError::CFIParseFailed, "Empty string supplied to CFI::Component"); return; } std::string utf8 = str.stl_str(); std::istringstream iss(utf8); // read an integer iss >> nodeIndex; if ( nodeIndex == 0 && iss.fail() ) { HandleError(EPUBError::CFIParseFailed, _Str("No node value at start of CFI::Component string '", str, "'")); return; } while ( !iss.eof() ) { char next = 0; iss >> next; switch ( next ) { case '[': { size_t pos = static_cast<size_t>(iss.tellg()); iss.ignore(std::numeric_limits<std::streamsize>::max(), ']'); size_t end = ((size_t)iss.tellg()) - 1; if ( iss.eof() ) { HandleError(EPUBError::CFIParseFailed); return; } if ( characterOffset != 0 ) { // this is a text qualifier flags |= TextQualifier; std::string sub = utf8.substr(pos, end-pos); // is there a side-bias? auto biasPos = sub.find(";s="); if ( biasPos == std::string::npos ) { textQualifier = std::move(sub); } else { textQualifier = sub.substr(0, biasPos); if ( sub.size() > biasPos + 3 ) { switch ( sub[biasPos+3] ) { case 'b': sideBias = SideBias::Before; break; case 'a': sideBias = SideBias::After; break; default: sideBias = SideBias::Unspecified; break; } } } } else { // it's a position qualifier qualifier = utf8.substr(pos, end-pos); flags |= Qualifier; } break; } case '~': { // character offsets and spatial/temporal offsets are mutually exclusive if ( HasCharacterOffset() ) break; // read a numeral iss >> temporalOffset; flags |= TemporalOffset; break; } case '@': { // character offsets and spatial/temporal offsets are mutually exclusive if ( HasCharacterOffset() ) break; // two floats, separated by a colon float x, y; // read x iss >> x; // check for and skip delimiter if ( iss.peek() != ':' ) break; iss.ignore(1); // read y iss >> y; spatialOffset.x = x; spatialOffset.y = y; flags |= SpatialOffset; break; } case ':': { // character offsets and spatial/temporal offsets are mutually exclusive if ( HasSpatialTemporalOffset() ) break; iss >> characterOffset; flags |= CharacterOffset; break; } case '!': { // must be the last character, and no offsets if ( ((int)iss.peek()) != -1 || HasSpatialTemporalOffset() || HasCharacterOffset() ) break; flags |= Indirector; break; } default: break; } } }