+ boost::filesystem::path::const_iterator i = root.begin ();
+ boost::filesystem::path::const_iterator j = file.begin ();
+
+ while (i != root.end() && j != file.end() && *i == *j) {
+ ++i;
+ ++j;
+ }
+
+ if (i != root.end ()) {
+ return optional<boost::filesystem::path> ();
+ }
+
+ boost::filesystem::path rel;
+ while (j != file.end ()) {
+ rel /= *j++;
+ }
+
+ return rel;
+}
+
+bool
+dcp::ids_equal (string a, string b)
+{
+ transform (a.begin(), a.end(), a.begin(), ::tolower);
+ transform (b.begin(), b.end(), b.begin(), ::tolower);
+ trim (a);
+ trim (b);
+ return a == b;
+}
+
+string
+dcp::file_to_string (boost::filesystem::path p, uintmax_t max_length)
+{
+ uintmax_t len = boost::filesystem::file_size (p);
+ if (len > max_length) {
+ throw MiscError ("Unexpectedly long file");
+ }
+
+ char* c = new char[len + 1];
+
+ FILE* f = fopen_boost (p, "r");
+ if (!f) {
+ return "";
+ }
+
+ fread (c, 1, len, f);
+ fclose (f);
+ c[len] = '\0';
+
+ string s (c);
+ delete[] c;
+
+ return s;