library StringUtils {
  /**
   * @dev Converts a string to unsigned integer using the specified `base`
   * @dev Throws on invalid input
   *      (wrong characters for a given `base`)
   * @dev Throws if given `base` is not supported
   * @param a string to convert
   * @param base number base, one of 2, 8, 10, 16
   * @return a number representing given string
   */
  function atoi(string a, uint8 base) internal pure returns (uint256 i) {
    // check if the base is valid
    require(base == 2 || base == 8 || base == 10 || base == 16);

    // convert string into bytes for convenient iteration
    bytes memory buf = bytes(a);

    // iterate over the string (bytes buffer)
    for(uint256 p = 0; p < buf.length; p++) {
      // extract the digit
      uint8 digit = uint8(buf[p]) - 0x30;

      // if digit is greater then 10 – mind the gap
      // see `itoa` function for more details
      if(digit > 10) {
        // remove the gap
        digit -= 7;
      }

      // check if digit meets the base
      require(digit < base);

      // move to the next digit slot
      i *= base;

      // add digit to the result
      i += digit;
    }

    // return the result
    return i;
  }

  /**
   * @dev Converts a integer to a string using the specified `base`
   * @dev Throws if given `base` is not supported
   * @param i integer to convert
   * @param base number base, one of 2, 8, 10, 16
   * @return a string representing given integer
   */
  function itoa(uint256 i, uint8 base) internal pure returns (string a) {
    // check if the base is valid
    require(base == 2 || base == 8 || base == 10 || base == 16);

    // for zero input the result is "0" string for any base
    if (i == 0) {
      return "0";
    }

    // bytes buffer to put ASCII characters into
    bytes memory buf = new bytes(256);

    // position within a buffer to be used in cycle
    uint256 p = 0;

    // extract digits one by one in a cycle
    while (i > 0) {
      // extract current digit
      uint8 digit = uint8(i % base);

      // convert it to an ASCII code
      // 0x20 is " "
      // 0x30-0x39 is "0"-"9"
      // 0x41-0x5A is "A"-"Z"
      // 0x61-0x7A is "a"-"z" ("A"-"Z" XOR " ")
      uint8 ascii = digit + 0x30;

      // if digit is greater then 10,
      // fix the 0x3A-0x40 gap of punctuation marks
      // (7 characters in ASCII table)
      if(digit > 10) {
        // jump through the gap
        ascii += 7;
      }

      // write character into the buffer
      buf[p++] = byte(ascii);

      // move to the next digit
      i /= base;
    }

    // `p` contains real length of the buffer now, save it
    uint256 length = p;

    // reverse the buffer
    for(p = 0; p < length / 2; p++) {
      // swap elements at position `p` from the beginning and end using XOR:
      // https://en.wikipedia.org/wiki/XOR_swap_algorithm
      buf[p] ^= buf[length - 1 - p];
      buf[length - 1 - p] ^= buf[p];
      buf[p] ^= buf[length - 1 - p];
    }

    // construct string and return
    return string(buf);
  }

  /**
   * @dev Concatenates two strings `s1` and `s2`, for example, if
   *      `s1` == `foo` and `s2` == `bar`, the result `s` == `foobar`
   * @param s1 first string
   * @param s2 second string
   * @return concatenation result s1 + s2
   */
  function concat(string s1, string s2) internal pure returns (string s) {
    // convert s1 into buffer 1
    bytes memory buf1 = bytes(s1);
    // convert s2 into buffer 2
    bytes memory buf2 = bytes(s2);
    // create a buffer for concatenation result
    bytes memory buf = new bytes(buf1.length + buf2.length);

    // copy buffer 1 into buffer
    for(uint256 i = 0; i < buf1.length; i++) {
      buf[i] = buf1[i];
    }

    // copy buffer 2 into buffer
    for(uint256 j = buf1.length; j < buf2.length; j++) {
      buf[j] = buf2[j - buf1.length];
    }

    // construct string and return
    return string(buf);
  }
}
/**
 * Library for working with strings, primarily converting
 * between strings and integer types
 */
function concat(string s1, string s2) internal pure returns (string s) {
  // convert s1 into buffer 1
  bytes memory buf1 = bytes(s1);
  // convert s2 into buffer 2
  bytes memory buf2 = bytes(s2);
  // create a buffer for concatenation result
  bytes memory buf = new bytes(buf1.length + buf2.length);

  // copy buffer 1 into buffer
  for(uint256 i = 0; i < buf1.length; i++) {
    buf[i] = buf1[i];
  }

  // copy buffer 2 into buffer
  for(uint256 j = buf1.length; j < buf2.length; j++) {
    buf[j] = buf2[j - buf1.length];
  }

  // construct string and return
  return string(buf);
}

/**
 * @dev Concatenates two strings `s1` and `s2`, for example, if
 *      `s1` == `foo` and `s2` == `bar`, the result `s` == `foobar`
 * @param s1 first string
 * @param s2 second string
 * @return concatenation result s1 + s2
 */