#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/ManagedStatic.h"
#include <cassert>
#include <xlocale.h>


namespace {
  struct locale_holder {
    locale_holder()
    : l(newlocale(LC_CTYPE_MASK,"en_US.UTF-8",LC_GLOBAL_LOCALE))
    {
      assert(NULL!=l);
    }
    ~locale_holder() {
      freelocale(l);
    }

    int mbswidth(llvm::SmallString<16> s) const {
       // this implementation assumes no '\0' in s
      assert(s.size()==strlen(s.c_str()));

      size_t size = mbstowcs_l(NULL,s.c_str(),0,l);
      assert(size!=(size_t)-1);
      if (size==0)
        return 0;
      llvm::SmallVector<wchar_t,200> ws(size);
      size = mbstowcs_l(&ws[0],s.c_str(),ws.size(),l);
      assert(ws.size()==size);
      return wcswidth_l(&ws[0],ws.size(),l);
    }

    int isprint(int c) const {
      return iswprint_l(c,l);
    }

  private:

    locale_t l;
  };

  llvm::ManagedStatic<locale_holder> l;
}

namespace llvm {
namespace sys {
namespace locale {

int columnWidth(StringRef s) {
  int width = l->mbswidth(s);
  assert(width>=0);
  return width;
}

bool isPrint(int c) {
  return l->isprint(c);
}

}
}
}