Skip to content

Commit

Permalink
Add variants of DString.insert_at to match .append (c3lang#1510)
Browse files Browse the repository at this point in the history
  • Loading branch information
chri-k authored Oct 2, 2024
1 parent 607a625 commit 2233f24
Show file tree
Hide file tree
Showing 3 changed files with 124 additions and 3 deletions.
109 changes: 106 additions & 3 deletions lib/std/core/dstring.c3
Original file line number Diff line number Diff line change
Expand Up @@ -154,13 +154,15 @@ fn String DString.str_view(self)
return (String)data.chars[:data.len];
}

fn void DString.append_utf32(&self, Char32[] chars)
fn usz DString.append_utf32(&self, Char32[] chars)
{
self.reserve(chars.len);
usz end = self.len();
foreach (Char32 c : chars)
{
self.append_char32(c);
}
return self.data().len - end;
}

/**
Expand All @@ -185,7 +187,7 @@ fn void DString.append_repeat(&self, char c, usz times)
/**
* @require c <= 0x10ffff
*/
fn void DString.append_char32(&self, Char32 c)
fn usz DString.append_char32(&self, Char32 c)
{
char[4] buffer @noinit;
char* p = &buffer;
Expand All @@ -194,6 +196,7 @@ fn void DString.append_char32(&self, Char32 c)
StringData* data = self.data();
data.chars[data.len:n] = buffer[:n];
data.len += n;
return n;
}

fn DString DString.tcopy(&self) => self.copy(allocator::temp());
Expand Down Expand Up @@ -387,7 +390,10 @@ macro void DString.append(&self, value)
$endswitch
}

fn void DString.insert_at(&self, usz index, String s)
/**
* @require index <= self.len()
**/
fn void DString.insert_chars_at(&self, usz index, String s)
{
if (s.len == 0) return;
self.reserve(s.len);
Expand Down Expand Up @@ -419,6 +425,103 @@ fn void DString.insert_at(&self, usz index, String s)
}
}

/**
* @require index <= self.len()
**/
fn void DString.insert_string_at(&self, usz index, DString str)
{
StringData* other = str.data();
if (!other) return;
self.insert_at(index, str.str_view());
}

/**
* @require index <= self.len()
**/
fn void DString.insert_char_at(&self, usz index, char c)
{
self.reserve(1);
StringData* data = self.data();

char* start = &data.chars[index];
mem::move(start + 1, start, self.len() - index);
data.chars[index] = c;
data.len++;
}

/**
* @require index <= self.len()
**/
fn usz DString.insert_char32_at(&self, usz index, Char32 c)
{
char[4] buffer @noinit;
char* p = &buffer;
usz n = conv::char32_to_utf8_unsafe(c, &p);

self.reserve(n);
StringData* data = self.data();

char* start = &data.chars[index];
mem::move(start + n, start, self.len() - index);
data.chars[index:n] = buffer[:n];
data.len += n;

return n;
}

/**
* @require index <= self.len()
**/
fn usz DString.insert_utf32_at(&self, usz index, Char32[] chars)
{
usz n = conv::utf8len_for_utf32(chars);

self.reserve(n);
StringData* data = self.data();

char* start = &data.chars[index];
mem::move(start + n, start, self.len() - index);

char[4] buffer @noinit;

foreach(c : chars)
{
char* p = &buffer;
usz m = conv::char32_to_utf8_unsafe(c, &p);
data.chars[index:m] = buffer[:m];
index += m;
}

data.len += n;

return n;
}

macro void DString.insert_at(&self, usz index, value)
{
var $Type = $typeof(value);
$switch ($Type)
$case char:
$case ichar:
self.insert_char_at(index, value);
$case DString:
self.insert_string_at(index, value);
$case String:
self.insert_chars_at(index, value);
$case Char32:
self.insert_char32_at(index, value);
$default:
$switch
$case $defined((Char32)value):
self.insert_char32_at(index, (Char32)value);
$case $defined((String)value):
self.insert_chars_at(index, (String)value);
$default:
$error "Unsupported type for insert";
$endswitch
$endswitch
}

fn usz! DString.appendf(&self, String format, args...) @maydiscard
{
if (!self.data()) self.new_init(format.len + 20);
Expand Down
1 change: 1 addition & 0 deletions releasenotes.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
- Added generic HMAC.
- Added generic PBKDF2 implementation.
- DString `reverse`.
- `DString.insert_at` now has variants for other types.

## 0.6.2 Change list

Expand Down
17 changes: 17 additions & 0 deletions test/unit/stdlib/core/dstring.c3
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,23 @@ fn void test_insert_at()
str.insert_at(5, " shiny");
s = str.str_view();
assert(s == "hello shiny world", "got '%s'; want 'hello shiny world'", s);

str.insert_at(0, '[');
s = str.str_view();
assert(s == "[hello shiny world", "got '%s'; want '[hello shiny world'", s);

str.insert_at(18, ']');
s = str.str_view();
assert(s == "[hello shiny world]", "got '%s'; want 'hello shiny world]'", s);

str.insert_at(0, 'ꫩ');
s = str.str_view();
assert(s == "ꫩ[hello shiny world]", "got '%s'; want 'ꫩ[hello shiny world]'", s);

// ꫩ is 3 bytes long
str.insert_utf32_at(4, {'寃', 't', 'e', 'x', 't', '¥'});
s = str.str_view();
assert(s == "ꫩ[寃text¥hello shiny world]", "got '%s'; want 'ꫩ[寃text¥hello shiny world]'", s);
}

fn void test_insert_at_overlaps()
Expand Down

0 comments on commit 2233f24

Please sign in to comment.