# All files / src/utils attr-list.js

100% Statements 38/38
90% Branches 18/20
100% Functions 8/8
100% Lines 37/37

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    9016x
    16x

    66x
    61x

    66x
    147x
    147x

    46x
    46x
    1x

    45x

    5x
    3x
    3x

    3x
    3x
    19x

    3x

    2x

    8x
    8x
    1x

    7x

    8x

    12x

    28x
    28x
    8x

    20x

    61x
    61x
    61x
    146x

    146x

    50x

    146x

    61x

     const DECIMAL_RESOLUTION_REGEX = /^(\d+)x(\d+)$/; // eslint-disable-line no-useless-escape
    const ATTR_LIST_REGEX = /\s*(.+?)\s*=((?:\".*?\")|.*?)(?:,|$)/g; // eslint-disable-line no-useless-escape

    // adapted from https://github.com/kanongil/node-m3u8parse/blob/master/attrlist.js
    class AttrList {
      constructor (attrs) {
        if (typeof attrs === 'string') {
          attrs = AttrList.parseAttrList(attrs);
        }

        for (let attr in attrs) {
          Eif (attrs.hasOwnProperty(attr)) {
            this[attr] = attrs[attr];
          }
        }
      }

      decimalInteger (attrName) {
        const intValue = parseInt(this[attrName], 10);
        if (intValue > Number.MAX_SAFE_INTEGER) {
          return Infinity;
        }

        return intValue;
      }

      hexadecimalInteger (attrName) {
        if (this[attrName]) {
          let stringValue = (this[attrName] || '0x').slice(2);
          stringValue = ((stringValue.length & 1) ? '0' : '') + stringValue;

          const value = new Uint8Array(stringValue.length / 2);
          for (let i = 0; i < stringValue.length / 2; i++) {
            value[i] = parseInt(stringValue.slice(i * 2, i * 2 + 2), 16);
          }

          return value;
        } else {
          return null;
        }
      }

      hexadecimalIntegerAsNumber (attrName) {
        const intValue = parseInt(this[attrName], 16);
        if (intValue > Number.MAX_SAFE_INTEGER) {
          return Infinity;
        }

        return intValue;
      }

      decimalFloatingPoint (attrName) {
        return parseFloat(this[attrName]);
      }

      enumeratedString (attrName) {
        return this[attrName];
      }

      decimalResolution (attrName) {
        const res = DECIMAL_RESOLUTION_REGEX.exec(this[attrName]);
        if (res === null) {
          return undefined;
        }

        return {
          width: parseInt(res[1], 10),
          height: parseInt(res[2], 10)
        };
      }

      static parseAttrList (input) {
        let match, attrs = {};
        ATTR_LIST_REGEX.lastIndex = 0;
        while ((match = ATTR_LIST_REGEX.exec(input)) !== null) {
          let value = match[2], quote = '"';

          if (value.indexOf(quote) === 0 &&
              value.lastIndexOf(quote) === (value.length - 1)) {
            value = value.slice(1, -1);
          }

          attrs[match[1]] = value;
        }
        return attrs;
      }
    }

    export default AttrList;