1 /*
2 * Copyright (C) 2005-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
4 *
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
7 */
8
9 #include "InputCodingTableBaiduPY.h"
10
11 #include "ServiceBroker.h"
12 #include "filesystem/CurlFile.h"
13 #include "guilib/GUIComponent.h"
14 #include "guilib/GUIMessage.h"
15 #include "guilib/GUIWindowManager.h"
16 #include "utils/RegExp.h"
17 #include "utils/StringUtils.h"
18
19 #include <stdlib.h>
20 #include <utility>
21
CInputCodingTableBaiduPY(const std::string & strUrl)22 CInputCodingTableBaiduPY::CInputCodingTableBaiduPY(const std::string& strUrl)
23 : CThread("BaiduPYApi"),
24 m_messageCounter{0},
25 m_api_begin{0},
26 m_api_end{20},
27 m_api_nomore{false},
28 m_initialized{false}
29 {
30 m_url = strUrl;
31 m_codechars = "abcdefghijklmnopqrstuvwxyz";
32 m_code = "";
33 }
34
Process()35 void CInputCodingTableBaiduPY::Process()
36 {
37 m_initialized = true;
38 while (!m_bStop) // Make sure we don't exit the thread
39 {
40 AbortableWait(m_Event, -1); // Wait for work to appear
41 while (!m_bStop) // Process all queued work before going back to wait on the event
42 {
43 CSingleLock lock(m_CS);
44 if (m_work.empty())
45 break;
46
47 auto work = m_work.front();
48 m_work.pop_front();
49 lock.Leave();
50
51 std::string data;
52 XFILE::CCurlFile http;
53 std::string strUrl;
54 strUrl = StringUtils::Format(m_url.c_str(), work.c_str(), m_api_begin, m_api_end);
55
56 if (http.Get(strUrl, data))
57 HandleResponse(work, data);
58 }
59 }
60 }
61
HandleResponse(const std::string & strCode,const std::string & response)62 void CInputCodingTableBaiduPY::HandleResponse(const std::string& strCode,
63 const std::string& response)
64 {
65 if (strCode != m_code) // don't handle obsolete response
66 return;
67
68 std::vector<std::wstring> words;
69 CRegExp reg;
70 reg.RegComp("\\[\"(.+?)\",[^\\]]+\\]");
71 int pos = 0;
72 int num = 0;
73 while ((pos = reg.RegFind(response.c_str(), pos)) >= 0)
74 {
75 num++;
76 std::string full = reg.GetMatch(0);
77 std::string word = reg.GetMatch(1);
78 pos += full.length();
79 words.push_back(UnicodeToWString(word));
80 }
81 if (words.size() < 20)
82 m_api_nomore = true;
83 else
84 {
85 m_api_begin += 20;
86 m_api_end += 20;
87 }
88 CSingleLock lock(m_CS);
89 m_responses.insert(std::make_pair(++m_messageCounter, words));
90 CGUIMessage msg(GUI_MSG_CODINGTABLE_LOOKUP_COMPLETED, 0, 0, m_messageCounter);
91 msg.SetStringParam(strCode);
92 lock.Leave();
93 CServiceBroker::GetGUI()->GetWindowManager().SendThreadMessage(
94 msg, CServiceBroker::GetGUI()->GetWindowManager().GetActiveWindowOrDialog());
95 }
96
UnicodeToWString(const std::string & unicode)97 std::wstring CInputCodingTableBaiduPY::UnicodeToWString(const std::string& unicode)
98 {
99 std::wstring result = L"";
100 for (unsigned int i = 0; i < unicode.length(); i += 6)
101 {
102 int c;
103 sscanf(unicode.c_str() + i, "\\u%x", &c);
104 result += (wchar_t)c;
105 }
106 return result;
107 }
108
GetResponse(int response)109 std::vector<std::wstring> CInputCodingTableBaiduPY::GetResponse(int response)
110 {
111 CSingleLock lock(m_CS);
112 auto words = m_responses.at(response);
113 m_responses.erase(response);
114 return words;
115 }
116
Initialize()117 void CInputCodingTableBaiduPY::Initialize()
118 {
119 CSingleLock lock(m_CS);
120 if (!IsRunning())
121 Create();
122 }
123
Deinitialize()124 void CInputCodingTableBaiduPY::Deinitialize()
125 {
126 m_Event.Set();
127 StopThread(true);
128 m_initialized = false;
129 }
130
IsInitialized() const131 bool CInputCodingTableBaiduPY::IsInitialized() const
132 {
133 return m_initialized;
134 }
135
GetWordListPage(const std::string & strCode,bool isFirstPage)136 bool CInputCodingTableBaiduPY::GetWordListPage(const std::string& strCode, bool isFirstPage)
137 {
138 if (strCode.empty())
139 return false;
140 if (isFirstPage || m_code != strCode)
141 {
142 m_api_begin = 0;
143 m_api_end = 20;
144 m_code = strCode;
145 m_api_nomore = false;
146 }
147 else
148 {
149 if (m_api_nomore)
150 return false;
151 }
152
153 CSingleLock lock(m_CS);
154 m_work.push_back(strCode);
155 m_Event.Set();
156 return true;
157 }
158