grab from latest android



git-svn-id: http://skia.googlecode.com/svn/trunk@27 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/views/SkOSFile.cpp b/src/views/SkOSFile.cpp
new file mode 100644
index 0000000..c8eeeea
--- /dev/null
+++ b/src/views/SkOSFile.cpp
@@ -0,0 +1,223 @@
+#include "SkOSFile.h"
+
+#ifdef SK_BUILD_FOR_WIN
+
+static U16* concat_to_16(const char src[], const char suffix[])
+{
+	size_t	i, len = strlen(src);
+	size_t  len2 = 3 + (suffix ? strlen(suffix) : 0);
+	U16*	dst = (U16*)sk_malloc_throw((len + len2) * sizeof(U16));
+
+	for (i = 0; i < len; i++)
+		dst[i] = src[i];
+
+	if (i > 0 && dst[i-1] != '/')
+		dst[i++] = '/';
+	dst[i++] = '*';
+
+	if (suffix)
+	{
+		while (*suffix)
+			dst[i++] = *suffix++;
+	}
+	dst[i] = 0;
+	SkASSERT(i + 1 <= len + len2);
+
+	return dst;
+}
+
+SkUTF16_Str::SkUTF16_Str(const char src[])
+{
+	size_t	len = strlen(src);
+
+	fStr = (U16*)sk_malloc_throw((len + 1) * sizeof(U16));
+	for (size_t i = 0; i < len; i++)
+		fStr[i] = src[i];
+	fStr[i] = 0;
+}
+
+////////////////////////////////////////////////////////////////////////////
+
+SkOSFile::Iter::Iter() : fHandle(0), fPath16(nil)
+{
+}
+
+SkOSFile::Iter::Iter(const char path[], const char suffix[]) : fHandle(0), fPath16(nil)
+{
+	this->reset(path, suffix);
+}
+
+SkOSFile::Iter::~Iter()
+{
+	sk_free(fPath16);
+	if (fHandle)
+		::FindClose(fHandle);
+}
+
+void SkOSFile::Iter::reset(const char path[], const char suffix[])
+{
+	if (fHandle)
+	{
+		::FindClose(fHandle);
+		fHandle = 0;
+	}
+	if (path == nil)
+		path = "";
+
+	sk_free(fPath16);
+	fPath16 = concat_to_16(path, suffix);
+}
+
+static bool is_magic_dir(const U16 dir[])
+{
+	// return true for "." and ".."
+	return dir[0] == '.' && (dir[1] == 0 || dir[1] == '.' && dir[2] == 0);
+}
+
+static bool get_the_file(HANDLE handle, SkString* name, WIN32_FIND_DATAW* dataPtr, bool getDir)
+{
+	WIN32_FIND_DATAW	data;
+
+	if (dataPtr == nil)
+	{
+		if (::FindNextFileW(handle, &data))
+			dataPtr = &data;
+		else
+			return false;
+	}
+
+	for (;;)
+	{
+		if (getDir)
+		{
+			if ((dataPtr->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && !is_magic_dir(dataPtr->cFileName))
+				break;
+		}
+		else
+		{
+			if (!(dataPtr->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
+				break;
+		}
+		if (!::FindNextFileW(handle, dataPtr))
+			return false;
+	}
+	// if we get here, we've found a file/dir
+	if (name)
+		name->setUTF16(dataPtr->cFileName);
+	return true;
+}
+
+bool SkOSFile::Iter::next(SkString* name, bool getDir)
+{
+	WIN32_FIND_DATAW	data;
+	WIN32_FIND_DATAW*	dataPtr = nil;
+
+	if (fHandle == 0)	// our first time
+	{
+		if (fPath16 == nil || *fPath16 == 0)	// check for no path
+			return false;
+
+		fHandle = ::FindFirstFileW(fPath16, &data);
+		if (fHandle != 0 && fHandle != (HANDLE)~0)
+			dataPtr = &data;
+	}
+	return fHandle != (HANDLE)~0 && get_the_file(fHandle, name, dataPtr, getDir);
+}
+
+#elif defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_UNIX)
+
+#if 0
+OSStatus FSPathMakeRef (
+   const UInt8 * path,
+   FSRef * ref,
+   Boolean * isDirectory
+);
+#endif
+
+SkOSFile::Iter::Iter() : fDIR(0)
+{
+}
+
+SkOSFile::Iter::Iter(const char path[], const char suffix[]) : fDIR(0)
+{
+	this->reset(path, suffix);
+}
+
+SkOSFile::Iter::~Iter()
+{
+	if (fDIR)
+		::closedir(fDIR);
+}
+
+void SkOSFile::Iter::reset(const char path[], const char suffix[])
+{
+	if (fDIR)
+	{
+		::closedir(fDIR);
+		fDIR = 0;
+	}
+
+	fPath.set(path);
+	if (path)
+	{
+		fDIR = ::opendir(path);
+		fSuffix.set(suffix);
+	}
+	else
+		fSuffix.reset();
+}
+
+// returns true if suffix is empty, or if str ends with suffix
+static bool issuffixfor(const SkString& suffix, const char str[])
+{
+	size_t  suffixLen = suffix.size();
+	size_t  strLen = strlen(str);
+	
+	return  strLen >= suffixLen &&
+			suffixLen == 0 ||
+			memcmp(suffix.c_str(), str + strLen - suffixLen, suffixLen) == 0;
+}
+
+#include <sys/stat.h>
+
+bool SkOSFile::Iter::next(SkString* name, bool getDir)
+{
+	if (fDIR)
+	{
+		dirent* entry;
+
+		while ((entry = ::readdir(fDIR)) != NULL)
+		{
+			struct stat s;
+			SkString	str(fPath);
+
+			if (!str.endsWith("/") && !str.endsWith("\\"))
+				str.append("/");
+			str.append(entry->d_name);
+
+			if (0 == stat(str.c_str(), &s))
+			{
+				if (getDir)
+				{
+					if (s.st_mode & S_IFDIR)
+						break;
+				}
+				else
+				{
+					if (!(s.st_mode & S_IFDIR) && issuffixfor(fSuffix, entry->d_name))
+						break;
+				}
+			}
+		}
+		if (entry)	// we broke out with a file
+		{
+			if (name)
+				name->set(entry->d_name);
+			return true;
+		}
+	}
+	return false;
+}
+
+#endif
+