📄 meta.c
字号:
/* This file is part of GNUnet. (C) 2003, 2004, 2005, 2006, 2008 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.*//** * @file util/containers/meta.c * @brief Storing of meta data * @author Christian Grothoff */#include "platform.h"#include "gnunet_util.h"#include <extractor.h>#include <zlib.h>#define EXTRA_CHECKS ALLOW_EXTRA_CHECKStypedef struct{ EXTRACTOR_KeywordType type; char *data;} Item;/** * Meta data to associate with a file, directory or namespace. */typedef struct GNUNET_MetaData{ unsigned int itemCount; Item *items;} MetaData;/** * Create a fresh MetaData token. */MetaData *GNUNET_meta_data_create (){ MetaData *ret; ret = GNUNET_malloc (sizeof (MetaData)); ret->items = NULL; ret->itemCount = 0; return ret;}/** * Free meta data. */voidGNUNET_meta_data_destroy (MetaData * md){ int i; if (md == NULL) return; for (i = 0; i < md->itemCount; i++) GNUNET_free (md->items[i].data); GNUNET_array_grow (md->items, md->itemCount, 0); GNUNET_free (md);}/** * Add the current time as the publication date * to the meta-data. */voidGNUNET_meta_data_add_publication_date (MetaData * md){ char *dat; GNUNET_Int32Time t; GNUNET_get_time_int32 (&t); GNUNET_meta_data_delete (md, EXTRACTOR_PUBLICATION_DATE, NULL); dat = GNUNET_int32_time_to_string (&t); GNUNET_meta_data_insert (md, EXTRACTOR_PUBLICATION_DATE, dat); GNUNET_free (dat);}/** * Extend metadata. * @return GNUNET_OK on success, GNUNET_SYSERR if this entry already exists */intGNUNET_meta_data_insert (MetaData * md, EXTRACTOR_KeywordType type, const char *data){ int idx; char *p; GNUNET_GE_ASSERT (NULL, data != NULL); for (idx = 0; idx < md->itemCount; idx++) { if ((md->items[idx].type == type) && (0 == strcmp (md->items[idx].data, data))) return GNUNET_SYSERR; } idx = md->itemCount; GNUNET_array_grow (md->items, md->itemCount, md->itemCount + 1); md->items[idx].type = type; md->items[idx].data = p = GNUNET_strdup (data); /* change OS native dir separators to unix '/' and others to '_' */ if (type == EXTRACTOR_FILENAME) { while (*p != '\0') { if (*p == DIR_SEPARATOR) *p = '/'; else if (*p == '\\') *p = '_'; p++; } } return GNUNET_OK;}/** * Remove an item. * @return GNUNET_OK on success, GNUNET_SYSERR if the item does not exist in md */intGNUNET_meta_data_delete (MetaData * md, EXTRACTOR_KeywordType type, const char *data){ int idx; int ret = GNUNET_SYSERR; for (idx = 0; idx < md->itemCount; idx++) { if ((md->items[idx].type == type) && ((data == NULL) || (0 == strcmp (md->items[idx].data, data)))) { GNUNET_free (md->items[idx].data); md->items[idx] = md->items[md->itemCount - 1]; GNUNET_array_grow (md->items, md->itemCount, md->itemCount - 1); if (data == NULL) { ret = GNUNET_OK; continue; } return GNUNET_OK; } } return ret;}/** * Iterate over MD entries, excluding thumbnails. * * @return number of entries */intGNUNET_meta_data_get_contents (const MetaData * md, GNUNET_MetaDataProcessor iterator, void *closure){ int i; int sub; sub = 0; for (i = md->itemCount - 1; i >= 0; i--) { if (!EXTRACTOR_isBinaryType (md->items[i].type)) { if ((iterator != NULL) && (GNUNET_OK != iterator (md->items[i].type, md->items[i].data, closure))) return GNUNET_SYSERR; } else sub++; } return md->itemCount - sub;}/** * Iterate over MD entries * * @return number of entries */char *GNUNET_meta_data_get_by_type (const MetaData * md, EXTRACTOR_KeywordType type){ int i; for (i = md->itemCount - 1; i >= 0; i--) if (type == md->items[i].type) return GNUNET_strdup (md->items[i].data); return NULL;}/** * Iterate over MD entries * * @return number of entries */char *GNUNET_meta_data_get_first_by_types (const MetaData * md, ...){ char *ret; va_list args; EXTRACTOR_KeywordType type; ret = NULL; va_start (args, md); while (1) { type = va_arg (args, EXTRACTOR_KeywordType); if (type == -1) break; ret = GNUNET_meta_data_get_by_type (md, type); if (ret != NULL) break; } va_end (args); return ret;}/** * Get a thumbnail from the meta-data (if present). * * @param thumb will be set to the thumbnail data. Must be * freed by the caller! * @return number of bytes in thumbnail, 0 if not available */size_tGNUNET_meta_data_get_thumbnail (const struct GNUNET_MetaData * md, unsigned char **thumb){ char *encoded; int ret; size_t size; encoded = GNUNET_meta_data_get_by_type (md, EXTRACTOR_THUMBNAIL_DATA); if (encoded == NULL) return 0; if (strlen (encoded) == 0) { GNUNET_free (encoded); return 0; /* invalid */ } *thumb = NULL; ret = EXTRACTOR_binaryDecode (encoded, thumb, &size); GNUNET_free (encoded); if (ret != 0) return 0; return size;}/** * Duplicate MetaData. */MetaData *GNUNET_meta_data_duplicate (const MetaData * md){ int i; MetaData *ret; if (md == NULL) return NULL; ret = GNUNET_meta_data_create (); for (i = md->itemCount - 1; i >= 0; i--) GNUNET_meta_data_insert (ret, md->items[i].type, md->items[i].data); return ret;}/** * Extract meta-data from a file. * * @return GNUNET_SYSERR on error, otherwise the number * of meta-data items obtained */intGNUNET_meta_data_extract_from_file (struct GNUNET_GE_Context *ectx, MetaData * md, const char *filename, EXTRACTOR_ExtractorList * extractors){ EXTRACTOR_KeywordList *head; EXTRACTOR_KeywordList *pos; int ret; if (filename == NULL) return GNUNET_SYSERR; if (extractors == NULL) return 0; head = EXTRACTOR_getKeywords (extractors, filename); head = EXTRACTOR_removeDuplicateKeywords (head, EXTRACTOR_DUPLICATES_REMOVE_UNKNOWN); pos = head; ret = 0; while (pos != NULL) { if (GNUNET_OK == GNUNET_meta_data_insert (md, pos->keywordType, pos->keyword)) ret++; pos = pos->next; } EXTRACTOR_freeKeywords (head); return ret;}static unsigned inttryCompression (char *data, unsigned int oldSize){ char *tmp; uLongf dlen;#ifdef compressBound dlen = compressBound (oldSize);#else dlen = oldSize + (oldSize / 100) + 20; /* documentation says 100.1% oldSize + 12 bytes, but we should be able to overshoot by more to be safe */#endif tmp = GNUNET_malloc (dlen); if (Z_OK == compress2 ((Bytef *) tmp, &dlen, (const Bytef *) data, oldSize, 9)) { if (dlen < oldSize) { memcpy (data, tmp, dlen); GNUNET_free (tmp); return dlen; } } GNUNET_free (tmp); return oldSize;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -