Skip to content

Commit 78ef170

Browse files
committed
string slice function
1 parent 7b96aab commit 78ef170

File tree

5 files changed

+83
-0
lines changed

5 files changed

+83
-0
lines changed

context.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,7 @@ namespace Sass {
364364
register_function(ctx, str_length_sig, str_length, env);
365365
register_function(ctx, str_insert_sig, str_insert, env);
366366
register_function(ctx, str_index_sig, str_index, env);
367+
register_function(ctx, str_slice_sig, str_slice, env);
367368
// Number Functions
368369
register_function(ctx, percentage_sig, percentage, env);
369370
register_function(ctx, round_sig, round, env);

functions.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -771,6 +771,35 @@ namespace Sass {
771771
return new (ctx.mem) Number(path, position, index);
772772
}
773773

774+
Signature str_slice_sig = "str-slice($string, $start-at, $end-at:-1)";
775+
BUILT_IN(str_slice)
776+
{
777+
String_Constant* s = ARG("$string", String_Constant);
778+
Number* n = ARG("$start-at", Number);
779+
Number* m = ARG("$end-at", Number);
780+
781+
string str = s->value();
782+
char quotemark = s->quote_mark();
783+
str = unquote(str);
784+
785+
// normalize into 0-based indices
786+
size_t start = UTF_8::code_point_offset_to_byte_offset(str, UTF_8::normalize_index(n->value(), UTF_8::code_point_count(str)));
787+
size_t end = UTF_8::code_point_offset_to_byte_offset(str, UTF_8::normalize_index(m->value(), UTF_8::code_point_count(str)));
788+
789+
string newstr;
790+
if(start - end == 0) {
791+
newstr = str.substr(start, end - start);
792+
} else {
793+
newstr = str.substr(start, end - start + UTF_8::length_of_code_point_at(str, end));
794+
}
795+
if(quotemark) {
796+
newstr = quote(newstr, quotemark);
797+
}
798+
799+
return new (ctx.mem) String_Constant(path, position, newstr);
800+
801+
}
802+
774803
///////////////////
775804
// NUMBER FUNCTIONS
776805
///////////////////

functions.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ namespace Sass {
6767
extern Signature str_length_sig;
6868
extern Signature str_insert_sig;
6969
extern Signature str_index_sig;
70+
extern Signature str_slice_sig;
7071
extern Signature percentage_sig;
7172
extern Signature round_sig;
7273
extern Signature ceil_sig;
@@ -121,6 +122,7 @@ namespace Sass {
121122
BUILT_IN(str_length);
122123
BUILT_IN(str_insert);
123124
BUILT_IN(str_index);
125+
BUILT_IN(str_slice);
124126
BUILT_IN(percentage);
125127
BUILT_IN(round);
126128
BUILT_IN(ceil);

utf8_string.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,50 @@ namespace Sass {
7373
return i;
7474
}
7575

76+
// function that returns number of bytes in a character in a string
77+
size_t length_of_code_point_at(const string& str, size_t pos) {
78+
unsigned char c = static_cast<unsigned char>(str[pos]);
79+
size_t i = 0;
80+
if(c < 128) {
81+
return 1;
82+
} else {
83+
++i; // go to the next byte
84+
++pos;
85+
// see if it's still part of the sequence
86+
while ((i < str.length()) && ((static_cast<unsigned char>(str[pos]) & 0b11000000) == 0b10000000)) {
87+
++i;
88+
++pos;
89+
}
90+
}
91+
return i;
92+
}
93+
94+
// function that will return a normalized index, given a crazy one
95+
size_t normalize_index(int index, size_t len) {
96+
int signed_len = len;
97+
// assuming the index is 1-based
98+
// we are returning a 0-based index
99+
if (index > 0 && index <= signed_len) {
100+
// positive and within string length
101+
return index-1;
102+
}
103+
else if (index > signed_len) {
104+
// positive and past string length
105+
return len;
106+
}
107+
else if (index == 0) {
108+
return 0;
109+
}
110+
else if (std::abs(index) <= signed_len) {
111+
// negative and within string length
112+
return index + signed_len;
113+
}
114+
else {
115+
// negative and past string length
116+
return 0;
117+
}
118+
}
119+
76120
}
77121
}
78122

utf8_string.hpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,15 @@ 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+
// function that will return the byte offset of a code point in a
2324
size_t code_point_offset_to_byte_offset(const string& str, size_t offset);
2425

26+
// function that returns number of bytes in a character in a string
27+
size_t length_of_code_point_at(const string& str, size_t pos);
28+
29+
// function that will return a normalized index, given a crazy one
30+
size_t normalize_index(int index, size_t len);
31+
2532
}
2633
}
2734

0 commit comments

Comments
 (0)