Fix bugs and add unit tests to FileInputStream class.
Add the class to Linux/Mac builds.
git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@7 672e30a5-4c29-85ac-ac6d-611c735e0a51
diff --git a/sfntly/port/file_input_stream.cc b/sfntly/port/file_input_stream.cc
index dcb37f7..d4432bb 100644
--- a/sfntly/port/file_input_stream.cc
+++ b/sfntly/port/file_input_stream.cc
@@ -59,6 +59,7 @@
fclose(file_);
length_ = 0;
position_ = 0;
+ file_ = NULL;
}
}
@@ -98,7 +99,6 @@
int32_t FileInputStream::read(ByteVector* b, int32_t offset, int32_t length) {
assert(b);
- assert(b->size() >= (size_t)(offset + length));
if (!file_) {
#if defined (SFNTLY_NO_EXCEPTION)
return 0;
@@ -114,6 +114,9 @@
#endif
}
size_t read_count = std::min<size_t>(length_ - position_, length);
+ if (b->size() < (size_t)(offset + read_count)) {
+ b->resize((size_t)(offset + read_count));
+ }
int32_t actual_read = fread(&((*b)[offset]), 1, read_count, file_);
position_ += actual_read;
return actual_read;
@@ -131,12 +134,16 @@
throw IOException("no opened file");
#endif
}
- if (n < 0) {
- return 0;
+ int64_t skip_count = 0;
+ if (n < 0) { // move backwards
+ skip_count = std::max<int64_t>(0 - (int64_t)position_, n);
+ position_ -= (size_t)(0 - skip_count);
+ fseek(file_, position_, SEEK_SET);
+ } else {
+ skip_count = std::min<size_t>(length_ - position_, (size_t)n);
+ position_ += (size_t)skip_count;
+ fseek(file_, (size_t)skip_count, SEEK_CUR);
}
- size_t skip_count = std::min<size_t>(length_ - position_, (size_t)n);
- fseek(file_, skip_count, SEEK_CUR);
- position_ += skip_count;
return skip_count;
}
@@ -156,8 +163,10 @@
}
size_t unread_count = std::min<size_t>(position_, length);
fseek(file_, position_ - unread_count, SEEK_SET);
+ position_ -= unread_count;
read(b, offset, length);
fseek(file_, position_ - unread_count, SEEK_SET);
+ position_ -= unread_count;
}
} // namespace sfntly
diff --git a/test/file_io_test.cc b/test/file_io_test.cc
new file mode 100644
index 0000000..f3b93ea
--- /dev/null
+++ b/test/file_io_test.cc
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2011 Google Inc. All Rights Reserved.
+ *
+ * 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.
+ */
+
+#include <stdio.h>
+
+#include "gtest/gtest.h"
+#include "sfntly/port/file_input_stream.h"
+#include "sfntly/data/font_input_stream.h"
+
+namespace sfntly {
+
+bool testFileInputStream() {
+ const char* test_file = "arial.ttf";
+ FILE* file_handle = NULL;
+#if defined (WIN32)
+ fopen_s(&file_handle, test_file, "rb");
+#else
+ file_handle = fopen(test_file, "rb");
+#endif
+ if (file_handle == NULL) {
+ return false;
+ }
+ fseek(file_handle, 0, SEEK_END);
+ size_t length = ftell(file_handle);
+ fseek(file_handle, 0, SEEK_SET);
+ ByteVector b1;
+ b1.resize(length);
+ fread(&(b1[0]), 1, length, file_handle);
+ fclose(file_handle);
+
+ // Full file reading test
+ FileInputStream is;
+ is.open(test_file);
+ EXPECT_EQ(length, is.available());
+ ByteVector b2;
+ is.read(&b2, 0, length);
+ is.close();
+ EXPECT_EQ(memcmp(&(b1[0]), &(b2[0]), length), 0);
+ b2.clear();
+
+ // Partial reading test
+ is.open(test_file);
+ is.skip(89);
+ is.read(&b2, 0, 100);
+ EXPECT_EQ(memcmp(&(b1[89]), &(b2[0]), 100), 0);
+ b2.clear();
+
+ // Skip test
+ is.skip(-89);
+ is.read(&b2, 0, 100);
+ EXPECT_EQ(memcmp(&(b1[100]), &(b2[0]), 100), 0);
+ b2.clear();
+ is.skip(100);
+ is.read(&b2, 0, 100);
+ EXPECT_EQ(memcmp(&(b1[300]), &(b2[0]), 100), 0);
+ is.skip(-400);
+ b2.clear();
+
+ // Offset test
+ is.read(&b2, 0, 100);
+ is.read(&b2, 100, 100);
+ EXPECT_EQ(memcmp(&(b1[0]), &(b2[0]), 200), 0);
+
+ // Unread test
+ ByteVector b3;
+ b3.resize(200);
+ is.unread(&b3);
+ EXPECT_EQ(memcmp(&(b3[0]), &(b2[0]), 200), 0);
+
+ return true;
+}
+
+bool testFontInputStream() {
+ const char* test_file = "arial.ttf";
+ FILE* file_handle = NULL;
+#if defined (WIN32)
+ fopen_s(&file_handle, test_file, "rb");
+#else
+ file_handle = fopen(test_file, "rb");
+#endif
+ if (file_handle == NULL) {
+ return false;
+ }
+ fseek(file_handle, 0, SEEK_END);
+ size_t length = ftell(file_handle);
+ fseek(file_handle, 0, SEEK_SET);
+ ByteVector b1;
+ b1.resize(length);
+ fread(&(b1[0]), 1, length, file_handle);
+ fclose(file_handle);
+
+ FileInputStream is;
+ is.open(test_file);
+ FontInputStream font_is1(&is);
+ EXPECT_EQ(font_is1.available(), length);
+
+ ByteVector b2;
+ font_is1.read(&b2, 0, length);
+ font_is1.close();
+ EXPECT_EQ(memcmp(&(b1[0]), &(b2[0]), length), 0);
+ b2.clear();
+
+ is.open(test_file);
+ is.skip(89);
+ FontInputStream font_is2(&is, 200);
+ font_is2.read(&b2, 0, 100);
+ EXPECT_EQ(memcmp(&(b1[89]), &(b2[0]), 100), 0);
+ font_is2.read(&b2, 100, 100);
+ EXPECT_EQ(memcmp(&(b1[89]), &(b2[0]), 200), 0);
+ b2.clear();
+ font_is2.skip(-200);
+ font_is2.read(&b2, 0, 100);
+ EXPECT_EQ(memcmp(&(b1[89]), &(b2[0]), 100), 0);
+
+ return true;
+}
+
+} // namespace sfntly
diff --git a/test/file_io_test.h b/test/file_io_test.h
new file mode 100644
index 0000000..f929ab4
--- /dev/null
+++ b/test/file_io_test.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2011 Google Inc. All Rights Reserved.
+ *
+ * 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.
+ */
+
+#ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_FILE_IO_TEST_H_
+#define TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_FILE_IO_TEST_H_
+
+namespace sfntly {
+
+bool testFileInputStream();
+bool testFontInputStream();
+
+} // namespace sfntly
+
+#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_FILE_IO_TEST_H_
diff --git a/test/main.cc b/test/main.cc
index 27862c5..ea17ae3 100644
--- a/test/main.cc
+++ b/test/main.cc
@@ -22,6 +22,7 @@
#include "test/smart_pointer_test.h"
#include "test/endian_test.h"
#include "test/byte_array_test.h"
+#include "test/file_io_test.h"
#include "test/font_data_test.h"
#include "test/open_type_data_test.h"
#include "test/otf_basic_editing_test.h"
@@ -50,6 +51,11 @@
}
#endif
+TEST(FileIO, All) {
+ EXPECT_TRUE(sfntly::testFileInputStream());
+ EXPECT_TRUE(sfntly::testFontInputStream());
+}
+
TEST(OpenTypeData, All) {
EXPECT_TRUE(sfntly::testOTFRead());
EXPECT_TRUE(sfntly::testOTFCopy());
diff --git a/test/test_font_utils.cc b/test/test_font_utils.cc
new file mode 100644
index 0000000..d8a7220
--- /dev/null
+++ b/test/test_font_utils.cc
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2011 Google Inc. All Rights Reserved.
+ *
+ * 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.
+ */
+
+#include <stdio.h>
+
+#include "gtest/gtest.h"
+#include "sfntly/data/memory_byte_array.h"
+#include "sfntly/port/file_input_stream.h"
+#include "test/test_font_utils.h"
+
+namespace sfntly {
+
+void builderForFontFile(const char* font_path, FontFactory* factory,
+ FontBuilderArray* builders) {
+ assert(factory);
+ FileInputStream is;
+ is.open(font_path);
+ factory->loadFontsForBuilding(&is, builders);
+ EXPECT_GT(builders->size(), static_cast<size_t>(0));
+}
+
+void serializeFont(const char* font_path, FontFactory* factory, Font* font) {
+ assert(font_path);
+ assert(factory);
+ assert(font);
+ MemoryOutputStream output_stream;
+ factory->serializeFont(font, &output_stream);
+ serializeToFile(&output_stream, font_path);
+}
+
+void loadFont(const char* font_path, FontFactory* factory, FontArray* fonts) {
+ FileInputStream is;
+ is.open(font_path);
+ factory->loadFonts(&is, fonts);
+ is.close();
+}
+
+void loadFile(const char* input_file_path, ByteVector* input_buffer) {
+ assert(input_file_path);
+ assert(input_buffer);
+
+ FILE* input_file = NULL;
+#if defined WIN32
+ fopen_s(&input_file, input_file_path, "rb");
+#else
+ input_file = fopen(input_file_path, "rb");
+#endif
+ EXPECT_NE(input_file, reinterpret_cast<FILE*>(NULL));
+ fseek(input_file, 0, SEEK_END);
+ size_t file_size = ftell(input_file);
+ fseek(input_file, 0, SEEK_SET);
+ input_buffer->resize(file_size);
+ fread(&((*input_buffer)[0]), 1, file_size, input_file);
+ fclose(input_file);
+}
+
+void serializeToFile(MemoryOutputStream* output_stream, const char* file_path) {
+ assert(file_path);
+ assert(output_stream);
+
+ FILE* output_file = NULL;
+#if defined WIN32
+ fopen_s(&output_file, file_path, "wb");
+#else
+ output_file = fopen(file_path, "wb");
+#endif
+ EXPECT_NE(output_file, reinterpret_cast<FILE*>(NULL));
+ fwrite(output_stream->get(), 1, output_stream->size(), output_file);
+ fflush(output_file);
+ fclose(output_file);
+}
+
+} // namespace sfntly
diff --git a/test/test_font_utils.h b/test/test_font_utils.h
new file mode 100644
index 0000000..d3f516d
--- /dev/null
+++ b/test/test_font_utils.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2011 Google Inc. All Rights Reserved.
+ *
+ * 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.
+ */
+
+#ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_TEST_FONT_UTILS_H_
+#define TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_TEST_FONT_UTILS_H_
+
+#include "sfntly/font.h"
+#include "sfntly/font_factory.h"
+#include "sfntly/port/memory_output_stream.h"
+
+namespace sfntly {
+
+void builderForFontFile(const char* font_path, FontFactory* factory,
+ FontBuilderArray* builders);
+void serializeFont(const char* font_path, FontFactory* factory, Font* font);
+void loadFont(const char* font_path, FontFactory* factory, FontArray* fonts);
+
+void loadFile(const char* input_file_path, ByteVector* input_buffer);
+void serializeToFile(MemoryOutputStream* output_stream, const char* file_path);
+
+} // namespace sfntly
+
+#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_TEST_FONT_UTILS_H_