Пример #1
0
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;
        }
    }
}