Skip to content

Commit 4d12040

Browse files
committedMar 24, 2018
Initial parser implementation
1 parent d9406da commit 4d12040

File tree

19 files changed

+1065
-19
lines changed

19 files changed

+1065
-19
lines changed
 

‎.gitignore

+8-19
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,11 @@
1-
# Compiled class file
2-
*.class
3-
4-
# Log file
5-
*.log
6-
7-
# BlueJ files
8-
*.ctxt
1+
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
2+
hs_err_pid*
93

10-
# Mobile Tools for Java (J2ME)
11-
.mtj.tmp/
4+
# Idea files
5+
.idea/
126

13-
# Package Files #
14-
*.jar
15-
*.war
16-
*.ear
17-
*.zip
18-
*.tar.gz
19-
*.rar
7+
# Gradle files
8+
.gradle/
209

21-
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
22-
hs_err_pid*
10+
# Kotlin build files
11+
build/

‎.travis.yml

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
language: java
2+
jdk:
3+
- oraclejdk8
4+
- oraclejdk9
5+
- openjdk7
6+
- openjdk8

‎build.gradle

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
group 'io.sniffy.influxdb'
2+
version '1.0-SNAPSHOT'
3+
4+
apply plugin: 'java'
5+
6+
sourceCompatibility = 1.7
7+
8+
repositories {
9+
mavenCentral()
10+
}

‎gradle/wrapper/gradle-wrapper.jar

53.5 KB
Binary file not shown.
+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#Sat Mar 24 13:06:14 MSK 2018
2+
distributionBase=GRADLE_USER_HOME
3+
distributionPath=wrapper/dists
4+
zipStoreBase=GRADLE_USER_HOME
5+
zipStorePath=wrapper/dists
6+
distributionUrl=https\://services.gradle.org/distributions/gradle-3.5-rc-2-all.zip

‎gradlew

+172
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
#!/usr/bin/env sh
2+
3+
##############################################################################
4+
##
5+
## Gradle start up script for UN*X
6+
##
7+
##############################################################################
8+
9+
# Attempt to set APP_HOME
10+
# Resolve links: $0 may be a link
11+
PRG="$0"
12+
# Need this for relative symlinks.
13+
while [ -h "$PRG" ] ; do
14+
ls=`ls -ld "$PRG"`
15+
link=`expr "$ls" : '.*-> \(.*\)$'`
16+
if expr "$link" : '/.*' > /dev/null; then
17+
PRG="$link"
18+
else
19+
PRG=`dirname "$PRG"`"/$link"
20+
fi
21+
done
22+
SAVED="`pwd`"
23+
cd "`dirname \"$PRG\"`/" >/dev/null
24+
APP_HOME="`pwd -P`"
25+
cd "$SAVED" >/dev/null
26+
27+
APP_NAME="Gradle"
28+
APP_BASE_NAME=`basename "$0"`
29+
30+
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31+
DEFAULT_JVM_OPTS=""
32+
33+
# Use the maximum available, or set MAX_FD != -1 to use that value.
34+
MAX_FD="maximum"
35+
36+
warn ( ) {
37+
echo "$*"
38+
}
39+
40+
die ( ) {
41+
echo
42+
echo "$*"
43+
echo
44+
exit 1
45+
}
46+
47+
# OS specific support (must be 'true' or 'false').
48+
cygwin=false
49+
msys=false
50+
darwin=false
51+
nonstop=false
52+
case "`uname`" in
53+
CYGWIN* )
54+
cygwin=true
55+
;;
56+
Darwin* )
57+
darwin=true
58+
;;
59+
MINGW* )
60+
msys=true
61+
;;
62+
NONSTOP* )
63+
nonstop=true
64+
;;
65+
esac
66+
67+
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68+
69+
# Determine the Java command to use to start the JVM.
70+
if [ -n "$JAVA_HOME" ] ; then
71+
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72+
# IBM's JDK on AIX uses strange locations for the executables
73+
JAVACMD="$JAVA_HOME/jre/sh/java"
74+
else
75+
JAVACMD="$JAVA_HOME/bin/java"
76+
fi
77+
if [ ! -x "$JAVACMD" ] ; then
78+
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79+
80+
Please set the JAVA_HOME variable in your environment to match the
81+
location of your Java installation."
82+
fi
83+
else
84+
JAVACMD="java"
85+
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86+
87+
Please set the JAVA_HOME variable in your environment to match the
88+
location of your Java installation."
89+
fi
90+
91+
# Increase the maximum file descriptors if we can.
92+
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93+
MAX_FD_LIMIT=`ulimit -H -n`
94+
if [ $? -eq 0 ] ; then
95+
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96+
MAX_FD="$MAX_FD_LIMIT"
97+
fi
98+
ulimit -n $MAX_FD
99+
if [ $? -ne 0 ] ; then
100+
warn "Could not set maximum file descriptor limit: $MAX_FD"
101+
fi
102+
else
103+
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104+
fi
105+
fi
106+
107+
# For Darwin, add options to specify how the application appears in the dock
108+
if $darwin; then
109+
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110+
fi
111+
112+
# For Cygwin, switch paths to Windows format before running java
113+
if $cygwin ; then
114+
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115+
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116+
JAVACMD=`cygpath --unix "$JAVACMD"`
117+
118+
# We build the pattern for arguments to be converted via cygpath
119+
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120+
SEP=""
121+
for dir in $ROOTDIRSRAW ; do
122+
ROOTDIRS="$ROOTDIRS$SEP$dir"
123+
SEP="|"
124+
done
125+
OURCYGPATTERN="(^($ROOTDIRS))"
126+
# Add a user-defined pattern to the cygpath arguments
127+
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128+
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129+
fi
130+
# Now convert the arguments - kludge to limit ourselves to /bin/sh
131+
i=0
132+
for arg in "$@" ; do
133+
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134+
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135+
136+
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137+
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138+
else
139+
eval `echo args$i`="\"$arg\""
140+
fi
141+
i=$((i+1))
142+
done
143+
case $i in
144+
(0) set -- ;;
145+
(1) set -- "$args0" ;;
146+
(2) set -- "$args0" "$args1" ;;
147+
(3) set -- "$args0" "$args1" "$args2" ;;
148+
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149+
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150+
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151+
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152+
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153+
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154+
esac
155+
fi
156+
157+
# Escape application args
158+
save ( ) {
159+
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160+
echo " "
161+
}
162+
APP_ARGS=$(save "$@")
163+
164+
# Collect all arguments for the java command, following the shell quoting and substitution rules
165+
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166+
167+
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168+
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169+
cd "$(dirname "$0")"
170+
fi
171+
172+
exec "$JAVACMD" "$@"

