1
0
Fork
You've already forked zigstr
0
Zigstr is a UTF-8 string type for Zig programs.
Zig 100%
2023年12月05日 09:48:42 -04:00
src Updates for latest Zig 0.12.dev; Now using main branch for deps 2023年12月05日 09:48:42 -04:00
.gitattributes Split out of Ziglyph 2021年06月29日 11:06:20 -04:00
.gitignore Now using Zigmod for Ziglyph dependency. 2021年08月22日 19:42:24 -04:00
.gitmodules Added v0.10 branch to Ziglyph submodule 2023年05月09日 09:14:19 -04:00
build.zig Updated module in build.zig 2023年08月15日 19:39:37 -04:00
build.zig.zon Updates for latest Zig 0.12.dev; Now using main branch for deps 2023年12月05日 09:48:42 -04:00
LICENSE Initial commit 2021年06月29日 10:59:46 -04:00
README.md Updated README for tag v0.11.2 2023年11月30日 09:12:40 -04:00

Zigstr

A UTF-8 string type.

Zig Version

This code will work with Zig version 0.11 stable.

Adding Zigstr to your Project

Zigstr uses the Zig build system and official package manager, so integration is the same as any other Zig module. To track the main development branch, in build.zig.zon add:

.dependencies = .{
 .zigstr = .{
		.url = "https://codeberg.org/dude_the_builder/zigstr/archive/v0.11.2.tar.gz",
 },
},

and in your build.zig:

const zigstr = b.dependency("zigstr", .{
 .target = target,
 .optimize = optimize,
});
// exe, lib, tests, etc.
exe.addModule("zigstr", zigstr.module("zigstr"));

When you now try to build your project, the compiler will produce a hash mismatch error, indicating the hash that you should add to build.zig.zon to make the build work.

To see available tags click here and when you click on a tag name, you'll see the link to the tar.gz file under Assets.

With all this, you can now @import("zigstr") in your project.

Ownership

There are two possibilities when creating a new Zigstr:

  • You own the bytes, requiring the deinit method to free them.
  • You don't own the bytes, so deinit will not free them.

To create a Zigstr in each of these circumstances:

// Here the slice is []const u8.
varstr=tryZigstr.fromConstBytes(allocator,"Hello");deferstr.deinit();// still need `deinit` to free other resources, but not the passed-in bytes.
// Here the slice is []u8.
varstr=tryZigstr.fromOwnedBytes(allocator,slice);deferstr.deinit();// owned bytes will be freed.

Usage Examples

constZigstr=@import("Zigstr");test"Zigstr README tests"{varallocator=std.testing.allocator;varstr=tryZigstr.fromConstBytes(std.testing.allocator,"Héllo");deferstr.deinit();// Byte count.
tryexpectEqual(@as(usize,6),str.byteLen());// Code point iteration.
varcp_iter=str.codePointIter();varwant=[_]u21{'H',0x00E9,'l','l','o'};vari:usize=0;while(cp_iter.next())|cp|:(i+=1){tryexpectEqual(want[i],cp.code);}// Code point count.
tryexpectEqual(@as(usize,5),trystr.codePointLen());// Collect all code points at once.
constcode_points=trystr.codePoints(allocator);deferallocator.free(code_points);for(code_points,0..)|cp,j|{tryexpectEqual(want[j],cp);}// Grapheme cluster iteration.
vargiter=trystr.graphemeIter();constgc_want=[_][]constu8{"H","é","l","l","o"};i=0;while(giter.next())|gc|:(i+=1){tryexpect(gc.eql(str.bytes(),gc_want[i]));}// Collect all grapheme clusters at once.
tryexpectEqual(@as(usize,5),trystr.graphemeLen());constgcs=trystr.graphemes(allocator);deferallocator.free(gcs);for(gcs,0..)|gc,j|{tryexpect(gc.eql(str.bytes(),gc_want[j]));}// Length by graphemes.
tryexpectEqual(@as(usize,5),trystr.graphemeLen());// Indexing (with negative indexes too.)
tryexpectEqual(trystr.byteAt(0),72);// H
tryexpectEqual(trystr.byteAt(-2),108);// l
tryexpectEqual(trystr.codePointAt(0),'H');tryexpectEqual(trystr.codePointAt(-2),'l');tryexpect((trystr.graphemeAt(0)).eql(str.bytes(),"H"));tryexpect((trystr.graphemeAt(-4)).eql(str.bytes(),"é"));// Copy
varstr2=trystr.copy(allocator);deferstr2.deinit();tryexpect(str.eql(str2));tryexpect(str2.eql("Héllo"));// Empty and obtain owned slice of bytes.
constbytes2=trystr2.toOwnedSlice();deferallocator.free(bytes2);tryexpect(str2.eql(""));tryexpectEqualStrings(bytes2,"Héllo");// Re-initialize a Zigstr.
trystr.reset("foo");// Equality
tryexpect(str.eql("foo"));// exact
tryexpect(!str.eql("fooo"));// lengths
tryexpect(!str.eql("foó"));// combining marks
tryexpect(!str.eql("Foo"));// letter case
// Trimming.
trystr.reset(" Hello");trystr.trimLeft(" ");tryexpect(str.eql("Hello"));trystr.reset("Hello ");trystr.trimRight(" ");tryexpect(str.eql("Hello"));trystr.reset(" Hello ");trystr.trim(" ");tryexpect(str.eql("Hello"));// indexOf / contains / lastIndexOf
trystr.reset("H\u{65}\u{301}llo");// Héllo
tryexpectEqual(str.indexOf("l"),2);tryexpectEqual(str.indexOf("z"),null);tryexpect(str.contains("l"));tryexpect(!str.contains("z"));tryexpectEqual(str.lastIndexOf("l"),3);tryexpectEqual(str.lastIndexOf("z"),null);// Count occurrences of substrings.
tryexpectEqual(str.count("l"),2);tryexpectEqual(str.count("ll"),1);tryexpectEqual(str.count("z"),0);// Tokenization
trystr.reset(" Hello World ");// Token iteration.
vartok_iter=str.tokenIter(" ");tryexpectEqualStrings("Hello",tok_iter.next().?);tryexpectEqualStrings("World",tok_iter.next().?);tryexpect(tok_iter.next()==null);// Collect all tokens at once.
varts=trystr.tokenize(allocator," ");deferallocator.free(ts);tryexpectEqual(@as(usize,2),ts.len);tryexpectEqualStrings("Hello",ts[0]);tryexpectEqualStrings("World",ts[1]);// Split
varsplit_iter=str.splitIter(" ");tryexpectEqualStrings("",split_iter.next().?);tryexpectEqualStrings("Hello",split_iter.next().?);tryexpectEqualStrings("World",split_iter.next().?);tryexpectEqualStrings("",split_iter.next().?);tryexpect(split_iter.next()==null);// Collect all sub-strings at once.
varss=trystr.split(allocator," ");deferallocator.free(ss);tryexpectEqual(@as(usize,4),ss.len);tryexpectEqualStrings("",ss[0]);tryexpectEqualStrings("Hello",ss[1]);tryexpectEqualStrings("World",ss[2]);tryexpectEqualStrings("",ss[3]);// Convenience methods for splitting on newline '\n'.
trystr.reset("Hello\nWorld");variter=str.lineIter();// line iterator
tryexpectEqualStrings(iter.next().?,"Hello");tryexpectEqualStrings(iter.next().?,"World");varlines_array=trystr.lines(allocator);// array of lines without ending \n.
deferallocator.free(lines_array);tryexpectEqualStrings(lines_array[0],"Hello");tryexpectEqualStrings(lines_array[1],"World");// startsWith / endsWith
trystr.reset("Hello World");tryexpect(str.startsWith("Hell"));tryexpect(!str.startsWith("Zig"));tryexpect(str.endsWith("World"));tryexpect(!str.endsWith("Zig"));// Concatenation
trystr.reset("Hello");trystr.concat(" World");tryexpect(str.eql("Hello World"));varothers=[_][]constu8{" is"," the"," tradition!"};trystr.concatAll(&others);tryexpect(str.eql("Hello World is the tradition!"));// replace
trystr.reset("Hello");varreplacements=trystr.replace("l","z");tryexpectEqual(@as(usize,2),replacements);tryexpect(str.eql("Hezzo"));replacements=trystr.replace("z","");tryexpectEqual(@as(usize,2),replacements);tryexpect(str.eql("Heo"));// Append code points.
trystr.reset("Hell");trystr.append('o');tryexpectEqual(@as(usize,5),str.byteLen());tryexpect(str.eql("Hello"));trystr.appendAll(&[_]u21{' ','W','o','r','l','d'});tryexpect(str.eql("Hello World"));// Test for empty string.
tryexpect(!str.isEmpty());// Test for whitespace only (blank) strings.
trystr.reset(" \t ");tryexpect(trystr.isBlank());tryexpect(!str.isEmpty());// Remove grapheme clusters (characters) from strings.
trystr.reset("Hello World");trystr.dropLeft(6);tryexpect(str.eql("World"));trystr.reset("Hello World");trystr.dropRight(6);tryexpect(str.eql("Hello"));// Insert at a grapheme index.
trystr.insert("Hi",0);tryexpect(str.eql("HiHello"));// Remove a sub-string.
trystr.remove("Hi");tryexpect(str.eql("Hello"));trystr.remove("Hello");tryexpect(str.eql(""));// Repeat a string's content.
trystr.reset("*");trystr.repeat(10);tryexpect(str.eql("**********"));trystr.repeat(1);tryexpect(str.eql("**********"));trystr.repeat(0);tryexpect(str.eql(""));// Reverse a string. Note correct handling of Unicode code point ordering.
trystr.reset("Héllo 😊");trystr.reverse();tryexpect(str.eql("😊 olléH"));// You can also construct a Zigstr from coce points.
constcp_array=[_]u21{0x68,0x65,0x6C,0x6C,0x6F};// "hello"
str.deinit();str=tryZigstr.fromCodePoints(allocator,&cp_array);tryexpect(str.eql("hello"));tryexpectEqual(str.codePointLen(),5);// Also create a Zigstr from a slice of strings.
str.deinit();str=tryZigstr.fromJoined(std.testing.allocator,&[_][]constu8{"Hello","World"}," ");tryexpect(str.eql("Hello World"));// Chomp line breaks.
trystr.reset("Hello\n");trystr.chomp();tryexpectEqual(@as(usize,5),str.byteLen());tryexpect(str.eql("Hello"));trystr.reset("Hello\r");trystr.chomp();tryexpectEqual(@as(usize,5),str.byteLen());tryexpect(str.eql("Hello"));trystr.reset("Hello\r\n");trystr.chomp();tryexpectEqual(@as(usize,5),str.byteLen());tryexpect(str.eql("Hello"));// byteSlice, codePointSlice, graphemeSlice, substr
trystr.reset("H\u{0065}\u{0301}llo");// Héllo
constbytes=trystr.byteSlice(1,4);tryexpectEqualSlices(u8,bytes,"\u{0065}\u{0301}");constcps=trystr.codePointSlice(allocator,1,3);deferallocator.free(cps);tryexpectEqualSlices(u21,cps,&[_]u21{'\u{0065}','\u{0301}'});constgs=trystr.graphemeSlice(allocator,1,2);deferallocator.free(gs);tryexpect(gs[0].eql(str.bytes(),"\u{0065}\u{0301}"));// Substrings
varsub=trystr.substr(1,2);tryexpectEqualStrings("\u{0065}\u{0301}",sub);tryexpectEqualStrings(bytes,sub);// Letter case detection.
trystr.reset("hello! 123");tryexpect(trystr.isLower());tryexpect(!trystr.isUpper());trystr.reset("HELLO! 123");tryexpect(trystr.isUpper());tryexpect(!trystr.isLower());// Letter case conversion.
trystr.reset("Héllo World! 123\n");trystr.toLower();tryexpect(str.eql("héllo world! 123\n"));trystr.toUpper();tryexpect(str.eql("HÉLLO WORLD! 123\n"));trystr.reset("tHe (mOviE) 2112\n");trystr.toTitle();tryexpect(str.eql("The (Movie) 2112\n"));// Parsing content.
trystr.reset("123");tryexpectEqual(trystr.parseInt(u8,10),123);trystr.reset("123.456");tryexpectEqual(trystr.parseFloat(f32),123.456);trystr.reset("true");tryexpect(trystr.parseBool());// Truthy == True, T, Yes, Y, On in any letter case.
// Not Truthy == False, F, No, N, Off in any letter case.
tryexpect(trystr.parseTruthy());trystr.reset("TRUE");tryexpect(trystr.parseTruthy());trystr.reset("T");tryexpect(trystr.parseTruthy());trystr.reset("No");tryexpect(!trystr.parseTruthy());trystr.reset("off");tryexpect(!trystr.parseTruthy());// Zigstr implements the std.fmt.format interface.
std.debug.print("Zigstr: {}\n",.{str});}