This is the API call to add a new entry in the linenoise history. * It uses a fixed array of char pointers that are shifted (memmoved) * when the history max length is reached in order to remove the older * entry and make room for the new one, so it is not exactly suitable for huge * histories, but will work well for a few hundred of entries. * * Using a circular buffer is smarter, but a bit
| 395 | * |
| 396 | * Using a circular buffer is smarter, but a bit more complex to handle. */ |
| 397 | int linenoiseHistoryAdd(const char* line) { |
| 398 | char* linecopy; |
| 399 | |
| 400 | if (history_max_len == 0) |
| 401 | return 0; |
| 402 | |
| 403 | /* Initialization on first call. */ |
| 404 | if (history == NULL) { |
| 405 | history = (char**)malloc(sizeof(char*) * history_max_len); |
| 406 | if (history == NULL) |
| 407 | return 0; |
| 408 | memset(history, 0, (sizeof(char*) * history_max_len)); |
| 409 | } |
| 410 | |
| 411 | if (!Utf8Proc::isValid(line, strlen(line))) { |
| 412 | return 0; |
| 413 | } |
| 414 | |
| 415 | /* Add an heap allocated copy of the line in the history. |
| 416 | * If we reached the max length, remove the older line. */ |
| 417 | if (!mlmode) { |
| 418 | std::string singleLineCopy = ""; |
| 419 | int spaceCount = 0; |
| 420 | // replace all newlines and tabs with spaces |
| 421 | const char* z = line; |
| 422 | char quote = 0; |
| 423 | bool inQuote = false; |
| 424 | bool inComment = false; |
| 425 | bool endWhile = false; |
| 426 | while (*z) { |
| 427 | switch (*z) { |
| 428 | case ' ': |
| 429 | case '\r': |
| 430 | case '\t': |
| 431 | case '\n': |
| 432 | case '\f': { /* White space is turned into a space */ |
| 433 | spaceCount++; |
| 434 | if (spaceCount >= 4) { |
| 435 | spaceCount = 0; |
| 436 | singleLineCopy += ' '; |
| 437 | } else if (z[1] && !isspace((unsigned char)z[1])) { |
| 438 | for (auto i = 0; i < spaceCount; i++) { |
| 439 | singleLineCopy += ' '; |
| 440 | } |
| 441 | spaceCount = 0; |
| 442 | } |
| 443 | break; |
| 444 | } |
| 445 | case '*': { |
| 446 | singleLineCopy += *z; |
| 447 | if (inQuote || !inComment) { |
| 448 | break; |
| 449 | } |
| 450 | if (z[1] == '/') { |
| 451 | z++; |
| 452 | singleLineCopy += *z; |
| 453 | inComment = false; |
| 454 | break; |
no test coverage detected