‎gradlew.bat

+84
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
@if "%DEBUG%" == "" @echo off
2+
@rem ##########################################################################
3+
@rem
4+
@rem Gradle startup script for Windows
5+
@rem
6+
@rem ##########################################################################
7+
8+
@rem Set local scope for the variables with windows NT shell
9+
if "%OS%"=="Windows_NT" setlocal
10+
11+
set DIRNAME=%~dp0
12+
if "%DIRNAME%" == "" set DIRNAME=.
13+
set APP_BASE_NAME=%~n0
14+
set APP_HOME=%DIRNAME%
15+
16+
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17+
set DEFAULT_JVM_OPTS=
18+
19+
@rem Find java.exe
20+
if defined JAVA_HOME goto findJavaFromJavaHome
21+
22+
set JAVA_EXE=java.exe
23+
%JAVA_EXE% -version >NUL 2>&1
24+
if "%ERRORLEVEL%" == "0" goto init
25+
26+
echo.
27+
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28+
echo.
29+
echo Please set the JAVA_HOME variable in your environment to match the
30+
echo location of your Java installation.
31+
32+
goto fail
33+
34+
:findJavaFromJavaHome
35+
set JAVA_HOME=%JAVA_HOME:"=%
36+
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37+
38+
if exist "%JAVA_EXE%" goto init
39+
40+
echo.
41+
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42+
echo.
43+
echo Please set the JAVA_HOME variable in your environment to match the
44+
echo location of your Java installation.
45+
46+
goto fail
47+
48+
:init
49+
@rem Get command-line arguments, handling Windows variants
50+
51+
if not "%OS%" == "Windows_NT" goto win9xME_args
52+
53+
:win9xME_args
54+
@rem Slurp the command line arguments.
55+
set CMD_LINE_ARGS=
56+
set _SKIP=2
57+
58+
:win9xME_args_slurp
59+
if "x%~1" == "x" goto execute
60+
61+
set CMD_LINE_ARGS=%*
62+
63+
:execute
64+
@rem Setup the command line
65+
66+
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67+
68+
@rem Execute Gradle
69+
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70+
71+
:end
72+
@rem End local scope for the variables with windows NT shell
73+
if "%ERRORLEVEL%"=="0" goto mainEnd
74+
75+
:fail
76+
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77+
rem the _cmd.exe /c_ return code!
78+
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79+
exit /b 1
80+
81+
:mainEnd
82+
if "%OS%"=="Windows_NT" endlocal
83+
84+
:omega

