From 42b22b84098fc215beb207c7f1e4ef3b4a022995 Mon Sep 17 00:00:00 2001 From: luoliangyi <87842688@qq.com> Date: Tue, 19 Jul 2022 17:09:52 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84HGScannerLib=E7=9A=84?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../windows/HGScannerLib/HGScannerLib.vcxproj | 8 + build/windows/HGSolution.sln | 1 + build/windows/HGTest/HGTest.vcxproj | 8 +- build/windows/HGTest/pch.cpp | 4 + build/windows/HGTest/pch.h | 1 + sdk/scannerlib/HGLibDeviceImpl.cpp | 236 +++++++++++++++++- sdk/scannerlib/HGLibDeviceImpl.hpp | 15 +- sdk/scannerlib/HGScannerLib.cpp | 52 +++- sdk/scannerlib/HGScannerLib.h | 2 +- sdk/webservice/ManagerV2.cpp | 4 +- 10 files changed, 307 insertions(+), 24 deletions(-) diff --git a/build/windows/HGScannerLib/HGScannerLib.vcxproj b/build/windows/HGScannerLib/HGScannerLib.vcxproj index 395b1c10..4210d846 100644 --- a/build/windows/HGScannerLib/HGScannerLib.vcxproj +++ b/build/windows/HGScannerLib/HGScannerLib.vcxproj @@ -125,6 +125,7 @@ NotUsing pch.h MultiThreaded + ../../../modules/base/;../../../modules/;../../../utility/;../../../../sdk/include/;%(AdditionalIncludeDirectories) Windows @@ -133,6 +134,8 @@ true false HGScannerLib.def + ../Release/HGBase.lib;../Release/HGImgFmt.lib;../Release/HGImgProc.lib;../../../../sdk/lib/win/x86/Release/sane.lib;%(AdditionalDependencies) + /LTCG %(AdditionalOptions) @@ -144,12 +147,14 @@ NotUsing pch.h MultiThreadedDebug + ../../../modules/base/;../../../modules/;../../../utility/;../../../../sdk/include/;%(AdditionalIncludeDirectories) Windows true false HGScannerLib.def + ../x64/Debug/HGBase.lib;../x64/Debug/HGImgFmt.lib;../x64/Debug/HGImgProc.lib;../../../../sdk/lib/win/x64/Release/sane.lib;%(AdditionalDependencies) @@ -163,6 +168,7 @@ NotUsing pch.h MultiThreaded + ../../../modules/base/;../../../modules/;../../../utility/;../../../../sdk/include/;%(AdditionalIncludeDirectories) Windows @@ -171,6 +177,8 @@ true false HGScannerLib.def + ../x64/Release/HGBase.lib;../x64/Release/HGImgFmt.lib;../x64/Release/HGImgProc.lib;../../../../sdk/lib/win/x64/Release/sane.lib;%(AdditionalDependencies) + /LTCG %(AdditionalOptions) diff --git a/build/windows/HGSolution.sln b/build/windows/HGSolution.sln index dd480ddb..73bae0bb 100644 --- a/build/windows/HGSolution.sln +++ b/build/windows/HGSolution.sln @@ -12,6 +12,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HGTest", "HGTest\HGTest.vcx {EFAE5F69-A4C2-4A07-8BE6-68714D86BCE2} = {EFAE5F69-A4C2-4A07-8BE6-68714D86BCE2} {4954F36B-A0A3-4550-9C4E-3B3D210F5CE4} = {4954F36B-A0A3-4550-9C4E-3B3D210F5CE4} {5D85F2AC-FACD-436C-A67B-E13056DD0C03} = {5D85F2AC-FACD-436C-A67B-E13056DD0C03} + {62CAD8E9-4461-49A1-8EB8-4CEBE113FE02} = {62CAD8E9-4461-49A1-8EB8-4CEBE113FE02} {4909ACEA-80FF-482E-9FA2-5E8534789A82} = {4909ACEA-80FF-482E-9FA2-5E8534789A82} EndProjectSection EndProject diff --git a/build/windows/HGTest/HGTest.vcxproj b/build/windows/HGTest/HGTest.vcxproj index 4de9d506..e2e500a7 100644 --- a/build/windows/HGTest/HGTest.vcxproj +++ b/build/windows/HGTest/HGTest.vcxproj @@ -93,7 +93,7 @@ true WIN32;_WINDOWS;_DEBUG;%(PreprocessorDefinitions) pch.h - ../../../modules;%(AdditionalIncludeDirectories) + ../../../modules/base/;../../../modules;../../../sdk;%(AdditionalIncludeDirectories) Windows @@ -116,7 +116,7 @@ true _WINDOWS;_DEBUG;%(PreprocessorDefinitions) pch.h - ../../../modules;%(AdditionalIncludeDirectories) + ../../../modules/base/;../../../modules;../../../sdk;%(AdditionalIncludeDirectories) Windows @@ -141,7 +141,7 @@ true WIN32;_WINDOWS;NDEBUG;%(PreprocessorDefinitions) pch.h - ../../../modules;%(AdditionalIncludeDirectories) + ../../../modules/base/;../../../modules;../../../sdk;%(AdditionalIncludeDirectories) Windows @@ -169,7 +169,7 @@ true _WINDOWS;NDEBUG;%(PreprocessorDefinitions) pch.h - ../../../modules;%(AdditionalIncludeDirectories) + ../../../modules/base/;../../../modules;../../../sdk;%(AdditionalIncludeDirectories) Windows diff --git a/build/windows/HGTest/pch.cpp b/build/windows/HGTest/pch.cpp index 06dc7ba6..70b6a20e 100644 --- a/build/windows/HGTest/pch.cpp +++ b/build/windows/HGTest/pch.cpp @@ -12,6 +12,7 @@ #pragma comment(lib, "../x64/Debug/HGTwainUser.lib") #pragma comment(lib, "../x64/Debug/HGSaneUser.lib") #pragma comment(lib, "../x64/Debug/HGVersion.lib") +#pragma comment(lib, "../x64/Debug/HGScannerLib.lib") #else #pragma comment(lib, "../x64/Release/HGBase.lib") #pragma comment(lib, "../x64/Release/HGImgFmt.lib") @@ -19,6 +20,7 @@ #pragma comment(lib, "../x64/Release/HGTwainUser.lib") #pragma comment(lib, "../x64/Release/HGSaneUser.lib") #pragma comment(lib, "../x64/Release/HGVersion.lib") +#pragma comment(lib, "../x64/Release/HGScannerLib.lib") #endif #else #ifdef _DEBUG @@ -28,6 +30,7 @@ #pragma comment(lib, "../Debug/HGTwainUser.lib") #pragma comment(lib, "../Debug/HGSaneUser.lib") #pragma comment(lib, "../Debug/HGVersion.lib") +#pragma comment(lib, "../Debug/HGScannerLib.lib") #else #pragma comment(lib, "../Release/HGBase.lib") #pragma comment(lib, "../Release/HGImgFmt.lib") @@ -35,5 +38,6 @@ #pragma comment(lib, "../Release/HGTwainUser.lib") #pragma comment(lib, "../Release/HGSaneUser.lib") #pragma comment(lib, "../Release/HGVersion.lib") +#pragma comment(lib, "../Release/HGScannerLib.lib") #endif #endif diff --git a/build/windows/HGTest/pch.h b/build/windows/HGTest/pch.h index 346e3393..c9162a8e 100644 --- a/build/windows/HGTest/pch.h +++ b/build/windows/HGTest/pch.h @@ -24,5 +24,6 @@ #include "twain_user/HGTwain.h" #include "sane_user/HGSane.h" #include "version/HGVersion.h" +#include "scannerlib/HGScannerLib.h" #endif //PCH_H diff --git a/sdk/scannerlib/HGLibDeviceImpl.cpp b/sdk/scannerlib/HGLibDeviceImpl.cpp index b1748fa5..e8885e87 100644 --- a/sdk/scannerlib/HGLibDeviceImpl.cpp +++ b/sdk/scannerlib/HGLibDeviceImpl.cpp @@ -1,6 +1,7 @@ #include "HGLibDeviceImpl.hpp" #include "base/HGInc.h" #include "base/HGInfo.h" +#include "base/HGImage.h" #include "HGString.h" HGLock HGLibDeviceImpl::m_lock = NULL; @@ -8,10 +9,18 @@ HGLibDeviceHotPlugEventFunc HGLibDeviceImpl::m_hotPlugEventFunc = NULL; HGPointer HGLibDeviceImpl::m_hotPlugEventParam = NULL; HGBool HGLibDeviceImpl::m_init = HGFALSE; std::vector HGLibDeviceImpl::m_devNameList; +std::map HGLibDeviceImpl::m_deviceList; HGLibDeviceImpl::HGLibDeviceImpl() { - + m_devHandle = NULL; + m_devName.clear(); + m_scanning = HGFALSE; + m_scanEvent = NULL; + m_eventFunc = NULL; + m_eventParam = NULL; + m_imageFunc = NULL; + m_imageParam = NULL; } HGLibDeviceImpl::~HGLibDeviceImpl() @@ -53,7 +62,13 @@ HGBool HGLibDeviceImpl::Deinit() return HGFALSE; } + if (!m_deviceList.empty()) + { + return HGFALSE; + } + sane_exit(); + m_devNameList.clear(); m_hotPlugEventFunc = NULL; m_hotPlugEventParam = NULL; HGBase_DestroyLock(m_lock); @@ -64,7 +79,23 @@ HGBool HGLibDeviceImpl::Deinit() HGChar** HGLibDeviceImpl::GetNameList() { - return NULL; + HGChar** nameList = NULL; + + HGBase_EnterLock(m_lock); + nameList = (HGChar **)malloc((m_devNameList.size() + 1) * sizeof(HGChar *)); + if (NULL != nameList) + { + nameList[m_devNameList.size()] = NULL; + for (int i = 0; i < (int)m_devNameList.size(); ++i) + { + nameList[i] = (HGChar *)malloc(m_devNameList[i].size() + 1); + if (NULL != nameList[i]) + strcpy(nameList[i], m_devNameList[i].c_str()); + } + } + HGBase_LeaveLock(m_lock); + + return nameList; } HGBool HGLibDeviceImpl::ReleaseNameList(HGChar** deviceName) @@ -74,16 +105,131 @@ HGBool HGLibDeviceImpl::ReleaseNameList(HGChar** deviceName) return HGFALSE; } - while (0 != *deviceName) + HGChar** p = deviceName; + while (0 != *p) { - free(*deviceName); - ++deviceName; + free(*p); + ++p; } free(deviceName); return HGTRUE; } +HGLibDeviceImpl* HGLibDeviceImpl::Open(const HGChar* deviceName) +{ + SANE_Handle devHandle = NULL; + sane_open(deviceName, &devHandle); + if (NULL == devHandle) + { + return NULL; + } + + HGLibDeviceImpl* deviceImpl = new HGLibDeviceImpl; + deviceImpl->m_devHandle = devHandle; + deviceImpl->m_devName = deviceName; + m_deviceList[devHandle] = deviceImpl; + return deviceImpl; +} + +HGBool HGLibDeviceImpl::Close() +{ + assert(NULL != m_devHandle); + assert(!m_devName.empty()); + + StopScan(); + sane_close(m_devHandle); + m_devHandle = NULL; + m_devName.clear(); + + std::map::iterator iter; + for (iter = m_deviceList.begin(); iter != m_deviceList.end(); ++iter) + { + if (iter->second == this) + { + m_deviceList.erase(iter); + break; + } + } + + delete this; + return HGTRUE; +} + +HGBool HGLibDeviceImpl::SetParam(const HGLibDeviceSetParam* param, HGUInt count) +{ + return HGFALSE; +} + +HGLibDeviceGetParamGroup* HGLibDeviceImpl::GetParamGroupList(HGUInt* count) +{ + return NULL; +} + +HGBool HGLibDeviceImpl::ReleaseParamGroupList(HGLibDeviceGetParamGroup* paramGroup, HGUInt count) +{ + return HGFALSE; +} + +HGBool HGLibDeviceImpl::ResetParam() +{ + return HGFALSE; +} + +HGBool HGLibDeviceImpl::StartScan(HGLibDeviceScanEventFunc eventFunc, HGPointer eventParam, + HGLibDeviceScanImageFunc imageFunc, HGPointer imageParam) +{ + if (m_scanning) + { + return HGFALSE; + } + + HGBase_CreateEvent(HGFALSE, HGFALSE, &m_scanEvent); + assert(NULL != m_scanEvent); + m_eventFunc = eventFunc; + m_eventParam = eventParam; + m_imageFunc = imageFunc; + m_imageParam = imageParam; + + SANE_Status status = sane_start(m_devHandle); + if (SANE_STATUS_GOOD != status) + { + m_eventFunc = NULL; + m_eventParam = NULL; + m_imageFunc = NULL; + m_imageParam = NULL; + HGBase_DestroyEvent(m_scanEvent); + m_scanEvent = NULL; + return HGFALSE; + } + + m_scanning = HGTRUE; + return HGTRUE; +} + +HGBool HGLibDeviceImpl::StopScan() +{ + if (!m_scanning) + { + return HGFALSE; + } + + sane_cancel(m_devHandle); + + assert(NULL != m_scanEvent); + HGBase_WaitEvent(m_scanEvent); + HGBase_DestroyEvent(m_scanEvent); + m_scanEvent = NULL; + + m_eventFunc = NULL; + m_eventParam = NULL; + m_imageFunc = NULL; + m_imageParam = NULL; + + m_scanning = HGFALSE; + return HGTRUE; +} + int HGLibDeviceImpl::sane_ex_callback(SANE_Handle hdev, int code, void* data, unsigned int* len, void* param) { switch (code) @@ -106,9 +252,6 @@ int HGLibDeviceImpl::sane_ex_callback(SANE_Handle hdev, int code, void* data, un SANE_Device* sane_dev = (SANE_Device*)data; HGBase_WriteInfo(HGBASE_INFOTYPE_DESC, "SANE_EVENT_DEVICE_LEFT, name=%s", Utf8ToStdString(sane_dev->name).c_str()); - if (NULL != m_hotPlugEventFunc) - m_hotPlugEventFunc(HGLIB_DEVHOTPLUG_EVENT_REMOVE, sane_dev->name, m_hotPlugEventParam); - HGBase_EnterLock(m_lock); for (int i = 0; i < (int)m_devNameList.size(); ++i) { @@ -119,6 +262,83 @@ int HGLibDeviceImpl::sane_ex_callback(SANE_Handle hdev, int code, void* data, un } } HGBase_LeaveLock(m_lock); + + if (NULL != m_hotPlugEventFunc) + m_hotPlugEventFunc(HGLIB_DEVHOTPLUG_EVENT_REMOVE, sane_dev->name, m_hotPlugEventParam); + } + break; + case SANE_EVENT_WORKING: + { + HGBase_WriteInfo(HGBASE_INFOTYPE_DESC, "SANE_EVENT_WORKING, msg=%s", Utf8ToStdString((char*)data).c_str()); + + HGLibDeviceImpl* deviceImpl = m_deviceList[hdev]; + if (NULL != deviceImpl->m_eventFunc) + { + deviceImpl->m_eventFunc((HGLibDevice)deviceImpl, HGLIB_DEVSCAN_EVENT_BEGIN, + HGFALSE, NULL, deviceImpl->m_eventParam); + deviceImpl->m_eventFunc((HGLibDevice)deviceImpl, HGLIB_DEVSCAN_EVENT_INFO, + HGFALSE, (const char*)data, deviceImpl->m_eventParam); + } + } + break; + case SANE_EVENT_SCAN_FINISHED: + { + HGBase_WriteInfo(HGBASE_INFOTYPE_DESC, "SANE_EVENT_SCAN_FINISHED, msg=%s", Utf8ToStdString((char*)data).c_str()); + + HGLibDeviceImpl* deviceImpl = m_deviceList[hdev]; + if (NULL != deviceImpl->m_eventFunc) + { + deviceImpl->m_eventFunc((HGLibDevice)deviceImpl, HGLIB_DEVSCAN_EVENT_INFO, + (0 != *len), (const char*)data, deviceImpl->m_eventParam); + deviceImpl->m_eventFunc((HGLibDevice)deviceImpl, HGLIB_DEVSCAN_EVENT_END, + HGFALSE, NULL, deviceImpl->m_eventParam); + } + + HGBase_SetEvent(deviceImpl->m_scanEvent); + } + break; + case SANE_EVENT_STATUS: + { + HGBase_WriteInfo(HGBASE_INFOTYPE_DESC, "SANE_EVENT_STATUS, msg=%s", Utf8ToStdString((char*)data).c_str()); + } + break; + case SANE_EVENT_ERROR: + { + HGBase_WriteInfo(HGBASE_INFOTYPE_DESC, "SANE_EVENT_ERROR, msg=%s", Utf8ToStdString((char*)data).c_str()); + } + break; + case SANE_EVENT_IMAGE_OK: + { + HGBase_WriteInfo(HGBASE_INFOTYPE_DESC, "SANE_EVENT_IMAGE_OK"); + + SANE_Image* sane_img = (SANE_Image*)data; + + HGLibDeviceImpl* deviceImpl = m_deviceList[hdev]; + if (NULL != deviceImpl->m_imageFunc) + { + HGUInt imgType = 0; + if (sane_img->header.format == SANE_FRAME_GRAY) + { + if (1 == sane_img->header.depth) + imgType = HGBASE_IMGTYPE_BINARY; + else if (8 == sane_img->header.depth) + imgType = HGBASE_IMGTYPE_GRAY; + } + else if (sane_img->header.format == SANE_FRAME_RGB) + imgType = HGBASE_IMGTYPE_RGB; + + HGByte* data = sane_img->data; + HGImageInfo imgInfo = { (HGUInt)sane_img->header.pixels_per_line, (HGUInt)sane_img->header.lines, + imgType, (HGUInt)sane_img->header.bytes_per_line, HGBASE_IMGORIGIN_TOP }; + + HGImage img = NULL; + HGBase_CreateImageFromData(data, &imgInfo, NULL, 0, HGBASE_IMGORIGIN_TOP, &img); + if (NULL != img) + { + deviceImpl->m_imageFunc((HGLibDevice)deviceImpl, (HGLibImage)img, deviceImpl->m_imageParam); + HGBase_DestroyImage(img); + } + } } break; } diff --git a/sdk/scannerlib/HGLibDeviceImpl.hpp b/sdk/scannerlib/HGLibDeviceImpl.hpp index 7c938754..8cb0d6ff 100644 --- a/sdk/scannerlib/HGLibDeviceImpl.hpp +++ b/sdk/scannerlib/HGLibDeviceImpl.hpp @@ -3,9 +3,11 @@ #include "HGScannerLib.h" #include "base/HGLock.h" +#include "base/HGEvent.h" #include "sane/sane_ex.h" #include "sane/sane_option_definitions.h" #include +#include #include class HGLibDeviceImpl @@ -19,7 +21,7 @@ public: static HGChar** GetNameList(); static HGBool ReleaseNameList(HGChar** deviceName); - HGBool Open(const HGChar* deviceName); + static HGLibDeviceImpl* Open(const HGChar* deviceName); HGBool Close(); HGBool SetParam(const HGLibDeviceSetParam* param, HGUInt count); HGLibDeviceGetParamGroup* GetParamGroupList(HGUInt* count); @@ -38,6 +40,17 @@ private: static HGPointer m_hotPlugEventParam; static HGBool m_init; static std::vector m_devNameList; + static std::map m_deviceList; + + + SANE_Handle m_devHandle; + std::string m_devName; + HGBool m_scanning; + HGEvent m_scanEvent; + HGLibDeviceScanEventFunc m_eventFunc; + HGPointer m_eventParam; + HGLibDeviceScanImageFunc m_imageFunc; + HGPointer m_imageParam; }; #endif /* __HGLIBDEVICEIMPL_HPP__ */ \ No newline at end of file diff --git a/sdk/scannerlib/HGScannerLib.cpp b/sdk/scannerlib/HGScannerLib.cpp index 17e08b20..9dade41e 100644 --- a/sdk/scannerlib/HGScannerLib.cpp +++ b/sdk/scannerlib/HGScannerLib.cpp @@ -115,41 +115,77 @@ HGBool HGAPI HGLib_ReleaseDeviceNameList(HGChar** deviceName) HGLibDevice HGAPI HGLib_OpenDevice(const HGChar* deviceName) { - return NULL; + return (HGLibDevice)HGLibDeviceImpl::Open(deviceName); } HGBool HGAPI HGLib_CloseDevice(HGLibDevice device) { - return HGFALSE; + if (NULL == device) + { + return HGFALSE; + } + + HGLibDeviceImpl* deviceImpl = (HGLibDeviceImpl*)device; + return deviceImpl->Close(); } HGBool HGAPI HGLib_SetDeviceParam(HGLibDevice device, const HGLibDeviceSetParam* param, HGUInt count) { - return HGFALSE; + if (NULL == device) + { + return HGFALSE; + } + + HGLibDeviceImpl* deviceImpl = (HGLibDeviceImpl*)device; + return deviceImpl->SetParam(param, count); } HGLibDeviceGetParamGroup* HGAPI HGLib_GetDeviceParamGroupList(HGLibDevice device, HGUInt* count) { - return NULL; + if (NULL == device) + { + return NULL; + } + + HGLibDeviceImpl* deviceImpl = (HGLibDeviceImpl*)device; + return deviceImpl->GetParamGroupList(count); } HGBool HGAPI HGLib_ReleaseDeviceParamGroupList(HGLibDeviceGetParamGroup* paramGroup, HGUInt count) { - return HGFALSE; + return HGLibDeviceImpl::ReleaseParamGroupList(paramGroup, count); } HGBool HGAPI HGLib_ResetDeviceParam(HGLibDevice device) { - return HGFALSE; + if (NULL == device) + { + return HGFALSE; + } + + HGLibDeviceImpl* deviceImpl = (HGLibDeviceImpl*)device; + return deviceImpl->ResetParam(); } HGBool HGAPI HGLib_StartDeviceScan(HGLibDevice device, HGLibDeviceScanEventFunc eventFunc, HGPointer eventParam, HGLibDeviceScanImageFunc imageFunc, HGPointer imageParam) { - return HGFALSE; + if (NULL == device) + { + return HGFALSE; + } + + HGLibDeviceImpl* deviceImpl = (HGLibDeviceImpl*)device; + return deviceImpl->StartScan(eventFunc, eventParam, imageFunc, imageParam); } HGBool HGAPI HGLib_StopDeviceScan(HGLibDevice device) { - return HGFALSE; + if (NULL == device) + { + return HGFALSE; + } + + HGLibDeviceImpl* deviceImpl = (HGLibDeviceImpl*)device; + return deviceImpl->StopScan(); } \ No newline at end of file diff --git a/sdk/scannerlib/HGScannerLib.h b/sdk/scannerlib/HGScannerLib.h index 94b61e17..7d04e2f2 100644 --- a/sdk/scannerlib/HGScannerLib.h +++ b/sdk/scannerlib/HGScannerLib.h @@ -146,7 +146,7 @@ HGEXPORT HGBool HGAPI HGLib_InitDevice(HGLibDeviceHotPlugEventFunc func, HGPoint HGEXPORT HGBool HGAPI HGLib_DeinitDevice(); /* 获取扫描仪名称列表 */ -HGEXPORT HGChar** HGAPI HGLib_GetDeviceNameList(HGUInt *count); +HGEXPORT HGChar** HGAPI HGLib_GetDeviceNameList(); /* 销毁扫描仪名称列表 */ HGEXPORT HGBool HGAPI HGLib_ReleaseDeviceNameList(HGChar** deviceName); diff --git a/sdk/webservice/ManagerV2.cpp b/sdk/webservice/ManagerV2.cpp index 120300b5..ae95beb1 100644 --- a/sdk/webservice/ManagerV2.cpp +++ b/sdk/webservice/ManagerV2.cpp @@ -4033,8 +4033,6 @@ namespace ver_2 } HGBase_EnterLock(p->m_lock); - if (NULL != p->m_saneEvent) - p->m_saneEvent(SANEEVENT_REMOVE, sane_dev->name, false, p->m_saneParam); for (int i = 0; i < (int)p->m_devNameList.size(); ++i) { if (0 == strcmp(sane_dev->name, p->m_devNameList[i].c_str())) @@ -4043,6 +4041,8 @@ namespace ver_2 break; } } + if (NULL != p->m_saneEvent) + p->m_saneEvent(SANEEVENT_REMOVE, sane_dev->name, false, p->m_saneParam); HGBase_LeaveLock(p->m_lock); } break;