PageRenderTime 57ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 0ms

/src/main/java/com/alibaba/fastjson/serializer/SerializeWriter.java

https://bitbucket.org/xiejuntao/xdesktop
Java | 1536 lines | 1219 code | 209 blank | 108 comment | 297 complexity | c54abca9344236bc7a88dc6a17e7af63 MD5 | raw file
  1. /*
  2. * Copyright 1999-2101 Alibaba Group.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package com.alibaba.fastjson.serializer;
  17. import static com.alibaba.fastjson.parser.CharTypes.replaceChars;
  18. import java.io.IOException;
  19. import java.io.OutputStream;
  20. import java.io.Writer;
  21. import java.lang.ref.SoftReference;
  22. import java.math.BigDecimal;
  23. import java.nio.charset.Charset;
  24. import com.alibaba.fastjson.JSON;
  25. import com.alibaba.fastjson.parser.CharTypes;
  26. import com.alibaba.fastjson.util.Base64;
  27. import com.alibaba.fastjson.util.IOUtils;
  28. /**
  29. * @author wenshao<szujobs@hotmail.com>
  30. */
  31. public final class SerializeWriter extends Writer {
  32. /**
  33. * The buffer where data is stored.
  34. */
  35. protected char buf[];
  36. /**
  37. * The number of chars in the buffer.
  38. */
  39. protected int count;
  40. private final static ThreadLocal<SoftReference<char[]>> bufLocal = new ThreadLocal<SoftReference<char[]>>();
  41. private int features;
  42. public SerializeWriter(){
  43. this.features = JSON.DEFAULT_GENERATE_FEATURE;
  44. SoftReference<char[]> ref = bufLocal.get();
  45. if (ref != null) {
  46. buf = ref.get();
  47. bufLocal.set(null);
  48. }
  49. if (buf == null) {
  50. buf = new char[1024];
  51. }
  52. }
  53. /**
  54. * Creates a new CharArrayWriter.
  55. */
  56. public SerializeWriter(SerializerFeature... features){
  57. SoftReference<char[]> ref = bufLocal.get();
  58. if (ref != null) {
  59. buf = ref.get();
  60. bufLocal.set(null);
  61. }
  62. if (buf == null) {
  63. buf = new char[1024];
  64. }
  65. int featuresValue = 0;
  66. for (SerializerFeature feature : features) {
  67. featuresValue |= feature.getMask();
  68. }
  69. this.features = featuresValue;
  70. }
  71. /**
  72. * Creates a new CharArrayWriter with the specified initial size.
  73. *
  74. * @param initialSize an int specifying the initial buffer size.
  75. * @exception IllegalArgumentException if initialSize is negative
  76. */
  77. public SerializeWriter(int initialSize){
  78. if (initialSize <= 0) {
  79. throw new IllegalArgumentException("Negative initial size: " + initialSize);
  80. }
  81. buf = new char[initialSize];
  82. }
  83. public void config(SerializerFeature feature, boolean state) {
  84. if (state) {
  85. features |= feature.getMask();
  86. } else {
  87. features &= ~feature.getMask();
  88. }
  89. }
  90. public boolean isEnabled(SerializerFeature feature) {
  91. return SerializerFeature.isEnabled(this.features, feature);
  92. }
  93. /**
  94. * Writes a character to the buffer.
  95. */
  96. public void write(int c) {
  97. int newcount = count + 1;
  98. if (newcount > buf.length) {
  99. expandCapacity(newcount);
  100. }
  101. buf[count] = (char) c;
  102. count = newcount;
  103. }
  104. public void write(char c) {
  105. int newcount = count + 1;
  106. if (newcount > buf.length) {
  107. expandCapacity(newcount);
  108. }
  109. buf[count] = c;
  110. count = newcount;
  111. }
  112. /**
  113. * Writes characters to the buffer.
  114. *
  115. * @param c the data to be written
  116. * @param off the start offset in the data
  117. * @param len the number of chars that are written
  118. */
  119. public void write(char c[], int off, int len) {
  120. if (off < 0 || off > c.length || len < 0 || off + len > c.length || off + len < 0) {
  121. throw new IndexOutOfBoundsException();
  122. } else if (len == 0) {
  123. return;
  124. }
  125. int newcount = count + len;
  126. if (newcount > buf.length) {
  127. expandCapacity(newcount);
  128. }
  129. System.arraycopy(c, off, buf, count, len);
  130. count = newcount;
  131. }
  132. public void expandCapacity(int minimumCapacity) {
  133. int newCapacity = (buf.length * 3) / 2 + 1;
  134. if (newCapacity < minimumCapacity) {
  135. newCapacity = minimumCapacity;
  136. }
  137. char newValue[] = new char[newCapacity];
  138. System.arraycopy(buf, 0, newValue, 0, count);
  139. buf = newValue;
  140. }
  141. /**
  142. * Write a portion of a string to the buffer.
  143. *
  144. * @param str String to be written from
  145. * @param off Offset from which to start reading characters
  146. * @param len Number of characters to be written
  147. */
  148. public void write(String str, int off, int len) {
  149. int newcount = count + len;
  150. if (newcount > buf.length) {
  151. expandCapacity(newcount);
  152. }
  153. str.getChars(off, off + len, buf, count);
  154. count = newcount;
  155. }
  156. /**
  157. * Writes the contents of the buffer to another character stream.
  158. *
  159. * @param out the output stream to write to
  160. * @throws IOException If an I/O error occurs.
  161. */
  162. public void writeTo(Writer out) throws IOException {
  163. out.write(buf, 0, count);
  164. }
  165. public void writeTo(OutputStream out, String charset) throws IOException {
  166. byte[] bytes = new String(buf, 0, count).getBytes(charset);
  167. out.write(bytes);
  168. }
  169. public void writeTo(OutputStream out, Charset charset) throws IOException {
  170. byte[] bytes = new String(buf, 0, count).getBytes(charset);
  171. out.write(bytes);
  172. }
  173. public SerializeWriter append(CharSequence csq) {
  174. String s = (csq == null ? "null" : csq.toString());
  175. write(s, 0, s.length());
  176. return this;
  177. }
  178. public SerializeWriter append(CharSequence csq, int start, int end) {
  179. String s = (csq == null ? "null" : csq).subSequence(start, end).toString();
  180. write(s, 0, s.length());
  181. return this;
  182. }
  183. /**
  184. * Appends the specified character to this writer.
  185. * <p>
  186. * An invocation of this method of the form <tt>out.append(c)</tt> behaves in exactly the same way as the invocation
  187. *
  188. * <pre>
  189. * out.write(c)
  190. * </pre>
  191. *
  192. * @param c The 16-bit character to append
  193. * @return This writer
  194. * @since 1.5
  195. */
  196. public SerializeWriter append(char c) {
  197. write(c);
  198. return this;
  199. }
  200. /**
  201. * Resets the buffer so that you can use it again without throwing away the already allocated buffer.
  202. */
  203. public void reset() {
  204. count = 0;
  205. }
  206. /**
  207. * Returns a copy of the input data.
  208. *
  209. * @return an array of chars copied from the input data.
  210. */
  211. public char[] toCharArray() {
  212. char[] newValue = new char[count];
  213. System.arraycopy(buf, 0, newValue, 0, count);
  214. return newValue;
  215. }
  216. public byte[] toBytes(String charsetName) {
  217. if (charsetName == null) {
  218. charsetName = "UTF-8";
  219. }
  220. Charset cs = Charset.forName(charsetName);
  221. SerialWriterStringEncoder encoder = new SerialWriterStringEncoder(cs);
  222. return encoder.encode(buf, 0, count);
  223. }
  224. /**
  225. * Returns the current size of the buffer.
  226. *
  227. * @return an int representing the current size of the buffer.
  228. */
  229. public int size() {
  230. return count;
  231. }
  232. /**
  233. * Converts input data to a string.
  234. *
  235. * @return the string.
  236. */
  237. public String toString() {
  238. return new String(buf, 0, count);
  239. }
  240. /**
  241. * Flush the stream.
  242. */
  243. public void flush() {
  244. }
  245. /**
  246. * Close the stream. This method does not release the buffer, since its contents might still be required. Note:
  247. * Invoking this method in this class will have no effect.
  248. */
  249. public void close() {
  250. if (buf.length <= 1024 * 8) {
  251. bufLocal.set(new SoftReference<char[]>(buf));
  252. }
  253. this.buf = null;
  254. }
  255. public void writeBooleanArray(boolean[] array) throws IOException {
  256. int[] sizeArray = new int[array.length];
  257. int totalSize = 2;
  258. for (int i = 0; i < array.length; ++i) {
  259. if (i != 0) {
  260. totalSize++;
  261. }
  262. boolean val = array[i];
  263. int size;
  264. if (val) {
  265. size = 4; // "true".length();
  266. } else {
  267. size = 5; // "false".length();
  268. }
  269. sizeArray[i] = size;
  270. totalSize += size;
  271. }
  272. int newcount = count + totalSize;
  273. if (newcount > buf.length) {
  274. expandCapacity(newcount);
  275. }
  276. buf[count] = '[';
  277. int currentSize = count + 1;
  278. for (int i = 0; i < array.length; ++i) {
  279. if (i != 0) {
  280. buf[currentSize++] = ',';
  281. }
  282. boolean val = array[i];
  283. if (val) {
  284. // System.arraycopy("true".toCharArray(), 0, buf, currentSize,
  285. // 4);
  286. buf[currentSize++] = 't';
  287. buf[currentSize++] = 'r';
  288. buf[currentSize++] = 'u';
  289. buf[currentSize++] = 'e';
  290. } else {
  291. buf[currentSize++] = 'f';
  292. buf[currentSize++] = 'a';
  293. buf[currentSize++] = 'l';
  294. buf[currentSize++] = 's';
  295. buf[currentSize++] = 'e';
  296. }
  297. }
  298. buf[currentSize] = ']';
  299. count = newcount;
  300. }
  301. public void write(String text) {
  302. if (text == null) {
  303. writeNull();
  304. return;
  305. }
  306. int length = text.length();
  307. int newcount = count + length;
  308. if (newcount > buf.length) {
  309. expandCapacity(newcount);
  310. }
  311. text.getChars(0, length, buf, count);
  312. count = newcount;
  313. return;
  314. }
  315. public void writeInt(int i) {
  316. if (i == Integer.MIN_VALUE) {
  317. write("-2147483648");
  318. return;
  319. }
  320. int size = (i < 0) ? IOUtils.stringSize(-i) + 1 : IOUtils.stringSize(i);
  321. int newcount = count + size;
  322. if (newcount > buf.length) {
  323. expandCapacity(newcount);
  324. }
  325. IOUtils.getChars(i, newcount, buf);
  326. count = newcount;
  327. }
  328. public void writeShortArray(short[] array) throws IOException {
  329. int[] sizeArray = new int[array.length];
  330. int totalSize = 2;
  331. for (int i = 0; i < array.length; ++i) {
  332. if (i != 0) {
  333. totalSize++;
  334. }
  335. short val = array[i];
  336. int size = IOUtils.stringSize(val);
  337. sizeArray[i] = size;
  338. totalSize += size;
  339. }
  340. int newcount = count + totalSize;
  341. if (newcount > buf.length) {
  342. expandCapacity(newcount);
  343. }
  344. buf[count] = '[';
  345. int currentSize = count + 1;
  346. for (int i = 0; i < array.length; ++i) {
  347. if (i != 0) {
  348. buf[currentSize++] = ',';
  349. }
  350. short val = array[i];
  351. currentSize += sizeArray[i];
  352. IOUtils.getChars(val, currentSize, buf);
  353. }
  354. buf[currentSize] = ']';
  355. count = newcount;
  356. }
  357. public void writeByteArray(byte[] bytes) {
  358. int bytesLen = bytes.length;
  359. if (bytesLen == 0) {
  360. write("\"\"");
  361. return;
  362. }
  363. final char[] CA = Base64.CA;
  364. int eLen = (bytesLen / 3) * 3; // Length of even 24-bits.
  365. int charsLen = ((bytesLen - 1) / 3 + 1) << 2; // base64 character count
  366. // char[] chars = new char[charsLen];
  367. int offset = count;
  368. int newcount = count + charsLen + 2;
  369. if (newcount > buf.length) {
  370. expandCapacity(newcount);
  371. }
  372. count = newcount;
  373. buf[offset++] = '\"';
  374. // Encode even 24-bits
  375. for (int s = 0, d = offset; s < eLen;) {
  376. // Copy next three bytes into lower 24 bits of int, paying attension to sign.
  377. int i = (bytes[s++] & 0xff) << 16 | (bytes[s++] & 0xff) << 8 | (bytes[s++] & 0xff);
  378. // Encode the int into four chars
  379. buf[d++] = CA[(i >>> 18) & 0x3f];
  380. buf[d++] = CA[(i >>> 12) & 0x3f];
  381. buf[d++] = CA[(i >>> 6) & 0x3f];
  382. buf[d++] = CA[i & 0x3f];
  383. }
  384. // Pad and encode last bits if source isn't even 24 bits.
  385. int left = bytesLen - eLen; // 0 - 2.
  386. if (left > 0) {
  387. // Prepare the int
  388. int i = ((bytes[eLen] & 0xff) << 10) | (left == 2 ? ((bytes[bytesLen - 1] & 0xff) << 2) : 0);
  389. // Set last four chars
  390. buf[newcount - 5] = CA[i >> 12];
  391. buf[newcount - 4] = CA[(i >>> 6) & 0x3f];
  392. buf[newcount - 3] = left == 2 ? CA[i & 0x3f] : '=';
  393. buf[newcount - 2] = '=';
  394. }
  395. buf[newcount - 1] = '\"';
  396. }
  397. public void writeIntArray(int[] array) {
  398. int[] sizeArray = new int[array.length];
  399. int totalSize = 2;
  400. for (int i = 0; i < array.length; ++i) {
  401. if (i != 0) {
  402. totalSize++;
  403. }
  404. int val = array[i];
  405. int size;
  406. if (val == Integer.MIN_VALUE) {
  407. size = "-2147483648".length();
  408. } else {
  409. size = (val < 0) ? IOUtils.stringSize(-val) + 1 : IOUtils.stringSize(val);
  410. }
  411. sizeArray[i] = size;
  412. totalSize += size;
  413. }
  414. int newcount = count + totalSize;
  415. if (newcount > buf.length) {
  416. expandCapacity(newcount);
  417. }
  418. buf[count] = '[';
  419. int currentSize = count + 1;
  420. for (int i = 0; i < array.length; ++i) {
  421. if (i != 0) {
  422. buf[currentSize++] = ',';
  423. }
  424. int val = array[i];
  425. if (val == Integer.MIN_VALUE) {
  426. System.arraycopy("-2147483648".toCharArray(), 0, buf, currentSize, sizeArray[i]);
  427. currentSize += sizeArray[i];
  428. } else {
  429. currentSize += sizeArray[i];
  430. IOUtils.getChars(val, currentSize, buf);
  431. }
  432. }
  433. buf[currentSize] = ']';
  434. count = newcount;
  435. }
  436. public void writeIntAndChar(int i, char c) {
  437. if (i == Integer.MIN_VALUE) {
  438. write("-2147483648");
  439. write(c);
  440. return;
  441. }
  442. int size = (i < 0) ? IOUtils.stringSize(-i) + 1 : IOUtils.stringSize(i);
  443. int newcount0 = count + size;
  444. int newcount1 = newcount0 + 1;
  445. if (newcount1 > buf.length) {
  446. expandCapacity(newcount1);
  447. }
  448. IOUtils.getChars(i, newcount0, buf);
  449. buf[newcount0] = c;
  450. count = newcount1;
  451. }
  452. public void writeLongAndChar(long i, char c) throws IOException {
  453. if (i == Long.MIN_VALUE) {
  454. write("-9223372036854775808");
  455. write(c);
  456. return;
  457. }
  458. int size = (i < 0) ? IOUtils.stringSize(-i) + 1 : IOUtils.stringSize(i);
  459. int newcount0 = count + size;
  460. int newcount1 = newcount0 + 1;
  461. if (newcount1 > buf.length) {
  462. expandCapacity(newcount1);
  463. }
  464. IOUtils.getChars(i, newcount0, buf);
  465. buf[newcount0] = c;
  466. count = newcount1;
  467. }
  468. public void writeLong(long i) {
  469. if (i == Long.MIN_VALUE) {
  470. write("-9223372036854775808");
  471. return;
  472. }
  473. int size = (i < 0) ? IOUtils.stringSize(-i) + 1 : IOUtils.stringSize(i);
  474. int newcount = count + size;
  475. if (newcount > buf.length) {
  476. expandCapacity(newcount);
  477. }
  478. IOUtils.getChars(i, newcount, buf);
  479. count = newcount;
  480. }
  481. public void writeNull() {
  482. int newcount = count + 4;
  483. if (newcount > buf.length) {
  484. expandCapacity(newcount);
  485. }
  486. buf[count] = 'n';
  487. buf[count + 1] = 'u';
  488. buf[count + 2] = 'l';
  489. buf[count + 3] = 'l';
  490. count = newcount;
  491. }
  492. public void writeLongArray(long[] array) {
  493. int[] sizeArray = new int[array.length];
  494. int totalSize = 2;
  495. for (int i = 0; i < array.length; ++i) {
  496. if (i != 0) {
  497. totalSize++;
  498. }
  499. long val = array[i];
  500. int size;
  501. if (val == Long.MIN_VALUE) {
  502. size = "-9223372036854775808".length();
  503. } else {
  504. size = (val < 0) ? IOUtils.stringSize(-val) + 1 : IOUtils.stringSize(val);
  505. }
  506. sizeArray[i] = size;
  507. totalSize += size;
  508. }
  509. int newcount = count + totalSize;
  510. if (newcount > buf.length) {
  511. expandCapacity(newcount);
  512. }
  513. buf[count] = '[';
  514. int currentSize = count + 1;
  515. for (int i = 0; i < array.length; ++i) {
  516. if (i != 0) {
  517. buf[currentSize++] = ',';
  518. }
  519. long val = array[i];
  520. if (val == Long.MIN_VALUE) {
  521. System.arraycopy("-9223372036854775808".toCharArray(), 0, buf, currentSize, sizeArray[i]);
  522. currentSize += sizeArray[i];
  523. } else {
  524. currentSize += sizeArray[i];
  525. IOUtils.getChars(val, currentSize, buf);
  526. }
  527. }
  528. buf[currentSize] = ']';
  529. count = newcount;
  530. }
  531. private void writeStringWithDoubleQuote(String text, final char seperator) {
  532. writeStringWithDoubleQuote(text, seperator, true);
  533. }
  534. private void writeStringWithDoubleQuote(String text, final char seperator, boolean checkSpecial) {
  535. // final boolean[] specicalFlags_doubleQuotes =
  536. // CharTypes.specicalFlags_doubleQuotes;
  537. // final int len_flags = specicalFlags_doubleQuotes.length;
  538. if (text == null) {
  539. writeNull();
  540. return;
  541. }
  542. int len = text.length();
  543. int newcount = count + len + 2;
  544. if (seperator != 0) {
  545. newcount++;
  546. }
  547. if (newcount > buf.length) {
  548. expandCapacity(newcount);
  549. }
  550. int start = count + 1;
  551. int end = start + len;
  552. buf[count] = '\"';
  553. text.getChars(0, len, buf, start);
  554. count = newcount;
  555. if (isEnabled(SerializerFeature.BrowserCompatible)) {
  556. int lastSpecialIndex = -1;
  557. for (int i = start; i < end; ++i) {
  558. char ch = buf[i];
  559. if (ch == '"' || ch == '/' || ch == '\\') {
  560. lastSpecialIndex = i;
  561. newcount += 1;
  562. continue;
  563. }
  564. if (ch == '\b' || ch == '\f' || ch == '\n' || ch == '\r' || ch == '\t') {
  565. lastSpecialIndex = i;
  566. newcount += 1;
  567. continue;
  568. }
  569. if (ch < 32) {
  570. lastSpecialIndex = i;
  571. newcount += 5;
  572. continue;
  573. }
  574. if (ch >= 127) {
  575. lastSpecialIndex = i;
  576. newcount += 5;
  577. continue;
  578. }
  579. }
  580. if (newcount > buf.length) {
  581. expandCapacity(newcount);
  582. }
  583. count = newcount;
  584. for (int i = lastSpecialIndex; i >= start; --i) {
  585. char ch = buf[i];
  586. if (ch == '\b' || ch == '\f' || ch == '\n' || ch == '\r' || ch == '\t') {
  587. System.arraycopy(buf, i + 1, buf, i + 2, end - i - 1);
  588. buf[i] = '\\';
  589. buf[i + 1] = replaceChars[(int) ch];
  590. end += 1;
  591. continue;
  592. }
  593. if (ch == '"' || ch == '/' || ch == '\\') {
  594. System.arraycopy(buf, i + 1, buf, i + 2, end - i - 1);
  595. buf[i] = '\\';
  596. buf[i + 1] = ch;
  597. end += 1;
  598. continue;
  599. }
  600. if (ch < 32) {
  601. System.arraycopy(buf, i + 1, buf, i + 6, end - i - 1);
  602. buf[i] = '\\';
  603. buf[i + 1] = 'u';
  604. buf[i + 2] = '0';
  605. buf[i + 3] = '0';
  606. buf[i + 4] = CharTypes.ASCII_CHARS[ch * 2];
  607. buf[i + 5] = CharTypes.ASCII_CHARS[ch * 2 + 1];
  608. end += 5;
  609. continue;
  610. }
  611. if (ch >= 127) {
  612. System.arraycopy(buf, i + 1, buf, i + 6, end - i - 1);
  613. buf[i] = '\\';
  614. buf[i + 1] = 'u';
  615. buf[i + 2] = CharTypes.digits[(ch >>> 12) & 15];
  616. buf[i + 3] = CharTypes.digits[(ch >>> 8) & 15];
  617. buf[i + 4] = CharTypes.digits[(ch >>> 4) & 15];
  618. buf[i + 5] = CharTypes.digits[ch & 15];
  619. end += 5;
  620. }
  621. }
  622. if (seperator != 0) {
  623. buf[count - 2] = '\"';
  624. buf[count - 1] = seperator;
  625. } else {
  626. buf[count - 1] = '\"';
  627. }
  628. return;
  629. }
  630. int specialCount = 0;
  631. int lastSpecialIndex = -1;
  632. char lastSpecial = '\0';
  633. if (checkSpecial) {
  634. for (int i = start; i < end; ++i) {
  635. char ch = buf[i];
  636. if (ch >= ']') {
  637. continue;
  638. }
  639. if (ch == ' ') {
  640. continue;
  641. }
  642. if (ch >= '0' && ch != '\\') {
  643. continue;
  644. }
  645. if (ch < CharTypes.specicalFlags_doubleQuotes.length
  646. && CharTypes.specicalFlags_doubleQuotes[ch] //
  647. || (ch == '\t' && isEnabled(SerializerFeature.WriteTabAsSpecial))
  648. || (ch == '/' && isEnabled(SerializerFeature.WriteSlashAsSpecial))) {
  649. specialCount++;
  650. lastSpecialIndex = i;
  651. lastSpecial = ch;
  652. }
  653. }
  654. }
  655. newcount += specialCount;
  656. if (newcount > buf.length) {
  657. expandCapacity(newcount);
  658. }
  659. count = newcount;
  660. if (specialCount == 1) {
  661. System.arraycopy(buf, lastSpecialIndex + 1, buf, lastSpecialIndex + 2, end - lastSpecialIndex - 1);
  662. buf[lastSpecialIndex] = '\\';
  663. buf[++lastSpecialIndex] = replaceChars[(int) lastSpecial];
  664. } else if (specialCount > 1) {
  665. System.arraycopy(buf, lastSpecialIndex + 1, buf, lastSpecialIndex + 2, end - lastSpecialIndex - 1);
  666. buf[lastSpecialIndex] = '\\';
  667. buf[++lastSpecialIndex] = replaceChars[(int) lastSpecial];
  668. end++;
  669. for (int i = lastSpecialIndex - 2; i >= start; --i) {
  670. char ch = buf[i];
  671. if (ch < CharTypes.specicalFlags_doubleQuotes.length
  672. && CharTypes.specicalFlags_doubleQuotes[ch] //
  673. || (ch == '\t' && isEnabled(SerializerFeature.WriteTabAsSpecial))
  674. || (ch == '/' && isEnabled(SerializerFeature.WriteSlashAsSpecial))) {
  675. System.arraycopy(buf, i + 1, buf, i + 2, end - i - 1);
  676. buf[i] = '\\';
  677. buf[i + 1] = replaceChars[(int) ch];
  678. end++;
  679. }
  680. }
  681. }
  682. if (seperator != 0) {
  683. buf[count - 2] = '\"';
  684. buf[count - 1] = seperator;
  685. } else {
  686. buf[count - 1] = '\"';
  687. }
  688. }
  689. public void writeKeyWithDoubleQuote(String text) {
  690. writeKeyWithDoubleQuote(text, true);
  691. }
  692. public void writeKeyWithDoubleQuote(String text, boolean checkSpecial) {
  693. final boolean[] specicalFlags_doubleQuotes = CharTypes.specicalFlags_doubleQuotes;
  694. int len = text.length();
  695. int newcount = count + len + 3;
  696. if (newcount > buf.length) {
  697. expandCapacity(newcount);
  698. }
  699. int start = count + 1;
  700. int end = start + len;
  701. buf[count] = '\"';
  702. text.getChars(0, len, buf, start);
  703. count = newcount;
  704. if (checkSpecial) {
  705. for (int i = start; i < end; ++i) {
  706. char ch = buf[i];
  707. if (ch < specicalFlags_doubleQuotes.length
  708. && specicalFlags_doubleQuotes[ch] //
  709. || (ch == '\t' && isEnabled(SerializerFeature.WriteTabAsSpecial))
  710. || (ch == '/' && isEnabled(SerializerFeature.WriteSlashAsSpecial))) {
  711. newcount++;
  712. if (newcount > buf.length) {
  713. expandCapacity(newcount);
  714. }
  715. count = newcount;
  716. System.arraycopy(buf, i + 1, buf, i + 2, end - i - 1);
  717. buf[i] = '\\';
  718. buf[++i] = replaceChars[(int) ch];
  719. end++;
  720. }
  721. }
  722. }
  723. buf[count - 2] = '\"';
  724. buf[count - 1] = ':';
  725. }
  726. public void writeFieldNull(char seperator, String name) {
  727. write(seperator);
  728. writeFieldName(name);
  729. writeNull();
  730. }
  731. public void writeFieldEmptyList(char seperator, String key) {
  732. write(seperator);
  733. writeFieldName(key);
  734. write("[]");
  735. }
  736. public void writeFieldNullString(char seperator, String name) {
  737. write(seperator);
  738. writeFieldName(name);
  739. if (isEnabled(SerializerFeature.WriteNullStringAsEmpty)) {
  740. writeString("");
  741. } else {
  742. writeNull();
  743. }
  744. }
  745. public void writeFieldNullBoolean(char seperator, String name) {
  746. write(seperator);
  747. writeFieldName(name);
  748. if (isEnabled(SerializerFeature.WriteNullBooleanAsFalse)) {
  749. write("false");
  750. } else {
  751. writeNull();
  752. }
  753. }
  754. public void writeFieldNullList(char seperator, String name) {
  755. write(seperator);
  756. writeFieldName(name);
  757. if (isEnabled(SerializerFeature.WriteNullListAsEmpty)) {
  758. write("[]");
  759. } else {
  760. writeNull();
  761. }
  762. }
  763. public void writeFieldNullNumber(char seperator, String name) {
  764. write(seperator);
  765. writeFieldName(name);
  766. if (isEnabled(SerializerFeature.WriteNullNumberAsZero)) {
  767. write('0');
  768. } else {
  769. writeNull();
  770. }
  771. }
  772. public void writeFieldValue(char seperator, String name, char value) {
  773. write(seperator);
  774. writeFieldName(name);
  775. if (value == 0) {
  776. writeString("\u0000");
  777. } else {
  778. writeString(Character.toString(value));
  779. }
  780. }
  781. public void writeFieldValue(char seperator, String name, boolean value) {
  782. char keySeperator = isEnabled(SerializerFeature.UseSingleQuotes) ? '\'' : '"';
  783. int intSize = value ? 4 : 5;
  784. int nameLen = name.length();
  785. int newcount = count + nameLen + 4 + intSize;
  786. if (newcount > buf.length) {
  787. expandCapacity(newcount);
  788. }
  789. int start = count;
  790. count = newcount;
  791. buf[start] = seperator;
  792. int nameEnd = start + nameLen + 1;
  793. buf[start + 1] = keySeperator;
  794. name.getChars(0, nameLen, buf, start + 2);
  795. buf[nameEnd + 1] = keySeperator;
  796. if (value) {
  797. System.arraycopy(":true".toCharArray(), 0, buf, nameEnd + 2, 5);
  798. } else {
  799. System.arraycopy(":false".toCharArray(), 0, buf, nameEnd + 2, 6);
  800. }
  801. }
  802. public void writeFieldValue1(char seperator, String name, boolean value) {
  803. write(seperator);
  804. writeFieldName(name);
  805. if (value) {
  806. write("true");
  807. } else {
  808. write("false");
  809. }
  810. }
  811. public void writeFieldValue(char seperator, String name, int value) {
  812. if (value == Integer.MIN_VALUE || (!isEnabled(SerializerFeature.QuoteFieldNames))) {
  813. writeFieldValue1(seperator, name, value);
  814. return;
  815. }
  816. char keySeperator = isEnabled(SerializerFeature.UseSingleQuotes) ? '\'' : '"';
  817. int intSize = (value < 0) ? IOUtils.stringSize(-value) + 1 : IOUtils.stringSize(value);
  818. int nameLen = name.length();
  819. int newcount = count + nameLen + 4 + intSize;
  820. if (newcount > buf.length) {
  821. expandCapacity(newcount);
  822. }
  823. int start = count;
  824. count = newcount;
  825. buf[start] = seperator;
  826. int nameEnd = start + nameLen + 1;
  827. buf[start + 1] = keySeperator;
  828. name.getChars(0, nameLen, buf, start + 2);
  829. buf[nameEnd + 1] = keySeperator;
  830. buf[nameEnd + 2] = ':';
  831. IOUtils.getChars(value, count, buf);
  832. }
  833. public void writeFieldValue1(char seperator, String name, int value) {
  834. write(seperator);
  835. writeFieldName(name);
  836. writeInt(value);
  837. }
  838. public void writeFieldValue(char seperator, String name, long value) {
  839. if (value == Long.MIN_VALUE || (!isEnabled(SerializerFeature.QuoteFieldNames))) {
  840. writeFieldValue1(seperator, name, value);
  841. return;
  842. }
  843. char keySeperator = isEnabled(SerializerFeature.UseSingleQuotes) ? '\'' : '"';
  844. int intSize = (value < 0) ? IOUtils.stringSize(-value) + 1 : IOUtils.stringSize(value);
  845. int nameLen = name.length();
  846. int newcount = count + nameLen + 4 + intSize;
  847. if (newcount > buf.length) {
  848. expandCapacity(newcount);
  849. }
  850. int start = count;
  851. count = newcount;
  852. buf[start] = seperator;
  853. int nameEnd = start + nameLen + 1;
  854. buf[start + 1] = keySeperator;
  855. name.getChars(0, nameLen, buf, start + 2);
  856. buf[nameEnd + 1] = keySeperator;
  857. buf[nameEnd + 2] = ':';
  858. IOUtils.getChars(value, count, buf);
  859. }
  860. public void writeFieldValue1(char seperator, String name, long value) {
  861. write(seperator);
  862. writeFieldName(name);
  863. writeLong(value);
  864. }
  865. public void writeFieldValue(char seperator, String name, float value) {
  866. write(seperator);
  867. writeFieldName(name);
  868. if (value == 0) {
  869. write('0');
  870. } else if (Float.isNaN(value)) {
  871. writeNull();
  872. } else if (Float.isInfinite(value)) {
  873. writeNull();
  874. } else {
  875. String text = Float.toString(value);
  876. if (text.endsWith(".0")) {
  877. text = text.substring(0, text.length() - 2);
  878. }
  879. write(text);
  880. }
  881. }
  882. public void writeFieldValue(char seperator, String name, double value) {
  883. write(seperator);
  884. writeFieldName(name);
  885. if (value == 0) {
  886. write('0');
  887. } else if (Double.isNaN(value)) {
  888. writeNull();
  889. } else if (Double.isInfinite(value)) {
  890. writeNull();
  891. } else {
  892. String text = Double.toString(value);
  893. if (text.endsWith(".0")) {
  894. text = text.substring(0, text.length() - 2);
  895. }
  896. write(text);
  897. }
  898. }
  899. public void writeFieldValue(char seperator, String name, String value) {
  900. if (isEnabled(SerializerFeature.QuoteFieldNames)) {
  901. if (isEnabled(SerializerFeature.UseSingleQuotes)) {
  902. write(seperator);
  903. writeFieldName(name);
  904. if (value == null) {
  905. writeNull();
  906. } else {
  907. writeString(value);
  908. }
  909. } else {
  910. if (isEnabled(SerializerFeature.BrowserCompatible)) {
  911. write(seperator);
  912. writeStringWithDoubleQuote(name, ':');
  913. writeStringWithDoubleQuote(value, (char) 0);
  914. } else {
  915. writeFieldValueStringWithDoubleQuote(seperator, name, value, true);
  916. }
  917. }
  918. } else {
  919. write(seperator);
  920. writeFieldName(name);
  921. if (value == null) {
  922. writeNull();
  923. } else {
  924. writeString(value);
  925. }
  926. }
  927. }
  928. private void writeFieldValueStringWithDoubleQuote(char seperator, String name, String value, boolean checkSpecial) {
  929. int nameLen = name.length();
  930. int valueLen;
  931. int newcount = count;
  932. if (value == null) {
  933. valueLen = 4;
  934. newcount += nameLen + 8;
  935. } else {
  936. valueLen = value.length();
  937. newcount += nameLen + valueLen + 6;
  938. }
  939. if (newcount > buf.length) {
  940. expandCapacity(newcount);
  941. }
  942. buf[count] = seperator;
  943. int nameStart = count + 2;
  944. int nameEnd = nameStart + nameLen;
  945. buf[count + 1] = '\"';
  946. name.getChars(0, nameLen, buf, nameStart);
  947. count = newcount;
  948. buf[nameEnd] = '\"';
  949. int index = nameEnd + 1;
  950. buf[index++] = ':';
  951. if (value == null) {
  952. buf[index++] = 'n';
  953. buf[index++] = 'u';
  954. buf[index++] = 'l';
  955. buf[index++] = 'l';
  956. return;
  957. }
  958. buf[index++] = '"';
  959. int valueStart = index;
  960. int valueEnd = valueStart + valueLen;
  961. value.getChars(0, valueLen, buf, valueStart);
  962. if (checkSpecial && !isEnabled(SerializerFeature.DisableCheckSpecialChar)) {
  963. int specialCount = 0;
  964. int lastSpecialIndex = -1;
  965. char lastSpecial = '\0';
  966. for (int i = valueStart; i < valueEnd; ++i) {
  967. char ch = buf[i];
  968. if (ch >= ']') {
  969. continue;
  970. }
  971. if (isSpecial(ch, this.features)) {
  972. specialCount++;
  973. lastSpecialIndex = i;
  974. lastSpecial = ch;
  975. }
  976. }
  977. if (specialCount > 0) {
  978. newcount += specialCount;
  979. if (newcount > buf.length) {
  980. expandCapacity(newcount);
  981. }
  982. count = newcount;
  983. }
  984. if (specialCount == 1) {
  985. System.arraycopy(buf, lastSpecialIndex + 1, buf, lastSpecialIndex + 2, valueEnd - lastSpecialIndex - 1);
  986. buf[lastSpecialIndex] = '\\';
  987. buf[++lastSpecialIndex] = replaceChars[(int) lastSpecial];
  988. } else if (specialCount > 1) {
  989. System.arraycopy(buf, lastSpecialIndex + 1, buf, lastSpecialIndex + 2, valueEnd - lastSpecialIndex - 1);
  990. buf[lastSpecialIndex] = '\\';
  991. buf[++lastSpecialIndex] = replaceChars[(int) lastSpecial];
  992. valueEnd++;
  993. for (int i = lastSpecialIndex - 2; i >= valueStart; --i) {
  994. char ch = buf[i];
  995. if (ch == '\b' || ch == '\n' || ch == '\r' || ch == '\f' || ch == '\\'
  996. || ch == '"' //
  997. || (ch == '\t' && isEnabled(SerializerFeature.WriteTabAsSpecial))
  998. || (ch == '/' && isEnabled(SerializerFeature.WriteSlashAsSpecial))) {
  999. System.arraycopy(buf, i + 1, buf, i + 2, valueEnd - i - 1);
  1000. buf[i] = '\\';
  1001. buf[i + 1] = replaceChars[(int) ch];
  1002. valueEnd++;
  1003. }
  1004. }
  1005. }
  1006. }
  1007. buf[count - 1] = '\"';
  1008. }
  1009. final static boolean isSpecial(char ch, int features) {
  1010. // if (ch > ']') {
  1011. // return false;
  1012. // }
  1013. if (ch == ' ') {
  1014. return false;
  1015. }
  1016. if (ch == '/' && SerializerFeature.isEnabled(features, SerializerFeature.WriteSlashAsSpecial)) {
  1017. return true;
  1018. }
  1019. if (ch > '#' && ch != '\\') {
  1020. return false;
  1021. }
  1022. if (ch == '\b' || ch == '\n' || ch == '\r' || ch == '\f' || ch == '\\' || ch == '"' //
  1023. || (ch == '\t' && SerializerFeature.isEnabled(features, SerializerFeature.WriteTabAsSpecial))){
  1024. return true;
  1025. }
  1026. return false;
  1027. }
  1028. // writeStringWithSingleQuote
  1029. public void writeFieldValue(char seperator, String name, Enum<?> value) {
  1030. if (value == null) {
  1031. write(seperator);
  1032. writeFieldName(name);
  1033. writeNull();
  1034. return;
  1035. }
  1036. if (isEnabled(SerializerFeature.WriteEnumUsingToString)) {
  1037. if (isEnabled(SerializerFeature.UseSingleQuotes)) {
  1038. writeFieldValue(seperator, name, value.name());
  1039. } else {
  1040. writeFieldValueStringWithDoubleQuote(seperator, name, value.name(), false);
  1041. return;
  1042. }
  1043. // writeStringWithDoubleQuote
  1044. } else {
  1045. writeFieldValue(seperator, name, value.ordinal());
  1046. }
  1047. }
  1048. public void writeFieldValue(char seperator, String name, BigDecimal value) {
  1049. write(seperator);
  1050. writeFieldName(name);
  1051. if (value == null) {
  1052. writeNull();
  1053. } else {
  1054. write(value.toString());
  1055. }
  1056. }
  1057. public void writeString(String text, char seperator) {
  1058. if (isEnabled(SerializerFeature.UseSingleQuotes)) {
  1059. writeStringWithSingleQuote(text);
  1060. write(seperator);
  1061. } else {
  1062. writeStringWithDoubleQuote(text, seperator);
  1063. }
  1064. }
  1065. public void writeString(String text) {
  1066. if (isEnabled(SerializerFeature.UseSingleQuotes)) {
  1067. writeStringWithSingleQuote(text);
  1068. } else {
  1069. writeStringWithDoubleQuote(text, (char) 0);
  1070. }
  1071. }
  1072. private void writeStringWithSingleQuote(String text) {
  1073. if (text == null) {
  1074. int newcount = count + 4;
  1075. if (newcount > buf.length) {
  1076. expandCapacity(newcount);
  1077. }
  1078. "null".getChars(0, 4, buf, count);
  1079. count = newcount;
  1080. return;
  1081. }
  1082. int len = text.length();
  1083. int newcount = count + len + 2;
  1084. if (newcount > buf.length) {
  1085. expandCapacity(newcount);
  1086. }
  1087. int start = count + 1;
  1088. int end = start + len;
  1089. buf[count] = '\'';
  1090. text.getChars(0, len, buf, start);
  1091. count = newcount;
  1092. int specialCount = 0;
  1093. int lastSpecialIndex = -1;
  1094. char lastSpecial = '\0';
  1095. for (int i = start; i < end; ++i) {
  1096. char ch = buf[i];
  1097. if (ch == '\b' || ch == '\n' || ch == '\r' || ch == '\f' || ch == '\\'
  1098. || ch == '\'' //
  1099. || (ch == '\t' && isEnabled(SerializerFeature.WriteTabAsSpecial))
  1100. || (ch == '/' && isEnabled(SerializerFeature.WriteSlashAsSpecial))) {
  1101. specialCount++;
  1102. lastSpecialIndex = i;
  1103. lastSpecial = ch;
  1104. }
  1105. }
  1106. newcount += specialCount;
  1107. if (newcount > buf.length) {
  1108. expandCapacity(newcount);
  1109. }
  1110. count = newcount;
  1111. if (specialCount == 1) {
  1112. System.arraycopy(buf, lastSpecialIndex + 1, buf, lastSpecialIndex + 2, end - lastSpecialIndex - 1);
  1113. buf[lastSpecialIndex] = '\\';
  1114. buf[++lastSpecialIndex] = replaceChars[(int) lastSpecial];
  1115. } else if (specialCount > 1) {
  1116. System.arraycopy(buf, lastSpecialIndex + 1, buf, lastSpecialIndex + 2, end - lastSpecialIndex - 1);
  1117. buf[lastSpecialIndex] = '\\';
  1118. buf[++lastSpecialIndex] = replaceChars[(int) lastSpecial];
  1119. end++;
  1120. for (int i = lastSpecialIndex - 2; i >= start; --i) {
  1121. char ch = buf[i];
  1122. if (ch == '\b' || ch == '\n' || ch == '\r' || ch == '\f' || ch == '\\'
  1123. || ch == '\'' //
  1124. || (ch == '\t' && isEnabled(SerializerFeature.WriteTabAsSpecial))
  1125. || (ch == '/' && isEnabled(SerializerFeature.WriteSlashAsSpecial))) {
  1126. System.arraycopy(buf, i + 1, buf, i + 2, end - i - 1);
  1127. buf[i] = '\\';
  1128. buf[i + 1] = replaceChars[(int) ch];
  1129. end++;
  1130. }
  1131. }
  1132. }
  1133. buf[count - 1] = '\'';
  1134. }
  1135. public void writeFieldName(String key) {
  1136. writeFieldName(key, false);
  1137. }
  1138. public void writeFieldName(String key, boolean checkSpecial) {
  1139. if (key == null) {
  1140. write("null:");
  1141. return;
  1142. }
  1143. if (isEnabled(SerializerFeature.UseSingleQuotes)) {
  1144. if (isEnabled(SerializerFeature.QuoteFieldNames)) {
  1145. writeKeyWithSingleQuote(key);
  1146. } else {
  1147. writeKeyWithSingleQuoteIfHasSpecial(key);
  1148. }
  1149. } else {
  1150. if (isEnabled(SerializerFeature.QuoteFieldNames)) {
  1151. writeKeyWithDoubleQuote(key, checkSpecial);
  1152. } else {
  1153. writeKeyWithDoubleQuoteIfHasSpecial(key);
  1154. }
  1155. }
  1156. }
  1157. private void writeKeyWithSingleQuote(String text) {
  1158. final boolean[] specicalFlags_singleQuotes = CharTypes.specicalFlags_singleQuotes;
  1159. int len = text.length();
  1160. int newcount = count + len + 3;
  1161. if (newcount > buf.length) {
  1162. expandCapacity(newcount);
  1163. }
  1164. int start = count + 1;
  1165. int end = start + len;
  1166. buf[count] = '\'';
  1167. text.getChars(0, len, buf, start);
  1168. count = newcount;
  1169. for (int i = start; i < end; ++i) {
  1170. char ch = buf[i];
  1171. if (ch < specicalFlags_singleQuotes.length
  1172. && specicalFlags_singleQuotes[ch] //
  1173. || (ch == '\t' && isEnabled(SerializerFeature.WriteTabAsSpecial))
  1174. || (ch == '/' && isEnabled(SerializerFeature.WriteSlashAsSpecial))) {
  1175. newcount++;
  1176. if (newcount > buf.length) {
  1177. expandCapacity(newcount);
  1178. }
  1179. count = newcount;
  1180. System.arraycopy(buf, i + 1, buf, i + 2, end - i - 1);
  1181. buf[i] = '\\';
  1182. buf[++i] = replaceChars[(int) ch];
  1183. end++;
  1184. }
  1185. }
  1186. buf[count - 2] = '\'';
  1187. buf[count - 1] = ':';
  1188. }
  1189. private void writeKeyWithDoubleQuoteIfHasSpecial(String text) {
  1190. final boolean[] specicalFlags_doubleQuotes = CharTypes.specicalFlags_doubleQuotes;
  1191. int len = text.length();
  1192. int newcount = count + len + 1;
  1193. if (newcount > buf.length) {
  1194. expandCapacity(newcount);
  1195. }
  1196. int start = count;
  1197. int end = start + len;
  1198. text.getChars(0, len, buf, start);
  1199. count = newcount;
  1200. boolean hasSpecial = false;
  1201. for (int i = start; i < end; ++i) {
  1202. char ch = buf[i];
  1203. if (ch < specicalFlags_doubleQuotes.length && specicalFlags_doubleQuotes[ch]) {
  1204. if (!hasSpecial) {
  1205. newcount += 3;
  1206. if (newcount > buf.length) {
  1207. expandCapacity(newcount);
  1208. }
  1209. count = newcount;
  1210. System.arraycopy(buf, i + 1, buf, i + 3, end - i - 1);
  1211. System.arraycopy(buf, 0, buf, 1, i);
  1212. buf[start] = '"';
  1213. buf[++i] = '\\';
  1214. buf[++i] = replaceChars[(int) ch];
  1215. end += 2;
  1216. buf[count - 2] = '"';
  1217. hasSpecial = true;
  1218. } else {
  1219. newcount++;
  1220. if (newcount > buf.length) {
  1221. expandCapacity(newcount);
  1222. }
  1223. count = newcount;
  1224. System.arraycopy(buf, i + 1, buf, i + 2, end - i);
  1225. buf[i] = '\\';
  1226. buf[++i] = replaceChars[(int) ch];
  1227. end++;
  1228. }
  1229. }
  1230. }
  1231. buf[count - 1] = ':';
  1232. }
  1233. private void writeKeyWithSingleQuoteIfHasSpecial(String text) {
  1234. final boolean[] specicalFlags_singleQuotes = CharTypes.specicalFlags_singleQuotes;
  1235. int len = text.length();
  1236. int newcount = count + len + 1;
  1237. if (newcount > buf.length) {
  1238. expandCapacity(newcount);
  1239. }
  1240. int start = count;
  1241. int end = start + len;
  1242. text.getChars(0, len, buf, start);
  1243. count = newcount;
  1244. boolean hasSpecial = false;
  1245. for (int i = start; i < end; ++i) {
  1246. char ch = buf[i];
  1247. if (ch < specicalFlags_singleQuotes.length && specicalFlags_singleQuotes[ch]) {
  1248. if (!hasSpecial) {
  1249. newcount += 3;
  1250. if (newcount > buf.length) {
  1251. expandCapacity(newcount);
  1252. }
  1253. count = newcount;
  1254. System.arraycopy(buf, i + 1, buf, i + 3, end - i - 1);
  1255. System.arraycopy(buf, 0, buf, 1, i);
  1256. buf[start] = '\'';
  1257. buf[++i] = '\\';
  1258. buf[++i] = replaceChars[(int) ch];
  1259. end += 2;
  1260. buf[count - 2] = '\'';
  1261. hasSpecial = true;
  1262. } else {
  1263. newcount++;
  1264. if (newcount > buf.length) {
  1265. expandCapacity(newcount);
  1266. }
  1267. count = newcount;
  1268. System.arraycopy(buf, i + 1, buf, i + 2, end - i);
  1269. buf[i] = '\\';
  1270. buf[++i] = replaceChars[(int) ch];
  1271. end++;
  1272. }
  1273. }
  1274. }
  1275. buf[newcount - 1] = ':';
  1276. }
  1277. }