5

I'd like to format url with number parameters as following:

http://someurl.com/?param1=100&param2=200

The problem is, it's always truncated after first number parameter e.g:

http://someurl.com/?param1=100. Not sure why.

In my contract I'm using strings library https://github.com/Arachnid/solidity-stringutils

contract code:

import "strings.sol";

contract MyContract {
    using strings for *;

    function bytes32ToString (bytes32 data) constant returns (string) {
        bytes memory bytesString = new bytes(32);
        for (uint j=0; j<32; j++) {
            byte char = byte(bytes32(uint(data) * 2 ** (8 * j)));
            if (char != 0) {
                bytesString[j] = char;
            }
        }
        return string(bytesString);
    }

    function uintToBytes(uint v) constant private returns (bytes32 ret) {
        if (v == 0) {
            ret = '0';
        }
        else {
            while (v > 0) {
                ret = bytes32(uint(ret) / (2 ** 8));
                ret |= bytes32(((v % 10) + 48) * 2 ** (8 * 31));
                v /= 10;
            }
        }
        return ret;
    }

    function uintToString(uint v) constant private returns (string ret) {
        return bytes32ToString(uintToBytes(v));
    }

    function formatUrl(uint param1, uint param2) constant returns(string) {
        var parts = new strings.slice[](4);
        parts[0] = "http://someurl.com/?param1=".toSlice();
        parts[1] = uintToString(param1).toSlice();
        parts[2] = "&?param2=".toSlice();
        parts[3] = uintToString(param2).toSlice();

        return "".toSlice().join(parts);
    }
}

So calling formatUrl(100, 200) returns "http://someurl.com/?param1=100"

If I changed function like this:

function formatUrl(uint param1, uint param2) constant returns(string) {
        var parts = new strings.slice[](4);
        parts[0] = "http://someurl.com/?param1=".toSlice();
        parts[3] = uintToString(param1).toSlice();
        parts[1] = "&?param2=".toSlice();
        parts[2] = uintToString(param2).toSlice();

        return "".toSlice().join(parts);
    }

I get output: "http://someurl.com/?param1=&?param2=200"

It always ends after inserting first number converted to string.

  • After pasting your base code into browser-solidity, I get ` someurl.com/?param1=100&?param2=200`, which as far as I understand is the desired output. How do you test this? – 4gn3s Sep 1 '16 at 12:50
  • I'm compiling locally using solc Version: 0.3.5-48238c9f/Release-Darwin/appleclang/JIT. Browser solidity is using now 0.3.6-3fc68da5/Release-Emscripten/clang. I don't know maybe it's that. Anyways 0.3.5 is latest version on npm – ma2s Sep 1 '16 at 14:52
  • are you sure you have the most recent strings.sol code? Can you maybe try pasting the strings.sol code from github directly into your file to make sure that the correct file gets imported? – 4gn3s Sep 1 '16 at 14:59
  • I re-pasted now, same result :/ – ma2s Sep 1 '16 at 17:45
6

Okay, so I eventually figured out. The problem was in bytes32ToString function. It always returns 32 character long string, where rest of unused chars are simply zero bytes and zero byte means end of a string. So that's why I couldn't join anything after such string, because it had zero bytes in it.

So this is edited bytes32ToString function. It doesn't return any zero bytes. There might exist more effective way tho. Improvements appreciated.

function bytes32ToString (bytes32 x) constant returns (string) {
    bytes memory bytesString = new bytes(32);
    uint charCount = 0;
    for (uint j = 0; j < 32; j++) {
        byte char = byte(bytes32(uint(x) * 2 ** (8 * j)));
        if (char != 0) {
            bytesString[charCount] = char;
            charCount++;
        }
    }
    bytes memory resultBytes = new bytes(charCount);
    for (j = 0; j < charCount; j++) {
        resultBytes[j] = bytesString[j];
    }

    return string(resultBytes);
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.