codec_nt.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. #include "volksdata/codec/codec_nt.h"
  2. /// NT codec iterator type.
  3. typedef struct {
  4. const VOLK_Codec * codec; // Codec that generated this iterator.
  5. VOLK_GraphIterator *gr_it; // Graph iterator.
  6. size_t cur; // Internal cursor.
  7. VOLK_rc rc; // Internal return code.
  8. char * str_s, // Temporary string.
  9. * str_p, // Temporary string.
  10. * str_o; // Temporary string.
  11. } VOLK_NTCodecIterator;
  12. /* * * Codec functions. * * */
  13. static VOLK_rc
  14. term_to_nt (const VOLK_Term *term, char **out_p)
  15. {
  16. VOLK_rc rc;
  17. char *out = NULL, *escaped;
  18. const char *metadata = NULL;
  19. size_t buf_len;
  20. char *data = term->data;
  21. switch (term->type) {
  22. case VOLK_TERM_IRIREF:
  23. out = realloc (*out_p, strlen (data) + 3);
  24. if (UNLIKELY (!out)) return VOLK_MEM_ERR;
  25. sprintf (out, "<%s>", data);
  26. if (data != term->data) free (data);
  27. rc = VOLK_OK;
  28. break;
  29. case VOLK_TERM_LITERAL:
  30. // Calculate string length.
  31. if (escape_lit (term->data, &escaped) != VOLK_OK)
  32. return VOLK_ERROR;
  33. buf_len = strlen (escaped) + 3; // Room for "" and terminator
  34. if (
  35. term->datatype != 0
  36. && term->datatype != VOLK_default_datatype
  37. ) {
  38. metadata = term->datatype->data;
  39. buf_len += strlen (metadata) + 4; // Room for ^^<>
  40. }
  41. out = realloc (*out_p, buf_len);
  42. if (UNLIKELY (!out)) return VOLK_MEM_ERR;
  43. sprintf (out, "\"%s\"", escaped);
  44. free (escaped);
  45. // Add datatype.
  46. if (metadata)
  47. out = strcat (strcat (strcat (out, "^^<"), metadata), ">");
  48. rc = VOLK_OK;
  49. break;
  50. case VOLK_TERM_LT_LITERAL:
  51. // Calculate string length.
  52. if (escape_lit (term->data, &escaped) != VOLK_OK)
  53. return VOLK_ERROR;
  54. buf_len = strlen (escaped) + 3; // Room for "" and terminator
  55. if (term->lang[0] != '\0') {
  56. metadata = term->lang;
  57. buf_len += strlen (metadata) + 1; // Room for @
  58. }
  59. out = realloc (*out_p, buf_len);
  60. if (UNLIKELY (!out)) return VOLK_MEM_ERR;
  61. sprintf (out, "\"%s\"", escaped);
  62. free (escaped);
  63. // Add lang.
  64. if (metadata) out = strcat (strcat (out, "@"), metadata);
  65. rc = VOLK_OK;
  66. break;
  67. case VOLK_TERM_BNODE:
  68. out = realloc (*out_p, strlen (term->data) + 3);
  69. if (UNLIKELY (!out)) return VOLK_MEM_ERR;
  70. sprintf (out, "_:%s", term->data);
  71. rc = VOLK_OK;
  72. break;
  73. default:
  74. out = *out_p; // This is considered garbage.
  75. rc = VOLK_PARSE_ERR;
  76. }
  77. *out_p = out;
  78. return rc;
  79. }
  80. static void *
  81. gr_to_nt_init (const VOLK_Graph *gr)
  82. {
  83. VOLK_NTCodecIterator *it;
  84. CALLOC_GUARD (it, NULL);
  85. it->codec = &nt_codec;
  86. it->gr_it = VOLK_graph_lookup(gr, NULL, NULL, NULL, &it->cur);
  87. return it;
  88. }
  89. static VOLK_rc
  90. gr_to_nt_iter (void *h, char **res) {
  91. VOLK_NTCodecIterator *it = h;
  92. VOLK_Triple *spo = NULL;
  93. VOLK_rc rc = VOLK_graph_iter_next (it->gr_it, &spo);
  94. if (rc != VOLK_OK) goto finally;
  95. term_to_nt (spo->s, &it->str_s);
  96. term_to_nt (spo->p, &it->str_p);
  97. term_to_nt (spo->o, &it->str_o);
  98. VOLK_triple_free (spo);
  99. // 3 term separators + dot + newline + terminal = 6
  100. char *tmp = realloc (
  101. *res, strlen (it->str_s) + strlen (it->str_p)
  102. + strlen (it->str_o) + 6);
  103. if (UNLIKELY (!tmp)) {
  104. *res = NULL;
  105. rc = VOLK_MEM_ERR;
  106. goto finally;
  107. }
  108. sprintf (tmp, "%s %s %s .\n", it->str_s, it->str_p, it->str_o);
  109. *res = tmp;
  110. it->cur++;
  111. finally:
  112. return rc;
  113. }
  114. static void
  115. gr_to_nt_done (void *h)
  116. {
  117. VOLK_NTCodecIterator *it = h;
  118. VOLK_graph_iter_free (it->gr_it);
  119. free (it->str_s);
  120. free (it->str_p);
  121. free (it->str_o);
  122. free (it);
  123. }
  124. const VOLK_Codec nt_codec = {
  125. .name = "N-Triples",
  126. .mimetype = "application/n-triples",
  127. .extension = "nt",
  128. .encode_term = term_to_nt,
  129. .encode_graph_init = gr_to_nt_init,
  130. .encode_graph_iter = gr_to_nt_iter,
  131. .encode_graph_done = gr_to_nt_done,
  132. .decode_term = VOLK_nt_parse_term,
  133. .decode_graph = VOLK_nt_parse_doc,
  134. };