1 //===-- ProgressEvent.cpp ---------------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "ProgressEvent.h" 10 11 #include "JSONUtils.h" 12 13 using namespace lldb_vscode; 14 using namespace llvm; 15 16 ProgressEvent::ProgressEvent(uint64_t progress_id, const char *message, 17 uint64_t completed, uint64_t total) 18 : m_progress_id(progress_id), m_message(message) { 19 if (completed == total) 20 m_event_type = progressEnd; 21 else if (completed == 0) 22 m_event_type = progressStart; 23 else if (completed < total) 24 m_event_type = progressUpdate; 25 else 26 m_event_type = progressInvalid; 27 28 if (0 < total && total < UINT64_MAX) 29 m_percentage = (uint32_t)(((float)completed / (float)total) * 100.0); 30 } 31 32 bool ProgressEvent::operator==(const ProgressEvent &other) const { 33 return m_progress_id == other.m_progress_id && 34 m_event_type == other.m_event_type && 35 m_percentage == other.m_percentage; 36 } 37 38 const char *ProgressEvent::GetEventName() const { 39 if (m_event_type == progressStart) 40 return "progressStart"; 41 else if (m_event_type == progressEnd) 42 return "progressEnd"; 43 else if (m_event_type == progressUpdate) 44 return "progressUpdate"; 45 else 46 return "progressInvalid"; 47 } 48 49 bool ProgressEvent::IsValid() const { return m_event_type != progressInvalid; } 50 51 uint64_t ProgressEvent::GetID() const { return m_progress_id; } 52 53 json::Value ProgressEvent::ToJSON() const { 54 llvm::json::Object event(CreateEventObject(GetEventName())); 55 llvm::json::Object body; 56 57 std::string progress_id_str; 58 llvm::raw_string_ostream progress_id_strm(progress_id_str); 59 progress_id_strm << m_progress_id; 60 progress_id_strm.flush(); 61 body.try_emplace("progressId", progress_id_str); 62 63 if (m_event_type == progressStart) { 64 EmplaceSafeString(body, "title", m_message); 65 body.try_emplace("cancellable", false); 66 } 67 68 auto now = std::chrono::duration<double>( 69 std::chrono::system_clock::now().time_since_epoch()); 70 std::string timestamp(llvm::formatv("{0:f9}", now.count())); 71 EmplaceSafeString(body, "timestamp", timestamp); 72 73 if (m_percentage) 74 body.try_emplace("percentage", *m_percentage); 75 76 event.try_emplace("body", std::move(body)); 77 return json::Value(std::move(event)); 78 } 79 80 ProgressEventFilterQueue::ProgressEventFilterQueue( 81 std::function<void(ProgressEvent)> callback) 82 : m_callback(callback) {} 83 84 void ProgressEventFilterQueue::Push(const ProgressEvent &event) { 85 if (!event.IsValid()) 86 return; 87 88 auto it = m_last_events.find(event.GetID()); 89 if (it == m_last_events.end() || !(it->second == event)) { 90 m_last_events[event.GetID()] = event; 91 m_callback(event); 92 } 93 } 94