‎lineprotocol/build.gradle

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
group 'io.sniffy.influxdb'
2+
version '1.0-SNAPSHOT'
3+
4+
apply plugin: 'java'
5+
6+
sourceCompatibility = 1.7
7+
8+
repositories {
9+
mavenCentral()
10+
}
11+
12+
dependencies {
13+
testCompile group: 'junit', name: 'junit', version: '4.12'
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package io.sniffy.influxdb.lineprotocol;
2+
3+
import java.util.Objects;
4+
5+
public class FieldBooleanValue extends FieldValue {
6+
7+
private final boolean value;
8+
9+
public FieldBooleanValue(boolean value) {
10+
this.value = value;
11+
}
12+
13+
@Override
14+
public String toString() {
15+
return Boolean.toString(value);
16+
}
17+
18+
@Override
19+
public boolean equals(Object o) {
20+
if (this == o) return true;
21+
if (o == null || getClass() != o.getClass()) return false;
22+
FieldBooleanValue that = (FieldBooleanValue) o;
23+
return value == that.value;
24+
}
25+
26+
@Override
27+
public int hashCode() {
28+
return Objects.hash(value);
29+
}
30+
31+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package io.sniffy.influxdb.lineprotocol;
2+
3+
import java.util.Objects;
4+
5+
public class FieldFloatValue extends FieldValue {
6+
7+
private final double value;
8+
9+
public FieldFloatValue(double value) {
10+
this.value = value;
11+
}
12+
13+
@Override
14+
public String toString() {
15+
return Double.toString(value);
16+
}
17+
18+
@Override
19+
public boolean equals(Object o) {
20+
if (this == o) return true;
21+
if (o == null || getClass() != o.getClass()) return false;
22+
FieldFloatValue that = (FieldFloatValue) o;
23+
return Double.compare(that.value, value) == 0;
24+
}
25+
26+
@Override
27+
public int hashCode() {
28+
return Objects.hash(value);
29+
}
30+
31+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package io.sniffy.influxdb.lineprotocol;
2+
3+
import java.util.Objects;
4+
5+
public class FieldIntegerValue extends FieldValue {
6+
7+
private final long value;
8+
9+
public FieldIntegerValue(long value) {
10+
this.value = value;
11+
}
12+
13+
@Override
14+
public String toString() {
15+
return Long.toString(value);
16+
}
17+
18+
@Override
19+
public boolean equals(Object o) {
20+
if (this == o) return true;
21+
if (o == null || getClass() != o.getClass()) return false;
22+
FieldIntegerValue that = (FieldIntegerValue) o;
23+
return value == that.value;
24+
}
25+
26+
@Override
27+
public int hashCode() {
28+
return Objects.hash(value);
29+
}
30+
31+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package io.sniffy.influxdb.lineprotocol;
2+
3+
import java.util.Objects;
4+
5+
public class FieldStringValue extends FieldValue {
6+
7+
private final String value;
8+
9+
public FieldStringValue(String value) {
10+
this.value = value;
11+
}
12+
13+
@Override
14+
public String toString() {
15+
return value;
16+
}
17+
18+
@Override
19+
public boolean equals(Object o) {
20+
if (this == o) return true;
21+
if (o == null || getClass() != o.getClass()) return false;
22+
FieldStringValue that = (FieldStringValue) o;
23+
return Objects.equals(value, that.value);
24+
}
25+
26+
@Override
27+
public int hashCode() {
28+
return Objects.hash(value);
29+
}
30+
31+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package io.sniffy.influxdb.lineprotocol;
2+
3+
public enum FieldType {
4+
STRING, FLOAT, INTEGER, BOOLEAN
5+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package io.sniffy.influxdb.lineprotocol;
2+
3+
public abstract class FieldValue {
4+
5+
@Override
6+
public abstract int hashCode();
7+
8+
@Override
9+
public abstract boolean equals(Object obj);
10+
11+
@Override
12+
public abstract String toString();
13+
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
package io.sniffy.influxdb.lineprotocol;
2+
3+
import java.math.BigDecimal;
4+
import java.util.Collections;
5+
import java.util.HashMap;
6+
import java.util.Map;
7+
8+
public class Point {
9+
10+
private final String measurement;
11+
private final Map<String, String> tags;
12+
private final Map<String, FieldValue> values;
13+
private final Long timestamp;
14+
15+
public Point(String measurement, Map<String, String> tags, Map<String, FieldValue> values, Long timestamp) {
16+
this.measurement = measurement;
17+
this.tags = Collections.unmodifiableMap(tags);
18+
this.values = Collections.unmodifiableMap(values);
19+
this.timestamp = timestamp;
20+
}
21+
22+
public String getMeasurement() {
23+
return measurement;
24+
}
25+
26+
public Map<String, String> getTags() {
27+
return tags;
28+
}
29+
30+
public Map<String, FieldValue> getValues() {
31+
return values;
32+
}
33+
34+
public Long getTimestamp() {
35+
return timestamp;
36+
}
37+
38+
public static class Builder {
39+
40+
private final boolean validate;
41+
42+
private String measurement;
43+
private final Map<String, String> tags = new HashMap<>();
44+
private final Map<String, FieldValue> values = new HashMap<>();
45+
private Long timestamp;
46+
47+
public Builder() {
48+
this(false);
49+
}
50+
51+
public Builder(boolean validate) {
52+
this.validate = validate;
53+
}
54+
55+
public String getMeasurement() {
56+
return measurement;
57+
}
58+
59+
public void setMeasurement(String measurement) {
60+
this.measurement = measurement;
61+
}
62+
63+
public Map<String, String> getTags() {
64+
return tags;
65+
}
66+
67+
public void setTags(Map<String, String> tags) {
68+
this.tags.clear();
69+
addTags(tags);
70+
}
71+
72+
public void addTag(String key, String value) {
73+
tags.put(key, value);
74+
}
75+
76+
public void addTags(Map<String, String> tags) {
77+
tags.putAll(tags);
78+
}
79+
80+
public Map<String, FieldValue> getValues() {
81+
return values;
82+
}
83+
84+
public void setValues(Map<String, FieldValue> values) {
85+
this.values.clear();
86+
addValues(values);
87+
}
88+
89+
public void addValue(String key, FieldValue value) {
90+
this.values.put(key, value);
91+
}
92+
93+
public void addValue(String key, String value) {
94+
this.values.put(key, new FieldStringValue(value));
95+
}
96+
97+
public void addValue(String key, float value) {
98+
addValue(key, (double) value);
99+
}
100+
101+
public void addValue(String key, BigDecimal value) {
102+
addValue(key, value.doubleValue());
103+
}
104+
105+
public void addValue(String key, double value) {
106+
this.values.put(key, new FieldFloatValue(value));
107+
}
108+
109+
public void addValue(String key, int value) {
110+
addValue(key, (long) value);
111+
}
112+
113+
public void addValue(String key, short value) {
114+
addValue(key, (long) value);
115+
}
116+
117+
public void addValue(String key, byte value) {
118+
addValue(key, (long) value);
119+
}
120+
121+
public void addValue(String key, long value) {
122+
this.values.put(key, new FieldIntegerValue(value));
123+
}
124+
125+
public void addValue(String key, boolean value) {
126+
this.values.put(key, new FieldBooleanValue(value));
127+
}
128+
129+
public void addValues(Map<String, FieldValue> values) {
130+
this.values.putAll(values);
131+
}
132+
133+
public Long getTimestamp() {
134+
return timestamp;
135+
}
136+
137+
public void setTimestamp(Long timestamp) {
138+
this.timestamp = timestamp;
139+
}
140+
141+
public Point build() {
142+
return values.isEmpty() ? null : new Point(
143+
measurement,
144+
tags,
145+
values,
146+
timestamp
147+
);
148+
}
149+
150+
}
151+
152+
}

‎parser/build.gradle

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
group 'io.sniffy.influxdb'
2+
version '1.0-SNAPSHOT'
3+
4+
buildscript {
5+
ext.kotlin_version = '1.2.30'
6+
ext.junitVersion = "5.0.0"
7+
ext.junitPlatformVersion = "1.0.0"
8+
9+
repositories {
10+
mavenCentral()
11+
}
12+
dependencies {
13+
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
14+
classpath "org.junit.platform:junit-platform-gradle-plugin:$junitPlatformVersion"
15+
}
16+
}
17+
18+
apply plugin: 'kotlin'
19+
apply plugin: 'org.junit.platform.gradle.plugin'
20+
21+
repositories {
22+
mavenCentral()
23+
}
24+
25+
dependencies {
26+
compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlin_version"
27+
compile project(':lineprotocol')
28+
29+
testCompile "org.junit.jupiter:junit-jupiter-api:$junitVersion"
30+
testCompile "org.junit.jupiter:junit-jupiter-params:$junitVersion"
31+
32+
runtime "org.junit.jupiter:junit-jupiter-engine:$junitVersion"
33+
runtime "org.junit.platform:junit-platform-console:$junitPlatformVersion"
34+
}
35+
36+
compileKotlin {
37+
kotlinOptions.jvmTarget = "1.8"
38+
}
39+
compileTestKotlin {
40+
kotlinOptions.jvmTarget = "1.8"
41+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,386 @@
1+
package io.sniffy.influxdb.parser
2+
3+
import io.sniffy.influxdb.lineprotocol.Point
4+
import io.sniffy.influxdb.parser.LineProtocolParser.State.*
5+
import java.io.InputStream
6+
import java.io.InputStreamReader
7+
import java.io.Reader
8+
import java.io.StringReader
9+
import java.lang.Long.parseLong
10+
11+
class LineProtocolParser(private val reader: Reader, private val failFast: Boolean = false) : Iterator<Point> {
12+
13+
private val sb = StringBuilder()
14+
private val sb2 = StringBuilder()
15+
16+
@Volatile private var nextPoint: Point? = null
17+
18+
constructor(string: String, failFast: Boolean = false) :
19+
this(StringReader(string), failFast)
20+
21+
constructor(inputStream: InputStream, failFast: Boolean = false) :
22+
this(InputStreamReader(inputStream, Charsets.UTF_8), failFast)
23+
24+
override fun hasNext(): Boolean {
25+
nextPoint = parseNext()
26+
return nextPoint != null
27+
}
28+
29+
override fun next(): Point {
30+
return nextPoint ?: throw NoSuchElementException()
31+
}
32+
33+
private enum class State {
34+
Beginning,
35+
36+
Comment,
37+
38+
Measurement,
39+
40+
TagKey,
41+
TagValue,
42+
43+
FieldKey,
44+
FieldValue,
45+
StringFieldValue,
46+
NonStringFieldValue,
47+
48+
Timestamp,
49+
50+
End {
51+
override fun finite() = true
52+
},
53+
Eos {
54+
override fun finite() = true
55+
},
56+
Error {
57+
override fun finite() = true
58+
};
59+
60+
open fun finite() = false
61+
62+
}
63+
64+
internal @Synchronized
65+
fun parseNext(): Point? {
66+
67+
val builder = Point.Builder()
68+
69+
var state = State.Beginning
70+
71+
sb.setLength(0)
72+
sb2.setLength(0)
73+
74+
// TODO: what about \r ??
75+
76+
while (!state.finite()) {
77+
when (state) {
78+
Beginning -> {
79+
val i1 = reader.read()
80+
if (i1 < 0) state = Eos
81+
else {
82+
val c1 = i1.toChar()
83+
when (c1) {
84+
'#' -> state = Comment
85+
else -> {
86+
sb.append(c1)
87+
state = Measurement
88+
}
89+
}
90+
}
91+
}
92+
Comment -> {
93+
val i1 = reader.read()
94+
if (i1 < 0) state = Eos
95+
else {
96+
val c1 = i1.toChar()
97+
when (c1) {
98+
'\n' -> state = Beginning
99+
}
100+
}
101+
102+
}
103+
Measurement -> {
104+
val i1 = reader.read()
105+
if (i1 < 0) state = Error
106+
else {
107+
val c1 = i1.toChar()
108+
when (c1) {
109+
'\\' -> {
110+
val i2 = reader.read()
111+
if (i2 < 0) state = Error
112+
else {
113+
val c2 = i2.toChar()
114+
when (c2) {
115+
'\n' -> state = Error
116+
',' -> sb.append(',')
117+
' ' -> sb.append(' ')
118+
else -> sb.append('\\').append(c2)
119+
}
120+
}
121+
}
122+
'\n' -> state = Error
123+
',', ' ' -> {
124+
val measurement = sb.toString()
125+
if (measurement.isEmpty()) {
126+
state = Error // TODO: read till end of line
127+
} else {
128+
builder.measurement = measurement
129+
state = if (',' == c1) TagKey else FieldKey
130+
}
131+
sb.setLength(0)
132+
}
133+
else -> sb.append(c1)
134+
}
135+
}
136+
}
137+
TagKey -> {
138+
val i1 = reader.read()
139+
if (i1 < 0) state = Error
140+
else {
141+
val c1 = i1.toChar()
142+
when (c1) {
143+
'\\' -> {
144+
val i2 = reader.read()
145+
if (i2 < 0) state = Error
146+
else {
147+
val c2 = i2.toChar()
148+
when (c2) {
149+
'\n' -> state = Error
150+
',' -> sb.append(',')
151+
' ' -> sb.append(' ')
152+
'=' -> sb.append('=')
153+
else -> sb.append('\\').append(c2)
154+
}
155+
}
156+
}
157+
'\n' -> state = Error
158+
',', ' ' -> {
159+
state = Error
160+
// TODO: read till new line
161+
}
162+
'=' -> {
163+
state = TagValue
164+
}
165+
else -> sb.append(c1)
166+
}
167+
}
168+
}
169+
TagValue -> {
170+
val i1 = reader.read()
171+
if (i1 < 0) state = Error
172+
else {
173+
val c1 = i1.toChar()
174+
when (c1) {
175+
'\\' -> {
176+
val i2 = reader.read()
177+
if (i2 < 0) state = Error
178+
else {
179+
val c2 = i2.toChar()
180+
when (c2) {
181+
'\n' -> state = Error
182+
',' -> sb2.append(',')
183+
' ' -> sb2.append(' ')
184+
'=' -> sb2.append('=')
185+
else -> sb2.append('\\').append(c2)
186+
}
187+
}
188+
}
189+
',', ' ' -> {
190+
val tagKey = sb.toString()
191+
val tagValue = sb2.toString()
192+
if (tagKey.isEmpty() || tagValue.isEmpty()) {
193+
state = Error // TODO: skip if fail fast or read till new Line
194+
} else {
195+
builder.addTag(tagKey, tagValue)
196+
state = if (',' == c1) TagKey else FieldKey
197+
}
198+
sb.setLength(0)
199+
sb2.setLength(0)
200+
}
201+
'\n' -> state = Error
202+
'=' -> {
203+
state = Error // TODO: read till new Line
204+
}
205+
else -> sb2.append(c1)
206+
}
207+
}
208+
}
209+
210+
FieldKey -> {
211+
val i1 = reader.read()
212+
if (i1 < 0) state = Error
213+
else {
214+
val c1 = i1.toChar()
215+
when (c1) {
216+
'\\' -> {
217+
val i2 = reader.read()
218+
if (i2 < 0) state = Error
219+
else {
220+
val c2 = i2.toChar()
221+
when (c2) {
222+
'\n' -> state = Error
223+
',' -> sb.append(',')
224+
' ' -> sb.append(' ')
225+
'=' -> sb.append('=')
226+
else -> sb.append('\\').append(c2)
227+
}
228+
}
229+
}
230+
'\n' -> state = Error
231+
',', ' ' -> {
232+
state = Error
233+
}
234+
'=' -> {
235+
state = FieldValue
236+
}
237+
else -> sb.append(c1)
238+
}
239+
}
240+
}
241+
FieldValue -> {
242+
val i1 = reader.read()
243+
if (i1 < 0) state = Error
244+
else {
245+
val c1 = i1.toChar()
246+
when (c1) {
247+
'\n' -> state = Error
248+
'"' -> state = StringFieldValue
249+
else -> {
250+
sb2.append(c1)
251+
state = NonStringFieldValue
252+
}
253+
}
254+
}
255+
}
256+
StringFieldValue -> {
257+
val i1 = reader.read()
258+
if (i1 < 0) state = Error
259+
else {
260+
val c1 = i1.toChar()
261+
when (c1) {
262+
'\\' -> {
263+
val i2 = reader.read()
264+
if (i2 < 0) state = Error
265+
else {
266+
val c2 = i2.toChar()
267+
when (c2) {
268+
'"' -> sb2.append('"')
269+
else -> sb2.append('\\').append(c2)
270+
}
271+
}
272+
}
273+
'"' -> {
274+
builder.addValue(sb.toString(), sb2.toString())
275+
sb.setLength(0)
276+
sb2.setLength(0)
277+
val i2 = reader.read()
278+
if (i2 < 0) state = End
279+
else when (i2.toChar()) {
280+
'\n' -> state = End
281+
',' -> state = FieldKey
282+
' ' -> state = Timestamp
283+
else -> state = Error
284+
}
285+
}
286+
else -> sb2.append(c1)
287+
}
288+
}
289+
}
290+
NonStringFieldValue -> {
291+
val i1 = reader.read()
292+
if (i1 < 0) {
293+
294+
val value = sb2.toString()
295+
296+
when (value) {
297+
"t", "T", "true", "True", "TRUE" -> {
298+
builder.addValue(sb.toString(), true)
299+
}
300+
"f", "F", "false", "False", "FALSE" -> {
301+
builder.addValue(sb.toString(), false)
302+
}
303+
else -> {
304+
if (value.endsWith('i')) {
305+
builder.addValue(
306+
sb.toString(),
307+
parseLong(value.substring(0, value.length - 1))
308+
)
309+
} else {
310+
builder.addValue(
311+
sb.toString(),
312+
java.lang.Double.parseDouble(value)
313+
)
314+
}
315+
}
316+
}
317+
318+
sb.setLength(0)
319+
sb2.setLength(0)
320+
321+
state = End
322+
} else {
323+
val c1 = i1.toChar()
324+
when (c1) {
325+
',', ' ', '\n' -> {
326+
327+
val value = sb2.toString()
328+
329+
when (value) {
330+
"t", "T", "true", "True", "TRUE" -> {
331+
builder.addValue(sb.toString(), true)
332+
}
333+
"f", "F", "false", "False", "FALSE" -> {
334+
builder.addValue(sb.toString(), false)
335+
}
336+
else -> {
337+
if (value.endsWith('i')) {
338+
builder.addValue(
339+
sb.toString(),
340+
parseLong(value.substring(0, value.length - 1))
341+
)
342+
} else {
343+
builder.addValue(
344+
sb.toString(),
345+
java.lang.Double.parseDouble(value)
346+
)
347+
}
348+
}
349+
}
350+
351+
sb.setLength(0)
352+
sb2.setLength(0)
353+
state = if (',' == c1) FieldKey else Timestamp
354+
}
355+
else -> sb2.append(c1)
356+
}
357+
}
358+
}
359+
360+
Timestamp -> {
361+
val i1 = reader.read()
362+
if (i1 < 0) {
363+
builder.timestamp = parseLong(sb.toString())
364+
state = End
365+
} else {
366+
val c1 = i1.toChar()
367+
when (c1) {
368+
'\n' -> {
369+
builder.timestamp = parseLong(sb.toString())
370+
state = End
371+
}
372+
else -> {
373+
sb.append(c1)
374+
}
375+
}
376+
}
377+
378+
}
379+
}
380+
}
381+
382+
return builder.build()
383+
384+
}
385+
386+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package io.sniffy.influxdb.parser
2+
3+
import io.sniffy.influxdb.lineprotocol.FieldFloatValue
4+
import org.junit.jupiter.api.Assertions.*
5+
import org.junit.jupiter.api.Test
6+
7+
internal class LineProtocolParserTest {
8+
9+
@Test
10+
fun simpleTest() {
11+
assertTrue(true)
12+
}
13+
14+
@Test
15+
fun parseOneValidLine() {
16+
val parser = LineProtocolParser("weather,location=us-midwest temperature=82 1465839830100400200")
17+
18+
assertTrue(parser.hasNext())
19+
20+
val point = parser.next()
21+
22+
assertEquals("weather", point.measurement)
23+
assertEquals(mapOf("location" to "us-midwest"), point.tags)
24+
assertEquals(mapOf("temperature" to FieldFloatValue(82.0)), point.values)
25+
assertEquals(1465839830100400200, point.timestamp)
26+
27+
assertFalse(parser.hasNext())
28+
}
29+
30+
@Test
31+
fun hasNextSkippedThrowsException() {
32+
val parser = LineProtocolParser("weather,location=us-midwest temperature=82 1465839830100400200")
33+
34+
assertThrows(NoSuchElementException::class.java, {
35+
parser.next()
36+
})
37+
}
38+
39+
}

‎settings.gradle

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
rootProject.name = 'influxdb-tools'
2+
include 'parser'
3+
include 'lineprotocol'
4+

0 commit comments

Comments
 (0)
Please sign in to comment.