# 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
    861x
    1x

    65x
    60x

    65x
    143x
    143x

    44x
    44x
    1x

    43x

    5x
    3x
    3x

    3x
    3x
    19x

    3x

    2x

    8x
    8x
    1x

    7x

    8x

    12x

    27x
    27x
    8x

    19x

    60x
    60x
    60x
    142x

    142x

    49x

    142x

    60x

     const DECIMAL_RESOLUTION_REGEX = /^(\d+)x(\d+)$/;
    const ATTR_LIST_REGEX = /\s*(.+?)\s*=((?:\".*?\")|.*?)(?:,|$)/g;

    // 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(var 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) {
        var match, attrs = {};
        ATTR_LIST_REGEX.lastIndex = 0;
        while ((match = ATTR_LIST_REGEX.exec(input)) !== null) {
          var 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;