Esempio n. 1
0
bool CFI::Component::operator==(const ePub3::CFI::Component &o) const
{
    // holy compound statements Batman!
    if ( (flags != o.flags) ||
         (nodeIndex != o.nodeIndex) ||
         (HasQualifier() && qualifier != o.qualifier) ||
         (HasCharacterOffset() && characterOffset != o.characterOffset) ||
         (HasSpatialOffset() && (spatialOffset.x != o.spatialOffset.x || spatialOffset.y != o.spatialOffset.y)) ||
         (HasTemporalOffset() && temporalOffset != o.temporalOffset) ||
         (HasTextQualifier() && textQualifier != o.textQualifier) )
    {
        return false;
    }
    
    return true;
}
Esempio n. 2
0
void CFI::AppendComponents(std::stringstream& builder, ComponentList::const_iterator start, ComponentList::const_iterator end)
{
    auto pos = start;
    while ( pos != end )
    {
        builder << "/" << pos->nodeIndex;
        if ( pos->HasQualifier() )
        {
            builder << "[" << pos->qualifier << "]";
        }
        if ( pos->HasCharacterOffset() )
        {
            builder << ":" << pos->characterOffset;
            
            if ( pos->HasTextQualifier() )
            {
                builder << "[" << pos->textQualifier << "]";
            }
        }
        else
        {
            if ( pos->HasTemporalOffset() )
            {
                builder << "~" << pos->temporalOffset;
            }
            if ( pos->HasSpatialOffset() )
            {
                builder << "@" << pos->spatialOffset.x << ":" << pos->spatialOffset.y;
            }
        }
        if ( pos->IsIndirector() )
        {
            builder << "!";
        }
        
        ++pos;
    }
}
Esempio n. 3
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;
        }
    }
}