dataStrs.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  1. /*
  2. * This file is part of the PikaPython project.
  3. * http://github.com/pikastech/pikapython
  4. *
  5. * MIT License
  6. *
  7. * Copyright (c) 2021 lyon liang6516@outlook.com
  8. *
  9. * Permission is hereby granted, free of charge, to any person obtaining a
  10. * copy of this software and associated documentation files (the "Software"),
  11. * to deal in the Software without restriction, including without limitation
  12. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  13. * and/or sell copies of the Software, and to permit persons to whom the
  14. * Software is furnished to do so, subject to the following conditions:
  15. *
  16. * The above copyright notice and this permission notice shall be included in
  17. * all copies or substantial portions of the Software.
  18. *
  19. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  20. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  22. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  23. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  24. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  25. * DEALINGS IN THE SOFTWARE.
  26. */
  27. #include "dataStrs.h"
  28. #include "PikaPlatform.h"
  29. #include "dataString.h"
  30. Args* New_strBuff(void) {
  31. return New_args(NULL);
  32. }
  33. char* strsRemovePrefix(Args* buffs_p, char* inputStr, char* prefix) {
  34. int32_t size = strGetSize(inputStr);
  35. char* buff = args_getBuff(buffs_p, size);
  36. return strRemovePrefix(inputStr, prefix, buff);
  37. }
  38. char* strsGetDirectStr(Args* buffs_p, char* argPath) {
  39. char* directStr = NULL;
  40. directStr = strsCut(buffs_p, argPath, '"', '"');
  41. if (NULL != directStr) {
  42. return directStr;
  43. }
  44. directStr = strsCut(buffs_p, argPath, '\'', '\'');
  45. if (NULL != directStr) {
  46. return directStr;
  47. }
  48. return NULL;
  49. }
  50. char* strsAppend(Args* buffs_p, char* strOrigin, char* strToAppend) {
  51. pika_assert(NULL != strToAppend);
  52. pika_assert(NULL != strOrigin);
  53. int32_t size = strGetSize(strOrigin) + strGetSize(strToAppend);
  54. char* buff = args_getBuff(buffs_p, size);
  55. char* strOut = strCopy(buff, strOrigin);
  56. strAppend(strOut, strToAppend);
  57. return strOut;
  58. }
  59. char* strsReturnOut(Args* buffs, Args* outbuffs, char* str) {
  60. char* line_out = strsCopy(outbuffs, str);
  61. strsDeinit(buffs);
  62. return line_out;
  63. }
  64. char* strsGetLastToken(Args* buffs_p, char* argPath, char sign) {
  65. int32_t size = strGetSize(argPath);
  66. char* buff = args_getBuff(buffs_p, size);
  67. return strGetLastToken(buff, argPath, sign);
  68. }
  69. char* strsCut(Args* buffs_p, char* strIn, char startSign, char endSign) {
  70. int32_t size = strGetSize(strIn);
  71. char* buff = args_getBuff(buffs_p, size);
  72. return strCut(buff, strIn, startSign, endSign);
  73. }
  74. char* strsDeleteChar(Args* buffs_p, char* strIn, char ch) {
  75. int32_t size = strGetSize(strIn);
  76. return strDeleteChar(args_getBuff(buffs_p, size), strIn, ch);
  77. }
  78. static uint32_t getSizeOfFirstToken(char* str, char sign) {
  79. uint32_t size = strGetSize(str);
  80. for (uint32_t i = 0; i < size; i++) {
  81. if (str[i] == sign) {
  82. return i;
  83. }
  84. }
  85. return size;
  86. }
  87. char* strsGetFirstToken(Args* buffs_p, char* strIn, char sign) {
  88. int32_t size = getSizeOfFirstToken(strIn, sign);
  89. return strGetFirstToken(args_getBuff(buffs_p, size), strIn, sign);
  90. }
  91. char* strsPopToken(Args* buffs_p, char** tokens, char sign) {
  92. return strsCopy(buffs_p, strPopFirstToken(tokens, sign));
  93. }
  94. char* strsPopLine(Args* buffs_p, char** tokens) {
  95. return strsCopy(buffs_p, strPopFirstToken(tokens, '\n'));
  96. }
  97. char* strsCopy(Args* buffs_p, char* source) {
  98. pika_assert(source != NULL);
  99. int32_t size = strGetSize(source);
  100. char* buff = args_getBuff(buffs_p, size);
  101. return strCopy(buff, source);
  102. }
  103. char* strsCacheArg(Args* buffs_p, Arg* arg) {
  104. pika_assert(arg != NULL);
  105. char* res = strsCopy(buffs_p, arg_getStr(arg));
  106. arg_deinit(arg);
  107. return res;
  108. }
  109. char* strsFormat(Args* buffs_p, uint16_t buffSize, const char* fmt, ...) {
  110. va_list args;
  111. va_start(args, fmt);
  112. char* res = args_getBuff(buffs_p, buffSize);
  113. pika_platform_vsnprintf(res, buffSize, fmt, args);
  114. va_end(args);
  115. return res;
  116. }
  117. Arg* arg_strAppend(Arg* arg_in, char* str_to_append) {
  118. pika_assert(NULL != str_to_append);
  119. Args buffs = {0};
  120. char* str_out = strsAppend(&buffs, arg_getStr(arg_in), str_to_append);
  121. Arg* arg_out = arg_newStr(str_out);
  122. arg_deinit(arg_in);
  123. strsDeinit(&buffs);
  124. return arg_out;
  125. }
  126. char* strsReplace(Args* buffs_p, char* orig, char* rep, char* with) {
  127. char* result; // the return string
  128. char* ins; // the next insert point
  129. char* tmp; // varies
  130. int len_rep; // length of rep (the string to remove)
  131. int len_with; // length of with (the string to replace rep with)
  132. int len_front; // distance between rep and end of last rep
  133. int count; // number of replacements
  134. pika_assert(NULL != orig);
  135. pika_assert(NULL != rep);
  136. /* no need replace, skip */
  137. if (NULL == strstr(orig, rep)) {
  138. return orig;
  139. }
  140. // sanity checks and initialization
  141. if (!orig || !rep)
  142. return NULL;
  143. len_rep = strlen(rep);
  144. if (len_rep == 0)
  145. return NULL; // empty rep causes infinite loop during count
  146. if (!with)
  147. with = "";
  148. len_with = strlen(with);
  149. // count the number of replacements needed
  150. ins = orig;
  151. tmp = strstr(ins, rep);
  152. count = 0;
  153. while (tmp) {
  154. count++;
  155. ins = tmp + len_rep;
  156. tmp = strstr(ins, rep);
  157. }
  158. tmp =
  159. args_getBuff(buffs_p, strlen(orig) + (len_with - len_rep) * count + 1);
  160. result = tmp;
  161. if (NULL == result) {
  162. return NULL;
  163. }
  164. // first time through the loop, all the variable are set correctly
  165. // from here on,
  166. // tmp points to the end of the result string
  167. // ins points to the next occurrence of rep in orig
  168. // orig points to the remainder of orig after "end of rep"
  169. while (count--) {
  170. ins = strstr(orig, rep);
  171. len_front = ins - orig;
  172. tmp = strncpy(tmp, orig, len_front) + len_front;
  173. tmp = strcpy(tmp, with) + len_with;
  174. orig += len_front + len_rep; // move to next "end of rep"
  175. }
  176. strcpy(tmp, orig);
  177. return result;
  178. }
  179. char* strsGetLine(Args* buffs_p, char* code) {
  180. int32_t lineSize = strGetLineSize(code);
  181. char* line_buff = args_getBuff(buffs_p, lineSize + 1);
  182. return strGetLine(line_buff, code);
  183. }
  184. void strsDeinit(Args* buffs_p) {
  185. link_deinit_stack(buffs_p);
  186. }
  187. char* strsPathFormat(Args* buffs_p, char* input) {
  188. int32_t size = strGetSize(input);
  189. char* buff = args_getBuff(buffs_p, size);
  190. strPathFormat(input, buff);
  191. return buff;
  192. }
  193. char* strsPathJoin(Args* buffs_p, char* input1, char* input2) {
  194. int32_t size = strGetSize(input1) + strGetSize(input2) + 1;
  195. char* buff = args_getBuff(buffs_p, size);
  196. strPathJoin(input1, input2, buff);
  197. return buff;
  198. }
  199. char* strsPathGetFolder(Args* buffs_p, char* input) {
  200. int32_t size = strGetSize(input);
  201. char* buff = args_getBuff(buffs_p, size);
  202. strPathGetFolder(input, buff);
  203. return buff;
  204. }
  205. char* strsPathGetFileName(Args* buffs_p, char* input) {
  206. int32_t size = strGetSize(input);
  207. char* buff = args_getBuff(buffs_p, size);
  208. strPathGetFileName(input, buff);
  209. return buff;
  210. }
  211. char* strsTransfer(Args* buffs, char* str, size_t* iout_p) {
  212. char* transfered_str = args_getBuff(buffs, strGetSize(str));
  213. size_t i_out = 0;
  214. size_t len = strGetSize(str);
  215. for (size_t i = 0; i < len; i++) {
  216. /* eg. replace '\x33' to '3' */
  217. if ((str[i] == '\\') && (str[i + 1] == 'x')) {
  218. char hex_str[] = "0x00";
  219. hex_str[2] = str[i + 2];
  220. hex_str[3] = str[i + 3];
  221. char hex = (char)strtoll(hex_str, NULL, 0);
  222. transfered_str[i_out++] = hex;
  223. i += 3;
  224. continue;
  225. }
  226. if (str[i] == '\\') {
  227. switch (str[i + 1]) {
  228. case 'r':
  229. transfered_str[i_out++] = '\r';
  230. break;
  231. case 'n':
  232. transfered_str[i_out++] = '\n';
  233. break;
  234. case 't':
  235. transfered_str[i_out++] = '\t';
  236. break;
  237. case 'b':
  238. transfered_str[i_out++] = '\b';
  239. break;
  240. case '\\':
  241. transfered_str[i_out++] = '\\';
  242. break;
  243. case '\'':
  244. transfered_str[i_out++] = '\'';
  245. break;
  246. case '\"':
  247. transfered_str[i_out++] = '\"';
  248. break;
  249. case '?':
  250. transfered_str[i_out++] = '\?';
  251. break;
  252. default:
  253. transfered_str[i_out++] = str[i];
  254. break;
  255. }
  256. i += 1;
  257. continue;
  258. }
  259. /* normal char */
  260. transfered_str[i_out++] = str[i];
  261. }
  262. *iout_p = i_out;
  263. return transfered_str;
  264. }
  265. char* strsFilePreProcess_ex(Args* outbuffs, char* lines, char* endwith) {
  266. Args buffs = {0};
  267. /* replace the "\r\n" to "\n" */
  268. lines = strsReplace(&buffs, lines, "\r\n", "\n");
  269. /* clear the void line */
  270. lines = strsReplace(&buffs, lines, "\n\n", "\n");
  271. /* add '\n' at the end */
  272. lines = strsAppend(&buffs, lines, endwith);
  273. char* result = strsCopy(outbuffs, lines);
  274. strsDeinit(&buffs);
  275. return result;
  276. }
  277. char* strsFilePreProcess(Args* outbuffs, char* lines) {
  278. return strsFilePreProcess_ex(outbuffs, lines, "\n\n");
  279. }
  280. char* strsSubStr(Args* buffs_p, char* name_start, char* name_end) {
  281. int32_t size = name_end - name_start;
  282. char* buff = args_getBuff(buffs_p, size + 1);
  283. for (int32_t i = 0; i < size; i++) {
  284. buff[i] = name_start[i];
  285. }
  286. buff[size] = '\0';
  287. return buff;
  288. }
  289. char* strsRepeat(Args* buffs, char* str, int num) {
  290. int32_t size = strGetSize(str) * num;
  291. char* buff = args_getBuff(buffs, size + 1);
  292. for (int32_t i = 0; i < num; i++) {
  293. for (int32_t j = 0; j < strGetSize(str); j++) {
  294. buff[i * strGetSize(str) + j] = str[j];
  295. }
  296. }
  297. buff[size] = '\0';
  298. return buff;
  299. }
  300. static void _add_indentation(const char* input, int spaces, char* output) {
  301. if (input == NULL || output == NULL || spaces < 0) {
  302. return;
  303. }
  304. const char* current = input;
  305. int output_index = 0;
  306. // Iterate over the input string
  307. while (*current) {
  308. // Add spaces at the beginning of each new line
  309. if (current == input || *(current - 1) == '\n') {
  310. for (int i = 0; i < spaces; ++i) {
  311. output[output_index++] = ' ';
  312. }
  313. }
  314. // Copy the current character
  315. output[output_index++] = *current++;
  316. }
  317. // Add the null terminator to the string
  318. output[output_index] = '\0';
  319. }
  320. char* strsAddIndentation(Args* buffs, char* str, int spaces) {
  321. int lines = 1;
  322. for (const char* current = str; *current; current++) {
  323. if (*current == '\n') {
  324. lines++;
  325. }
  326. }
  327. int output_length = strGetSize(str) + spaces * lines;
  328. char* buff = args_getBuff(buffs, output_length + 1);
  329. _add_indentation(str, spaces, buff);
  330. return buff;
  331. }