All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.rapidoid.writable.WritableUtils Maven / Gradle / Ivy

There is a newer version: 5.5.5
Show newest version
/*-
 * #%L
 * rapidoid-commons
 * %%
 * Copyright (C) 2014 - 2018 Nikolche Mihajlovski and contributors
 * %%
 * 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.
 * #L%
 */

package org.rapidoid.writable;


import org.rapidoid.RapidoidThing;
import org.rapidoid.annotation.Authors;
import org.rapidoid.annotation.Since;

import static org.rapidoid.util.Constants.*;

@Authors("Nikolche Mihajlovski")
@Since("5.3.4")
public class WritableUtils extends RapidoidThing {

	private static final String MIN_VALUE = Long.MIN_VALUE + "";

	public static void putNumAsText(Writable out, long n) {
		if (n >= 0) {
			writeDigits(out, n);
		} else {
			if (n == Long.MIN_VALUE) {
				writeAscii(out, MIN_VALUE);
			} else {
				out.writeByte((byte) '-');
				putNumAsText(out, -n);
			}
		}
	}

	private static void writeDigits(Writable out, long n) {
		int digit = (int) (n % 10);

		if (n >= 10) {
			writeDigits(out, n / 10);
		}

		out.writeByte((byte) (digit + '0'));
	}

	public static void writeAscii(Writable out, String s) {
		for (int i = 0; i < s.length(); i++) {
			out.writeByte((byte) s.charAt(i));
		}
	}

	public static void writeAscii(Writable out, byte[] bytes) {
		out.writeBytes(bytes);
	}

	public static void writeUTF8(Writable out, String src) {
		int limit = src.length();

		for (int i = 0; i < limit; i++) {
			char c = src.charAt(i);

			if (c < 128) {
				out.writeByte((byte) c);

			} else {
				// https://en.wikipedia.org/wiki/UTF-8

				if (c < 0x800) {
					// [110xxxxx, 10xxxxxx]
					out.writeByte((byte) (UTF8_2_BYTES_LEAD | c >> 6));     // highest 5 bits
					out.writeByte((byte) (UTF8_CONTINUATION | c & LAST_6)); // lowest 6 bits

				} else if (Character.isSurrogate(c)) {

					if (Character.isHighSurrogate(c)) {
						int next = i + 1;

						if (next < limit) {
							char nextChar = src.charAt(next);

							if (Character.isLowSurrogate(nextChar)) {
								int cp = Character.toCodePoint(c, nextChar);

								// [11110xxx, 10xxxxxx, 10xxxxxx, 10xxxxxx]
								out.writeByte((byte) (UTF8_4_BYTES_LEAD | cp >> 18));          // highest 3 bits
								out.writeByte((byte) (UTF8_CONTINUATION | cp >> 12 & LAST_6)); // next 6 bits
								out.writeByte((byte) (UTF8_CONTINUATION | cp >> 6 & LAST_6));  // next 6 bits
								out.writeByte((byte) (UTF8_CONTINUATION | cp & LAST_6));       // lowest 6 bits

								i++; // the next char was successfully consumed

							} else {
								out.writeByte(MALFORMED_CHAR); // expected low surrogate
							}

						} else {
							out.writeByte(MALFORMED_CHAR); // expected one more character
						}

					} else {
						out.writeByte(MALFORMED_CHAR); // expected high surrogate
					}

				} else {
					// [1110xxxx, 10xxxxxx, 10xxxxxx]
					out.writeByte((byte) (UTF8_3_BYTES_LEAD | c >> 12));         // highest 4 bits
					out.writeByte((byte) (UTF8_CONTINUATION | c >> 6 & LAST_6)); // next 6 bits
					out.writeByte((byte) (UTF8_CONTINUATION | c & LAST_6));      // lowest 6 bits
				}
			}
		}
	}

	public static void writeUTF8HtmlEscaped(Writable out, String src) {
		int limit = src.length();

		for (int i = 0; i < limit; i++) {
			char c = src.charAt(i);

			if (c < 128) {

				switch (c) {
					case '<': // <
						out.writeByte((byte) '&');
						out.writeByte((byte) 'l');
						out.writeByte((byte) 't');
						out.writeByte((byte) ';');
						break;

					case '>': // >
						out.writeByte((byte) '&');
						out.writeByte((byte) 'g');
						out.writeByte((byte) 't');
						out.writeByte((byte) ';');
						break;

					case '&': // &
						out.writeByte((byte) '&');
						out.writeByte((byte) 'a');
						out.writeByte((byte) 'm');
						out.writeByte((byte) 'p');
						out.writeByte((byte) ';');
						break;

					case '"': // "
						out.writeByte((byte) '&');
						out.writeByte((byte) 'q');
						out.writeByte((byte) 'u');
						out.writeByte((byte) 'o');
						out.writeByte((byte) 't');
						out.writeByte((byte) ';');
						break;

					case '\'': // '
						out.writeByte((byte) '&');
						out.writeByte((byte) 'a');
						out.writeByte((byte) 'p');
						out.writeByte((byte) 'o');
						out.writeByte((byte) 's');
						out.writeByte((byte) ';');
						break;

					default:
						out.writeByte((byte) c);
						break;
				}

			} else {
				// https://en.wikipedia.org/wiki/UTF-8

				if (c < 0x800) {
					// [110xxxxx, 10xxxxxx]
					out.writeByte((byte) (UTF8_2_BYTES_LEAD | c >> 6));     // highest 5 bits
					out.writeByte((byte) (UTF8_CONTINUATION | c & LAST_6)); // lowest 6 bits

				} else if (Character.isSurrogate(c)) {

					if (Character.isHighSurrogate(c)) {
						int next = i + 1;

						if (next < limit) {
							char nextChar = src.charAt(next);

							if (Character.isLowSurrogate(nextChar)) {
								int cp = Character.toCodePoint(c, nextChar);

								// [11110xxx, 10xxxxxx, 10xxxxxx, 10xxxxxx]
								out.writeByte((byte) (UTF8_4_BYTES_LEAD | cp >> 18));          // highest 3 bits
								out.writeByte((byte) (UTF8_CONTINUATION | cp >> 12 & LAST_6)); // next 6 bits
								out.writeByte((byte) (UTF8_CONTINUATION | cp >> 6 & LAST_6));  // next 6 bits
								out.writeByte((byte) (UTF8_CONTINUATION | cp & LAST_6));       // lowest 6 bits

								i++; // the next char was successfully consumed

							} else {
								out.writeByte(MALFORMED_CHAR); // expected low surrogate
							}

						} else {
							out.writeByte(MALFORMED_CHAR); // expected one more character
						}

					} else {
						out.writeByte(MALFORMED_CHAR); // expected high surrogate
					}

				} else {
					// [1110xxxx, 10xxxxxx, 10xxxxxx]
					out.writeByte((byte) (UTF8_3_BYTES_LEAD | c >> 12));         // highest 4 bits
					out.writeByte((byte) (UTF8_CONTINUATION | c >> 6 & LAST_6)); // next 6 bits
					out.writeByte((byte) (UTF8_CONTINUATION | c & LAST_6));      // lowest 6 bits
				}
			}
		}
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy