Merge "Added at() method to vector. We use a dummy static field as the returned reference when the index is out of bound."
diff --git a/include/vector b/include/vector
index 051da1d..b17cc70 100644
--- a/include/vector
+++ b/include/vector
@@ -132,6 +132,13 @@
     // @return A reference to the element.
     reference operator[](size_type index) { return *(mBegin + index); }
 
+    // 'at' is similar to operator[] except that it does check bounds.
+    const_reference at(const size_type index) const
+    { return index < mLength ? *( mBegin + index) : sDummy; }
+
+    reference at(const size_type index)
+    { return index < mLength ? *( mBegin + index) : sDummy; }
+
     iterator begin() { return iterator(mBegin); }
     iterator end() { return iterator(mBegin + mLength); }
 
@@ -217,6 +224,7 @@
     pointer mBegin;
     size_type mCapacity;
     size_type mLength;
+    static value_type sDummy;  // at() doen't throw exception and returns mDummy.
     static const size_type kExponentialFactor = 2;
     static const size_type kExponentialLimit = 256;
     static const size_type kLinearIncrement = 256;
@@ -234,6 +242,7 @@
 //
 // Invariant: mLength <= mCapacity <= max_size()
 
+
 template<typename _T>
 vector<_T>::vector()
         :mBegin(NULL), mCapacity(0), mLength(0) { }
@@ -490,6 +499,9 @@
     free(mBegin);
 }
 
+// Dummy element returned when at() is out of bound.
+template<typename _T> _T vector<_T>::sDummy;
+
 }  // namespace std
 
 #endif  // ANDROID_ASTL_VECTOR__
diff --git a/tests/test_vector.cpp b/tests/test_vector.cpp
index 8b85b97..95de15e 100644
--- a/tests/test_vector.cpp
+++ b/tests/test_vector.cpp
@@ -641,6 +641,14 @@
     return true;
 }
 
+// Valgrind should not barf when we access element out of bound.
+bool testAt() {
+    vector<int> vec;
+
+    vec.at(1000) = 0xdeadbeef;
+    EXPECT_TRUE(vec.at(1000) == 0xdeadbeef);
+    return true;
+}
 }  // namespace android
 
 int main(int argc, char **argv)
@@ -659,5 +667,6 @@
     FAIL_UNLESS(testCtorDtorForNonPod);
     FAIL_UNLESS(testEraseElt);
     FAIL_UNLESS(testEraseRange);
+    FAIL_UNLESS(testAt);
     return kPassed;
 }