/* formato.cpp - Definiciones de los métodos
 *               de la clase CNumEntero
 */
#include <sstream>
#include <string>
#include "formato.h" // clase CNumEntero
using namespace std;

/////////////////////////////////////////////////////////////////
// Iniciar punto
char CNumEntero::punto = '.';

// Dar formato al atributo valor
ostream& operator<<(ostream& os, const CNumEntero& ob)
{
  // Construir un objeto stringstream con un búfer dinámico
  stringstream ss1;
  
  // Dotar a ss1 con el mismo formato numérico que os:
  // (setf(indicador que se modifica, indicador que se desactiva))
  // base: dec, oct o hex
  ss1.setf(os.flags() & ios::basefield, ios::basefield);
  // si/no mostrar signo positivo
  ss1.setf(os.flags() & ios::showpos, ios::showpos);
  // si/no mostrar base
  ss1.setf(os.flags() & ios::showbase, ios::showbase);
  
  // Convertir ob a texto y almacenarlo en ss1
  ss1 << ob.valor << ends;
  // Construir un objeto stringstream con un búfer dinámico
  stringstream ss2;
  
  // Copiar ss1 a ss2 añadiendo los puntos
  // Copiar primero el signo y el especificador de la base
  char car = ss1.get(); // primer carácter de ss1
  if (car == '+' || car == '-')
  {
    ss2 << car;      // insertar car en ss2
    car = ss1.get(); // siguiente carácter
  }
  if (car == 'x' || car == 'X')
  {
    ss2 << car;
    car = ss1.get();
  }
  if (car == '0')
  {
    ss2 << car;
    car = ss1.get();
  }
  
  // Copiar los dígitos e insertar los puntos
  ss2 << car;      // copiar el dígito más significativo
  car = ss1.get(); // siguiente dígito
  
  // Distancia en dígitos entre punto y punto
  int distancia = (os.flags() & ios::oct) ? 4 : 3;
  
  // Dígitos que quedan
  int pos_act = ss1.tellg();
  ss1.seekg(0, ios::end);
  int ult_pos = ss1.tellg();
  int quedan = ult_pos - pos_act;
  
  // Volver a la posición actual
  ss1.seekg(pos_act, ios::beg);
  do
  {
    if (car && !(quedan-- % distancia))
      ss2 << CNumEntero::punto;
    ss2 << car;
    car = ss1.get();
  }
  while (!ss1.eof());
  
  // Insertar el texto en el flujo os
  os << ss2.str();
  
  return os;
}
/////////////////////////////////////////////////////////////////

