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

com.android.resources.aar.ProtoStyledStringDecoder Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * 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.
 */
package com.android.resources.aar;

import com.android.aapt.Resources;
import com.android.utils.XmlUtils;
import org.jetbrains.annotations.NotNull;

import java.util.ArrayList;
import java.util.List;

/**
 * Static methods for converting {@link Resources.StyledString} proto message back to the original XML string.
 */
class ProtoStyledStringDecoder {
  /**
   * Decodes the given {@link Resources.StyledString} proto message to obtain the original XML string.
   *
   * @param styledStringMsg the proto message to decode
   * @return the original XML string
   */
  @NotNull
  public static String getRawXmlValue(@NotNull Resources.StyledString styledStringMsg) {
    String text = styledStringMsg.getValue();
    StringBuilder xmlValue = new StringBuilder(text.length() * 2);
    List spanList = styledStringMsg.getSpanList();
    List spanStack = new ArrayList<>(spanList.size());

    int offset = 0;
    for (int i = 0; i <= styledStringMsg.getSpanCount(); i++) {
      int oldOffset = offset;
      Resources.StyledString.Span spanMsg;
      if (i < styledStringMsg.getSpanCount()) {
        spanMsg = styledStringMsg.getSpan(i);
        offset = spanMsg.getFirstChar();
      } else {
        spanMsg = null;
        offset = text.length();
      }
      // Check if there are any tags that need to be closed.
      while (!spanStack.isEmpty() && spanStack.get(spanStack.size() - 1).getLastChar() < offset) {
        Resources.StyledString.Span span = spanStack.remove(spanStack.size() - 1);
        int spanEnd = span.getLastChar() + 1;
        if (spanEnd > oldOffset) {
          XmlUtils.appendXmlTextValue(xmlValue, text, oldOffset, spanEnd);
          oldOffset = spanEnd;
        }
        String tagText = span.getTag();
        int tagEnd = indexOfOrEnd(tagText, ';', 0);
        // Write the closing tag.
        xmlValue.append("');
      }
      if (offset >= oldOffset) {
        // Copy text between tags.
        XmlUtils.appendXmlTextValue(xmlValue, text, oldOffset, offset);
        // Start a new tag.
        if (spanMsg != null) {
          String tagText = spanMsg.getTag();
          int pos = indexOfOrEnd(tagText, ';', 0);
          if (pos != 0) {
            spanStack.add(spanMsg);
            xmlValue.append('<').append(tagText, 0, pos);
            while (pos < tagText.length()) {
              pos++;
              int nextPos = indexOfOrEnd(tagText, ';', pos);
              int nameEnd = tagText.indexOf('=', pos);
              if (nameEnd > pos && nameEnd < nextPos) {
                xmlValue.append(' ');
                xmlValue.append(tagText, pos, nameEnd + 1);
                xmlValue.append('"');
                // Attribute values in the proto message are not escaped. Append with escaping.
                XmlUtils.appendXmlAttributeValue(xmlValue, tagText, nameEnd + 1, nextPos);
                xmlValue.append('"');
              }
              pos = nextPos;
            }
            xmlValue.append('>');
          }
        }
      }
    }
    return xmlValue.toString();
  }

  private static int indexOfOrEnd(@NotNull String str, char ch, int fromIndex) {
    int index = str.indexOf(ch, fromIndex);
    return index >= 0 ? index : str.length();
  }

  /** Do not instantiate. All methods are static. */
  private ProtoStyledStringDecoder() {}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy