• Stars
    star
    1,115
  • Rank 40,154 (Top 0.9 %)
  • Language
    Solidity
  • License
    Apache License 2.0
  • Created about 8 years ago
  • Updated 9 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Basic string utilities for Solidity

String & slice utility library for Solidity

Overview

Functionality in this library is largely implemented using an abstraction called a 'slice'. A slice represents a part of a string - anything from the entire string to a single character, or even no characters at all (a 0-length slice). Since a slice only has to specify an offset and a length, copying and manipulating slices is a lot less expensive than copying and manipulating the strings they reference.

To further reduce gas costs, most functions on slice that need to return a slice modify the original one instead of allocating a new one; for instance, s.split(".") will return the text up to the first '.', modifying s to only contain the remainder of the string after the '.'. In situations where you do not want to modify the original slice, you can make a copy first with .copy(), for example: s.copy().split("."). Try and avoid using this idiom in loops; since Solidity has no memory management, it will result in allocating many short-lived slices that are later discarded.

Functions that return two slices come in two versions: a non-allocating version that takes the second slice as an argument, modifying it in place, and an allocating version that allocates and returns the second slice; see nextRune for example.

Functions that have to copy string data will return strings rather than slices; these can be cast back to slices for further processing if required.

Examples

Basic usage

import "github.com/Arachnid/solidity-stringutils/strings.sol";

contract Contract {
    using strings for *;

    // ...
}

Getting the character length of a string

var len = "Unicode snowman ☃".toSlice().len(); // 17

Splitting a string around a delimiter

var s = "foo bar baz".toSlice();
var foo = s.split(" ".toSlice());

After the above code executes, s is now "bar baz", and foo is now "foo".

Splitting a string into an array

var s = "www.google.com".toSlice();
var delim = ".".toSlice();
var parts = new string[](s.count(delim) + 1);
for(uint i = 0; i < parts.length; i++) {
    parts[i] = s.split(delim).toString();
}

Extracting the middle part of a string

var s = "www.google.com".toSlice();
strings.slice memory part;
s.split(".".toSlice(), part); // part and return value is "www"
s.split(".".toSlice(), part); // part and return value is "google"

This approach uses less memory than the above, by reusing the slice part for each section of string extracted.

Converting a slice back to a string

var myString = mySlice.toString();

Finding and returning the first occurrence of a substring

var s = "A B C B D".toSlice();
s.find("B".toSlice()); // "B C B D"

find modifies s to contain the part of the string from the first match onwards.

Finding and returning the last occurrence of a substring

var s = "A B C B D".toSlice();
s.rfind("B".toSlice()); // "A B C B"

rfind modifies s to contain the part of the string from the last match back to the start.

Finding without modifying the original slice.

var s = "A B C B D".toSlice();
var substring = s.copy().rfind("B".toSlice()); // "A B C B"

copy lets you cheaply duplicate a slice so you don't modify the original.

Prefix and suffix matching

var s = "A B C B D".toSlice();
s.startsWith("A".toSlice()); // True
s.endsWith("D".toSlice()); // True
s.startsWith("B".toSlice()); // False

Removing a prefix or suffix

var s = "A B C B D".toSlice();
s.beyond("A ".toSlice()).until(" D".toSlice()); // "B C B"

beyond modifies s to contain the text after its argument; until modifies s to contain the text up to its argument. If the argument isn't found, s is unmodified.

Finding and returning the string up to the first match

var s = "A B C B D".toSlice();
var needle = "B".toSlice();
var substring = s.until(s.copy().find(needle).beyond(needle));

Calling find on a copy of s returns the part of the string from needle onwards; calling .beyond(needle) removes needle as a prefix, and finally calling s.until() removes the entire end of the string, leaving everything up to and including the first match.

Concatenating strings

var s = "abc".toSlice().concat("def".toSlice()); // "abcdef"

Reference

toSlice(string self) internal returns (slice)

Returns a slice containing the entire string.

Arguments:

  • self The string to make a slice from.

Returns A newly allocated slice containing the entire string.

copy(slice self) internal returns (slice)

Returns a new slice containing the same data as the current slice.

Arguments:

  • self The slice to copy.

Returns A new slice containing the same data as self.

toString(slice self) internal returns (string)

Copies a slice to a new string.

Arguments:

  • self The slice to copy.

Returns A newly allocated string containing the slice's text.

len(slice self) internal returns (uint)

Returns the length in runes of the slice. Note that this operation takes time proportional to the length of the slice; avoid using it in loops, and call slice.empty() if you only need to know whether the slice is empty or not.

Arguments:

  • self The slice to operate on.

Returns The length of the slice in runes.

empty(slice self) internal returns (bool)

Returns true if the slice is empty (has a length of 0).

Arguments:

  • self The slice to operate on.

Returns True if the slice is empty, False otherwise.

compare(slice self, slice other) internal returns (int)

