mirror of https://github.com/apache/lucene.git
SOLR-4607: use noggit 0.5 release jar
git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1457811 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
a4d66b3e1d
commit
edc777e22e
|
@ -197,6 +197,11 @@
|
|||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.noggit</groupId>
|
||||
<artifactId>noggit</artifactId>
|
||||
<version>0.5</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-lang</groupId>
|
||||
<artifactId>commons-lang</artifactId>
|
||||
|
|
|
@ -85,6 +85,10 @@
|
|||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.noggit</groupId>
|
||||
<artifactId>noggit</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
|
|
|
@ -183,6 +183,8 @@ Other Changes
|
|||
* SOLR-4544: Refactor HttpShardHandlerFactory so load-balancing logic can be customized.
|
||||
(Ryan Ernst via Robert Muir)
|
||||
|
||||
* SOLR-4607: Use noggit 0.5 release jar rather than a forked copy. (Yonik Seeley, Robert Muir)
|
||||
|
||||
================== 4.2.1 ==================
|
||||
|
||||
Versions of Major Components
|
||||
|
|
|
@ -22,8 +22,8 @@ import java.io.StringReader;
|
|||
import java.util.*;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.noggit.JSONParser;
|
||||
import org.apache.noggit.ObjectBuilder;
|
||||
import org.noggit.JSONParser;
|
||||
import org.noggit.ObjectBuilder;
|
||||
import org.apache.solr.common.SolrException;
|
||||
import org.apache.solr.common.SolrInputDocument;
|
||||
import org.apache.solr.common.SolrInputField;
|
||||
|
|
|
@ -23,9 +23,9 @@ import org.apache.lucene.util.Attribute;
|
|||
import org.apache.lucene.util.AttributeSource;
|
||||
import org.apache.lucene.util.AttributeSource.State;
|
||||
import org.apache.lucene.util.BytesRef;
|
||||
import org.apache.noggit.JSONUtil;
|
||||
import org.apache.noggit.JSONWriter;
|
||||
import org.apache.noggit.ObjectBuilder;
|
||||
import org.noggit.JSONUtil;
|
||||
import org.noggit.JSONWriter;
|
||||
import org.noggit.ObjectBuilder;
|
||||
import org.apache.solr.common.util.Base64;
|
||||
import org.apache.solr.schema.PreAnalyzedField.ParseResult;
|
||||
import org.apache.solr.schema.PreAnalyzedField.PreAnalyzedParser;
|
||||
|
|
|
@ -24,7 +24,7 @@ import java.util.HashMap;
|
|||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.noggit.JSONParser;
|
||||
import org.noggit.JSONParser;
|
||||
import org.apache.lucene.analysis.util.ResourceLoader;
|
||||
import org.apache.lucene.util.IOUtils;
|
||||
import org.apache.solr.common.SolrException;
|
||||
|
|
|
@ -32,8 +32,8 @@ import javax.servlet.http.HttpServletResponse;
|
|||
|
||||
import org.apache.lucene.util.BytesRef;
|
||||
import org.apache.lucene.util.IOUtils;
|
||||
import org.apache.noggit.CharArr;
|
||||
import org.apache.noggit.JSONWriter;
|
||||
import org.noggit.CharArr;
|
||||
import org.noggit.JSONWriter;
|
||||
import org.apache.solr.cloud.ZkController;
|
||||
import org.apache.solr.common.SolrException;
|
||||
import org.apache.solr.common.cloud.SolrZkClient;
|
||||
|
|
|
@ -18,8 +18,8 @@
|
|||
package org.apache.solr;
|
||||
|
||||
import org.apache.lucene.search.FieldCache;
|
||||
import org.apache.noggit.JSONUtil;
|
||||
import org.apache.noggit.ObjectBuilder;
|
||||
import org.noggit.JSONUtil;
|
||||
import org.noggit.ObjectBuilder;
|
||||
import org.apache.solr.client.solrj.impl.BinaryResponseParser;
|
||||
import org.apache.solr.common.params.CommonParams;
|
||||
import org.apache.solr.common.params.GroupParams;
|
||||
|
|
|
@ -21,8 +21,8 @@ import org.apache.lucene.search.FieldCache;
|
|||
import org.apache.lucene.search.Query;
|
||||
import org.apache.lucene.search.BooleanQuery;
|
||||
|
||||
import org.apache.noggit.JSONUtil;
|
||||
import org.apache.noggit.ObjectBuilder;
|
||||
import org.noggit.JSONUtil;
|
||||
import org.noggit.ObjectBuilder;
|
||||
import org.apache.solr.common.params.ModifiableSolrParams;
|
||||
import org.apache.solr.core.SolrCore;
|
||||
import org.apache.solr.handler.JsonUpdateRequestHandler;
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
package org.apache.solr.request;
|
||||
|
||||
import org.apache.noggit.ObjectBuilder;
|
||||
import org.noggit.ObjectBuilder;
|
||||
import org.apache.solr.SolrTestCaseJ4;
|
||||
import org.apache.solr.common.SolrException;
|
||||
import org.apache.solr.common.params.ModifiableSolrParams;
|
||||
|
|
|
@ -18,7 +18,7 @@ package org.apache.solr.search;
|
|||
|
||||
|
||||
import org.apache.lucene.util.LuceneTestCase.Slow;
|
||||
import org.apache.noggit.ObjectBuilder;
|
||||
import org.noggit.ObjectBuilder;
|
||||
import org.apache.solr.common.SolrException;
|
||||
import org.apache.solr.common.SolrInputDocument;
|
||||
import org.apache.solr.request.SolrQueryRequest;
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
package org.apache.solr.search;
|
||||
|
||||
|
||||
import org.apache.noggit.ObjectBuilder;
|
||||
import org.noggit.ObjectBuilder;
|
||||
import org.apache.solr.SolrTestCaseJ4;
|
||||
import org.apache.solr.request.SolrQueryRequest;
|
||||
import org.apache.solr.update.DirectUpdateHandler2;
|
||||
|
|
|
@ -18,7 +18,7 @@ package org.apache.solr.search;
|
|||
|
||||
|
||||
import org.apache.lucene.util.Constants;
|
||||
import org.apache.noggit.ObjectBuilder;
|
||||
import org.noggit.ObjectBuilder;
|
||||
import org.apache.solr.request.SolrQueryRequest;
|
||||
import org.apache.solr.update.UpdateHandler;
|
||||
import org.apache.solr.update.UpdateLog;
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
package org.apache.solr.search;
|
||||
|
||||
|
||||
import org.apache.noggit.ObjectBuilder;
|
||||
import org.noggit.ObjectBuilder;
|
||||
import org.apache.solr.request.SolrQueryRequest;
|
||||
import org.apache.solr.util.TestHarness;
|
||||
import org.junit.BeforeClass;
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
package org.apache.solr.search;
|
||||
|
||||
|
||||
import org.apache.noggit.ObjectBuilder;
|
||||
import org.noggit.ObjectBuilder;
|
||||
import org.apache.solr.request.SolrQueryRequest;
|
||||
import org.apache.solr.util.TestHarness;
|
||||
import org.junit.BeforeClass;
|
||||
|
|
|
@ -18,7 +18,7 @@ package org.apache.solr.update.processor;
|
|||
*/
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import org.apache.noggit.ObjectBuilder;
|
||||
import org.noggit.ObjectBuilder;
|
||||
import org.apache.solr.SolrTestCaseJ4;
|
||||
import org.apache.solr.client.solrj.request.UpdateRequest;
|
||||
import org.apache.solr.common.SolrInputDocument;
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
8e6e65624d2e09a30190c6434abe23b7d4e5413c
|
|
@ -0,0 +1,201 @@
|
|||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
|
@ -0,0 +1,3 @@
|
|||
noggit
|
||||
|
||||
https://github.com/yonik/noggit
|
|
@ -44,6 +44,7 @@
|
|||
<dependency org="org.codehaus.woodstox" name="wstx-asl" rev="3.2.7" transitive="false"/>
|
||||
<dependency org="org.slf4j" name="slf4j-api" rev="1.6.4" transitive="false"/>
|
||||
<dependency org="org.slf4j" name="slf4j-jdk14" rev="1.6.4" transitive="false"/>
|
||||
<dependency org="org.noggit" name="noggit" rev="0.5" transitive="false"/>
|
||||
<exclude org="*" ext="*" matcher="regexp" type="${ivy.exclude.types}"/>
|
||||
</dependencies>
|
||||
</ivy-module>
|
||||
|
|
|
@ -1,372 +0,0 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.noggit;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.io.Writer;
|
||||
import java.nio.CharBuffer;
|
||||
|
||||
// CharArr origins
|
||||
// V1.0 7/06/97
|
||||
// V1.1 9/21/99
|
||||
// V1.2 2/02/04 // Java5 features
|
||||
// V1.3 11/26/06 // Make safe for Java 1.4, work into Noggit
|
||||
|
||||
|
||||
// Java5 version could look like the following:
|
||||
// public class CharArr implements CharSequence, Appendable, Readable, Closeable {
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
public class CharArr implements CharSequence, Appendable {
|
||||
protected char[] buf;
|
||||
protected int start;
|
||||
protected int end;
|
||||
|
||||
public CharArr() {
|
||||
this(32);
|
||||
}
|
||||
|
||||
public CharArr(int size) {
|
||||
buf = new char[size];
|
||||
}
|
||||
|
||||
public CharArr(char[] arr, int start, int end) {
|
||||
set(arr,start,end);
|
||||
}
|
||||
|
||||
public void setStart(int start) { this.start = start; }
|
||||
public void setEnd(int end) { this.end = end; }
|
||||
public void set(char[] arr, int start, int end) {
|
||||
this.buf = arr;
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
}
|
||||
|
||||
public char[] getArray() { return buf; }
|
||||
public int getStart() { return start; }
|
||||
public int getEnd() { return end; }
|
||||
public int size() { return end-start; }
|
||||
@Override
|
||||
public int length() { return size(); }
|
||||
public int capacity() { return buf.length; }
|
||||
|
||||
|
||||
@Override
|
||||
public char charAt(int index) {
|
||||
return buf[start+index];
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharArr subSequence(int start, int end) {
|
||||
return new CharArr(buf, this.start+start, this.start+end);
|
||||
}
|
||||
|
||||
public int read() throws IOException {
|
||||
if (start>=end) return -1;
|
||||
return buf[start++];
|
||||
}
|
||||
|
||||
public int read(char cbuf[], int off, int len) {
|
||||
//TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void unsafeWrite(char b) {
|
||||
buf[end++] = b;
|
||||
}
|
||||
|
||||
public void unsafeWrite(int b) { unsafeWrite((char)b); }
|
||||
|
||||
public void unsafeWrite(char b[], int off, int len) {
|
||||
System.arraycopy(b, off, buf, end, len);
|
||||
end += len;
|
||||
}
|
||||
|
||||
protected void resize(int len) {
|
||||
char newbuf[] = new char[Math.max(buf.length << 1, len)];
|
||||
System.arraycopy(buf, start, newbuf, 0, size());
|
||||
buf = newbuf;
|
||||
}
|
||||
|
||||
public void reserve(int num) {
|
||||
if (end + num > buf.length) resize(end + num);
|
||||
}
|
||||
|
||||
public void write(char b) {
|
||||
if (end >= buf.length) {
|
||||
resize(end+1);
|
||||
}
|
||||
unsafeWrite(b);
|
||||
}
|
||||
|
||||
public final void write(int b) { write((char)b); }
|
||||
|
||||
public final void write(char[] b) {
|
||||
write(b,0,b.length);
|
||||
}
|
||||
|
||||
public void write(char b[], int off, int len) {
|
||||
reserve(len);
|
||||
unsafeWrite(b, off, len);
|
||||
}
|
||||
|
||||
public final void write(CharArr arr) {
|
||||
write(arr.buf, start, end-start);
|
||||
}
|
||||
|
||||
public final void write(String s) {
|
||||
write(s, 0, s.length());
|
||||
}
|
||||
|
||||
public void write(String s, int stringOffset, int len) {
|
||||
reserve(len);
|
||||
s.getChars(stringOffset, len, buf, end);
|
||||
end += len;
|
||||
}
|
||||
|
||||
public void flush() {
|
||||
}
|
||||
|
||||
public final void reset() {
|
||||
start = end = 0;
|
||||
}
|
||||
|
||||
public void close() {
|
||||
}
|
||||
|
||||
public char[] toCharArray() {
|
||||
char newbuf[] = new char[size()];
|
||||
System.arraycopy(buf, start, newbuf, 0, size());
|
||||
return newbuf;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new String(buf, start, size());
|
||||
}
|
||||
|
||||
|
||||
public int read(CharBuffer cb) throws IOException {
|
||||
|
||||
/***
|
||||
int sz = size();
|
||||
if (sz<=0) return -1;
|
||||
if (sz>0) cb.put(buf, start, sz);
|
||||
return -1;
|
||||
***/
|
||||
|
||||
int sz = size();
|
||||
if (sz>0) cb.put(buf, start, sz);
|
||||
start=end;
|
||||
while (true) {
|
||||
fill();
|
||||
int s = size();
|
||||
if (s==0) return sz==0 ? -1 : sz;
|
||||
sz += s;
|
||||
cb.put(buf, start, s);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public int fill() throws IOException {
|
||||
return 0; // or -1?
|
||||
}
|
||||
|
||||
//////////////// Appendable methods /////////////
|
||||
@Override
|
||||
public final Appendable append(CharSequence csq) throws IOException {
|
||||
return append(csq, 0, csq.length());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Appendable append(CharSequence csq, int start, int end) throws IOException {
|
||||
write(csq.subSequence(start, end).toString());
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Appendable append(char c) {
|
||||
write(c);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class NullCharArr extends CharArr {
|
||||
public NullCharArr() {
|
||||
super(new char[1],0,0);
|
||||
}
|
||||
@Override
|
||||
public void unsafeWrite(char b) {}
|
||||
|
||||
@Override
|
||||
public void unsafeWrite(char b[], int off, int len) {}
|
||||
|
||||
@Override
|
||||
public void unsafeWrite(int b) {}
|
||||
|
||||
@Override
|
||||
public void write(char b) {}
|
||||
|
||||
@Override
|
||||
public void write(char b[], int off, int len) {}
|
||||
|
||||
@Override
|
||||
public void reserve(int num) {}
|
||||
|
||||
@Override
|
||||
protected void resize(int len) {}
|
||||
|
||||
@Override
|
||||
public Appendable append(CharSequence csq, int start, int end) throws IOException {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public char charAt(int index) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(String s, int stringOffset, int len) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// IDEA: a subclass that refills the array from a reader?
|
||||
class CharArrReader extends CharArr {
|
||||
protected final Reader in;
|
||||
|
||||
public CharArrReader(Reader in, int size) {
|
||||
super(size);
|
||||
this.in = in;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
if (start>=end) fill();
|
||||
return start>=end ? -1 : buf[start++];
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(CharBuffer cb) throws IOException {
|
||||
// empty the buffer and then read direct
|
||||
int sz = size();
|
||||
if (sz>0) cb.put(buf,start,end);
|
||||
int sz2 = in.read(cb);
|
||||
if (sz2>=0) return sz+sz2;
|
||||
return sz>0 ? sz : -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int fill() throws IOException {
|
||||
if (start>=end) {
|
||||
reset();
|
||||
} else if (start>0) {
|
||||
System.arraycopy(buf, start, buf, 0, size());
|
||||
end=size(); start=0;
|
||||
}
|
||||
/***
|
||||
// fill fully or not???
|
||||
do {
|
||||
int sz = in.read(buf,end,buf.length-end);
|
||||
if (sz==-1) return;
|
||||
end+=sz;
|
||||
} while (end < buf.length);
|
||||
***/
|
||||
|
||||
int sz = in.read(buf,end,buf.length-end);
|
||||
if (sz>0) end+=sz;
|
||||
return sz;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
class CharArrWriter extends CharArr {
|
||||
protected Writer sink;
|
||||
|
||||
@Override
|
||||
public void flush() {
|
||||
try {
|
||||
sink.write(buf, start, end-start);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
start = end = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(char b) {
|
||||
if (end >= buf.length) {
|
||||
flush();
|
||||
}
|
||||
unsafeWrite(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(char b[], int off, int len) {
|
||||
int space = buf.length - end;
|
||||
if (len < space) {
|
||||
unsafeWrite(b, off, len);
|
||||
} else if (len < buf.length) {
|
||||
unsafeWrite(b, off, space);
|
||||
flush();
|
||||
unsafeWrite(b, off+space, len-space);
|
||||
} else {
|
||||
flush();
|
||||
try {
|
||||
sink.write(b, off, len);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(String s, int stringOffset, int len) {
|
||||
int space = buf.length - end;
|
||||
if (len < space) {
|
||||
s.getChars(stringOffset, stringOffset+len, buf, end);
|
||||
end += len;
|
||||
} else if (len < buf.length) {
|
||||
// if the data to write is small enough, buffer it.
|
||||
s.getChars(stringOffset, stringOffset+space, buf, end);
|
||||
flush();
|
||||
s.getChars(stringOffset+space, stringOffset+len, buf, 0);
|
||||
end = len-space;
|
||||
} else {
|
||||
flush();
|
||||
// don't buffer, just write to sink
|
||||
try {
|
||||
sink.write(s, stringOffset, len);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,53 +0,0 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.noggit;
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
public class CharUtil {
|
||||
|
||||
// belongs in number utils or charutil?
|
||||
public long parseLong(char[] arr, int start, int end) {
|
||||
long x = 0;
|
||||
boolean negative = arr[start] == '-';
|
||||
for (int i=negative ? start+1 : start; i<end; i++) {
|
||||
// If constructing the largest negative number, this will overflow
|
||||
// to the largest negative number. This is OK since the negation of
|
||||
// the largest negative number is itself in two's complement.
|
||||
x = x * 10 + (arr[i] - '0');
|
||||
}
|
||||
// could replace conditional-move with multiplication of sign... not sure
|
||||
// which is faster.
|
||||
return negative ? -x : x;
|
||||
}
|
||||
|
||||
|
||||
public int compare(char[] a, int a_start, int a_end, char[] b, int b_start, int b_end) {
|
||||
int a_len = a_end - a_start;
|
||||
int b_len = b_end - b_start;
|
||||
int len = Math.min(a_len,b_len);
|
||||
while (--len>=0) {
|
||||
int c = a[a_start] - b[b_start];
|
||||
if (c!=0) return c;
|
||||
a_start++; b_start++;
|
||||
}
|
||||
return a_len-b_len;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,837 +0,0 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.noggit;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
|
||||
/**
|
||||
*/
|
||||
|
||||
public class JSONParser {
|
||||
|
||||
/** Event indicating a JSON string value, including member names of objects */
|
||||
public static final int STRING=1;
|
||||
/** Event indicating a JSON number value which fits into a signed 64 bit integer */
|
||||
public static final int LONG=2;
|
||||
/** Event indicating a JSON number value which has a fractional part or an exponent
|
||||
* and with string length <= 23 chars not including sign. This covers
|
||||
* all representations of normal values for Double.toString().
|
||||
*/
|
||||
public static final int NUMBER=3;
|
||||
/** Event indicating a JSON number value that was not produced by toString of any
|
||||
* Java primitive numerics such as Double or Long. It is either
|
||||
* an integer outside the range of a 64 bit signed integer, or a floating
|
||||
* point value with a string representation of more than 23 chars.
|
||||
*/
|
||||
public static final int BIGNUMBER=4;
|
||||
/** Event indicating a JSON boolean */
|
||||
public static final int BOOLEAN=5;
|
||||
/** Event indicating a JSON null */
|
||||
public static final int NULL=6;
|
||||
/** Event indicating the start of a JSON object */
|
||||
public static final int OBJECT_START=7;
|
||||
/** Event indicating the end of a JSON object */
|
||||
public static final int OBJECT_END=8;
|
||||
/** Event indicating the start of a JSON array */
|
||||
public static final int ARRAY_START=9;
|
||||
/** Event indicating the end of a JSON array */
|
||||
public static final int ARRAY_END=10;
|
||||
/** Event indicating the end of input has been reached */
|
||||
public static final int EOF=11;
|
||||
|
||||
public static class ParseException extends RuntimeException {
|
||||
public ParseException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
||||
|
||||
public static String getEventString( int e )
|
||||
{
|
||||
switch( e )
|
||||
{
|
||||
case STRING: return "STRING";
|
||||
case LONG: return "LONG";
|
||||
case NUMBER: return "NUMBER";
|
||||
case BIGNUMBER: return "BIGNUMBER";
|
||||
case BOOLEAN: return "BOOLEAN";
|
||||
case NULL: return "NULL";
|
||||
case OBJECT_START: return "OBJECT_START";
|
||||
case OBJECT_END: return "OBJECT_END";
|
||||
case ARRAY_START: return "ARRAY_START";
|
||||
case ARRAY_END: return "ARRAY_END";
|
||||
case EOF: return "EOF";
|
||||
}
|
||||
return "Unknown: "+e;
|
||||
}
|
||||
|
||||
private static final CharArr devNull = new NullCharArr();
|
||||
|
||||
|
||||
final char[] buf; // input buffer with JSON text in it
|
||||
int start; // current position in the buffer
|
||||
int end; // end position in the buffer (one past last valid index)
|
||||
final Reader in; // optional reader to obtain data from
|
||||
boolean eof=false; // true if the end of the stream was reached.
|
||||
long gpos; // global position = gpos + start
|
||||
|
||||
int event; // last event read
|
||||
|
||||
public JSONParser(Reader in) {
|
||||
this(in, new char[8192]);
|
||||
// 8192 matches the default buffer size of a BufferedReader so double
|
||||
// buffering of the data is avoided.
|
||||
}
|
||||
|
||||
public JSONParser(Reader in, char[] buffer) {
|
||||
this.in = in;
|
||||
this.buf = buffer;
|
||||
}
|
||||
|
||||
// idea - if someone passes us a CharArrayReader, we could
|
||||
// directly use that buffer as it's protected.
|
||||
|
||||
public JSONParser(char[] data, int start, int end) {
|
||||
this.in = null;
|
||||
this.buf = data;
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
}
|
||||
|
||||
public JSONParser(String data) {
|
||||
this(data, 0, data.length());
|
||||
}
|
||||
|
||||
public JSONParser(String data, int start, int end) {
|
||||
this.in = null;
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
this.buf = new char[end-start];
|
||||
data.getChars(start,end,buf,0);
|
||||
}
|
||||
|
||||
// temporary output buffer
|
||||
private final CharArr out = new CharArr(64);
|
||||
|
||||
// We need to keep some state in order to (at a minimum) know if
|
||||
// we should skip ',' or ':'.
|
||||
private byte[] stack = new byte[16];
|
||||
private int ptr=0; // pointer into the stack of parser states
|
||||
private byte state=0; // current parser state
|
||||
|
||||
// parser states stored in the stack
|
||||
private static final byte DID_OBJSTART =1; // '{' just read
|
||||
private static final byte DID_ARRSTART =2; // '[' just read
|
||||
private static final byte DID_ARRELEM =3; // array element just read
|
||||
private static final byte DID_MEMNAME =4; // object member name (map key) just read
|
||||
private static final byte DID_MEMVAL =5; // object member value (map val) just read
|
||||
|
||||
// info about value that was just read (or is in the middle of being read)
|
||||
private int valstate;
|
||||
|
||||
// push current parser state (use at start of new container)
|
||||
private final void push() {
|
||||
if (ptr >= stack.length) {
|
||||
// doubling here is probably overkill, but anything that needs to double more than
|
||||
// once (32 levels deep) is very atypical anyway.
|
||||
byte[] newstack = new byte[stack.length<<1];
|
||||
System.arraycopy(stack,0,newstack,0,stack.length);
|
||||
stack = newstack;
|
||||
}
|
||||
stack[ptr++] = state;
|
||||
}
|
||||
|
||||
// pop parser state (use at end of container)
|
||||
private final void pop() {
|
||||
if (--ptr<0) {
|
||||
throw err("Unbalanced container");
|
||||
} else {
|
||||
state = stack[ptr];
|
||||
}
|
||||
}
|
||||
|
||||
protected void fill() throws IOException {
|
||||
if (in!=null) {
|
||||
gpos += end;
|
||||
start=0;
|
||||
int num = in.read(buf,0,buf.length);
|
||||
end = num>=0 ? num : 0;
|
||||
}
|
||||
if (start>=end) eof=true;
|
||||
}
|
||||
|
||||
private void getMore() throws IOException {
|
||||
fill();
|
||||
if (start>=end) {
|
||||
throw err(null);
|
||||
}
|
||||
}
|
||||
|
||||
protected int getChar() throws IOException {
|
||||
if (start>=end) {
|
||||
fill();
|
||||
if (start>=end) return -1;
|
||||
}
|
||||
return buf[start++];
|
||||
}
|
||||
|
||||
private int getCharNWS() throws IOException {
|
||||
for (;;) {
|
||||
int ch = getChar();
|
||||
if (!(ch==' ' || ch=='\t' || ch=='\n' || ch=='\r')) return ch;
|
||||
}
|
||||
}
|
||||
|
||||
private void expect(char[] arr) throws IOException {
|
||||
for (int i=1; i<arr.length; i++) {
|
||||
int ch = getChar();
|
||||
if (ch != arr[i]) {
|
||||
throw err("Expected " + new String(arr));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ParseException err(String msg) {
|
||||
// We can't tell if EOF was hit by comparing start<=end
|
||||
// because the illegal char could have been the last in the buffer
|
||||
// or in the stream. To deal with this, the "eof" var was introduced
|
||||
if (!eof && start>0) start--; // backup one char
|
||||
String chs = "char=" + ((start>=end) ? "(EOF)" : "" + (char)buf[start]);
|
||||
String pos = "position=" + (gpos+start);
|
||||
String tot = chs + ',' + pos + getContext();
|
||||
if (msg==null) {
|
||||
if (start>=end) msg = "Unexpected EOF";
|
||||
else msg="JSON Parse Error";
|
||||
}
|
||||
return new ParseException(msg + ": " + tot);
|
||||
}
|
||||
|
||||
private String getContext() {
|
||||
String context = "";
|
||||
if (start>=0) {
|
||||
context += " BEFORE='" + errEscape(Math.max(start-60,0), start+1) + "'";
|
||||
}
|
||||
if (start<end) {
|
||||
context += " AFTER='" + errEscape(start+1, start+40) + "'";
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
private String errEscape(int a, int b) {
|
||||
b = Math.min(b, end);
|
||||
if (a>=b) return "";
|
||||
return new String(buf, a, b-a).replaceAll("\\s+"," ");
|
||||
}
|
||||
|
||||
|
||||
private boolean bool; // boolean value read
|
||||
private long lval; // long value read
|
||||
private int nstate; // current state while reading a number
|
||||
private static final int HAS_FRACTION = 0x01; // nstate flag, '.' already read
|
||||
private static final int HAS_EXPONENT = 0x02; // nstate flag, '[eE][+-]?[0-9]' already read
|
||||
|
||||
/** Returns the long read... only significant if valstate==LONG after
|
||||
* this call. firstChar should be the first numeric digit read.
|
||||
*/
|
||||
private long readNumber(int firstChar, boolean isNeg) throws IOException {
|
||||
out.unsafeWrite(firstChar); // unsafe OK since we know output is big enough
|
||||
// We build up the number in the negative plane since it's larger (by one) than
|
||||
// the positive plane.
|
||||
long v = '0' - firstChar;
|
||||
// can't overflow a long in 18 decimal digits (i.e. 17 additional after the first).
|
||||
// we also need 22 additional to handle double so we'll handle in 2 separate loops.
|
||||
int i;
|
||||
for (i=0; i<17; i++) {
|
||||
int ch = getChar();
|
||||
// TODO: is this switch faster as an if-then-else?
|
||||
switch(ch) {
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
v = v*10 - (ch-'0');
|
||||
out.unsafeWrite(ch);
|
||||
continue;
|
||||
case '.':
|
||||
out.unsafeWrite('.');
|
||||
valstate = readFrac(out,22-i);
|
||||
return 0;
|
||||
case 'e':
|
||||
case 'E':
|
||||
out.unsafeWrite(ch);
|
||||
nstate=0;
|
||||
valstate = readExp(out,22-i);
|
||||
return 0;
|
||||
default:
|
||||
// return the number, relying on nextEvent() to return an error
|
||||
// for invalid chars following the number.
|
||||
if (ch!=-1) --start; // push back last char if not EOF
|
||||
|
||||
valstate = LONG;
|
||||
return isNeg ? v : -v;
|
||||
}
|
||||
}
|
||||
|
||||
// after this, we could overflow a long and need to do extra checking
|
||||
boolean overflow = false;
|
||||
long maxval = isNeg ? Long.MIN_VALUE : -Long.MAX_VALUE;
|
||||
|
||||
for (; i<22; i++) {
|
||||
int ch = getChar();
|
||||
switch(ch) {
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
if (v < (0x8000000000000000L/10)) overflow=true; // can't multiply by 10 w/o overflowing
|
||||
v *= 10;
|
||||
int digit = ch - '0';
|
||||
if (v < maxval + digit) overflow=true; // can't add digit w/o overflowing
|
||||
v -= digit;
|
||||
out.unsafeWrite(ch);
|
||||
continue;
|
||||
case '.':
|
||||
out.unsafeWrite('.');
|
||||
valstate = readFrac(out,22-i);
|
||||
return 0;
|
||||
case 'e':
|
||||
case 'E':
|
||||
out.unsafeWrite(ch);
|
||||
nstate=0;
|
||||
valstate = readExp(out,22-i);
|
||||
return 0;
|
||||
default:
|
||||
// return the number, relying on nextEvent() to return an error
|
||||
// for invalid chars following the number.
|
||||
if (ch!=-1) --start; // push back last char if not EOF
|
||||
|
||||
valstate = overflow ? BIGNUMBER : LONG;
|
||||
return isNeg ? v : -v;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
nstate=0;
|
||||
valstate = BIGNUMBER;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// read digits right of decimal point
|
||||
private int readFrac(CharArr arr, int lim) throws IOException {
|
||||
nstate = HAS_FRACTION; // deliberate set instead of '|'
|
||||
while(--lim>=0) {
|
||||
int ch = getChar();
|
||||
if (ch>='0' && ch<='9') {
|
||||
arr.write(ch);
|
||||
} else if (ch=='e' || ch=='E') {
|
||||
arr.write(ch);
|
||||
return readExp(arr,lim);
|
||||
} else {
|
||||
if (ch!=-1) start--; // back up
|
||||
return NUMBER;
|
||||
}
|
||||
}
|
||||
return BIGNUMBER;
|
||||
}
|
||||
|
||||
|
||||
// call after 'e' or 'E' has been seen to read the rest of the exponent
|
||||
private int readExp(CharArr arr, int lim) throws IOException {
|
||||
nstate |= HAS_EXPONENT;
|
||||
int ch = getChar(); lim--;
|
||||
|
||||
if (ch=='+' || ch=='-') {
|
||||
arr.write(ch);
|
||||
ch = getChar(); lim--;
|
||||
}
|
||||
|
||||
// make sure at least one digit is read.
|
||||
if (ch<'0' || ch>'9') {
|
||||
throw err("missing exponent number");
|
||||
}
|
||||
arr.write(ch);
|
||||
|
||||
return readExpDigits(arr,lim);
|
||||
}
|
||||
|
||||
// continuation of readExpStart
|
||||
private int readExpDigits(CharArr arr, int lim) throws IOException {
|
||||
while (--lim>=0) {
|
||||
int ch = getChar();
|
||||
if (ch>='0' && ch<='9') {
|
||||
arr.write(ch);
|
||||
} else {
|
||||
if (ch!=-1) start--; // back up
|
||||
return NUMBER;
|
||||
}
|
||||
}
|
||||
return BIGNUMBER;
|
||||
}
|
||||
|
||||
private void continueNumber(CharArr arr) throws IOException {
|
||||
if (arr != out) arr.write(out);
|
||||
|
||||
if ((nstate & HAS_EXPONENT)!=0){
|
||||
readExpDigits(arr, Integer.MAX_VALUE);
|
||||
return;
|
||||
}
|
||||
if (nstate != 0) {
|
||||
readFrac(arr, Integer.MAX_VALUE);
|
||||
return;
|
||||
}
|
||||
|
||||
for(;;) {
|
||||
int ch = getChar();
|
||||
if (ch>='0' && ch <='9') {
|
||||
arr.write(ch);
|
||||
} else if (ch=='.') {
|
||||
arr.write(ch);
|
||||
readFrac(arr,Integer.MAX_VALUE);
|
||||
return;
|
||||
} else if (ch=='e' || ch=='E') {
|
||||
arr.write(ch);
|
||||
readExp(arr,Integer.MAX_VALUE);
|
||||
return;
|
||||
} else {
|
||||
if (ch!=-1) start--;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private int hexval(int hexdig) {
|
||||
if (hexdig>='0' && hexdig <='9') {
|
||||
return hexdig-'0';
|
||||
} else if (hexdig>='A' && hexdig <='F') {
|
||||
return hexdig+(10-'A');
|
||||
} else if (hexdig>='a' && hexdig <='f') {
|
||||
return hexdig+(10-'a');
|
||||
}
|
||||
throw err("invalid hex digit");
|
||||
}
|
||||
|
||||
// backslash has already been read when this is called
|
||||
private char readEscapedChar() throws IOException {
|
||||
switch (getChar()) {
|
||||
case '"' : return '"';
|
||||
case '\\' : return '\\';
|
||||
case '/' : return '/';
|
||||
case 'n' : return '\n';
|
||||
case 'r' : return '\r';
|
||||
case 't' : return '\t';
|
||||
case 'f' : return '\f';
|
||||
case 'b' : return '\b';
|
||||
case 'u' :
|
||||
return (char)(
|
||||
(hexval(getChar()) << 12)
|
||||
| (hexval(getChar()) << 8)
|
||||
| (hexval(getChar()) << 4)
|
||||
| (hexval(getChar())));
|
||||
}
|
||||
throw err("Invalid character escape in string");
|
||||
}
|
||||
|
||||
// a dummy buffer we can use to point at other buffers
|
||||
private final CharArr tmp = new CharArr(null,0,0);
|
||||
|
||||
private CharArr readStringChars() throws IOException {
|
||||
char c=0;
|
||||
int i;
|
||||
for (i=start; i<end; i++) {
|
||||
c = buf[i];
|
||||
if (c=='"') {
|
||||
tmp.set(buf,start,i); // directly use input buffer
|
||||
start=i+1; // advance past last '"'
|
||||
return tmp;
|
||||
} else if (c=='\\') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
out.reset();
|
||||
readStringChars2(out, i);
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
// middle is the pointer to the middle of a buffer to start scanning for a non-string
|
||||
// character ('"' or "/"). start<=middle<end
|
||||
// this should be faster for strings with fewer escapes, but probably slower for many escapes.
|
||||
private void readStringChars2(CharArr arr, int middle) throws IOException {
|
||||
for (;;) {
|
||||
if (middle>=end) {
|
||||
arr.write(buf,start,middle-start);
|
||||
start=middle;
|
||||
getMore();
|
||||
middle=start;
|
||||
}
|
||||
int ch = buf[middle++];
|
||||
if (ch=='"') {
|
||||
int len = middle-start-1;
|
||||
if (len>0) arr.write(buf,start,len);
|
||||
start=middle;
|
||||
return;
|
||||
} else if (ch=='\\') {
|
||||
int len = middle-start-1;
|
||||
if (len>0) arr.write(buf,start,len);
|
||||
start=middle;
|
||||
arr.write(readEscapedChar());
|
||||
middle=start;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*** alternate implelentation
|
||||
// middle is the pointer to the middle of a buffer to start scanning for a non-string
|
||||
// character ('"' or "/"). start<=middle<end
|
||||
private void readStringChars2a(CharArr arr, int middle) throws IOException {
|
||||
int ch=0;
|
||||
for(;;) {
|
||||
// find the next non-string char
|
||||
for (; middle<end; middle++) {
|
||||
ch = buf[middle];
|
||||
if (ch=='"' || ch=='\\') break;
|
||||
}
|
||||
|
||||
arr.write(buf,start,middle-start);
|
||||
if (middle>=end) {
|
||||
getMore();
|
||||
middle=start;
|
||||
} else {
|
||||
start = middle+1; // set buffer pointer to correct spot
|
||||
if (ch=='"') {
|
||||
valstate=0;
|
||||
return;
|
||||
} else if (ch=='\\') {
|
||||
arr.write(readEscapedChar());
|
||||
if (start>=end) getMore();
|
||||
middle=start;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
***/
|
||||
|
||||
|
||||
// return the next event when parser is in a neutral state (no
|
||||
// map separators or array element separators to read
|
||||
private int next(int ch) throws IOException {
|
||||
for(;;) {
|
||||
switch (ch) {
|
||||
case ' ':
|
||||
case '\t': break;
|
||||
case '\r':
|
||||
case '\n': break; // try and keep track of linecounts?
|
||||
case '"' :
|
||||
valstate = STRING;
|
||||
return STRING;
|
||||
case '{' :
|
||||
push();
|
||||
state= DID_OBJSTART;
|
||||
return OBJECT_START;
|
||||
case '[':
|
||||
push();
|
||||
state=DID_ARRSTART;
|
||||
return ARRAY_START;
|
||||
case '0' :
|
||||
out.reset();
|
||||
//special case '0'? If next char isn't '.' val=0
|
||||
ch=getChar();
|
||||
if (ch=='.') {
|
||||
start--; ch='0';
|
||||
readNumber('0',false);
|
||||
return valstate;
|
||||
} else if (ch>'9' || ch<'0') {
|
||||
out.unsafeWrite('0');
|
||||
if (ch!=-1) start--;
|
||||
lval = 0;
|
||||
valstate=LONG;
|
||||
return LONG;
|
||||
} else {
|
||||
throw err("Leading zeros not allowed");
|
||||
}
|
||||
case '1' :
|
||||
case '2' :
|
||||
case '3' :
|
||||
case '4' :
|
||||
case '5' :
|
||||
case '6' :
|
||||
case '7' :
|
||||
case '8' :
|
||||
case '9' :
|
||||
out.reset();
|
||||
lval = readNumber(ch,false);
|
||||
return valstate;
|
||||
case '-' :
|
||||
out.reset();
|
||||
out.unsafeWrite('-');
|
||||
ch = getChar();
|
||||
if (ch<'0' || ch>'9') throw err("expected digit after '-'");
|
||||
lval = readNumber(ch,true);
|
||||
return valstate;
|
||||
case 't':
|
||||
valstate=BOOLEAN;
|
||||
// TODO: test performance of this non-branching inline version.
|
||||
// if ((('r'-getChar())|('u'-getChar())|('e'-getChar())) != 0) err("");
|
||||
expect(JSONUtil.TRUE_CHARS);
|
||||
bool=true;
|
||||
return BOOLEAN;
|
||||
case 'f':
|
||||
valstate=BOOLEAN;
|
||||
expect(JSONUtil.FALSE_CHARS);
|
||||
bool=false;
|
||||
return BOOLEAN;
|
||||
case 'n':
|
||||
valstate=NULL;
|
||||
expect(JSONUtil.NULL_CHARS);
|
||||
return NULL;
|
||||
case -1:
|
||||
if (getLevel()>0) throw err("Premature EOF");
|
||||
return EOF;
|
||||
default: throw err(null);
|
||||
}
|
||||
|
||||
ch = getChar();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "start="+start+",end="+end+",state="+state+"valstate="+valstate;
|
||||
}
|
||||
|
||||
|
||||
/** Returns the next event encountered in the JSON stream, one of
|
||||
* <ul>
|
||||
* <li>{@link #STRING}</li>
|
||||
* <li>{@link #LONG}</li>
|
||||
* <li>{@link #NUMBER}</li>
|
||||
* <li>{@link #BIGNUMBER}</li>
|
||||
* <li>{@link #BOOLEAN}</li>
|
||||
* <li>{@link #NULL}</li>
|
||||
* <li>{@link #OBJECT_START}</li>
|
||||
* <li>{@link #OBJECT_END}</li>
|
||||
* <li>{@link #OBJECT_END}</li>
|
||||
* <li>{@link #ARRAY_START}</li>
|
||||
* <li>{@link #ARRAY_END}</li>
|
||||
* <li>{@link #EOF}</li>
|
||||
* </ul>
|
||||
*/
|
||||
public int nextEvent() throws IOException {
|
||||
if (valstate==STRING) {
|
||||
readStringChars2(devNull,start);
|
||||
}
|
||||
else if (valstate==BIGNUMBER) {
|
||||
continueNumber(devNull);
|
||||
}
|
||||
|
||||
valstate=0;
|
||||
|
||||
int ch; // TODO: factor out getCharNWS() to here and check speed
|
||||
switch (state) {
|
||||
case 0:
|
||||
return event = next(getCharNWS());
|
||||
case DID_OBJSTART:
|
||||
ch = getCharNWS();
|
||||
if (ch=='}') {
|
||||
pop();
|
||||
return event = OBJECT_END;
|
||||
}
|
||||
if (ch != '"') {
|
||||
throw err("Expected string");
|
||||
}
|
||||
state = DID_MEMNAME;
|
||||
valstate = STRING;
|
||||
return event = STRING;
|
||||
case DID_MEMNAME:
|
||||
ch = getCharNWS();
|
||||
if (ch!=':') {
|
||||
throw err("Expected key,value separator ':'");
|
||||
}
|
||||
state = DID_MEMVAL; // set state first because it might be pushed...
|
||||
return event = next(getChar());
|
||||
case DID_MEMVAL:
|
||||
ch = getCharNWS();
|
||||
if (ch=='}') {
|
||||
pop();
|
||||
return event = OBJECT_END;
|
||||
} else if (ch!=',') {
|
||||
throw err("Expected ',' or '}'");
|
||||
}
|
||||
ch = getCharNWS();
|
||||
if (ch != '"') {
|
||||
throw err("Expected string");
|
||||
}
|
||||
state = DID_MEMNAME;
|
||||
valstate = STRING;
|
||||
return event = STRING;
|
||||
case DID_ARRSTART:
|
||||
ch = getCharNWS();
|
||||
if (ch==']') {
|
||||
pop();
|
||||
return event = ARRAY_END;
|
||||
}
|
||||
state = DID_ARRELEM; // set state first, might be pushed...
|
||||
return event = next(ch);
|
||||
case DID_ARRELEM:
|
||||
ch = getCharNWS();
|
||||
if (ch==']') {
|
||||
pop();
|
||||
return event = ARRAY_END;
|
||||
} else if (ch!=',') {
|
||||
throw err("Expected ',' or ']'");
|
||||
}
|
||||
// state = DID_ARRELEM;
|
||||
return event = next(getChar());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int lastEvent() {
|
||||
return event;
|
||||
}
|
||||
|
||||
public boolean wasKey()
|
||||
{
|
||||
return state == DID_MEMNAME;
|
||||
}
|
||||
|
||||
|
||||
private void goTo(int what) throws IOException {
|
||||
if (valstate==what) { valstate=0; return; }
|
||||
if (valstate==0) {
|
||||
int ev = nextEvent(); // TODO
|
||||
if (valstate!=what) {
|
||||
throw err("type mismatch");
|
||||
}
|
||||
valstate=0;
|
||||
}
|
||||
else {
|
||||
throw err("type mismatch");
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns the JSON string value, decoding any escaped characters. */
|
||||
public String getString() throws IOException {
|
||||
return getStringChars().toString();
|
||||
}
|
||||
|
||||
/** Returns the characters of a JSON string value, decoding any escaped characters.
|
||||
* <p/>The underlying buffer of the returned <code>CharArr</code> should *not* be
|
||||
* modified as it may be shared with the input buffer.
|
||||
* <p/>The returned <code>CharArr</code> will only be valid up until
|
||||
* the next JSONParser method is called. Any required data should be
|
||||
* read before that point.
|
||||
*/
|
||||
public CharArr getStringChars() throws IOException {
|
||||
goTo(STRING);
|
||||
return readStringChars();
|
||||
}
|
||||
|
||||
/** Reads a JSON string into the output, decoding any escaped characters. */
|
||||
public void getString(CharArr output) throws IOException {
|
||||
goTo(STRING);
|
||||
readStringChars2(output,start);
|
||||
}
|
||||
|
||||
/** Reads a number from the input stream and parses it as a long, only if
|
||||
* the value will in fact fit into a signed 64 bit integer. */
|
||||
public long getLong() throws IOException {
|
||||
goTo(LONG);
|
||||
return lval;
|
||||
}
|
||||
|
||||
/** Reads a number from the input stream and parses it as a double */
|
||||
public double getDouble() throws IOException {
|
||||
return Double.parseDouble(getNumberChars().toString());
|
||||
}
|
||||
|
||||
/** Returns the characters of a JSON numeric value.
|
||||
* <p/>The underlying buffer of the returned <code>CharArr</code> should *not* be
|
||||
* modified as it may be shared with the input buffer.
|
||||
* <p/>The returned <code>CharArr</code> will only be valid up until
|
||||
* the next JSONParser method is called. Any required data should be
|
||||
* read before that point.
|
||||
*/
|
||||
public CharArr getNumberChars() throws IOException {
|
||||
int ev=0;
|
||||
if (valstate==0) ev = nextEvent();
|
||||
|
||||
if (valstate == LONG || valstate == NUMBER) {
|
||||
valstate=0;
|
||||
return out;
|
||||
}
|
||||
else if (valstate==BIGNUMBER) {
|
||||
continueNumber(out);
|
||||
valstate=0;
|
||||
return out;
|
||||
} else {
|
||||
throw err("Unexpected " + ev);
|
||||
}
|
||||
}
|
||||
|
||||
/** Reads a JSON numeric value into the output. */
|
||||
public void getNumberChars(CharArr output) throws IOException {
|
||||
int ev=0;
|
||||
if (valstate==0) ev=nextEvent();
|
||||
if (valstate == LONG || valstate == NUMBER) output.write(this.out);
|
||||
else if (valstate==BIGNUMBER) {
|
||||
continueNumber(output);
|
||||
} else {
|
||||
throw err("Unexpected " + ev);
|
||||
}
|
||||
valstate=0;
|
||||
}
|
||||
|
||||
/** Reads a boolean value */
|
||||
public boolean getBoolean() throws IOException {
|
||||
goTo(BOOLEAN);
|
||||
return bool;
|
||||
}
|
||||
|
||||
/** Reads a null value */
|
||||
public void getNull() throws IOException {
|
||||
goTo(NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the current nesting level, the number of parent objects or arrays.
|
||||
*/
|
||||
public int getLevel() {
|
||||
return ptr;
|
||||
}
|
||||
|
||||
public long getPosition()
|
||||
{
|
||||
return gpos+start;
|
||||
}
|
||||
}
|
|
@ -1,162 +0,0 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.noggit;
|
||||
|
||||
/**
|
||||
*/
|
||||
|
||||
public class JSONUtil {
|
||||
public static final char[] TRUE_CHARS = new char[] {'t','r','u','e'};
|
||||
public static final char[] FALSE_CHARS = new char[] {'f','a','l','s','e'};
|
||||
public static final char[] NULL_CHARS = new char[] {'n','u','l','l'};
|
||||
public static final char[] HEX_CHARS = new char[] {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
|
||||
public static final char VALUE_SEPARATOR = ',';
|
||||
public static final char NAME_SEPARATOR = ':';
|
||||
public static final char OBJECT_START = '{';
|
||||
public static final char OBJECT_END = '}';
|
||||
public static final char ARRAY_START = '[';
|
||||
public static final char ARRAY_END = ']';
|
||||
|
||||
public static String toJSON(Object o) {
|
||||
CharArr out = new CharArr();
|
||||
new JSONWriter(out).write(o);
|
||||
return out.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param o The object to convert to JSON
|
||||
* @param indentSize The number of space characters to use as an indent (default 2). 0=newlines but no spaces, -1=no indent at all.
|
||||
* @return Given Object converted to its JSON representation using the given indentSize
|
||||
*/
|
||||
public static String toJSON(Object o, int indentSize) {
|
||||
CharArr out = new CharArr();
|
||||
new JSONWriter(out,indentSize).write(o);
|
||||
return out.toString();
|
||||
}
|
||||
|
||||
public static void writeNumber(int number, CharArr out) {
|
||||
out.write(Integer.toString(number));
|
||||
}
|
||||
|
||||
public static void writeNumber(long number, CharArr out) {
|
||||
out.write(Long.toString(number));
|
||||
}
|
||||
|
||||
public static void writeNumber(float number, CharArr out) {
|
||||
out.write(Float.toString(number));
|
||||
}
|
||||
|
||||
public static void writeNumber(double number, CharArr out) {
|
||||
out.write(Double.toString(number));
|
||||
}
|
||||
|
||||
public static void writeString(CharArr val, CharArr out) {
|
||||
writeString(val.getArray(), val.getStart(), val.getEnd(), out);
|
||||
}
|
||||
|
||||
public static void writeString(char[] val, int start, int end, CharArr out) {
|
||||
out.write('"');
|
||||
writeStringPart(val,start,end,out);
|
||||
out.write('"');
|
||||
}
|
||||
|
||||
public static void writeString(CharSequence val, int start, int end, CharArr out) {
|
||||
out.write('"');
|
||||
writeStringPart(val,start,end,out);
|
||||
out.write('"');
|
||||
}
|
||||
|
||||
public static void writeStringPart(char[] val, int start, int end, CharArr out) {
|
||||
for (int i=start; i<end; i++) {
|
||||
char ch = val[i];
|
||||
switch(ch) {
|
||||
case '"':
|
||||
case '\\':
|
||||
out.write('\\');
|
||||
out.write(ch);
|
||||
break;
|
||||
case '\r': out.write('\\'); out.write('r'); break;
|
||||
case '\n': out.write('\\'); out.write('n'); break;
|
||||
case '\t': out.write('\\'); out.write('t'); break;
|
||||
case '\b': out.write('\\'); out.write('b'); break;
|
||||
case '\f': out.write('\\'); out.write('f'); break;
|
||||
// case '/':
|
||||
default:
|
||||
if (ch <= 0x1F) {
|
||||
unicodeEscape(ch,out);
|
||||
} else {
|
||||
// These characters are valid JSON, but not valid JavaScript
|
||||
if (ch=='\u2028' || ch=='\u2029') {
|
||||
unicodeEscape(ch,out);
|
||||
} else {
|
||||
out.write(ch);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void writeStringPart(CharSequence chars, int start, int end, CharArr out) {
|
||||
for (int i=start; i<end; i++) {
|
||||
char ch = chars.charAt(i);
|
||||
switch(ch) {
|
||||
case '"':
|
||||
case '\\':
|
||||
out.write('\\');
|
||||
out.write(ch);
|
||||
break;
|
||||
case '\r': out.write('\\'); out.write('r'); break;
|
||||
case '\n': out.write('\\'); out.write('n'); break;
|
||||
case '\t': out.write('\\'); out.write('t'); break;
|
||||
case '\b': out.write('\\'); out.write('b'); break;
|
||||
case '\f': out.write('\\'); out.write('f'); break;
|
||||
// case '/':
|
||||
default:
|
||||
if (ch <= 0x1F) {
|
||||
unicodeEscape(ch,out);
|
||||
} else {
|
||||
// These characters are valid JSON, but not valid JavaScript
|
||||
if (ch=='\u2028' || ch=='\u2029') {
|
||||
unicodeEscape(ch,out);
|
||||
} else {
|
||||
out.write(ch);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void unicodeEscape(int ch, CharArr out) {
|
||||
out.write('\\');
|
||||
out.write('u');
|
||||
out.write(HEX_CHARS[ch>>>12]);
|
||||
out.write(HEX_CHARS[(ch>>>8)&0xf]);
|
||||
out.write(HEX_CHARS[(ch>>>4)&0xf]);
|
||||
out.write(HEX_CHARS[ch&0xf]);
|
||||
}
|
||||
|
||||
public static void writeNull(CharArr out) {
|
||||
out.write(NULL_CHARS);
|
||||
}
|
||||
|
||||
public static void writeBoolean(boolean val, CharArr out) {
|
||||
out.write(val ? TRUE_CHARS : FALSE_CHARS);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,342 +0,0 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.noggit;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
*/
|
||||
public class JSONWriter {
|
||||
|
||||
/** Implement this interface on your class to support serialization */
|
||||
public static interface Writable {
|
||||
public void write(JSONWriter writer);
|
||||
}
|
||||
|
||||
protected int level;
|
||||
protected int indent;
|
||||
protected final CharArr out;
|
||||
|
||||
/**
|
||||
* @param out the CharArr to write the output to.
|
||||
* @param indentSize The number of space characters to use as an indent (default 2). 0=newlines but no spaces, -1=no indent at all.
|
||||
*/
|
||||
public JSONWriter(CharArr out, int indentSize) {
|
||||
this.out = out;
|
||||
this.indent = indentSize;
|
||||
}
|
||||
|
||||
public JSONWriter(CharArr out) {
|
||||
this(out, 2);
|
||||
}
|
||||
|
||||
public void setIndentSize(int indentSize) {
|
||||
this.indent = indentSize;
|
||||
}
|
||||
|
||||
public void indent() {
|
||||
if (indent >= 0) {
|
||||
out.write('\n');
|
||||
if (indent > 0) {
|
||||
int spaces = level*indent;
|
||||
out.reserve(spaces);
|
||||
for (int i=0; i<spaces; i++) {
|
||||
out.unsafeWrite(' ');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void write(Object o) {
|
||||
if (o == null) {
|
||||
writeNull();
|
||||
} else if (o instanceof CharSequence) {
|
||||
writeString((CharSequence)o);
|
||||
} else if (o instanceof Number) {
|
||||
if (o instanceof Integer || o instanceof Long) {
|
||||
write(((Number)o).longValue());
|
||||
} else if (o instanceof Float || o instanceof Double) {
|
||||
write(((Number)o).doubleValue());
|
||||
} else {
|
||||
CharArr arr = new CharArr();
|
||||
arr.write(o.toString());
|
||||
writeNumber(arr);
|
||||
}
|
||||
} else if (o instanceof Map) {
|
||||
write((Map)o);
|
||||
} else if (o instanceof Collection) {
|
||||
write((Collection)o);
|
||||
} else if (o instanceof Object[]) {
|
||||
write(Arrays.asList((Object[])o));
|
||||
} else if (o instanceof Boolean) {
|
||||
write(((Boolean)o).booleanValue());
|
||||
} else if (o instanceof Writable) {
|
||||
((Writable) o).write(this);
|
||||
}
|
||||
else if (o instanceof int[]) {
|
||||
write((int[])o);
|
||||
} else if (o instanceof float[]) {
|
||||
write((float[])o);
|
||||
} else if (o instanceof long[]) {
|
||||
write((long[])o);
|
||||
} else if (o instanceof double[]) {
|
||||
write((double[])o);
|
||||
} else if (o instanceof short[]) {
|
||||
write((short[])o);
|
||||
} else if (o instanceof boolean[]) {
|
||||
write((boolean[])o);
|
||||
} else if (o instanceof char[]) {
|
||||
write((char[])o);
|
||||
} else if (o instanceof byte[]) {
|
||||
write((byte[])o);
|
||||
} else {
|
||||
handleUnknownClass(o);
|
||||
}
|
||||
}
|
||||
|
||||
/** Override this method for custom handling of unknown classes. Also see the Writable interface. */
|
||||
public void handleUnknownClass(Object o) {
|
||||
writeString(out.toString());
|
||||
}
|
||||
|
||||
public void write(Map val) {
|
||||
startObject();
|
||||
int sz = val.size();
|
||||
boolean first = true;
|
||||
for (Map.Entry entry : (Set<Map.Entry>)val.entrySet()) {
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
writeValueSeparator();
|
||||
}
|
||||
if (sz>1) indent();
|
||||
writeString(entry.getKey().toString());
|
||||
writeNameSeparator();
|
||||
write(entry.getValue());
|
||||
}
|
||||
endObject();
|
||||
}
|
||||
|
||||
public void write(Collection val) {
|
||||
startArray();
|
||||
int sz = val.size();
|
||||
boolean first = true;
|
||||
for (Object o : val) {
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
writeValueSeparator();
|
||||
}
|
||||
if (sz>1) indent();
|
||||
write(o);
|
||||
}
|
||||
endArray();
|
||||
}
|
||||
|
||||
/** A byte[] may be either a single logical value, or a list of small integers.
|
||||
* It's up to the implementation to decide.
|
||||
*/
|
||||
public void write(byte[] val) {
|
||||
startArray();
|
||||
boolean first = true;
|
||||
for (short v : val) {
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
writeValueSeparator();
|
||||
}
|
||||
write(v);
|
||||
}
|
||||
endArray();
|
||||
}
|
||||
|
||||
public void write(short[] val) {
|
||||
startArray();
|
||||
boolean first = true;
|
||||
for (short v : val) {
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
writeValueSeparator();
|
||||
}
|
||||
write(v);
|
||||
}
|
||||
endArray();
|
||||
}
|
||||
|
||||
public void write(int[] val) {
|
||||
startArray();
|
||||
boolean first = true;
|
||||
for (int v : val) {
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
writeValueSeparator();
|
||||
}
|
||||
write(v);
|
||||
}
|
||||
endArray();
|
||||
}
|
||||
|
||||
public void write(long[] val) {
|
||||
startArray();
|
||||
boolean first = true;
|
||||
for (long v : val) {
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
writeValueSeparator();
|
||||
}
|
||||
write(v);
|
||||
}
|
||||
endArray();
|
||||
}
|
||||
|
||||
public void write(float[] val) {
|
||||
startArray();
|
||||
boolean first = true;
|
||||
for (float v : val) {
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
writeValueSeparator();
|
||||
}
|
||||
write(v);
|
||||
}
|
||||
endArray();
|
||||
}
|
||||
|
||||
public void write(double[] val) {
|
||||
startArray();
|
||||
boolean first = true;
|
||||
for (double v : val) {
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
writeValueSeparator();
|
||||
}
|
||||
write(v);
|
||||
}
|
||||
endArray();
|
||||
}
|
||||
|
||||
public void write(boolean[] val) {
|
||||
startArray();
|
||||
boolean first = true;
|
||||
for (boolean v : val) {
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
writeValueSeparator();
|
||||
}
|
||||
write(v);
|
||||
}
|
||||
endArray();
|
||||
}
|
||||
|
||||
|
||||
public void write(short number) { write ((int)number); }
|
||||
public void write(byte number) { write((int)number); }
|
||||
|
||||
|
||||
public void writeNull() {
|
||||
JSONUtil.writeNull(out);
|
||||
}
|
||||
|
||||
public void writeString(CharSequence str) {
|
||||
JSONUtil.writeString(str,0,str.length(),out);
|
||||
}
|
||||
|
||||
public void writeString(CharArr str) {
|
||||
JSONUtil.writeString(str,out);
|
||||
}
|
||||
|
||||
public void writeStringStart() {
|
||||
out.write('"');
|
||||
}
|
||||
|
||||
public void writeStringChars(CharArr partialStr) {
|
||||
JSONUtil.writeStringPart(partialStr.getArray(), partialStr.getStart(), partialStr.getEnd(), out);
|
||||
}
|
||||
|
||||
public void writeStringEnd() {
|
||||
out.write('"');
|
||||
}
|
||||
|
||||
public void write(long number) {
|
||||
JSONUtil.writeNumber(number,out);
|
||||
}
|
||||
|
||||
public void write(int number) {
|
||||
JSONUtil.writeNumber(number,out);
|
||||
}
|
||||
|
||||
public void write(double number) {
|
||||
JSONUtil.writeNumber(number,out);
|
||||
}
|
||||
|
||||
public void write(float number) {
|
||||
JSONUtil.writeNumber(number,out);
|
||||
}
|
||||
|
||||
public void write(boolean bool) {
|
||||
JSONUtil.writeBoolean(bool,out);
|
||||
}
|
||||
|
||||
public void write(char[] val) {
|
||||
JSONUtil.writeString(val, 0, val.length, out);
|
||||
}
|
||||
|
||||
public void writeNumber(CharArr digits) {
|
||||
out.write(digits);
|
||||
}
|
||||
|
||||
public void writePartialNumber(CharArr digits) {
|
||||
out.write(digits);
|
||||
}
|
||||
|
||||
public void startObject() {
|
||||
out.write('{');
|
||||
level++;
|
||||
}
|
||||
|
||||
public void endObject() {
|
||||
out.write('}');
|
||||
level--;
|
||||
}
|
||||
|
||||
public void startArray() {
|
||||
out.write('[');
|
||||
level++;
|
||||
}
|
||||
|
||||
public void endArray() {
|
||||
out.write(']');
|
||||
level--;
|
||||
}
|
||||
|
||||
public void writeValueSeparator() {
|
||||
out.write(',');
|
||||
}
|
||||
|
||||
public void writeNameSeparator() {
|
||||
out.write(':');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,152 +0,0 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.noggit;
|
||||
|
||||
import java.util.*;
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
|
||||
/**
|
||||
*/
|
||||
public class ObjectBuilder {
|
||||
|
||||
public static Object fromJSON(String json) throws IOException {
|
||||
JSONParser p = new JSONParser(json);
|
||||
return getVal(p);
|
||||
}
|
||||
|
||||
public static Object getVal(JSONParser parser) throws IOException {
|
||||
return new ObjectBuilder(parser).getVal();
|
||||
}
|
||||
|
||||
final JSONParser parser;
|
||||
|
||||
public ObjectBuilder(JSONParser parser) throws IOException {
|
||||
this.parser = parser;
|
||||
if (parser.lastEvent()==0) parser.nextEvent();
|
||||
}
|
||||
|
||||
|
||||
public Object getVal() throws IOException {
|
||||
int ev = parser.lastEvent();
|
||||
switch(ev) {
|
||||
case JSONParser.STRING: return getString();
|
||||
case JSONParser.LONG: return getLong();
|
||||
case JSONParser.NUMBER: return getNumber();
|
||||
case JSONParser.BIGNUMBER: return getBigNumber();
|
||||
case JSONParser.BOOLEAN: return getBoolean();
|
||||
case JSONParser.NULL: return getNull();
|
||||
case JSONParser.OBJECT_START: return getObject();
|
||||
case JSONParser.OBJECT_END: return null; // OR ERROR?
|
||||
case JSONParser.ARRAY_START: return getArray();
|
||||
case JSONParser.ARRAY_END: return null; // OR ERROR?
|
||||
case JSONParser.EOF: return null; // OR ERROR?
|
||||
default: return null; // OR ERROR?
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Object getString() throws IOException {
|
||||
return parser.getString();
|
||||
}
|
||||
|
||||
public Object getLong() throws IOException {
|
||||
return Long.valueOf(parser.getLong());
|
||||
}
|
||||
|
||||
public Object getNumber() throws IOException {
|
||||
CharArr num = parser.getNumberChars();
|
||||
String numstr = num.toString();
|
||||
double d = Double.parseDouble(numstr);
|
||||
if (!Double.isInfinite(d)) return Double.valueOf(d);
|
||||
// TODO: use more efficient constructor in Java5
|
||||
return new BigDecimal(numstr);
|
||||
}
|
||||
|
||||
public Object getBigNumber() throws IOException {
|
||||
CharArr num = parser.getNumberChars();
|
||||
String numstr = num.toString();
|
||||
for(int ch; (ch=num.read())!=-1;) {
|
||||
if (ch=='.' || ch=='e' || ch=='E') return new BigDecimal(numstr);
|
||||
}
|
||||
return new BigInteger(numstr);
|
||||
}
|
||||
|
||||
public Object getBoolean() throws IOException {
|
||||
return parser.getBoolean();
|
||||
}
|
||||
|
||||
public Object getNull() throws IOException {
|
||||
parser.getNull();
|
||||
return null;
|
||||
}
|
||||
|
||||
public Object newObject() throws IOException {
|
||||
return new LinkedHashMap();
|
||||
}
|
||||
|
||||
public Object getKey() throws IOException {
|
||||
return parser.getString();
|
||||
}
|
||||
|
||||
public void addKeyVal(Object map, Object key, Object val) throws IOException {
|
||||
Object prev = ((Map)map).put(key,val);
|
||||
// TODO: test for repeated value?
|
||||
}
|
||||
|
||||
public Object objectEnd(Object obj) {
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
||||
public Object getObject() throws IOException {
|
||||
Object m = newObject();
|
||||
for(;;) {
|
||||
int ev = parser.nextEvent();
|
||||
if (ev==JSONParser.OBJECT_END) return objectEnd(m);
|
||||
Object key = getKey();
|
||||
ev = parser.nextEvent();
|
||||
Object val = getVal();
|
||||
addKeyVal(m, key, val);
|
||||
}
|
||||
}
|
||||
|
||||
public Object newArray() {
|
||||
return new ArrayList();
|
||||
}
|
||||
|
||||
public void addArrayVal(Object arr, Object val) throws IOException {
|
||||
((List)arr).add(val);
|
||||
}
|
||||
|
||||
public Object endArray(Object arr) {
|
||||
return arr;
|
||||
}
|
||||
|
||||
public Object getArray() throws IOException {
|
||||
Object arr = newArray();
|
||||
for(;;) {
|
||||
int ev = parser.nextEvent();
|
||||
if (ev==JSONParser.ARRAY_END) return endArray(arr);
|
||||
Object val = getVal();
|
||||
addArrayVal(arr, val);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<html>
|
||||
<body>
|
||||
JSON streaming parser and serializer.
|
||||
</body>
|
||||
</html>
|
|
@ -26,7 +26,7 @@ import java.util.Map;
|
|||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.noggit.JSONWriter;
|
||||
import org.noggit.JSONWriter;
|
||||
import org.apache.solr.common.SolrException;
|
||||
import org.apache.solr.common.SolrException.ErrorCode;
|
||||
import org.apache.zookeeper.KeeperException;
|
||||
|
|
|
@ -17,8 +17,8 @@ package org.apache.solr.common.cloud;
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import org.apache.noggit.JSONUtil;
|
||||
import org.apache.noggit.JSONWriter;
|
||||
import org.noggit.JSONUtil;
|
||||
import org.noggit.JSONWriter;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
|
|
@ -17,7 +17,7 @@ package org.apache.solr.common.cloud;
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import org.apache.noggit.JSONWriter;
|
||||
import org.noggit.JSONWriter;
|
||||
import org.apache.solr.common.SolrException;
|
||||
import org.apache.solr.common.SolrInputDocument;
|
||||
import org.apache.solr.common.params.SolrParams;
|
||||
|
|
|
@ -17,7 +17,7 @@ package org.apache.solr.common.cloud;
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import org.apache.noggit.JSONUtil;
|
||||
import org.noggit.JSONUtil;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
|
|
|
@ -17,8 +17,8 @@ package org.apache.solr.common.cloud;
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import org.apache.noggit.JSONUtil;
|
||||
import org.apache.noggit.JSONWriter;
|
||||
import org.noggit.JSONUtil;
|
||||
import org.noggit.JSONWriter;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
|
|
|
@ -17,8 +17,8 @@ package org.apache.solr.common.cloud;
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import org.apache.noggit.JSONUtil;
|
||||
import org.apache.noggit.JSONWriter;
|
||||
import org.noggit.JSONUtil;
|
||||
import org.noggit.JSONWriter;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
|
|
|
@ -31,10 +31,10 @@ import java.util.concurrent.ThreadFactory;
|
|||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import org.apache.noggit.CharArr;
|
||||
import org.apache.noggit.JSONParser;
|
||||
import org.apache.noggit.JSONWriter;
|
||||
import org.apache.noggit.ObjectBuilder;
|
||||
import org.noggit.CharArr;
|
||||
import org.noggit.JSONParser;
|
||||
import org.noggit.JSONWriter;
|
||||
import org.noggit.ObjectBuilder;
|
||||
import org.apache.solr.common.SolrException;
|
||||
import org.apache.solr.common.SolrException.ErrorCode;
|
||||
import org.apache.solr.common.util.ByteUtils;
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
package org.apache.solr.common.util;
|
||||
|
||||
import org.apache.noggit.CharArr;
|
||||
import org.noggit.CharArr;
|
||||
|
||||
public class ByteUtils {
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
*/
|
||||
package org.apache.solr.common.util;
|
||||
|
||||
import org.apache.noggit.CharArr;
|
||||
import org.noggit.CharArr;
|
||||
import org.apache.solr.common.SolrDocument;
|
||||
import org.apache.solr.common.SolrDocumentList;
|
||||
import org.apache.solr.common.SolrInputDocument;
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
package org.apache.solr;
|
||||
|
||||
import org.apache.noggit.ObjectBuilder;
|
||||
import org.noggit.ObjectBuilder;
|
||||
import org.apache.solr.common.util.StrUtils;
|
||||
|
||||
import java.util.*;
|
||||
|
|
|
@ -26,7 +26,6 @@ import javax.xml.xpath.XPathExpressionException;
|
|||
import org.apache.lucene.util.Constants;
|
||||
import org.apache.lucene.util.LuceneTestCase;
|
||||
import org.apache.lucene.util.QuickPatchThreadsFilter;
|
||||
import org.apache.noggit.*;
|
||||
import org.apache.solr.client.solrj.util.ClientUtils;
|
||||
import org.apache.solr.common.*;
|
||||
import org.apache.solr.common.cloud.SolrZkClient;
|
||||
|
@ -47,6 +46,9 @@ import org.apache.solr.util.TestHarness;
|
|||
import org.junit.*;
|
||||
import org.junit.rules.RuleChain;
|
||||
import org.junit.rules.TestRule;
|
||||
import org.noggit.CharArr;
|
||||
import org.noggit.JSONUtil;
|
||||
import org.noggit.ObjectBuilder;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.xml.sax.SAXException;
|
||||
|
|
Loading…
Reference in New Issue