示例#1
0
文件: api.c 项目: deadbits/ccan
int main(void)
{
	struct permutation *pi;
	int single = 12345;
	char pair[] = { 'P', 'Q' };
	uint16_t triple[] = {7, 9, 1000};
	word four[] = {"ZERO", "ONE", "TWO", "THREE"};
	int i;

	plan_tests(2 * permutation_count(1) + 1
		   + 2 * permutation_count(2) + 1
		   + 2 * permutation_count(3) + 1
		   + 2 * permutation_count(4) + 1
		   + MAX_ITEMS + 1);

	/* One */
	pi = permutation_new(1);
	CHECK_ORDER(&single, int, 12345);
	ok1(!permutation_change_array(pi, &single, sizeof(single)));
	CHECK_ORDER(&single, int, 12345);
	free(pi);

	/* Pair */
	pi = PERMUTATION_NEW(pair);
	CHECK_ORDER(pair, char, 'P', 'Q');
	PERMUTE(pi, pair);
	CHECK_ORDER(pair, char, 'Q', 'P');
	ok1(!PERMUTATION_CHANGE_ARRAY(pi, pair));
	CHECK_ORDER(pair, char, 'Q', 'P');
	free(pi);

	/* Triple */
	pi = PERMUTATION_NEW(triple);
	CHECK_ORDER(triple, uint16_t, 7, 9, 1000);
	PERMUTE(pi, triple);
	CHECK_ORDER(triple, uint16_t, 7, 1000, 9);
	PERMUTE(pi, triple);
	CHECK_ORDER(triple, uint16_t, 1000, 7, 9);
	PERMUTE(pi, triple);
	CHECK_ORDER(triple, uint16_t, 1000, 9, 7);
	PERMUTE(pi, triple);
	CHECK_ORDER(triple, uint16_t, 9, 1000, 7);
	PERMUTE(pi, triple);
	CHECK_ORDER(triple, uint16_t, 9, 7, 1000);
	ok1(!PERMUTATION_CHANGE_ARRAY(pi, triple));
	CHECK_ORDER(triple, uint16_t, 9, 7, 1000);
	free(pi);

	/* Four */
	pi = PERMUTATION_NEW(four);
	CHECK_ORDER(four, word, "ZERO", "ONE", "TWO", "THREE");
	PERMUTE(pi, four);
	CHECK_ORDER(four, word, "ZERO", "ONE", "THREE", "TWO");
	PERMUTE(pi, four);
	CHECK_ORDER(four, word, "ZERO", "THREE", "ONE", "TWO");
	PERMUTE(pi, four);
	CHECK_ORDER(four, word, "THREE", "ZERO", "ONE", "TWO");
	PERMUTE(pi, four);
	CHECK_ORDER(four, word, "THREE", "ZERO", "TWO", "ONE");
	PERMUTE(pi, four);
	CHECK_ORDER(four, word, "ZERO", "THREE", "TWO", "ONE");
	PERMUTE(pi, four);
	CHECK_ORDER(four, word, "ZERO", "TWO", "THREE", "ONE");
	PERMUTE(pi, four);
	CHECK_ORDER(four, word, "ZERO", "TWO", "ONE", "THREE");
	PERMUTE(pi, four);
	CHECK_ORDER(four, word, "TWO", "ZERO", "ONE", "THREE");
	PERMUTE(pi, four);
	CHECK_ORDER(four, word, "TWO", "ZERO", "THREE", "ONE");
	PERMUTE(pi, four);
	CHECK_ORDER(four, word, "TWO", "THREE", "ZERO", "ONE");
	PERMUTE(pi, four);
	CHECK_ORDER(four, word, "THREE", "TWO", "ZERO", "ONE");
	PERMUTE(pi, four);
	CHECK_ORDER(four, word, "THREE", "TWO", "ONE", "ZERO");
	PERMUTE(pi, four);
	CHECK_ORDER(four, word, "TWO", "THREE", "ONE", "ZERO");
	PERMUTE(pi, four);
	CHECK_ORDER(four, word, "TWO", "ONE", "THREE", "ZERO");
	PERMUTE(pi, four);
	CHECK_ORDER(four, word, "TWO", "ONE", "ZERO", "THREE");
	PERMUTE(pi, four);
	CHECK_ORDER(four, word, "ONE", "TWO", "ZERO", "THREE");
	PERMUTE(pi, four);
	CHECK_ORDER(four, word, "ONE", "TWO", "THREE", "ZERO");
	PERMUTE(pi, four);
	CHECK_ORDER(four, word, "ONE", "THREE", "TWO", "ZERO");
	PERMUTE(pi, four);
	CHECK_ORDER(four, word, "THREE", "ONE", "TWO", "ZERO");
	PERMUTE(pi, four);
	CHECK_ORDER(four, word, "THREE", "ONE", "ZERO", "TWO");
	PERMUTE(pi, four);
	CHECK_ORDER(four, word, "ONE", "THREE", "ZERO", "TWO");
	PERMUTE(pi, four);
	CHECK_ORDER(four, word, "ONE", "ZERO", "THREE", "TWO");
	PERMUTE(pi, four);
	CHECK_ORDER(four, word, "ONE", "ZERO", "TWO", "THREE");
	ok1(!PERMUTATION_CHANGE_ARRAY(pi, four));
	CHECK_ORDER(four, word, "ONE", "ZERO", "TWO", "THREE");
	free(pi);

	for (i = 0; i <= MAX_ITEMS; i++) {
		uint64_t nperms = 1;

		diag("Counting permutations of %d\n", i);

		pi = permutation_new(i);
		while (permutation_change(pi))
			nperms++;

		ok(nperms == permutation_count(i),
		   "%"PRId64" permutations of %d (%d! == %lld)",
		   nperms, i, i, permutation_count(i));
		free(pi);
	}

	/* This exits depending on whether all tests passed */

	return exit_status();
}
/**
 * @internal
 * Decode a ordered register list from the 10 bit register encoding as defined by the CFE format.
 *
 * @param permutation The 10-bit encoded register list.
 * @param count The number of registers to decode from @a permutation.
 * @param registers On return, the ordered list of decoded register values. These values must correspond to the CFE
 * register values, <em>not</em> the register values as defined in the PLCrashReporter thread state APIs.
 *
 * @warning This API is unlikely to be useful outside the CFE encoder implementation, and should not generally be used.
 * Callers must be careful to pass only literal register values defined in the CFE format (eg, values 1-6).
 */
