auto import from //depot/cupcake/@135843
diff --git a/tools/layoutlib_utils/.classpath b/tools/layoutlib_utils/.classpath
new file mode 100644
index 0000000..0321c43
--- /dev/null
+++ b/tools/layoutlib_utils/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/layoutlib_api"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/tools/layoutlib_utils/.project b/tools/layoutlib_utils/.project
new file mode 100644
index 0000000..b427809
--- /dev/null
+++ b/tools/layoutlib_utils/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>layoutlib_utils</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
diff --git a/tools/layoutlib_utils/Android.mk b/tools/layoutlib_utils/Android.mk
new file mode 100644
index 0000000..50eb0ff
--- /dev/null
+++ b/tools/layoutlib_utils/Android.mk
@@ -0,0 +1,26 @@
+#
+# Copyright (C) 2008 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.
+#
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under,src)
+
+LOCAL_JAVA_LIBRARIES := \
+	layoutlib_api
+
+LOCAL_MODULE := layoutlib_utils
+
+include $(BUILD_HOST_JAVA_LIBRARY)
diff --git a/tools/layoutlib_utils/src/com/android/layoutlib/utils/ResourceValue.java b/tools/layoutlib_utils/src/com/android/layoutlib/utils/ResourceValue.java
new file mode 100644
index 0000000..98b4de6
--- /dev/null
+++ b/tools/layoutlib_utils/src/com/android/layoutlib/utils/ResourceValue.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2008 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.layoutlib.utils;
+
+import com.android.layoutlib.api.IResourceValue;
+
+public class ResourceValue implements IResourceValue {
+    private final String mType;
+    private final String mName;
+    private String mValue = null;
+    private final boolean mIsFramwork;
+    
+    public ResourceValue(String type, String name, boolean isFramwork) {
+        mType = type;
+        mName = name;
+        mIsFramwork = isFramwork;
+    }
+
+    public ResourceValue(String type, String name, String value, boolean isFramework) {
+        mType = type;
+        mName = name;
+        mValue = value;
+        mIsFramwork = isFramework;
+    }
+
+    public String getType() {
+        return mType;
+    }
+
+    public final String getName() {
+        return mName;
+    }
+    
+    public final String getValue() {
+        return mValue;
+    }
+    
+    public final void setValue(String value) {
+        mValue = value;
+    }
+    
+    public void replaceWith(ResourceValue value) {
+        mValue = value.mValue;
+    }
+
+    public boolean isFramework() {
+        return mIsFramwork;
+    }
+}
diff --git a/tools/layoutlib_utils/src/com/android/layoutlib/utils/StyleResourceValue.java b/tools/layoutlib_utils/src/com/android/layoutlib/utils/StyleResourceValue.java
new file mode 100644
index 0000000..a32ac1b
--- /dev/null
+++ b/tools/layoutlib_utils/src/com/android/layoutlib/utils/StyleResourceValue.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2008 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.layoutlib.utils;
+
+import com.android.layoutlib.api.IResourceValue;
+import com.android.layoutlib.api.IStyleResourceValue;
+
+import java.util.HashMap;
+
+public final class StyleResourceValue extends ResourceValue implements IStyleResourceValue {
+
+    private String mParentStyle = null;
+    private HashMap<String, IResourceValue> mItems = new HashMap<String, IResourceValue>();
+
+    public StyleResourceValue(String type, String name, boolean isFramework) {
+        super(type, name, isFramework);
+    }
+
+    public StyleResourceValue(String type, String name, String parentStyle, boolean isFramework) {
+        super(type, name, isFramework);
+        mParentStyle = parentStyle;
+    }
+
+    public String getParentStyle() {
+        return mParentStyle;
+    }
+    
+    public IResourceValue findItem(String name) {
+        return mItems.get(name);
+    }
+    
+    public void addItem(IResourceValue value) {
+        mItems.put(value.getName(), value);
+    }
+    
+    @Override
+    public void replaceWith(ResourceValue value) {
+        super.replaceWith(value);
+        
+        if (value instanceof StyleResourceValue) {
+            mItems.clear();
+            mItems.putAll(((StyleResourceValue)value).mItems);
+        }
+    }
+
+}
diff --git a/tools/layoutlib_utils/src/com/android/layoutlib/utils/ValueResourceParser.java b/tools/layoutlib_utils/src/com/android/layoutlib/utils/ValueResourceParser.java
new file mode 100644
index 0000000..8b768ef
--- /dev/null
+++ b/tools/layoutlib_utils/src/com/android/layoutlib/utils/ValueResourceParser.java
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2008 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.layoutlib.utils;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ * SAX handler to parser value resource files.
+ */
+public final class ValueResourceParser extends DefaultHandler {
+
+    // TODO: reuse definitions from somewhere else.
+    private final static String NODE_RESOURCES = "resources";
+    private final static String NODE_ITEM = "item";
+    private final static String ATTR_NAME = "name";
+    private final static String ATTR_TYPE = "type";
+    private final static String ATTR_PARENT = "parent";
+    
+    // Resource type definition
+    private final static String RES_STYLE = "style";
+    private final static String RES_ATTR = "attr";
+    
+    private final static String DEFAULT_NS_PREFIX = "android:";
+    private final static int DEFAULT_NS_PREFIX_LEN = DEFAULT_NS_PREFIX.length();
+    
+    public interface IValueResourceRepository {
+        void addResourceValue(String resType, ResourceValue value);
+    }
+    
+    private boolean inResources = false;
+    private int mDepth = 0;
+    private StyleResourceValue mCurrentStyle = null;
+    private ResourceValue mCurrentValue = null;
+    private IValueResourceRepository mRepository;
+    private final boolean mIsFramework;
+    
+    public ValueResourceParser(IValueResourceRepository repository, boolean isFramework) {
+        mRepository = repository;
+        mIsFramework = isFramework;
+    }
+
+    @Override
+    public void endElement(String uri, String localName, String qName) throws SAXException {
+        if (mCurrentValue != null) {
+            mCurrentValue.setValue(trimXmlWhitespaces(mCurrentValue.getValue()));
+        }
+        
+        if (inResources && qName.equals(NODE_RESOURCES)) {
+            inResources = false;
+        } else if (mDepth == 2) {
+            mCurrentValue = null;
+            mCurrentStyle = null;
+        } else if (mDepth == 3) {
+            mCurrentValue = null;
+        }
+        
+        mDepth--;
+        super.endElement(uri, localName, qName);
+    }
+
+    @Override
+    public void startElement(String uri, String localName, String qName, Attributes attributes)
+            throws SAXException {
+        try {
+            mDepth++;
+            if (inResources == false && mDepth == 1) {
+                if (qName.equals(NODE_RESOURCES)) {
+                    inResources = true;
+                }
+            } else if (mDepth == 2 && inResources == true) {
+                String type;
+                
+                // if the node is <item>, we get the type from the attribute "type"
+                if (NODE_ITEM.equals(qName)) {
+                    type = attributes.getValue(ATTR_TYPE);
+                } else {
+                    // the type is the name of the node.
+                    type = qName;
+                }
+
+                if (type != null) {
+                    if (RES_ATTR.equals(type) == false) {
+                        // get the resource name
+                        String name = attributes.getValue(ATTR_NAME);
+                        if (name != null) {
+                            if (RES_STYLE.equals(type)) {
+                                String parent = attributes.getValue(ATTR_PARENT);
+                                mCurrentStyle = new StyleResourceValue(type, name, parent, mIsFramework);
+                                mRepository.addResourceValue(type, mCurrentStyle);
+                            } else {
+                                mCurrentValue = new ResourceValue(type, name, mIsFramework);
+                                mRepository.addResourceValue(type, mCurrentValue);
+                            }
+                        }
+                    }
+                }
+            } else if (mDepth == 3 && mCurrentStyle != null) {
+                // get the resource name
+                String name = attributes.getValue(ATTR_NAME);
+                if (name != null) {
+                    // the name can, in some cases, contain a prefix! we remove it.
+                    if (name.startsWith(DEFAULT_NS_PREFIX)) {
+                        name = name.substring(DEFAULT_NS_PREFIX_LEN);
+                    }
+    
+                    mCurrentValue = new ResourceValue(null, name, mIsFramework);
+                    mCurrentStyle.addItem(mCurrentValue);
+                }
+            }
+        } finally {
+            super.startElement(uri, localName, qName, attributes);
+        }
+    }
+    
+    @Override
+    public void characters(char[] ch, int start, int length) throws SAXException {
+        if (mCurrentValue != null) {
+            String value = mCurrentValue.getValue();
+            if (value == null) {
+                mCurrentValue.setValue(new String(ch, start, length));
+            } else {
+                mCurrentValue.setValue(value + new String(ch, start, length));
+            }
+        }
+    }
+    
+    public static String trimXmlWhitespaces(String value) {
+        if (value == null) {
+            return null;
+        }
+
+        // look for carriage return and replace all whitespace around it by just 1 space.
+        int index;
+        
+        while ((index = value.indexOf('\n')) != -1) {
+            // look for whitespace on each side
+            int left = index - 1;
+            while (left >= 0) {
+                if (Character.isWhitespace(value.charAt(left))) {
+                    left--;
+                } else {
+                    break;
+                }
+            }
+            
+            int right = index + 1;
+            int count = value.length();
+            while (right < count) {
+                if (Character.isWhitespace(value.charAt(right))) {
+                    right++;
+                } else {
+                    break;
+                }
+            }
+            
+            // remove all between left and right (non inclusive) and replace by a single space.
+            String leftString = null;
+            if (left >= 0) {
+                leftString = value.substring(0, left + 1);
+            }
+            String rightString = null;
+            if (right < count) {
+                rightString = value.substring(right);
+            }
+            
+            if (leftString != null) {
+                value = leftString;
+                if (rightString != null) {
+                    value += " " + rightString;
+                }
+            } else {
+                value = rightString != null ? rightString : "";
+            }
+        }
+        
+        // now we un-escape the string
+        int length = value.length();
+        char[] buffer = value.toCharArray();
+        
+        for (int i = 0 ; i < length ; i++) {
+            if (buffer[i] == '\\') {
+                if (buffer[i+1] == 'u') {
+                    // this is unicode char.
+                    int unicodeChar = Integer.parseInt(new String(buffer, i+2, 4), 16);
+                    
+                    // put the unicode char at the location of the \
+                    buffer[i] = (char)unicodeChar;
+
+                    // offset the rest of the buffer since we go from 6 to 1 char
+                    if (i + 6 < buffer.length) {
+                        System.arraycopy(buffer, i+6, buffer, i+1, length - i - 6);
+                    }
+                    length -= 5;
+                } else {
+                    if (buffer[i+1] == 'n') {
+                        // replace the 'n' char with \n
+                        buffer[i+1] = '\n';
+                    }
+                    
+                    // offset the buffer to erase the \
+                    System.arraycopy(buffer, i+1, buffer, i, length - i - 1);
+                    length--;
+                }
+            }
+        }
+        
+        return new String(buffer, 0, length);
+    }
+}