3

I have a bytes32[] array. I convert strings to bytes32 before they are added to the array as follows:

function stringToBytes32(string memory source) returns (bytes32 result) {
    assembly {
    result := mload(add(source, 32))
    }
}

which will turn the string into a hex like 0x5468697320697320612074657374206d65737361676520746861742077696c6c, for example.

However, if the string converted into bytes32 is over 32 characters, I don't know how to turn it back into its original string over 32 characters. Using web3.toAscii only brings back the first 32 characters.

Sanchit
  • 3,482
  • 1
  • 12
  • 29
ZhouW
  • 1,348
  • 2
  • 18
  • 35
  • This sort of thing could be awkward and costly to handle in a smart contract and it will lead to unwanted complexity in the contract. I would incline to the minimal smart contract design. Make the clients encode/decode the data into 32-byte chunks. – Rob Hitchens Jul 08 '17 at 16:59
  • Say if I had messages of 128 characters in length that needed to be stored and called from a contract, would it be a horrible solution to have four bytes32[] arrays? If I can't use an array of strings. – ZhouW Jul 09 '17 at 01:15
  • If I understand correctly, it would be four bytes32, without the array or a bytes32[4]. Would be appropriate IMHO. – Rob Hitchens Jul 09 '17 at 01:55
  • No, I was thinking of having multiple bytes32[] arrays (probably a bad idea). I need some way of storing many messages that are longer than 32 characters so I thought I would need to use arrays. – ZhouW Jul 09 '17 at 02:36
  • For the interface, work with one message at a time. For storage, arrays would probably be part of it. Have a look over here https://ethereum.stackexchange.com/questions/13167/are-there-well-solved-and-simple-storage-patterns-for-solidity. – Rob Hitchens Jul 09 '17 at 07:27

1 Answers1

2
struct DocumentStruct{bytes32 string1; bytes32 string2; bytes32 string3;}
mapping(bytes32 => DocumentStruct) public documentStructs;

function StoreDocument(bytes32 key,bytes32 string1,bytes32 string2,bytes32 string3) onlyOwner returns (bool success) {
    documentStructs[key].string1 = value;
    documentStructs[key].string2 = name;
    documentStructs[key].string3 = name;
    return true;
}

function RetrieveData(bytes32 key) public constant returns(string,string,string) {
    var d = bytes32ToString(documentStructs[key].string1);
    var e = bytes32ToString(documentStructs[key].string2);
    var f = bytes32ToString(documentStructs[key].string3);
    return (d,e,f);
}
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 bytesStringTrimmed = new bytes(charCount);
for (j = 0; j < charCount; j++) {
    bytesStringTrimmed[j] = bytesString[j];
}
return string(bytesStringTrimmed);
}

This works pretty well for me. I would agree that its a little complex to encode and decode, but just run your 32 byte array through it to get a string back

Edit - Here's some added stuff. A rather hacky way, but it might work for you. I'm sure Rob will yell at this answer though

thefett
  • 3,873
  • 5
  • 26
  • 48