void apigee_plcrash_async_cfe_register_decode (uint32_t permutation, uint32_t count, uint32_t registers[]) {
    PLCF_ASSERT(count <= PLCRASH_ASYNC_CFE_SAVED_REGISTER_MAX);
    
    /*
     * Each register is encoded by mapping the values to a 10-bit range, and then further sub-ranges within that range,
     * with a subrange allocated to each position. See the encoding function for full documentation.
     */
	int permunreg[PLCRASH_ASYNC_CFE_SAVED_REGISTER_MAX];
#define PERMUTE(pos, factor) do { \
permunreg[pos] = permutation/factor; \
permutation -= (permunreg[pos]*factor); \
} while (0)
    
    PLCF_ASSERT(PLCRASH_ASYNC_CFE_SAVED_REGISTER_MAX == 6);
	switch (count) {
		case 6:
            PERMUTE(0, 120);
            PERMUTE(1, 24);
            PERMUTE(2, 6);
            PERMUTE(3, 2);
            PERMUTE(4, 1);
            
            /*
             * There are 6 elements in the list, 6 possible values for each element, and values may not repeat. The
             * value of the last element can be derived from the values previously seen (and due to the positional
             * renumbering performed, the value of the last element will *always* be 0).
             */
            permunreg[5] = 0;
			break;
		case 5:
            PERMUTE(0, 120);
            PERMUTE(1, 24);
            PERMUTE(2, 6);
            PERMUTE(3, 2);
            PERMUTE(4, 1);
			break;
		case 4:
            PERMUTE(0, 60);
            PERMUTE(1, 12);
            PERMUTE(2, 3);
            PERMUTE(3, 1);
			break;
		case 3:
            PERMUTE(0, 20);
            PERMUTE(1, 4);
            PERMUTE(2, 1);
			break;
		case 2:
            PERMUTE(0, 5);
            PERMUTE(1, 1);
			break;
		case 1:
            PERMUTE(0, 1);
			break;
	}
#undef PERMUTE
    
	/* Recompute the actual register values based on the position-relative values. */
	bool position_used[PLCRASH_ASYNC_CFE_SAVED_REGISTER_MAX+1] = { 0 };
    
	for (uint32_t i = 0; i < count; ++i) {
		int renumbered = 0;
		for (int u = 1; u < 7; u++) {
			if (!position_used[u]) {
				if (renumbered == permunreg[i]) {
					registers[i] = u;
					position_used[u] = true;
					break;
				}
				renumbered++;
			}
		}
	}
}