Returns a positive number if other comes lexicographically after self, a negative number if it comes before, or zero if the contents of the two slices are equal. Comparison is done per-rune, on unicode codepoints.

Arguments:

  • self The first slice to compare.
  • other The second slice to compare.

Returns The result of the comparison.

equals(slice self, slice other) internal returns (bool)

Returns true if the two slices contain the same text.

Arguments:

  • self The first slice to compare.
  • self The second slice to compare.

Returns True if the slices are equal, false otherwise.

nextRune(slice self, slice rune) internal returns (slice)

Extracts the first rune in the slice into rune, advancing the slice to point to the next rune and returning self.

Arguments:

  • self The slice to operate on.
  • rune The slice that will contain the first rune.

Returns rune.

nextRune(slice self) internal returns (slice ret)

Returns the first rune in the slice, advancing the slice to point to the next rune.

Arguments:

  • self The slice to operate on.

Returns A slice containing only the first rune from self.

ord(slice self) internal returns (uint ret)

Returns the number of the first codepoint in the slice.

Arguments:

  • self The slice to operate on.

Returns The number of the first codepoint in the slice.

keccak(slice self) internal returns (bytes32 ret)

Returns the keccak-256 hash of the slice.

Arguments:

  • self The slice to hash.

Returns The hash of the slice.

startsWith(slice self, slice needle) internal returns (bool)

Returns true if self starts with needle.

Arguments:

  • self The slice to operate on.
  • needle The slice to search for.

Returns True if the slice starts with the provided text, false otherwise.

beyond(slice self, slice needle) internal returns (slice)

If self starts with needle, needle is removed from the beginning of self. Otherwise, self is unmodified.

Arguments:

  • self The slice to operate on.
  • needle The slice to search for.

Returns self

endsWith(slice self, slice needle) internal returns (bool)

Returns true if the slice ends with needle.

Arguments:

  • self The slice to operate on.
  • needle The slice to search for.

Returns True if the slice starts with the provided text, false otherwise.

until(slice self, slice needle) internal returns (slice)

If self ends with needle, needle is removed from the end of self. Otherwise, self is unmodified.

Arguments:

  • self The slice to operate on.
  • needle The slice to search for.

Returns self

find(slice self, slice needle) internal returns (slice)

Modifies self to contain everything from the first occurrence of needle to the end of the slice. self is set to the empty slice if needle is not found.

Arguments:

  • self The slice to search and modify.
  • needle The text to search for.

Returns self.

rfind(slice self, slice needle) internal returns (slice)

Modifies self to contain the part of the string from the start of self to the end of the first occurrence of needle. If needle is not found, self is set to the empty slice.

Arguments:

  • self The slice to search and modify.
  • needle The text to search for.

Returns self.

split(slice self, slice needle, slice token) internal returns (slice)

Splits the slice, setting self to everything after the first occurrence of needle, and token to everything before it. If needle does not occur in self, self is set to the empty slice, and token is set to the entirety of self.

Arguments:

  • self The slice to split.
  • needle The text to search for in self.
  • token An output parameter to which the first token is written.

Returns token.

split(slice self, slice needle) internal returns (slice token)

Splits the slice, setting self to everything after the first occurrence of needle, and returning everything before it. If needle does not occur in self, self is set to the empty slice, and the entirety of self is returned.

Arguments:

  • self The slice to split.
  • needle The text to search for in self.

Returns The part of self up to the first occurrence of delim.

rsplit(slice self, slice needle, slice token) internal returns (slice)

Splits the slice, setting self to everything before the last occurrence of needle, and token to everything after it. If needle does not occur in self, self is set to the empty slice, and token is set to the entirety of self.

Arguments:

  • self The slice to split.
  • needle The text to search for in self.
  • token An output parameter to which the first token is written.

Returns token.

rsplit(slice self, slice needle) internal returns (slice token)

Splits the slice, setting self to everything before the last occurrence of needle, and returning everything after it. If needle does not occur in self, self is set to the empty slice, and the entirety of self is returned.

Arguments:

  • self The slice to split.
  • needle The text to search for in self.

Returns The part of self after the last occurrence of delim.

count(slice self, slice needle) internal returns (uint count)

Counts the number of nonoverlapping occurrences of needle in self.

Arguments:

  • self The slice to search.
  • needle The text to search for in self.

Returns The number of occurrences of needle found in self.

contains(slice self, slice needle) internal returns (bool)

Returns True if self contains needle.

Arguments:

  • self The slice to search.
  • needle The text to search for in self.

Returns True if needle is found in self, false otherwise.

concat(slice self, slice other) internal returns (string)

Returns a newly allocated string containing the concatenation of self and other.

Arguments:

  • self The first slice to concatenate.
  • other The second slice to concatenate.

Returns The concatenation of the two strings.

join(slice self, slice[] parts) internal returns (string)

Joins an array of slices, using self as a delimiter, returning a newly allocated string.

