コード例 #1
0
static sg_error
sg_vector_clone_into_int(sg_vector **dest, const sg_vector *src){

	/* we can assume that everything is correct from caller perspective */
	size_t i;
	sg_vector *tmp   = ((*dest)->used_count == src->used_count)
			 ? *dest
			 : sg_vector_resize(*dest, src->used_count);
	char const *src_data   = VECTOR_DATA_CONST(src);
	char *dest_data = VECTOR_DATA(tmp);
	size_t item_size = src->info.item_size;

	assert(src->info.copy_fn);

	if( !tmp ) {
		RETURN_FROM_PREVIOUS_ERROR( "vector", sg_get_error() );
	}

	for( i = 0; i < src->used_count; ++i ) {
		sg_error rc = src->info.copy_fn( src_data + i * item_size, dest_data + i * item_size );
		if( SG_ERROR_NONE != rc ) {
			sg_vector_free( tmp );
			*dest = NULL;
			return rc;
		}
	}

	*dest = tmp;

	return SG_ERROR_NONE;
}
コード例 #2
0
ファイル: int_achievement.c プロジェクト: 4144/Hercules
/**
 * Saves changed achievements for a character.
 * @param[in]   char_id     character identifier.
 * @param[out]  cp          pointer to loaded achievements.
 * @param[in]   p           pointer to map-sent character achievements.
 * @return number of achievements saved.
 */
