Zero-tolerance, no error reporting, cheap .ini parsing Set ini_size==0 to let us use strlen(ini_data). Do not call this function with a 0 if your buffer is actually empty!
| 15583 | // Zero-tolerance, no error reporting, cheap .ini parsing |
| 15584 | // Set ini_size==0 to let us use strlen(ini_data). Do not call this function with a 0 if your buffer is actually empty! |
| 15585 | void ImGui::LoadIniSettingsFromMemory(const char* ini_data, size_t ini_size) |
| 15586 | { |
| 15587 | ImGuiContext& g = *GImGui; |
| 15588 | IM_ASSERT(g.Initialized); |
| 15589 | //IM_ASSERT(!g.WithinFrameScope && "Cannot be called between NewFrame() and EndFrame()"); |
| 15590 | //IM_ASSERT(g.SettingsLoaded == false && g.FrameCount == 0); |
| 15591 | |
| 15592 | // For user convenience, we allow passing a non zero-terminated string (hence the ini_size parameter). |
| 15593 | // For our convenience and to make the code simpler, we'll also write zero-terminators within the buffer. So let's create a writable copy.. |
| 15594 | if (ini_size == 0) |
| 15595 | ini_size = ImStrlen(ini_data); |
| 15596 | g.SettingsIniData.Buf.resize((int)ini_size + 1); |
| 15597 | char* const buf = g.SettingsIniData.Buf.Data; |
| 15598 | char* const buf_end = buf + ini_size; |
| 15599 | memcpy(buf, ini_data, ini_size); |
| 15600 | buf_end[0] = 0; |
| 15601 | |
| 15602 | // Call pre-read handlers |
| 15603 | // Some types will clear their data (e.g. dock information) some types will allow merge/override (window) |
| 15604 | for (ImGuiSettingsHandler& handler : g.SettingsHandlers) |
| 15605 | if (handler.ReadInitFn != NULL) |
| 15606 | handler.ReadInitFn(&g, &handler); |
| 15607 | |
| 15608 | void* entry_data = NULL; |
| 15609 | ImGuiSettingsHandler* entry_handler = NULL; |
| 15610 | |
| 15611 | char* line_end = NULL; |
| 15612 | for (char* line = buf; line < buf_end; line = line_end + 1) |
| 15613 | { |
| 15614 | // Skip new lines markers, then find end of the line |
| 15615 | while (*line == '\n' || *line == '\r') |
| 15616 | line++; |
| 15617 | line_end = line; |
| 15618 | while (line_end < buf_end && *line_end != '\n' && *line_end != '\r') |
| 15619 | line_end++; |
| 15620 | line_end[0] = 0; |
| 15621 | if (line[0] == ';') |
| 15622 | continue; |
| 15623 | if (line[0] == '[' && line_end > line && line_end[-1] == ']') |
| 15624 | { |
| 15625 | // Parse "[Type][Name]". Note that 'Name' can itself contains [] characters, which is acceptable with the current format and parsing code. |
| 15626 | line_end[-1] = 0; |
| 15627 | const char* name_end = line_end - 1; |
| 15628 | const char* type_start = line + 1; |
| 15629 | char* type_end = (char*)(void*)ImStrchrRange(type_start, name_end, ']'); |
| 15630 | const char* name_start = type_end ? ImStrchrRange(type_end + 1, name_end, '[') : NULL; |
| 15631 | if (!type_end || !name_start) |
| 15632 | continue; |
| 15633 | *type_end = 0; // Overwrite first ']' |
| 15634 | name_start++; // Skip second '[' |
| 15635 | entry_handler = FindSettingsHandler(type_start); |
| 15636 | entry_data = entry_handler ? entry_handler->ReadOpenFn(&g, entry_handler, name_start) : NULL; |
| 15637 | } |
| 15638 | else if (entry_handler != NULL && entry_data != NULL) |
| 15639 | { |
| 15640 | // Let type handler parse the line |
| 15641 | entry_handler->ReadLineFn(&g, entry_handler, entry_data, line); |
| 15642 | } |
nothing calls this directly
no test coverage detected