28#define _RWSTD_TEST_SRC
45_rw_find_match (
const char* beg,
49 bool is_escaped =
false;
51 for (; beg <
end; ++beg) {
53 const bool is_space = 0 != isspace (
UChar (*beg));
55 if (!is_escaped && match_space == is_space) {
59 is_escaped = !is_escaped && (*beg ==
'\\');
80 const long r =
value - (
q * 10);
85 case 0:
buffer [
n] =
'0';
break;
86 case 1:
buffer [
n] =
'1';
break;
87 case 2:
buffer [
n] =
'2';
break;
88 case 3:
buffer [
n] =
'3';
break;
89 case 4:
buffer [
n] =
'4';
break;
90 case 5:
buffer [
n] =
'5';
break;
91 case 6:
buffer [
n] =
'6';
break;
92 case 7:
buffer [
n] =
'7';
break;
93 case 8:
buffer [
n] =
'8';
break;
94 case 9:
buffer [
n] =
'9';
break;
100 }
while (
value != 0);
107 for (
int i = 0,
j =
n - 1;
i <
j; ++
i, --
j)
125static const char* _rw_find_open_brace (
const char* beg,
128 bool is_escaped =
false;
129 bool is_shelled =
false;
131 for (; beg <
end; ++beg) {
133 const bool is_match = (*beg ==
'{');
134 if (!is_escaped && !is_shelled && is_match) {
138 is_shelled = !is_shelled && (*beg ==
'$');
139 is_escaped = !is_escaped && (*beg ==
'\\');
148static const char* _rw_find_close_brace (
const char* beg,
151 bool is_escaped =
false;
154 for (
int depth = 1; beg <
end; ++beg) {
156 const bool is_open_brace = (*beg ==
'{');
157 if (!is_escaped && is_open_brace) {
161 const bool is_close_brace = (*beg ==
'}');
162 if (!is_escaped && is_close_brace) {
166 is_escaped = !is_escaped && (*beg ==
'\\');
178static const char* _rw_find_next_comma (
const char* beg,
181 bool is_escaped =
false;
184 for (
int depth = 0; beg <
end; ++beg) {
186 const bool is_open_brace = (*beg ==
'{');
187 if (!is_escaped && is_open_brace) {
191 const bool is_close_brace = (*beg ==
'}');
192 if (!is_escaped && is_close_brace) {
196 const bool is_comma = (*beg ==
',');
197 if (!is_escaped && is_comma) {
202 is_escaped = !is_escaped && (*beg ==
'\\');
226 bool append (
const char*
s,
size_t n);
249 char*
buf,
size_t len,
char sep);
260 struct _rw_brace_node
265 _rw_brace_node* sibling_;
266 _rw_brace_node* child_;
272 _rw_brace_node* get_new_node ();
279 _rw_brace_node* build_anything (
const char* beg,
const char*
end);
284 _rw_brace_node* build_character_sequence (
const char* beg,
289 _rw_brace_node* build_integer_sequence (
const char* beg,
295 _rw_brace_node* build_list (
const char* beg,
const char*
end);
300#ifdef _RWSTD_NO_NESTED_CLASS_ACCESS
304 struct _rw_brace_node_buffer;
305 friend struct _rw_brace_node_buffer;
309 struct _rw_recursion_context;
310 friend struct _rw_recursion_context;
316 struct _rw_brace_node_buffer
318 _rw_brace_node nodes_ [
size];
320 _rw_brace_node_buffer* next_;
326 _rw_brace_node_buffer node_cache_;
327 _rw_brace_node_buffer* nodes_;
331 void reset_for_reuse (
char*
buf,
size_t len);
332 void free_range_buffers ();
335 struct _rw_range_buffer
337 _rw_range_buffer* next_;
340 _rw_range_buffer* ranges_;
350 struct _rw_recursion_context
352 _rw_recursion_context (_rw_brace_node* pnode)
353 : parent_ (0), node_ (pnode)
357 _rw_recursion_context (_rw_recursion_context* parent)
358 : parent_ (parent), node_ (parent->node_->child_)
362 _rw_recursion_context* parent_;
363 _rw_brace_node* node_;
369 bool brace_expand (_rw_recursion_context* self,
char sep);
373 bool brace_expand_write (_rw_recursion_context* context);
377 : nodes_ (&node_cache_)
381 node_cache_.next_ = 0;
386 _rw_brace_node_buffer* nodes = node_cache_.next_;
389 _rw_brace_node_buffer* next = nodes->next_;
399 reset_for_reuse (0, 0);
407 char*
buf,
size_t len,
char sep)
417 reset_for_reuse (
buf,
len);
420 = build_anything (beg,
end);
425 _rw_recursion_context context (root);
427 if (!brace_expand (&context, sep)) {
442_rw_brace_graph::_rw_brace_node*
443_rw_brace_graph::get_new_node ()
448 if (! (nodes_->used_ < size)) {
453 nodes_ = nodes_->next_;
459 const size_t sz =
sizeof (_rw_brace_node_buffer);
461 nodes_->next_ = (_rw_brace_node_buffer*)malloc (
sz);
465 nodes_ = nodes_->next_;
472 _rw_brace_node* node = &nodes_->nodes_ [nodes_->used_ - 1];
481_rw_brace_graph::_rw_brace_node*
482_rw_brace_graph::build_anything (
const char* beg,
const char* end)
485 const char* open_brace = _rw_find_open_brace (beg, end);
489 _rw_brace_node*
prefix = get_new_node ();
494 prefix->len_ = (open_brace - beg);
496 _rw_brace_node* child = 0;
499 child = build_character_sequence (open_brace, end);
503 child = build_integer_sequence (open_brace, end);
507 child = build_list (open_brace, end);
524 _rw_brace_node*
prefix = get_new_node ();
534_rw_brace_graph::_rw_brace_node*
535_rw_brace_graph::build_integer_sequence (
const char* beg,
const char* end)
546 long ibeg = strtol (beg, &
pend, 10);
547 if (!ibeg && (
pend == beg))
551 const size_t ibeg_dig = (
pend - beg);
555 if (! (beg [0] ==
'.' && beg [1] ==
'.'))
562 long iend = strtol (beg, &
pend, 10);
563 if (!iend && (
pend == beg))
567 const size_t iend_dig = (
pend - beg);
576 _rw_brace_node* suffix = build_anything (beg, end);
581 const int dir = (ibeg < iend) ? 1 : -1;
585 const size_t len = (ibeg_dig < iend_dig ? iend_dig : ibeg_dig);
588 const size_t num = 1 + (iend - ibeg) * dir;
596 const size_t bsz =
cnt +
sizeof (_rw_range_buffer);
601 = (_rw_range_buffer*)malloc (bsz);
610 char* ranges = (
char*)&
buffer [1];
612 _rw_brace_node* first_child = 0;
613 _rw_brace_node* final_child = 0;
616 for (; ibeg != iend; ibeg += dir) {
620 _rw_brace_node* child = get_new_node ();
625 child->len_ = _rw_itoa_10 (ranges, ibeg);
626 child->str_ = ranges;
629 ranges += child->len_;
636 final_child->sibling_ = child;
640 while (child->child_)
641 child = child->child_;
642 child->child_ = suffix;
646 _rw_brace_node* child = get_new_node ();
651 child->len_ = _rw_itoa_10 (ranges, ibeg);
652 child->str_ = ranges;
659 final_child->sibling_ = child;
663 while (child->child_)
664 child = child->child_;
665 child->child_ = suffix;
670_rw_brace_graph::_rw_brace_node*
671_rw_brace_graph::build_character_sequence (
const char* beg,
const char* end)
688 const int both_are_lower =
689 islower (
UChar (cbeg)) && islower (
UChar (cend));
690 const int both_are_upper =
691 isupper (
UChar (cbeg)) && isupper (
UChar (cend));
693 if (! (both_are_lower || both_are_upper))
697 static const char* alpha_table [] =
699 "abcdefghijklmnopqrstuvwxyz",
700 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
703 const char* sequence = alpha_table [both_are_upper];
705 const int dir = (cbeg < cend) ? 1 : -1;
708 _rw_brace_node* suffix = build_anything (beg + 6, end);
712 _rw_brace_node* first_child = 0;
713 _rw_brace_node* final_child = 0;
716 for (; cbeg != cend; cbeg += dir) {
720 _rw_brace_node* child = get_new_node ();
725 child->str_ = sequence + (cbeg - sequence [0]);
733 final_child->sibling_ = child;
737 while (child->child_)
738 child = child->child_;
739 child->child_ = suffix;
743 _rw_brace_node* child = get_new_node ();
747 child->str_ = sequence + (cbeg - sequence [0]);
755 final_child->sibling_ = child;
759 while (child->child_)
760 child = child->child_;
761 child->child_ = suffix;
766_rw_brace_graph::_rw_brace_node*
767_rw_brace_graph::build_list (
const char* beg,
const char* end)
780 const char* end_of_list = _rw_find_close_brace (beg, end);
785 _rw_brace_node* suffix = build_anything (end_of_list + 1, end);
790 const char* mid = _rw_find_next_comma (beg, end_of_list);
792 _rw_brace_node* first_child = 0;
793 _rw_brace_node* final_child = 0;
799 _rw_brace_node* child = build_anything (beg, mid);
808 final_child->sibling_ = child;
814 while (child->child_)
815 child = child->child_;
816 child->child_ = suffix;
819 mid = _rw_find_next_comma (beg, end_of_list);
830 _rw_brace_node* child = build_anything (beg, end_of_list);
838 final_child->sibling_ = child;
841 while (child->child_)
842 child = child->child_;
843 child->child_ = suffix;
849void _rw_brace_graph::reset_for_reuse (
char*
buf,
size_t len)
851 node_cache_.used_ = 0;
852 nodes_ = &node_cache_;
860 free_range_buffers ();
863void _rw_brace_graph::free_range_buffers ()
865 _rw_range_buffer* ranges = ranges_;
868 _rw_range_buffer* next = ranges->next_;
880bool _rw_brace_graph::brace_expand_write (_rw_recursion_context* context)
882 if (context->parent_) {
883 if (!brace_expand_write (context->parent_))
887 bool is_escaped =
false;
889 const char* beg = context->node_->str_;
890 const size_t len = context->node_->len_;
892 for (
size_t n = 0;
n <
len; ++
n, ++beg) {
894 is_escaped = !is_escaped && (*beg ==
'\\');
896 if (!string_.
append (beg, 1))
904bool _rw_brace_graph::brace_expand (_rw_recursion_context* self,
char sep)
909 !self->node_->sibling_ && !self->node_->child_) {
911 const size_t length_before = string_.
length_;
915 if (!brace_expand_write (self))
918 const size_t length_after = string_.
length_;
921 if (length_before != length_after && !string_.
append (&sep, 1))
929 _rw_recursion_context context (self);
930 while (context.node_) {
932 if (!brace_expand (&context, sep))
935 context.node_ = context.node_->sibling_;
950 while (! (new_len < new_cap))
953 char* new_buf = (
char*)malloc (new_cap);
962 new_buf [new_len] =
'\0';
988 char*
s,
size_t n,
char sep)
995 sz = strlen (brace_expr);
1001 brace_expr +
sz,
s,
n, sep);
1011 char*
s,
size_t n,
char sep)
1018 sz = strlen (shell_expr);
1021 const char* beg = shell_expr;
1022 const char*
end = shell_expr +
sz;
1031 const char* tok_beg = _rw_find_match (beg,
end,
false);
1034 if (!
result.append (
"\0", 1))
1040 bool is_first_expand =
true;
1045 const char* tok_end = _rw_find_match (tok_beg,
end,
true);
1053 graph.build_and_expand (tok_beg, tok_end,
buf,
sizeof (
buf), sep);
1062 const char* term = exp;
1063 for (; *term; term += strlen (term) + 1)
1066 const size_t len = exp < term ? (term - exp) - 1 : 0;
1068 if (is_first_expand)
1070 else if (
result.append (&sep, 1))
1074 is_first_expand =
false;
1094 tok_beg = _rw_find_match (tok_end,
end,
false);
char * rw_brace_expand(const char *brace_expr, size_t sz, char *s, size_t n, char sep)
char * rw_shell_expand(const char *shell_expr, size_t sz, char *s, size_t n, char sep)
char * build_and_expand(const char *beg, const char *end, char *buf, size_t len, char sep)
bool append(const char *s, size_t n)
_rw_string_buffer(char *s, size_t n)
long prefix(const entry_type &entry)