patch invert (patch p, tree t) { switch (get_type (p)) { case PATCH_MODIFICATION: return patch (get_inverse (p), get_modification (p)); case PATCH_BRANCH: ASSERT (N(p) <= 1, "ambiguous application"); case PATCH_COMPOUND: { int i, n=N(p); array<patch> r(n); for (i=0; i<n; i++) { r[n-1-i]= invert (p[i], t); t= clean_apply (p[i], t); } return patch (get_type (p) == PATCH_BRANCH, r); } case PATCH_BIRTH: return patch (get_author (p), !get_birth (p)); case PATCH_AUTHOR: return patch (get_author (p), invert (p[0], t)); default: FAILED ("unsupported patch type"); return patch (); } }
bool join (patch& p1, patch p2, tree t) { //cout << "Join " << p1 << LF << "with " << p2 << LF; if (get_type (p1) == PATCH_AUTHOR && get_type (p2) == PATCH_AUTHOR && get_author (p1) == get_author (p2)) { double author= get_author (p1); patch q1= p1[0]; patch q2= p2[0]; bool r= join (q1, q2, t); if (r) p1= patch (author, q1); return r; } if (get_type (p1) == PATCH_MODIFICATION && get_type (p2) == PATCH_MODIFICATION) { modification m1= get_modification (p1); modification m2= get_modification (p2); modification i2= get_inverse (p2); modification i1= get_inverse (p1); bool r= join (m1, m2, t); bool v= join (i2, i1, clean_apply (p2, clean_apply (p1, t))); if (r && v) p1= patch (m1, i2); return r && v; } if (get_type (p1) == PATCH_COMPOUND && nr_children (p1) > 0 && nr_children (remove_set_cursor (p1)) == 1 && nr_children (p1[0]) == 1) { patch q= p1[0]; bool rf= join (q, p2, t); if (rf) p1= q; return rf; } if (get_type (p2) == PATCH_COMPOUND && nr_children (p2) > 0 && nr_children (remove_set_cursor (p2)) == 1 && nr_children (p2[0]) == 1) { patch q= p2[0]; bool rf= join (p1, q, t); if (rf) { array<patch> a= children (p1); array<patch> b= children (p2); p1= patch (append (a, range (b, 1, N(b)))); } return rf; } return false; }
QString Entry::get_author_short(int number) const { //trim up the author list so the dialog looks nice. might want to //just make this the first author. Could search for the first comma //and delete after that. if ( _author.length() > 25 ) { QString author_short(get_author().section(",",0,number)); author_short+=" et. al"; return author_short; } return get_author(); }
patch remove_set_cursor (patch p) { switch (get_type (p)) { case PATCH_MODIFICATION: if (get_modification (p)->k != MOD_SET_CURSOR) return copy (p); return patch (array<patch> ()); case PATCH_COMPOUND: { array<patch> r; for (int i=0; i<N(p); i++) { patch q= remove_set_cursor (p[i]); r << children (q); } if (N(r) == 1) return r[0]; return patch (r); } case PATCH_BRANCH: case PATCH_BIRTH: return copy (p); case PATCH_AUTHOR: { patch q= remove_set_cursor (p[0]); if (nr_children (q) == 0) return q; else return patch (get_author (p), q); } default: FAILED ("unsupported patch type"); } return p; }
void parse_author_line(char *ident, const struct ident **author, struct time *time) { char *nameend = strchr(ident, '<'); char *emailend = strchr(ident, '>'); const char *name, *email = ""; if (nameend && emailend) *nameend = *emailend = 0; name = chomp_string(ident); if (nameend) email = chomp_string(nameend + 1); if (!*name) name = *email ? email : unknown_ident.name; if (!*email) email = *name ? name : unknown_ident.email; *author = get_author(name, email); /* Parse epoch and timezone */ if (time && emailend && emailend[1] == ' ') { char *secs = emailend + 2; char *zone = strchr(secs, ' '); parse_timesec(time, secs); if (zone && strlen(zone) == STRING_SIZE(" +0700")) parse_timezone(time, zone + 1); } }
///============================================================================================= void GlobalInfo_i::GetGlobalInfoW(GlobalInfo * Info) const { LogTrace(); Info->StructSize = sizeof(*Info); Info->MinFarVersion = get_min_version(); Info->Version = get_version(); Info->Author = get_author(); Info->Description = get_description(); Info->Guid = *get_guid(); Info->Title = get_title(); }
bool operator == (patch p1, patch p2) { if (get_type (p1) != get_type (p2)) return false; switch (get_type (p1)) { case PATCH_MODIFICATION: return get_modification (p1) == get_modification (p2) && get_inverse (p1) == get_inverse (p2); case PATCH_COMPOUND: case PATCH_BRANCH: if (N(p1) != N(p2)) return false; for (int i=0; i<N(p1); i++) if (p1[i] != p2[i]) return false; return true; case PATCH_BIRTH: return get_birth (p1) == get_birth (p2) && get_author (p1) == get_author (p2); case PATCH_AUTHOR: return get_author (p1) == get_author (p2) && p1[0] == p2[0]; default: FAILED ("unsupported patch type"); } return false; }
tm_ostream& operator << (tm_ostream& out, patch p) { switch (get_type (p)) { case PATCH_MODIFICATION: out << get_modification (p) << " -- " << get_inverse (p); break; case PATCH_COMPOUND: if (N(p) == 0) out << "No children"; else { out << "Composite" << INDENT; for (int i=0; i<N(p); i++) out << LF << p[i]; out << UNINDENT; } break; case PATCH_BRANCH: if (N(p) == 0) out << "No branches"; else for (int i=0; i<N(p); i++) { if (i != 0) out << LF; out << "Branch " << i << INDENT << LF << p[i] << UNINDENT; } break; case PATCH_BIRTH: if (get_birth (p)) out << "Birth "; else out << "Death "; out << get_author (p); break; case PATCH_AUTHOR: out << "Author " << get_author (p) << INDENT << LF; out << p[0]; out << UNINDENT; break; default: FAILED ("unsupported patch type"); } return out; }
patch compactify (patch p) { switch (get_type (p)) { case PATCH_COMPOUND: { double a= 0; for (int i=0; i<N(p); i++) if (get_type (p[i]) != PATCH_AUTHOR) a= -1; else if (a == 0) a= get_author (p[i]); else if (a != get_author (p[i])) a= -1; if (a <= 0) { array<patch> r; insert (r, p); if (N(r) == 1) return r[0]; return patch (r); } else { array<patch> r; for (int i=0; i<N(p); i++) insert (r, p[i][0]); if (N(r) == 1) return patch (a, r[0]); return patch (a, patch (r)); } } case PATCH_BRANCH: if (N(p) == 1) return p[0]; else { int i, n= N(p); array<patch> r (n); for (i=0; i<n; i++) r[i]= compactify (p[i]); return patch (true, r); } case PATCH_AUTHOR: return patch (get_author (p), compactify (p[0])); } return p; }
bool parse_blame_info(struct blame_commit *commit, char author[SIZEOF_STR], char *line) { if (match_blame_header("author ", &line)) { string_ncopy_do(author, SIZEOF_STR, line, strlen(line)); } else if (match_blame_header("author-mail ", &line)) { char *end = strchr(line, '>'); if (end) *end = 0; if (*line == '<') line++; commit->author = get_author(author, line); author[0] = 0; } else if (match_blame_header("author-time ", &line)) { parse_timesec(&commit->time, line); } else if (match_blame_header("author-tz ", &line)) { parse_timezone(&commit->time, line); } else if (match_blame_header("summary ", &line)) { string_ncopy(commit->title, line, strlen(line)); } else if (match_blame_header("previous ", &line)) { if (strlen(line) <= SIZEOF_REV) return FALSE; string_copy_rev(commit->parent_id, line); line += SIZEOF_REV; commit->parent_filename = get_path(line); if (!commit->parent_filename) return TRUE; } else if (match_blame_header("filename ", &line)) { commit->filename = get_path(line); return TRUE; } return FALSE; }
patch copy (patch p) { switch (get_type (p)) { case PATCH_MODIFICATION: return patch (copy (get_modification (p)), copy (get_inverse (p))); case PATCH_COMPOUND: case PATCH_BRANCH: { int i, n= N(p); array<patch> r (n); for (i=0; i<N(p); i++) r[i]= copy (p[i]); return patch (get_type (p) == PATCH_BRANCH, r); } case PATCH_BIRTH: return p; case PATCH_AUTHOR: return patch (get_author (p), copy (p[0])); default: FAILED ("unsupported patch type"); } return p; }
bool swap (patch& p1, patch& p2, double a1, double a2) { if (is_nil (p1) || is_nil (p2)) return false; if (get_type (p1) == PATCH_BRANCH) return false; if (get_type (p2) == PATCH_BRANCH) return false; if (get_type (p1) == PATCH_COMPOUND) { int n= N(p1); array<patch> a (n); for (int i=0; i<n; i++) a[i]= p1[i]; for (int i=n-1; i>=0; i--) { if (!swap (a[i], p2, a1, a2)) return false; swap_basic (a[i], p2); } p1= p2; p2= patch (a); return true; } if (get_type (p2) == PATCH_COMPOUND) { int n= N(p2); array<patch> a (n); for (int i=0; i<n; i++) a[i]= p2[i]; for (int i=0; i<n; i++) { if (!swap (p1, a[i], a1, a2)) return false; swap_basic (p1, a[i]); } p2= p1; p1= patch (a); return true; } if (get_type (p1) == PATCH_AUTHOR) { patch s= p1[0]; bool r= swap (s, p2, get_author (p1), a2); p2= patch (get_author (p1), p2); p1= s; return r; } if (get_type (p2) == PATCH_AUTHOR) { patch s= p2[0]; bool r= swap (p1, s, a1, get_author (p2)); p1= patch (get_author (p2), p1); p2= s; return r; } if (get_type (p1) == PATCH_BIRTH) { if (get_author (p1) == a2) return false; return swap_basic (p1, p2); } if (get_type (p2) == PATCH_BIRTH) { if (get_author (p2) == a1) return false; return swap_basic (p1, p2); } if (get_type (p1) == PATCH_MODIFICATION && get_type (p2) == PATCH_MODIFICATION) { modification m1= get_modification (p1); modification m2= get_modification (p2); modification i1= get_inverse (p1); modification i2= get_inverse (p2); bool r= swap (m1, m2); bool v= swap (i2, i1); p1= patch (m1, i1); p2= patch (m2, i2); return r && v && possible_inverse (m1, i1) && possible_inverse (m2, i2); } FAILED ("invalid situation"); return false; }
int main(int argc, char ** argv) { setlocale(LC_MESSAGES, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); try { enum { rdf_ntriple, rdf_turtle, vorbis_comments, metadata_author, metadata_creation, metadata_description, metadata_language, metadata_modification, metadata_publication, metadata_publisher, metadata_rights, metadata_subjects, metadata_title, } output_type = rdf_ntriple; bool print_time = false; bool all_metadata = false; const option_group general_options = { nullptr, { { 't', "time", bind_value(print_time, true), i18n("Time how long it takes to extract the metadata") }, { 'a', "all", bind_value(all_metadata, true), i18n("Extract all available metadata") }, }}; const option_group format_options = { i18n("Metadata Format:"), { { 0, "ntriple", bind_value(output_type, rdf_ntriple), i18n("Output RDF N-Triple metadata statements") }, { 0, "turtle", bind_value(output_type, rdf_turtle), i18n("Output RDF Turtle metadata statements") }, { 0, "vorbis", bind_value(output_type, vorbis_comments), i18n("Output VorbisComment entries") }, }}; const option_group extract_options = { i18n("Metadata Extraction:"), { { 0, "author", bind_value(output_type, metadata_author), i18n("Output the document author") }, { 0, "creation", bind_value(output_type, metadata_creation), i18n("Output the document creation date") }, { 0, "description", bind_value(output_type, metadata_description), i18n("Output the document description") }, { 0, "language", bind_value(output_type, metadata_language), i18n("Output the document language") }, { 0, "modification", bind_value(output_type, metadata_modification), i18n("Output the document modification date") }, { 0, "publication", bind_value(output_type, metadata_publication), i18n("Output the document publication date") }, { 0, "publisher", bind_value(output_type, metadata_publisher), i18n("Output the document publisher") }, { 0, "rights", bind_value(output_type, metadata_rights), i18n("Output the document rights (e.g. copyright)") }, { 0, "subjects", bind_value(output_type, metadata_subjects), i18n("Output the document subjects") }, { 0, "title", bind_value(output_type, metadata_title), i18n("Output the document title") }, }}; const std::initializer_list<const option_group *> options = { &general_options, &format_options, &extract_options, }; const std::initializer_list<const char *> usage = { i18n("metadata [OPTION..] DOCUMENT.."), }; if (!parse_command_line(options, usage, argc, argv)) return 0; cainteoir::stopwatch timer; rdf::graph metadata; if (argc == 0) cainteoir::createDocumentReader(nullptr, metadata, std::string()); else for(int i = 0; i < argc; ++i) { auto reader = cainteoir::createDocumentReader(argv[i], metadata, std::string()); if (!reader) fprintf(stderr, i18n("unsupported document format for file \"%s\"\n"), argv[i]); if (all_metadata) while (reader->read(&metadata)) ; } if (print_time) fprintf(stderr, "Extraction Time: %G\n", timer.elapsed()); const char *filename = (argc == 1) ? argv[0] : nullptr; rdf::uri subject(filename ? filename : std::string(), std::string()); if (!metadata.empty()) switch (output_type) { case vorbis_comments: { const rdf::uri subject = rdf::uri(argv[0], std::string()); std::list<cainteoir::vorbis_comment> comments; cainteoir::add_document_metadata(comments, metadata, subject); for (auto &comment : comments) std::cout << comment.label << "=" << comment.value << std::endl; } break; case metadata_author: fprintf(stdout, "%s\n", get_author(metadata, subject).c_str()); break; case metadata_creation: fprintf(stdout, "%s\n", get_date(metadata, subject, "creation").c_str()); break; case metadata_description: fprintf(stdout, "%s\n", get_dublincore(metadata, subject, "description").c_str()); break; case metadata_language: fprintf(stdout, "%s\n", get_dublincore(metadata, subject, "language").c_str()); break; case metadata_modification: fprintf(stdout, "%s\n", get_date(metadata, subject, "modification").c_str()); break; case metadata_publication: fprintf(stdout, "%s\n", get_date(metadata, subject, "publication").c_str()); break; case metadata_publisher: fprintf(stdout, "%s\n", get_dublincore(metadata, subject, "publisher").c_str()); break; case metadata_rights: fprintf(stdout, "%s\n", get_dublincore(metadata, subject, "rights").c_str()); break; case metadata_subjects: for (auto &item : get_dublincore_items(metadata, subject, "subject")) fprintf(stdout, "%s\n", item.c_str()); break; case metadata_title: fprintf(stdout, "%s\n", get_dublincore(metadata, subject, "title").c_str()); break; default: { (*rdf::create_formatter(std::cout, output_type == rdf_ntriple ? rdf::formatter::ntriple : rdf::formatter::turtle)) << rdf::rdf << rdf::rdfa << rdf::rdfs << rdf::xsd << rdf::xml << rdf::owl << rdf::dc << rdf::dcterms << rdf::dcam << rdf::epub << rdf::epv << rdf::opf << rdf::ocf << rdf::pkg << rdf::media << rdf::onix << rdf::marc << rdf::ncx << rdf::dtb << rdf::smil << rdf::xhtml << rdf::skos << rdf::foaf << rdf::ref << rdf::tts << rdf::iana << rdf::subtag << metadata; } break; } } catch (std::runtime_error &e) { fprintf(stderr, i18n("error: %s\n"), e.what()); return EXIT_FAILURE; } return EXIT_SUCCESS; }