2 libpsh/stringbuilder.c - string builder
3 Copyright 2020 Zhang Maiyun
5 This file is part of Psh, P shell.
7 Psh is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 Psh is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <https://www.gnu.org/licenses/>.
31 #include "libpsh/stringbuilder.h"
32 #include "libpsh/xmalloc.h"
34 /* Create a new builder */
35 psh_stringbuilder
*psh_stringbuilder_create()
37 psh_stringbuilder
*builder
= xmalloc(sizeof(psh_stringbuilder
));
38 builder
->total_length
= 0;
39 builder
->current
= builder
->first
= NULL
;
43 /* Append a string starting at *STRING with a length of LENGTH to the builder.
44 STRING gets free()d if IF_FREE is 1 */
45 const char *psh_stringbuilder_add_length(psh_stringbuilder
*builder
,
46 const char *string
, size_t length
,
49 struct _psh_sb_item
*previous
;
50 /* Don't waste memory here */
53 builder
->total_length
+= length
;
58 printf("[psh_stringbuilder_add_length]\n");
59 printf("orig this: %p\n", builder
->current
->next
);
61 builder
->current
->next
= xmalloc(sizeof(struct _psh_sb_item
));
63 printf("this: %p\n", builder
->current
->next
);
64 printf("last: %p\n", builder
->current
);
65 printf("orig string: %p\n", builder
->current
->next
->string
);
66 printf("string: %s\n", string
);
68 previous
= builder
->current
;
69 builder
->current
= builder
->current
->next
;
74 builder
->first
= xmalloc(sizeof(struct _psh_sb_item
));
75 builder
->current
= builder
->first
;
78 /* Now current is to be filled */
79 builder
->current
->previous
= previous
;
80 builder
->current
->length
= length
;
81 builder
->current
->string
= string
;
82 builder
->current
->if_free
= if_free
;
83 builder
->current
->next
= NULL
;
84 /* Now current is filled */
88 /* Append STRING to the builder */
89 const char *psh_stringbuilder_add(psh_stringbuilder
*builder
,
90 const char *string
, int if_free
)
92 size_t length
= strlen(string
);
93 return psh_stringbuilder_add_length(builder
, string
, length
, if_free
);
96 /* Remove the last member of the builder */
97 void psh_stringbuilder_pop(psh_stringbuilder
*builder
)
99 builder
->total_length
-= builder
->current
->length
;
100 if (builder
->current
->if_free
)
101 xfree(builder
->current
->string
);
102 builder
->current
= builder
->current
->previous
;
103 xfree(builder
->current
->next
);
104 builder
->current
->next
= NULL
;
107 /* Generate a string from the builder */
108 char *psh_stringbuilder_yield(psh_stringbuilder
*builder
)
110 struct _psh_sb_item
*cur_from
= builder
->first
;
111 char *result
= xmalloc(P_CS
* builder
->total_length
+ 1);
112 char *cur_to
= result
;
115 /* Copy the string without trailing NUL */
116 memmove(cur_to
, cur_from
->string
, cur_from
->length
);
117 /* Increase result pointer */
118 cur_to
+= cur_from
->length
;
119 /* Get next string */
120 cur_from
= cur_from
->next
;
123 result
[builder
->total_length
] = 0;
127 /* Free resources used by the builder */
128 void psh_stringbuilder_free(psh_stringbuilder
*builder
)
130 struct _psh_sb_item
*cur
= builder
->first
;
135 xfree(cur
->previous
);