mirror of
https://github.com/kerberos-io/openalpr-base.git
synced 2025-10-07 10:30:52 +08:00
Moved bindings to src/bindings
This commit is contained in:
40
src/bindings/csharp/openalpr-net/AssemblyInfo.cpp
Normal file
40
src/bindings/csharp/openalpr-net/AssemblyInfo.cpp
Normal file
@@ -0,0 +1,40 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
using namespace System;
|
||||
using namespace System::Reflection;
|
||||
using namespace System::Runtime::CompilerServices;
|
||||
using namespace System::Runtime::InteropServices;
|
||||
using namespace System::Security::Permissions;
|
||||
|
||||
//
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
//
|
||||
[assembly:AssemblyTitleAttribute("openalprnet")];
|
||||
[assembly:AssemblyDescriptionAttribute("")];
|
||||
[assembly:AssemblyConfigurationAttribute("")];
|
||||
[assembly:AssemblyCompanyAttribute("")];
|
||||
[assembly:AssemblyProductAttribute("openalprnet")];
|
||||
[assembly:AssemblyCopyrightAttribute("Copyright (c) 2015")];
|
||||
[assembly:AssemblyTrademarkAttribute("")];
|
||||
[assembly:AssemblyCultureAttribute("")];
|
||||
|
||||
//
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the value or you can default the Revision and Build Numbers
|
||||
// by using the '*' as shown below:
|
||||
|
||||
[assembly:AssemblyVersionAttribute("1.0.*")];
|
||||
|
||||
[assembly:ComVisible(false)];
|
||||
|
||||
[assembly:CLSCompliantAttribute(true)];
|
||||
|
||||
[assembly:SecurityPermission(SecurityAction::RequestMinimum, UnmanagedCode = true)];
|
5
src/bindings/csharp/openalpr-net/Stdafx.cpp
Normal file
5
src/bindings/csharp/openalpr-net/Stdafx.cpp
Normal file
@@ -0,0 +1,5 @@
|
||||
// stdafx.cpp : source file that includes just the standard includes
|
||||
// openalpr-net.pch will be the pre-compiled header
|
||||
// stdafx.obj will contain the pre-compiled type information
|
||||
|
||||
#include "stdafx.h"
|
7
src/bindings/csharp/openalpr-net/Stdafx.h
Normal file
7
src/bindings/csharp/openalpr-net/Stdafx.h
Normal file
@@ -0,0 +1,7 @@
|
||||
// stdafx.h : include file for standard system include files,
|
||||
// or project specific include files that are used frequently,
|
||||
// but are changed infrequently
|
||||
|
||||
#pragma once
|
||||
|
||||
|
BIN
src/bindings/csharp/openalpr-net/app.ico
Normal file
BIN
src/bindings/csharp/openalpr-net/app.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
BIN
src/bindings/csharp/openalpr-net/app.rc
Normal file
BIN
src/bindings/csharp/openalpr-net/app.rc
Normal file
Binary file not shown.
394
src/bindings/csharp/openalpr-net/openalpr-net.cpp
Normal file
394
src/bindings/csharp/openalpr-net/openalpr-net.cpp
Normal file
@@ -0,0 +1,394 @@
|
||||
/*
|
||||
* Copyright (c) 2014 New Designs Unlimited, LLC
|
||||
*
|
||||
* This file is part of OpenAlpr.Net.
|
||||
*
|
||||
* OpenAlpr.Net is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "openalpr-net.h"
|
||||
#include "alpr.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <windows.h>
|
||||
#using <mscorlib.dll>
|
||||
//#include <msclr\marshal.h>
|
||||
#include <msclr\marshal_cppstd.h>
|
||||
|
||||
#include "opencv2/highgui/highgui.hpp"
|
||||
#include "opencv2/imgproc/imgproc.hpp"
|
||||
|
||||
using namespace System;
|
||||
using namespace msclr::interop;
|
||||
using namespace System::Collections::Generic;
|
||||
using namespace System::Runtime::InteropServices;
|
||||
using namespace System::Drawing;
|
||||
using namespace alpr;
|
||||
|
||||
namespace openalprnet {
|
||||
|
||||
private ref class AlprHelper sealed
|
||||
{
|
||||
public:
|
||||
static std::vector<char> ToVector(array<char>^ src)
|
||||
{
|
||||
std::vector<char> result(src->Length);
|
||||
pin_ptr<char> pin(&src[0]);
|
||||
char *first(pin), *last(pin + src->Length);
|
||||
std::copy(first, last, result.begin());
|
||||
return result;
|
||||
}
|
||||
|
||||
static std::vector<AlprRegionOfInterest> ToVector(List<System::Drawing::Rectangle>^ src)
|
||||
{
|
||||
std::vector<AlprRegionOfInterest> result;
|
||||
|
||||
for each(System::Drawing::Rectangle^ rect in src)
|
||||
{
|
||||
AlprRegionOfInterest roi(rect->X, rect->Y, rect->Width, rect->Height);
|
||||
result.push_back(roi);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static unsigned char* ToCharPtr(array<unsigned char>^ src)
|
||||
{
|
||||
//unsigned char* result = (unsigned char*) new unsigned char[src->Length];
|
||||
pin_ptr<unsigned char> pin(&src[0]);
|
||||
unsigned char* pc = pin;
|
||||
return pc;
|
||||
}
|
||||
|
||||
static System::String^ ToManagedString(std::string s)
|
||||
{
|
||||
return gcnew String(s.c_str());
|
||||
}
|
||||
|
||||
static std::string ToStlString(System::String^ s)
|
||||
{
|
||||
IntPtr ptr = Marshal::StringToHGlobalAnsi(s);
|
||||
if(ptr != IntPtr::Zero)
|
||||
{
|
||||
std::string tmp(reinterpret_cast<char*>(static_cast<void*>(ptr)));
|
||||
Marshal::FreeHGlobal(ptr);
|
||||
return tmp;
|
||||
}
|
||||
return std::string();
|
||||
}
|
||||
};
|
||||
|
||||
public ref class AlprPlateNet sealed
|
||||
{
|
||||
public:
|
||||
AlprPlateNet(AlprPlate plate){
|
||||
//_characters = marshal_as<System::String^>(plate.characters);
|
||||
m_characters = AlprHelper::ToManagedString(plate.characters);
|
||||
m_overall_confidence=plate.overall_confidence;
|
||||
m_matches_template=plate.matches_template;
|
||||
}
|
||||
|
||||
property System::String^ characters {
|
||||
System::String^ get() {
|
||||
return m_characters;
|
||||
}
|
||||
}
|
||||
|
||||
property float overall_confidence {
|
||||
float get() {
|
||||
return m_overall_confidence;
|
||||
}
|
||||
}
|
||||
|
||||
property bool matches_template {
|
||||
bool get() {
|
||||
return m_matches_template;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
System::String^ m_characters;
|
||||
float m_overall_confidence;
|
||||
bool m_matches_template;
|
||||
};
|
||||
|
||||
public ref class AlprPlateResultNet sealed
|
||||
{
|
||||
public:
|
||||
AlprPlateResultNet(AlprPlateResult result) {
|
||||
m_plate_index = result.plate_index;
|
||||
m_processing_time_ms = result.processing_time_ms;
|
||||
m_regionConfidence = result.regionConfidence;
|
||||
m_region = AlprHelper::ToManagedString(result.region);
|
||||
m_bestPlate = gcnew AlprPlateNet(result.bestPlate);
|
||||
|
||||
m_plate_points = gcnew List<System::Drawing::Point>(4);
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
m_plate_points->Add(System::Drawing::Point(result.plate_points[i].x, result.plate_points[i].y));
|
||||
}
|
||||
|
||||
int num = result.topNPlates.size();
|
||||
m_topNPlates = gcnew List<AlprPlateNet^>(num);
|
||||
for (int i = 0; i < num; i++)
|
||||
{
|
||||
m_topNPlates->Add(gcnew AlprPlateNet(result.topNPlates[i]));
|
||||
}
|
||||
}
|
||||
|
||||
property int requested_topn {
|
||||
int get() {
|
||||
return m_requested_topn;
|
||||
}
|
||||
}
|
||||
|
||||
property int regionConfidence {
|
||||
int get() {
|
||||
return m_regionConfidence;
|
||||
}
|
||||
}
|
||||
|
||||
property int plate_index {
|
||||
int get() {
|
||||
return m_plate_index;
|
||||
}
|
||||
}
|
||||
|
||||
property System::String^ region {
|
||||
System::String^ get() {
|
||||
return m_region;
|
||||
}
|
||||
}
|
||||
|
||||
property AlprPlateNet^ bestPlate {
|
||||
AlprPlateNet^ get() {
|
||||
return m_bestPlate;
|
||||
}
|
||||
}
|
||||
|
||||
property List<System::Drawing::Point>^ plate_points {
|
||||
List<System::Drawing::Point>^ get() {
|
||||
return m_plate_points;
|
||||
}
|
||||
}
|
||||
|
||||
property List<AlprPlateNet^>^ topNPlates {
|
||||
List<AlprPlateNet^>^ get() {
|
||||
return m_topNPlates;
|
||||
}
|
||||
}
|
||||
|
||||
property float processing_time_ms {
|
||||
float get() {
|
||||
return m_processing_time_ms;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
int m_requested_topn;
|
||||
int m_regionConfidence;
|
||||
int m_plate_index;
|
||||
System::String^ m_region;
|
||||
float m_processing_time_ms;
|
||||
List<AlprPlateNet^>^ m_topNPlates;
|
||||
List<System::Drawing::Point>^ m_plate_points;
|
||||
AlprPlateNet^ m_bestPlate;
|
||||
};
|
||||
|
||||
|
||||
public ref class AlprResultsNet sealed
|
||||
{
|
||||
public:
|
||||
AlprResultsNet(AlprResults results) {
|
||||
m_epoch_time = results.epoch_time;
|
||||
m_img_width = results.img_width;
|
||||
m_img_height = results.img_height;
|
||||
m_total_processing_time_ms = results.total_processing_time_ms;
|
||||
|
||||
int num_rois = results.regionsOfInterest.size();
|
||||
m_regionsOfInterest = gcnew List<System::Drawing::Rectangle>(num_rois);
|
||||
for (int i = 0; i < num_rois; i++)
|
||||
{
|
||||
m_regionsOfInterest->Add(System::Drawing::Rectangle(
|
||||
results.regionsOfInterest[i].x,
|
||||
results.regionsOfInterest[i].y,
|
||||
results.regionsOfInterest[i].width,
|
||||
results.regionsOfInterest[i].height));
|
||||
}
|
||||
|
||||
int num_plates = results.plates.size();
|
||||
m_plates = gcnew List<AlprPlateResultNet^>(num_plates);
|
||||
for (int i = 0; i < num_plates; i++)
|
||||
{
|
||||
m_plates->Add(gcnew AlprPlateResultNet(results.plates[i]));
|
||||
}
|
||||
|
||||
std::string json = Alpr::toJson(results);
|
||||
m_json = AlprHelper::ToManagedString(json);
|
||||
}
|
||||
|
||||
property long epoch_time {
|
||||
long get() {
|
||||
return m_epoch_time;
|
||||
}
|
||||
}
|
||||
|
||||
property int img_width {
|
||||
int get() {
|
||||
return m_img_width;
|
||||
}
|
||||
}
|
||||
|
||||
property int img_height {
|
||||
int get() {
|
||||
return m_img_height;
|
||||
}
|
||||
}
|
||||
|
||||
property float total_processing_time_ms {
|
||||
float get() {
|
||||
return m_total_processing_time_ms;
|
||||
}
|
||||
}
|
||||
|
||||
property List<System::Drawing::Rectangle>^ regionsOfInterest {
|
||||
List<System::Drawing::Rectangle>^ get() {
|
||||
return m_regionsOfInterest;
|
||||
}
|
||||
}
|
||||
|
||||
property List<AlprPlateResultNet^>^ plates {
|
||||
List<AlprPlateResultNet^>^ get() {
|
||||
return m_plates;
|
||||
}
|
||||
}
|
||||
|
||||
property System::String^ json {
|
||||
System::String^ get() {
|
||||
return m_json;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
long m_epoch_time;
|
||||
int m_img_width;
|
||||
int m_img_height;
|
||||
float m_total_processing_time_ms;
|
||||
List<System::Drawing::Rectangle>^ m_regionsOfInterest;
|
||||
List<AlprPlateResultNet^>^ m_plates;
|
||||
System::String^ m_json;
|
||||
};
|
||||
|
||||
|
||||
public ref class AlprNet sealed
|
||||
{
|
||||
public:
|
||||
// Allocate the native object on the C++ Heap via a constructor
|
||||
AlprNet(System::String^ country, System::String^ configFile, System::String^ runtimeDir) : m_Impl( new Alpr(marshal_as<std::string>(country), marshal_as<std::string>(configFile), marshal_as<std::string>(runtimeDir)) ) { }
|
||||
|
||||
// Deallocate the native object on a destructor
|
||||
~AlprNet(){
|
||||
delete m_Impl;
|
||||
}
|
||||
|
||||
property int TopN {
|
||||
int get() {
|
||||
return m_topN;
|
||||
}
|
||||
void set( int topn ){
|
||||
m_topN = topn;
|
||||
m_Impl->setTopN(topn);
|
||||
}
|
||||
}
|
||||
|
||||
property bool DetectRegion {
|
||||
bool get() {
|
||||
return m_detectRegion;
|
||||
}
|
||||
void set( bool detectRegion ) {
|
||||
m_detectRegion = detectRegion;
|
||||
m_Impl->setDetectRegion(detectRegion);
|
||||
}
|
||||
}
|
||||
|
||||
property System::String^ DefaultRegion {
|
||||
System::String^ get() {
|
||||
return m_defaultRegion;
|
||||
}
|
||||
void set( System::String^ region ){
|
||||
m_defaultRegion = region;
|
||||
m_Impl->setDefaultRegion(marshal_as<std::string>(region));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recognize from an image on disk
|
||||
/// </summary>
|
||||
AlprResultsNet^ recognize(System::String^ filepath) {
|
||||
AlprResults results = m_Impl->recognize(marshal_as<std::string>(filepath));
|
||||
return gcnew AlprResultsNet(results);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recognize from an image on disk
|
||||
/// </summary>
|
||||
AlprResultsNet^ recognize(System::String^ filepath, List<System::Drawing::Rectangle>^ regionsOfInterest) {
|
||||
cv::Mat frame = cv::imread( marshal_as<std::string>(filepath) );
|
||||
std::vector<AlprRegionOfInterest> rois = AlprHelper::ToVector(regionsOfInterest);
|
||||
AlprResults results = m_Impl->recognize(frame.data, frame.elemSize(), frame.cols, frame.rows, rois );
|
||||
return gcnew AlprResultsNet(results);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recognize from byte data representing an encoded image (e.g., BMP, PNG, JPG, GIF etc).
|
||||
/// </summary>
|
||||
/// <param name="imageBuffer">Bytes representing image data</param>
|
||||
AlprResultsNet^ recognize(cli::array<char>^ imageBuffer) {
|
||||
std::vector<char> p = AlprHelper::ToVector(imageBuffer);
|
||||
AlprResults results = m_Impl->recognize(p);
|
||||
return gcnew AlprResultsNet(results);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recognize from raw pixel data
|
||||
/// </summary>
|
||||
AlprResultsNet^ recognize(cli::array<unsigned char>^ pixelData, int bytesPerPixel, int imgWidth, int imgHeight, List<System::Drawing::Rectangle>^ regionsOfInterest) {
|
||||
unsigned char* p = AlprHelper::ToCharPtr(pixelData);
|
||||
std::vector<AlprRegionOfInterest> rois = AlprHelper::ToVector(regionsOfInterest);
|
||||
AlprResults results = m_Impl->recognize(p, bytesPerPixel, imgWidth, imgHeight, rois);
|
||||
free(p); // ?? memory leak?
|
||||
return gcnew AlprResultsNet(results);
|
||||
}
|
||||
|
||||
bool isLoaded() {
|
||||
return m_Impl->isLoaded();
|
||||
}
|
||||
|
||||
static System::String^ getVersion() {
|
||||
return AlprHelper::ToManagedString(Alpr::getVersion());
|
||||
}
|
||||
|
||||
protected:
|
||||
// Deallocate the native object on the finalizer just in case no destructor is called
|
||||
!AlprNet() {
|
||||
delete m_Impl;
|
||||
}
|
||||
|
||||
private:
|
||||
Alpr * m_Impl;
|
||||
int m_topN;
|
||||
bool m_detectRegion;
|
||||
System::String^ m_defaultRegion;
|
||||
};
|
||||
}
|
9
src/bindings/csharp/openalpr-net/openalpr-net.h
Normal file
9
src/bindings/csharp/openalpr-net/openalpr-net.h
Normal file
@@ -0,0 +1,9 @@
|
||||
// openalpr-net.h
|
||||
|
||||
#pragma once
|
||||
|
||||
//using namespace System;
|
||||
|
||||
namespace openalprnet {
|
||||
|
||||
}
|
102
src/bindings/csharp/openalpr-net/openalpr-net.vcxproj
Normal file
102
src/bindings/csharp/openalpr-net/openalpr-net.vcxproj
Normal file
@@ -0,0 +1,102 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{4044340C-C435-4A1F-8F12-0806C38AE3B6}</ProjectGuid>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<Keyword>ManagedCProj</Keyword>
|
||||
<RootNamespace>openalprnet</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CLRSupport>true</CLRSupport>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<CLRSupport>true</CLRSupport>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<UseOfMfc>false</UseOfMfc>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<AdditionalIncludeDirectories>C:\projects\openalpr\libraries\tesseract-ocr\api;C:\projects\openalpr\libraries\tesseract-ocr\ccstruct;C:\projects\openalpr\libraries\tesseract-ocr\ccmain;C:\projects\openalpr\libraries\tesseract-ocr\ccutil;C:\projects\openalpr\libraries\opencv;C:\projects\openalpr\libraries\opencv\include;C:\projects\openalpr\libraries\opencv\include\opencv;C:\projects\openalpr\libraries\opencv\modules\core\include;C:\projects\openalpr\libraries\opencv\modules\flann\include;C:\projects\openalpr\libraries\opencv\modules\imgproc\include;C:\projects\openalpr\libraries\opencv\modules\highgui\include;C:\projects\openalpr\libraries\opencv\modules\features2d\include;C:\projects\openalpr\libraries\opencv\modules\calib3d\include;C:\projects\openalpr\libraries\opencv\modules\ml\include;C:\projects\openalpr\libraries\opencv\modules\video\include;C:\projects\openalpr\libraries\opencv\modules\legacy\include;C:\projects\openalpr\libraries\opencv\modules\objdetect\include;C:\projects\openalpr\libraries\opencv\modules\photo\include;C:\projects\openalpr\libraries\opencv\modules\gpu\include;C:\projects\openalpr\libraries\opencv\modules\ocl\include;C:\projects\openalpr\libraries\opencv\modules\nonfree\include;C:\projects\openalpr\libraries\opencv\modules\contrib\include;C:\projects\openalpr\libraries\opencv\modules\stitching\include;C:\projects\openalpr\libraries\opencv\modules\superres\include;C:\projects\openalpr\libraries\opencv\modules\ts\include;C:\projects\openalpr\libraries\opencv\modules\videostab\include;C:\projects\openalpr\src\openalpr;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib;C:\projects\openalpr\libraries\opencv\lib\Release\opencv_videostab2410.lib;C:\projects\openalpr\libraries\opencv\lib\Release\opencv_ts2410.lib;C:\projects\openalpr\libraries\opencv\lib\Release\opencv_superres2410.lib;C:\projects\openalpr\libraries\opencv\lib\Release\opencv_stitching2410.lib;C:\projects\openalpr\libraries\opencv\lib\Release\opencv_contrib2410.lib;C:\projects\openalpr\libraries\tesseract-ocr\vs2010\LIB_Release\libtesseract303-static.lib;C:\projects\openalpr\libraries\tesseract-ocr\vs2010\LIB_Release\liblept170.lib;ws2_32.lib;C:\projects\openalpr\libraries\opencv\lib\Release\opencv_nonfree2410.lib;C:\projects\openalpr\libraries\opencv\lib\Release\opencv_ocl2410.lib;C:\projects\openalpr\libraries\opencv\lib\Release\opencv_gpu2410.lib;C:\projects\openalpr\libraries\opencv\lib\Release\opencv_photo2410.lib;C:\projects\openalpr\libraries\opencv\lib\Release\opencv_objdetect2410.lib;C:\projects\openalpr\libraries\opencv\lib\Release\opencv_legacy2410.lib;C:\projects\openalpr\libraries\opencv\lib\Release\opencv_video2410.lib;C:\projects\openalpr\libraries\opencv\lib\Release\opencv_ml2410.lib;C:\projects\openalpr\libraries\opencv\lib\Release\opencv_calib3d2410.lib;C:\projects\openalpr\libraries\opencv\lib\Release\opencv_features2d2410.lib;C:\projects\openalpr\libraries\opencv\lib\Release\opencv_highgui2410.lib;C:\projects\openalpr\libraries\opencv\lib\Release\opencv_imgproc2410.lib;C:\projects\openalpr\libraries\opencv\lib\Release\opencv_flann2410.lib;C:\projects\openalpr\libraries\opencv\lib\Release\opencv_core2410.lib;C:\projects\openalpr\src\openalpr\support\Release\support.lib;C:\projects\openalpr\src\openalpr\Release\openalpr-static.lib</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<AdditionalIncludeDirectories>C:\projects\openalpr\libraries\tesseract-ocr\api;C:\projects\openalpr\libraries\tesseract-ocr\ccstruct;C:\projects\openalpr\libraries\tesseract-ocr\ccmain;C:\projects\openalpr\libraries\tesseract-ocr\ccutil;C:\projects\openalpr\libraries\opencv;C:\projects\openalpr\libraries\opencv\include;C:\projects\openalpr\libraries\opencv\include\opencv;C:\projects\openalpr\libraries\opencv\modules\core\include;C:\projects\openalpr\libraries\opencv\modules\flann\include;C:\projects\openalpr\libraries\opencv\modules\imgproc\include;C:\projects\openalpr\libraries\opencv\modules\highgui\include;C:\projects\openalpr\libraries\opencv\modules\features2d\include;C:\projects\openalpr\libraries\opencv\modules\calib3d\include;C:\projects\openalpr\libraries\opencv\modules\ml\include;C:\projects\openalpr\libraries\opencv\modules\video\include;C:\projects\openalpr\libraries\opencv\modules\legacy\include;C:\projects\openalpr\libraries\opencv\modules\objdetect\include;C:\projects\openalpr\libraries\opencv\modules\photo\include;C:\projects\openalpr\libraries\opencv\modules\gpu\include;C:\projects\openalpr\libraries\opencv\modules\ocl\include;C:\projects\openalpr\libraries\opencv\modules\nonfree\include;C:\projects\openalpr\libraries\opencv\modules\contrib\include;C:\projects\openalpr\libraries\opencv\modules\stitching\include;C:\projects\openalpr\libraries\opencv\modules\superres\include;C:\projects\openalpr\libraries\opencv\modules\ts\include;C:\projects\openalpr\libraries\opencv\modules\videostab\include;C:\projects\openalpr\src\openalpr;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib;C:\projects\openalpr\libraries\opencv\lib\Release\opencv_videostab248.lib;C:\projects\openalpr\libraries\opencv\lib\Release\opencv_ts248.lib;C:\projects\openalpr\libraries\opencv\lib\Release\opencv_superres248.lib;C:\projects\openalpr\libraries\opencv\lib\Release\opencv_stitching248.lib;C:\projects\openalpr\libraries\opencv\lib\Release\opencv_contrib248.lib;C:\projects\openalpr\libraries\tesseract-ocr\vs2010\LIB_Release\libtesseract303-static.lib;C:\projects\openalpr\libraries\tesseract-ocr\vs2010\LIB_Release\liblept170.lib;ws2_32.lib;C:\projects\openalpr\libraries\opencv\lib\Release\opencv_nonfree248.lib;C:\projects\openalpr\libraries\opencv\lib\Release\opencv_ocl248.lib;C:\projects\openalpr\libraries\opencv\lib\Release\opencv_gpu248.lib;C:\projects\openalpr\libraries\opencv\lib\Release\opencv_photo248.lib;C:\projects\openalpr\libraries\opencv\lib\Release\opencv_objdetect248.lib;C:\projects\openalpr\libraries\opencv\lib\Release\opencv_legacy248.lib;C:\projects\openalpr\libraries\opencv\lib\Release\opencv_video248.lib;C:\projects\openalpr\libraries\opencv\lib\Release\opencv_ml248.lib;C:\projects\openalpr\libraries\opencv\lib\Release\opencv_calib3d248.lib;C:\projects\openalpr\libraries\opencv\lib\Release\opencv_features2d248.lib;C:\projects\openalpr\libraries\opencv\lib\Release\opencv_highgui248.lib;C:\projects\openalpr\libraries\opencv\lib\Release\opencv_imgproc248.lib;C:\projects\openalpr\libraries\opencv\lib\Release\opencv_flann248.lib;C:\projects\openalpr\libraries\opencv\lib\Release\opencv_core248.lib;C:\projects\openalpr\src\openalpr\support\Release\support.lib;C:\projects\openalpr\src\openalpr\Release\openalpr-static.lib</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="openalpr-net.h" />
|
||||
<ClInclude Include="resource.h" />
|
||||
<ClInclude Include="Stdafx.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="AssemblyInfo.cpp" />
|
||||
<ClCompile Include="openalpr-net.cpp" />
|
||||
<ClCompile Include="Stdafx.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="app.ico" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="app.rc" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
@@ -0,0 +1,49 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="openalpr-net.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Stdafx.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="resource.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="openalpr-net.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="AssemblyInfo.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Stdafx.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="app.ico">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="app.rc">
|
||||
<Filter>Resource Files</Filter>
|
||||
</ResourceCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
@@ -0,0 +1,3 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
</Project>
|
3
src/bindings/csharp/openalpr-net/resource.h
Normal file
3
src/bindings/csharp/openalpr-net/resource.h
Normal file
@@ -0,0 +1,3 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by app.rc
|
82
src/bindings/csharp/openalprnet-cli/CommandLine.cs
Normal file
82
src/bindings/csharp/openalprnet-cli/CommandLine.cs
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (c) 2015 Dr. Masroor Ehsan
|
||||
*
|
||||
* This file is part of OpenAlpr.Net.
|
||||
*
|
||||
* OpenAlpr.Net is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace openalprnet_cli
|
||||
{
|
||||
internal static class CommandLine
|
||||
{
|
||||
private const string NameGroup = "name"; // Names of capture groups
|
||||
private const string ValueGroup = "value";
|
||||
/* The regex that extracts names and comma-separated values for switches
|
||||
in the form (<switch>[="value 1",value2,...])+ */
|
||||
|
||||
private static readonly Regex RexPattern =
|
||||
new Regex(@"(?<name>[^=]+)=?((?<quoted>\""?)(?<value>(?(quoted)[^\""]+|[^,]+))\""?,?)*",
|
||||
RegexOptions.Compiled | RegexOptions.CultureInvariant |
|
||||
RegexOptions.ExplicitCapture | RegexOptions.IgnoreCase);
|
||||
|
||||
public static void Process(this string[] args, Action printUsage, params Switch[] switches)
|
||||
{
|
||||
/* Run through all matches in the argument list and if any of the switches
|
||||
match, get the values and invoke the handler we were given. We do a Sum()
|
||||
here for 2 reasons; a) To actually run the handlers
|
||||
and b) see if any were invoked at all (each returns 1 if invoked).
|
||||
If none were invoked, we simply invoke the printUsage handler. */
|
||||
if ((from arg in args
|
||||
from Match match in RexPattern.Matches(arg)
|
||||
from s in switches
|
||||
where match.Success &&
|
||||
((string.Compare(match.Groups[NameGroup].Value, s.Name, true) == 0) ||
|
||||
(string.Compare(match.Groups[NameGroup].Value, s.ShortForm, true) == 0))
|
||||
select s.InvokeHandler(match.Groups[ValueGroup].Value.Split(','))).Sum() == 0)
|
||||
printUsage(); // We didn't find any switches
|
||||
}
|
||||
|
||||
public class Switch // Class that encapsulates switch data.
|
||||
{
|
||||
public Switch(string name, Action<IEnumerable<string>> handler, string shortForm)
|
||||
{
|
||||
Name = name;
|
||||
Handler = handler;
|
||||
ShortForm = shortForm;
|
||||
}
|
||||
|
||||
public Switch(string name, Action<IEnumerable<string>> handler)
|
||||
{
|
||||
Name = name;
|
||||
Handler = handler;
|
||||
ShortForm = null;
|
||||
}
|
||||
|
||||
public string Name { get; private set; }
|
||||
public string ShortForm { get; private set; }
|
||||
public Action<IEnumerable<string>> Handler { get; private set; }
|
||||
|
||||
public int InvokeHandler(string[] values)
|
||||
{
|
||||
Handler(values);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
141
src/bindings/csharp/openalprnet-cli/Program.cs
Normal file
141
src/bindings/csharp/openalprnet-cli/Program.cs
Normal file
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Copyright (c) 2015 Dr. Masroor Ehsan
|
||||
*
|
||||
* This file is part of OpenAlpr.Net.
|
||||
*
|
||||
* OpenAlpr.Net is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using openalprnet;
|
||||
|
||||
namespace openalprnet_cli
|
||||
{
|
||||
internal class Program
|
||||
{
|
||||
public static string AssemblyDirectory
|
||||
{
|
||||
get
|
||||
{
|
||||
var codeBase = Assembly.GetExecutingAssembly().CodeBase;
|
||||
var uri = new UriBuilder(codeBase);
|
||||
var path = Uri.UnescapeDataString(uri.Path);
|
||||
return Path.GetDirectoryName(path);
|
||||
}
|
||||
}
|
||||
|
||||
private static bool StrToBool(string s)
|
||||
{
|
||||
return !string.IsNullOrEmpty(s) && s.Trim() == "1";
|
||||
}
|
||||
|
||||
private static void Main(string[] args)
|
||||
{
|
||||
var region = "us";
|
||||
var detectRegion = false;
|
||||
var benchmark = false;
|
||||
var json = false;
|
||||
var filename = string.Empty;
|
||||
|
||||
|
||||
args.Process(
|
||||
() => Console.WriteLine("Usage: r=us/eu b=0/1 j=0/1 d=0/1 f=<filename>"),
|
||||
new CommandLine.Switch("r",
|
||||
val => { if (val.Any()) region = val.First().Trim().ToLower(); }),
|
||||
new CommandLine.Switch("b",
|
||||
val => { if (val.Any()) benchmark = StrToBool(val.First()); }),
|
||||
new CommandLine.Switch("j",
|
||||
val => { if (val.Any()) json = StrToBool(val.First()); }),
|
||||
new CommandLine.Switch("d",
|
||||
val => { if (val.Any()) detectRegion = StrToBool(val.First()); }),
|
||||
new CommandLine.Switch("f",
|
||||
val => { if (val.Any()) filename = val.First().Trim(); })
|
||||
);
|
||||
|
||||
Console.WriteLine("OpenAlpr Version: {0}", AlprNet.getVersion());
|
||||
var config = Path.Combine(AssemblyDirectory, "openalpr.conf");
|
||||
var runtime_data = Path.Combine(AssemblyDirectory, "runtime_data");
|
||||
var alpr = new AlprNet(region, config, runtime_data);
|
||||
if (!alpr.isLoaded())
|
||||
{
|
||||
Console.WriteLine("OpenAlpr failed to load!");
|
||||
return;
|
||||
}
|
||||
|
||||
//var samplePath = Path.Combine(AssemblyDirectory, @"samples\eu-1.jpg");
|
||||
//alpr.TopN = 3;
|
||||
alpr.DefaultRegion = region;
|
||||
alpr.DetectRegion = detectRegion;
|
||||
|
||||
if (Directory.Exists(filename))
|
||||
{
|
||||
var files = Directory.GetFiles(filename, "*.jpg", SearchOption.TopDirectoryOnly);
|
||||
foreach (var fname in files)
|
||||
{
|
||||
PerformAlpr(alpr, fname, benchmark, json);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!File.Exists(filename))
|
||||
{
|
||||
Console.WriteLine("The file doesn't exist!");
|
||||
return;
|
||||
}
|
||||
var buffer = File.ReadAllBytes(filename);
|
||||
PerformAlpr(alpr, buffer, benchmark, json);
|
||||
}
|
||||
|
||||
private static void PerformAlpr(AlprNet alpr, string filename, bool benchmark, bool writeJson)
|
||||
{
|
||||
Console.WriteLine("Processing '{0}'...\n------------------", Path.GetFileName(filename));
|
||||
var buffer = File.ReadAllBytes(filename);
|
||||
PerformAlpr(alpr, buffer, benchmark, writeJson);
|
||||
}
|
||||
|
||||
private static void PerformAlpr(AlprNet alpr, byte[] buffer, bool benchmark, bool writeJson)
|
||||
{
|
||||
var sw = Stopwatch.StartNew();
|
||||
sbyte[] signedBuffer = (sbyte[])(Array)buffer;
|
||||
var results = alpr.recognize(signedBuffer);
|
||||
sw.Stop();
|
||||
if (benchmark)
|
||||
{
|
||||
Console.WriteLine("Total Time to process image(s): {0} msec(s)", sw.ElapsedMilliseconds);
|
||||
}
|
||||
|
||||
if (writeJson)
|
||||
{
|
||||
//Console.WriteLine(alpr.toJson());
|
||||
}
|
||||
else
|
||||
{
|
||||
var i = 0;
|
||||
foreach (var result in results.plates)
|
||||
{
|
||||
Console.WriteLine("Plate {0}: {1} result(s)", i++, result.topNPlates.Count);
|
||||
Console.WriteLine(" Processing Time: {0} msec(s)", result.processing_time_ms);
|
||||
foreach (var plate in result.topNPlates)
|
||||
{
|
||||
Console.WriteLine(" - {0}\t Confidence: {1}\tMatches Template: {2}", plate.characters,
|
||||
plate.overall_confidence, plate.matches_template);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("openalprnet-cli")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("openalprnet-cli")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2015")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("42477de2-b13e-4959-a03e-ae43c65e68f3")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
64
src/bindings/csharp/openalprnet-cli/openalprnet-cli.csproj
Normal file
64
src/bindings/csharp/openalprnet-cli/openalprnet-cli.csproj
Normal file
@@ -0,0 +1,64 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
|
||||
<ProductVersion>8.0.30703</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{BD50C6C1-EEB9-48D2-A87C-70F5342579DD}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>openalprnet_cli</RootNamespace>
|
||||
<AssemblyName>openalprnet-cli</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<TargetFrameworkProfile>Client</TargetFrameworkProfile>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="CommandLine.cs" />
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\openalpr-net\openalpr-net.vcxproj">
|
||||
<Project>{4044340C-C435-4A1F-8F12-0806C38AE3B6}</Project>
|
||||
<Name>openalpr-net</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
192
src/bindings/csharp/openalprnet-windemo/Form1.Designer.cs
generated
Normal file
192
src/bindings/csharp/openalprnet-windemo/Form1.Designer.cs
generated
Normal file
@@ -0,0 +1,192 @@
|
||||
namespace openalprnet_windemo
|
||||
{
|
||||
partial class Form1
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.btnDetect = new System.Windows.Forms.Button();
|
||||
this.picLicensePlate = new System.Windows.Forms.PictureBox();
|
||||
this.picOriginal = new System.Windows.Forms.PictureBox();
|
||||
this.lbxPlates = new System.Windows.Forms.ListBox();
|
||||
this.label1 = new System.Windows.Forms.Label();
|
||||
this.label2 = new System.Windows.Forms.Label();
|
||||
this.label3 = new System.Windows.Forms.Label();
|
||||
this.openFileDialog = new System.Windows.Forms.OpenFileDialog();
|
||||
this.label4 = new System.Windows.Forms.Label();
|
||||
this.rbUSA = new System.Windows.Forms.RadioButton();
|
||||
this.rbEU = new System.Windows.Forms.RadioButton();
|
||||
((System.ComponentModel.ISupportInitialize)(this.picLicensePlate)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.picOriginal)).BeginInit();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// btnDetect
|
||||
//
|
||||
this.btnDetect.Location = new System.Drawing.Point(830, 25);
|
||||
this.btnDetect.Name = "btnDetect";
|
||||
this.btnDetect.Size = new System.Drawing.Size(291, 37);
|
||||
this.btnDetect.TabIndex = 0;
|
||||
this.btnDetect.Text = "Detect License Plate";
|
||||
this.btnDetect.UseVisualStyleBackColor = true;
|
||||
this.btnDetect.Click += new System.EventHandler(this.button1_Click);
|
||||
//
|
||||
// picLicensePlate
|
||||
//
|
||||
this.picLicensePlate.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
|
||||
this.picLicensePlate.Location = new System.Drawing.Point(827, 403);
|
||||
this.picLicensePlate.Name = "picLicensePlate";
|
||||
this.picLicensePlate.Size = new System.Drawing.Size(294, 123);
|
||||
this.picLicensePlate.TabIndex = 1;
|
||||
this.picLicensePlate.TabStop = false;
|
||||
//
|
||||
// picOriginal
|
||||
//
|
||||
this.picOriginal.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
|
||||
this.picOriginal.Location = new System.Drawing.Point(12, 25);
|
||||
this.picOriginal.Name = "picOriginal";
|
||||
this.picOriginal.Size = new System.Drawing.Size(809, 501);
|
||||
this.picOriginal.TabIndex = 2;
|
||||
this.picOriginal.TabStop = false;
|
||||
//
|
||||
// lbxPlates
|
||||
//
|
||||
this.lbxPlates.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.lbxPlates.FormattingEnabled = true;
|
||||
this.lbxPlates.Location = new System.Drawing.Point(827, 81);
|
||||
this.lbxPlates.Name = "lbxPlates";
|
||||
this.lbxPlates.Size = new System.Drawing.Size(294, 303);
|
||||
this.lbxPlates.TabIndex = 3;
|
||||
//
|
||||
// label1
|
||||
//
|
||||
this.label1.AutoSize = true;
|
||||
this.label1.Location = new System.Drawing.Point(12, 9);
|
||||
this.label1.Name = "label1";
|
||||
this.label1.Size = new System.Drawing.Size(76, 13);
|
||||
this.label1.TabIndex = 4;
|
||||
this.label1.Text = "Source Image:";
|
||||
//
|
||||
// label2
|
||||
//
|
||||
this.label2.AutoSize = true;
|
||||
this.label2.Location = new System.Drawing.Point(827, 387);
|
||||
this.label2.Name = "label2";
|
||||
this.label2.Size = new System.Drawing.Size(96, 13);
|
||||
this.label2.TabIndex = 5;
|
||||
this.label2.Text = "License Plate ROI:";
|
||||
//
|
||||
// label3
|
||||
//
|
||||
this.label3.AutoSize = true;
|
||||
this.label3.Location = new System.Drawing.Point(827, 65);
|
||||
this.label3.Name = "label3";
|
||||
this.label3.Size = new System.Drawing.Size(124, 13);
|
||||
this.label3.TabIndex = 6;
|
||||
this.label3.Text = "Matched License Plates:";
|
||||
//
|
||||
// openFileDialog
|
||||
//
|
||||
this.openFileDialog.Filter = "Image files (*.jpg, *.jpeg, *.jpe, *.jfif, *.png) | *.jpg; *.jpeg; *.jpe; *.jfif;" +
|
||||
" *.png|All files (*.*)|*.*";
|
||||
//
|
||||
// label4
|
||||
//
|
||||
this.label4.AutoSize = true;
|
||||
this.label4.Location = new System.Drawing.Point(827, 9);
|
||||
this.label4.Name = "label4";
|
||||
this.label4.Size = new System.Drawing.Size(44, 13);
|
||||
this.label4.TabIndex = 7;
|
||||
this.label4.Text = "Region:";
|
||||
//
|
||||
// rbUSA
|
||||
//
|
||||
this.rbUSA.AutoSize = true;
|
||||
this.rbUSA.Checked = true;
|
||||
this.rbUSA.Location = new System.Drawing.Point(878, 7);
|
||||
this.rbUSA.Name = "rbUSA";
|
||||
this.rbUSA.Size = new System.Drawing.Size(40, 17);
|
||||
this.rbUSA.TabIndex = 8;
|
||||
this.rbUSA.TabStop = true;
|
||||
this.rbUSA.Text = "US";
|
||||
this.rbUSA.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// rbEU
|
||||
//
|
||||
this.rbEU.AutoSize = true;
|
||||
this.rbEU.Location = new System.Drawing.Point(924, 7);
|
||||
this.rbEU.Name = "rbEU";
|
||||
this.rbEU.Size = new System.Drawing.Size(40, 17);
|
||||
this.rbEU.TabIndex = 9;
|
||||
this.rbEU.Text = "EU";
|
||||
this.rbEU.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// Form1
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.BackColor = System.Drawing.Color.White;
|
||||
this.ClientSize = new System.Drawing.Size(1128, 538);
|
||||
this.Controls.Add(this.rbEU);
|
||||
this.Controls.Add(this.rbUSA);
|
||||
this.Controls.Add(this.label4);
|
||||
this.Controls.Add(this.label3);
|
||||
this.Controls.Add(this.label2);
|
||||
this.Controls.Add(this.label1);
|
||||
this.Controls.Add(this.lbxPlates);
|
||||
this.Controls.Add(this.picOriginal);
|
||||
this.Controls.Add(this.picLicensePlate);
|
||||
this.Controls.Add(this.btnDetect);
|
||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
|
||||
this.MaximizeBox = false;
|
||||
this.MinimizeBox = false;
|
||||
this.Name = "Form1";
|
||||
this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
|
||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
|
||||
this.Text = "OpenALPR-Net Demo";
|
||||
this.Load += new System.EventHandler(this.Form1_Load);
|
||||
((System.ComponentModel.ISupportInitialize)(this.picLicensePlate)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.picOriginal)).EndInit();
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.Button btnDetect;
|
||||
private System.Windows.Forms.PictureBox picLicensePlate;
|
||||
private System.Windows.Forms.PictureBox picOriginal;
|
||||
private System.Windows.Forms.ListBox lbxPlates;
|
||||
private System.Windows.Forms.Label label1;
|
||||
private System.Windows.Forms.Label label2;
|
||||
private System.Windows.Forms.Label label3;
|
||||
private System.Windows.Forms.OpenFileDialog openFileDialog;
|
||||
private System.Windows.Forms.Label label4;
|
||||
private System.Windows.Forms.RadioButton rbUSA;
|
||||
private System.Windows.Forms.RadioButton rbEU;
|
||||
}
|
||||
}
|
||||
|
186
src/bindings/csharp/openalprnet-windemo/Form1.cs
Normal file
186
src/bindings/csharp/openalprnet-windemo/Form1.cs
Normal file
@@ -0,0 +1,186 @@
|
||||
/*
|
||||
* Copyright (c) 2015 Dr. Masroor Ehsan
|
||||
*
|
||||
* This file is part of OpenAlpr.Net.
|
||||
*
|
||||
* OpenAlpr.Net is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Windows.Forms;
|
||||
using openalprnet;
|
||||
|
||||
namespace openalprnet_windemo
|
||||
{
|
||||
public partial class Form1 : Form
|
||||
{
|
||||
public Form1()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public static string AssemblyDirectory
|
||||
{
|
||||
get
|
||||
{
|
||||
var codeBase = Assembly.GetExecutingAssembly().CodeBase;
|
||||
var uri = new UriBuilder(codeBase);
|
||||
var path = Uri.UnescapeDataString(uri.Path);
|
||||
return Path.GetDirectoryName(path);
|
||||
}
|
||||
}
|
||||
|
||||
public Rectangle boundingRectangle(List<Point> points)
|
||||
{
|
||||
// Add checks here, if necessary, to make sure that points is not null,
|
||||
// and that it contains at least one (or perhaps two?) elements
|
||||
|
||||
var minX = points.Min(p => p.X);
|
||||
var minY = points.Min(p => p.Y);
|
||||
var maxX = points.Max(p => p.X);
|
||||
var maxY = points.Max(p => p.Y);
|
||||
|
||||
return new Rectangle(new Point(minX, minY), new Size(maxX - minX, maxY - minY));
|
||||
}
|
||||
|
||||
private static Image cropImage(Image img, Rectangle cropArea)
|
||||
{
|
||||
var bmpImage = new Bitmap(img);
|
||||
return bmpImage.Clone(cropArea, bmpImage.PixelFormat);
|
||||
}
|
||||
|
||||
public static Bitmap combineImages(List<Image> images)
|
||||
{
|
||||
//read all images into memory
|
||||
Bitmap finalImage = null;
|
||||
|
||||
try
|
||||
{
|
||||
var width = 0;
|
||||
var height = 0;
|
||||
|
||||
foreach (var bmp in images)
|
||||
{
|
||||
width += bmp.Width;
|
||||
height = bmp.Height > height ? bmp.Height : height;
|
||||
}
|
||||
|
||||
//create a bitmap to hold the combined image
|
||||
finalImage = new Bitmap(width, height);
|
||||
|
||||
//get a graphics object from the image so we can draw on it
|
||||
using (var g = Graphics.FromImage(finalImage))
|
||||
{
|
||||
//set background color
|
||||
g.Clear(Color.Black);
|
||||
|
||||
//go through each image and draw it on the final image
|
||||
var offset = 0;
|
||||
foreach (Bitmap image in images)
|
||||
{
|
||||
g.DrawImage(image,
|
||||
new Rectangle(offset, 0, image.Width, image.Height));
|
||||
offset += image.Width;
|
||||
}
|
||||
}
|
||||
|
||||
return finalImage;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (finalImage != null)
|
||||
finalImage.Dispose();
|
||||
|
||||
throw ex;
|
||||
}
|
||||
finally
|
||||
{
|
||||
//clean up memory
|
||||
foreach (var image in images)
|
||||
{
|
||||
image.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void button1_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (openFileDialog.ShowDialog(this) == DialogResult.OK)
|
||||
{
|
||||
processImageFile(openFileDialog.FileName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void processImageFile(string fileName)
|
||||
{
|
||||
resetControls();
|
||||
var region = rbUSA.Checked ? "us" : "eu";
|
||||
String config_file = Path.Combine(AssemblyDirectory, "openalpr.conf");
|
||||
String runtime_data_dir = Path.Combine(AssemblyDirectory, "runtime_data");
|
||||
using (var alpr = new AlprNet(region, config_file, runtime_data_dir))
|
||||
{
|
||||
if (!alpr.isLoaded())
|
||||
{
|
||||
lbxPlates.Items.Add("Error initializing OpenALPR");
|
||||
return;
|
||||
}
|
||||
picOriginal.ImageLocation = fileName;
|
||||
picOriginal.Load();
|
||||
|
||||
var results = alpr.recognize(fileName);
|
||||
|
||||
var images = new List<Image>(results.plates.Count());
|
||||
var i = 1;
|
||||
foreach (var result in results.plates)
|
||||
{
|
||||
var rect = boundingRectangle(result.plate_points);
|
||||
var img = Image.FromFile(fileName);
|
||||
var cropped = cropImage(img, rect);
|
||||
images.Add(cropped);
|
||||
|
||||
lbxPlates.Items.Add("\t\t-- Plate #" + i++ + " --");
|
||||
foreach (var plate in result.topNPlates)
|
||||
{
|
||||
lbxPlates.Items.Add(string.Format(@"{0} {1}% {2}",
|
||||
plate.characters.PadRight(12),
|
||||
plate.overall_confidence.ToString("N1").PadLeft(8),
|
||||
plate.matches_template.ToString().PadLeft(8)));
|
||||
}
|
||||
}
|
||||
|
||||
if (images.Any())
|
||||
{
|
||||
picLicensePlate.Image = combineImages(images);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void resetControls()
|
||||
{
|
||||
picOriginal.Image = null;
|
||||
picLicensePlate.Image = null;
|
||||
lbxPlates.Items.Clear();
|
||||
}
|
||||
|
||||
private void Form1_Load(object sender, EventArgs e)
|
||||
{
|
||||
resetControls();
|
||||
}
|
||||
}
|
||||
}
|
123
src/bindings/csharp/openalprnet-windemo/Form1.resx
Normal file
123
src/bindings/csharp/openalprnet-windemo/Form1.resx
Normal file
@@ -0,0 +1,123 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<metadata name="openFileDialog.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>17, 17</value>
|
||||
</metadata>
|
||||
</root>
|
39
src/bindings/csharp/openalprnet-windemo/Program.cs
Normal file
39
src/bindings/csharp/openalprnet-windemo/Program.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2015 Dr. Masroor Ehsan
|
||||
*
|
||||
* This file is part of OpenAlpr.Net.
|
||||
*
|
||||
* OpenAlpr.Net is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace openalprnet_windemo
|
||||
{
|
||||
static class Program
|
||||
{
|
||||
/// <summary>
|
||||
/// The main entry point for the application.
|
||||
/// </summary>
|
||||
[STAThread]
|
||||
static void Main()
|
||||
{
|
||||
Application.EnableVisualStyles();
|
||||
Application.SetCompatibleTextRenderingDefault(false);
|
||||
Application.Run(new Form1());
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("openalprnet-windemo")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("openalprnet-windemo")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2015")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("b1ab96ca-afe9-497d-9aa0-74ace195dfca")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
63
src/bindings/csharp/openalprnet-windemo/Properties/Resources.Designer.cs
generated
Normal file
63
src/bindings/csharp/openalprnet-windemo/Properties/Resources.Designer.cs
generated
Normal file
@@ -0,0 +1,63 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.34209
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace openalprnet_windemo.Properties {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||
/// </summary>
|
||||
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||
// class via a tool like ResGen or Visual Studio.
|
||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
// with the /str option, or rebuild your VS project.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Resources {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal Resources() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the cached ResourceManager instance used by this class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("openalprnet_windemo.Properties.Resources", typeof(Resources).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the current thread's CurrentUICulture property for all
|
||||
/// resource lookups using this strongly typed resource class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,117 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
26
src/bindings/csharp/openalprnet-windemo/Properties/Settings.Designer.cs
generated
Normal file
26
src/bindings/csharp/openalprnet-windemo/Properties/Settings.Designer.cs
generated
Normal file
@@ -0,0 +1,26 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.34209
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace openalprnet_windemo.Properties {
|
||||
|
||||
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")]
|
||||
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
|
||||
|
||||
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
||||
|
||||
public static Settings Default {
|
||||
get {
|
||||
return defaultInstance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,7 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
|
||||
<Profiles>
|
||||
<Profile Name="(Default)" />
|
||||
</Profiles>
|
||||
<Settings />
|
||||
</SettingsFile>
|
3
src/bindings/csharp/openalprnet-windemo/app.config
Normal file
3
src/bindings/csharp/openalprnet-windemo/app.config
Normal file
@@ -0,0 +1,3 @@
|
||||
<?xml version="1.0"?>
|
||||
<configuration>
|
||||
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup></configuration>
|
@@ -0,0 +1,96 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
|
||||
<ProductVersion>8.0.30703</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{C7863A14-55D2-4389-9072-04AA6E30AAD1}</ProjectGuid>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>openalprnet_windemo</RootNamespace>
|
||||
<AssemblyName>openalprnet-windemo</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<TargetFrameworkProfile>
|
||||
</TargetFrameworkProfile>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Deployment" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Form1.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Form1.Designer.cs">
|
||||
<DependentUpon>Form1.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<EmbeddedResource Include="Form1.resx">
|
||||
<DependentUpon>Form1.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
<Compile Include="Properties\Resources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
<DesignTime>True</DesignTime>
|
||||
</Compile>
|
||||
<None Include="app.config" />
|
||||
<None Include="Properties\Settings.settings">
|
||||
<Generator>SettingsSingleFileGenerator</Generator>
|
||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||
</None>
|
||||
<Compile Include="Properties\Settings.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Settings.settings</DependentUpon>
|
||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\openalpr-net\openalpr-net.vcxproj">
|
||||
<Project>{4044340C-C435-4A1F-8F12-0806C38AE3B6}</Project>
|
||||
<Name>openalpr-net</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
4
src/bindings/java/.gitignore
vendored
Normal file
4
src/bindings/java/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
*.class
|
||||
.idea/
|
||||
*.so
|
||||
*.iml
|
85
src/bindings/java/com_openalpr_jni_Alpr.h
Normal file
85
src/bindings/java/com_openalpr_jni_Alpr.h
Normal file
@@ -0,0 +1,85 @@
|
||||
/* DO NOT EDIT THIS FILE - it is machine generated */
|
||||
#include <jni.h>
|
||||
/* Header for class com_openalpr_jni_Alpr */
|
||||
|
||||
#ifndef _Included_com_openalpr_jni_Alpr
|
||||
#define _Included_com_openalpr_jni_Alpr
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/*
|
||||
* Class: com_openalpr_jni_Alpr
|
||||
* Method: initialize
|
||||
* Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_com_openalpr_jni_Alpr_initialize
|
||||
(JNIEnv *, jobject, jstring, jstring, jstring);
|
||||
|
||||
/*
|
||||
* Class: com_openalpr_jni_Alpr
|
||||
* Method: dispose
|
||||
* Signature: ()V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_com_openalpr_jni_Alpr_dispose
|
||||
(JNIEnv *, jobject);
|
||||
|
||||
/*
|
||||
* Class: com_openalpr_jni_Alpr
|
||||
* Method: is_loaded
|
||||
* Signature: ()Z
|
||||
*/
|
||||
JNIEXPORT jboolean JNICALL Java_com_openalpr_jni_Alpr_is_1loaded
|
||||
(JNIEnv *, jobject);
|
||||
|
||||
/*
|
||||
* Class: com_openalpr_jni_Alpr
|
||||
* Method: native_recognize
|
||||
* Signature: (Ljava/lang/String;)Ljava/lang/String;
|
||||
*/
|
||||
JNIEXPORT jstring JNICALL Java_com_openalpr_jni_Alpr_native_1recognize__Ljava_lang_String_2
|
||||
(JNIEnv *, jobject, jstring);
|
||||
|
||||
/*
|
||||
* Class: com_openalpr_jni_Alpr
|
||||
* Method: native_recognize
|
||||
* Signature: ([B)Ljava/lang/String;
|
||||
*/
|
||||
JNIEXPORT jstring JNICALL Java_com_openalpr_jni_Alpr_native_1recognize___3B
|
||||
(JNIEnv *, jobject, jbyteArray);
|
||||
|
||||
/*
|
||||
* Class: com_openalpr_jni_Alpr
|
||||
* Method: set_default_region
|
||||
* Signature: (Ljava/lang/String;)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_com_openalpr_jni_Alpr_set_1default_1region
|
||||
(JNIEnv *, jobject, jstring);
|
||||
|
||||
/*
|
||||
* Class: com_openalpr_jni_Alpr
|
||||
* Method: detect_region
|
||||
* Signature: (Z)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_com_openalpr_jni_Alpr_detect_1region
|
||||
(JNIEnv *, jobject, jboolean);
|
||||
|
||||
/*
|
||||
* Class: com_openalpr_jni_Alpr
|
||||
* Method: set_top_n
|
||||
* Signature: (I)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_com_openalpr_jni_Alpr_set_1top_1n
|
||||
(JNIEnv *, jobject, jint);
|
||||
|
||||
/*
|
||||
* Class: com_openalpr_jni_Alpr
|
||||
* Method: get_version
|
||||
* Signature: ()Ljava/lang/String;
|
||||
*/
|
||||
JNIEXPORT jstring JNICALL Java_com_openalpr_jni_Alpr_get_1version
|
||||
(JNIEnv *, jobject);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
22
src/bindings/java/make.sh
Executable file
22
src/bindings/java/make.sh
Executable file
@@ -0,0 +1,22 @@
|
||||
#!/bin/sh
|
||||
|
||||
# openbsd 4.9
|
||||
# gcc 4.2.1
|
||||
# openjdk 1.7.0
|
||||
|
||||
OPENALPR_INCLUDE_DIR=/storage/projects/alpr/src/openalpr/
|
||||
OPENALPR_LIB_DIR=/storage/projects/alpr/src/build/openalpr/
|
||||
JAVA_PATH=/usr/lib/jvm/java-1.7.0-openjdk-amd64
|
||||
|
||||
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.:${OPENALPR_LIB_DIR}
|
||||
# Compile java
|
||||
javac -Xlint:unchecked src/com/openalpr/jni/json/*.java src/com/openalpr/jni/*.java src/Main.java
|
||||
|
||||
# Create native header from Alpr java file
|
||||
javah -classpath src com.openalpr.jni.Alpr
|
||||
|
||||
# Compile/link native interface
|
||||
g++ -Wall -L${OPENALPR_LIB_DIR} -I${JAVA_PATH}/include/ -I${OPENALPR_INCLUDE_DIR} -shared -fPIC -o libopenalprjni.so openalprjni.cpp -lopenalpr
|
||||
|
||||
# Test
|
||||
java -classpath src Main
|
120
src/bindings/java/openalprjni.cpp
Normal file
120
src/bindings/java/openalprjni.cpp
Normal file
@@ -0,0 +1,120 @@
|
||||
#include <alpr.h>
|
||||
|
||||
#include "com_openalpr_jni_Alpr.h"
|
||||
|
||||
using namespace alpr;
|
||||
|
||||
bool initialized = false;
|
||||
static Alpr* nativeAlpr;
|
||||
|
||||
JNIEXPORT void JNICALL Java_com_openalpr_jni_Alpr_initialize
|
||||
(JNIEnv *env, jobject thisObj, jstring jcountry, jstring jconfigFile, jstring jruntimeDir)
|
||||
{
|
||||
//printf("Initialize");
|
||||
|
||||
// Convert strings from java to C++ and release resources
|
||||
const char *ccountry = env->GetStringUTFChars(jcountry, NULL);
|
||||
std::string country(ccountry);
|
||||
env->ReleaseStringUTFChars(jcountry, ccountry);
|
||||
|
||||
const char *cconfigFile = env->GetStringUTFChars(jconfigFile, NULL);
|
||||
std::string configFile(cconfigFile);
|
||||
env->ReleaseStringUTFChars(jconfigFile, cconfigFile);
|
||||
|
||||
const char *cruntimeDir = env->GetStringUTFChars(jruntimeDir, NULL);
|
||||
std::string runtimeDir(cruntimeDir);
|
||||
env->ReleaseStringUTFChars(jruntimeDir, cruntimeDir);
|
||||
|
||||
|
||||
nativeAlpr = new alpr::Alpr(country, configFile, runtimeDir);
|
||||
|
||||
initialized = true;
|
||||
return;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_com_openalpr_jni_Alpr_dispose
|
||||
(JNIEnv *env, jobject thisObj)
|
||||
{
|
||||
//printf("Dispose");
|
||||
initialized = false;
|
||||
delete nativeAlpr;
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jboolean JNICALL Java_com_openalpr_jni_Alpr_is_1loaded
|
||||
(JNIEnv *env, jobject thisObj)
|
||||
{
|
||||
//printf("IS LOADED");
|
||||
|
||||
if (!initialized)
|
||||
return false;
|
||||
|
||||
return (jboolean) nativeAlpr->isLoaded();
|
||||
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL Java_com_openalpr_jni_Alpr_native_1recognize__Ljava_lang_String_2
|
||||
(JNIEnv *env, jobject thisObj, jstring jimageFile)
|
||||
{
|
||||
//printf("Recognize file");
|
||||
|
||||
// Convert strings from java to C++ and release resources
|
||||
const char *cimageFile = env->GetStringUTFChars(jimageFile, NULL);
|
||||
std::string imageFile(cimageFile);
|
||||
env->ReleaseStringUTFChars(jimageFile, cimageFile);
|
||||
|
||||
AlprResults results = nativeAlpr->recognize(imageFile);
|
||||
|
||||
std::string json = Alpr::toJson(results);
|
||||
|
||||
return env->NewStringUTF(json.c_str());
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jstring JNICALL Java_com_openalpr_jni_Alpr_native_1recognize___3B
|
||||
(JNIEnv *env, jobject thisObj, jbyteArray jimageBytes)
|
||||
{
|
||||
//printf("Recognize byte array");
|
||||
|
||||
int len = env->GetArrayLength (jimageBytes);
|
||||
unsigned char* buf = new unsigned char[len];
|
||||
env->GetByteArrayRegion (jimageBytes, 0, len, reinterpret_cast<jbyte*>(buf));
|
||||
|
||||
std::vector<char> cvec(buf, buf+len);
|
||||
|
||||
AlprResults results = nativeAlpr->recognize(cvec);
|
||||
std::string json = Alpr::toJson(results);
|
||||
|
||||
return env->NewStringUTF(json.c_str());
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_com_openalpr_jni_Alpr_set_1default_1region
|
||||
(JNIEnv *env, jobject thisObj, jstring jdefault_region)
|
||||
{
|
||||
// Convert strings from java to C++ and release resources
|
||||
const char *cdefault_region = env->GetStringUTFChars(jdefault_region, NULL);
|
||||
std::string default_region(cdefault_region);
|
||||
env->ReleaseStringUTFChars(jdefault_region, cdefault_region);
|
||||
|
||||
nativeAlpr->setDefaultRegion(default_region);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_com_openalpr_jni_Alpr_detect_1region
|
||||
(JNIEnv *env, jobject thisObj, jboolean detect_region)
|
||||
{
|
||||
nativeAlpr->setDetectRegion(detect_region);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_com_openalpr_jni_Alpr_set_1top_1n
|
||||
(JNIEnv *env, jobject thisObj, jint top_n)
|
||||
{
|
||||
nativeAlpr->setTopN(top_n);
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL Java_com_openalpr_jni_Alpr_get_1version
|
||||
(JNIEnv *env, jobject thisObj)
|
||||
{
|
||||
std::string version = nativeAlpr->getVersion();
|
||||
|
||||
return env->NewStringUTF(version.c_str());
|
||||
}
|
46
src/bindings/java/src/Main.java
Normal file
46
src/bindings/java/src/Main.java
Normal file
@@ -0,0 +1,46 @@
|
||||
import com.openalpr.jni.Alpr;
|
||||
import com.openalpr.jni.AlprPlate;
|
||||
import com.openalpr.jni.AlprPlateResult;
|
||||
import com.openalpr.jni.AlprResults;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.Files;
|
||||
|
||||
public class Main {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
Alpr alpr = new Alpr("us", "/etc/openalpr/openalpr.conf", "/usr/share/openalpr/runtime_data/");
|
||||
|
||||
alpr.setTopN(10);
|
||||
alpr.setDefaultRegion("wa");
|
||||
|
||||
// Read an image into a byte array and send it to OpenALPR
|
||||
Path path = Paths.get("/storage/projects/alpr/samples/testing/car1.jpg");
|
||||
byte[] imagedata = Files.readAllBytes(path);
|
||||
|
||||
AlprResults results = alpr.recognize(imagedata);
|
||||
|
||||
System.out.println("OpenALPR Version: " + alpr.getVersion());
|
||||
System.out.println("Image Size: " + results.getImgWidth() + "x" + results.getImgHeight());
|
||||
System.out.println("Processing Time: " + results.getTotalProcessingTimeMs() + " ms");
|
||||
System.out.println("Found " + results.getPlates().size() + " results");
|
||||
|
||||
System.out.format(" %-15s%-8s\n", "Plate Number", "Confidence");
|
||||
for (AlprPlateResult result : results.getPlates())
|
||||
{
|
||||
for (AlprPlate plate : result.getTopNPlates()) {
|
||||
if (plate.isMatchesTemplate())
|
||||
System.out.print(" * ");
|
||||
else
|
||||
System.out.print(" - ");
|
||||
System.out.format("%-15s%-8f\n", plate.getCharacters(), plate.getOverallConfidence());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Make sure to call this to release memory
|
||||
alpr.unload();
|
||||
}
|
||||
}
|
72
src/bindings/java/src/com/openalpr/jni/Alpr.java
Normal file
72
src/bindings/java/src/com/openalpr/jni/Alpr.java
Normal file
@@ -0,0 +1,72 @@
|
||||
package com.openalpr.jni;
|
||||
|
||||
public class Alpr {
|
||||
static {
|
||||
// Load the OpenALPR library at runtime
|
||||
// openalprjni.dll (Windows) or libopenalprjni.so (Linux/Mac)
|
||||
System.loadLibrary("openalprjni");
|
||||
}
|
||||
|
||||
private native void initialize(String country, String configFile, String runtimeDir);
|
||||
private native void dispose();
|
||||
|
||||
private native boolean is_loaded();
|
||||
private native String native_recognize(String imageFile);
|
||||
private native String native_recognize(byte[] imageBytes);
|
||||
|
||||
private native void set_default_region(String region);
|
||||
private native void detect_region(boolean detectRegion);
|
||||
private native void set_top_n(int topN);
|
||||
private native String get_version();
|
||||
|
||||
|
||||
|
||||
public Alpr(String country, String configFile, String runtimeDir)
|
||||
{
|
||||
initialize(country, configFile, runtimeDir);
|
||||
}
|
||||
|
||||
public void unload()
|
||||
{
|
||||
dispose();
|
||||
}
|
||||
|
||||
public boolean isLoaded()
|
||||
{
|
||||
return is_loaded();
|
||||
}
|
||||
|
||||
public AlprResults recognize(String imageFile)
|
||||
{
|
||||
String json = native_recognize(imageFile);
|
||||
return new AlprResults(json);
|
||||
}
|
||||
|
||||
|
||||
public AlprResults recognize(byte[] imageBytes)
|
||||
{
|
||||
String json = native_recognize(imageBytes);
|
||||
return new AlprResults(json);
|
||||
}
|
||||
|
||||
|
||||
public void setTopN(int topN)
|
||||
{
|
||||
set_top_n(topN);
|
||||
}
|
||||
|
||||
public void setDefaultRegion(String region)
|
||||
{
|
||||
set_default_region(region);
|
||||
}
|
||||
|
||||
public void setDetectRegion(boolean detectRegion)
|
||||
{
|
||||
detect_region(detectRegion);
|
||||
}
|
||||
|
||||
public String getVersion()
|
||||
{
|
||||
return get_version();
|
||||
}
|
||||
}
|
23
src/bindings/java/src/com/openalpr/jni/AlprCoordinate.java
Normal file
23
src/bindings/java/src/com/openalpr/jni/AlprCoordinate.java
Normal file
@@ -0,0 +1,23 @@
|
||||
package com.openalpr.jni;
|
||||
|
||||
|
||||
import com.openalpr.jni.json.JSONObject;
|
||||
|
||||
public class AlprCoordinate {
|
||||
private final int x;
|
||||
private final int y;
|
||||
|
||||
AlprCoordinate(JSONObject coordinateObj)
|
||||
{
|
||||
x = coordinateObj.getInt("x");
|
||||
y = coordinateObj.getInt("y");
|
||||
}
|
||||
|
||||
public int getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public int getY() {
|
||||
return y;
|
||||
}
|
||||
}
|
29
src/bindings/java/src/com/openalpr/jni/AlprPlate.java
Normal file
29
src/bindings/java/src/com/openalpr/jni/AlprPlate.java
Normal file
@@ -0,0 +1,29 @@
|
||||
package com.openalpr.jni;
|
||||
|
||||
|
||||
import com.openalpr.jni.json.JSONObject;
|
||||
|
||||
public class AlprPlate {
|
||||
private final String characters;
|
||||
private final float overall_confidence;
|
||||
private final boolean matches_template;
|
||||
|
||||
AlprPlate(JSONObject plateObj)
|
||||
{
|
||||
characters = plateObj.getString("plate");
|
||||
overall_confidence = (float) plateObj.getDouble("confidence");
|
||||
matches_template = plateObj.getInt("matches_template") != 0;
|
||||
}
|
||||
|
||||
public String getCharacters() {
|
||||
return characters;
|
||||
}
|
||||
|
||||
public float getOverallConfidence() {
|
||||
return overall_confidence;
|
||||
}
|
||||
|
||||
public boolean isMatchesTemplate() {
|
||||
return matches_template;
|
||||
}
|
||||
}
|
100
src/bindings/java/src/com/openalpr/jni/AlprPlateResult.java
Normal file
100
src/bindings/java/src/com/openalpr/jni/AlprPlateResult.java
Normal file
@@ -0,0 +1,100 @@
|
||||
package com.openalpr.jni;
|
||||
|
||||
|
||||
import com.openalpr.jni.json.JSONArray;
|
||||
import com.openalpr.jni.json.JSONObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class AlprPlateResult {
|
||||
// The number requested is always >= the topNPlates count
|
||||
private final int requested_topn;
|
||||
|
||||
// the best plate is the topNPlate with the highest confidence
|
||||
private final AlprPlate bestPlate;
|
||||
|
||||
// A list of possible plate number permutations
|
||||
private List<AlprPlate> topNPlates;
|
||||
|
||||
// The processing time for this plate
|
||||
private final float processing_time_ms;
|
||||
|
||||
// the X/Y coordinates of the corners of the plate (clock-wise from top-left)
|
||||
private List<AlprCoordinate> plate_points;
|
||||
|
||||
// The index of the plate if there were multiple plates returned
|
||||
private final int plate_index;
|
||||
|
||||
// When region detection is enabled, this returns the region. Region detection is experimental
|
||||
private final int regionConfidence;
|
||||
private final String region;
|
||||
|
||||
AlprPlateResult(JSONObject plateResult)
|
||||
{
|
||||
requested_topn = plateResult.getInt("requested_topn");
|
||||
|
||||
JSONArray candidatesArray = plateResult.getJSONArray("candidates");
|
||||
|
||||
if (candidatesArray.length() > 0)
|
||||
bestPlate = new AlprPlate((JSONObject) candidatesArray.get(0));
|
||||
else
|
||||
bestPlate = null;
|
||||
|
||||
topNPlates = new ArrayList<AlprPlate>(candidatesArray.length());
|
||||
for (int i = 0; i < candidatesArray.length(); i++)
|
||||
{
|
||||
JSONObject candidateObj = (JSONObject) candidatesArray.get(i);
|
||||
AlprPlate newPlate = new AlprPlate(candidateObj);
|
||||
topNPlates.add(newPlate);
|
||||
}
|
||||
|
||||
JSONArray coordinatesArray = plateResult.getJSONArray("coordinates");
|
||||
plate_points = new ArrayList<AlprCoordinate>(coordinatesArray.length());
|
||||
for (int i = 0; i < coordinatesArray.length(); i++)
|
||||
{
|
||||
JSONObject coordinateObj = (JSONObject) coordinatesArray.get(i);
|
||||
AlprCoordinate coordinate = new AlprCoordinate(coordinateObj);
|
||||
plate_points.add(coordinate);
|
||||
}
|
||||
|
||||
processing_time_ms = (float) plateResult.getDouble("processing_time_ms");
|
||||
plate_index = plateResult.getInt("plate_index");
|
||||
|
||||
regionConfidence = plateResult.getInt("region_confidence");
|
||||
region = plateResult.getString("region");
|
||||
|
||||
}
|
||||
|
||||
public int getRequestedTopn() {
|
||||
return requested_topn;
|
||||
}
|
||||
|
||||
public AlprPlate getBestPlate() {
|
||||
return bestPlate;
|
||||
}
|
||||
|
||||
public List<AlprPlate> getTopNPlates() {
|
||||
return topNPlates;
|
||||
}
|
||||
|
||||
public float getProcessingTimeMs() {
|
||||
return processing_time_ms;
|
||||
}
|
||||
|
||||
public List<AlprCoordinate> getPlatePoints() {
|
||||
return plate_points;
|
||||
}
|
||||
|
||||
public int getPlateIndex() {
|
||||
return plate_index;
|
||||
}
|
||||
|
||||
public int getRegionConfidence() {
|
||||
return regionConfidence;
|
||||
}
|
||||
|
||||
public String getRegion() {
|
||||
return region;
|
||||
}
|
||||
}
|
@@ -0,0 +1,35 @@
|
||||
package com.openalpr.jni;
|
||||
|
||||
import com.openalpr.jni.json.JSONObject;
|
||||
|
||||
|
||||
public class AlprRegionOfInterest {
|
||||
private final int x;
|
||||
private final int y;
|
||||
private final int width;
|
||||
private final int height;
|
||||
|
||||
AlprRegionOfInterest(JSONObject roiObj)
|
||||
{
|
||||
x = roiObj.getInt("x");
|
||||
y = roiObj.getInt("y");
|
||||
width = roiObj.getInt("width");
|
||||
height = roiObj.getInt("height");
|
||||
}
|
||||
|
||||
public int getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public int getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
public int getWidth() {
|
||||
return width;
|
||||
}
|
||||
|
||||
public int getHeight() {
|
||||
return height;
|
||||
}
|
||||
}
|
70
src/bindings/java/src/com/openalpr/jni/AlprResults.java
Normal file
70
src/bindings/java/src/com/openalpr/jni/AlprResults.java
Normal file
@@ -0,0 +1,70 @@
|
||||
package com.openalpr.jni;
|
||||
|
||||
import com.openalpr.jni.json.JSONArray;
|
||||
import com.openalpr.jni.json.JSONObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class AlprResults {
|
||||
private final long epoch_time;
|
||||
private final int img_width;
|
||||
private final int img_height;
|
||||
private final float total_processing_time_ms;
|
||||
|
||||
private List<AlprPlateResult> plates;
|
||||
|
||||
private List<AlprRegionOfInterest> regionsOfInterest;
|
||||
|
||||
AlprResults(String json)
|
||||
{
|
||||
JSONObject jobj = new JSONObject(json);
|
||||
|
||||
epoch_time = jobj.getLong("epoch_time");
|
||||
img_width = jobj.getInt("img_width");
|
||||
img_height = jobj.getInt("img_height");
|
||||
total_processing_time_ms = (float) jobj.getDouble("processing_time_ms");
|
||||
|
||||
JSONArray resultsArray = jobj.getJSONArray("results");
|
||||
plates = new ArrayList<AlprPlateResult>(resultsArray.length());
|
||||
for (int i = 0; i < resultsArray.length(); i++)
|
||||
{
|
||||
JSONObject plateObj = (JSONObject) resultsArray.get(i);
|
||||
AlprPlateResult result = new AlprPlateResult(plateObj);
|
||||
plates.add(result);
|
||||
}
|
||||
|
||||
JSONArray roisArray = jobj.getJSONArray("regions_of_interest");
|
||||
regionsOfInterest = new ArrayList<AlprRegionOfInterest>(roisArray.length());
|
||||
for (int i = 0; i < roisArray.length(); i++)
|
||||
{
|
||||
JSONObject roiObj = (JSONObject) roisArray.get(i);
|
||||
AlprRegionOfInterest roi = new AlprRegionOfInterest(roiObj);
|
||||
regionsOfInterest.add(roi);
|
||||
}
|
||||
}
|
||||
|
||||
public long getEpochTime() {
|
||||
return epoch_time;
|
||||
}
|
||||
|
||||
public int getImgWidth() {
|
||||
return img_width;
|
||||
}
|
||||
|
||||
public int getImgHeight() {
|
||||
return img_height;
|
||||
}
|
||||
|
||||
public float getTotalProcessingTimeMs() {
|
||||
return total_processing_time_ms;
|
||||
}
|
||||
|
||||
public List<AlprPlateResult> getPlates() {
|
||||
return plates;
|
||||
}
|
||||
|
||||
public List<AlprRegionOfInterest> getRegionsOfInterest() {
|
||||
return regionsOfInterest;
|
||||
}
|
||||
}
|
279
src/bindings/java/src/com/openalpr/jni/json/CDL.java
Executable file
279
src/bindings/java/src/com/openalpr/jni/json/CDL.java
Executable file
@@ -0,0 +1,279 @@
|
||||
package com.openalpr.jni.json;
|
||||
|
||||
/*
|
||||
Copyright (c) 2002 JSON.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
The Software shall be used for Good, not Evil.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This provides static methods to convert comma delimited text into a
|
||||
* JSONArray, and to covert a JSONArray into comma delimited text. Comma
|
||||
* delimited text is a very popular format for data interchange. It is
|
||||
* understood by most database, spreadsheet, and organizer programs.
|
||||
* <p>
|
||||
* Each row of text represents a row in a table or a data record. Each row
|
||||
* ends with a NEWLINE character. Each row contains one or more values.
|
||||
* Values are separated by commas. A value can contain any character except
|
||||
* for comma, unless is is wrapped in single quotes or double quotes.
|
||||
* <p>
|
||||
* The first row usually contains the names of the columns.
|
||||
* <p>
|
||||
* A comma delimited list can be converted into a JSONArray of JSONObjects.
|
||||
* The names for the elements in the JSONObjects can be taken from the names
|
||||
* in the first row.
|
||||
* @author JSON.org
|
||||
* @version 2014-05-03
|
||||
*/
|
||||
public class CDL {
|
||||
|
||||
/**
|
||||
* Get the next value. The value can be wrapped in quotes. The value can
|
||||
* be empty.
|
||||
* @param x A JSONTokener of the source text.
|
||||
* @return The value string, or null if empty.
|
||||
* @throws JSONException if the quoted string is badly formed.
|
||||
*/
|
||||
private static String getValue(JSONTokener x) throws JSONException {
|
||||
char c;
|
||||
char q;
|
||||
StringBuffer sb;
|
||||
do {
|
||||
c = x.next();
|
||||
} while (c == ' ' || c == '\t');
|
||||
switch (c) {
|
||||
case 0:
|
||||
return null;
|
||||
case '"':
|
||||
case '\'':
|
||||
q = c;
|
||||
sb = new StringBuffer();
|
||||
for (;;) {
|
||||
c = x.next();
|
||||
if (c == q) {
|
||||
break;
|
||||
}
|
||||
if (c == 0 || c == '\n' || c == '\r') {
|
||||
throw x.syntaxError("Missing close quote '" + q + "'.");
|
||||
}
|
||||
sb.append(c);
|
||||
}
|
||||
return sb.toString();
|
||||
case ',':
|
||||
x.back();
|
||||
return "";
|
||||
default:
|
||||
x.back();
|
||||
return x.nextTo(',');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Produce a JSONArray of strings from a row of comma delimited values.
|
||||
* @param x A JSONTokener of the source text.
|
||||
* @return A JSONArray of strings.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static JSONArray rowToJSONArray(JSONTokener x) throws JSONException {
|
||||
JSONArray ja = new JSONArray();
|
||||
for (;;) {
|
||||
String value = getValue(x);
|
||||
char c = x.next();
|
||||
if (value == null ||
|
||||
(ja.length() == 0 && value.length() == 0 && c != ',')) {
|
||||
return null;
|
||||
}
|
||||
ja.put(value);
|
||||
for (;;) {
|
||||
if (c == ',') {
|
||||
break;
|
||||
}
|
||||
if (c != ' ') {
|
||||
if (c == '\n' || c == '\r' || c == 0) {
|
||||
return ja;
|
||||
}
|
||||
throw x.syntaxError("Bad character '" + c + "' (" +
|
||||
(int)c + ").");
|
||||
}
|
||||
c = x.next();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Produce a JSONObject from a row of comma delimited text, using a
|
||||
* parallel JSONArray of strings to provides the names of the elements.
|
||||
* @param names A JSONArray of names. This is commonly obtained from the
|
||||
* first row of a comma delimited text file using the rowToJSONArray
|
||||
* method.
|
||||
* @param x A JSONTokener of the source text.
|
||||
* @return A JSONObject combining the names and values.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static JSONObject rowToJSONObject(JSONArray names, JSONTokener x)
|
||||
throws JSONException {
|
||||
JSONArray ja = rowToJSONArray(x);
|
||||
return ja != null ? ja.toJSONObject(names) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Produce a comma delimited text row from a JSONArray. Values containing
|
||||
* the comma character will be quoted. Troublesome characters may be
|
||||
* removed.
|
||||
* @param ja A JSONArray of strings.
|
||||
* @return A string ending in NEWLINE.
|
||||
*/
|
||||
public static String rowToString(JSONArray ja) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < ja.length(); i += 1) {
|
||||
if (i > 0) {
|
||||
sb.append(',');
|
||||
}
|
||||
Object object = ja.opt(i);
|
||||
if (object != null) {
|
||||
String string = object.toString();
|
||||
if (string.length() > 0 && (string.indexOf(',') >= 0 ||
|
||||
string.indexOf('\n') >= 0 || string.indexOf('\r') >= 0 ||
|
||||
string.indexOf(0) >= 0 || string.charAt(0) == '"')) {
|
||||
sb.append('"');
|
||||
int length = string.length();
|
||||
for (int j = 0; j < length; j += 1) {
|
||||
char c = string.charAt(j);
|
||||
if (c >= ' ' && c != '"') {
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
sb.append('"');
|
||||
} else {
|
||||
sb.append(string);
|
||||
}
|
||||
}
|
||||
}
|
||||
sb.append('\n');
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Produce a JSONArray of JSONObjects from a comma delimited text string,
|
||||
* using the first row as a source of names.
|
||||
* @param string The comma delimited text.
|
||||
* @return A JSONArray of JSONObjects.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static JSONArray toJSONArray(String string) throws JSONException {
|
||||
return toJSONArray(new JSONTokener(string));
|
||||
}
|
||||
|
||||
/**
|
||||
* Produce a JSONArray of JSONObjects from a comma delimited text string,
|
||||
* using the first row as a source of names.
|
||||
* @param x The JSONTokener containing the comma delimited text.
|
||||
* @return A JSONArray of JSONObjects.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static JSONArray toJSONArray(JSONTokener x) throws JSONException {
|
||||
return toJSONArray(rowToJSONArray(x), x);
|
||||
}
|
||||
|
||||
/**
|
||||
* Produce a JSONArray of JSONObjects from a comma delimited text string
|
||||
* using a supplied JSONArray as the source of element names.
|
||||
* @param names A JSONArray of strings.
|
||||
* @param string The comma delimited text.
|
||||
* @return A JSONArray of JSONObjects.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static JSONArray toJSONArray(JSONArray names, String string)
|
||||
throws JSONException {
|
||||
return toJSONArray(names, new JSONTokener(string));
|
||||
}
|
||||
|
||||
/**
|
||||
* Produce a JSONArray of JSONObjects from a comma delimited text string
|
||||
* using a supplied JSONArray as the source of element names.
|
||||
* @param names A JSONArray of strings.
|
||||
* @param x A JSONTokener of the source text.
|
||||
* @return A JSONArray of JSONObjects.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static JSONArray toJSONArray(JSONArray names, JSONTokener x)
|
||||
throws JSONException {
|
||||
if (names == null || names.length() == 0) {
|
||||
return null;
|
||||
}
|
||||
JSONArray ja = new JSONArray();
|
||||
for (;;) {
|
||||
JSONObject jo = rowToJSONObject(names, x);
|
||||
if (jo == null) {
|
||||
break;
|
||||
}
|
||||
ja.put(jo);
|
||||
}
|
||||
if (ja.length() == 0) {
|
||||
return null;
|
||||
}
|
||||
return ja;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Produce a comma delimited text from a JSONArray of JSONObjects. The
|
||||
* first row will be a list of names obtained by inspecting the first
|
||||
* JSONObject.
|
||||
* @param ja A JSONArray of JSONObjects.
|
||||
* @return A comma delimited text.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static String toString(JSONArray ja) throws JSONException {
|
||||
JSONObject jo = ja.optJSONObject(0);
|
||||
if (jo != null) {
|
||||
JSONArray names = jo.names();
|
||||
if (names != null) {
|
||||
return rowToString(names) + toString(names, ja);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Produce a comma delimited text from a JSONArray of JSONObjects using
|
||||
* a provided list of names. The list of names is not included in the
|
||||
* output.
|
||||
* @param names A JSONArray of strings.
|
||||
* @param ja A JSONArray of JSONObjects.
|
||||
* @return A comma delimited text.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static String toString(JSONArray names, JSONArray ja)
|
||||
throws JSONException {
|
||||
if (names == null || names.length() == 0) {
|
||||
return null;
|
||||
}
|
||||
StringBuffer sb = new StringBuffer();
|
||||
for (int i = 0; i < ja.length(); i += 1) {
|
||||
JSONObject jo = ja.optJSONObject(i);
|
||||
if (jo != null) {
|
||||
sb.append(rowToString(jo.toJSONArray(names)));
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
169
src/bindings/java/src/com/openalpr/jni/json/Cookie.java
Executable file
169
src/bindings/java/src/com/openalpr/jni/json/Cookie.java
Executable file
@@ -0,0 +1,169 @@
|
||||
package com.openalpr.jni.json;
|
||||
|
||||
/*
|
||||
Copyright (c) 2002 JSON.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
The Software shall be used for Good, not Evil.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Convert a web browser cookie specification to a JSONObject and back.
|
||||
* JSON and Cookies are both notations for name/value pairs.
|
||||
* @author JSON.org
|
||||
* @version 2014-05-03
|
||||
*/
|
||||
public class Cookie {
|
||||
|
||||
/**
|
||||
* Produce a copy of a string in which the characters '+', '%', '=', ';'
|
||||
* and control characters are replaced with "%hh". This is a gentle form
|
||||
* of URL encoding, attempting to cause as little distortion to the
|
||||
* string as possible. The characters '=' and ';' are meta characters in
|
||||
* cookies. By convention, they are escaped using the URL-encoding. This is
|
||||
* only a convention, not a standard. Often, cookies are expected to have
|
||||
* encoded values. We encode '=' and ';' because we must. We encode '%' and
|
||||
* '+' because they are meta characters in URL encoding.
|
||||
* @param string The source string.
|
||||
* @return The escaped result.
|
||||
*/
|
||||
public static String escape(String string) {
|
||||
char c;
|
||||
String s = string.trim();
|
||||
int length = s.length();
|
||||
StringBuilder sb = new StringBuilder(length);
|
||||
for (int i = 0; i < length; i += 1) {
|
||||
c = s.charAt(i);
|
||||
if (c < ' ' || c == '+' || c == '%' || c == '=' || c == ';') {
|
||||
sb.append('%');
|
||||
sb.append(Character.forDigit((char)((c >>> 4) & 0x0f), 16));
|
||||
sb.append(Character.forDigit((char)(c & 0x0f), 16));
|
||||
} else {
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert a cookie specification string into a JSONObject. The string
|
||||
* will contain a name value pair separated by '='. The name and the value
|
||||
* will be unescaped, possibly converting '+' and '%' sequences. The
|
||||
* cookie properties may follow, separated by ';', also represented as
|
||||
* name=value (except the secure property, which does not have a value).
|
||||
* The name will be stored under the key "name", and the value will be
|
||||
* stored under the key "value". This method does not do checking or
|
||||
* validation of the parameters. It only converts the cookie string into
|
||||
* a JSONObject.
|
||||
* @param string The cookie specification string.
|
||||
* @return A JSONObject containing "name", "value", and possibly other
|
||||
* members.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static JSONObject toJSONObject(String string) throws JSONException {
|
||||
String name;
|
||||
JSONObject jo = new JSONObject();
|
||||
Object value;
|
||||
JSONTokener x = new JSONTokener(string);
|
||||
jo.put("name", x.nextTo('='));
|
||||
x.next('=');
|
||||
jo.put("value", x.nextTo(';'));
|
||||
x.next();
|
||||
while (x.more()) {
|
||||
name = unescape(x.nextTo("=;"));
|
||||
if (x.next() != '=') {
|
||||
if (name.equals("secure")) {
|
||||
value = Boolean.TRUE;
|
||||
} else {
|
||||
throw x.syntaxError("Missing '=' in cookie parameter.");
|
||||
}
|
||||
} else {
|
||||
value = unescape(x.nextTo(';'));
|
||||
x.next();
|
||||
}
|
||||
jo.put(name, value);
|
||||
}
|
||||
return jo;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert a JSONObject into a cookie specification string. The JSONObject
|
||||
* must contain "name" and "value" members.
|
||||
* If the JSONObject contains "expires", "domain", "path", or "secure"
|
||||
* members, they will be appended to the cookie specification string.
|
||||
* All other members are ignored.
|
||||
* @param jo A JSONObject
|
||||
* @return A cookie specification string
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static String toString(JSONObject jo) throws JSONException {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append(escape(jo.getString("name")));
|
||||
sb.append("=");
|
||||
sb.append(escape(jo.getString("value")));
|
||||
if (jo.has("expires")) {
|
||||
sb.append(";expires=");
|
||||
sb.append(jo.getString("expires"));
|
||||
}
|
||||
if (jo.has("domain")) {
|
||||
sb.append(";domain=");
|
||||
sb.append(escape(jo.getString("domain")));
|
||||
}
|
||||
if (jo.has("path")) {
|
||||
sb.append(";path=");
|
||||
sb.append(escape(jo.getString("path")));
|
||||
}
|
||||
if (jo.optBoolean("secure")) {
|
||||
sb.append(";secure");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert <code>%</code><i>hh</i> sequences to single characters, and
|
||||
* convert plus to space.
|
||||
* @param string A string that may contain
|
||||
* <code>+</code> <small>(plus)</small> and
|
||||
* <code>%</code><i>hh</i> sequences.
|
||||
* @return The unescaped string.
|
||||
*/
|
||||
public static String unescape(String string) {
|
||||
int length = string.length();
|
||||
StringBuilder sb = new StringBuilder(length);
|
||||
for (int i = 0; i < length; ++i) {
|
||||
char c = string.charAt(i);
|
||||
if (c == '+') {
|
||||
c = ' ';
|
||||
} else if (c == '%' && i + 2 < length) {
|
||||
int d = JSONTokener.dehexchar(string.charAt(i + 1));
|
||||
int e = JSONTokener.dehexchar(string.charAt(i + 2));
|
||||
if (d >= 0 && e >= 0) {
|
||||
c = (char)(d * 16 + e);
|
||||
i += 2;
|
||||
}
|
||||
}
|
||||
sb.append(c);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
89
src/bindings/java/src/com/openalpr/jni/json/CookieList.java
Executable file
89
src/bindings/java/src/com/openalpr/jni/json/CookieList.java
Executable file
@@ -0,0 +1,89 @@
|
||||
package com.openalpr.jni.json;
|
||||
|
||||
/*
|
||||
Copyright (c) 2002 JSON.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
The Software shall be used for Good, not Evil.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* Convert a web browser cookie list string to a JSONObject and back.
|
||||
* @author JSON.org
|
||||
* @version 2014-05-03
|
||||
*/
|
||||
public class CookieList {
|
||||
|
||||
/**
|
||||
* Convert a cookie list into a JSONObject. A cookie list is a sequence
|
||||
* of name/value pairs. The names are separated from the values by '='.
|
||||
* The pairs are separated by ';'. The names and the values
|
||||
* will be unescaped, possibly converting '+' and '%' sequences.
|
||||
*
|
||||
* To add a cookie to a cooklist,
|
||||
* cookielistJSONObject.put(cookieJSONObject.getString("name"),
|
||||
* cookieJSONObject.getString("value"));
|
||||
* @param string A cookie list string
|
||||
* @return A JSONObject
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static JSONObject toJSONObject(String string) throws JSONException {
|
||||
JSONObject jo = new JSONObject();
|
||||
JSONTokener x = new JSONTokener(string);
|
||||
while (x.more()) {
|
||||
String name = Cookie.unescape(x.nextTo('='));
|
||||
x.next('=');
|
||||
jo.put(name, Cookie.unescape(x.nextTo(';')));
|
||||
x.next();
|
||||
}
|
||||
return jo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a JSONObject into a cookie list. A cookie list is a sequence
|
||||
* of name/value pairs. The names are separated from the values by '='.
|
||||
* The pairs are separated by ';'. The characters '%', '+', '=', and ';'
|
||||
* in the names and values are replaced by "%hh".
|
||||
* @param jo A JSONObject
|
||||
* @return A cookie list string
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static String toString(JSONObject jo) throws JSONException {
|
||||
boolean b = false;
|
||||
Iterator<String> keys = jo.keys();
|
||||
String string;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
while (keys.hasNext()) {
|
||||
string = keys.next();
|
||||
if (!jo.isNull(string)) {
|
||||
if (b) {
|
||||
sb.append(';');
|
||||
}
|
||||
sb.append(Cookie.escape(string));
|
||||
sb.append("=");
|
||||
sb.append(Cookie.escape(jo.getString(string)));
|
||||
b = true;
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
163
src/bindings/java/src/com/openalpr/jni/json/HTTP.java
Executable file
163
src/bindings/java/src/com/openalpr/jni/json/HTTP.java
Executable file
@@ -0,0 +1,163 @@
|
||||
package com.openalpr.jni.json;
|
||||
|
||||
/*
|
||||
Copyright (c) 2002 JSON.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
The Software shall be used for Good, not Evil.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* Convert an HTTP header to a JSONObject and back.
|
||||
* @author JSON.org
|
||||
* @version 2014-05-03
|
||||
*/
|
||||
public class HTTP {
|
||||
|
||||
/** Carriage return/line feed. */
|
||||
public static final String CRLF = "\r\n";
|
||||
|
||||
/**
|
||||
* Convert an HTTP header string into a JSONObject. It can be a request
|
||||
* header or a response header. A request header will contain
|
||||
* <pre>{
|
||||
* Method: "POST" (for example),
|
||||
* "Request-URI": "/" (for example),
|
||||
* "HTTP-Version": "HTTP/1.1" (for example)
|
||||
* }</pre>
|
||||
* A response header will contain
|
||||
* <pre>{
|
||||
* "HTTP-Version": "HTTP/1.1" (for example),
|
||||
* "Status-Code": "200" (for example),
|
||||
* "Reason-Phrase": "OK" (for example)
|
||||
* }</pre>
|
||||
* In addition, the other parameters in the header will be captured, using
|
||||
* the HTTP field names as JSON names, so that <pre>
|
||||
* Date: Sun, 26 May 2002 18:06:04 GMT
|
||||
* Cookie: Q=q2=PPEAsg--; B=677gi6ouf29bn&b=2&f=s
|
||||
* Cache-Control: no-cache</pre>
|
||||
* become
|
||||
* <pre>{...
|
||||
* Date: "Sun, 26 May 2002 18:06:04 GMT",
|
||||
* Cookie: "Q=q2=PPEAsg--; B=677gi6ouf29bn&b=2&f=s",
|
||||
* "Cache-Control": "no-cache",
|
||||
* ...}</pre>
|
||||
* It does no further checking or conversion. It does not parse dates.
|
||||
* It does not do '%' transforms on URLs.
|
||||
* @param string An HTTP header string.
|
||||
* @return A JSONObject containing the elements and attributes
|
||||
* of the XML string.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static JSONObject toJSONObject(String string) throws JSONException {
|
||||
JSONObject jo = new JSONObject();
|
||||
HTTPTokener x = new HTTPTokener(string);
|
||||
String token;
|
||||
|
||||
token = x.nextToken();
|
||||
if (token.toUpperCase().startsWith("HTTP")) {
|
||||
|
||||
// Response
|
||||
|
||||
jo.put("HTTP-Version", token);
|
||||
jo.put("Status-Code", x.nextToken());
|
||||
jo.put("Reason-Phrase", x.nextTo('\0'));
|
||||
x.next();
|
||||
|
||||
} else {
|
||||
|
||||
// Request
|
||||
|
||||
jo.put("Method", token);
|
||||
jo.put("Request-URI", x.nextToken());
|
||||
jo.put("HTTP-Version", x.nextToken());
|
||||
}
|
||||
|
||||
// Fields
|
||||
|
||||
while (x.more()) {
|
||||
String name = x.nextTo(':');
|
||||
x.next(':');
|
||||
jo.put(name, x.nextTo('\0'));
|
||||
x.next();
|
||||
}
|
||||
return jo;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert a JSONObject into an HTTP header. A request header must contain
|
||||
* <pre>{
|
||||
* Method: "POST" (for example),
|
||||
* "Request-URI": "/" (for example),
|
||||
* "HTTP-Version": "HTTP/1.1" (for example)
|
||||
* }</pre>
|
||||
* A response header must contain
|
||||
* <pre>{
|
||||
* "HTTP-Version": "HTTP/1.1" (for example),
|
||||
* "Status-Code": "200" (for example),
|
||||
* "Reason-Phrase": "OK" (for example)
|
||||
* }</pre>
|
||||
* Any other members of the JSONObject will be output as HTTP fields.
|
||||
* The result will end with two CRLF pairs.
|
||||
* @param jo A JSONObject
|
||||
* @return An HTTP header string.
|
||||
* @throws JSONException if the object does not contain enough
|
||||
* information.
|
||||
*/
|
||||
public static String toString(JSONObject jo) throws JSONException {
|
||||
Iterator<String> keys = jo.keys();
|
||||
String string;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (jo.has("Status-Code") && jo.has("Reason-Phrase")) {
|
||||
sb.append(jo.getString("HTTP-Version"));
|
||||
sb.append(' ');
|
||||
sb.append(jo.getString("Status-Code"));
|
||||
sb.append(' ');
|
||||
sb.append(jo.getString("Reason-Phrase"));
|
||||
} else if (jo.has("Method") && jo.has("Request-URI")) {
|
||||
sb.append(jo.getString("Method"));
|
||||
sb.append(' ');
|
||||
sb.append('"');
|
||||
sb.append(jo.getString("Request-URI"));
|
||||
sb.append('"');
|
||||
sb.append(' ');
|
||||
sb.append(jo.getString("HTTP-Version"));
|
||||
} else {
|
||||
throw new JSONException("Not enough material for an HTTP header.");
|
||||
}
|
||||
sb.append(CRLF);
|
||||
while (keys.hasNext()) {
|
||||
string = keys.next();
|
||||
if (!"HTTP-Version".equals(string) && !"Status-Code".equals(string) &&
|
||||
!"Reason-Phrase".equals(string) && !"Method".equals(string) &&
|
||||
!"Request-URI".equals(string) && !jo.isNull(string)) {
|
||||
sb.append(string);
|
||||
sb.append(": ");
|
||||
sb.append(jo.getString(string));
|
||||
sb.append(CRLF);
|
||||
}
|
||||
}
|
||||
sb.append(CRLF);
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
77
src/bindings/java/src/com/openalpr/jni/json/HTTPTokener.java
Executable file
77
src/bindings/java/src/com/openalpr/jni/json/HTTPTokener.java
Executable file
@@ -0,0 +1,77 @@
|
||||
package com.openalpr.jni.json;
|
||||
|
||||
/*
|
||||
Copyright (c) 2002 JSON.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
The Software shall be used for Good, not Evil.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The HTTPTokener extends the JSONTokener to provide additional methods
|
||||
* for the parsing of HTTP headers.
|
||||
* @author JSON.org
|
||||
* @version 2014-05-03
|
||||
*/
|
||||
public class HTTPTokener extends JSONTokener {
|
||||
|
||||
/**
|
||||
* Construct an HTTPTokener from a string.
|
||||
* @param string A source string.
|
||||
*/
|
||||
public HTTPTokener(String string) {
|
||||
super(string);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the next token or string. This is used in parsing HTTP headers.
|
||||
* @throws JSONException
|
||||
* @return A String.
|
||||
*/
|
||||
public String nextToken() throws JSONException {
|
||||
char c;
|
||||
char q;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
do {
|
||||
c = next();
|
||||
} while (Character.isWhitespace(c));
|
||||
if (c == '"' || c == '\'') {
|
||||
q = c;
|
||||
for (;;) {
|
||||
c = next();
|
||||
if (c < ' ') {
|
||||
throw syntaxError("Unterminated string.");
|
||||
}
|
||||
if (c == q) {
|
||||
return sb.toString();
|
||||
}
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
for (;;) {
|
||||
if (c == 0 || Character.isWhitespace(c)) {
|
||||
return sb.toString();
|
||||
}
|
||||
sb.append(c);
|
||||
c = next();
|
||||
}
|
||||
}
|
||||
}
|
977
src/bindings/java/src/com/openalpr/jni/json/JSONArray.java
Normal file
977
src/bindings/java/src/com/openalpr/jni/json/JSONArray.java
Normal file
@@ -0,0 +1,977 @@
|
||||
package com.openalpr.jni.json;
|
||||
|
||||
/*
|
||||
Copyright (c) 2002 JSON.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
The Software shall be used for Good, not Evil.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A JSONArray is an ordered sequence of values. Its external text form is a
|
||||
* string wrapped in square brackets with commas separating the values. The
|
||||
* internal form is an object having <code>get</code> and <code>opt</code>
|
||||
* methods for accessing the values by index, and <code>put</code> methods for
|
||||
* adding or replacing values. The values can be any of these types:
|
||||
* <code>Boolean</code>, <code>JSONArray</code>, <code>JSONObject</code>,
|
||||
* <code>Number</code>, <code>String</code>, or the
|
||||
* <code>JSONObject.NULL object</code>.
|
||||
* <p>
|
||||
* The constructor can convert a JSON text into a Java object. The
|
||||
* <code>toString</code> method converts to JSON text.
|
||||
* <p>
|
||||
* A <code>get</code> method returns a value if one can be found, and throws an
|
||||
* exception if one cannot be found. An <code>opt</code> method returns a
|
||||
* default value instead of throwing an exception, and so is useful for
|
||||
* obtaining optional values.
|
||||
* <p>
|
||||
* The generic <code>get()</code> and <code>opt()</code> methods return an
|
||||
* object which you can cast or query for type. There are also typed
|
||||
* <code>get</code> and <code>opt</code> methods that do type checking and type
|
||||
* coercion for you.
|
||||
* <p>
|
||||
* The texts produced by the <code>toString</code> methods strictly conform to
|
||||
* JSON syntax rules. The constructors are more forgiving in the texts they will
|
||||
* accept:
|
||||
* <ul>
|
||||
* <li>An extra <code>,</code> <small>(comma)</small> may appear just
|
||||
* before the closing bracket.</li>
|
||||
* <li>The <code>null</code> value will be inserted when there is <code>,</code>
|
||||
* <small>(comma)</small> elision.</li>
|
||||
* <li>Strings may be quoted with <code>'</code> <small>(single
|
||||
* quote)</small>.</li>
|
||||
* <li>Strings do not need to be quoted at all if they do not begin with a quote
|
||||
* or single quote, and if they do not contain leading or trailing spaces, and
|
||||
* if they do not contain any of these characters:
|
||||
* <code>{ } [ ] / \ : , #</code> and if they do not look like numbers and
|
||||
* if they are not the reserved words <code>true</code>, <code>false</code>, or
|
||||
* <code>null</code>.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author JSON.org
|
||||
* @version 2014-05-03
|
||||
*/
|
||||
public class JSONArray {
|
||||
|
||||
/**
|
||||
* The arrayList where the JSONArray's properties are kept.
|
||||
*/
|
||||
private final ArrayList<Object> myArrayList;
|
||||
|
||||
/**
|
||||
* Construct an empty JSONArray.
|
||||
*/
|
||||
public JSONArray() {
|
||||
this.myArrayList = new ArrayList<Object>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a JSONArray from a JSONTokener.
|
||||
*
|
||||
* @param x
|
||||
* A JSONTokener
|
||||
* @throws JSONException
|
||||
* If there is a syntax error.
|
||||
*/
|
||||
public JSONArray(JSONTokener x) throws JSONException {
|
||||
this();
|
||||
if (x.nextClean() != '[') {
|
||||
throw x.syntaxError("A JSONArray text must start with '['");
|
||||
}
|
||||
if (x.nextClean() != ']') {
|
||||
x.back();
|
||||
for (;;) {
|
||||
if (x.nextClean() == ',') {
|
||||
x.back();
|
||||
this.myArrayList.add(JSONObject.NULL);
|
||||
} else {
|
||||
x.back();
|
||||
this.myArrayList.add(x.nextValue());
|
||||
}
|
||||
switch (x.nextClean()) {
|
||||
case ',':
|
||||
if (x.nextClean() == ']') {
|
||||
return;
|
||||
}
|
||||
x.back();
|
||||
break;
|
||||
case ']':
|
||||
return;
|
||||
default:
|
||||
throw x.syntaxError("Expected a ',' or ']'");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a JSONArray from a source JSON text.
|
||||
*
|
||||
* @param source
|
||||
* A string that begins with <code>[</code> <small>(left
|
||||
* bracket)</small> and ends with <code>]</code>
|
||||
* <small>(right bracket)</small>.
|
||||
* @throws JSONException
|
||||
* If there is a syntax error.
|
||||
*/
|
||||
public JSONArray(String source) throws JSONException {
|
||||
this(new JSONTokener(source));
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a JSONArray from a Collection.
|
||||
*
|
||||
* @param collection
|
||||
* A Collection.
|
||||
*/
|
||||
public JSONArray(Collection<Object> collection) {
|
||||
this.myArrayList = new ArrayList<Object>();
|
||||
if (collection != null) {
|
||||
Iterator<Object> iter = collection.iterator();
|
||||
while (iter.hasNext()) {
|
||||
this.myArrayList.add(JSONObject.wrap(iter.next()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a JSONArray from an array
|
||||
*
|
||||
* @throws JSONException
|
||||
* If not an array.
|
||||
*/
|
||||
public JSONArray(Object array) throws JSONException {
|
||||
this();
|
||||
if (array.getClass().isArray()) {
|
||||
int length = Array.getLength(array);
|
||||
for (int i = 0; i < length; i += 1) {
|
||||
this.put(JSONObject.wrap(Array.get(array, i)));
|
||||
}
|
||||
} else {
|
||||
throw new JSONException(
|
||||
"JSONArray initial value should be a string or collection or array.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the object value associated with an index.
|
||||
*
|
||||
* @param index
|
||||
* The index must be between 0 and length() - 1.
|
||||
* @return An object value.
|
||||
* @throws JSONException
|
||||
* If there is no value for the index.
|
||||
*/
|
||||
public Object get(int index) throws JSONException {
|
||||
Object object = this.opt(index);
|
||||
if (object == null) {
|
||||
throw new JSONException("JSONArray[" + index + "] not found.");
|
||||
}
|
||||
return object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the boolean value associated with an index. The string values "true"
|
||||
* and "false" are converted to boolean.
|
||||
*
|
||||
* @param index
|
||||
* The index must be between 0 and length() - 1.
|
||||
* @return The truth.
|
||||
* @throws JSONException
|
||||
* If there is no value for the index or if the value is not
|
||||
* convertible to boolean.
|
||||
*/
|
||||
public boolean getBoolean(int index) throws JSONException {
|
||||
Object object = this.get(index);
|
||||
if (object.equals(Boolean.FALSE)
|
||||
|| (object instanceof String && ((String) object)
|
||||
.equalsIgnoreCase("false"))) {
|
||||
return false;
|
||||
} else if (object.equals(Boolean.TRUE)
|
||||
|| (object instanceof String && ((String) object)
|
||||
.equalsIgnoreCase("true"))) {
|
||||
return true;
|
||||
}
|
||||
throw new JSONException("JSONArray[" + index + "] is not a boolean.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the double value associated with an index.
|
||||
*
|
||||
* @param index
|
||||
* The index must be between 0 and length() - 1.
|
||||
* @return The value.
|
||||
* @throws JSONException
|
||||
* If the key is not found or if the value cannot be converted
|
||||
* to a number.
|
||||
*/
|
||||
public double getDouble(int index) throws JSONException {
|
||||
Object object = this.get(index);
|
||||
try {
|
||||
return object instanceof Number ? ((Number) object).doubleValue()
|
||||
: Double.parseDouble((String) object);
|
||||
} catch (Exception e) {
|
||||
throw new JSONException("JSONArray[" + index + "] is not a number.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the int value associated with an index.
|
||||
*
|
||||
* @param index
|
||||
* The index must be between 0 and length() - 1.
|
||||
* @return The value.
|
||||
* @throws JSONException
|
||||
* If the key is not found or if the value is not a number.
|
||||
*/
|
||||
public int getInt(int index) throws JSONException {
|
||||
Object object = this.get(index);
|
||||
try {
|
||||
return object instanceof Number ? ((Number) object).intValue()
|
||||
: Integer.parseInt((String) object);
|
||||
} catch (Exception e) {
|
||||
throw new JSONException("JSONArray[" + index + "] is not a number.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the JSONArray associated with an index.
|
||||
*
|
||||
* @param index
|
||||
* The index must be between 0 and length() - 1.
|
||||
* @return A JSONArray value.
|
||||
* @throws JSONException
|
||||
* If there is no value for the index. or if the value is not a
|
||||
* JSONArray
|
||||
*/
|
||||
public JSONArray getJSONArray(int index) throws JSONException {
|
||||
Object object = this.get(index);
|
||||
if (object instanceof JSONArray) {
|
||||
return (JSONArray) object;
|
||||
}
|
||||
throw new JSONException("JSONArray[" + index + "] is not a JSONArray.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the JSONObject associated with an index.
|
||||
*
|
||||
* @param index
|
||||
* subscript
|
||||
* @return A JSONObject value.
|
||||
* @throws JSONException
|
||||
* If there is no value for the index or if the value is not a
|
||||
* JSONObject
|
||||
*/
|
||||
public JSONObject getJSONObject(int index) throws JSONException {
|
||||
Object object = this.get(index);
|
||||
if (object instanceof JSONObject) {
|
||||
return (JSONObject) object;
|
||||
}
|
||||
throw new JSONException("JSONArray[" + index + "] is not a JSONObject.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the long value associated with an index.
|
||||
*
|
||||
* @param index
|
||||
* The index must be between 0 and length() - 1.
|
||||
* @return The value.
|
||||
* @throws JSONException
|
||||
* If the key is not found or if the value cannot be converted
|
||||
* to a number.
|
||||
*/
|
||||
public long getLong(int index) throws JSONException {
|
||||
Object object = this.get(index);
|
||||
try {
|
||||
return object instanceof Number ? ((Number) object).longValue()
|
||||
: Long.parseLong((String) object);
|
||||
} catch (Exception e) {
|
||||
throw new JSONException("JSONArray[" + index + "] is not a number.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the string associated with an index.
|
||||
*
|
||||
* @param index
|
||||
* The index must be between 0 and length() - 1.
|
||||
* @return A string value.
|
||||
* @throws JSONException
|
||||
* If there is no string value for the index.
|
||||
*/
|
||||
public String getString(int index) throws JSONException {
|
||||
Object object = this.get(index);
|
||||
if (object instanceof String) {
|
||||
return (String) object;
|
||||
}
|
||||
throw new JSONException("JSONArray[" + index + "] not a string.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the value is null.
|
||||
*
|
||||
* @param index
|
||||
* The index must be between 0 and length() - 1.
|
||||
* @return true if the value at the index is null, or if there is no value.
|
||||
*/
|
||||
public boolean isNull(int index) {
|
||||
return JSONObject.NULL.equals(this.opt(index));
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a string from the contents of this JSONArray. The
|
||||
* <code>separator</code> string is inserted between each element. Warning:
|
||||
* This method assumes that the data structure is acyclical.
|
||||
*
|
||||
* @param separator
|
||||
* A string that will be inserted between the elements.
|
||||
* @return a string.
|
||||
* @throws JSONException
|
||||
* If the array contains an invalid number.
|
||||
*/
|
||||
public String join(String separator) throws JSONException {
|
||||
int len = this.length();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
for (int i = 0; i < len; i += 1) {
|
||||
if (i > 0) {
|
||||
sb.append(separator);
|
||||
}
|
||||
sb.append(JSONObject.valueToString(this.myArrayList.get(i)));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of elements in the JSONArray, included nulls.
|
||||
*
|
||||
* @return The length (or size).
|
||||
*/
|
||||
public int length() {
|
||||
return this.myArrayList.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the optional object value associated with an index.
|
||||
*
|
||||
* @param index
|
||||
* The index must be between 0 and length() - 1.
|
||||
* @return An object value, or null if there is no object at that index.
|
||||
*/
|
||||
public Object opt(int index) {
|
||||
return (index < 0 || index >= this.length()) ? null : this.myArrayList
|
||||
.get(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the optional boolean value associated with an index. It returns false
|
||||
* if there is no value at that index, or if the value is not Boolean.TRUE
|
||||
* or the String "true".
|
||||
*
|
||||
* @param index
|
||||
* The index must be between 0 and length() - 1.
|
||||
* @return The truth.
|
||||
*/
|
||||
public boolean optBoolean(int index) {
|
||||
return this.optBoolean(index, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the optional boolean value associated with an index. It returns the
|
||||
* defaultValue if there is no value at that index or if it is not a Boolean
|
||||
* or the String "true" or "false" (case insensitive).
|
||||
*
|
||||
* @param index
|
||||
* The index must be between 0 and length() - 1.
|
||||
* @param defaultValue
|
||||
* A boolean default.
|
||||
* @return The truth.
|
||||
*/
|
||||
public boolean optBoolean(int index, boolean defaultValue) {
|
||||
try {
|
||||
return this.getBoolean(index);
|
||||
} catch (Exception e) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the optional double value associated with an index. NaN is returned
|
||||
* if there is no value for the index, or if the value is not a number and
|
||||
* cannot be converted to a number.
|
||||
*
|
||||
* @param index
|
||||
* The index must be between 0 and length() - 1.
|
||||
* @return The value.
|
||||
*/
|
||||
public double optDouble(int index) {
|
||||
return this.optDouble(index, Double.NaN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the optional double value associated with an index. The defaultValue
|
||||
* is returned if there is no value for the index, or if the value is not a
|
||||
* number and cannot be converted to a number.
|
||||
*
|
||||
* @param index
|
||||
* subscript
|
||||
* @param defaultValue
|
||||
* The default value.
|
||||
* @return The value.
|
||||
*/
|
||||
public double optDouble(int index, double defaultValue) {
|
||||
try {
|
||||
return this.getDouble(index);
|
||||
} catch (Exception e) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the optional int value associated with an index. Zero is returned if
|
||||
* there is no value for the index, or if the value is not a number and
|
||||
* cannot be converted to a number.
|
||||
*
|
||||
* @param index
|
||||
* The index must be between 0 and length() - 1.
|
||||
* @return The value.
|
||||
*/
|
||||
public int optInt(int index) {
|
||||
return this.optInt(index, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the optional int value associated with an index. The defaultValue is
|
||||
* returned if there is no value for the index, or if the value is not a
|
||||
* number and cannot be converted to a number.
|
||||
*
|
||||
* @param index
|
||||
* The index must be between 0 and length() - 1.
|
||||
* @param defaultValue
|
||||
* The default value.
|
||||
* @return The value.
|
||||
*/
|
||||
public int optInt(int index, int defaultValue) {
|
||||
try {
|
||||
return this.getInt(index);
|
||||
} catch (Exception e) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the optional JSONArray associated with an index.
|
||||
*
|
||||
* @param index
|
||||
* subscript
|
||||
* @return A JSONArray value, or null if the index has no value, or if the
|
||||
* value is not a JSONArray.
|
||||
*/
|
||||
public JSONArray optJSONArray(int index) {
|
||||
Object o = this.opt(index);
|
||||
return o instanceof JSONArray ? (JSONArray) o : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the optional JSONObject associated with an index. Null is returned if
|
||||
* the key is not found, or null if the index has no value, or if the value
|
||||
* is not a JSONObject.
|
||||
*
|
||||
* @param index
|
||||
* The index must be between 0 and length() - 1.
|
||||
* @return A JSONObject value.
|
||||
*/
|
||||
public JSONObject optJSONObject(int index) {
|
||||
Object o = this.opt(index);
|
||||
return o instanceof JSONObject ? (JSONObject) o : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the optional long value associated with an index. Zero is returned if
|
||||
* there is no value for the index, or if the value is not a number and
|
||||
* cannot be converted to a number.
|
||||
*
|
||||
* @param index
|
||||
* The index must be between 0 and length() - 1.
|
||||
* @return The value.
|
||||
*/
|
||||
public long optLong(int index) {
|
||||
return this.optLong(index, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the optional long value associated with an index. The defaultValue is
|
||||
* returned if there is no value for the index, or if the value is not a
|
||||
* number and cannot be converted to a number.
|
||||
*
|
||||
* @param index
|
||||
* The index must be between 0 and length() - 1.
|
||||
* @param defaultValue
|
||||
* The default value.
|
||||
* @return The value.
|
||||
*/
|
||||
public long optLong(int index, long defaultValue) {
|
||||
try {
|
||||
return this.getLong(index);
|
||||
} catch (Exception e) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the optional string value associated with an index. It returns an
|
||||
* empty string if there is no value at that index. If the value is not a
|
||||
* string and is not null, then it is coverted to a string.
|
||||
*
|
||||
* @param index
|
||||
* The index must be between 0 and length() - 1.
|
||||
* @return A String value.
|
||||
*/
|
||||
public String optString(int index) {
|
||||
return this.optString(index, "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the optional string associated with an index. The defaultValue is
|
||||
* returned if the key is not found.
|
||||
*
|
||||
* @param index
|
||||
* The index must be between 0 and length() - 1.
|
||||
* @param defaultValue
|
||||
* The default value.
|
||||
* @return A String value.
|
||||
*/
|
||||
public String optString(int index, String defaultValue) {
|
||||
Object object = this.opt(index);
|
||||
return JSONObject.NULL.equals(object) ? defaultValue : object
|
||||
.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a boolean value. This increases the array's length by one.
|
||||
*
|
||||
* @param value
|
||||
* A boolean value.
|
||||
* @return this.
|
||||
*/
|
||||
public JSONArray put(boolean value) {
|
||||
this.put(value ? Boolean.TRUE : Boolean.FALSE);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Put a value in the JSONArray, where the value will be a JSONArray which
|
||||
* is produced from a Collection.
|
||||
*
|
||||
* @param value
|
||||
* A Collection value.
|
||||
* @return this.
|
||||
*/
|
||||
public JSONArray put(Collection<Object> value) {
|
||||
this.put(new JSONArray(value));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a double value. This increases the array's length by one.
|
||||
*
|
||||
* @param value
|
||||
* A double value.
|
||||
* @throws JSONException
|
||||
* if the value is not finite.
|
||||
* @return this.
|
||||
*/
|
||||
public JSONArray put(double value) throws JSONException {
|
||||
Double d = new Double(value);
|
||||
JSONObject.testValidity(d);
|
||||
this.put(d);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Append an int value. This increases the array's length by one.
|
||||
*
|
||||
* @param value
|
||||
* An int value.
|
||||
* @return this.
|
||||
*/
|
||||
public JSONArray put(int value) {
|
||||
this.put(new Integer(value));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Append an long value. This increases the array's length by one.
|
||||
*
|
||||
* @param value
|
||||
* A long value.
|
||||
* @return this.
|
||||
*/
|
||||
public JSONArray put(long value) {
|
||||
this.put(new Long(value));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Put a value in the JSONArray, where the value will be a JSONObject which
|
||||
* is produced from a Map.
|
||||
*
|
||||
* @param value
|
||||
* A Map value.
|
||||
* @return this.
|
||||
*/
|
||||
public JSONArray put(Map<String, Object> value) {
|
||||
this.put(new JSONObject(value));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Append an object value. This increases the array's length by one.
|
||||
*
|
||||
* @param value
|
||||
* An object value. The value should be a Boolean, Double,
|
||||
* Integer, JSONArray, JSONObject, Long, or String, or the
|
||||
* JSONObject.NULL object.
|
||||
* @return this.
|
||||
*/
|
||||
public JSONArray put(Object value) {
|
||||
this.myArrayList.add(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Put or replace a boolean value in the JSONArray. If the index is greater
|
||||
* than the length of the JSONArray, then null elements will be added as
|
||||
* necessary to pad it out.
|
||||
*
|
||||
* @param index
|
||||
* The subscript.
|
||||
* @param value
|
||||
* A boolean value.
|
||||
* @return this.
|
||||
* @throws JSONException
|
||||
* If the index is negative.
|
||||
*/
|
||||
public JSONArray put(int index, boolean value) throws JSONException {
|
||||
this.put(index, value ? Boolean.TRUE : Boolean.FALSE);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Put a value in the JSONArray, where the value will be a JSONArray which
|
||||
* is produced from a Collection.
|
||||
*
|
||||
* @param index
|
||||
* The subscript.
|
||||
* @param value
|
||||
* A Collection value.
|
||||
* @return this.
|
||||
* @throws JSONException
|
||||
* If the index is negative or if the value is not finite.
|
||||
*/
|
||||
public JSONArray put(int index, Collection<Object> value) throws JSONException {
|
||||
this.put(index, new JSONArray(value));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Put or replace a double value. If the index is greater than the length of
|
||||
* the JSONArray, then null elements will be added as necessary to pad it
|
||||
* out.
|
||||
*
|
||||
* @param index
|
||||
* The subscript.
|
||||
* @param value
|
||||
* A double value.
|
||||
* @return this.
|
||||
* @throws JSONException
|
||||
* If the index is negative or if the value is not finite.
|
||||
*/
|
||||
public JSONArray put(int index, double value) throws JSONException {
|
||||
this.put(index, new Double(value));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Put or replace an int value. If the index is greater than the length of
|
||||
* the JSONArray, then null elements will be added as necessary to pad it
|
||||
* out.
|
||||
*
|
||||
* @param index
|
||||
* The subscript.
|
||||
* @param value
|
||||
* An int value.
|
||||
* @return this.
|
||||
* @throws JSONException
|
||||
* If the index is negative.
|
||||
*/
|
||||
public JSONArray put(int index, int value) throws JSONException {
|
||||
this.put(index, new Integer(value));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Put or replace a long value. If the index is greater than the length of
|
||||
* the JSONArray, then null elements will be added as necessary to pad it
|
||||
* out.
|
||||
*
|
||||
* @param index
|
||||
* The subscript.
|
||||
* @param value
|
||||
* A long value.
|
||||
* @return this.
|
||||
* @throws JSONException
|
||||
* If the index is negative.
|
||||
*/
|
||||
public JSONArray put(int index, long value) throws JSONException {
|
||||
this.put(index, new Long(value));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Put a value in the JSONArray, where the value will be a JSONObject that
|
||||
* is produced from a Map.
|
||||
*
|
||||
* @param index
|
||||
* The subscript.
|
||||
* @param value
|
||||
* The Map value.
|
||||
* @return this.
|
||||
* @throws JSONException
|
||||
* If the index is negative or if the the value is an invalid
|
||||
* number.
|
||||
*/
|
||||
public JSONArray put(int index, Map<String, Object> value) throws JSONException {
|
||||
this.put(index, new JSONObject(value));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Put or replace an object value in the JSONArray. If the index is greater
|
||||
* than the length of the JSONArray, then null elements will be added as
|
||||
* necessary to pad it out.
|
||||
*
|
||||
* @param index
|
||||
* The subscript.
|
||||
* @param value
|
||||
* The value to put into the array. The value should be a
|
||||
* Boolean, Double, Integer, JSONArray, JSONObject, Long, or
|
||||
* String, or the JSONObject.NULL object.
|
||||
* @return this.
|
||||
* @throws JSONException
|
||||
* If the index is negative or if the the value is an invalid
|
||||
* number.
|
||||
*/
|
||||
public JSONArray put(int index, Object value) throws JSONException {
|
||||
JSONObject.testValidity(value);
|
||||
if (index < 0) {
|
||||
throw new JSONException("JSONArray[" + index + "] not found.");
|
||||
}
|
||||
if (index < this.length()) {
|
||||
this.myArrayList.set(index, value);
|
||||
} else {
|
||||
while (index != this.length()) {
|
||||
this.put(JSONObject.NULL);
|
||||
}
|
||||
this.put(value);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an index and close the hole.
|
||||
*
|
||||
* @param index
|
||||
* The index of the element to be removed.
|
||||
* @return The value that was associated with the index, or null if there
|
||||
* was no value.
|
||||
*/
|
||||
public Object remove(int index) {
|
||||
return index >= 0 && index < this.length()
|
||||
? this.myArrayList.remove(index)
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if two JSONArrays are similar.
|
||||
* They must contain similar sequences.
|
||||
*
|
||||
* @param other The other JSONArray
|
||||
* @return true if they are equal
|
||||
*/
|
||||
public boolean similar(Object other) {
|
||||
if (!(other instanceof JSONArray)) {
|
||||
return false;
|
||||
}
|
||||
int len = this.length();
|
||||
if (len != ((JSONArray)other).length()) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < len; i += 1) {
|
||||
Object valueThis = this.get(i);
|
||||
Object valueOther = ((JSONArray)other).get(i);
|
||||
if (valueThis instanceof JSONObject) {
|
||||
if (!((JSONObject)valueThis).similar(valueOther)) {
|
||||
return false;
|
||||
}
|
||||
} else if (valueThis instanceof JSONArray) {
|
||||
if (!((JSONArray)valueThis).similar(valueOther)) {
|
||||
return false;
|
||||
}
|
||||
} else if (!valueThis.equals(valueOther)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Produce a JSONObject by combining a JSONArray of names with the values of
|
||||
* this JSONArray.
|
||||
*
|
||||
* @param names
|
||||
* A JSONArray containing a list of key strings. These will be
|
||||
* paired with the values.
|
||||
* @return A JSONObject, or null if there are no names or if this JSONArray
|
||||
* has no values.
|
||||
* @throws JSONException
|
||||
* If any of the names are null.
|
||||
*/
|
||||
public JSONObject toJSONObject(JSONArray names) throws JSONException {
|
||||
if (names == null || names.length() == 0 || this.length() == 0) {
|
||||
return null;
|
||||
}
|
||||
JSONObject jo = new JSONObject();
|
||||
for (int i = 0; i < names.length(); i += 1) {
|
||||
jo.put(names.getString(i), this.opt(i));
|
||||
}
|
||||
return jo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a JSON text of this JSONArray. For compactness, no unnecessary
|
||||
* whitespace is added. If it is not possible to produce a syntactically
|
||||
* correct JSON text then null will be returned instead. This could occur if
|
||||
* the array contains an invalid number.
|
||||
* <p>
|
||||
* Warning: This method assumes that the data structure is acyclical.
|
||||
*
|
||||
* @return a printable, displayable, transmittable representation of the
|
||||
* array.
|
||||
*/
|
||||
public String toString() {
|
||||
try {
|
||||
return this.toString(0);
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a prettyprinted JSON text of this JSONArray. Warning: This method
|
||||
* assumes that the data structure is acyclical.
|
||||
*
|
||||
* @param indentFactor
|
||||
* The number of spaces to add to each level of indentation.
|
||||
* @return a printable, displayable, transmittable representation of the
|
||||
* object, beginning with <code>[</code> <small>(left
|
||||
* bracket)</small> and ending with <code>]</code>
|
||||
* <small>(right bracket)</small>.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public String toString(int indentFactor) throws JSONException {
|
||||
StringWriter sw = new StringWriter();
|
||||
synchronized (sw.getBuffer()) {
|
||||
return this.write(sw, indentFactor, 0).toString();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the contents of the JSONArray as JSON text to a writer. For
|
||||
* compactness, no whitespace is added.
|
||||
* <p>
|
||||
* Warning: This method assumes that the data structure is acyclical.
|
||||
*
|
||||
* @return The writer.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public Writer write(Writer writer) throws JSONException {
|
||||
return this.write(writer, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the contents of the JSONArray as JSON text to a writer. For
|
||||
* compactness, no whitespace is added.
|
||||
* <p>
|
||||
* Warning: This method assumes that the data structure is acyclical.
|
||||
*
|
||||
* @param indentFactor
|
||||
* The number of spaces to add to each level of indentation.
|
||||
* @param indent
|
||||
* The indention of the top level.
|
||||
* @return The writer.
|
||||
* @throws JSONException
|
||||
*/
|
||||
Writer write(Writer writer, int indentFactor, int indent)
|
||||
throws JSONException {
|
||||
try {
|
||||
boolean commanate = false;
|
||||
int length = this.length();
|
||||
writer.write('[');
|
||||
|
||||
if (length == 1) {
|
||||
JSONObject.writeValue(writer, this.myArrayList.get(0),
|
||||
indentFactor, indent);
|
||||
} else if (length != 0) {
|
||||
final int newindent = indent + indentFactor;
|
||||
|
||||
for (int i = 0; i < length; i += 1) {
|
||||
if (commanate) {
|
||||
writer.write(',');
|
||||
}
|
||||
if (indentFactor > 0) {
|
||||
writer.write('\n');
|
||||
}
|
||||
JSONObject.indent(writer, newindent);
|
||||
JSONObject.writeValue(writer, this.myArrayList.get(i),
|
||||
indentFactor, newindent);
|
||||
commanate = true;
|
||||
}
|
||||
if (indentFactor > 0) {
|
||||
writer.write('\n');
|
||||
}
|
||||
JSONObject.indent(writer, indent);
|
||||
}
|
||||
writer.write(']');
|
||||
return writer;
|
||||
} catch (IOException e) {
|
||||
throw new JSONException(e);
|
||||
}
|
||||
}
|
||||
}
|
43
src/bindings/java/src/com/openalpr/jni/json/JSONException.java
Executable file
43
src/bindings/java/src/com/openalpr/jni/json/JSONException.java
Executable file
@@ -0,0 +1,43 @@
|
||||
package com.openalpr.jni.json;
|
||||
|
||||
/**
|
||||
* The JSONException is thrown by the JSON.org classes when things are amiss.
|
||||
*
|
||||
* @author JSON.org
|
||||
* @version 2014-05-03
|
||||
*/
|
||||
public class JSONException extends RuntimeException {
|
||||
private static final long serialVersionUID = 0;
|
||||
private Throwable cause;
|
||||
|
||||
/**
|
||||
* Constructs a JSONException with an explanatory message.
|
||||
*
|
||||
* @param message
|
||||
* Detail about the reason for the exception.
|
||||
*/
|
||||
public JSONException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new JSONException with the specified cause.
|
||||
* @param cause The cause.
|
||||
*/
|
||||
public JSONException(Throwable cause) {
|
||||
super(cause.getMessage());
|
||||
this.cause = cause;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the cause of this exception or null if the cause is nonexistent
|
||||
* or unknown.
|
||||
*
|
||||
* @return the cause of this exception or null if the cause is nonexistent
|
||||
* or unknown.
|
||||
*/
|
||||
@Override
|
||||
public Throwable getCause() {
|
||||
return this.cause;
|
||||
}
|
||||
}
|
467
src/bindings/java/src/com/openalpr/jni/json/JSONML.java
Executable file
467
src/bindings/java/src/com/openalpr/jni/json/JSONML.java
Executable file
@@ -0,0 +1,467 @@
|
||||
package com.openalpr.jni.json;
|
||||
|
||||
/*
|
||||
Copyright (c) 2008 JSON.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
The Software shall be used for Good, not Evil.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
|
||||
/**
|
||||
* This provides static methods to convert an XML text into a JSONArray or
|
||||
* JSONObject, and to covert a JSONArray or JSONObject into an XML text using
|
||||
* the JsonML transform.
|
||||
*
|
||||
* @author JSON.org
|
||||
* @version 2014-05-03
|
||||
*/
|
||||
public class JSONML {
|
||||
|
||||
/**
|
||||
* Parse XML values and store them in a JSONArray.
|
||||
* @param x The XMLTokener containing the source string.
|
||||
* @param arrayForm true if array form, false if object form.
|
||||
* @param ja The JSONArray that is containing the current tag or null
|
||||
* if we are at the outermost level.
|
||||
* @return A JSONArray if the value is the outermost tag, otherwise null.
|
||||
* @throws JSONException
|
||||
*/
|
||||
private static Object parse(
|
||||
XMLTokener x,
|
||||
boolean arrayForm,
|
||||
JSONArray ja
|
||||
) throws JSONException {
|
||||
String attribute;
|
||||
char c;
|
||||
String closeTag = null;
|
||||
int i;
|
||||
JSONArray newja = null;
|
||||
JSONObject newjo = null;
|
||||
Object token;
|
||||
String tagName = null;
|
||||
|
||||
// Test for and skip past these forms:
|
||||
// <!-- ... -->
|
||||
// <![ ... ]]>
|
||||
// <! ... >
|
||||
// <? ... ?>
|
||||
|
||||
while (true) {
|
||||
if (!x.more()) {
|
||||
throw x.syntaxError("Bad XML");
|
||||
}
|
||||
token = x.nextContent();
|
||||
if (token == XML.LT) {
|
||||
token = x.nextToken();
|
||||
if (token instanceof Character) {
|
||||
if (token == XML.SLASH) {
|
||||
|
||||
// Close tag </
|
||||
|
||||
token = x.nextToken();
|
||||
if (!(token instanceof String)) {
|
||||
throw new JSONException(
|
||||
"Expected a closing name instead of '" +
|
||||
token + "'.");
|
||||
}
|
||||
if (x.nextToken() != XML.GT) {
|
||||
throw x.syntaxError("Misshaped close tag");
|
||||
}
|
||||
return token;
|
||||
} else if (token == XML.BANG) {
|
||||
|
||||
// <!
|
||||
|
||||
c = x.next();
|
||||
if (c == '-') {
|
||||
if (x.next() == '-') {
|
||||
x.skipPast("-->");
|
||||
} else {
|
||||
x.back();
|
||||
}
|
||||
} else if (c == '[') {
|
||||
token = x.nextToken();
|
||||
if (token.equals("CDATA") && x.next() == '[') {
|
||||
if (ja != null) {
|
||||
ja.put(x.nextCDATA());
|
||||
}
|
||||
} else {
|
||||
throw x.syntaxError("Expected 'CDATA['");
|
||||
}
|
||||
} else {
|
||||
i = 1;
|
||||
do {
|
||||
token = x.nextMeta();
|
||||
if (token == null) {
|
||||
throw x.syntaxError("Missing '>' after '<!'.");
|
||||
} else if (token == XML.LT) {
|
||||
i += 1;
|
||||
} else if (token == XML.GT) {
|
||||
i -= 1;
|
||||
}
|
||||
} while (i > 0);
|
||||
}
|
||||
} else if (token == XML.QUEST) {
|
||||
|
||||
// <?
|
||||
|
||||
x.skipPast("?>");
|
||||
} else {
|
||||
throw x.syntaxError("Misshaped tag");
|
||||
}
|
||||
|
||||
// Open tag <
|
||||
|
||||
} else {
|
||||
if (!(token instanceof String)) {
|
||||
throw x.syntaxError("Bad tagName '" + token + "'.");
|
||||
}
|
||||
tagName = (String)token;
|
||||
newja = new JSONArray();
|
||||
newjo = new JSONObject();
|
||||
if (arrayForm) {
|
||||
newja.put(tagName);
|
||||
if (ja != null) {
|
||||
ja.put(newja);
|
||||
}
|
||||
} else {
|
||||
newjo.put("tagName", tagName);
|
||||
if (ja != null) {
|
||||
ja.put(newjo);
|
||||
}
|
||||
}
|
||||
token = null;
|
||||
for (;;) {
|
||||
if (token == null) {
|
||||
token = x.nextToken();
|
||||
}
|
||||
if (token == null) {
|
||||
throw x.syntaxError("Misshaped tag");
|
||||
}
|
||||
if (!(token instanceof String)) {
|
||||
break;
|
||||
}
|
||||
|
||||
// attribute = value
|
||||
|
||||
attribute = (String)token;
|
||||
if (!arrayForm && ("tagName".equals(attribute) || "childNode".equals(attribute))) {
|
||||
throw x.syntaxError("Reserved attribute.");
|
||||
}
|
||||
token = x.nextToken();
|
||||
if (token == XML.EQ) {
|
||||
token = x.nextToken();
|
||||
if (!(token instanceof String)) {
|
||||
throw x.syntaxError("Missing value");
|
||||
}
|
||||
newjo.accumulate(attribute, XML.stringToValue((String)token));
|
||||
token = null;
|
||||
} else {
|
||||
newjo.accumulate(attribute, "");
|
||||
}
|
||||
}
|
||||
if (arrayForm && newjo.length() > 0) {
|
||||
newja.put(newjo);
|
||||
}
|
||||
|
||||
// Empty tag <.../>
|
||||
|
||||
if (token == XML.SLASH) {
|
||||
if (x.nextToken() != XML.GT) {
|
||||
throw x.syntaxError("Misshaped tag");
|
||||
}
|
||||
if (ja == null) {
|
||||
if (arrayForm) {
|
||||
return newja;
|
||||
} else {
|
||||
return newjo;
|
||||
}
|
||||
}
|
||||
|
||||
// Content, between <...> and </...>
|
||||
|
||||
} else {
|
||||
if (token != XML.GT) {
|
||||
throw x.syntaxError("Misshaped tag");
|
||||
}
|
||||
closeTag = (String)parse(x, arrayForm, newja);
|
||||
if (closeTag != null) {
|
||||
if (!closeTag.equals(tagName)) {
|
||||
throw x.syntaxError("Mismatched '" + tagName +
|
||||
"' and '" + closeTag + "'");
|
||||
}
|
||||
tagName = null;
|
||||
if (!arrayForm && newja.length() > 0) {
|
||||
newjo.put("childNodes", newja);
|
||||
}
|
||||
if (ja == null) {
|
||||
if (arrayForm) {
|
||||
return newja;
|
||||
} else {
|
||||
return newjo;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (ja != null) {
|
||||
ja.put(token instanceof String
|
||||
? XML.stringToValue((String)token)
|
||||
: token);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert a well-formed (but not necessarily valid) XML string into a
|
||||
* JSONArray using the JsonML transform. Each XML tag is represented as
|
||||
* a JSONArray in which the first element is the tag name. If the tag has
|
||||
* attributes, then the second element will be JSONObject containing the
|
||||
* name/value pairs. If the tag contains children, then strings and
|
||||
* JSONArrays will represent the child tags.
|
||||
* Comments, prologs, DTDs, and <code><[ [ ]]></code> are ignored.
|
||||
* @param string The source string.
|
||||
* @return A JSONArray containing the structured data from the XML string.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static JSONArray toJSONArray(String string) throws JSONException {
|
||||
return toJSONArray(new XMLTokener(string));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert a well-formed (but not necessarily valid) XML string into a
|
||||
* JSONArray using the JsonML transform. Each XML tag is represented as
|
||||
* a JSONArray in which the first element is the tag name. If the tag has
|
||||
* attributes, then the second element will be JSONObject containing the
|
||||
* name/value pairs. If the tag contains children, then strings and
|
||||
* JSONArrays will represent the child content and tags.
|
||||
* Comments, prologs, DTDs, and <code><[ [ ]]></code> are ignored.
|
||||
* @param x An XMLTokener.
|
||||
* @return A JSONArray containing the structured data from the XML string.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static JSONArray toJSONArray(XMLTokener x) throws JSONException {
|
||||
return (JSONArray)parse(x, true, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert a well-formed (but not necessarily valid) XML string into a
|
||||
* JSONObject using the JsonML transform. Each XML tag is represented as
|
||||
* a JSONObject with a "tagName" property. If the tag has attributes, then
|
||||
* the attributes will be in the JSONObject as properties. If the tag
|
||||
* contains children, the object will have a "childNodes" property which
|
||||
* will be an array of strings and JsonML JSONObjects.
|
||||
|
||||
* Comments, prologs, DTDs, and <code><[ [ ]]></code> are ignored.
|
||||
* @param x An XMLTokener of the XML source text.
|
||||
* @return A JSONObject containing the structured data from the XML string.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static JSONObject toJSONObject(XMLTokener x) throws JSONException {
|
||||
return (JSONObject)parse(x, false, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert a well-formed (but not necessarily valid) XML string into a
|
||||
* JSONObject using the JsonML transform. Each XML tag is represented as
|
||||
* a JSONObject with a "tagName" property. If the tag has attributes, then
|
||||
* the attributes will be in the JSONObject as properties. If the tag
|
||||
* contains children, the object will have a "childNodes" property which
|
||||
* will be an array of strings and JsonML JSONObjects.
|
||||
|
||||
* Comments, prologs, DTDs, and <code><[ [ ]]></code> are ignored.
|
||||
* @param string The XML source text.
|
||||
* @return A JSONObject containing the structured data from the XML string.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static JSONObject toJSONObject(String string) throws JSONException {
|
||||
return toJSONObject(new XMLTokener(string));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reverse the JSONML transformation, making an XML text from a JSONArray.
|
||||
* @param ja A JSONArray.
|
||||
* @return An XML string.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static String toString(JSONArray ja) throws JSONException {
|
||||
int i;
|
||||
JSONObject jo;
|
||||
String key;
|
||||
Iterator<String> keys;
|
||||
int length;
|
||||
Object object;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String tagName;
|
||||
String value;
|
||||
|
||||
// Emit <tagName
|
||||
|
||||
tagName = ja.getString(0);
|
||||
XML.noSpace(tagName);
|
||||
tagName = XML.escape(tagName);
|
||||
sb.append('<');
|
||||
sb.append(tagName);
|
||||
|
||||
object = ja.opt(1);
|
||||
if (object instanceof JSONObject) {
|
||||
i = 2;
|
||||
jo = (JSONObject)object;
|
||||
|
||||
// Emit the attributes
|
||||
|
||||
keys = jo.keys();
|
||||
while (keys.hasNext()) {
|
||||
key = keys.next();
|
||||
XML.noSpace(key);
|
||||
value = jo.optString(key);
|
||||
if (value != null) {
|
||||
sb.append(' ');
|
||||
sb.append(XML.escape(key));
|
||||
sb.append('=');
|
||||
sb.append('"');
|
||||
sb.append(XML.escape(value));
|
||||
sb.append('"');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
i = 1;
|
||||
}
|
||||
|
||||
// Emit content in body
|
||||
|
||||
length = ja.length();
|
||||
if (i >= length) {
|
||||
sb.append('/');
|
||||
sb.append('>');
|
||||
} else {
|
||||
sb.append('>');
|
||||
do {
|
||||
object = ja.get(i);
|
||||
i += 1;
|
||||
if (object != null) {
|
||||
if (object instanceof String) {
|
||||
sb.append(XML.escape(object.toString()));
|
||||
} else if (object instanceof JSONObject) {
|
||||
sb.append(toString((JSONObject)object));
|
||||
} else if (object instanceof JSONArray) {
|
||||
sb.append(toString((JSONArray)object));
|
||||
}
|
||||
}
|
||||
} while (i < length);
|
||||
sb.append('<');
|
||||
sb.append('/');
|
||||
sb.append(tagName);
|
||||
sb.append('>');
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the JSONML transformation, making an XML text from a JSONObject.
|
||||
* The JSONObject must contain a "tagName" property. If it has children,
|
||||
* then it must have a "childNodes" property containing an array of objects.
|
||||
* The other properties are attributes with string values.
|
||||
* @param jo A JSONObject.
|
||||
* @return An XML string.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static String toString(JSONObject jo) throws JSONException {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int i;
|
||||
JSONArray ja;
|
||||
String key;
|
||||
Iterator<String> keys;
|
||||
int length;
|
||||
Object object;
|
||||
String tagName;
|
||||
String value;
|
||||
|
||||
//Emit <tagName
|
||||
|
||||
tagName = jo.optString("tagName");
|
||||
if (tagName == null) {
|
||||
return XML.escape(jo.toString());
|
||||
}
|
||||
XML.noSpace(tagName);
|
||||
tagName = XML.escape(tagName);
|
||||
sb.append('<');
|
||||
sb.append(tagName);
|
||||
|
||||
//Emit the attributes
|
||||
|
||||
keys = jo.keys();
|
||||
while (keys.hasNext()) {
|
||||
key = keys.next();
|
||||
if (!"tagName".equals(key) && !"childNodes".equals(key)) {
|
||||
XML.noSpace(key);
|
||||
value = jo.optString(key);
|
||||
if (value != null) {
|
||||
sb.append(' ');
|
||||
sb.append(XML.escape(key));
|
||||
sb.append('=');
|
||||
sb.append('"');
|
||||
sb.append(XML.escape(value));
|
||||
sb.append('"');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Emit content in body
|
||||
|
||||
ja = jo.optJSONArray("childNodes");
|
||||
if (ja == null) {
|
||||
sb.append('/');
|
||||
sb.append('>');
|
||||
} else {
|
||||
sb.append('>');
|
||||
length = ja.length();
|
||||
for (i = 0; i < length; i += 1) {
|
||||
object = ja.get(i);
|
||||
if (object != null) {
|
||||
if (object instanceof String) {
|
||||
sb.append(XML.escape(object.toString()));
|
||||
} else if (object instanceof JSONObject) {
|
||||
sb.append(toString((JSONObject)object));
|
||||
} else if (object instanceof JSONArray) {
|
||||
sb.append(toString((JSONArray)object));
|
||||
} else {
|
||||
sb.append(object.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
sb.append('<');
|
||||
sb.append('/');
|
||||
sb.append(tagName);
|
||||
sb.append('>');
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
1686
src/bindings/java/src/com/openalpr/jni/json/JSONObject.java
Executable file
1686
src/bindings/java/src/com/openalpr/jni/json/JSONObject.java
Executable file
File diff suppressed because it is too large
Load Diff
18
src/bindings/java/src/com/openalpr/jni/json/JSONString.java
Executable file
18
src/bindings/java/src/com/openalpr/jni/json/JSONString.java
Executable file
@@ -0,0 +1,18 @@
|
||||
package com.openalpr.jni.json;
|
||||
/**
|
||||
* The <code>JSONString</code> interface allows a <code>toJSONString()</code>
|
||||
* method so that a class can change the behavior of
|
||||
* <code>JSONObject.toString()</code>, <code>JSONArray.toString()</code>,
|
||||
* and <code>JSONWriter.value(</code>Object<code>)</code>. The
|
||||
* <code>toJSONString</code> method will be used instead of the default behavior
|
||||
* of using the Object's <code>toString()</code> method and quoting the result.
|
||||
*/
|
||||
public interface JSONString {
|
||||
/**
|
||||
* The <code>toJSONString</code> method allows a class to produce its own JSON
|
||||
* serialization.
|
||||
*
|
||||
* @return A strictly syntactically correct JSON text.
|
||||
*/
|
||||
public String toJSONString();
|
||||
}
|
78
src/bindings/java/src/com/openalpr/jni/json/JSONStringer.java
Executable file
78
src/bindings/java/src/com/openalpr/jni/json/JSONStringer.java
Executable file
@@ -0,0 +1,78 @@
|
||||
package com.openalpr.jni.json;
|
||||
|
||||
/*
|
||||
Copyright (c) 2006 JSON.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
The Software shall be used for Good, not Evil.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
import java.io.StringWriter;
|
||||
|
||||
/**
|
||||
* JSONStringer provides a quick and convenient way of producing JSON text.
|
||||
* The texts produced strictly conform to JSON syntax rules. No whitespace is
|
||||
* added, so the results are ready for transmission or storage. Each instance of
|
||||
* JSONStringer can produce one JSON text.
|
||||
* <p>
|
||||
* A JSONStringer instance provides a <code>value</code> method for appending
|
||||
* values to the
|
||||
* text, and a <code>key</code>
|
||||
* method for adding keys before values in objects. There are <code>array</code>
|
||||
* and <code>endArray</code> methods that make and bound array values, and
|
||||
* <code>object</code> and <code>endObject</code> methods which make and bound
|
||||
* object values. All of these methods return the JSONWriter instance,
|
||||
* permitting cascade style. For example, <pre>
|
||||
* myString = new JSONStringer()
|
||||
* .object()
|
||||
* .key("JSON")
|
||||
* .value("Hello, World!")
|
||||
* .endObject()
|
||||
* .toString();</pre> which produces the string <pre>
|
||||
* {"JSON":"Hello, World!"}</pre>
|
||||
* <p>
|
||||
* The first method called must be <code>array</code> or <code>object</code>.
|
||||
* There are no methods for adding commas or colons. JSONStringer adds them for
|
||||
* you. Objects and arrays can be nested up to 20 levels deep.
|
||||
* <p>
|
||||
* This can sometimes be easier than using a JSONObject to build a string.
|
||||
* @author JSON.org
|
||||
* @version 2008-09-18
|
||||
*/
|
||||
public class JSONStringer extends JSONWriter {
|
||||
/**
|
||||
* Make a fresh JSONStringer. It can be used to build one JSON text.
|
||||
*/
|
||||
public JSONStringer() {
|
||||
super(new StringWriter());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the JSON text. This method is used to obtain the product of the
|
||||
* JSONStringer instance. It will return <code>null</code> if there was a
|
||||
* problem in the construction of the JSON text (such as the calls to
|
||||
* <code>array</code> were not properly balanced with calls to
|
||||
* <code>endArray</code>).
|
||||
* @return The JSON text.
|
||||
*/
|
||||
public String toString() {
|
||||
return this.mode == 'd' ? this.writer.toString() : null;
|
||||
}
|
||||
}
|
446
src/bindings/java/src/com/openalpr/jni/json/JSONTokener.java
Normal file
446
src/bindings/java/src/com/openalpr/jni/json/JSONTokener.java
Normal file
@@ -0,0 +1,446 @@
|
||||
package com.openalpr.jni.json;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
|
||||
/*
|
||||
Copyright (c) 2002 JSON.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
The Software shall be used for Good, not Evil.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* A JSONTokener takes a source string and extracts characters and tokens from
|
||||
* it. It is used by the JSONObject and JSONArray constructors to parse
|
||||
* JSON source strings.
|
||||
* @author JSON.org
|
||||
* @version 2014-05-03
|
||||
*/
|
||||
public class JSONTokener {
|
||||
|
||||
private long character;
|
||||
private boolean eof;
|
||||
private long index;
|
||||
private long line;
|
||||
private char previous;
|
||||
private Reader reader;
|
||||
private boolean usePrevious;
|
||||
|
||||
|
||||
/**
|
||||
* Construct a JSONTokener from a Reader.
|
||||
*
|
||||
* @param reader A reader.
|
||||
*/
|
||||
public JSONTokener(Reader reader) {
|
||||
this.reader = reader.markSupported()
|
||||
? reader
|
||||
: new BufferedReader(reader);
|
||||
this.eof = false;
|
||||
this.usePrevious = false;
|
||||
this.previous = 0;
|
||||
this.index = 0;
|
||||
this.character = 1;
|
||||
this.line = 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Construct a JSONTokener from an InputStream.
|
||||
* @param inputStream The source.
|
||||
*/
|
||||
public JSONTokener(InputStream inputStream) throws JSONException {
|
||||
this(new InputStreamReader(inputStream));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Construct a JSONTokener from a string.
|
||||
*
|
||||
* @param s A source string.
|
||||
*/
|
||||
public JSONTokener(String s) {
|
||||
this(new StringReader(s));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Back up one character. This provides a sort of lookahead capability,
|
||||
* so that you can test for a digit or letter before attempting to parse
|
||||
* the next number or identifier.
|
||||
*/
|
||||
public void back() throws JSONException {
|
||||
if (this.usePrevious || this.index <= 0) {
|
||||
throw new JSONException("Stepping back two steps is not supported");
|
||||
}
|
||||
this.index -= 1;
|
||||
this.character -= 1;
|
||||
this.usePrevious = true;
|
||||
this.eof = false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the hex value of a character (base16).
|
||||
* @param c A character between '0' and '9' or between 'A' and 'F' or
|
||||
* between 'a' and 'f'.
|
||||
* @return An int between 0 and 15, or -1 if c was not a hex digit.
|
||||
*/
|
||||
public static int dehexchar(char c) {
|
||||
if (c >= '0' && c <= '9') {
|
||||
return c - '0';
|
||||
}
|
||||
if (c >= 'A' && c <= 'F') {
|
||||
return c - ('A' - 10);
|
||||
}
|
||||
if (c >= 'a' && c <= 'f') {
|
||||
return c - ('a' - 10);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public boolean end() {
|
||||
return this.eof && !this.usePrevious;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determine if the source string still contains characters that next()
|
||||
* can consume.
|
||||
* @return true if not yet at the end of the source.
|
||||
*/
|
||||
public boolean more() throws JSONException {
|
||||
this.next();
|
||||
if (this.end()) {
|
||||
return false;
|
||||
}
|
||||
this.back();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the next character in the source string.
|
||||
*
|
||||
* @return The next character, or 0 if past the end of the source string.
|
||||
*/
|
||||
public char next() throws JSONException {
|
||||
int c;
|
||||
if (this.usePrevious) {
|
||||
this.usePrevious = false;
|
||||
c = this.previous;
|
||||
} else {
|
||||
try {
|
||||
c = this.reader.read();
|
||||
} catch (IOException exception) {
|
||||
throw new JSONException(exception);
|
||||
}
|
||||
|
||||
if (c <= 0) { // End of stream
|
||||
this.eof = true;
|
||||
c = 0;
|
||||
}
|
||||
}
|
||||
this.index += 1;
|
||||
if (this.previous == '\r') {
|
||||
this.line += 1;
|
||||
this.character = c == '\n' ? 0 : 1;
|
||||
} else if (c == '\n') {
|
||||
this.line += 1;
|
||||
this.character = 0;
|
||||
} else {
|
||||
this.character += 1;
|
||||
}
|
||||
this.previous = (char) c;
|
||||
return this.previous;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Consume the next character, and check that it matches a specified
|
||||
* character.
|
||||
* @param c The character to match.
|
||||
* @return The character.
|
||||
* @throws JSONException if the character does not match.
|
||||
*/
|
||||
public char next(char c) throws JSONException {
|
||||
char n = this.next();
|
||||
if (n != c) {
|
||||
throw this.syntaxError("Expected '" + c + "' and instead saw '" +
|
||||
n + "'");
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the next n characters.
|
||||
*
|
||||
* @param n The number of characters to take.
|
||||
* @return A string of n characters.
|
||||
* @throws JSONException
|
||||
* Substring bounds error if there are not
|
||||
* n characters remaining in the source string.
|
||||
*/
|
||||
public String next(int n) throws JSONException {
|
||||
if (n == 0) {
|
||||
return "";
|
||||
}
|
||||
|
||||
char[] chars = new char[n];
|
||||
int pos = 0;
|
||||
|
||||
while (pos < n) {
|
||||
chars[pos] = this.next();
|
||||
if (this.end()) {
|
||||
throw this.syntaxError("Substring bounds error");
|
||||
}
|
||||
pos += 1;
|
||||
}
|
||||
return new String(chars);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the next char in the string, skipping whitespace.
|
||||
* @throws JSONException
|
||||
* @return A character, or 0 if there are no more characters.
|
||||
*/
|
||||
public char nextClean() throws JSONException {
|
||||
for (;;) {
|
||||
char c = this.next();
|
||||
if (c == 0 || c > ' ') {
|
||||
return c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the characters up to the next close quote character.
|
||||
* Backslash processing is done. The formal JSON format does not
|
||||
* allow strings in single quotes, but an implementation is allowed to
|
||||
* accept them.
|
||||
* @param quote The quoting character, either
|
||||
* <code>"</code> <small>(double quote)</small> or
|
||||
* <code>'</code> <small>(single quote)</small>.
|
||||
* @return A String.
|
||||
* @throws JSONException Unterminated string.
|
||||
*/
|
||||
public String nextString(char quote) throws JSONException {
|
||||
char c;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (;;) {
|
||||
c = this.next();
|
||||
switch (c) {
|
||||
case 0:
|
||||
case '\n':
|
||||
case '\r':
|
||||
throw this.syntaxError("Unterminated string");
|
||||
case '\\':
|
||||
c = this.next();
|
||||
switch (c) {
|
||||
case 'b':
|
||||
sb.append('\b');
|
||||
break;
|
||||
case 't':
|
||||
sb.append('\t');
|
||||
break;
|
||||
case 'n':
|
||||
sb.append('\n');
|
||||
break;
|
||||
case 'f':
|
||||
sb.append('\f');
|
||||
break;
|
||||
case 'r':
|
||||
sb.append('\r');
|
||||
break;
|
||||
case 'u':
|
||||
sb.append((char)Integer.parseInt(this.next(4), 16));
|
||||
break;
|
||||
case '"':
|
||||
case '\'':
|
||||
case '\\':
|
||||
case '/':
|
||||
sb.append(c);
|
||||
break;
|
||||
default:
|
||||
throw this.syntaxError("Illegal escape.");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (c == quote) {
|
||||
return sb.toString();
|
||||
}
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the text up but not including the specified character or the
|
||||
* end of line, whichever comes first.
|
||||
* @param delimiter A delimiter character.
|
||||
* @return A string.
|
||||
*/
|
||||
public String nextTo(char delimiter) throws JSONException {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (;;) {
|
||||
char c = this.next();
|
||||
if (c == delimiter || c == 0 || c == '\n' || c == '\r') {
|
||||
if (c != 0) {
|
||||
this.back();
|
||||
}
|
||||
return sb.toString().trim();
|
||||
}
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the text up but not including one of the specified delimiter
|
||||
* characters or the end of line, whichever comes first.
|
||||
* @param delimiters A set of delimiter characters.
|
||||
* @return A string, trimmed.
|
||||
*/
|
||||
public String nextTo(String delimiters) throws JSONException {
|
||||
char c;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (;;) {
|
||||
c = this.next();
|
||||
if (delimiters.indexOf(c) >= 0 || c == 0 ||
|
||||
c == '\n' || c == '\r') {
|
||||
if (c != 0) {
|
||||
this.back();
|
||||
}
|
||||
return sb.toString().trim();
|
||||
}
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the next value. The value can be a Boolean, Double, Integer,
|
||||
* JSONArray, JSONObject, Long, or String, or the JSONObject.NULL object.
|
||||
* @throws JSONException If syntax error.
|
||||
*
|
||||
* @return An object.
|
||||
*/
|
||||
public Object nextValue() throws JSONException {
|
||||
char c = this.nextClean();
|
||||
String string;
|
||||
|
||||
switch (c) {
|
||||
case '"':
|
||||
case '\'':
|
||||
return this.nextString(c);
|
||||
case '{':
|
||||
this.back();
|
||||
return new JSONObject(this);
|
||||
case '[':
|
||||
this.back();
|
||||
return new JSONArray(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle unquoted text. This could be the values true, false, or
|
||||
* null, or it can be a number. An implementation (such as this one)
|
||||
* is allowed to also accept non-standard forms.
|
||||
*
|
||||
* Accumulate characters until we reach the end of the text or a
|
||||
* formatting character.
|
||||
*/
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
while (c >= ' ' && ",:]}/\\\"[{;=#".indexOf(c) < 0) {
|
||||
sb.append(c);
|
||||
c = this.next();
|
||||
}
|
||||
this.back();
|
||||
|
||||
string = sb.toString().trim();
|
||||
if ("".equals(string)) {
|
||||
throw this.syntaxError("Missing value");
|
||||
}
|
||||
return JSONObject.stringToValue(string);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Skip characters until the next character is the requested character.
|
||||
* If the requested character is not found, no characters are skipped.
|
||||
* @param to A character to skip to.
|
||||
* @return The requested character, or zero if the requested character
|
||||
* is not found.
|
||||
*/
|
||||
public char skipTo(char to) throws JSONException {
|
||||
char c;
|
||||
try {
|
||||
long startIndex = this.index;
|
||||
long startCharacter = this.character;
|
||||
long startLine = this.line;
|
||||
this.reader.mark(1000000);
|
||||
do {
|
||||
c = this.next();
|
||||
if (c == 0) {
|
||||
this.reader.reset();
|
||||
this.index = startIndex;
|
||||
this.character = startCharacter;
|
||||
this.line = startLine;
|
||||
return c;
|
||||
}
|
||||
} while (c != to);
|
||||
} catch (IOException exception) {
|
||||
throw new JSONException(exception);
|
||||
}
|
||||
this.back();
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Make a JSONException to signal a syntax error.
|
||||
*
|
||||
* @param message The error message.
|
||||
* @return A JSONException object, suitable for throwing
|
||||
*/
|
||||
public JSONException syntaxError(String message) {
|
||||
return new JSONException(message + this.toString());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Make a printable string of this JSONTokener.
|
||||
*
|
||||
* @return " at {index} [character {character} line {line}]"
|
||||
*/
|
||||
public String toString() {
|
||||
return " at " + this.index + " [character " + this.character + " line " +
|
||||
this.line + "]";
|
||||
}
|
||||
}
|
327
src/bindings/java/src/com/openalpr/jni/json/JSONWriter.java
Executable file
327
src/bindings/java/src/com/openalpr/jni/json/JSONWriter.java
Executable file
@@ -0,0 +1,327 @@
|
||||
package com.openalpr.jni.json;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
|
||||
/*
|
||||
Copyright (c) 2006 JSON.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
The Software shall be used for Good, not Evil.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* JSONWriter provides a quick and convenient way of producing JSON text.
|
||||
* The texts produced strictly conform to JSON syntax rules. No whitespace is
|
||||
* added, so the results are ready for transmission or storage. Each instance of
|
||||
* JSONWriter can produce one JSON text.
|
||||
* <p>
|
||||
* A JSONWriter instance provides a <code>value</code> method for appending
|
||||
* values to the
|
||||
* text, and a <code>key</code>
|
||||
* method for adding keys before values in objects. There are <code>array</code>
|
||||
* and <code>endArray</code> methods that make and bound array values, and
|
||||
* <code>object</code> and <code>endObject</code> methods which make and bound
|
||||
* object values. All of these methods return the JSONWriter instance,
|
||||
* permitting a cascade style. For example, <pre>
|
||||
* new JSONWriter(myWriter)
|
||||
* .object()
|
||||
* .key("JSON")
|
||||
* .value("Hello, World!")
|
||||
* .endObject();</pre> which writes <pre>
|
||||
* {"JSON":"Hello, World!"}</pre>
|
||||
* <p>
|
||||
* The first method called must be <code>array</code> or <code>object</code>.
|
||||
* There are no methods for adding commas or colons. JSONWriter adds them for
|
||||
* you. Objects and arrays can be nested up to 20 levels deep.
|
||||
* <p>
|
||||
* This can sometimes be easier than using a JSONObject to build a string.
|
||||
* @author JSON.org
|
||||
* @version 2011-11-24
|
||||
*/
|
||||
public class JSONWriter {
|
||||
private static final int maxdepth = 200;
|
||||
|
||||
/**
|
||||
* The comma flag determines if a comma should be output before the next
|
||||
* value.
|
||||
*/
|
||||
private boolean comma;
|
||||
|
||||
/**
|
||||
* The current mode. Values:
|
||||
* 'a' (array),
|
||||
* 'd' (done),
|
||||
* 'i' (initial),
|
||||
* 'k' (key),
|
||||
* 'o' (object).
|
||||
*/
|
||||
protected char mode;
|
||||
|
||||
/**
|
||||
* The object/array stack.
|
||||
*/
|
||||
private final JSONObject stack[];
|
||||
|
||||
/**
|
||||
* The stack top index. A value of 0 indicates that the stack is empty.
|
||||
*/
|
||||
private int top;
|
||||
|
||||
/**
|
||||
* The writer that will receive the output.
|
||||
*/
|
||||
protected Writer writer;
|
||||
|
||||
/**
|
||||
* Make a fresh JSONWriter. It can be used to build one JSON text.
|
||||
*/
|
||||
public JSONWriter(Writer w) {
|
||||
this.comma = false;
|
||||
this.mode = 'i';
|
||||
this.stack = new JSONObject[maxdepth];
|
||||
this.top = 0;
|
||||
this.writer = w;
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a value.
|
||||
* @param string A string value.
|
||||
* @return this
|
||||
* @throws JSONException If the value is out of sequence.
|
||||
*/
|
||||
private JSONWriter append(String string) throws JSONException {
|
||||
if (string == null) {
|
||||
throw new JSONException("Null pointer");
|
||||
}
|
||||
if (this.mode == 'o' || this.mode == 'a') {
|
||||
try {
|
||||
if (this.comma && this.mode == 'a') {
|
||||
this.writer.write(',');
|
||||
}
|
||||
this.writer.write(string);
|
||||
} catch (IOException e) {
|
||||
throw new JSONException(e);
|
||||
}
|
||||
if (this.mode == 'o') {
|
||||
this.mode = 'k';
|
||||
}
|
||||
this.comma = true;
|
||||
return this;
|
||||
}
|
||||
throw new JSONException("Value out of sequence.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Begin appending a new array. All values until the balancing
|
||||
* <code>endArray</code> will be appended to this array. The
|
||||
* <code>endArray</code> method must be called to mark the array's end.
|
||||
* @return this
|
||||
* @throws JSONException If the nesting is too deep, or if the object is
|
||||
* started in the wrong place (for example as a key or after the end of the
|
||||
* outermost array or object).
|
||||
*/
|
||||
public JSONWriter array() throws JSONException {
|
||||
if (this.mode == 'i' || this.mode == 'o' || this.mode == 'a') {
|
||||
this.push(null);
|
||||
this.append("[");
|
||||
this.comma = false;
|
||||
return this;
|
||||
}
|
||||
throw new JSONException("Misplaced array.");
|
||||
}
|
||||
|
||||
/**
|
||||
* End something.
|
||||
* @param mode Mode
|
||||
* @param c Closing character
|
||||
* @return this
|
||||
* @throws JSONException If unbalanced.
|
||||
*/
|
||||
private JSONWriter end(char mode, char c) throws JSONException {
|
||||
if (this.mode != mode) {
|
||||
throw new JSONException(mode == 'a'
|
||||
? "Misplaced endArray."
|
||||
: "Misplaced endObject.");
|
||||
}
|
||||
this.pop(mode);
|
||||
try {
|
||||
this.writer.write(c);
|
||||
} catch (IOException e) {
|
||||
throw new JSONException(e);
|
||||
}
|
||||
this.comma = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* End an array. This method most be called to balance calls to
|
||||
* <code>array</code>.
|
||||
* @return this
|
||||
* @throws JSONException If incorrectly nested.
|
||||
*/
|
||||
public JSONWriter endArray() throws JSONException {
|
||||
return this.end('a', ']');
|
||||
}
|
||||
|
||||
/**
|
||||
* End an object. This method most be called to balance calls to
|
||||
* <code>object</code>.
|
||||
* @return this
|
||||
* @throws JSONException If incorrectly nested.
|
||||
*/
|
||||
public JSONWriter endObject() throws JSONException {
|
||||
return this.end('k', '}');
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a key. The key will be associated with the next value. In an
|
||||
* object, every value must be preceded by a key.
|
||||
* @param string A key string.
|
||||
* @return this
|
||||
* @throws JSONException If the key is out of place. For example, keys
|
||||
* do not belong in arrays or if the key is null.
|
||||
*/
|
||||
public JSONWriter key(String string) throws JSONException {
|
||||
if (string == null) {
|
||||
throw new JSONException("Null key.");
|
||||
}
|
||||
if (this.mode == 'k') {
|
||||
try {
|
||||
this.stack[this.top - 1].putOnce(string, Boolean.TRUE);
|
||||
if (this.comma) {
|
||||
this.writer.write(',');
|
||||
}
|
||||
this.writer.write(JSONObject.quote(string));
|
||||
this.writer.write(':');
|
||||
this.comma = false;
|
||||
this.mode = 'o';
|
||||
return this;
|
||||
} catch (IOException e) {
|
||||
throw new JSONException(e);
|
||||
}
|
||||
}
|
||||
throw new JSONException("Misplaced key.");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Begin appending a new object. All keys and values until the balancing
|
||||
* <code>endObject</code> will be appended to this object. The
|
||||
* <code>endObject</code> method must be called to mark the object's end.
|
||||
* @return this
|
||||
* @throws JSONException If the nesting is too deep, or if the object is
|
||||
* started in the wrong place (for example as a key or after the end of the
|
||||
* outermost array or object).
|
||||
*/
|
||||
public JSONWriter object() throws JSONException {
|
||||
if (this.mode == 'i') {
|
||||
this.mode = 'o';
|
||||
}
|
||||
if (this.mode == 'o' || this.mode == 'a') {
|
||||
this.append("{");
|
||||
this.push(new JSONObject());
|
||||
this.comma = false;
|
||||
return this;
|
||||
}
|
||||
throw new JSONException("Misplaced object.");
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Pop an array or object scope.
|
||||
* @param c The scope to close.
|
||||
* @throws JSONException If nesting is wrong.
|
||||
*/
|
||||
private void pop(char c) throws JSONException {
|
||||
if (this.top <= 0) {
|
||||
throw new JSONException("Nesting error.");
|
||||
}
|
||||
char m = this.stack[this.top - 1] == null ? 'a' : 'k';
|
||||
if (m != c) {
|
||||
throw new JSONException("Nesting error.");
|
||||
}
|
||||
this.top -= 1;
|
||||
this.mode = this.top == 0
|
||||
? 'd'
|
||||
: this.stack[this.top - 1] == null
|
||||
? 'a'
|
||||
: 'k';
|
||||
}
|
||||
|
||||
/**
|
||||
* Push an array or object scope.
|
||||
* @param jo The scope to open.
|
||||
* @throws JSONException If nesting is too deep.
|
||||
*/
|
||||
private void push(JSONObject jo) throws JSONException {
|
||||
if (this.top >= maxdepth) {
|
||||
throw new JSONException("Nesting too deep.");
|
||||
}
|
||||
this.stack[this.top] = jo;
|
||||
this.mode = jo == null ? 'a' : 'k';
|
||||
this.top += 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Append either the value <code>true</code> or the value
|
||||
* <code>false</code>.
|
||||
* @param b A boolean.
|
||||
* @return this
|
||||
* @throws JSONException
|
||||
*/
|
||||
public JSONWriter value(boolean b) throws JSONException {
|
||||
return this.append(b ? "true" : "false");
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a double value.
|
||||
* @param d A double.
|
||||
* @return this
|
||||
* @throws JSONException If the number is not finite.
|
||||
*/
|
||||
public JSONWriter value(double d) throws JSONException {
|
||||
return this.value(new Double(d));
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a long value.
|
||||
* @param l A long.
|
||||
* @return this
|
||||
* @throws JSONException
|
||||
*/
|
||||
public JSONWriter value(long l) throws JSONException {
|
||||
return this.append(Long.toString(l));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Append an object value.
|
||||
* @param object The object to append. It can be null, or a Boolean, Number,
|
||||
* String, JSONObject, or JSONArray, or an object that implements JSONString.
|
||||
* @return this
|
||||
* @throws JSONException If the value is out of sequence.
|
||||
*/
|
||||
public JSONWriter value(Object object) throws JSONException {
|
||||
return this.append(JSONObject.valueToString(object));
|
||||
}
|
||||
}
|
72
src/bindings/java/src/com/openalpr/jni/json/Property.java
Normal file
72
src/bindings/java/src/com/openalpr/jni/json/Property.java
Normal file
@@ -0,0 +1,72 @@
|
||||
package com.openalpr.jni.json;
|
||||
|
||||
/*
|
||||
Copyright (c) 2002 JSON.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
The Software shall be used for Good, not Evil.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
import java.util.Enumeration;
|
||||
import java.util.Iterator;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* Converts a Property file data into JSONObject and back.
|
||||
* @author JSON.org
|
||||
* @version 2014-05-03
|
||||
*/
|
||||
public class Property {
|
||||
/**
|
||||
* Converts a property file object into a JSONObject. The property file object is a table of name value pairs.
|
||||
* @param properties java.util.Properties
|
||||
* @return JSONObject
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static JSONObject toJSONObject(java.util.Properties properties) throws JSONException {
|
||||
JSONObject jo = new JSONObject();
|
||||
if (properties != null && !properties.isEmpty()) {
|
||||
Enumeration enumProperties = properties.propertyNames();
|
||||
while(enumProperties.hasMoreElements()) {
|
||||
String name = (String)enumProperties.nextElement();
|
||||
jo.put(name, properties.getProperty(name));
|
||||
}
|
||||
}
|
||||
return jo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the JSONObject into a property file object.
|
||||
* @param jo JSONObject
|
||||
* @return java.util.Properties
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static Properties toProperties(JSONObject jo) throws JSONException {
|
||||
Properties properties = new Properties();
|
||||
if (jo != null) {
|
||||
Iterator<String> keys = jo.keys();
|
||||
while (keys.hasNext()) {
|
||||
String name = keys.next();
|
||||
properties.put(name, jo.getString(name));
|
||||
}
|
||||
}
|
||||
return properties;
|
||||
}
|
||||
}
|
490
src/bindings/java/src/com/openalpr/jni/json/XML.java
Executable file
490
src/bindings/java/src/com/openalpr/jni/json/XML.java
Executable file
@@ -0,0 +1,490 @@
|
||||
package com.openalpr.jni.json;
|
||||
|
||||
/*
|
||||
Copyright (c) 2002 JSON.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
The Software shall be used for Good, not Evil.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* This provides static methods to convert an XML text into a JSONObject,
|
||||
* and to covert a JSONObject into an XML text.
|
||||
* @author JSON.org
|
||||
* @version 2014-05-03
|
||||
*/
|
||||
public class XML {
|
||||
|
||||
/** The Character '&'. */
|
||||
public static final Character AMP = '&';
|
||||
|
||||
/** The Character '''. */
|
||||
public static final Character APOS = '\'';
|
||||
|
||||
/** The Character '!'. */
|
||||
public static final Character BANG = '!';
|
||||
|
||||
/** The Character '='. */
|
||||
public static final Character EQ = '=';
|
||||
|
||||
/** The Character '>'. */
|
||||
public static final Character GT = '>';
|
||||
|
||||
/** The Character '<'. */
|
||||
public static final Character LT = '<';
|
||||
|
||||
/** The Character '?'. */
|
||||
public static final Character QUEST = '?';
|
||||
|
||||
/** The Character '"'. */
|
||||
public static final Character QUOT = '"';
|
||||
|
||||
/** The Character '/'. */
|
||||
public static final Character SLASH = '/';
|
||||
|
||||
/**
|
||||
* Replace special characters with XML escapes:
|
||||
* <pre>
|
||||
* & <small>(ampersand)</small> is replaced by &amp;
|
||||
* < <small>(less than)</small> is replaced by &lt;
|
||||
* > <small>(greater than)</small> is replaced by &gt;
|
||||
* " <small>(double quote)</small> is replaced by &quot;
|
||||
* </pre>
|
||||
* @param string The string to be escaped.
|
||||
* @return The escaped string.
|
||||
*/
|
||||
public static String escape(String string) {
|
||||
StringBuilder sb = new StringBuilder(string.length());
|
||||
for (int i = 0, length = string.length(); i < length; i++) {
|
||||
char c = string.charAt(i);
|
||||
switch (c) {
|
||||
case '&':
|
||||
sb.append("&");
|
||||
break;
|
||||
case '<':
|
||||
sb.append("<");
|
||||
break;
|
||||
case '>':
|
||||
sb.append(">");
|
||||
break;
|
||||
case '"':
|
||||
sb.append(""");
|
||||
break;
|
||||
case '\'':
|
||||
sb.append("'");
|
||||
break;
|
||||
default:
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Throw an exception if the string contains whitespace.
|
||||
* Whitespace is not allowed in tagNames and attributes.
|
||||
* @param string A string.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static void noSpace(String string) throws JSONException {
|
||||
int i, length = string.length();
|
||||
if (length == 0) {
|
||||
throw new JSONException("Empty string.");
|
||||
}
|
||||
for (i = 0; i < length; i += 1) {
|
||||
if (Character.isWhitespace(string.charAt(i))) {
|
||||
throw new JSONException("'" + string +
|
||||
"' contains a space character.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scan the content following the named tag, attaching it to the context.
|
||||
* @param x The XMLTokener containing the source string.
|
||||
* @param context The JSONObject that will include the new material.
|
||||
* @param name The tag name.
|
||||
* @return true if the close tag is processed.
|
||||
* @throws JSONException
|
||||
*/
|
||||
private static boolean parse(XMLTokener x, JSONObject context,
|
||||
String name) throws JSONException {
|
||||
char c;
|
||||
int i;
|
||||
JSONObject jsonobject = null;
|
||||
String string;
|
||||
String tagName;
|
||||
Object token;
|
||||
|
||||
// Test for and skip past these forms:
|
||||
// <!-- ... -->
|
||||
// <! ... >
|
||||
// <![ ... ]]>
|
||||
// <? ... ?>
|
||||
// Report errors for these forms:
|
||||
// <>
|
||||
// <=
|
||||
// <<
|
||||
|
||||
token = x.nextToken();
|
||||
|
||||
// <!
|
||||
|
||||
if (token == BANG) {
|
||||
c = x.next();
|
||||
if (c == '-') {
|
||||
if (x.next() == '-') {
|
||||
x.skipPast("-->");
|
||||
return false;
|
||||
}
|
||||
x.back();
|
||||
} else if (c == '[') {
|
||||
token = x.nextToken();
|
||||
if ("CDATA".equals(token)) {
|
||||
if (x.next() == '[') {
|
||||
string = x.nextCDATA();
|
||||
if (string.length() > 0) {
|
||||
context.accumulate("content", string);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
throw x.syntaxError("Expected 'CDATA['");
|
||||
}
|
||||
i = 1;
|
||||
do {
|
||||
token = x.nextMeta();
|
||||
if (token == null) {
|
||||
throw x.syntaxError("Missing '>' after '<!'.");
|
||||
} else if (token == LT) {
|
||||
i += 1;
|
||||
} else if (token == GT) {
|
||||
i -= 1;
|
||||
}
|
||||
} while (i > 0);
|
||||
return false;
|
||||
} else if (token == QUEST) {
|
||||
|
||||
// <?
|
||||
|
||||
x.skipPast("?>");
|
||||
return false;
|
||||
} else if (token == SLASH) {
|
||||
|
||||
// Close tag </
|
||||
|
||||
token = x.nextToken();
|
||||
if (name == null) {
|
||||
throw x.syntaxError("Mismatched close tag " + token);
|
||||
}
|
||||
if (!token.equals(name)) {
|
||||
throw x.syntaxError("Mismatched " + name + " and " + token);
|
||||
}
|
||||
if (x.nextToken() != GT) {
|
||||
throw x.syntaxError("Misshaped close tag");
|
||||
}
|
||||
return true;
|
||||
|
||||
} else if (token instanceof Character) {
|
||||
throw x.syntaxError("Misshaped tag");
|
||||
|
||||
// Open tag <
|
||||
|
||||
} else {
|
||||
tagName = (String)token;
|
||||
token = null;
|
||||
jsonobject = new JSONObject();
|
||||
for (;;) {
|
||||
if (token == null) {
|
||||
token = x.nextToken();
|
||||
}
|
||||
|
||||
// attribute = value
|
||||
|
||||
if (token instanceof String) {
|
||||
string = (String)token;
|
||||
token = x.nextToken();
|
||||
if (token == EQ) {
|
||||
token = x.nextToken();
|
||||
if (!(token instanceof String)) {
|
||||
throw x.syntaxError("Missing value");
|
||||
}
|
||||
jsonobject.accumulate(string,
|
||||
XML.stringToValue((String)token));
|
||||
token = null;
|
||||
} else {
|
||||
jsonobject.accumulate(string, "");
|
||||
}
|
||||
|
||||
// Empty tag <.../>
|
||||
|
||||
} else if (token == SLASH) {
|
||||
if (x.nextToken() != GT) {
|
||||
throw x.syntaxError("Misshaped tag");
|
||||
}
|
||||
if (jsonobject.length() > 0) {
|
||||
context.accumulate(tagName, jsonobject);
|
||||
} else {
|
||||
context.accumulate(tagName, "");
|
||||
}
|
||||
return false;
|
||||
|
||||
// Content, between <...> and </...>
|
||||
|
||||
} else if (token == GT) {
|
||||
for (;;) {
|
||||
token = x.nextContent();
|
||||
if (token == null) {
|
||||
if (tagName != null) {
|
||||
throw x.syntaxError("Unclosed tag " + tagName);
|
||||
}
|
||||
return false;
|
||||
} else if (token instanceof String) {
|
||||
string = (String)token;
|
||||
if (string.length() > 0) {
|
||||
jsonobject.accumulate("content",
|
||||
XML.stringToValue(string));
|
||||
}
|
||||
|
||||
// Nested element
|
||||
|
||||
} else if (token == LT) {
|
||||
if (parse(x, jsonobject, tagName)) {
|
||||
if (jsonobject.length() == 0) {
|
||||
context.accumulate(tagName, "");
|
||||
} else if (jsonobject.length() == 1 &&
|
||||
jsonobject.opt("content") != null) {
|
||||
context.accumulate(tagName,
|
||||
jsonobject.opt("content"));
|
||||
} else {
|
||||
context.accumulate(tagName, jsonobject);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw x.syntaxError("Misshaped tag");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Try to convert a string into a number, boolean, or null. If the string
|
||||
* can't be converted, return the string. This is much less ambitious than
|
||||
* JSONObject.stringToValue, especially because it does not attempt to
|
||||
* convert plus forms, octal forms, hex forms, or E forms lacking decimal
|
||||
* points.
|
||||
* @param string A String.
|
||||
* @return A simple JSON value.
|
||||
*/
|
||||
public static Object stringToValue(String string) {
|
||||
if ("true".equalsIgnoreCase(string)) {
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
if ("false".equalsIgnoreCase(string)) {
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
if ("null".equalsIgnoreCase(string)) {
|
||||
return JSONObject.NULL;
|
||||
}
|
||||
|
||||
// If it might be a number, try converting it, first as a Long, and then as a
|
||||
// Double. If that doesn't work, return the string.
|
||||
|
||||
try {
|
||||
char initial = string.charAt(0);
|
||||
if (initial == '-' || (initial >= '0' && initial <= '9')) {
|
||||
Long value = new Long(string);
|
||||
if (value.toString().equals(string)) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
} catch (Exception ignore) {
|
||||
try {
|
||||
Double value = new Double(string);
|
||||
if (value.toString().equals(string)) {
|
||||
return value;
|
||||
}
|
||||
} catch (Exception ignoreAlso) {
|
||||
}
|
||||
}
|
||||
return string;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert a well-formed (but not necessarily valid) XML string into a
|
||||
* JSONObject. Some information may be lost in this transformation
|
||||
* because JSON is a data format and XML is a document format. XML uses
|
||||
* elements, attributes, and content text, while JSON uses unordered
|
||||
* collections of name/value pairs and arrays of values. JSON does not
|
||||
* does not like to distinguish between elements and attributes.
|
||||
* Sequences of similar elements are represented as JSONArrays. Content
|
||||
* text may be placed in a "content" member. Comments, prologs, DTDs, and
|
||||
* <code><[ [ ]]></code> are ignored.
|
||||
* @param string The source string.
|
||||
* @return A JSONObject containing the structured data from the XML string.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static JSONObject toJSONObject(String string) throws JSONException {
|
||||
JSONObject jo = new JSONObject();
|
||||
XMLTokener x = new XMLTokener(string);
|
||||
while (x.more() && x.skipPast("<")) {
|
||||
parse(x, jo, null);
|
||||
}
|
||||
return jo;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert a JSONObject into a well-formed, element-normal XML string.
|
||||
* @param object A JSONObject.
|
||||
* @return A string.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static String toString(Object object) throws JSONException {
|
||||
return toString(object, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert a JSONObject into a well-formed, element-normal XML string.
|
||||
* @param object A JSONObject.
|
||||
* @param tagName The optional name of the enclosing tag.
|
||||
* @return A string.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static String toString(Object object, String tagName)
|
||||
throws JSONException {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int i;
|
||||
JSONArray ja;
|
||||
JSONObject jo;
|
||||
String key;
|
||||
Iterator<String> keys;
|
||||
int length;
|
||||
String string;
|
||||
Object value;
|
||||
if (object instanceof JSONObject) {
|
||||
|
||||
// Emit <tagName>
|
||||
|
||||
if (tagName != null) {
|
||||
sb.append('<');
|
||||
sb.append(tagName);
|
||||
sb.append('>');
|
||||
}
|
||||
|
||||
// Loop thru the keys.
|
||||
|
||||
jo = (JSONObject)object;
|
||||
keys = jo.keys();
|
||||
while (keys.hasNext()) {
|
||||
key = keys.next();
|
||||
value = jo.opt(key);
|
||||
if (value == null) {
|
||||
value = "";
|
||||
}
|
||||
string = value instanceof String ? (String)value : null;
|
||||
|
||||
// Emit content in body
|
||||
|
||||
if ("content".equals(key)) {
|
||||
if (value instanceof JSONArray) {
|
||||
ja = (JSONArray)value;
|
||||
length = ja.length();
|
||||
for (i = 0; i < length; i += 1) {
|
||||
if (i > 0) {
|
||||
sb.append('\n');
|
||||
}
|
||||
sb.append(escape(ja.get(i).toString()));
|
||||
}
|
||||
} else {
|
||||
sb.append(escape(value.toString()));
|
||||
}
|
||||
|
||||
// Emit an array of similar keys
|
||||
|
||||
} else if (value instanceof JSONArray) {
|
||||
ja = (JSONArray)value;
|
||||
length = ja.length();
|
||||
for (i = 0; i < length; i += 1) {
|
||||
value = ja.get(i);
|
||||
if (value instanceof JSONArray) {
|
||||
sb.append('<');
|
||||
sb.append(key);
|
||||
sb.append('>');
|
||||
sb.append(toString(value));
|
||||
sb.append("</");
|
||||
sb.append(key);
|
||||
sb.append('>');
|
||||
} else {
|
||||
sb.append(toString(value, key));
|
||||
}
|
||||
}
|
||||
} else if ("".equals(value)) {
|
||||
sb.append('<');
|
||||
sb.append(key);
|
||||
sb.append("/>");
|
||||
|
||||
// Emit a new tag <k>
|
||||
|
||||
} else {
|
||||
sb.append(toString(value, key));
|
||||
}
|
||||
}
|
||||
if (tagName != null) {
|
||||
|
||||
// Emit the </tagname> close tag
|
||||
|
||||
sb.append("</");
|
||||
sb.append(tagName);
|
||||
sb.append('>');
|
||||
}
|
||||
return sb.toString();
|
||||
|
||||
// XML does not have good support for arrays. If an array appears in a place
|
||||
// where XML is lacking, synthesize an <array> element.
|
||||
|
||||
} else {
|
||||
if (object.getClass().isArray()) {
|
||||
object = new JSONArray(object);
|
||||
}
|
||||
if (object instanceof JSONArray) {
|
||||
ja = (JSONArray)object;
|
||||
length = ja.length();
|
||||
for (i = 0; i < length; i += 1) {
|
||||
sb.append(toString(ja.opt(i), tagName == null ? "array" : tagName));
|
||||
}
|
||||
return sb.toString();
|
||||
} else {
|
||||
string = (object == null) ? "null" : escape(object.toString());
|
||||
return (tagName == null) ? "\"" + string + "\"" :
|
||||
(string.length() == 0) ? "<" + tagName + "/>" :
|
||||
"<" + tagName + ">" + string + "</" + tagName + ">";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
365
src/bindings/java/src/com/openalpr/jni/json/XMLTokener.java
Executable file
365
src/bindings/java/src/com/openalpr/jni/json/XMLTokener.java
Executable file
@@ -0,0 +1,365 @@
|
||||
package com.openalpr.jni.json;
|
||||
|
||||
/*
|
||||
Copyright (c) 2002 JSON.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
The Software shall be used for Good, not Evil.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The XMLTokener extends the JSONTokener to provide additional methods
|
||||
* for the parsing of XML texts.
|
||||
* @author JSON.org
|
||||
* @version 2014-05-03
|
||||
*/
|
||||
public class XMLTokener extends JSONTokener {
|
||||
|
||||
|
||||
/** The table of entity values. It initially contains Character values for
|
||||
* amp, apos, gt, lt, quot.
|
||||
*/
|
||||
public static final java.util.HashMap<String, Character> entity;
|
||||
|
||||
static {
|
||||
entity = new java.util.HashMap<String, Character>(8);
|
||||
entity.put("amp", XML.AMP);
|
||||
entity.put("apos", XML.APOS);
|
||||
entity.put("gt", XML.GT);
|
||||
entity.put("lt", XML.LT);
|
||||
entity.put("quot", XML.QUOT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an XMLTokener from a string.
|
||||
* @param s A source string.
|
||||
*/
|
||||
public XMLTokener(String s) {
|
||||
super(s);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the text in the CDATA block.
|
||||
* @return The string up to the <code>]]></code>.
|
||||
* @throws JSONException If the <code>]]></code> is not found.
|
||||
*/
|
||||
public String nextCDATA() throws JSONException {
|
||||
char c;
|
||||
int i;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (;;) {
|
||||
c = next();
|
||||
if (end()) {
|
||||
throw syntaxError("Unclosed CDATA");
|
||||
}
|
||||
sb.append(c);
|
||||
i = sb.length() - 3;
|
||||
if (i >= 0 && sb.charAt(i) == ']' &&
|
||||
sb.charAt(i + 1) == ']' && sb.charAt(i + 2) == '>') {
|
||||
sb.setLength(i);
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the next XML outer token, trimming whitespace. There are two kinds
|
||||
* of tokens: the '<' character which begins a markup tag, and the content
|
||||
* text between markup tags.
|
||||
*
|
||||
* @return A string, or a '<' Character, or null if there is no more
|
||||
* source text.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public Object nextContent() throws JSONException {
|
||||
char c;
|
||||
StringBuilder sb;
|
||||
do {
|
||||
c = next();
|
||||
} while (Character.isWhitespace(c));
|
||||
if (c == 0) {
|
||||
return null;
|
||||
}
|
||||
if (c == '<') {
|
||||
return XML.LT;
|
||||
}
|
||||
sb = new StringBuilder();
|
||||
for (;;) {
|
||||
if (c == '<' || c == 0) {
|
||||
back();
|
||||
return sb.toString().trim();
|
||||
}
|
||||
if (c == '&') {
|
||||
sb.append(nextEntity(c));
|
||||
} else {
|
||||
sb.append(c);
|
||||
}
|
||||
c = next();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the next entity. These entities are translated to Characters:
|
||||
* <code>& ' > < "</code>.
|
||||
* @param ampersand An ampersand character.
|
||||
* @return A Character or an entity String if the entity is not recognized.
|
||||
* @throws JSONException If missing ';' in XML entity.
|
||||
*/
|
||||
public Object nextEntity(char ampersand) throws JSONException {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (;;) {
|
||||
char c = next();
|
||||
if (Character.isLetterOrDigit(c) || c == '#') {
|
||||
sb.append(Character.toLowerCase(c));
|
||||
} else if (c == ';') {
|
||||
break;
|
||||
} else {
|
||||
throw syntaxError("Missing ';' in XML entity: &" + sb);
|
||||
}
|
||||
}
|
||||
String string = sb.toString();
|
||||
Object object = entity.get(string);
|
||||
return object != null ? object : ampersand + string + ";";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the next XML meta token. This is used for skipping over <!...>
|
||||
* and <?...?> structures.
|
||||
* @return Syntax characters (<code>< > / = ! ?</code>) are returned as
|
||||
* Character, and strings and names are returned as Boolean. We don't care
|
||||
* what the values actually are.
|
||||
* @throws JSONException If a string is not properly closed or if the XML
|
||||
* is badly structured.
|
||||
*/
|
||||
public Object nextMeta() throws JSONException {
|
||||
char c;
|
||||
char q;
|
||||
do {
|
||||
c = next();
|
||||
} while (Character.isWhitespace(c));
|
||||
switch (c) {
|
||||
case 0:
|
||||
throw syntaxError("Misshaped meta tag");
|
||||
case '<':
|
||||
return XML.LT;
|
||||
case '>':
|
||||
return XML.GT;
|
||||
case '/':
|
||||
return XML.SLASH;
|
||||
case '=':
|
||||
return XML.EQ;
|
||||
case '!':
|
||||
return XML.BANG;
|
||||
case '?':
|
||||
return XML.QUEST;
|
||||
case '"':
|
||||
case '\'':
|
||||
q = c;
|
||||
for (;;) {
|
||||
c = next();
|
||||
if (c == 0) {
|
||||
throw syntaxError("Unterminated string");
|
||||
}
|
||||
if (c == q) {
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
}
|
||||
default:
|
||||
for (;;) {
|
||||
c = next();
|
||||
if (Character.isWhitespace(c)) {
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
switch (c) {
|
||||
case 0:
|
||||
case '<':
|
||||
case '>':
|
||||
case '/':
|
||||
case '=':
|
||||
case '!':
|
||||
case '?':
|
||||
case '"':
|
||||
case '\'':
|
||||
back();
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the next XML Token. These tokens are found inside of angle
|
||||
* brackets. It may be one of these characters: <code>/ > = ! ?</code> or it
|
||||
* may be a string wrapped in single quotes or double quotes, or it may be a
|
||||
* name.
|
||||
* @return a String or a Character.
|
||||
* @throws JSONException If the XML is not well formed.
|
||||
*/
|
||||
public Object nextToken() throws JSONException {
|
||||
char c;
|
||||
char q;
|
||||
StringBuilder sb;
|
||||
do {
|
||||
c = next();
|
||||
} while (Character.isWhitespace(c));
|
||||
switch (c) {
|
||||
case 0:
|
||||
throw syntaxError("Misshaped element");
|
||||
case '<':
|
||||
throw syntaxError("Misplaced '<'");
|
||||
case '>':
|
||||
return XML.GT;
|
||||
case '/':
|
||||
return XML.SLASH;
|
||||
case '=':
|
||||
return XML.EQ;
|
||||
case '!':
|
||||
return XML.BANG;
|
||||
case '?':
|
||||
return XML.QUEST;
|
||||
|
||||
// Quoted string
|
||||
|
||||
case '"':
|
||||
case '\'':
|
||||
q = c;
|
||||
sb = new StringBuilder();
|
||||
for (;;) {
|
||||
c = next();
|
||||
if (c == 0) {
|
||||
throw syntaxError("Unterminated string");
|
||||
}
|
||||
if (c == q) {
|
||||
return sb.toString();
|
||||
}
|
||||
if (c == '&') {
|
||||
sb.append(nextEntity(c));
|
||||
} else {
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
default:
|
||||
|
||||
// Name
|
||||
|
||||
sb = new StringBuilder();
|
||||
for (;;) {
|
||||
sb.append(c);
|
||||
c = next();
|
||||
if (Character.isWhitespace(c)) {
|
||||
return sb.toString();
|
||||
}
|
||||
switch (c) {
|
||||
case 0:
|
||||
return sb.toString();
|
||||
case '>':
|
||||
case '/':
|
||||
case '=':
|
||||
case '!':
|
||||
case '?':
|
||||
case '[':
|
||||
case ']':
|
||||
back();
|
||||
return sb.toString();
|
||||
case '<':
|
||||
case '"':
|
||||
case '\'':
|
||||
throw syntaxError("Bad character in a name");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Skip characters until past the requested string.
|
||||
* If it is not found, we are left at the end of the source with a result of false.
|
||||
* @param to A string to skip past.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public boolean skipPast(String to) throws JSONException {
|
||||
boolean b;
|
||||
char c;
|
||||
int i;
|
||||
int j;
|
||||
int offset = 0;
|
||||
int length = to.length();
|
||||
char[] circle = new char[length];
|
||||
|
||||
/*
|
||||
* First fill the circle buffer with as many characters as are in the
|
||||
* to string. If we reach an early end, bail.
|
||||
*/
|
||||
|
||||
for (i = 0; i < length; i += 1) {
|
||||
c = next();
|
||||
if (c == 0) {
|
||||
return false;
|
||||
}
|
||||
circle[i] = c;
|
||||
}
|
||||
|
||||
/* We will loop, possibly for all of the remaining characters. */
|
||||
|
||||
for (;;) {
|
||||
j = offset;
|
||||
b = true;
|
||||
|
||||
/* Compare the circle buffer with the to string. */
|
||||
|
||||
for (i = 0; i < length; i += 1) {
|
||||
if (circle[j] != to.charAt(i)) {
|
||||
b = false;
|
||||
break;
|
||||
}
|
||||
j += 1;
|
||||
if (j >= length) {
|
||||
j -= length;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we exit the loop with b intact, then victory is ours. */
|
||||
|
||||
if (b) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Get the next character. If there isn't one, then defeat is ours. */
|
||||
|
||||
c = next();
|
||||
if (c == 0) {
|
||||
return false;
|
||||
}
|
||||
/*
|
||||
* Shove the character in the circle buffer and advance the
|
||||
* circle offset. The offset is mod n.
|
||||
*/
|
||||
circle[offset] = c;
|
||||
offset += 1;
|
||||
if (offset >= length) {
|
||||
offset -= length;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
3
src/bindings/python/.gitignore
vendored
Normal file
3
src/bindings/python/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
*.pyc
|
||||
*.so
|
||||
.idea/
|
10
src/bindings/python/make.sh
Executable file
10
src/bindings/python/make.sh
Executable file
@@ -0,0 +1,10 @@
|
||||
#!/bin/bash
|
||||
|
||||
OPENALPR_INCLUDE_DIR=/storage/projects/alpr/src/openalpr/
|
||||
OPENALPR_LIB_DIR=/storage/projects/alpr/src/build/openalpr/
|
||||
|
||||
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.:${OPENALPR_LIB_DIR}
|
||||
|
||||
g++ -Wall -L${OPENALPR_LIB_DIR} -I${OPENALPR_INCLUDE_DIR} -shared -fPIC -o libopenalprpy.so openalprpy.cpp -lopenalpr
|
||||
|
||||
python test.py
|
91
src/bindings/python/openalpr.py
Normal file
91
src/bindings/python/openalpr.py
Normal file
@@ -0,0 +1,91 @@
|
||||
import ctypes
|
||||
import json
|
||||
import platform
|
||||
|
||||
class Alpr():
|
||||
def __init__(self, country, config_file, runtime_dir):
|
||||
|
||||
# Load the .dll for Windows and the .so for Unix-based
|
||||
if platform.system().lower().find("windows") != -1:
|
||||
self._openalprpy_lib = ctypes.cdll.LoadLibrary("openalprpy.dll")
|
||||
else:
|
||||
self._openalprpy_lib = ctypes.cdll.LoadLibrary("libopenalprpy.so")
|
||||
|
||||
|
||||
self._initialize_func = self._openalprpy_lib.initialize
|
||||
self._initialize_func.argtypes = [ctypes.c_char_p, ctypes.c_char_p, ctypes.c_char_p]
|
||||
|
||||
self._dispose_func = self._openalprpy_lib.dispose
|
||||
|
||||
self._is_loaded_func = self._openalprpy_lib.isLoaded
|
||||
self._is_loaded_func.restype = ctypes.c_bool
|
||||
|
||||
self._recognize_file_func = self._openalprpy_lib.recognizeFile
|
||||
self._recognize_file_func.restype = ctypes.c_void_p
|
||||
self._recognize_file_func.argtypes = [ctypes.c_char_p]
|
||||
|
||||
self._recognize_array_func = self._openalprpy_lib.recognizeArray
|
||||
self._recognize_array_func.restype = ctypes.c_void_p
|
||||
self._recognize_array_func.argtypes = [ctypes.POINTER(ctypes.c_ubyte), ctypes.c_uint]
|
||||
|
||||
self._free_json_mem_func = self._openalprpy_lib.freeJsonMem
|
||||
|
||||
|
||||
self._set_default_region_func = self._openalprpy_lib.setDefaultRegion
|
||||
self._set_default_region_func.argtypes = [ctypes.c_char_p]
|
||||
|
||||
self._set_detect_region_func = self._openalprpy_lib.setDetectRegion
|
||||
self._set_detect_region_func.argtypes = [ctypes.c_bool]
|
||||
|
||||
|
||||
self._set_top_n_func = self._openalprpy_lib.setTopN
|
||||
self._set_top_n_func.argtypes = [ctypes.c_int]
|
||||
|
||||
self._get_version_func = self._openalprpy_lib.getVersion
|
||||
self._get_version_func.restype = ctypes.c_void_p
|
||||
|
||||
self._initialize_func(country, config_file, runtime_dir)
|
||||
|
||||
|
||||
def unload(self):
|
||||
self._openalprpy_lib.dispose()
|
||||
|
||||
def is_loaded(self):
|
||||
return self._is_loaded_func()
|
||||
|
||||
def recognize_file(self, file_path):
|
||||
ptr = self._recognize_file_func(file_path)
|
||||
json_data = ctypes.cast(ptr, ctypes.c_char_p).value
|
||||
response_obj = json.loads(json_data)
|
||||
self._free_json_mem_func(ptr)
|
||||
|
||||
return response_obj
|
||||
|
||||
def recognize_array(self, byte_array):
|
||||
|
||||
pb = ctypes.cast(byte_array, ctypes.POINTER(ctypes.c_ubyte))
|
||||
ptr = self._recognize_array_func(pb, len(byte_array))
|
||||
json_data = ctypes.cast(ptr, ctypes.c_char_p).value
|
||||
response_obj = json.loads(json_data)
|
||||
self._free_json_mem_func(ptr)
|
||||
|
||||
return response_obj
|
||||
|
||||
def get_version(self):
|
||||
|
||||
ptr = self._get_version_func()
|
||||
version_number = ctypes.cast(ptr, ctypes.c_char_p).value
|
||||
self._free_json_mem_func(ptr)
|
||||
|
||||
return version_number
|
||||
|
||||
def set_top_n(self, topn):
|
||||
self._set_top_n_func(topn)
|
||||
|
||||
def set_default_region(self, region):
|
||||
self._set_default_region_func(region)
|
||||
|
||||
def set_detect_region(self, enabled):
|
||||
self._set_detect_region_func(enabled)
|
||||
|
||||
|
129
src/bindings/python/openalprpy.cpp
Normal file
129
src/bindings/python/openalprpy.cpp
Normal file
@@ -0,0 +1,129 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <alpr.h>
|
||||
|
||||
extern "C" {
|
||||
|
||||
using namespace alpr;
|
||||
|
||||
bool initialized = false;
|
||||
static Alpr* nativeAlpr;
|
||||
|
||||
void initialize(char* ccountry, char* cconfigFile, char* cruntimeDir)
|
||||
{
|
||||
//printf("Initialize");
|
||||
|
||||
// Convert strings from char* to string
|
||||
std::string country(ccountry);
|
||||
std::string configFile(cconfigFile);
|
||||
std::string runtimeDir(cruntimeDir);
|
||||
|
||||
//std::cout << country << std::endl << configFile << std::endl << runtimeDir << std::endl;
|
||||
nativeAlpr = new alpr::Alpr(country, configFile, runtimeDir);
|
||||
|
||||
initialized = true;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void dispose()
|
||||
{
|
||||
//printf("Dispose");
|
||||
initialized = false;
|
||||
delete nativeAlpr;
|
||||
}
|
||||
|
||||
|
||||
bool isLoaded()
|
||||
{
|
||||
//printf("IS LOADED");
|
||||
|
||||
if (!initialized)
|
||||
return false;
|
||||
|
||||
return nativeAlpr->isLoaded();
|
||||
|
||||
}
|
||||
|
||||
char* recognizeFile(char* cimageFile)
|
||||
{
|
||||
//printf("Recognize file");
|
||||
|
||||
// Convert strings from java to C++ and release resources
|
||||
std::string imageFile(cimageFile);
|
||||
|
||||
AlprResults results = nativeAlpr->recognize(imageFile);
|
||||
|
||||
std::string json = Alpr::toJson(results);
|
||||
|
||||
int strsize = sizeof(char) * (strlen(json.c_str()) + 1);
|
||||
char* membuffer = (char*)malloc(strsize);
|
||||
strcpy(membuffer, json.c_str());
|
||||
//printf("allocated address: %p\n", membuffer);
|
||||
|
||||
return membuffer;
|
||||
}
|
||||
|
||||
void freeJsonMem(char* ptr)
|
||||
{
|
||||
//printf("freeing address: %p\n", ptr);
|
||||
free( ptr );
|
||||
}
|
||||
|
||||
|
||||
char* recognizeArray(unsigned char* buf, int len)
|
||||
{
|
||||
//printf("Recognize byte array");
|
||||
//printf("buffer pointer: %p\n", buf);
|
||||
//printf("buffer length: %d\n", len);
|
||||
|
||||
|
||||
std::vector<char> cvec(buf, buf+len);
|
||||
|
||||
AlprResults results = nativeAlpr->recognize(cvec);
|
||||
std::string json = Alpr::toJson(results);
|
||||
|
||||
int strsize = sizeof(char) * (strlen(json.c_str()) + 1);
|
||||
char* membuffer = (char*)malloc(strsize);
|
||||
strcpy(membuffer, json.c_str());
|
||||
//printf("allocated address: %p\n", membuffer);
|
||||
|
||||
return membuffer;
|
||||
}
|
||||
|
||||
void setDefaultRegion(char* cdefault_region)
|
||||
{
|
||||
// Convert strings from java to C++ and release resources
|
||||
std::string default_region(cdefault_region);
|
||||
|
||||
nativeAlpr->setDefaultRegion(default_region);
|
||||
}
|
||||
|
||||
void setDetectRegion(bool detect_region)
|
||||
{
|
||||
nativeAlpr->setDetectRegion(detect_region);
|
||||
}
|
||||
|
||||
void setTopN(int top_n)
|
||||
{
|
||||
nativeAlpr->setTopN(top_n);
|
||||
}
|
||||
|
||||
char* getVersion()
|
||||
{
|
||||
std::string version = nativeAlpr->getVersion();
|
||||
|
||||
int strsize = sizeof(char) * (strlen(version.c_str()) + 1);
|
||||
char* membuffer = (char*)malloc(strsize);
|
||||
strcpy(membuffer, version.c_str());
|
||||
//printf("allocated address: %p\n", membuffer);
|
||||
|
||||
return membuffer;
|
||||
}
|
||||
|
||||
|
||||
}
|
40
src/bindings/python/test.py
Normal file
40
src/bindings/python/test.py
Normal file
@@ -0,0 +1,40 @@
|
||||
from openalpr import Alpr
|
||||
|
||||
|
||||
try:
|
||||
alpr = Alpr("us", "/etc/openalpr/openalpr.conf", "/usr/share/openalpr/runtime_data")
|
||||
|
||||
if not alpr.is_loaded():
|
||||
print("Error loading OpenALPR")
|
||||
else:
|
||||
print("Using OpenALPR " + alpr.get_version())
|
||||
|
||||
alpr.set_top_n(7)
|
||||
alpr.set_default_region("wa")
|
||||
alpr.set_detect_region(False)
|
||||
jpeg_bytes = open("/storage/projects/alpr/samples/testing/car1.jpg", "rb").read()
|
||||
results = alpr.recognize_array(jpeg_bytes)
|
||||
|
||||
# Uncomment to see the full results structure
|
||||
# import pprint
|
||||
# pprint.pprint(results)
|
||||
|
||||
print("Image size: %dx%d" %(results['img_width'], results['img_height']))
|
||||
print("Processing Time: %f" % results['processing_time_ms'])
|
||||
|
||||
i = 0
|
||||
for plate in results['results']:
|
||||
i += 1
|
||||
print("Plate #%d" % i)
|
||||
print(" %12s %12s" % ("Plate", "Confidence"))
|
||||
for candidate in plate['candidates']:
|
||||
prefix = "-"
|
||||
if candidate['matches_template']:
|
||||
prefix = "*"
|
||||
|
||||
print(" %s %12s%12f" % (prefix, candidate['plate'], candidate['confidence']))
|
||||
|
||||
|
||||
|
||||
finally:
|
||||
alpr.unload()
|
Reference in New Issue
Block a user