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

io.dylemma.spac.json.WrappedJacksonParser.scala Maven / Gradle / Ivy

The newest version!
package io.dylemma.spac
package json

import java.io.IOException
import com.fasterxml.jackson.core.{JsonLocation, JsonToken, JsonParser => JacksonParser}

import scala.annotation.tailrec

private[json] class WrappedJacksonParser(parser: JacksonParser) extends Iterator[JsonEvent] with AutoCloseable {
	def close() = parser.close()

	private var pendingNext: Option[JsonEvent] = None

	def hasNext = {
		if (pendingNext.isEmpty) pendingNext = maybeNext()
		pendingNext.isDefined
	}
	def next() = pendingNext match {
		case None =>
			maybeNext() getOrElse {
				throw new NoSuchElementException("called next() when hasNext was false")
			}
		case Some(e) =>
			pendingNext = None
			e
	}

	def maybeNext(): Option[JsonEvent] = {
		try _maybeNext()
		catch { case e: IOException =>
			latestLocation match {
				case None => throw e
				case Some(loc) => throw SpacException.addTrace(e, SpacTraceElement.NearLocation(loc))
			}
		}
	}

	@tailrec private def _maybeNext(): Option[JsonEvent] = {
		val token = parser.nextToken()
		if (token == null) {
			None
		} else {
			val loc = currentLocation
			token match {
				case JsonToken.START_OBJECT => Some(JsonEvent.ObjectStart(loc))
				case JsonToken.FIELD_NAME => Some(JsonEvent.FieldStart(parser.getCurrentName, loc))
				case JsonToken.END_OBJECT => Some(JsonEvent.ObjectEnd(loc))
				case JsonToken.START_ARRAY => Some(JsonEvent.ArrayStart(loc))
				case JsonToken.END_ARRAY => Some(JsonEvent.ArrayEnd(loc))
				case JsonToken.VALUE_FALSE => Some(JsonEvent.JBool(false, loc))
				case JsonToken.VALUE_TRUE => Some(JsonEvent.JBool(true, loc))
				case JsonToken.VALUE_NUMBER_INT => Some(JsonEvent.JLong(parser.getLongValue, loc))
				case JsonToken.VALUE_NUMBER_FLOAT => Some(JsonEvent.JDouble(parser.getDoubleValue, loc))
				case JsonToken.VALUE_STRING => Some(JsonEvent.JString(parser.getText, loc))
				case JsonToken.VALUE_NULL => Some(JsonEvent.JNull(loc))
				case _ => _maybeNext()
			}
		}
	}

	private var latestLocation: Option[ContextLocation] = None

	private def currentLocation: ContextLocation = {
		val loc = parser.getCurrentLocation
		val result = new WrappedJsonLocation(loc)
		latestLocation = Some(result)
		result
	}

	private class WrappedJsonLocation(loc: JsonLocation) extends ContextLocation {
		import ContextLocation.Tag._
		def get[A](tag: ContextLocation.Tag[A]) = tag match {
			case LineNumber => Some(loc.getLineNr.longValue)
			case ColumnOffset => Some(loc.getColumnNr.longValue)
			case CharOffset => Some(loc.getCharOffset)
			case _ => None
		}
	}


}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy