I need help converting a number string to a SQL_NUMERIC_STRUCT value to use decimal and numeric database data types. The SQL_NUMERIC_STRUCT value is a 16-byte hexadecimal unsigned integer. For example, I have a string "12312312899012312890522341231231232198", that contains 38 digits (maximum for SQL SERVER decimal or numeric data types). In other languages such a c# there is a built-in conversion function, but my Visual studio 2019 does not allow me to directly use 128-bit integers in the C++ environment. The Microsoft help page offers example with a small,2-byte integer, unfortunately.
I have found a solution.
bool ConvertToNumericStruct (char* s, SQL_NUMERIC_STRUCT* v){
int sc = (int)strlen(s), scale = 0, i,y, z;
char c, p = 0, d; bool minus = false;
int _tmp, x, carryover;
memset(v->val, 0, 16);
for (i = 0; i < sc; i++) {
c = s[i];
if (i == 0 && c == '-')minus = true;
else if (c == '.') { if (scale == 0)scale = sc - i - 1; else return false; }
else if (c < '0' || c>'9') return false;
else
{
if (p > 38) return false;
d = c - 48;
_tmp = 0;
carryover = d;
y = 0; z = 0;
for (x = sc - 1; x > -1; x--)
{
if (y % 2 == 1)
{
_tmp = (v->val[z] >> 4) * 10 + carryover;
v->val[z] &= 0x0F;
v->val[z] |= ((_tmp % 16) << 4 & 0xF0);
z++;
if (z > 15) break;
}
else {
_tmp = (v->val[z] & 0x0F) * 10 + carryover;
v->val[z] &= 0Xf0;
v->val[z] |= ((_tmp % 16) & 0x0F);
}
y++;
carryover = _tmp / 16;
}
p++;
}
}
v->precision = p;
v->scale = scale;
if (minus) v->sign = 0; else v->sign = 1;
return true;}
If you want to insert data defined by decimal or numeric into database such as MySql via UnixODBC with the function SQLBindParameter,you can just use SQL_C_CHAR for fCtype and SQL_CHAR for fSqltype with a char-string buffer.No need to convert.That would be done implicitly.
Related
I need size of initialized data stored in an integer variable.
Suppose.
u32 var = 0x0; should return 0
u32 var = 0x12; should return 1
u32 var = 0x1234; should return 2
u32 var = 0x123456; should return 3
u32 var = 0x12345678; should return 4
A log2(x) will give you the exponent of a binary value. Some C implementations have this function already built-in. If not, there are some alternative here: How to write log base(2) in c/c++
The resulting exponent can be divided and rounded in order to give the values you need.
A first attempt (untested) is:
int byteCount(const int x)
{
if (x == 0) return 0; /* Avoid error */
return (int)trunc((log10(x)/log10(2))/8+1);
}
UPDATE:
It seems my code is being taken literally. Here is an optimized version:
int byteCount(const u32 x)
{
if (x == 0) return 0; /* Avoid error */
return (int)trunc((log10(x)/0.301029995663981)/8+1);
}
Do you need to count number of non-zero bytes?
u8 countNonZeroBytes(u32 n) {
u8 result = n == 0 ? 0 : 1;
while (n >> 8 != 0) {
result++;
n = n >> 8;
}
return result;
}
This should give you the answer as per your requirement.
u8 CountNonZeroBytes(u32 n) {
u32 mask = 0xFF;
u8 i, result = 0;
for (i = 0; i < sizeof(n); i++) {
if (mask & n)
result++;
mask = mask << 8;
}
return result;
}
Here is a version of the "leading zeroes" approach to log2 that doesn't use floating point. The optimizer will do loop unrolling, so it's equivalent to the "four compare" version. It is 4x faster than the floating point version.
u32
bytecnt(u32 val)
{
int bitno;
u32 msk;
u32 bycnt;
bycnt = 0;
for (bitno = 24; bitno >= 0; bitno -= 8) {
msk = 0xFF << bitno;
if (val & msk) {
bycnt = bitno / 8;
bycnt += 1;
break;
}
}
return bycnt;
}
Here is a test program that compares the two algorithms [Note that I'm using Jaime's floating point version for comparison]:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
typedef unsigned int u32;
#define RATIO \
do { \
if (tvslow > tvfast) \
ratio = tvslow / tvfast; \
else \
ratio = tvfast / tvslow; \
printf("%.3fx\n",ratio); \
} while (0)
int opt_f;
// _tvgetf -- get timestamp
double
_tvgetf(void)
{
struct timespec ts;
double val;
#if 1
clock_gettime(CLOCK_REALTIME,&ts);
#else
clock_gettime(CLOCK_MONOTONIC_RAW,&ts);
#endif
val = ts.tv_nsec;
val /= 1e9;
val += ts.tv_sec;
return val;
}
u32
bytecnt(u32 val)
{
int bitno;
u32 msk;
u32 bycnt;
bycnt = 0;
for (bitno = 24; bitno >= 0; bitno -= 8) {
msk = 0xFF << bitno;
if (val & msk) {
bycnt = bitno / 8;
bycnt += 1;
break;
}
}
return bycnt;
}
u32
bytecnt2(u32 val)
{
u32 bycnt;
do {
if (val & (0xFF << 24)) {
bycnt = 4;
break;
}
if (val & (0xFF << 16)) {
bycnt = 3;
break;
}
if (val & (0xFF << 8)) {
bycnt = 2;
break;
}
if (val & (0xFF << 0)) {
bycnt = 1;
break;
}
bycnt = 0;
} while (0);
return bycnt;
}
int byteCount(const int x)
{
if (x == 0) return 0; /* Avoid error */
return (int)trunc((log10(x)/log10(2))/8+1);
}
u32 byteCount2(u32 x)
{
if (x == 0) return 0; /* Avoid error */
return (u32)trunc((log10(x)/log10(2))/8+1);
}
static double l2 = 0;
u32 byteCount3(u32 x)
{
if (x == 0) return 0; /* Avoid error */
return (u32)trunc((log10(x)/l2)/8+1);
}
u32 byteCount4(u32 x)
{
if (x == 0) return 0; /* Avoid error */
return (u32)trunc((log10(x)/0.301029995663981)/8+1);
}
void
test(u32 val)
{
u32 bicnt;
u32 lgcnt;
bicnt = bytecnt(val);
lgcnt = byteCount2(val);
if (bicnt != lgcnt) {
printf("%8.8X: bicnt=%8.8X lgcnt=%8.8X\n",
val,bicnt,lgcnt);
exit(1);
}
}
double
timeit(u32 (*proc)(u32),const char *who)
{
double tvbeg;
double tvdif;
double tvper;
int trycnt;
int trymax;
u32 val;
trymax = 1000000;
trymax *= 10;
tvbeg = _tvgetf();
for (trycnt = 1; trycnt < trymax; ++trycnt) {
for (val = 1; val != 0; val <<= 1)
proc(val);
}
tvdif = _tvgetf();
tvdif -= tvbeg;
tvper = tvdif;
tvper /= trymax;
tvper /= 32;
printf("%.9f %.9f -- %s\n",tvdif,tvper,who);
return tvdif;
}
int
main(int argc,char **argv)
{
char *cp;
u32 val;
double tvfast;
double tvslow;
double ratio;
--argc;
++argv;
l2 = log10(2);
for (; argc > 0; --argc, ++argv) {
cp = *argv;
if (*cp != '-')
break;
switch (cp[1]) {
case 'f':
opt_f = 1;
break;
}
}
// do quick validity test
printf("quick validity test ...\n");
test(0);
for (val = 1; val != 0; val <<= 1)
test(val);
// speed tests
printf("speed tests ...\n");
tvfast = timeit(bytecnt2,"bytecnt2");
tvslow = timeit(bytecnt,"bytecnt");
RATIO;
tvslow = timeit(byteCount2,"byteCount2");
RATIO;
tvslow = timeit(byteCount3,"byteCount3");
RATIO;
tvslow = timeit(byteCount4,"byteCount4");
RATIO;
// do full validity test
if (opt_f) {
for (val = 1; val != 0; ++val)
test(val);
}
return 0;
}
Here is the test output:
quick validity test ...
speed tests ...
1.180300474 0.000000004 -- bytecnt2
1.363260031 0.000000004 -- bytecnt
1.155x
6.759670734 0.000000021 -- byteCount2
5.727x
6.653460503 0.000000021 -- byteCount3
5.637x
6.636421680 0.000000021 -- byteCount4
5.623x
UPDATE:
my byteCount proposal is not optimized, for the sake of clarity. For example, you can convert log10(2) into a constant. I think that would have a noticeable increase of performance.
I've updated the test program to incorporate the changes.
But, the optimizer had already eliminated the log10(2) in your original code (i.e. only one call to log10), so hand coding it had little to no effect.
Several others did similar loop implementations for number of zero bytes [which I don't believe is what OP wanted, based on the "sizeof" phrase].
It turns out that the fastest version is also the simplest, most boring, and [IMO] most straightforward. This is something I added: bytecnt2, which is the "four compares" suggested by Paul R.
Doing floating point would be fine with better [or comparable] performance. I'd give it a pass even at 2x [FYI, before getting the results, I assumed that they would be ballpark (e.g. within 10%)].
But, the F.P. implementation is also less straightforward for OP's intended result.
IMO, something that is 4x slower [and more complicated] is a red flag. Not just tweaking, but indicates the approach is incorrect. Taking an int and converting it into a float [and back again], using some relatively heavyweight functions, for something that simple bit shifting/masking will accomplish.
If you don't mind use gcc extensions, this is a very good solution:
by the way you should be more clear in your question. Your terminology is confusing. Both "size" and "initialized" are used outside their established meaning.
Extra extra safe/portable: (probably not needed):
size_t leading_zeroes(uint32_t v)
{
if (v == 0) // __builtin_clz is undefined for 0
return sizeof(uint32_t) * CHAR_BIT;
return __builtin_clz(v);
}
size_t trailing_bytes(uint32_t v)
{
return sizeof(uint32_t) - leading_zeroes(v) / CHAR_BIT;
}
Simpler version:
size_t leading_zeroes(uint32_t v)
{
if (v == 0) // __builtin_clz is undefined for 0
return 32;
return __builtin_clz(v);
}
size_t trailing_bytes(uint32_t v)
{
return 4 - leading_zeroes(v) / 8;
}
I'm trying to read up on constraint satisfaction problems and trying to code them to solve a few sample problems. I came across http://rosettacode.org/wiki/Zebra_puzzle#C.2B.2B to solve the classic zebra puzzle. In the C code given in rosetta code website, There was this following function. I have given only a few lines from it. I didn't know what the purpose of the two if statements is and how they worked.
Can someone explain it?
int checkHouses(int ha[5][5])
{
...
int c_add = 0, c_or = 0;
int m_add = 0, m_or = 0;
int d_add = 0, d_or = 0;
int a_add = 0, a_or = 0;
int s_add = 0, s_or = 0;
for (int i = 0; i < 5; i++) {
// Uniqueness tests.
if (ha[i][C] >= 0) {
c_add += (1 << ha[i][C]);
c_or |= (1 << ha[i][C]);
}
if (ha[i][M] >= 0) {
m_add += (1 << ha[i][M]);
m_or |= (1 << ha[i][M]);
}
if (ha[i][D] >= 0) {
d_add += (1 << ha[i][D]);
d_or |= (1 << ha[i][D]);
}
if (ha[i][A] >= 0) {
a_add += (1 << ha[i][A]);
a_or |= (1 << ha[i][A]);
}
if (ha[i][S] >= 0) {
s_add += (1 << ha[i][S]);
s_or |= (1 << ha[i][S]);
}
}
if ((c_add != c_or) || (m_add != m_or) || (d_add != d_or)
|| (a_add != a_or) || (s_add != s_or)) {
return Invalid;
}
if ((c_add != 0b11111) || (m_add != 0b11111) || (d_add != 0b11111)
|| (a_add != 0b11111) || (s_add != 0b11111)) {
return Underfull;
}
The comment actually explains it: they are verifying that there are no duplicate values between ha[0..4][x] for each value of x.
As to how it is doing it: each value is assigned a bit position, such that 1<<ha[i][x] will yield a number with only the bit in that position set. x_or will be the OR of those values, while x_add is their sum. If there is a duplicate value, it will not have an effect on x_or (that bit is already set), but will on x_add; hence, they will be different.
I am currently working on a program where I need to have this kind of output:
I have to output the binary in IEEE 754 of 64 and 32-bit numbers in C.
I already have the double and single floating point approximation, but I'm having trouble finding out how to output the binary of these in IEEE 754 notation, and color code them as well. Any thoughts/solutions on how to do this would be much appreciated.
This does not guarantee the correct answer if the underlying machine is something esoteric, however:
float f = 3.14;
uint32_t u;
memcpy(&u, &f, sizeof u);
for (int i = 31; i >= 0; i--)
putchar('0' + ((u >> i) & 1));
I decided to take the opportunity to refresh my memory of the IEE-754 floating-point standard. Below is a mashup I made for displaying a string in its single-precision floating point number representation, though it is easily modified for the double-precision format.
The code won't work with +Inf, -Inf, NaN, trailing-zero, fractionless and leftout-zero (.fraction instead of 0.fraction or integer. instead of integer.0) numbers, it's just supposed to give the general idea of how to do what you want to do in a portable and well-defined (and highly entertaining) way.
#define EXPLEN 8 /* Fraction length for single-precision */
#define SIGNIFLEN 23 /* Significand length for single-precision */
#define EXPBIAS 0x7F /* Exponent bias for single-precision */
#define BITLEN (1 + EXPLEN + SIGNIFLEN)
BOOL strToFloat(char *floatStr, char *outBits, size_t outBitsLen){
unsigned long int floatStrLength = strlen(floatStr), intPart, fracPart, intPartHighestBit = 1, fracPartLength,
fracPartPowTen = 1, temp;
char roundBit, stickyBit, expPart = 0;
int i;
/* Get sign */
if (floatStr[0] == '-'){
floatStr++;
outBits[0] = '1';
} else {
if (floatStr[0] == '+')
floatStr++;
outBits[0] = '0';
}
if (sscanf(floatStr, "%lu.%lu", &intPart, &fracPart) == EOF ||
outBitsLen < BITLEN + 1)
return FALSE; /* Failure */
/* Get integer part */
temp = intPart;
while (temp >>= 1)
intPartHighestBit <<= 1;
for (i = EXPLEN + 1; i < BITLEN && (intPartHighestBit >>= 1); i++, expPart++)
outBits[i] = !!(intPart & intPartHighestBit) + '0';
/* Get fraction part */
fracPartLength = strlen(strchr(floatStr, '.'));
while (--fracPartLength)
fracPartPowTen *= 10;
if (!intPart && i == EXPLEN + 1)
if (fracPart > 0){
i--;
expPart--;
} else
expPart = -EXPBIAS;
for (; i < BITLEN; fracPart = (fracPart << 1) % fracPartPowTen){
outBits[i] = !!((fracPart << 1) - (fracPart << 1) % fracPartPowTen) + '0';
if (outBits[i] == '0' && i == EXPLEN) /* Start writing only after first set bit is reached if number <1 */
expPart--;
else
i++;
}
/* Get exponent part */
for (i = EXPLEN, expPart += EXPBIAS; i > 0; i--, expPart >>= 1)
outBits[i] = (unsigned char)expPart % 2 + '0';
/* Round fraction part (to-nearest mode) */
if ((fracPart << 1) - (fracPart << 1) % fracPartPowTen){ /* Guard bit set, rounding needed */
fracPart = (fracPart << 1) % fracPartPowTen;
roundBit = !!((fracPart << 1) - (fracPart << 1) % fracPartPowTen);
fracPart = (fracPart << 1) % fracPartPowTen;
stickyBit = !!((fracPart << 1) - (fracPart << 1) % fracPartPowTen);
if (roundBit || stickyBit || outBits[BITLEN - 1] == '0'){ /* Round up, add 1 to mantissa (and to exponent
if mantissa overflows)*/
for (i = BITLEN - 1; outBits[i] == '1' && i > 0; i--)
outBits[i] = '0';
outBits[i] = '1';
}
}
outBits[BITLEN] = '\0';
return TRUE; /* Success */
}
Example usage:
char *str = "-3.14",
*outFloat = malloc(BITLEN + 1);
if (outFloat && strToFloat(str, outFloat, BITLEN + 1))
printf("%s", outFloat);
outputs
11000000010010001111010111000011
UPDATE: did my best to
remove magic numbers so it's easier to change this to use the double-precision format;
fix (I think) the rounding overflows;
fix zeroes issues;
refactor the code for setting the sign bit; and I also fiddled with some types, both per #Segmented's request in the comments.
Well, that was lots of fun! If you see any errors or space for improvement in this (rather hasty) code, please post it!
Given an unsigned integer a (less or equal to 1024), I need to find a number p which satisfy the following condition :
lowest p >= a
p is a power of 2
I'm sure there is a better solution, using bitwise operators.
Have you a better solution ?
unsigned int closest_pow2(unsigned int a)
{
if (a == 0 || a > 1024) return 0; //error, never happen
if (a == 1) return 1;
if (a == 2) return 2;
if (a <= 4) return 4;
if (a <= 8) return 8;
if (a <= 16) return 16;
if (a <= 32) return 32;
if (a <= 64) return 64;
if (a <= 128) return 128;
if (a <= 256) return 256;
if (a <= 512) return 512;
if (a <= 1024) return 1024;
}
The following does it without the relatively expensive conditional statements or loops:
unsigned next_power_of_two(unsigned int x) {
x = x - 1;
x = x | (x >> 1);
x = x | (x >> 2);
x = x | (x >> 4);
x = x | (x >> 8);
return x + 1;
}
If this is a trick question (since I see no requirement that you must find the lowest p >= a), then this is a solution:
return 1024;
Stylistically, I prefer not to use bitwise operators because they tend to make the code harder to read--they encapsulate the bit structure much less than other types of commands. Even without bitwise operators, the code could be made much more concise:
int pow = 1;
if (a == 0 || a > 1024) return 0;
while (pow < 2000) {
if (a <= pow) return pow;
pow *= 2;
}
If you don't want to hardcode a number larger than the largest number of bits (probably a better coding practice anyway), you can write as follows:
final int MAX_POSSIBLE_BIT_VALUE = 1024;
unsigned int closest_pow2(unsigned int a) {
if (a == 0 || a > MAX_POSSIBLE_BIT_VALUE) return 0;
int pow = 1;
while (pow <= MAX_POSSIBLE_BIT_VALUE) {
if (a <= pow) return pow;
pow *= 2;
}
return pow;
}
I am not sure if I am calculating the parity bit correctly for the the check Parity bit function I wrote. The codeWord is 11 chars long with 4 parity bits and 7 data bits. Does the implementation look good?
void parityCheck(char* codeWord) {
int parity[4] = {0}, i = 0, diffParity[4] = {0}, twoPower = 0, bitSum = 0;
// Stores # of 1's for each parity bit in array.
parity[0] = (codeWord[2] - 48) + (codeWord[4] - 48) + (codeWord[6] - 48) + (codeWord[8] - 48) + (codeWord[10] - 48);
parity[1] = (codeWord[2] - 48) + (codeWord[5] - 48) + (codeWord[6] - 48) + (codeWord[9] - 48) + (codeWord[10] - 48);
parity[2] = (codeWord[4] - 48) + (codeWord[5] - 48) + (codeWord[6] - 48);
parity[3] = (codeWord[8] - 48) + (codeWord[9] - 48) + (codeWord[10] - 48);
// Determines if sum of bits is even or odd, then tests for difference from actual parity bit.
for (i = 0; i < 4; i++) {
twoPower = (int)pow((double)2, i);
if (parity[i] % 2 == 0)
parity[i] = 0;
else
parity[i] = 1;
if ((codeWord[twoPower-1] - 48) != parity[i])
diffParity[i] = 1;
}
// Calculates the location of the error bit.
for (i = 0; i < 4; i++) {
twoPower = (int)pow((double)2, i);
bitSum += diffParity[i]*twoPower;
}
// Inverts bit at location of error.
if (bitSum <= 11 && bitSum > 0) {
if ((codeWord[bitSum-1] - 48))
codeWord[bitSum-1] = '0';
else
codeWord[bitSum-1] = '1';
}
Does the implementation look good?
This very much depends on your measure for “good”. I can confirm that it does get the job done, so at least it is correct. Your code is very verbose, and thus hard to check for correctness. I'd do the following:
int parity_check(int codeWord) {
int parity = 0, codeWordBit, bitPos;
for (bitPos = 1; bitPos <= 11; ++bitPos) {
codeWordBit = ((codeWord >> (bitPos - 1)) & 1);
parity ^= bitPos*codeWordBit;
}
if (parity != 0) {
if (parity > 11)
return -1; // multi-bit error!
codeWord ^= 1 << (parity - 1);
}
return codeWord;
}
Instead of a sequence of digit characters, I treat your whole code word as a single integer, which is a lot more efficient.
Looking at the table at Wikipedia, I see that the columns of that table form binary representations of the sequence 1 … 11. Each code word bit affects exactly those parity bits mentioned in that column, so I take the code word bit (which is zero or one), multiply it by the bit pattern of that column to obtain either that pattern or zero, then XOR this with the current parity bit pattern. The effect of this is that a zero code word bit won't change anything, whereas a non-zero code word bit flips all associated parity bits.
Some care has to be taken because the bit pattern is one-based, whereas the bit position using the right shift trick is zero-based. So I have to subtract one, then shift right by that amount, and then extract the least significant digit in order to obtain the codeWordBit.
Using my implementation for reference, I was able to verify (by complete enumeration) that your code works the same.
Your code works fine AFAIK as it passed test cases I conjured up. Some simplifications were employed, but the OP functionality not changed. Some classic simplifications were made for easier viewing.
void parityCheck(char* cW) {
int parity[4] = { 0 }, i = 0, diffParity[4] = { 0 }, twoPower = 0, bitSum = 0;
// Stores # of 1's for each parity bit in array.
parity[0] = (cW[2] - '0') + (cW[4] - '0') + (cW[6] - '0') + (cW[8] - '0') + (cW[10] - '0');
parity[1] = (cW[2] - '0') + (cW[5] - '0') + (cW[6] - '0') + (cW[9] - '0') + (cW[10] - '0');
parity[2] = (cW[4] - '0') + (cW[5] - '0') + (cW[6] - '0');
parity[3] = (cW[8] - '0') + (cW[9] - '0') + (cW[10] - '0');
// Determines if sum of bits is even or odd, then tests for difference from actual parity bit.
for (i = 0; i < 4; i++) {
//twoPower = (int) pow((double) 2, i);
twoPower = 1 << i;
//if (parity[i] % 2 == 0) parity[i] = 0; else parity[i] = 1;
parity[i] &= 1; // Make 0 even, 1 odd.
if ((cW[twoPower - 1]-'0') != parity[i])
diffParity[i] = 1;
}
// Calculates the location of the error bit.
for (i = 0; i < 4; i++) {
// twoPower = (int) pow((double) 2, i);
twoPower = 1 << i;
bitSum += diffParity[i] * twoPower;
}
// Inverts bit at location of error.
if (bitSum <= 11 && bitSum > 0) {
if ((cW[bitSum - 1]-'0'))
cW[bitSum - 1] = '0';
else
cW[bitSum - 1] = '1';
}
}
void TestP(const char * Test) {
char buf[100];
strcpy(buf, Test);
parityCheck(buf);
printf("'%s' '%s'\n", Test, buf);
}
int main(void) {
TestP("00000000000");
TestP("10011100101");
TestP("10100111001");
}
It would have been useful had the OP posted test patterns.
Here's my implementation. It works. The public is free to use it at no charge.
I used the acronym "secded" as in, "single-error-correcting, double-error-detecting." You can re-wire this as a "triple error detector" if you want that instead. Really, some small part of this is secded and the rest is Hamming 7,4 -- but I named these methods what I did, when I did.
The "strings" here are not NUL-terminated, but counted. This code is excerpted from a Python module written in C. That is the provenance of the string type you see.
A key point here was realizing that there are only 16 Hamming 7,4 codes. I calculated secded_of_nibble() with some Python code, which unfortunately I no longer have.
static const unsigned char secded_of_nibble[] =
{ 0x0, 0xd2, 0x55, 0x87, 0x99, 0x4b, 0xcc, 0x1e, 0xe1, 0x33, 0xb4, 0x66, 0x78, 0
xaa, 0x2d, 0xff };
int fec_secded_encode_cch_bits(const char * strIn, const int cchIn, char * strOu
t, const int cchOut)
{
assert( cchIn * 2 == cchOut);
if( cchIn * 2 != cchOut)
return 0;
if (!strIn || !strOut)
return 0;
int i;
for (i = 0; i < cchIn; i ++)
{
char in_byte = strIn[i];
char hi_byte = secded_of_nibble[(in_byte >> 4) & 0xf];
char lo_byte = secded_of_nibble[in_byte & 0xf];
strOut[i * 2] = hi_byte;
strOut[i * 2 + 1] = lo_byte;
}
return 1;
}
char bv_H[] = {0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0x8};
char val_nibble(char ch)
{
return ((ch & 0x20) >> 2) | ((ch & 0xE) >> 1);
}
char correct_nibble(char ch)
{
char nibble = 0;
int i = 0;
for (i = 0; i < 8; i++)
if (ch & (1 << (7-i)))
nibble ^= bv_H[i];
return nibble;
}
void apply_correct(char nib_correct, char * pbyte, int * pcSec, int *pcDed)
{
if (0 == nib_correct)
return;
if (nib_correct & 0x8)
{
(*pcSec) ++;
int bit = (8 - (nib_correct & 0x7)) & 0x7;
/* fprintf(stderr, "bit %d, %02X\n", bit, 1 << bit);*/
(*pbyte) ^= (1 << bit);
}
else
{
(*pcDed) ++;
}
}
int fec_secded_decode_cch_bits
(
const char * strIn,
const int cchIn,
char * strOut,
const int cchOut,
int * pcSec,
int * pcDed
)
{
assert( cchIn == cchOut *2);
if( cchIn != cchOut * 2)
return 0;
if (!strIn || !strOut)
return 0;
int i;
for (i = 0; i < cchOut; i ++)
{
char hi_byte = strIn[i * 2];
char lo_byte = strIn[i * 2 + 1];
char hi_correct = correct_nibble(hi_byte);
char lo_correct = correct_nibble(lo_byte);
if (hi_correct || lo_correct)
{
apply_correct(hi_correct, &hi_byte, pcSec, pcDed);
apply_correct(lo_correct, &lo_byte, pcSec, pcDed);
/* fprintf(stderr, "Corrections %x %x.\n", hi_correct, lo_correct);*/
}
char hi_nibble = val_nibble(hi_byte);
char lo_nibble = val_nibble(lo_byte);
strOut[i] = (hi_nibble << 4) | lo_nibble;
}
return 1;
}