Arguments:

  • self The delimiter to use.
  • parts A list of slices to join.

Returns A newly allocated string containing all the slices in parts, joined with self.

More Repositories

1

evmdis

EVM disassembler
Go
531
star
2

bloggart

A blog application for App Engine
Python
283
star
3

uscc

JavaScript
233
star
4

flashbots-proxy

An Ethereum RPC proxy that makes composing and submitting flashbots bundles easy
TypeScript
134
star
5

etherquery

Custom ethereum client that uploads blockchain data to BigQuery
Go
123
star
6

aetycoon

aetycoon provides a library of useful App Engine datastore property classes.
Python
73
star
7

netboot.me

Boot anything, anywhere, anytime
Python
61
star
8

dfpga

Discrete FPGA implementation
Python
56
star
9

sggc

Boilerplate and tests for the first Solidity Gas Golfing Contest
JavaScript
50
star
10

aeoid

Easy OpenID support for App Engine
Python
47
star
11

eth-ens-namehash

A javascript module for generating ENS namehashes per spec https://github.com/ethereum/EIPs/issues/137
JavaScript
42
star
12

pyqrencode

Python wrapper for qrencode library.
Python
39
star
13

bulkupdate

App Engine bulk updater library
Python
39
star
14

tweetengine

An App Engine app for group twittering
Python
35
star
15

extrabalance

Python
34
star
16

xenium

A framework for decentralised production and redemption of single-use codes
C
33
star
17

df-vizier

TypeScript
32
star
18

ensdns

ENS->DNS gateway service
Go
31
star
19

AEAuth

A sample app demonstrating how to do App Engine authentication in an Android app
Java
30
star
20

tokencheckingaccount

A smart contract that allows tokens to be stored in a 'checking account' and released with a signature
JavaScript
24
star
21

flashbots-ens-rescue

Rescues ENS names from compromised accounts using flashbots
TypeScript
24
star
22

bdbdatastore

An alternate datastore backend for App Engine, implemented using BDB JE.
Java
20
star
23

amulets

A contract and DApp for amulets, short poems with lucky SHA-256 hashes.
JavaScript
18
star
24

ethjs-abi-bigquery

ethjs-abi library, compiled for use in Google BigQuery
JavaScript
17
star
25

vaniteth

Generates Ethereum vanity addresses
Go
16
star
26

sandplotter

Sand Plotter Design Files and code
Python
15
star
27

Atomify

Converts email to Atom
Python
15
star
28

dnsprove

A tool to convince an Ethereum DNSSEC oracle of the contents of DNS records
Go
15
star
29

netboot.me-gpxe

gPXE fork for netboot.me booting
C
14
star
30

hodlcoin

HODLcoin - an ERC20 token that rewards hodlers.
JavaScript
13
star
31

fork.ethstats.net

HTML
12
star
32

clio

Python
11
star
33

mapreduce-demo

Demo application for App Engine's mapreduce library
Python
9
star
34

busdrivershield

Stackable I2C motor shield for Arduino
C
9
star
35

sm130

SM130 Arduino Library
C++
8
star
36

loregenie

A fantasy RPG NPC generator using OpenAI
TypeScript
7
star
37

shell

Enhanced interactive Python shell for App Engine
Python
6
star
38

go-ethereum

Official golang implementation of the Ethereum protocol
Go
5
star
39

iZac

iZac, the Android Bartender
Java
5
star
40

channel-chat

Channel based chat system for App Engine
Python
5
star
41

go4

Connect 4 solver in Go
Go
5
star
42

exabrot

Explore the exabrot
Python
5
star
43

redactus

A censorship resistant distributed publishing system
Scala
5
star
44

auditreporter

HTML
4
star
45

sotens

State of the ENS presentation
HTML
4
star
46

sggc.github.io

HTML
4
star
47

advisor

Advice machine
Python
3
star
48

eth-multisig-v2

Multi-Sig Wallet v2, supporting original Wallet.sol methods with additional confirmAndExecute improvements to allow for single-transaction signing by multiple owners.
JavaScript
3
star
49

reload

Re:load adjustable dummy load
3
star
50

evmopt

EVM disassembler/optimizer
Go
3
star
51

google_appengine

A git copy of the current svn trunk of the Python App Engine SDK
Python
3
star
52

pointless.site

HTML
3
star
53

devcon2

2
star
54

steppercape

Design files and firmware for the Beaglebone stepper cape.
C
2
star
55

linkdrop-v1

JavaScript
2
star
56

stringprep-js

Pure-JS stringprep implementation
JavaScript
2
star
57

cah

Python
2
star
58

loregenie-development

TypeScript
1
star
59

norsborg-ens

ENS deployment information and code for the norsborg testnet for Hack The Valley
JavaScript
1
star
60

preima.gr

Preimage server for Keccak-256 (and potentially others)
Python
1
star