function parseQRCode(text, options) {
    if (text.length < 3 || text.length > 2000) throw new Error("Invalid length of EvtLink");

    let textSplited = text.split("_");
    if (textSplited.length > 2) return null;

    let rawText;

    if (textSplited[0].startsWith(qrPrefix)) {
        rawText = textSplited[0].substr(qrPrefix.length);
    }
    else {
        rawText = textSplited[0];
    }
    
    // decode segments base42
    let segmentsBytes = EvtLink.dec2b(rawText);
    if (segmentsBytes.length < 2) throw new Error("no flag in segment");
    let flag = segmentsBytes.readInt16BE(0);
    
    if ((flag & 1) == 0) { // check version of EvtLink
        throw new Error("The EvtLink is invalid or its version is newer than version 1 and is not supported by evtjs yet");
    }
    let segmentsBytesRaw = new Buffer(segmentsBytes.length - 2);
    segmentsBytes.copy(segmentsBytesRaw, 0, 2, segmentsBytes.length);

    let publicKeys = [ ];
    let signatures = [ ];

    if (textSplited[1]) {
        let buf = EvtLink.dec2b(textSplited[1]);
        let i = 0;

        if (buf.length % 65 !== 0) {
            throw new Error("length of signature is invalid");
        }

        while (i * 65 < buf.length) {
            let current = new Buffer(65);
            buf.copy(current, 0, i * 65, i * 65 + 65);
            let signature = ecc.Signature.fromBuffer(current);
            signatures.push(signature.toString());

            if (!options || options.recoverPublicKeys) {
                publicKeys.push(signature.recover(segmentsBytes).toString());
            }

            ++i;
        }
    }

    return { flag, segments: parseSegments(segmentsBytesRaw), publicKeys, signatures };
}