Skip to content

Commit c004b57

Browse files
committed
string insert function using code point offset to byte offset function
1 parent 0a612e5 commit c004b57

File tree

6 files changed

+75
-1
lines changed

6 files changed

+75
-1
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
CXX ?= g++
2-
CXXFLAGS = -Wall -O2 -fPIC -g
2+
CXXFLAGS = -Wall -fPIC -g
33
LDFLAGS = -fPIC
44

55
PREFIX = /usr/local

context.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,7 @@ namespace Sass {
362362
register_function(ctx, unquote_sig, sass_unquote, env);
363363
register_function(ctx, quote_sig, sass_quote, env);
364364
register_function(ctx, str_length_sig, str_length, env);
365+
register_function(ctx, str_insert_sig, str_insert, env);
365366
// Number Functions
366367
register_function(ctx, percentage_sig, percentage, env);
367368
register_function(ctx, round_sig, round, env);

functions.cpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -709,6 +709,49 @@ namespace Sass {
709709
return new (ctx.mem) Number(path, position, len);
710710
}
711711

712+
Signature str_insert_sig = "str-insert($string, $insert, $index)";
713+
BUILT_IN(str_insert)
714+
{
715+
String_Constant* s = ARG("$string", String_Constant);
716+
string str = s->value();
717+
char quotemark = s->quote_mark();
718+
str = unquote(str);
719+
String_Constant* i = ARG("$insert", String_Constant);
720+
string ins = i->value();
721+
ins = unquote(ins);
722+
Number* ind = ARG("$index", Number);
723+
double index = ind->value();
724+
size_t len = UTF_8::code_point_count(str, 0, str.size());
725+
726+
if (index > 0 && index <= len) {
727+
// positive and within string length
728+
str.insert(UTF_8::code_point_offset_to_byte_offset(str, index-1), ins);
729+
}
730+
else if (index > len) {
731+
// positive and past string length
732+
str += ins;
733+
}
734+
else if (index == 0) {
735+
str = ins + str;
736+
}
737+
else if (std::abs(index) <= len) {
738+
// negative and within string length
739+
index += len + 1;
740+
str.insert(UTF_8::code_point_offset_to_byte_offset(str, index), ins);
741+
}
742+
else {
743+
// negative and past string length
744+
str = ins + str;
745+
}
746+
747+
if (quotemark) {
748+
str = quote(str, quotemark);
749+
}
750+
751+
return new (ctx.mem) String_Constant(path, position, str);
752+
753+
}
754+
712755
///////////////////
713756
// NUMBER FUNCTIONS
714757
///////////////////

functions.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ namespace Sass {
6565
extern Signature unquote_sig;
6666
extern Signature quote_sig;
6767
extern Signature str_length_sig;
68+
extern Signature str_insert_sig;
6869
extern Signature percentage_sig;
6970
extern Signature round_sig;
7071
extern Signature ceil_sig;
@@ -117,6 +118,7 @@ namespace Sass {
117118
BUILT_IN(sass_unquote);
118119
BUILT_IN(sass_quote);
119120
BUILT_IN(str_length);
121+
BUILT_IN(str_insert);
120122
BUILT_IN(percentage);
121123
BUILT_IN(round);
122124
BUILT_IN(ceil);

utf8_string.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,32 @@ namespace Sass {
4747
return code_point_count(str, 0, str.length());
4848
}
4949

50+
// function that will return the byte offset of a code point in a
51+
size_t code_point_offset_to_byte_offset(const string& str, size_t offset) {
52+
size_t i = 0;
53+
size_t len = 0;
54+
55+
while (len < offset) {
56+
unsigned char c = static_cast<unsigned char>(str[i]);
57+
if (c < 128) {
58+
// it's a single-byte character
59+
++len;
60+
++i;
61+
}
62+
// it's a multi bit sequence and presumably it's a leading bit
63+
else {
64+
++i; // go to the next byte
65+
// see if it's still part of the sequence
66+
while ((i < str.length()) && ((static_cast<unsigned char>(str[i]) & 0b11000000) == 0b10000000)) {
67+
++i;
68+
}
69+
// when it's not [aka a new leading bit], increment and move on
70+
++len;
71+
}
72+
}
73+
return i;
74+
}
75+
5076
}
5177
}
5278

utf8_string.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ namespace Sass {
2020
size_t code_point_count(const string& str, size_t start, size_t end);
2121
size_t code_point_count(const string& str);
2222

23+
size_t code_point_offset_to_byte_offset(const string& str, size_t offset);
24+
2325
}
2426
}
2527

0 commit comments

Comments
 (0)