-2

I am writing an operating system in C and assembly, and in implementing the EXT2 file system I have encountered a problem. I need to convert FOUR bytes of hexadecimal to decimal in c. An example would be to convert 00 00 01(10000) to 65536.I need to convert to decimal,because parsing the super block requires all values to be in decimal. Most specifically the ext2 fs I'm working on is here:

#include "ext2.h"
#include <stdlib.h>
long hex2dec(unsigned const char *hex){
long ret = 0;
int i = 0;
while(hex[i] != 0){
    //if(hex[i] >= 0x00 && hex[i] <= 0x09)
    //  ret+=(10 * i) * hex[i];
}
//kprintf("\n");
return ret;
}
char *strsep(char *buf,int offset,int num){
char *ret = malloc(1024);
int j = 0;
int i = offset;
int end = (offset + num);
int i1 = 0;
while(i1 < num){
    ///kstrcat(ret,&buf[i]);
    ret[i1] = buf[i];
    i++;
    i1++;
}
return ret;
}
int get_partition(partnum){
if(partnum > 4)
    return -1;
//int i = (12 * partnum);
int i = 0;
if(partnum == 1)
    i = 190;
else if(partnum == 2)
    i = 206;
else if(partnum == 3)
    i = 222;
else
    i = 190;
int ret = 0;
char *buf = malloc(1024);
ata_read_master(buf,1,0x00);
ret = buf[(i + 2)];
return ret;
}
int _intlen(int i){
int ret = 0;
while(i){
    ret++;
    i/=10;
}
return ret;
}
int _hex2int(char c){
if(c == '0')
    return 0;
else if(c == '1')
    return 1;
else if(c == '2')
    return 2;
else if(c == '3')
    return 3;
    else if(c == '4')
            return 4;
    else if(c == '5')
            return 5;
    else if(c == '6')
            return 6;
    else if(c == '7')
            return 7;
    else if(c == '8')
            return 8;
    else if(c == '9')
            return 9;
    else if(c == 'A')
            return 10;
    else if(c == 'B')
            return 11;
    else if(c == 'C')
            return 12;
    else if(c == 'D')
            return 13;
    else if(c == 'E')
            return 14;
    else if(c == 'F')
            return 15;


}
int hex2int(char c){
int i = c;

}
int comb(const char *str,int n){
int i = 0;
int ret = 0;
while(i < n){
    //if(str[i] == 0x01)
    //  kprintf("(:");
    /*int j = str[i];
    int k = 0;
    int m = 0;
    if(j < 10)
        j*=10;
    else
        while(j > 0){
            k+=(10 ^ (_intlen(j) - m)) * j % 10;
            m++;
            j/=10;
        }
    //kprintf("%d",j);
    //if(j == 1)
    //  kprintf("(:");*/
    i++;
}

//ret = (char)ret;
ret = (char)str
int ret = 0;
int i = 0;
char *s = malloc(1024);
/*while(i < n){

    //kstrcat(s,&((char*)buf[i]));
    n++;
}*/

return ret;
//kprintf("\n");
//return ret;
}
struct ext2_superblock *parse_sblk(int partnum){
int i = get_partition(partnum);
if(i > 0)
    kprintf("[EXT2_SUPERBLOCK]Found partition!\n");
else
    i = 0;
struct ext2_superblock *ret;
struct ext2_superblock retnp;
char *buf = malloc(1024);
int i1 = 0;
//char *tmpbuf = malloc(4);
/*if(i != 0)
    ata_read_master(buf,((i * 4)/256),0x00);
else{
    kprintf("[WRN]: Looking for superblock at offset 1024\n");
    ata_read_master(buf,4,0x00);
}*/
ata_read_master(buf,2,0x00);
const char *cmp = strsep(buf,0,4);


retnp.ninode = comb(strsep(buf,0,4),4);

    retnp.nblock = comb(strsep(buf,4,4),4);
    retnp.nsblock = comb(strsep(buf,8,4),4);
    retnp.nunallocb = comb(strsep(buf,12,4),4);
    retnp.nunalloci = comb(strsep(buf,16,4),4);
    retnp.supernum = comb(strsep(buf,20,4),4);
    retnp.leftshiftbs = comb(strsep(buf,24,4),4);
    retnp.leftshiftfs = comb(strsep(buf,28,4),4);
    retnp.numofblockpg= comb(strsep(buf,32,4),4);
 //   retnp.numofffpbg= comb(strsep(buf,36,4));
    retnp.numoffpbg = comb(strsep(buf,36,4),4);
    retnp.numofinpbg = comb(strsep(buf,40,4),4);
    retnp.lastmount = comb(strsep(buf,44,4),4);
    retnp.lastwrite = comb(strsep(buf,48,4),4);
    retnp.fsckpass = comb(strsep(buf,52,2),2);
    retnp.fsckallow = comb(strsep(buf,54,2),2);
    retnp.sig = comb(strsep(buf,56,2),2);
    retnp.state = comb(strsep(buf,58,2),2);
    retnp.erroropp = comb(strsep(buf,60,2),2);
    retnp.minorpor = comb(strsep(buf,52,2),2);
    retnp.ptimefsck = comb(strsep(buf,64,4),4);
    retnp.inter = comb(strsep(buf,68,4),4);
    retnp.osid = comb(strsep(buf,72,4),4);
retnp.mpv = comb(strsep(buf,76,4),4);
    retnp.uid = comb(strsep(buf,80,2),2);
retnp.gid = comb(strsep(buf,82,2),2);
ret = &retnp;
return ret;
i1 = 0;


}

If there is anyway of avoiding conversion and successfully implementing ext2 I would be glad to hear it. I would prefer it to be in c,but assembly is also okay.

Zach S
  • 86
  • 1
  • 7
  • 1
    Please post the relevant code inline as text and not as links – EdChum Dec 02 '15 at 15:20
  • @EdChum okay,I will in a sec – Zach S Dec 02 '15 at 15:20
  • 3
    "I need to convert to decimal,because parsing the super block requires all values to be in decimal." I think you are at a very wron level of abstraction. I don't think you need to parse or convert anything here. Just take the values as they are, maybe combine them to form values longer than 1 byte. But I really don't see the need for conversion to or drom text. – glglgl Dec 02 '15 at 15:25
  • Where is the target `00 00 01` in the code? – MikeCAT Dec 02 '15 at 15:32
  • @MikeCAT it's meant to be generic,but that is in a 1GB hard drive image,so I figured it would be too big to post – Zach S Dec 02 '15 at 15:33
  • OK, you are asking how to implement `hex2dec`, right? – MikeCAT Dec 02 '15 at 15:35
  • 2
    @ZachS If you think that e.g. `int x = 4711;` somehow puts a "decimal" value in `x`, I believe you're way into the deep end writing an operating system and a file system driver. That's just not true, and your question makes little sense (as pointed out by @glglgl). Converting four packed bytes into an integer has nothing to do with "converting hex to decimal". – unwind Dec 02 '15 at 15:41
  • @unwind Firstly the four packed bytes are in hexadecimal format when read into the string from my ata reader,secondly I Know that integers are positive and negative numbers,and pointers point to memory,etc. Secondly I never thought that it was a decimal value. I just need to convert from the character pointer to an integer. for example on the ext2 superblock the 1st 3 bytes are made to point the number of inodes in the system,but they are in hexadecimal format. They are read into my string as char str[] = {0x00,0x00,0x01}. I need to get that to decimal format or at least int – Zach S Dec 02 '15 at 15:47
  • 1
    @ZachS That is raw binary data, it is not in hexadecimal format, that is just a property of how you happen to view the data. `char str[] = { 0, 0, 1 };` is the exact same data but in decimal. – unwind Dec 02 '15 at 15:53
  • @unwind But that's not how I want it. I need all of the characters "combined" to be 10000. That's where the problem arises. I know I can express string like that,but I need some way to read all in put it into a single char or int. – Zach S Dec 02 '15 at 15:55

2 Answers2

1

If you have this:

const uint8_t bytes[] = { 0, 0, 1 };

and you want to consider that the bytes of a (24-bit) unsigned integer in little-endian order, you can convert to the actual integer using:

const uint32_t value = ((uint32_t) bytes[2] << 16) | (bytes[1] << 8) | bytes[0];

This will set value equal to 65536.

unwind
  • 391,730
  • 64
  • 469
  • 606
0

You can use std::istringstream or sscanf instead of writing your own.

char const * hex_text[] = "0x100";
const std::string hex_str(hex_text);
std::istringstream text_stream(hex_str);
unsigned int value;
text_stream >> std::ios::hex >> value;
std::cout << "Decimal value of 0x100: " << value << "\n";

Or using sscanf:

sscanf(hex_text, "0x%X", &value);
std::cout << "Decimal value of 0x100: " << value << "\n";

A good idea is to search your C++ reference for existing functions or search the internet, before writing your own.

To roll your own:

unsigned int hex2dec(const std::string& hex_text)
{
  unsigned int value = 0U;
  const unsigned int length = hex_text.length();
  for (unsigned int i = 0; i < length; ++i)
  {
    const char c = hex_text[i];
    if ((c >= '0') && (c <= '9'))
    {
       value = value * 16 + (c - '0');
    }
    else
    {
      c = toupper(c);
      if ((c >= 'A') && (c <= 'Z'))
      {
         value = value * 16 + (c - 'A') + 10;
      }
    }
  }
  return value;
}

To convert to use C-style character strings, change the parameter type and use strlen for the length.

Thomas Matthews
  • 56,849
  • 17
  • 98
  • 154