X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;ds=sidebyside;f=yang%2Fyang-parser-impl%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fyangtools%2Fyang%2Fparser%2Fstmt%2Frfc6020%2FUtils.java;fp=yang%2Fyang-parser-impl%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fyangtools%2Fyang%2Fparser%2Fstmt%2Frfc6020%2FUtils.java;h=e786ee95610f2ffa5366460b2671d4bec0a108ec;hb=c8e2399ca8503fb2a3e5c2e359554af9c45bf1d6;hp=bce189b6df16bcfba55e29b3868356a72e543fb7;hpb=fd69b921c893b7754d1345a8270844a4feb1d1bc;p=yangtools.git diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/Utils.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/Utils.java index bce189b6df..e786ee9561 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/Utils.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/Utils.java @@ -7,9 +7,11 @@ */ package org.opendaylight.yangtools.yang.parser.stmt.rfc6020; +import static com.google.common.base.CharMatcher.WHITESPACE; import static org.opendaylight.yangtools.yang.common.YangConstants.RFC6020_YANG_NAMESPACE; import static org.opendaylight.yangtools.yang.common.YangConstants.YANG_XPATH_FUNCTIONS_PREFIX; +import com.google.common.annotations.VisibleForTesting; import com.google.common.base.CharMatcher; import com.google.common.base.Splitter; import com.google.common.collect.ImmutableBiMap; @@ -214,8 +216,11 @@ public final class Utils { * in the inner string and trim the result. */ checkDoubleQuotedString(innerStr, yangVersion, ref); - sb.append(innerStr.replace("\\\"", "\"").replace("\\\\", "\\").replace("\\n", "\n") - .replace("\\t", "\t")); + sb.append(trimWhitespace(innerStr, stringNode.getSymbol().getCharPositionInLine()) + .replace("\\\"", "\"") + .replace("\\\\", "\\") + .replace("\\n", "\n") + .replace("\\t", "\t")); } else if (firstChar == '\'' && lastChar == '\'') { /* * According to RFC6020 a single quote character cannot occur in @@ -266,6 +271,83 @@ public final class Utils { } } + @VisibleForTesting + static String trimWhitespace(final String str, final int dquot) { + int brk = str.indexOf('\n'); + if (brk == -1) { + // No need to trim whitespace + return str; + } + + // Okay, we may need to do some trimming, set up a builder and append the first segment + final int length = str.length(); + final StringBuilder sb = new StringBuilder(length); + + // Append first segment, which needs only tail-trimming + sb.append(str, 0, trimTrailing(str, 0, brk)).append('\n'); + + // With that out of the way, setup our iteration state. The string segment we are looking at is + // str.substring(start, end), which is guaranteed not to include any line breaks, i.e. end <= brk unless we are + // at the last segment. + int start = brk + 1; + brk = str.indexOf('\n', start); + + // Loop over inner strings + while (brk != -1) { + final int end = brk != -1 ? brk : length; + trimLeadingAndAppend(sb, dquot, str, start, trimTrailing(str, start, end)).append('\n'); + start = end + 1; + brk = str.indexOf('\n', start); + } + + return trimLeadingAndAppend(sb, dquot, str, start, length).toString(); + } + + private static StringBuilder trimLeadingAndAppend(final StringBuilder sb, final int dquot, final String str, + final int start, final int end) { + int offset = start; + int pos = 0; + + while (pos <= dquot) { + if (offset == end) { + // We ran out of data, nothing to append + return sb; + } + + final char ch = str.charAt(offset); + if (ch == '\t') { + // tabs are to be treated as 8 spaces + pos += 8; + } else if (WHITESPACE.matches(ch)) { + pos++; + } else { + break; + } + + offset++; + } + + // We have expanded beyond double quotes, push equivalent spaces + while (pos - 1 > dquot) { + sb.append(' '); + pos--; + } + + return sb.append(str, offset, end); + } + + private static int trimTrailing(final String str, final int start, final int end) { + int ret = end; + while (ret > start) { + final int prev = ret - 1; + if (!WHITESPACE.matches(str.charAt(prev))) { + break; + } + ret = prev; + } + return ret; + } + @Nullable public static StatementContextBase findNode(final StmtContext rootStmtCtx, final SchemaNodeIdentifier node) {