static int inter_achievement_tosql(int char_id, struct char_achievements *cp, const struct char_achievements *p)
{
	StringBuf buf;
	int i = 0, rows = 0;

	nullpo_ret(cp);
	nullpo_ret(p);
	Assert_ret(char_id > 0);

	StrBuf->Init(&buf);
	StrBuf->Printf(&buf, "REPLACE INTO `%s` (`char_id`, `ach_id`, `completed_at`, `rewarded_at`", char_achievement_db);
	for (i = 0; i < MAX_ACHIEVEMENT_OBJECTIVES; i++)
		StrBuf->Printf(&buf, ", `obj_%d`", i);
	StrBuf->AppendStr(&buf, ") VALUES ");

	for (i = 0; i < VECTOR_LENGTH(*p); i++) {
		int j = 0;
		bool save = false;
		struct achievement *pa = &VECTOR_INDEX(*p, i), *cpa = NULL;

		ARR_FIND(0, VECTOR_LENGTH(*cp), j, ((cpa = &VECTOR_INDEX(*cp, j)) && cpa->id == pa->id));

		if (j == VECTOR_LENGTH(*cp))
			save = true;
		else if (memcmp(cpa, pa, sizeof(struct achievement)) != 0)
			save = true;

		if (save) {
			StrBuf->Printf(&buf, "%s('%d', '%d', '%"PRId64"', '%"PRId64"'", rows ?", ":"", char_id, pa->id, (int64)pa->completed_at, (int64)pa->rewarded_at);
			for (j = 0; j < MAX_ACHIEVEMENT_OBJECTIVES; j++)
				StrBuf->Printf(&buf, ", '%d'", pa->objective[j]);
			StrBuf->AppendStr(&buf, ")");
			rows++;
		}
	}

	if (rows > 0 && SQL_ERROR == SQL->QueryStr(inter->sql_handle, StrBuf->Value(&buf))) {
		Sql_ShowDebug(inter->sql_handle);
		StrBuf->Destroy(&buf); // Destroy the buffer.
		return 0;
	}
	// Destroy the buffer.
	StrBuf->Destroy(&buf);

	if (rows) {
		ShowInfo("achievements saved for char %d (total: %d, saved: %d)\n", char_id, VECTOR_LENGTH(*p), rows);

		/* Sync with inter-db acheivements. */
		VECTOR_CLEAR(*cp);
		VECTOR_ENSURE(*cp, VECTOR_LENGTH(*p), 1);
		VECTOR_PUSHARRAY(*cp, VECTOR_DATA(*p), VECTOR_LENGTH(*p));
	}

	return rows;
}
コード例 #3
0
static void
sg_vector_init_new(struct sg_vector *vector, size_t new_count){
	/* Initialise any new items. */
	if (new_count > vector->used_count && vector->info.init_fn != NULL) {
		char *data = VECTOR_DATA(vector);
		size_t i;

		for( i = vector->used_count; i < new_count; ++i ){
			vector->info.init_fn(data + i * vector->info.item_size);
		}
	}

	if (new_count > vector->used_count)
		vector->used_count = new_count;
}
コード例 #4
0
static void
sg_vector_destroy_unused(struct sg_vector *vector, size_t new_count){

	/* Destroy any now-unused items.
	 *
	 * Note that there's an assumption here that making the vector smaller
	 * will never fail; if it did, then we would have destroyed items here
	 * but not actually got rid of the vector pointing to them before the
	 * error return.) */
	if (new_count < vector->used_count && vector->info.destroy_fn != NULL) {
		char *data = VECTOR_DATA(vector);
		size_t i;

		i = vector->used_count;
		while( i > new_count ) {
			--i;
			vector->info.destroy_fn(data + i * vector->info.item_size);
		}
	}

	if (new_count < vector->used_count)
		vector->used_count = new_count;
}
コード例 #5
0
sg_error
sg_vector_compute_diff(sg_vector **dest_vector_ptr, const sg_vector *cur_vector, const sg_vector *last_vector) {

	if( NULL == dest_vector_ptr ) {
		RETURN_WITH_SET_ERROR("vector", SG_ERROR_INVALID_ARGUMENT, "sg_vector_compute_diff(dest_vector_ptr)");
	}

	if( cur_vector ) {
		sg_error rc = sg_vector_clone_into( dest_vector_ptr, cur_vector ); /* proves *dest, cur */
		if( SG_ERROR_NONE != rc ) {
			RETURN_FROM_PREVIOUS_ERROR( "vector", rc );
		}

		if( NULL == *dest_vector_ptr )
			return SG_ERROR_NONE;
		assert( cur_vector->info.compute_diff_fn );
		assert( cur_vector->info.compare_fn );

		TRACE_LOG_FMT("vector",
			      "computing vector diff between vector containing %lu items (cur) and vector containing %lu items (last)",
			      cur_vector->used_count, last_vector ? last_vector->used_count : 0 );

		if( last_vector &&
		    ( SG_ERROR_NONE == sg_prove_vector(last_vector) ) &&
		    ( SG_ERROR_NONE == sg_prove_vector_compat(cur_vector, last_vector ) ) ) {
			size_t i, item_size = last_vector->info.item_size;
			unsigned matched[(cur_vector->used_count / (8 * sizeof(unsigned))) + 1];

			char *diff = VECTOR_DATA(*dest_vector_ptr);
			char const *last = VECTOR_DATA_CONST(last_vector);

			memset( matched, 0, sizeof(matched) );

			for( i = 0; i < (*dest_vector_ptr)->used_count; ++i ) {
				size_t j;
				for( j = 0; j < last_vector->used_count; ++j ) {
					if( BIT_ISSET(matched, j) ) /* already matched? */
						continue;

					if (last_vector->info.compare_fn(last + j * item_size, diff + i * item_size) == 0) {
						BIT_SET(matched, j);
						last_vector->info.compute_diff_fn(last + j * item_size, diff + i * item_size);
					}
				}

				if( j == last_vector->used_count ) {
					/* We have lost an item since last time - skip */
				}
			}

			/* XXX append the items lost since last run? */
		}
	}
	else {
		sg_vector_free(*dest_vector_ptr);
		*dest_vector_ptr = NULL;

		RETURN_WITH_SET_ERROR("vector", SG_ERROR_INVALID_ARGUMENT, "sg_vector_compute_diff(cur_vector)");
	}

	return SG_ERROR_NONE;
}